Skip to content

Commit ff1ecf9

Browse files
committed
Api key management works
1 parent 21f728f commit ff1ecf9

File tree

10 files changed

+130
-59
lines changed

10 files changed

+130
-59
lines changed

src/app/admin/api-key/api-key-edit/api-key-edit.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
name="permissions"
4444
[compareWith]="compare"
4545
[(ngModel)]="apiKeyRequest.permissions"
46+
[multiple]="true"
4647
>
4748
<mat-option
4849
*ngFor="let permission of permissions"

src/app/admin/api-key/api-key-edit/api-key-edit.component.ts

Lines changed: 69 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import { Location } from '@angular/common';
2+
import { HttpErrorResponse } from '@angular/common/http';
23
import { Component, OnInit } from '@angular/core';
34
import { ActivatedRoute } from '@angular/router';
45
import { PermissionResponse } from '@app/admin/permission/permission.model';
6+
import { PermissionService } from '@app/admin/permission/permission.service';
57
import { TranslateService } from '@ngx-translate/core';
8+
import { ErrorMessageService } from '@shared/error-message.service';
69
import { BackButton } from '@shared/models/back-button.model';
10+
import { SharedVariableService } from '@shared/shared-variable/shared-variable.service';
711
import { ApiKeyRequest } from '../api-key.model';
812
import { ApiKeyService } from '../api-key.service';
913

@@ -20,24 +24,30 @@ export class ApiKeyEditComponent implements OnInit {
2024
};
2125
public title = '';
2226
public submitButton = '';
23-
private apiKeyId: number;
27+
private id: number;
2428
public errorMessage: string;
2529
public errorMessages: string[];
2630
public errorFields: string[];
2731
public formFailedSubmit = false;
2832
public isEditMode = false;
2933
public permissions: PermissionResponse[] = [];
34+
private organizationId: number;
3035

3136
constructor(
3237
private translate: TranslateService,
3338
private route: ActivatedRoute,
3439
private location: Location,
35-
private apiKeyService: ApiKeyService
40+
private apiKeyService: ApiKeyService,
41+
private permissionService: PermissionService,
42+
private errorMessageService: ErrorMessageService,
43+
private sharedVariableService: SharedVariableService
3644
) {
3745
translate.use('da');
3846
}
3947

