diff --git a/package-lock.json b/package-lock.json index 9ba098c9fd..cbc6df3fed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@denbi/cloud-portal-webapp", - "version": "4.899.0", + "version": "4.900.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@denbi/cloud-portal-webapp", - "version": "4.899.0", + "version": "4.900.0", "dependencies": { "@angular-eslint/eslint-plugin": "^18.3.0", "@angular/animations": "18.2.8", @@ -99,7 +99,7 @@ "less-loader": "12.2.0", "lint-staged": "15.2.10", "ngx-spec": "2.1.6", - "npm-run-all2": "6.2.6", + "npm-run-all2": "7.0.1", "prettier": "3.3.3", "raw-loader": "4.0.2", "sass-loader": "16.0.2", @@ -13661,9 +13661,9 @@ } }, "node_modules/npm-run-all2": { - "version": "6.2.6", - "resolved": "https://registry.npmjs.org/npm-run-all2/-/npm-run-all2-6.2.6.tgz", - "integrity": "sha512-tkyb4pc0Zb0oOswCb5tORPk9MvVL6gcDq1cMItQHmsbVk1skk7YF6cH+UU2GxeNLHMuk6wFEOSmEmJ2cnAK1jg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/npm-run-all2/-/npm-run-all2-7.0.1.tgz", + "integrity": "sha512-Adbv+bJQ8UTAM03rRODqrO5cx0YU5KCG2CvHtSURiadvdTjjgGJXdbc1oQ9CXBh9dnGfHSoSB1Web/0Dzp6kOQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13672,9 +13672,9 @@ "memorystream": "^0.3.1", "minimatch": "^9.0.0", "pidtree": "^0.6.0", - "read-package-json-fast": "^3.0.2", + "read-package-json-fast": "^4.0.0", "shell-quote": "^1.7.3", - "which": "^3.0.1" + "which": "^5.0.0" }, "bin": { "npm-run-all": "bin/npm-run-all/index.js", @@ -13683,8 +13683,8 @@ "run-s": "bin/run-s/index.js" }, "engines": { - "node": "^14.18.0 || ^16.13.0 || >=18.0.0", - "npm": ">= 8" + "node": "^18.17.0 || >=20.5.0", + "npm": ">= 9" } }, "node_modules/npm-run-all2/node_modules/ansi-styles": { @@ -13700,20 +13700,30 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/npm-run-all2/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, "node_modules/npm-run-all2/node_modules/which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", - "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, "license": "ISC", "dependencies": { - "isexe": "^2.0.0" + "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-run-path": { @@ -15434,16 +15444,37 @@ } }, "node_modules/read-package-json-fast": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", - "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-4.0.0.tgz", + "integrity": "sha512-qpt8EwugBWDw2cgE2W+/3oxC+KTez2uSVR8JU9Q36TXPAGCaozfQUs59v4j4GFpWTaw0i6hAZSvOmu1J0uOEUg==", "dev": true, + "license": "ISC", "dependencies": { - "json-parse-even-better-errors": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" + "json-parse-even-better-errors": "^4.0.0", + "npm-normalize-package-bin": "^4.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-4.0.0.tgz", + "integrity": "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/read-package-json-fast/node_modules/npm-normalize-package-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", + "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/readable-stream": { diff --git a/package.json b/package.json index e9f35a7b8b..600e7b1bd6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@denbi/cloud-portal-webapp", - "version": "4.899.0", + "version": "4.900.0", "description": "de.NBI Cloud Portal", "scripts": { "ng": "ng serve", @@ -109,7 +109,7 @@ "less-loader": "12.2.0", "lint-staged": "15.2.10", "ngx-spec": "2.1.6", - "npm-run-all2": "6.2.6", + "npm-run-all2": "7.0.1", "prettier": "3.3.3", "raw-loader": "4.0.2", "sass-loader": "16.0.2", diff --git a/src/app/api-connector/applications.service.ts b/src/app/api-connector/applications.service.ts index c004fca888..606a0e9da9 100644 --- a/src/app/api-connector/applications.service.ts +++ b/src/app/api-connector/applications.service.ts @@ -336,4 +336,17 @@ export class ApplicationsService { withCredentials: true }) } + + checkForTakenShortname(shortname: string,exclude_project_id?:string|number): Observable { + + let params:any={ shortname: shortname } + if (exclude_project_id){ + params={ shortname: shortname ,exclude_project_id:exclude_project_id} + } + return this.http.get(`${ApiSettings.getApiBaseURL()}project_applications/shortname/`, { + params: params, + withCredentials: true + }); + + } } diff --git a/src/app/applications/application-formular/application-formular.component.html b/src/app/applications/application-formular/application-formular.component.html index 14e60fcaa6..d39356fbf6 100644 --- a/src/app/applications/application-formular/application-formular.component.html +++ b/src/app/applications/application-formular/application-formular.component.html @@ -145,6 +145,14 @@
General Information
Umlauts and special characters are prohibited in the shortname. +
+ + Warning: This shortname is already in use. A unique suffix will be automatically appended upon + submission. + +
General Information #shortname (keyup)="checkShortname(shortname.value)" class="form-control" - maxlength="15" + min="5" + [maxlength]="shortNameMaxLength" + (ngModelChange)="setDefaulShortnameLength()" [(ngModel)]="application.project_application_shortname" minlength="5" placeholder="e.g. ThalianaBench" @@ -490,7 +500,7 @@
Resources
/>
GB
- How much total extra storage do you need for your VMs? + How much total storage do you need for your VMs in form of Volumes?
diff --git a/src/app/applications/application-formular/application-formular.component.ts b/src/app/applications/application-formular/application-formular.component.ts index 8beeb64cd6..2e4b25d457 100644 --- a/src/app/applications/application-formular/application-formular.component.ts +++ b/src/app/applications/application-formular/application-formular.component.ts @@ -33,6 +33,9 @@ import { UserService } from '../../api-connector/user.service' import { Userinfo } from '../../userinfo/userinfo.model' import { User } from '../application.model/user.model' import { NotificationModalComponent } from '../../shared/modal/notification-modal' +import { Subject, Subscription } from 'rxjs'; +import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; +import { thresholdScott } from 'd3' /** * Application formular component. @@ -51,6 +54,8 @@ export class ApplicationFormularComponent extends ApplicationBaseClassComponent @Input() application: Application @Input() is_validation: boolean = false @Input() hash: string + DEFAULT_SHORTNAME_MAX_LENGTH:number=15 + shortNameMaxLength:number=15 userinfo: Userinfo valid_pi_affiliations @@ -87,6 +92,9 @@ export class ApplicationFormularComponent extends ApplicationBaseClassComponent WIKI_BACKUP_LINK: string = WIKI_BACKUP_LINK GDPR_LINK: string = GDPR_LINK survey_link_visible: boolean = false + private nameCheckPipe = new Subject(); + shortnameChecking: boolean = false; + shortNameTaken: boolean = false; MAX_LIFETIME_DEFAULT: number = 6 max_lifetime: number = this.MAX_LIFETIME_DEFAULT @@ -119,6 +127,7 @@ export class ApplicationFormularComponent extends ApplicationBaseClassComponent this.getListOfFlavors() this.getListOfTypes() this.is_vo_admin = is_vo + this.nameCheckPipe.pipe(debounceTime(600), distinctUntilChanged()).subscribe(value => {this.checkIfNameIsTaken(value)}); if (this.openstack_project) { this.simple_vm_min_vm = true @@ -138,6 +147,21 @@ export class ApplicationFormularComponent extends ApplicationBaseClassComponent } } + setDefaulShortnameLength():void{ + this.shortNameMaxLength=this.DEFAULT_SHORTNAME_MAX_LENGTH + } + + checkIfNameIsTaken(shortname: string): void { + this.shortnameChecking = true; + + this.applicationsService.checkForTakenShortname(shortname,this.application?.project_application_id).subscribe((result: boolean): void => { + let nameExists: boolean = result['exists']; + this.shortnameChecking = false; + this.shortNameTaken = nameExists; + }); + + } + checkValidityComment(): boolean { if (this.extraResourceCommentRequired) { if (this.application.project_application_comment?.length < 50) { @@ -173,6 +197,10 @@ export class ApplicationFormularComponent extends ApplicationBaseClassComponent if (this.application && !this.initiated_validation && this.is_validation) { this.openstack_project = this.application.project_application_openstack_project + if(this.application.project_application_shortname.length > 15){ + this.shortNameMaxLength=this.application.project_application_shortname.length + } + this.simple_vm_project = !this.openstack_project this.application.project_application_pi = new User() @@ -238,6 +266,11 @@ export class ApplicationFormularComponent extends ApplicationBaseClassComponent */ public checkShortname(shortname: string): void { this.invalid_shortname = !/^[a-zA-Z0-9\s]*$/.test(shortname) + if (!this.invalid_shortname) { + this.shortnameChecking = true; + this.nameCheckPipe.next(shortname); + } + } public checkLongname(longname: string): void { diff --git a/src/app/projectmanagement/modals/adjust-application/adjust-application.component.html b/src/app/projectmanagement/modals/adjust-application/adjust-application.component.html index 4106c18141..b0b772fdb3 100644 --- a/src/app/projectmanagement/modals/adjust-application/adjust-application.component.html +++ b/src/app/projectmanagement/modals/adjust-application/adjust-application.component.html @@ -27,7 +27,7 @@

Adjust application for {{ application?.project_application_shortname }}

[ngStyle]="{ 'background-color': adjustedApplication.project_application_openstack_project ? '#FF0000' - : '#00adef' + : '#00adef', }" > @@ -78,7 +78,7 @@

Adjust application for {{ application?.project_application_shortname }}

appInteger [ngClass]="{ 'is-invalid': resourceAdjustmentForm.controls.granted_lifetime_counter?.invalid, - 'is-valid': resourceAdjustmentForm.controls.granted_lifetime_counter?.valid + 'is-valid': resourceAdjustmentForm.controls.granted_lifetime_counter?.valid, }" />
@@ -109,7 +109,7 @@
style="font-size: 25px" [ngClass]="{ 'icon-arrow-up': groupval.isOpen, - 'icon-arrow-down': !groupval.isOpen + 'icon-arrow-down': !groupval.isOpen, }" > @@ -163,7 +163,7 @@
appIntegerOrNull [ngClass]="{ 'is-invalid': name?.invalid, - 'is-valid': name?.valid + 'is-valid': name?.valid, }" />
VMs
@@ -217,7 +217,7 @@
appInteger [ngClass]="{ 'is-invalid': resourceAdjustmentForm.controls.granted_volume_counter?.invalid, - 'is-valid': resourceAdjustmentForm.controls.grated_volume_counter?.valid + 'is-valid': resourceAdjustmentForm.controls.grated_volume_counter?.valid, }" /> @@ -247,7 +247,7 @@
/>
GB
- Requested extra storage + Requested volume storage
@@ -264,13 +264,13 @@
appInteger [ngClass]="{ 'is-invalid': resourceAdjustmentForm.controls.granted_volume_limit?.invalid, - 'is-valid': resourceAdjustmentForm.controls.granted_volume_limit?.valid + 'is-valid': resourceAdjustmentForm.controls.granted_volume_limit?.valid, }" [disabled]="resourceAdjustmentForm.controls.granted_volume_counter?.value === 0" />
GB
- Amount of extra storage you want to grant + Amount of volume storage you want to grant
@@ -316,7 +316,7 @@
required [ngClass]="{ 'is-invalid': resourceAdjustmentForm.controls.granted_object_storage?.invalid, - 'is-valid': resourceAdjustmentForm.controls.granted_object_storage?.valid + 'is-valid': resourceAdjustmentForm.controls.granted_object_storage?.valid, }" />
GB
diff --git a/src/app/projectmanagement/modals/modification-request/modification-request.component.html b/src/app/projectmanagement/modals/modification-request/modification-request.component.html index 5551ec8d73..92d6d34293 100644 --- a/src/app/projectmanagement/modals/modification-request/modification-request.component.html +++ b/src/app/projectmanagement/modals/modification-request/modification-request.component.html @@ -126,7 +126,7 @@
aria-describedby="{{ flavor.name }}_help" [ngClass]="{ 'is-invalid': name?.invalid && !adjustment, - 'is-valid': name?.valid && !adjustment + 'is-valid': name?.valid && !adjustment, }" />
@@ -160,7 +160,7 @@
aria-describedby="adjust_{{ flavor.name }}_help" [ngClass]="{ 'is-invalid': name?.invalid, - 'is-valid': name?.valid + 'is-valid': name?.valid, }" /> @@ -220,7 +220,7 @@
appInteger [ngClass]="{ 'is-invalid': modificationForm.controls.project_application_renewal_volume_counter?.invalid, - 'is-valid': modificationForm.controls.project_application_renewal_volume_counter?.valid + 'is-valid': modificationForm.controls.project_application_renewal_volume_counter?.valid, }" />
@@ -259,7 +259,7 @@
appInteger [ngClass]="{ 'is-invalid': modificationForm.controls.project_application_renewal_volume_counter_adjusted?.invalid, - 'is-valid': modificationForm.controls.project_application_renewal_volume_counter_adjusted?.valid + 'is-valid': modificationForm.controls.project_application_renewal_volume_counter_adjusted?.valid, }" /> @@ -291,7 +291,7 @@
/>
GB
- Current extra storage + Current volume storage
@@ -310,17 +310,17 @@
appInteger [ngClass]="{ 'is-invalid': modificationForm.controls.project_application_renewal_volume_limit?.invalid, - 'is-valid': modificationForm.controls.project_application_renewal_volume_limit?.valid + 'is-valid': modificationForm.controls.project_application_renewal_volume_limit?.valid, }" [disabled]="modificationForm.controls.project_application_renewal_volume_counter?.value === 0" />
GB
What is the total amount of volume storage, that you need in the future? How much total volume storage does the user want in the future?
@@ -351,7 +351,7 @@
appInteger [ngClass]="{ 'is-invalid': modificationForm.controls.project_application_renewal_volume_limit_adjusted?.invalid, - 'is-valid': modificationForm.controls.project_application_renewal_volume_limit_adjusted?.valid + 'is-valid': modificationForm.controls.project_application_renewal_volume_limit_adjusted?.valid, }" [disabled]="modificationForm.controls.project_application_renewal_volume_counter_adjusted?.value === 0" /> @@ -407,7 +407,7 @@
required [ngClass]="{ 'is-invalid': modificationForm.controls.project_application_renewal_object_storage?.invalid, - 'is-valid': modificationForm.controls.project_application_renewal_object_storage?.valid + 'is-valid': modificationForm.controls.project_application_renewal_object_storage?.valid, }" />
GB
@@ -448,7 +448,7 @@
required [ngClass]="{ 'is-invalid': modificationForm.controls.project_application_renewal_object_storage_adjust?.invalid, - 'is-valid': modificationForm.controls.project_application_renewal_object_storage_adjust?.valid + 'is-valid': modificationForm.controls.project_application_renewal_object_storage_adjust?.valid, }" />
GB
@@ -553,7 +553,7 @@
required [ngClass]="{ 'is-invalid': modificationForm.controls.project_application_renewal_cloud_service_user_number?.invalid, - 'is-valid': modificationForm.controls.project_application_renewal_cloud_service_user_number?.valid + 'is-valid': modificationForm.controls.project_application_renewal_cloud_service_user_number?.valid, }" /> @@ -611,7 +611,7 @@
[ngClass]="{ 'is-invalid': modificationForm.controls.project_application_renewal_comment?.invalid || !checkValidityComment(), - 'is-valid': modificationForm.controls.project_application_renewal_comment?.valid && checkValidityComment() + 'is-valid': modificationForm.controls.project_application_renewal_comment?.valid && checkValidityComment(), }" >
diff --git a/src/app/projectmanagement/overview.component.html b/src/app/projectmanagement/overview.component.html index 093540ec68..76eb8253e1 100644 --- a/src/app/projectmanagement/overview.component.html +++ b/src/app/projectmanagement/overview.component.html @@ -431,7 +431,6 @@

Request termination

+ ` + ) }) } diff --git a/src/app/shared/modal/abstract-base-modal/abstract-base-modal.component.ts b/src/app/shared/modal/abstract-base-modal/abstract-base-modal.component.ts index 6a05109455..77810f2642 100644 --- a/src/app/shared/modal/abstract-base-modal/abstract-base-modal.component.ts +++ b/src/app/shared/modal/abstract-base-modal/abstract-base-modal.component.ts @@ -14,7 +14,6 @@ export abstract class AbstractBaseModalComponent { } async hide(): Promise { - console.log('close modal abstract') this.modalService.hide(this.modalId) //Fix when calling hide and show form within a modal -- if it is called directly after another the new modal won't open @@ -29,8 +28,7 @@ export abstract class AbstractBaseModalComponent { const bsModalRef: BsModalRef = this.modalService.show(modalType, { initialState }) this.bsModalRef = bsModalRef bsModalRef.setClass('modal-lg') - this.modalId = bsModalRef.id - console.log(`new id ${this.modalId}`) + this.modalId = bsModalRef.id return bsModalRef.content.event } diff --git a/src/app/shared/shared_modules/public-key/generate-public-key-modal/generate-public-key-modal.component.html b/src/app/shared/shared_modules/public-key/generate-public-key-modal/generate-public-key-modal.component.html new file mode 100644 index 0000000000..7f3107d7e4 --- /dev/null +++ b/src/app/shared/shared_modules/public-key/generate-public-key-modal/generate-public-key-modal.component.html @@ -0,0 +1,55 @@ + + + + + diff --git a/src/app/shared/shared_modules/public-key/generate-public-key-modal/generate-public-key-modal.component.scss b/src/app/shared/shared_modules/public-key/generate-public-key-modal/generate-public-key-modal.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/shared/shared_modules/public-key/generate-public-key-modal/generate-public-key-modal.component.spec.ts b/src/app/shared/shared_modules/public-key/generate-public-key-modal/generate-public-key-modal.component.spec.ts new file mode 100644 index 0000000000..883f9cbe67 --- /dev/null +++ b/src/app/shared/shared_modules/public-key/generate-public-key-modal/generate-public-key-modal.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GeneratePublicKeyModalComponent } from './generate-public-key-modal.component'; + +describe('GeneratePublicKeyModalComponent', () => { + let component: GeneratePublicKeyModalComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [GeneratePublicKeyModalComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(GeneratePublicKeyModalComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/shared/shared_modules/public-key/generate-public-key-modal/generate-public-key-modal.component.ts b/src/app/shared/shared_modules/public-key/generate-public-key-modal/generate-public-key-modal.component.ts new file mode 100644 index 0000000000..f5457773e7 --- /dev/null +++ b/src/app/shared/shared_modules/public-key/generate-public-key-modal/generate-public-key-modal.component.ts @@ -0,0 +1,48 @@ +import { Component, EventEmitter, Injectable, Output } from '@angular/core'; +import { KeyService } from 'app/api-connector/key.service'; +import { AbstractBaseModalComponent } from 'app/shared/modal/abstract-base-modal/abstract-base-modal.component'; +import { BsModalService } from 'ngx-bootstrap/modal'; +import { saveAs } from 'file-saver' + +@Injectable({ providedIn: 'root' }) +@Component({ + selector: 'app-generate-public-key-modal', + templateUrl: './generate-public-key-modal.component.html', + styleUrl: './generate-public-key-modal.component.scss' +}) +export class GeneratePublicKeyModalComponent extends AbstractBaseModalComponent { + userlogin:string; + acknowledgement_given:boolean=false + + constructor( + protected modalService: BsModalService, + private keyService:KeyService + ) { + super(modalService) + + } + showGeneratePublicKeyModal( + userlogin:string + + ): EventEmitter { + const initialState = { + userlogin + } + + return this.showBaseModal(GeneratePublicKeyModalComponent, initialState) + } + + downloadPem(data: string): void { + const blob: Blob = new Blob([data], { type: 'pem' }) + const url: string = window.URL.createObjectURL(blob) + saveAs(url, `${this.userlogin}_ecdsa`) + } + + + generateKey(): void { + this.keyService.generateKey().subscribe((res: any): void => { + this.event.emit() + this.downloadPem(res['private_key']) + }) + } +} diff --git a/src/app/shared/shared_modules/public-key/public-key.component.html b/src/app/shared/shared_modules/public-key/public-key.component.html index 26783b83b5..fd5247ac7a 100644 --- a/src/app/shared/shared_modules/public-key/public-key.component.html +++ b/src/app/shared/shared_modules/public-key/public-key.component.html @@ -17,7 +17,7 @@ class="btn btn-primary" style="float: left; margin: 2px" type="button" - (click)="unsetAcknowledgment();generateKeyModal.show()" + (click)="showGeneratePublicKeyModal()" id="generateSShKey" data-test-id="generateSShKey" > @@ -27,7 +27,7 @@ class="btn btn-primary" style="float: left; margin: 2px" type="button" - (click)="public_key = '';unsetAcknowledgment(); pubKeyModal.show()" + (click)="showSetPublicKeyModal()" id="setPublicKeyButton" data-test-id="setPublicKeyButton" > @@ -71,229 +71,3 @@ - - - - - - - diff --git a/src/app/shared/shared_modules/public-key/public-key.component.ts b/src/app/shared/shared_modules/public-key/public-key.component.ts index 13a6d859da..5d6cf119e2 100644 --- a/src/app/shared/shared_modules/public-key/public-key.component.ts +++ b/src/app/shared/shared_modules/public-key/public-key.component.ts @@ -10,6 +10,8 @@ import { AbstractBaseClass } from '../baseClass/abstract-base-class' import { WIKI_GENERATE_KEYS, CLOUD_PORTAL_SUPPORT_MAIL } from '../../../../links/links' import { NotificationModalComponent } from '../../modal/notification-modal' import { BlacklistedResponse } from '../../../api-connector/response-interfaces' +import { GeneratePublicKeyModalComponent } from './generate-public-key-modal/generate-public-key-modal.component' +import { SetPublicKeyModalComponent } from './set-public-key-modal/set-public-key-modal.component' /** * Public Key component. @@ -34,7 +36,8 @@ export class PublicKeyComponent extends AbstractBaseClass implements OnInit { constructor( private keyService: KeyService, private clipboardService: ClipboardService, - private modalService: BsModalService + private generatePublicKeyModal:GeneratePublicKeyModalComponent, + private setPublicKeyModalComponent:SetPublicKeyModalComponent ) { super() } @@ -45,25 +48,30 @@ export class PublicKeyComponent extends AbstractBaseClass implements OnInit { } } - unsetAcknowledgment():void{ - this.acknowledgement_given=false; - } + showSetPublicKeyModal():void{ + this.setPublicKeyModalComponent.showSetPublicKeyModal(this.userinfo.PublicKey).subscribe(() =>{ + console.log("event submitted") + this.getUserPublicKey() + }) - downloadPem(data: string): void { - const blob: Blob = new Blob([data], { type: 'pem' }) - const url: string = window.URL.createObjectURL(blob) - saveAs(url, `${this.userinfo.UserLogin}_ecdsa`) } - generateKey(): void { - this.keyService.generateKey().subscribe((res: any): void => { + showGeneratePublicKeyModal():void{ + this.generatePublicKeyModal.showGeneratePublicKeyModal(this.userinfo.UserLogin).subscribe(() =>{ + console.log("event submitted") this.getUserPublicKey() - this.downloadPem(res['private_key']) }) } + unsetAcknowledgment():void{ + this.acknowledgement_given=false; + } + + + + isKeyBlocked(): void { - this.keyService.isBlocked(this.public_key.trim()).subscribe((res: BlacklistedResponse) => { + this.keyService.isBlocked(this.userinfo.PublicKey.trim()).subscribe((res: BlacklistedResponse) => { this.blocked_key = res.blacklisted }) } @@ -75,41 +83,7 @@ export class PublicKeyComponent extends AbstractBaseClass implements OnInit { }) } - validateKey(): void { - this.keyService.validateKey(this.public_key.trim()).subscribe( - (res: any) => { - this.validated_key = res['status'] === 'valid' - }, - () => { - this.validated_key = false - } - ) - } - importKey(): void { - const re: RegExp = /\+/gi - - this.keyService.postKey(this.public_key.replace(re, '%2B').trim()).subscribe({ - next: (): void => { - this.getUserPublicKey() - const initialState = { - notificationModalTitle: 'Success', - notificationModalType: 'info', - notificationModalMessage: 'The new public key got successfully set' - } - this.modalService.show(NotificationModalComponent, { initialState }) - }, - error: (): any => { - const initialState = { - notificationModalTitle: 'Error', - notificationModalType: 'danger', - notificationModalMessage: - 'We were not able successfully set a new public key. Please enter a valid public key!' - } - this.modalService.show(NotificationModalComponent, { initialState }) - } - }) - } copyToClipboard(text: string): void { if (this.clipboardService.isSupported) { diff --git a/src/app/shared/shared_modules/public-key/public-key.module.ts b/src/app/shared/shared_modules/public-key/public-key.module.ts index 1bd631f55b..720e875114 100644 --- a/src/app/shared/shared_modules/public-key/public-key.module.ts +++ b/src/app/shared/shared_modules/public-key/public-key.module.ts @@ -8,6 +8,8 @@ import { AlertModule } from 'ngx-bootstrap/alert' import { NgbModule } from '@ng-bootstrap/ng-bootstrap' import { PublicKeyComponent } from './public-key.component' import { PipeModuleModule } from '../../../pipe-module/pipe-module.module' +import { GeneratePublicKeyModalComponent } from './generate-public-key-modal/generate-public-key-modal.component' +import { SetPublicKeyModalComponent } from './set-public-key-modal/set-public-key-modal.component' /** * Public key module. @@ -23,7 +25,7 @@ import { PipeModuleModule } from '../../../pipe-module/pipe-module.module' PipeModuleModule ], - declarations: [PublicKeyComponent], + declarations: [PublicKeyComponent,GeneratePublicKeyModalComponent,SetPublicKeyModalComponent], exports: [PublicKeyComponent, AlertModule, FormsModule, ModalModule, CommonModule, TabsModule] }) export class PublicKeyModule {} diff --git a/src/app/shared/shared_modules/public-key/set-public-key-modal/set-public-key-modal.component.html b/src/app/shared/shared_modules/public-key/set-public-key-modal/set-public-key-modal.component.html new file mode 100644 index 0000000000..469c201282 --- /dev/null +++ b/src/app/shared/shared_modules/public-key/set-public-key-modal/set-public-key-modal.component.html @@ -0,0 +1,67 @@ + + + + + diff --git a/src/app/shared/shared_modules/public-key/set-public-key-modal/set-public-key-modal.component.scss b/src/app/shared/shared_modules/public-key/set-public-key-modal/set-public-key-modal.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/shared/shared_modules/public-key/set-public-key-modal/set-public-key-modal.component.spec.ts b/src/app/shared/shared_modules/public-key/set-public-key-modal/set-public-key-modal.component.spec.ts new file mode 100644 index 0000000000..5222159674 --- /dev/null +++ b/src/app/shared/shared_modules/public-key/set-public-key-modal/set-public-key-modal.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SetPublicKeyModalComponent } from './set-public-key-modal.component'; + +describe('SetPublicKeyModalComponent', () => { + let component: SetPublicKeyModalComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [SetPublicKeyModalComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(SetPublicKeyModalComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/shared/shared_modules/public-key/set-public-key-modal/set-public-key-modal.component.ts b/src/app/shared/shared_modules/public-key/set-public-key-modal/set-public-key-modal.component.ts new file mode 100644 index 0000000000..416cdc5171 --- /dev/null +++ b/src/app/shared/shared_modules/public-key/set-public-key-modal/set-public-key-modal.component.ts @@ -0,0 +1,80 @@ +import { Component, EventEmitter, Injectable } from '@angular/core'; +import { KeyService } from 'app/api-connector/key.service'; +import { BlacklistedResponse } from 'app/api-connector/response-interfaces'; +import { AbstractBaseModalComponent } from 'app/shared/modal/abstract-base-modal/abstract-base-modal.component'; +import { NotificationModalComponent } from 'app/shared/modal/notification-modal'; +import { BsModalService } from 'ngx-bootstrap/modal'; + +@Injectable({ providedIn: 'root' }) +@Component({ + selector: 'app-set-public-key-modal', + templateUrl: './set-public-key-modal.component.html', + styleUrl: './set-public-key-modal.component.scss' +}) +export class SetPublicKeyModalComponent extends AbstractBaseModalComponent { + + acknowledgement_given:boolean=false + public_key:string; + validated_key: boolean = false + blocked_key: boolean = false + current_key_blocked: boolean = false + + constructor( + protected modalService: BsModalService, + private keyService:KeyService + ) { + super(modalService) + + } + showSetPublicKeyModal( + userlogin:string + + ): EventEmitter { + const initialState = { + userlogin + } + + return this.showBaseModal(SetPublicKeyModalComponent, initialState) + } + isKeyBlocked(): void { + this.keyService.isBlocked(this.public_key.trim()).subscribe((res: BlacklistedResponse) => { + this.blocked_key = res.blacklisted + }) + } + +validateKey(): void { + this.keyService.validateKey(this.public_key.trim()).subscribe( + (res: any) => { + this.validated_key = res['status'] === 'valid' + }, + () => { + this.validated_key = false + } + ) + } + + importKey(): void { + const re: RegExp = /\+/gi + + this.keyService.postKey(this.public_key.replace(re, '%2B').trim()).subscribe({ + next: (): void => { + this.event.emit() + const initialState = { + notificationModalTitle: 'Success', + notificationModalType: 'info', + notificationModalMessage: 'The new public key got successfully set' + } + this.modalService.show(NotificationModalComponent, { initialState }) + }, + error: (): any => { + const initialState = { + notificationModalTitle: 'Error', + notificationModalType: 'danger', + notificationModalMessage: + 'We were not able successfully set a new public key. Please enter a valid public key!' + } + this.modalService.show(NotificationModalComponent, { initialState }) + } + }) + } +} diff --git a/src/links/links.ts b/src/links/links.ts index bca5730564..f36d30c87e 100644 --- a/src/links/links.ts +++ b/src/links/links.ts @@ -37,6 +37,7 @@ export const SCALING_UP_WIKI: string = `${environment.SIMPLEVM_WIKI_PRE}simple_v export const CREDITS_WIKI: string = `${environment.WIKI_PRE}portal/credits/` export const WIKI_PERSONAL_DATA: string = `${environment.WIKI_PRE}portal/personal_data` export const SURVEY_LINK: string = 'https://cloud.denbi.de/survey/index.php/252136?lang=en' +export const TERMINATION_SURVEY_LINK: string= 'https://cloud.denbi.de/survey/index.php/823721?lang=en' export const CLOUD_PORTAL_SUPPORT_MAIL = 'cloud-helpdesk@denbi.de' export const POLICY_LINK: string = 'https://cloud.denbi.de/about/policies/' export const SIMPLE_VM_LINK: string = 'https://cloud.denbi.de/about/project-types/simplevm/'