Skip to content

Commit f7672b9

Browse files
Merge branch 'stage' into feature/IOT-1583-MoveApplication
2 parents 743587b + 5fb82e0 commit f7672b9

File tree

85 files changed

+1677
-766
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+1677
-766
lines changed

.github/workflows/on-push-pr.action.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,9 @@ jobs:
1717
vulnerabilities-scan:
1818
runs-on: ubuntu-latest
1919
steps:
20-
- uses: actions/checkout@v2
21-
name: Checkout repository
22-
- uses: debricked/actions/scan@v1
23-
name: Run a vulnerability scan
20+
- uses: actions/checkout@v4
21+
- uses: debricked/actions@v4
2422
env:
25-
# Token must have API access scope to run scans
2623
DEBRICKED_TOKEN: ${{ secrets.DEBRICKED_TOKEN }}
2724
code-build:
2825
runs-on: ubuntu-latest

src/app/admin/organisation/organisation-detail/organisation-detail.component.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010
>
1111
</app-top-bar>
1212
<div class="container-fluid">
13+
<div *ngIf="errorMessages" class="error-messages p-3">
14+
<ul class="mb-0">
15+
<li *ngFor="let error of errorMessages">
16+
{{ error | translate }}
17+
</li>
18+
</ul>
19+
</div>
1320
<div class="row">
1421
<div class="col-12">
1522
<div class="jumbotron">

src/app/admin/organisation/organisation-detail/organisation-detail.component.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import { environment } from "@environments/environment";
1717
import { Title } from "@angular/platform-browser";
1818
import { MeService } from "@shared/services/me.service";
1919
import { OrganizationAccessScope } from "@shared/enums/access-scopes";
20+
import { ErrorMessageService } from "@shared/error-message.service";
21+
import { HttpErrorResponse } from "@angular/common/http";
2022