4048
ngOnInit(): void {
49+
this.getPermissions();
50+
this.translate.use('da');
4151
this.translate
4252
.get(['NAV.API-KEY', 'FORM.EDIT-API-KEY', 'API-KEY.EDIT.SAVE'])
4353
.subscribe((translations) => {
@@ -46,35 +56,79 @@ export class ApiKeyEditComponent implements OnInit {
4656
this.submitButton = translations['API-KEY.EDIT.SAVE'];
4757
});
4858

49-
this.apiKeyId = +this.route.snapshot.paramMap.get('api-key-id');
59+
this.id = +this.route.snapshot.paramMap.get('api-key-id');
60+
this.organizationId = this.sharedVariableService.getSelectedOrganisationId();
5061

51-
if (this.apiKeyId > 0) {
52-
// TODO: Fetch current api key
53-
this.isEditMode = true;
54-
}
62+
// if (this.id > 0) {
63+
// // TODO: Fetch current api key
64+
// this.getApiKey(this.id);
65+
// this.isEditMode = true;
66+
// }
67+
}
68+
69+
// private getApiKey(id: number) {
70+
// this.apiKeyService.get(id).subscribe(
71+
// (response) => {
72+
// console.log(response);
73+
// this.apiKeyRequest.id = response.id;
74+
// this.apiKeyRequest.name = response.name;
75+
// this.apiKeyRequest.permissions = response.permissions;
76+
// },
77+
// (error: HttpErrorResponse) => {
78+
// this.showError(error);
79+
// }
80+
// );
81+
// }
82+
83+
private getPermissions() {
84+
this.permissionService
85+
.getPermissions(
86+
undefined,
87+
undefined,
88+
undefined,
89+
undefined,
90+
undefined,
91+
this.organizationId
92+
)
93+
.subscribe(
94+
(permissions) => {
95+
this.permissions = permissions.data.filter(
96+
(x) => x.organization?.id === this.organizationId
97+
);
98+
},
99+
(error: HttpErrorResponse) => {
100+
this.showError(error);
101+
}
102+
);
55103
}
56104

57105
onSubmit(): void {
58-
if (this.apiKeyId) {
59-
this.update();
60-
} else {
61-
this.create();
62-
}
106+
this.id ? this.update() : this.create();
63107
}
64108

65109
private create(): void {
66-
// TODO: CREATE
110+
this.apiKeyService.create(this.apiKeyRequest).subscribe(
111+
() => this.routeBack(),
112+
(err) => this.showError(err)
113+
);
67114
}
68115

69116
private update(): void {
70-
// TODO: UPDATE
71-
this.routeBack();
117+
this.apiKeyService
118+
.update(this.apiKeyRequest, this.id)
119+
.subscribe(this.routeBack, this.showError);
72120
}
73121

74122
public compare(o1: any, o2: any): boolean {
75123
return o1 === o2;
76124
}
77125

126+
private showError(err: HttpErrorResponse) {
127+
const result = this.errorMessageService.handleErrorMessageWithFields(err);
128+
this.errorFields = result.errorFields;
129+
this.errorMessages = result.errorMessages;
130+
}
131+
78132
routeBack(): void {
79133
this.location.back();
80134
}
Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1-
<app-top-bar [title]="'NAV.API-KEY' | translate">
1+
<app-top-bar
2+
[title]="'NAV.API-KEY' | translate"
3+
[ctaLabel]="'API-KEY.CREATE-NEW-API-KEY' | translate"
4+
[ctaRouterLink]="'new-api-key'"
5+
>
26
</app-top-bar>
37
<div class="container-fluid">
48
<div class="row">
5-
<div class="col-12">
6-
<div class="jumbotron--table">
7-
<app-api-key-table [organisationId]="organisationId"></app-api-key-table>
8-
</div>
9+
<div class="col-12">
10+
<div class="jumbotron--table">
11+
<app-api-key-table
12+
[organisationId]="organisationId"
13+
></app-api-key-table>
914
</div>
15+
</div>
1016
</div>
1117
</div>

src/app/admin/api-key/api-key-list/api-key-table/api-key-table.component.html

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,7 @@
1616
{{ 'API-KEY.NAME' | translate }}
1717
</th>
1818
<td mat-cell *matCellDef="let element">
19-
<!-- <a *ngIf="canAccess(element); else justText"
20-
(click)="routeToPermissions(element)"
21-
routerLinkActive="active" class="permission-link">
22-
{{element.name}}
23-
</a> -->
24-
<!-- <ng-template #justText> -->
2519
{{ element.name }}
26-
<!-- </ng-template> -->
2720
</td>
2821
</ng-container>
2922

@@ -33,9 +26,12 @@
3326
{{ 'API-KEY.PERMISSIONS' | translate }}
3427
</th>
3528
<td mat-cell *matCellDef="let element">
36-
<div *ngIf="element.users; else noUsers">
37-
{{ element.users.length }}
38-
</div>
29+
<ng-container *ngIf="element.permissions; else noUsers">
30+
<ng-container *ngFor="let pm of element.permissions">
31+
<span>{{ pm.name }}</span>
32+
<br />
33+
</ng-container>
34+
</ng-container>
3935
<ng-template #noUsers>{{ 'NoUsersAdded' | translate }}</ng-template>
4036
</td>
4137
</ng-container>
@@ -68,13 +64,14 @@
6864
class="dropdown-menu dropdown-menu--table"
6965
attr.aria-labelledby="tableRowDropdown-{{ element.id }}"
7066
>
71-
<li class="dropdown-item">
67+
<!-- TODO: Delete. Edit is not part of estimate. Since it's only one option, use a delete button instead -->
68+
<!-- <li class="dropdown-item">
7269
<a
7370
[routerLink]="['/admin/api-key', element.id, 'edit-api-key']"
7471
routerLinkActive="active"
7572
>{{ 'API-KEY.TABLE-ROW.EDIT' | translate }}
7673
</a>
77-
</li>
74+
</li> -->
7875
<li class="dropdown-item">
7976
<a (click)="deleteApiKey(element.id)" [routerLink]=""
8077
>{{ 'API-KEY.TABLE-ROW.DELETE' | translate }}

src/app/admin/api-key/api-key-list/api-key-table/api-key-table.component.ts

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,13 @@ import { ApiKeyService } from '../../api-key.service';
1717
})
1818
export class ApiKeyTableComponent implements AfterViewInit {
1919
@Input() organisationId: number;
20-
displayedColumns: string[] = ['name', 'permissions', 'key', 'menu'];
21-
data: ApiKeyResponse[] = [
22-
// { id: 1, name: 'Abcd', key: 'sdafsegjhkjtrewr34252t$25!', permissions: [] },
23-
// {
24-
// id: 2,
25-
// name: 'DoofApi',
26-
// key: 'jasdhjlw8o3-4u2qeuqnwodasd-521529f',
27-
// permissions: [],
28-
// },
20+
displayedColumns: string[] = [
21+
'name',
22+
'permissions',
23+
'key',
24+
'menu',
2925
];
26+
data: ApiKeyResponse[] = [];
3027
isLoadingResults = true;
3128
@ViewChild(MatPaginator) paginator: MatPaginator;
3229
@ViewChild(MatSort) sort: MatSort;
@@ -83,15 +80,7 @@ export class ApiKeyTableComponent implements AfterViewInit {
8380
);
8481
}
8582

86-
canAccess(element: ApiKeyResponse) {
87-
// if (element.type === PermissionType.GlobalAdmin) {
88-
// return this.meService.hasGlobalAdmin();
89-
// }
90-
// return element.permissions?.some(
91-
// (p) =>
92-
// p.organization &&
93-
// this.meService.hasAdminAccessInTargetOrganization(p.organization.id)
94-
// );
83+
canAccess(_element: ApiKeyResponse) {
9584
return this.meService.hasAdminAccessInTargetOrganization(
9685
this.organisationId
9786
);

src/app/navbar/organisation-dropdown/organisation-dropdown.component.html

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@
3939
</a>
4040
<fa-icon [icon]="faIdBadge" class="navbar-icon"></fa-icon>
4141
</li>
42-
<li class="nav-item">
43-
<a routerLink="/admin/api-key" routerLinkActive="active"
44-
class="nav-link pl-5 position-relative rounded">
45-
{{'NAV.API-KEY' | translate}}
46-
</a>
47-
<fa-icon [icon]="faKey" class="navbar-icon"></fa-icon>
48-
</li>
4942
</div>
43+
<li *ngIf="user && (isOrgAdmin || isGlobalAdmin)" class="nav-item">
44+
<a routerLink="/admin/api-key" routerLinkActive="active"
45+
class="nav-link pl-5 position-relative rounded">
46+
{{'NAV.API-KEY' | translate}}
47+
</a>
48+
<fa-icon [icon]="faKey" class="navbar-icon"></fa-icon>
49+
</li>
5050
</ul>

src/app/shared/pipes/pipes.module.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { ActiveDeactivePipe } from './activeDeactive.pipe';
55
import { isGlobalAdminPipe } from './is-global-admin.pipe';
66
import { CreatedUpdatedByPipe } from './created-updated-by.pipe';
77
import { CustomDatePipe, CustomTableDatePipe } from './custom-date.pipe';
8+
import { UniquePermissionOrganizationsPipe } from './unique-permission-organizations.pipe';
89

910
@NgModule({
1011
declarations: [
@@ -14,6 +15,7 @@ import { CustomDatePipe, CustomTableDatePipe } from './custom-date.pipe';
1415
CustomDatePipe,
1516
CustomTableDatePipe,
1617
CreatedUpdatedByPipe,
18+
UniquePermissionOrganizationsPipe,
1719
],
1820
imports: [
1921
CommonModule
@@ -25,6 +27,7 @@ import { CustomDatePipe, CustomTableDatePipe } from './custom-date.pipe';
2527
CustomDatePipe,
2628
CustomTableDatePipe,
2729
CreatedUpdatedByPipe,
30+
UniquePermissionOrganizationsPipe,
2831
]
2932
})
3033
export class PipesModule { }
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Pipe, PipeTransform } from '@angular/core';
2+
import { PermissionResponse } from '@app/admin/permission/permission.model';
3+
4+
@Pipe({
5+
name: 'uniquePermissionOrganizations',
6+
})
7+
export class UniquePermissionOrganizationsPipe implements PipeTransform {
8+
transform(
9+
value: PermissionResponse[],
10+
..._: unknown[]
11+
): PermissionResponse[] {
12+
// Ensure that no element appears twice. Orders it so that the duplicate (second match) takes priority
13+
const uniqueArr = Array.from(
14+
new Map(value.map((item) => [item.organization?.id, item])).values()
15+
);
16+
17+
return uniqueArr;
18+
}
19+
}

src/assets/i18n/da.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -850,15 +850,17 @@
850850
"SIGFOX": "Sigfox",
851851
"API-KEY": {
852852
"NAME": "Navn",
853+
"ORGANIZATION": "Organisation",
853854
"PERMISSIONS": "Brugergrupper",
854855
"KEY": "Nøgle",
856+
"CREATE-NEW-API-KEY": "Opret ny nøgle",
855857
"DETAIL": {},
856858
"EDIT": {
857859
"NAME": "Indtast nøglens navn",
858860
"NAME-PLACEHOLDER": "Indtast nøglens navn",
859861
"CANCEL": "Annuller",
860862
"SAVE": "Gem nøgle",
861-
"CREATE-NEW-API-KEY": "Opret nøgle"
863+
"CREATE-API-KEY": "Opret nøgle"
862864
},
863865
"TABLE-ROW": {
864866
"EDIT": "Redigér",

tslint.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@
129129
"use-lifecycle-interface": true,
130130
"use-pipe-transform-interface": true,
131131
"variable-name": {
132-
"options": ["ban-keywords", "check-format", "allow-pascal-case"]
132+
"options": ["ban-keywords", "check-format", "allow-pascal-case", "allow-leading-underscore"]
133133
},
134134
"whitespace": {
135135
"options": [

0 commit comments

Comments
 (0)