From 1019c9dad209bbbae97ff20ef50bab8ba6518817 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henry=20T=C3=A4schner?= <129834483+HenryT-CG@users.noreply.github.com> Date: Thu, 6 Jun 2024 07:45:32 +0200 Subject: [PATCH] feat: add IAM roles (#88) --- src/_mixins.scss | 10 +++ .../app-detail/app-detail.component.html | 8 +-- .../app-detail/app-detail.component.spec.ts | 8 +-- .../app-detail/app-detail.component.ts | 9 +-- .../app-search/app-search.component.html | 2 +- .../app-search/app-search.component.scss | 8 --- .../permission-detail.component.html | 6 +- .../role-detail/role-detail.component.html | 61 +++++++++++++++++-- .../role-detail/role-detail.component.scss | 18 ++++++ .../role-detail/role-detail.component.ts | 41 ++++++++++++- src/assets/i18n/de.json | 22 +++++-- src/assets/i18n/en.json | 28 ++++++--- 12 files changed, 175 insertions(+), 46 deletions(-) create mode 100644 src/app/permission/role-detail/role-detail.component.scss diff --git a/src/_mixins.scss b/src/_mixins.scss index e69f53d..3a62968 100644 --- a/src/_mixins.scss +++ b/src/_mixins.scss @@ -229,3 +229,13 @@ } } } + +@mixin listbox-zebra-rows { + :host ::ng-deep { + .p-listbox:not(.p-disabled) .p-listbox-item:not(.p-highlight):not(.p-disabled) { + &:nth-child(odd) { + background-color: #f8f9fa; + } + } + } +} diff --git a/src/app/permission/app-detail/app-detail.component.html b/src/app/permission/app-detail/app-detail.component.html index 1e95918..34071e9 100644 --- a/src/app/permission/app-detail/app-detail.component.html +++ b/src/app/permission/app-detail/app-detail.component.html @@ -183,10 +183,9 @@ pbutton type="button" *ngIf="myPermissions.includes('ROLE#CREATE') && showRoleTools" - [id]="'app_detail_permission_table_header_add_idm_roles_action'" - (click)="onCreateIDMRoles($event)" - [disabled]="true" - [title]="'ACTIONS.CREATE.IDM_ROLES.TOOLTIP' | translate" + [id]="'app_detail_permission_table_header_add_iam_roles_action'" + (click)="onAddIAMRoles($event)" + [title]="'ACTIONS.CREATE.IAM_ROLES.TOOLTIP' | translate" class="p-1 p-button-rounded font-medium p-button-text p-button p-component p-button-icon-only" > @@ -512,6 +511,7 @@ [roles]="roles" [role]="role" [changeMode]="changeMode" + [showIamRolesDialog]="showIamRolesDialog" [displayDetailDialog]="showRoleDetailDialog" [displayDeleteDialog]="showRoleDeleteDialog" (dataChanged)="onDetailChanged($event)" diff --git a/src/app/permission/app-detail/app-detail.component.spec.ts b/src/app/permission/app-detail/app-detail.component.spec.ts index 7f744af..a3ee1c9 100644 --- a/src/app/permission/app-detail/app-detail.component.spec.ts +++ b/src/app/permission/app-detail/app-detail.component.spec.ts @@ -380,12 +380,10 @@ describe('AppDetailComponent', () => { /** * CREATE */ - it('should do something onCreateIDMRoles', () => { - spyOn(console, 'log') + it('should do something onAddIAMRoles', () => { + component.onAddIAMRoles(new MouseEvent('click')) - component.onCreateIDMRoles(new MouseEvent('click')) - - expect(console.log).toHaveBeenCalled() + expect(component.showIamRolesDialog).toBeTrue() }) it('should return if there are no missing ws roles', () => { diff --git a/src/app/permission/app-detail/app-detail.component.ts b/src/app/permission/app-detail/app-detail.component.ts index 3a6ee8f..769b961 100644 --- a/src/app/permission/app-detail/app-detail.component.ts +++ b/src/app/permission/app-detail/app-detail.component.ts @@ -115,6 +115,7 @@ export class AppDetailComponent implements OnInit, OnDestroy { public missingWorkspaceRoles = false public showRoleDetailDialog = false public showRoleDeleteDialog = false + public showIamRolesDialog = false public showRoleTools = false constructor( @@ -366,10 +367,6 @@ export class AppDetailComponent implements OnInit, OnDestroy { } } - public onCreateIDMRoles(ev: MouseEvent) { - console.log('TODO: select IDM roles to take over into permissions') - } - public onCreateWorkspaceRoles(ev: MouseEvent) { ev.stopPropagation() if (!this.missingWorkspaceRoles) return @@ -624,8 +621,12 @@ export class AppDetailComponent implements OnInit, OnDestroy { this.showPermissionDeleteDialog = false this.showRoleDetailDialog = false this.showRoleDeleteDialog = false + this.showIamRolesDialog = false if (changed) this.loadData() } + public onAddIAMRoles(ev: MouseEvent) { + this.showIamRolesDialog = true + } /**************************************************************************** * PERMISSION diff --git a/src/app/permission/app-search/app-search.component.html b/src/app/permission/app-search/app-search.component.html index bb9128b..f59361e 100644 --- a/src/app/permission/app-search/app-search.component.html +++ b/src/app/permission/app-search/app-search.component.html @@ -114,7 +114,7 @@ *ngIf="app.apps" [id]="'app_search_data_idx_' + idx + '_apps'" [title]="'APP.APPS' | translate" - class="card-badge-right badge-2-1 p-1 text-primary" + class="card-badge-right badge-2 p-1 text-xs" >{{ app.apps }}
diff --git a/src/app/permission/app-search/app-search.component.scss b/src/app/permission/app-search/app-search.component.scss index 6248eed..8d97422 100644 --- a/src/app/permission/app-search/app-search.component.scss +++ b/src/app/permission/app-search/app-search.component.scss @@ -5,14 +5,6 @@ @include search-criteria-select-button; @include card-badges; -:host ::ng-deep { - .card-badge-left, - .card-badge-right { - &.badge-2-1 { - top: 32px; - } - } -} @media screen and (min-width: 768px) { .md\:h-2-5rem { height: 2.5rem !important; diff --git a/src/app/permission/permission-detail/permission-detail.component.html b/src/app/permission/permission-detail/permission-detail.component.html index 1af86f6..1f33f2a 100644 --- a/src/app/permission/permission-detail/permission-detail.component.html +++ b/src/app/permission/permission-detail/permission-detail.component.html @@ -141,14 +141,14 @@ [dismissableMask]="true" [style]="{ 'max-width': '425px' }" > -
+
-
+
{{ ('ACTIONS.DELETE.MESSAGE.TEXT' | translate).replace('{{ITEM}}', permission?.resource + '#' + permission?.action) }}
-
{{ 'ACTIONS.DELETE.MESSAGE.INFO' | translate }}
+
{{ 'ACTIONS.DELETE.MESSAGE.INFO' | translate }}
diff --git a/src/app/permission/role-detail/role-detail.component.html b/src/app/permission/role-detail/role-detail.component.html index bde099b..a9cf77d 100644 --- a/src/app/permission/role-detail/role-detail.component.html +++ b/src/app/permission/role-detail/role-detail.component.html @@ -9,7 +9,7 @@ [style]="{ width: '400px' }" >
-
+
@@ -63,11 +63,13 @@ [dismissableMask]="true" [style]="{ 'max-width': '425px' }" > -
+
-
{{ ('ACTIONS.DELETE.MESSAGE.TEXT' | translate).replace('{{ITEM}}', role?.name) }}
-
{{ 'ACTIONS.DELETE.MESSAGE.INFO' | translate }}
+
+ {{ ('ACTIONS.DELETE.MESSAGE.TEXT' | translate).replace('{{ITEM}}', role?.name) }} +
+
{{ 'ACTIONS.DELETE.MESSAGE.INFO' | translate }}
@@ -96,3 +98,54 @@
+ + + +
+
{{ 'ROLE.IAM.INFO' | translate }}
+ +
+ +
+ + +
+
+
diff --git a/src/app/permission/role-detail/role-detail.component.scss b/src/app/permission/role-detail/role-detail.component.scss new file mode 100644 index 0000000..7a2beec --- /dev/null +++ b/src/app/permission/role-detail/role-detail.component.scss @@ -0,0 +1,18 @@ +@import '/src/_mixins.scss'; + +@include listbox-zebra-rows; + +:host ::ng-deep { + .p-listbox { + box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12); + .p-listbox-list-wrapper { + border-radius: var(--border-radius); + .p-listbox-list .p-listbox-item { + padding: 0.5rem 1rem; + .p-checkbox { + margin-right: 1rem; + } + } + } + } +} diff --git a/src/app/permission/role-detail/role-detail.component.ts b/src/app/permission/role-detail/role-detail.component.ts index ba8c223..0274193 100644 --- a/src/app/permission/role-detail/role-detail.component.ts +++ b/src/app/permission/role-detail/role-detail.component.ts @@ -4,12 +4,13 @@ import { TranslateService } from '@ngx-translate/core' import { PortalMessageService, UserService } from '@onecx/portal-integration-angular' -import { Role, CreateRoleRequest, UpdateRoleRequest, RoleAPIService } from 'src/app/shared/generated' +import { Role, CreateRoleRequest, IAMRole, UpdateRoleRequest, RoleAPIService } from 'src/app/shared/generated' import { App, ChangeMode } from 'src/app/permission/app-detail/app-detail.component' @Component({ selector: 'app-role-detail', - templateUrl: './role-detail.component.html' + templateUrl: './role-detail.component.html', + styleUrls: ['./role-detail.component.scss'] }) export class RoleDetailComponent implements OnChanges { @Input() currentApp!: App @@ -18,10 +19,13 @@ export class RoleDetailComponent implements OnChanges { @Input() changeMode: ChangeMode = 'VIEW' @Input() displayDetailDialog = false @Input() displayDeleteDialog = false + @Input() showIamRolesDialog = false @Output() dataChanged: EventEmitter = new EventEmitter() public myPermissions = new Array() // permissions of the user public formGroupRole: FormGroup + public iamRoles!: IAMRole[] + public selectedIamRoles: IAMRole[] | undefined constructor( private roleApi: RoleAPIService, @@ -44,6 +48,7 @@ export class RoleDetailComponent implements OnChanges { this.formGroupRole.controls['name'].patchValue(this.role.name) this.formGroupRole.controls['description'].patchValue(this.role.description) } + if (this.showIamRolesDialog) this.getIamRoles() } public onClose(): void { @@ -111,6 +116,9 @@ export class RoleDetailComponent implements OnChanges { } } + /** + * Delete a ROLE + */ public onDeleteConfirmation() { this.roleApi.deleteRole({ id: this.role?.id ?? '' }).subscribe({ next: () => { @@ -123,4 +131,33 @@ export class RoleDetailComponent implements OnChanges { } }) } + + /** + * Select IAM Roles to be added + */ + public getIamRoles() { + this.roleApi.searchAvailableRoles({ iAMRoleSearchCriteria: { pageSize: 1000 } }).subscribe({ + next: (data) => { + this.iamRoles = data.stream ?? [] + }, + error: (err) => { + console.error(err.error) + } + }) + } + public onAddIamRoles() { + console.log('onAddIamRoles', this.selectedIamRoles) + if (this.selectedIamRoles && this.selectedIamRoles.length > 0) + this.roleApi.createRole({ createRolesRequest: { roles: this.selectedIamRoles! } }).subscribe({ + next: () => { + this.msgService.success({ summaryKey: 'ACTIONS.CREATE.MESSAGE.ROLE_OK' }) + this.dataChanged.emit(true) + }, + error: (err) => { + this.msgService.error({ summaryKey: 'ACTIONS.CREATE.MESSAGE.ROLE_NOK' }) + console.error(err) + } + }) + else this.dataChanged.emit(false) + } } diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index 69f0b3f..933440b 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -17,7 +17,7 @@ "PERMISSION.TOOLTIP": "Eine neue Berechtigung erstellen", "ROLE": "Rolle erstellen", "ROLE.TOOLTIP": "Eine neue Rolle erstellen", - "IDM_ROLES.TOOLTIP": "IDM Rollen auswählen damit sie hier verwendet werden können", + "IAM_ROLES.TOOLTIP": "IAM Rollen auswählen damit sie hier verwendet werden können", "WORKSPACE_ROLES.TOOLTIP": "Fehlende Workspace Rollen übernehmen damit sie hier verwendet werden können", "MESSAGE": { "APPLICATION_OK": "Die App wurde erfolgreich erstellt", @@ -223,7 +223,13 @@ "TOOLTIP": "Liste der Rollen zu denen Berechtigungen erteilt werden können. Wirksam werden Berechtigungen für einen Benutzer erst dann, wenn der Benutzer der Rolle zugeordnet wird.", "NAME": "Name", "DESCRIPTION": "Beschreibung", - "MANDATORY": "Diese Rolle ist notwendig für den Betrieb und kann somit nicht bearbeitet oder gelöscht werden." + "MANDATORY": "Diese Rolle ist notwendig für den Betrieb und kann somit nicht bearbeitet oder gelöscht werden.", + "IAM": { + "HEADER": "IAM Rollen auswählen", + "INFO": "Liste der fehlenden IAM Rollen", + "Filter": "Filter", + "SAVE": "Auswahl übernehmen" + } }, "VALIDATION": { "HINTS": { @@ -242,9 +248,9 @@ } }, "EXCEPTIONS": { - "HTTP_MISSING_PARAMETER": "Parameter aus der URL konnten nicht abgerufen werden", + "HTTP_MISSING_PARAMETER": "Parameter aus der URL konnten nicht ermittelt werden", "HTTP_STATUS_0": { - "APP": "Unbekanntes Problem beim Abrufen von Apps/Applikationen - Bitte versuchen sie es noch einmal.", + "APP": "Unbekanntes Problem beim Abrufen von Applikationen - Bitte versuchen sie es noch einmal.", "ROLES": "Unbekanntes Problem beim Abrufen von Rollen - Bitte versuchen sie es noch einmal.", "PERMISSIONS": "Unbekanntes Problem beim Abrufen von Berechtigungen - Bitte versuchen sie es noch einmal.", "ASSIGNMENTS": "Unbekanntes Problem beim Abrufen von Berechtigungen - Bitte versuchen sie es noch einmal.", @@ -254,9 +260,13 @@ "ROLES": "Die Rolle konnte nicht verarbeitet werden.", "PERMISSIONS": "Die Berechtigung konnte nicht verarbeitet werden." }, + "HTTP_STATUS_401": { + "APPS": "Sie haben keine Rechte um Applikationen zu sehen.", + "WORKSPACE": "Sie haben keine Rechte um Workspace Daten zu sehen." + }, "HTTP_STATUS_403": { - "APP": "Sie haben keine Rechte um App/Applikation Daten zu sehen.", - "APPS": "Sie haben keine Rechte um Apps/Applikationen zu sehen.", + "APP": "Sie haben keine Rechte um Applikation Daten zu sehen.", + "APPS": "Sie haben keine Rechte um Applikationen zu sehen.", "ROLES": "Sie haben keine Rechte um Rollen zu sehen.", "PERMISSIONS": "Sie haben keine Rechte um Berechtigungen zu sehen.", "ASSIGNMENTS": "Sie haben keine Rechte um Berechtigungen zu sehen.", diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 466aeb0..8700b5f 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -17,7 +17,7 @@ "PERMISSION.TOOLTIP": "Create a new Permission", "ROLE": "Create Role", "ROLE.TOOLTIP": "Create a new Role", - "IDM_ROLES.TOOLTIP": "Select IDM Roles to be used here", + "IAM_ROLES.TOOLTIP": "Select IAM Roles to be used here", "WORKSPACE_ROLES.TOOLTIP": "Create missing Workspace Roles to be used here", "MESSAGE": { "APPLICATION_OK": "The App was created successfully", @@ -223,7 +223,13 @@ "TOOLTIP": "List of roles to which permissions can be granted. Permissions for a user only become effective when the user is assigned to the role.", "NAME": "Name", "DESCRIPTION": "Description", - "MANDATORY": "This Role is necessary for operation and cannot therefore be changed or deleted." + "MANDATORY": "This Role is necessary for operation and cannot therefore be changed or deleted.", + "IAM": { + "HEADER": "Select IAM Roles", + "INFO": "List of missing IAM Roles", + "Filter": "Filter", + "SAVE": "Add selection" + } }, "VALIDATION": { "HINTS": { @@ -242,9 +248,9 @@ } }, "EXCEPTIONS": { - "HTTP_MISSING_PARAMETER": "Parameters could not be loaded from URL", + "HTTP_MISSING_PARAMETER": "Parameters from the URL could not be determined", "HTTP_STATUS_0": { - "APP": "Unknown problem retrieving App/Application data - please try again.", + "APP": "Unknown problem retrieving Application data - please try again.", "ROLES": "Unknown problem retrieving Role data - please try again.", "PERMISSIONS": "Unknown problem retrieving Permission data - please try again.", "ASSIGNMENTS": "Unknown problem retrieving Assignment data - please try again.", @@ -254,9 +260,13 @@ "ROLES": "The Role could not be processed.", "PERMISSIONS": "The permission could not be processed." }, + "HTTP_STATUS_401": { + "APPS": "You have no permissions to see Applications.", + "WORKSPACE": "You have no permissions to see Workspace Data." + }, "HTTP_STATUS_403": { - "APP": "You have no permissions to see App data.", - "APPS": "You have no permissions to see Apps/Applications.", + "APP": "You have no permissions to see Application data.", + "APPS": "You have no permissions to see Applications.", "ROLES": "You have no permissions to see Roles.", "PERMISSIONS": "You have no permissions to see Permissions.", "ASSIGNMENTS": "You have no permissions to see Assignments.", @@ -264,7 +274,7 @@ }, "HTTP_STATUS_404": { "APP": "App could not be found.", - "APPS": "No Apps/Applications could be found.", + "APPS": "No Applications could be found.", "ROLE": "Role could not be found.", "ROLES": "No Roles could be found.", "PERMISSIONS": "No Permissions could be found.", @@ -272,8 +282,8 @@ "WORKSPACE": "Workspace data could not be found." }, "HTTP_STATUS_500": { - "APP": "Unknown problem retrieving App/Application data - please try again.", - "APPS": "Unknown problem retrieving App/Applications data - please try again.", + "APP": "Unknown problem retrieving Application data - please try again.", + "APPS": "Unknown problem retrieving Applications data - please try again.", "ROLES": "Unknown problem retrieving Role data - please try again.", "PERMISSIONS": "Unknown problem retrieving Permission data - please try again.", "ASSIGNMENTS": "Unknown problem retrieving Assignment data - please try again.",