Skip to content

Commit

Permalink
feat(ui): auto create ssh/gpg key at project creation (#3802)
Browse files Browse the repository at this point in the history
* feat(ui): auto create ssh/gpg key at project creation

Signed-off-by: Yvonnick Esnault <[email protected]>

* cr

Signed-off-by: Yvonnick Esnault <[email protected]>

* cr

Signed-off-by: Yvonnick Esnault <[email protected]>

* Update ui/src/assets/i18n/fr.json

Co-Authored-By: yesnault <[email protected]>
  • Loading branch information
yesnault authored and richardlt committed Jan 3, 2019
1 parent 94e77c7 commit a525a4e
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 65 deletions.
23 changes: 23 additions & 0 deletions engine/api/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package api
import (
"context"
"database/sql"
"fmt"
"net/http"
"regexp"
"strings"
Expand Down Expand Up @@ -451,6 +452,28 @@ func (api *API) addProjectHandler() service.Handler {
}
}

var sshExists, gpgExists bool
for _, k := range p.Keys {
switch k.Type {
case sdk.KeyTypeSSH:
sshExists = true
case sdk.KeyTypePGP:
gpgExists = true
}
}

if !sshExists {
p.Keys = append(p.Keys, sdk.ProjectKey{Key: sdk.Key{
Type: sdk.KeyTypeSSH,
Name: fmt.Sprintf("proj-%s-%s", sdk.KeyTypeSSH, strings.ToLower(p.Key))},
})
}
if !gpgExists {
p.Keys = append(p.Keys, sdk.ProjectKey{Key: sdk.Key{
Type: sdk.KeyTypePGP,
Name: fmt.Sprintf("proj-%s-%s", sdk.KeyTypePGP, strings.ToLower(p.Key))},
})
}
for _, k := range p.Keys {
k.ProjectID = p.ID
switch k.Type {
Expand Down
9 changes: 7 additions & 2 deletions ui/src/app/shared/keys/form/keys.form.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
<div class="KeyForm">
<div class="ui form">
<div class="ui info message" *ngIf="newKey.type == 'ssh'">
{{ 'keys_ssh_key_help' | translate }} <a href="https://ovh.github.io/cds/cli/worker/key/install/">Worker Install Key</a>
</div>
<div class="ui info message" *ngIf="newKey.type == 'pgp'">
{{ 'keys_pgp_key_help' | translate }} <a href="https://ovh.github.io/cds/cli/worker/key/install/">Worker Install Key</a>
</div>
<div class="fields">
<div class="seven wide field">
<label>{{ 'keys_name' | translate}}</label>
Expand All @@ -16,8 +22,7 @@
[options]="keyTypes"
[isSearchable]="true"
#selectKeyType>
<sui-select-option *ngFor="let t of selectKeyType.filteredOptions"
[value]="t">
<sui-select-option *ngFor="let t of selectKeyType.filteredOptions" [value]="t">
</sui-select-option>
</sui-select>
</div>
Expand Down
12 changes: 0 additions & 12 deletions ui/src/app/views/project/add/project.add.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,26 +109,14 @@ describe('CDS: Project Show Component', () => {
expect(router.navigate).toHaveBeenCalled();
});

it('it should generate an project key', () => {
let fixture = TestBed.createComponent(ProjectAddComponent);
fixture.componentInstance.generateKey('^r%t*$f#|m');
expect(fixture.componentInstance.project.key).toBe('RTFM');

});

it('it should generate errors', () => {
let fixture = TestBed.createComponent(ProjectAddComponent);
fixture.componentInstance.addSshKey = true;
fixture.componentInstance.createProject();

expect(fixture.componentInstance.nameError).toBeTruthy();
expect(fixture.componentInstance.keyError).toBeTruthy();
expect(fixture.componentInstance.sshError).toBeTruthy();

// pattern error
fixture.componentInstance.project.key = 'aze';
fixture.componentInstance.createProject();
expect(fixture.componentInstance.keyError).toBeTruthy();
});
});

Expand Down
25 changes: 1 addition & 24 deletions ui/src/app/views/project/add/project.add.component.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import {Component, ViewChild} from '@angular/core';
import {Router} from '@angular/router';
import {TranslateService} from '@ngx-translate/core';
import {cloneDeep} from 'lodash';
import {SemanticModalComponent} from 'ng-semantic/ng-semantic';
import {first} from 'rxjs/operators';
import {Group, GroupPermission} from '../../../model/group.model';
import {Key, KeyType} from '../../../model/keys.model';
import {Project} from '../../../model/project.model';
import {GroupService} from '../../../service/group/group.service';
import {ProjectStore} from '../../../service/project/project.store';
Expand All @@ -22,13 +20,10 @@ export class ProjectAddComponent {
project: Project;
newGroup: Group = new Group();
group: Group = new Group();
addSshKey = false;
sshKey: Key;

loading = false;
nameError = false;
keyError = false;
sshError = false;
fileTooLarge = false;

groupList: Group[];
Expand All @@ -39,8 +34,6 @@ export class ProjectAddComponent {
constructor(private _projectStore: ProjectStore, private _toast: ToastService, private _translate: TranslateService,
private _router: Router, private _groupService: GroupService, private _permissionService: PermissionService) {
this.project = new Project();
this.sshKey = new Key();
this.sshKey.type = KeyType.SSH;
this.loadGroups(null);
}

Expand All @@ -57,7 +50,6 @@ export class ProjectAddComponent {
}
this.project.key = name.toUpperCase();
this.project.key = this.project.key.replace(/([.,; *`§%&#_\-'+?^=!:$\\"{}()|\[\]\/\\])/g, '').substr(0, 5);
this.sshKey.name = 'sshkey';
}

/**
Expand All @@ -67,7 +59,6 @@ export class ProjectAddComponent {
this.loading = true;
this.nameError = false;
this.keyError = false;
this.sshError = false;
if (!this.project.name || this.project.name.length === 0) {
this.nameError = true;
}
Expand All @@ -88,21 +79,7 @@ export class ProjectAddComponent {
this.project.groups.push(gp);
}

if (this.addSshKey && (!this.sshKey.name || this.sshKey.name === '')) {
this.sshError = true;
}

if (!this.nameError && !this.keyError && !this.sshError) {
if (this.addSshKey) {
this.project.keys = new Array<Key>();

let sshKeyCloned = cloneDeep(this.sshKey);
if (sshKeyCloned.name.indexOf('proj-') !== 0) {
sshKeyCloned.name = 'proj-' + sshKeyCloned.name;
}
this.project.keys.push(sshKeyCloned);
}

if (!this.nameError && !this.keyError) {
this._projectStore.createProject(this.project).subscribe(p => {
this.loading = true;
this._toast.success('', this._translate.instant('project_added'));
Expand Down
23 changes: 0 additions & 23 deletions ui/src/app/views/project/add/project.add.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,29 +36,6 @@ <h2>{{ 'project_create' | translate }}</h2>

<hr>

<div class="ui message">
{{'project_add_ssh_key_help' | translate}}
</div>
<div class="field">
<div class="ui checkbox">
<input type="checkbox" id="sshkey" name="sshkey" [(ngModel)]="addSshKey">
<label for="sshkey">{{ 'project_add_ssh_key' | translate }}</label>
</div>
</div>
<div class="field" *ngIf="addSshKey">
<label>{{ 'wizard_ssh_key_name' | translate }}</label>
<div class="ui labeled input">
<div class="ui label">proj-</div>
<input type="text" name="keyname" [(ngModel)]="sshKey.name">
</div>

</div>
<div class="ui error message" *ngIf="sshError">
{{ 'project_ssh_error' | translate }}
</div>

<hr>

<div class="ui message">
{{'project_add_group_help' | translate}}
</div>
Expand Down
4 changes: 2 additions & 2 deletions ui/src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,8 @@
"keys_removed": "Key has been removed",
"keys_type": "Key type",
"keys_no": "There is no keys",
"keys_ssh_key_help": "A SSH Key is useful when you want to git clone some code from a Git Repository. CDS can generate a key pair and you can copy / paste the public key to your access keys on your repositories. If you want to use manually the key, please read:",
"keys_pgp_key_help": "A PGP Key is useful when you want to git tag a repository. If you want to use manually the key, please read:",

"usage_application_list": "Applications used",
"usage_workflow_list": "Workflows used",
Expand Down Expand Up @@ -631,8 +633,6 @@
"project_list_card_updated": "Updated the {{date}}",
"project_advanced_title": "Project administration",
"project_added": "Project has just been created",
"project_add_ssh_key": "Generate a ssh key",
"project_add_ssh_key_help": "A SSK Key is useful when you want to git clone some code from a Git Repository. CDS can generate a key pair and you can copy / paste the public key to your access keys on your repositories.",
"project_add_group_help": "Read / Write / Execute permissions have to be set on this new project. You can choose an existing users group or let empty to automatically create a new group, you will be administrator of this group.",
"project_applications_list": "List of applications in the project: ",
"project_create": "Create a new project",
Expand Down
4 changes: 2 additions & 2 deletions ui/src/assets/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,8 @@
"keys_removed": "La clé a été supprimée",
"keys_type": "Type de clé",
"keys_no": "Il n'y a aucune clé",
"keys_ssh_key_help": "Une clé SSH est généralement utile lorsque vous souhaitez cloner un dépôt Git. CDS peut générer une paire de clé, il ne vous restera qu'à copier / coller la clé publique fournie par CDS dans les clés autorisées sur vos dépôts. Si vous souhaitez utiliser cette clé manuellement, consultez la documentation:",
"keys_pgp_key_help": "Une clé PGP est généralement utile lorsque vous souhaitez tagguer un dépôt Git. Si vous souhaitez utiliser cette clé manuellement, consultez la documentation:",

"usage_application_list": "Applications utilisées",
"usage_workflow_list": "Workflows utilisés",
Expand Down Expand Up @@ -631,8 +633,6 @@
"project_list_card_updated": "Mis à jour le {{date}}",
"project_advanced_title": "Administration du projet",
"project_added": "Projet créé",
"project_add_ssh_key": "Générer une clé ssh",
"project_add_ssh_key_help": "Une clé ssh est généralement utile lorsque vous souhaitez cloner un dépôt Git. CDS peut générer une paire de clé, il ne vous restera qu'à copier / coller la clé publique fournie par CDS dans les clés autorisées sur vos dépôts.",
"project_add_group_help": "Les permissions de Lecture / Écriture / Exécution doivent être positionnées sur ce nouveau projet. Vous pouvez choisir un groupe d'utilisateurs existant ou laisser vide pour que CDS créé automatiquement un nouveau groupe, vous en serez l'administrateur.",
"project_applications_list": "Liste des applications du projet : ",
"project_create": "Création d'un projet",
Expand Down

0 comments on commit a525a4e

Please sign in to comment.