2123
@Component({
2224
selector: "app-organisation-detail",
@@ -34,6 +36,7 @@ export class OrganisationDetailComponent implements OnInit, OnChanges, OnDestroy
3436
private applicationsSubscription: Subscription;
3537
private deleteDialogSubscription: Subscription;
3638
public dropdownButton: DropdownButton;
39+
public errorMessages: string[];
3740

3841
organisation: OrganisationResponse;
3942
public backButton: BackButton = {
@@ -53,7 +56,8 @@ export class OrganisationDetailComponent implements OnInit, OnChanges, OnDestroy
5356
private deleteDialogService: DeleteDialogService,
5457
private location: Location,
5558
private titleService: Title,
56-
private meService: MeService
59+
private meService: MeService,
60+
private errorMessageService: ErrorMessageService
5761
) {}
5862

5963
ngOnChanges(changes: SimpleChanges): void {}
@@ -100,6 +104,10 @@ export class OrganisationDetailComponent implements OnInit, OnChanges, OnDestroy
100104
this.deleteDialogSubscription = this.deleteDialogService.showSimpleDialog().subscribe(response => {
101105
if (response) {
102106
this.organisationService.delete(this.organisation.id).subscribe(response => {
107+
if (response instanceof HttpErrorResponse) {
108+
this.errorMessages = this.errorMessageService.handleErrorMessageWithFields(response).errorMessages;
109+
return;
110+
}
103111
this.location.back();
104112
});
105113
} else {

src/app/admin/organisation/organisation-list/organisation-tabel/organisation-tabel.component.html

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
<div class="mat-elevation-z8">
1+
<div *ngIf="errorMessages" class="error-messages p-3">
2+
<ul class="mb-0">
3+
<li *ngFor="let error of errorMessages">
4+
{{ error | translate }}
5+
</li>
6+
</ul>
7+
</div>
8+
<div class="mat-elevation-z8 mt-3">
29
<div class="loading-shade" *ngIf="isLoadingResults">
310
<mat-spinner *ngIf="isLoadingResults"></mat-spinner>
411
</div>

src/app/admin/organisation/organisation-list/organisation-tabel/organisation-tabel.component.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import { MatPaginator, PageEvent } from "@angular/material/paginator";
88
import { environment } from "@environments/environment";
99
import { startWith, switchMap, map, catchError } from "rxjs/operators";
1010
import { DefaultPageSizeOptions } from "@shared/constants/page.constants";
11+
import { ErrorMessageService } from "@shared/error-message.service";
12+
import { HttpErrorResponse } from "@angular/common/http";
1113

1214
@Component({
1315
selector: "app-organisation-tabel",
@@ -30,8 +32,13 @@ export class OrganisationTabelComponent implements AfterViewInit {
3032
pageSizeOptions = DefaultPageSizeOptions;
3133

3234
isLoadingResults = true;
35+
public errorMessages: string[];
3336

34-
constructor(private organisationService: OrganisationService, private deleteDialogService: DeleteDialogService) {}
37+
constructor(
38+
private organisationService: OrganisationService,
39+
private deleteDialogService: DeleteDialogService,
40+
private errorMessageService: ErrorMessageService
41+
) {}
3542

3643
ngAfterViewInit() {
3744
// If the user changes the sort order, reset back to the first page.
@@ -72,6 +79,10 @@ export class OrganisationTabelComponent implements AfterViewInit {
7279
this.deleteDialogService.showSimpleDialog().subscribe(response => {
7380
if (response) {
7481
this.organisationService.delete(element.id).subscribe(response => {
82+
if (response instanceof HttpErrorResponse) {
83+
this.errorMessages = this.errorMessageService.handleErrorMessageWithFields(response).errorMessages;
84+
return;
85+
}
7586
if (response.ok) {
7687
this.refresh();
7788
}

src/app/admin/permission/permission-edit/permission-edit.component.html

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,10 @@
6969
[compareWith]="compare"
7070
#multiSelect
7171
>
72-
<app-mat-select-search [formControl]="userMultiFilterCtrl"></app-mat-select-search>
72+
<app-mat-select-search
73+
[initialValues]="this.permission.userIds"
74+
[formControl]="userMultiFilterCtrl"
75+
></app-mat-select-search>
7376
<mat-option *ngFor="let user of filteredUsersMulti | async" [value]="user.id">
7477
{{ getTextForUser(user) }}
7578
</mat-option>
@@ -102,25 +105,28 @@
102105
</div>
103106

104107
<div class="form-group mt-3 col-12" *ngIf="isOrganizationApplicationPermission()">
105-
<label class="form-label" for="name">{{ "PERMISSION.EDIT.APPS" | translate }}</label>
106-
<div class="col-12">
107-
<mat-select
108-
id="applicationIds"
109-
[formControl]="applicationMultiCtrl"
110-
[multiple]="true"
111-
class="form-control"
112-
panelClass="overflow-x-hidden"
113-
[(value)]="permission.applicationIds"
114-
name="applicationIds"
115-
#multiSelect
116-
[compareWith]="compare"
117-
>
118-
<app-mat-select-search [formControl]="applicationMultiFilterCtrl"></app-mat-select-search>
119-
<mat-option *ngFor="let app of filteredApplicationsMulti | async" [value]="app.id">
120-
{{ app.name }}
121-
</mat-option>
122-
</mat-select>
123-
</div>
108+
<label class="form-label" for="name">{{ "PERMISSION.EDIT.APPS" | translate }}</label>
109+
<div class="col-12">
110+
<mat-select
111+
id="applicationIds"
112+
[formControl]="applicationMultiCtrl"
113+
[multiple]="true"
114+
class="form-control"
115+
panelClass="overflow-x-hidden"
116+
[(value)]="permission.applicationIds"
117+
name="applicationIds"
118+
#multiSelect
119+
[compareWith]="compare"
120+
>
121+
<app-mat-select-search
122+
[initialValues]="this.permission.applicationIds"
123+
[formControl]="applicationMultiFilterCtrl"
124+
></app-mat-select-search>
125+
<mat-option *ngFor="let app of filteredApplicationsMulti | async" [value]="app.id">
126+
{{ app.name }}
127+
</mat-option>
128+
</mat-select>
129+
</div>
124130
</div>
125131

126132
<div *ngIf="isReadOrWrite()">

src/app/admin/permission/permission.service.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ export class PermissionService {
5353
orderByColumn?: string,
5454
orderByDirection?: string,
5555
userId?: number,
56-
organisationId?: number
56+
organisationId?: number,
57+
ignoreGlobalAdmin?: boolean
5758
): Observable<PermissionGetManyResponse> {
5859
if (userId || organisationId) {
5960
return this.restService.get(this.endpoint, {
@@ -63,6 +64,7 @@ export class PermissionService {
6364
sort: orderByDirection,
6465
userId: userId,
6566
organisationId: organisationId,
67+
ignoreGlobalAdmin: ignoreGlobalAdmin,
6668
});
6769
} else {
6870
return this.restService.get(this.endpoint, {
@@ -97,10 +99,20 @@ export class PermissionService {
9799
offset: offset,
98100
orderOn: orderByColumn,
99101
sort: orderByDirection,
102+
ignoreGlobalAdmin: ignoreGlobalAdmin,
100103
});
101104
}
102105
}
103106

107+
getPermissionsWithoutUsers(userId?: number): Observable<PermissionGetManyResponse> {
108+
return this.restService.get(this.endpoint + "/getAllPermissionsWithoutUsers", {
109+
limit: 1000,
110+
offset: 0,
111+
userId: userId ?? undefined,
112+
ignoreGlobalAdmin: true,
113+
});
114+
}
115+
104116
deletePermission(id: number) {
105117
return this.restService.delete(this.endpoint, id);
106118
}

src/app/admin/users/new-kombit-user-page/new-user.component.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ <h1>
5050
panelClass="overflow-x-hidden"
5151
aria-required="true"
5252
>
53-
<app-mat-select-search [formControl]="organisationsFilterCtrl"></app-mat-select-search>
53+
<app-mat-select-search
54+
[formControl]="organisationsFilterCtrl"
55+
></app-mat-select-search>
5456

5557
<mat-option *ngFor="let org of filteredOrganisations | async" [value]="org">{{ org.name }}</mat-option>
5658
</mat-select>

src/app/admin/users/user-edit/user-edit.component.html

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,25 @@
7777
/>
7878
</div>
7979
</div>
80+
81+
<div class="row mb-5">
82+
<div class="form-group mt-3 col-12">
83+
<label class="form-label" id="permissions" for="permissions">{{ "QUESTION.PERMISSION.SELECT-PERMISSION" | translate }}</label
84+
>*
85+
<mat-select
86+
class="form-control"
87+
name="permissions"
88+
[compareWith]="compare"
89+
[(ngModel)]="user.permissionIds"
90+
[multiple]="true"
91+
>
92+
<mat-option *ngFor="let permission of permissions" [value]="permission.id">
93+
{{ permission.name }}
94+
</mat-option>
95+
</mat-select>
96+
</div>
97+
</div>
98+
8099
<div class="row mb-5">
81100
<mat-slide-toggle [(ngModel)]="user.active" id="active" name="active">
82101
{{ "USERS.FORM.ACTIVE" | translate }}</mat-slide-toggle

src/app/admin/users/user-edit/user-edit.component.ts

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
import { HttpErrorResponse } from "@angular/common/http";
2-
import { Component, OnInit } from "@angular/core";
3-
import { UntypedFormGroup } from "@angular/forms";
2+
import { Component, OnDestroy, OnInit } from "@angular/core";
3+
import { UntypedFormControl, UntypedFormGroup } from "@angular/forms";
44
import { ActivatedRoute } from "@angular/router";
55
import { UserRequest } from "../user.model";
66
import { TranslateService } from "@ngx-translate/core";
77
import { UserService } from "../user.service";
8-
import { Subscription } from "rxjs";
8+
import { Subject, Subscription } from "rxjs";
99
import { Location } from "@angular/common";
10-
import { PermissionType } from "@app/admin/permission/permission.model";
11-
import { AuthService, CurrentUserInfoResponse } from "@auth/auth.service";
12-
import { SharedVariableService } from "@shared/shared-variable/shared-variable.service";
10+
import { PermissionResponse, PermissionType } from "@app/admin/permission/permission.model";
1311
import { MeService } from "@shared/services/me.service";
1412
import { OrganizationAccessScope } from "@shared/enums/access-scopes";
13+
import { PermissionService } from "@app/admin/permission/permission.service";
14+
import { SharedVariableService } from "@shared/shared-variable/shared-variable.service";
1515

1616
@Component({
1717
selector: "app-user-edit",
1818
templateUrl: "./user-edit.component.html",
1919
styleUrls: ["./user-edit.component.scss"],
2020
})
21-
export class UserEditComponent implements OnInit {
22-
user = new UserRequest();
21+
export class UserEditComponent implements OnInit, OnDestroy {
22+
public user = new UserRequest();
23+
public permissions: PermissionResponse[];
24+
public permissionsSubscription: Subscription;
2325
public errorMessage: string;
2426
public errorMessages: any;
2527
public errorFields: string[];
@@ -28,20 +30,22 @@ export class UserEditComponent implements OnInit {
2830
public backButtonTitle = "";
2931
public title = "";
3032
public submitButton = "";
31-
id: number;
32-
subscription: Subscription;
33-
isGlobalAdmin = false;
34-
isKombit: boolean;
35-
canEdit: boolean;
33+
public id: number;
34+
public subscription: Subscription;
35+
public isGlobalAdmin = false;
36+
public isKombit: boolean;
37+
public canEdit: boolean;
38+
public permissionMultiCtrl: UntypedFormControl = new UntypedFormControl();
39+
private _onDestroy = new Subject<void>();
3640

3741
constructor(
3842
private translate: TranslateService,
3943
private route: ActivatedRoute,
4044
private userService: UserService,
4145
private location: Location,
42-
private authService: AuthService,
43-
private sharedVariableService: SharedVariableService,
44-
private meService: MeService
46+
private meService: MeService,
47+
private permissionService: PermissionService,
48+
private sharedVariableService: SharedVariableService
4549
) {}
4650

4751
ngOnInit(): void {
@@ -60,6 +64,7 @@ export class UserEditComponent implements OnInit {
6064
}
6165
this.amIGlobalAdmin();
6266
this.canEdit = this.meService.hasAccessToTargetOrganization(OrganizationAccessScope.UserAdministrationWrite);
67+
this.getPermissions(this.sharedVariableService.getUserInfo().user.id);
6368
}
6469

6570
private getUser(id: number) {
@@ -70,6 +75,8 @@ export class UserEditComponent implements OnInit {
7075
this.user.active = response.active;
7176
this.user.globalAdmin = response.permissions.some(perm => perm.name === PermissionType.GlobalAdmin);
7277
this.isKombit = response.nameId != null;
78+
this.user.permissionIds = response.permissions.map(pm => pm.id);
79+
7380
// We cannot set the password.
7481
});
7582
}
@@ -80,8 +87,7 @@ export class UserEditComponent implements OnInit {
8087

8188
private create(): void {
8289
this.userService.post(this.user).subscribe(
83-
response => {
84-
console.log(response);
90+
() => {
8591
this.routeBack();
8692
},
8793
(error: HttpErrorResponse) => {
@@ -132,4 +138,28 @@ export class UserEditComponent implements OnInit {
132138
routeBack(): void {
133139
this.location.back();
134140
}
141+
142+
public compare(matOptionValue: number, ngModelObject: number): boolean {
143+
return matOptionValue === ngModelObject;
144+
}
145+
146+
private getPermissions(userId: number) {
147+
this.permissionsSubscription = this.permissionService
148+
.getPermissionsWithoutUsers(this.meService.hasGlobalAdmin() ? undefined : userId)
149+
.subscribe(res => {
150+
this.permissions = res.data.sort((a, b) => a.name.localeCompare(b.name, "da-DK", { numeric: true }));
151+
if (!this.id) {
152+
this.permissionMultiCtrl.setValue(this.user.permissionIds);
153+
}
154+
});
155+
}
156+
157+
ngOnDestroy() {
158+
// prevent memory leak by unsubscribing
159+
if (this.permissionsSubscription) {
160+
this.permissionsSubscription.unsubscribe();
161+
}
162+
this._onDestroy.next();
163+
this._onDestroy.complete();
164+
}
135165
}

0 commit comments

Comments
 (0)