Commit a38b54f8 authored by Lukas Burgey's avatar Lukas Burgey

Rework account management

Related to #10
parent 34aa92bf
<div class="mat-typography" style="margin-bottom: 50px;">
<h2>Key Management</h2>
<div style="margin-bottom: 15px;">
<p>
These are your currently uploaded SSH public keys.
</p>
</div>
<div style="margin-bottom: 35px;">
<mat-table [dataSource]="sshKeyTable">
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef>Name</mat-header-cell>
<mat-cell *matCellDef="let element">{{ element.name}}</mat-cell>
</ng-container>
<ng-container matColumnDef="key">
<mat-header-cell *matHeaderCellDef>Key</mat-header-cell>
<mat-cell style="font-size: 11px;" *matCellDef="let element">{{ element.key }}</mat-cell>
</ng-container>
<ng-container matColumnDef="action">
<mat-header-cell *matHeaderCellDef>Delete</mat-header-cell>
<mat-cell *matCellDef="let element">
<button *ngIf="keyDeleteable(element)" mat-icon-button matTooltip="Delete key" (click)="userService.removeSshKey(element)">
<mat-icon>delete_forever</mat-icon>
</button>
<button *ngIf="!keyDeleteable(element)" mat-icon-button matTooltip="This key is provided by the Proxy. It cannot be deleted." [disabled]="true" (click)="userService.removeSshKey(element)">
<mat-icon>delete_forever</mat-icon>
</button>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="columns"></mat-header-row>
<mat-row *matRowDef="let row; columns: columns;"></mat-row>
</mat-table>
</div>
<!-- uploading section -->
<div>
<div *ngIf="upload; then uploading else not_uploading"></div>
<ng-template #not_uploading>
<p>
You can upload more SSH public keys to use for accessing services.
</p>
<button mat-raised-button color="primary" (click)="upload = true">
Upload more
</button>
</ng-template>
<ng-template #uploading>
<form (ngSubmit)="uploadKey()" #sshKeyForm="ngForm">
<mat-form-field>
<input matInput placeholder="Name" required [(ngModel)]="formKey.name" name="name">
</mat-form-field>
<mat-form-field>
<textarea matInput placeholder="Key" required [(ngModel)]="formKey.key" name="key"></textarea>
</mat-form-field>
<button mat-raised-button color="primary" type="submit" [disabled]="!sshKeyForm.form.valid">
Upload key
</button>
<button matInput mat-icon-button (click)="resetKeyUpload()" matTooltip="Abort key upload">
<mat-icon>cancel</mat-icon>
</button>
</form>
</ng-template>
</div>
</div>
<div class="mat-typography">
<h3>Account Management</h3>
<h2>Account Management</h2>
<p class="mat-body-1">
You can delete your account. All deployments will be withdrawn if you choose to do so.
You can delete your account. All deployments will be removed if you choose to do so. You will not be able to use the deployed credentials.
</p>
<p class="mat-body-2">
<mat-checkbox [(ngModel)]="sure" style="margin-right: 8px" [checked]="sure">
I'm sure I want to delete my data from the server.
</mat-checkbox>
I'm sure I want to delete all my data from the server.
<p>
<button mat-raised-button mat-dialog-close color="primary" (click)="delete()" [disabled]="!sure">
<button mat-raised-button mat-dialog-close color="primary" (click)="userService.deleteUser()" [disabled]="!sure">
Delete
</button>
</p>
......
import { Component, OnInit } from '@angular/core';
import { DataSource } from '@angular/cdk/collections';
import { UserService } from '../../user.service';
import { SSHKey, NewSSHKey } from '../../types/types.module';
import { SSHKeysDataSource } from './sshkeys-data-source';
@Component({
selector: 'app-account',
......@@ -8,18 +11,44 @@ import { UserService } from '../../user.service';
styleUrls: ['./account.component.css']
})
export class AccountComponent implements OnInit {
public sure: boolean;
columns = ['name', 'key', 'action'];
// ssh upload form
// does the user want to upload a key?
upload: boolean;
formKey: NewSSHKey;
sshKeyTable: DataSource<SSHKey>;
// account deletion form
sure: boolean = false;
constructor(
public userService: UserService,
) {
this.sure = false;
this.resetKeyUpload();
}
ngOnInit() {
this.sshKeyTable = new SSHKeysDataSource(this.userService);
}
resetKeyUpload() {
this.upload = false;
this.formKey = {
name: '',
key: '',
}
}
uploadKey() {
this.userService.uploadSshKey(this.formKey);
this.resetKeyUpload();
}
delete() {
this.userService.deleteUser();
keyDeleteable(key: SSHKey): boolean {
return key.name !== "unity_key";
}
}
import { CollectionViewer, DataSource } from "@angular/cdk/collections";
import { Observable } from 'rxjs/Observable';
import { UserService } from '../../user.service';
import { SSHKey } from '../../types/types.module';
export class SSHKeysDataSource implements DataSource<SSHKey> {
constructor(
private userService: UserService,
) {}
connect(collectionViewer: CollectionViewer): Observable<SSHKey[]> {
return this.userService.subscribeSSHKeys();
}
disconnect(collectionViewer: CollectionViewer): void {
}
}
......@@ -2,7 +2,6 @@ import { Injectable } from '@angular/core';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { ProfileComponent } from './profile/profile.component';
import { SshKeysComponent } from './ssh-keys/ssh-keys.component';
import { AccountComponent } from './account/account.component';
import { QuestionnaireComponent } from './questionnaire/questionnaire.component';
import { CredentialsComponent } from './credentials/credentials.component';
......@@ -13,7 +12,6 @@ import * as t from '../types/types.module';
@Injectable()
export class DialogService {
profileDialog: MatDialogRef<any>;
sshKeysDialog: MatDialogRef<any>;
accountDialog: MatDialogRef<any>;
questionnaireDialog: MatDialogRef<any>;
credentialsDialog: MatDialogRef<any>;
......@@ -34,13 +32,6 @@ export class DialogService {
);
}
public openSshKeys() {
this.sshKeysDialog = this.dialog.open(
SshKeysComponent,
this.settings,
);
}
public openAccount() {
this.accountDialog = this.dialog.open(
AccountComponent,
......
......@@ -9,7 +9,6 @@ import {SharedModule} from '../shared/shared.module';
// declarations
import {QuestionnaireComponent} from './questionnaire/questionnaire.component';
import {ProfileComponent} from './profile/profile.component';
import {SshKeysComponent} from './ssh-keys/ssh-keys.component';
import {AccountComponent} from './account/account.component';
import {CredentialsComponent} from './credentials/credentials.component';
import {MessageComponent} from './message/message.component';
......@@ -27,7 +26,6 @@ import {DialogService} from './dialog.service';
declarations: [
QuestionnaireComponent,
ProfileComponent,
SshKeysComponent,
AccountComponent,
CredentialsComponent,
MessageComponent,
......@@ -35,7 +33,6 @@ import {DialogService} from './dialog.service';
entryComponents: [
QuestionnaireComponent,
ProfileComponent,
SshKeysComponent,
AccountComponent,
CredentialsComponent,
MessageComponent,
......
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SshKeysComponent } from './ssh-keys.component';
describe('SshKeysComponent', () => {
let component: SshKeysComponent;
let fixture: ComponentFixture<SshKeysComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SshKeysComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SshKeysComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
import { MatTableDataSource } from '@angular/material';
import {HttpClient} from '@angular/common/http';
import { UserService } from '../../user.service';
import { SSHKey, NewSSHKey } from '../../types/types.module';
import * as t from '../../types/types.module';
@Component({
selector: 'app-ssh-keys',
templateUrl: './ssh-keys.component.html',
styleUrls: ['./ssh-keys.component.css']
})
export class SshKeysComponent implements OnInit {
columns = ['name', 'key', 'action'];
// does the user want to upload a key?
upload: boolean;
formKey: t.NewSSHKey;
constructor(
public userService: UserService,
public http: HttpClient,
) {
}
ngOnInit() {
this.upload = false;
this.formKey = {
name: '',
key: '',
}
}
private uploadSshKey(key: t.NewSSHKey) {
const body = {
'type': 'add',
'key': key,
};
return this.http.post('/backend/api/sshkey', body).subscribe(
(newKey: t.SSHKey) => {
if (newKey) {
this.userService.user.ssh_keys.push(newKey);
}
},
(err) => {
console.log(err);
this.userService.update();
}
);
}
private removeSshKey(key: t.SSHKey) {
return this.http.post('/backend/api/sshkey', {
'type': 'remove',
'id': key.id,
}).subscribe(
(data: {deleted: boolean}) => {
if (data && data.deleted) {
this.userService.user.ssh_keys = this.userService.user.ssh_keys.filter(
k => key.id != k.id
);
}
},
(err) => {
console.log(err);
this.userService.update();
}
);
}
public _sshKeyTable(): MatTableDataSource<any> {
return new MatTableDataSource(this.userService.user.ssh_keys);
}
public uploadKey() {
this.uploadSshKey(this.formKey);
this.ngOnInit();
}
public deleteKey(key: SSHKey) {
this.removeSshKey(key);
this.ngOnInit();
}
}
......@@ -20,9 +20,11 @@
<button mat-button mat-icon-button (click)="dialog.openAccount()">
<mat-icon>settings</mat-icon>
</button>
<!--
<button mat-button mat-icon-button (click)="dialog.openSshKeys()">
<mat-icon>vpn_key</mat-icon>
</button>
-->
<button *ngIf="userService.user.profile_name != undefined" mat-button (click)="dialog.openProfile()">
{{ userService.user.profile_name }}
</button>
......
......@@ -18,11 +18,14 @@ import * as t from './types/types.module';
export class UserService {
private _loggedIn: boolean = false;
public user: t.User;
user$ = <BehaviorSubject<t.User>> new BehaviorSubject(new Object);
private user: t.User;
private user$ = <BehaviorSubject<t.User>> new BehaviorSubject(new Object);
public userState: t.UserState;
userState$ = <BehaviorSubject<t.UserState>> new BehaviorSubject(new Object);
public userState$ = <BehaviorSubject<t.UserState>> new BehaviorSubject(new Object);
private sshKeys: t.SSHKey[] = new Array<t.SSHKey>();
private sshKeys$ = <BehaviorSubject<t.SSHKey[]>> new BehaviorSubject([]);
public messages: string[] = [];
// local copy of services
......@@ -43,6 +46,7 @@ export class UserService {
) {
this.update();
// AUTO LOGIN
this.subscribeUserState().subscribe(
(state: t.UserState) => {
......@@ -70,6 +74,10 @@ export class UserService {
return this.user$.asObservable();
}
public subscribeSSHKeys(): Observable<t.SSHKey[]> {
return this.sshKeys$.asObservable();
}
// PRIVATE API
private initStomp() {
// handle with care
......@@ -129,6 +137,9 @@ export class UserService {
private updateUser(newUser: t.User) {
this.user = newUser;
this.user$.next(this.user);
this.sshKeys = this.user.ssh_keys;
this.sshKeys$.next(this.sshKeys);
}
private updateServices(newServices: t.Service[]){
......@@ -343,4 +354,35 @@ export class UserService {
}
);
}
public uploadSshKey(key: t.NewSSHKey) {
console.log('uploading key:', key);
const body = {
'type': 'add',
'key': key,
};
return this.http.post('/backend/api/sshkey', body).subscribe(
(newKey: t.SSHKey) => {
this.sshKeys.push(newKey);
this.sshKeys$.next(this.sshKeys);
}
);
}
public removeSshKey(key: t.SSHKey) {
console.log('deleting key:', key);
return this.http.post('/backend/api/sshkey', {
'type': 'remove',
'id': key.id,
}).subscribe(
(data: {deleted: boolean}) => {
if (data && data.deleted) {
this.sshKeys = this.sshKeys.filter(
k => key.id != k.id
);
this.sshKeys$.next(this.sshKeys);
}
}
);
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment