Skip to content

Commit 7044b13

Browse files
augusthjerrildAugustHA-Iteratornlg
authored
Feature/iot 1249 manage kombit users (#82)
* First changes to management of kombit users. * i18n translations * Made the form page for entering email and wanted organizations. Redirect to new page when entering and succes. Not possible to enter awaiting-page or new-user page manually by url * NewKombitUser page done, ready for user information page * User page. Need to fix console error "undefined length" * Changed name so it's more clear that it's requestedOrganizations and not actual organizations. Started on moving userpage link and login to top right corner. * moved help and log out buttons to top right corner * Next step is to fit padding in top bar. Styling. * Css styling * removing if statement. Top bar should visible when first time entering from kombit * Sending an array of ids instead of org object. OBS on undefined on find. * fixed undefined on find. Changed some variable names. Removed search bar and user-page when first time login from kombit, but possible to log out. * Made admin/users so there is two tables. One for existing users and one for users applying. Next step is to make the approve and reject buttons and functionality. * Made acceptuser page when some user is requesting access to organization. * Can only press once. Also changed back so new-user back is only called when a user from kombit is logged in and has no email. This specific flow has not been tested since it's not possible to create a test kombit user locally. * Changed some endpoints so page is allowed * Changed RejectUserDto to have all the info about the rejected user Minor code improvements * Minor code style improvements Co-authored-by: August Andersen <aha@iterator-it.dk> Co-authored-by: nlg <nlg@iterator-it.dk>
1 parent db693a4 commit 7044b13

37 files changed

+1592
-186
lines changed

src/app/admin/admin-routing.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { UsersComponent } from './users/users.component';
1515
import { ApiKeyComponent } from './api-key/api-key.component';
1616
import { ApiKeyListComponent } from './api-key/api-key-list/api-key-list.component';
1717
import { ApiKeyEditComponent } from './api-key/api-key-edit/api-key-edit.component';
18+
import { AcceptUserComponent } from './users/accept-user/accept-user.component';
1819

1920

2021
const adminRoutes: Routes = [
@@ -32,6 +33,7 @@ const adminRoutes: Routes = [
3233
{ path: 'new-user', component: UserEditComponent },
3334
{ path: ':user-id', component: UserDetailComponent },
3435
{ path: ':user-id/edit-user', component: UserEditComponent },
36+
{ path: 'accept-user/:user-id/:org-id', component: AcceptUserComponent }
3537
]
3638
},
3739
{

src/app/admin/admin.module.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ import { ApiKeyComponent } from './api-key/api-key.component';
3232
import { ApiKeyListComponent } from './api-key/api-key-list/api-key-list.component';
3333
import { ApiKeyTableComponent } from './api-key/api-key-list/api-key-table/api-key-table.component';
3434
import { ApiKeyEditComponent } from './api-key/api-key-edit/api-key-edit.component';
35+
import { AwaitingUsersTableComponent } from './users/user-list/awaiting-users-table/awaiting-users-table.component';
36+
import { AcceptUserComponent } from './users/accept-user/accept-user.component';
3537

3638
@NgModule({
3739
declarations: [
@@ -54,6 +56,8 @@ import { ApiKeyEditComponent } from './api-key/api-key-edit/api-key-edit.compone
5456
ApiKeyListComponent,
5557
ApiKeyTableComponent,
5658
ApiKeyEditComponent,
59+
AwaitingUsersTableComponent,
60+
AcceptUserComponent,
5761
],
5862
imports: [
5963
AdminRoutingModule,

src/app/admin/organisation/organisation.service.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,20 @@ import {
99
} from './organisation.model';
1010
import { map, shareReplay } from 'rxjs/operators';
1111
import { UserMinimalService } from '../users/user-minimal.service';
12+
import { UpdateUserOrgsDto } from '../users/user.model';
1213

1314
@Injectable({
1415
providedIn: 'root',
1516
})
1617
export class OrganisationService {
1718
URL = 'organization';
1819
URLMINIMAL = 'organization/minimal';
20+
URLMINIMAL_NEWKOMBIT = 'kombitCreation/minimal';
1921

2022
constructor(
2123
private restService: RestService,
22-
private userMinimalService: UserMinimalService) { }
24+
private userMinimalService: UserMinimalService
25+
) {}
2326

2427
post(body: Organisation): Observable<OrganisationResponse> {
2528
return this.restService.post(this.URL, body);
@@ -32,27 +35,32 @@ export class OrganisationService {
3235
}
3336

3437
getOne(id: number): Observable<OrganisationResponse> {
35-
return this.restService.get(this.URL, {}, id)
36-
.pipe(
37-
map(
38-
(response: OrganisationResponse) => {
39-
response.createdByName = this.userMinimalService.getUserNameFrom(response.createdBy);
40-
response.updatedByName = this.userMinimalService.getUserNameFrom(response.updatedBy);
41-
return response;
42-
}
43-
)
44-
);
38+
return this.restService.get(this.URL, {}, id).pipe(
39+
map((response: OrganisationResponse) => {
40+
response.createdByName = this.userMinimalService.getUserNameFrom(
41+
response.createdBy
42+
);
43+
response.updatedByName = this.userMinimalService.getUserNameFrom(
44+
response.updatedBy
45+
);
46+
return response;
47+
})
48+
);
4549
}
4650

4751
getMinimal(): Observable<OrganisationGetMinimalResponse> {
4852
return this.restService.get(this.URLMINIMAL, {}).pipe(shareReplay(1));
4953
}
5054

55+
getMinimalNoPerm(): Observable<OrganisationGetMinimalResponse> {
56+
return this.restService.get(this.URLMINIMAL_NEWKOMBIT, {}).pipe(shareReplay(1));
57+
}
58+
5159
getMultiple(
5260
limit: number = 1000,
5361
offset: number = 0,
5462
orderByColumn?: string,
55-
orderByDirection?: string,
63+
orderByDirection?: string
5664
): Observable<OrganisationGetManyResponse> {
5765
return this.restService.get(this.URL, {
5866
limit,

src/app/admin/permission/permission.model.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ export class PermissionRequest {
1111
automaticallyAddNewApplications = true;
1212
}
1313

14+
export class PermissionRequestAcceptUser {
15+
organizationId: number;
16+
userId: number;
17+
level: PermissionType;
18+
}
19+
1420
export interface PermissionResponse {
1521
type: PermissionType;
1622
name: string;

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
PermissionGetManyResponse,
66
PermissionResponse,
77
PermissionRequest,
8+
PermissionRequestAcceptUser,
89
} from './permission.model';
910
import { map } from 'rxjs/operators';
1011
import { UserMinimalService } from '../users/user-minimal.service';
@@ -25,6 +26,12 @@ export class PermissionService {
2526
});
2627
}
2728

29+
createPermissionAcceptUser(body: PermissionRequestAcceptUser): Observable<PermissionResponse> {
30+
return this.restService.put(this.endpoint + '/acceptUser', body, undefined, {
31+
observe: 'response',
32+
});
33+
}
34+
2835
updatePermission(
2936
body: PermissionRequest,
3037
id: number
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<div *ngIf="user">
2+
<app-top-bar
3+
[backButtonTitle]="backButtonTitle"
4+
[title]="title"
5+
></app-top-bar>
6+
7+
<form (ngSubmit)="onSubmit()" class="os2-form p-3 mt-4">
8+
<div *ngIf="errorMessages" class="error-messages p-3">
9+
<ul class="mb-0">
10+
<li *ngFor="let error of errorMessages">
11+
{{ error | translate }}
12+
</li>
13+
</ul>
14+
</div>
15+
<div class="container-fluid">
16+
<div class="row">
17+
<div class="col-12">
18+
<div class="jumbotron">
19+
<h3>
20+
{{ 'USERS.ACCEPT-USER.QUESTION-ACCEPT' | translate }}
21+
{{ user.name }}
22+
</h3>
23+
<mat-divider></mat-divider>
24+
25+
<div class="form-group mt-3 col-12">
26+
<label class="form-label" for="level">{{
27+
'PERMISSION.EDIT.TYPE' | translate
28+
}}</label
29+
>*
30+
<select
31+
id="level"
32+
class="form-select"
33+
name="level"
34+
[(ngModel)]="permission.level"
35+
required
36+
[ngClass]="{
37+
'is-invalid':
38+
formFailedSubmit && errorFields.includes('organizationId'),
39+
'is-valid':
40+
formFailedSubmit && !errorFields.includes('organizationId')
41+
}"
42+
placeholder="'PERMISSION.EDIT.TYPE-PLACEHOLDER' | translate"
43+
>
44+
<option
45+
*ngFor="let level of allowedLevels()"
46+
[value]="level"
47+
[selected]="level === permission.level"
48+
>
49+
{{ level }}</option
50+
>
51+
</select>
52+
</div>
53+
<div class="form-group mt-5">
54+
<button
55+
(click)="routeBack()"
56+
class="btn btn-secondary"
57+
type="button"
58+
>
59+
{{ 'GEN.CANCEL' | translate }}
60+
</button>
61+
<button class="btn btn-primary ml-2" type="submit">
62+
{{ 'USERS.ACCEPT-USER.ACCEPT' | translate }}
63+
</button>
64+
</div>
65+
</div>
66+
</div>
67+
</div>
68+
</div>
69+
</form>
70+
</div>

src/app/admin/users/accept-user/accept-user.component.scss

Whitespace-only changes.
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { HttpErrorResponse } from '@angular/common/http';
2+
import { Component, OnInit } from '@angular/core';
3+
import { ActivatedRoute, Router } from '@angular/router';
4+
import {
5+
PermissionRequestAcceptUser,
6+
PermissionType,
7+
} from '@app/admin/permission/permission.model';
8+
import { TranslateService } from '@ngx-translate/core';
9+
import { ErrorMessageService } from '@shared/error-message.service';
10+
import { Subscription } from 'rxjs';
11+
import { UserResponse } from '../user.model';
12+
import { UserService } from '../user.service';
13+
import { Location } from '@angular/common';
14+
import { PermissionService } from '@app/admin/permission/permission.service';
15+
16+
@Component({
17+
selector: 'app-accept-user',
18+
templateUrl: './accept-user.component.html',
19+
styleUrls: ['./accept-user.component.scss'],
20+
})
21+
export class AcceptUserComponent implements OnInit {
22+
public backButtonTitle: string;
23+
permission = new PermissionRequestAcceptUser();
24+
public title: string;
25+
userId: number;
26+
subscription: Subscription;
27+
user: UserResponse;
28+
errorFields: string[];
29+
organizationId: number;
30+
public formFailedSubmit = false;
31+
errorMessages: any;
32+
33+
constructor(
34+
private userService: UserService,
35+
private location: Location,
36+
private translate: TranslateService,
37+
private route: ActivatedRoute,
38+
private errorMessageService: ErrorMessageService,
39+
private permissionService: PermissionService
40+
) {}
41+
42+
ngOnInit(): void {
43+
this.userId = +this.route.snapshot.paramMap.get('user-id');
44+
this.organizationId = +this.route.snapshot.paramMap.get('org-id');
45+
if (this.userId) {
46+
this.getUser(this.userId);
47+
}
48+
49+
this.translate
50+
.get(['GEN.BACK', 'USERS.ACCEPT-USER.ACCEPT'])
51+
.subscribe((translations) => {
52+
this.backButtonTitle = translations['GEN.BACK'];
53+
this.title = translations['USERS.ACCEPT-USER.ACCEPT'];
54+
});
55+
this.permission.userId = this.userId;
56+
this.permission.organizationId = this.organizationId;
57+
}
58+
59+
private getUser(id: number) {
60+
this.subscription = this.userService
61+
.getOne(id, false)
62+
.subscribe((response) => {
63+
this.user = response;
64+
});
65+
}
66+
67+
allowedLevels() {
68+
return [
69+
PermissionType.OrganizationAdmin,
70+
PermissionType.Write,
71+
PermissionType.Read,
72+
];
73+
}
74+
75+
private showError(err: HttpErrorResponse) {
76+
const result = this.errorMessageService.handleErrorMessageWithFields(err);
77+
this.errorFields = result.errorFields;
78+
this.errorMessages = result.errorMessages;
79+
}
80+
81+
routeBack(): void {
82+
this.location.back();
83+
}
84+
85+
onSubmit(): void {
86+
this.permissionService
87+
.createPermissionAcceptUser(this.permission)
88+
.subscribe(
89+
() => {
90+
this.routeBack();
91+
},
92+
(error: HttpErrorResponse) => {
93+
console.log(error);
94+
this.showError(error);
95+
}
96+
);
97+
}
98+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<app-top-bar></app-top-bar>
2+
3+
<div class="container-fluid">
4+
<div class="row">
5+
<div class="col-12">
6+
<div class="jumbotron">
7+
<h1>
8+
{{ 'NEW_USER.FIRST_LOGIN' | translate }}
9+
</h1>
10+
<form (ngSubmit)="onSubmit()" #newUserForm="ngForm" class="p-3 mt-4">
11+
<div *ngIf="errorMessages" class="error-messages p-3">
12+
<ul class="mb-0">
13+
<li *ngFor="let error of errorMessages">
14+
{{ error | translate }}
15+
</li>
16+
</ul>
17+
</div>
18+
<div class="row">
19+
<div class="form-group mt-3">
20+
<label class="form-label" for="createNewKombitUserDto.email">{{
21+
'USERS.EMAIL' | translate
22+
}}</label
23+
>*
24+
25+
<input
26+
type="email"
27+
class="form-control"
28+
id="email"
29+
maxlength="50"
30+
required
31+
name="email"
32+
[(ngModel)]="createNewKombitUserFromFrontend.email"
33+
[ngClass]="{
34+
'is-invalid':
35+
formFailedSubmit && errorFields.includes('email'),
36+
'is-valid': formFailedSubmit && !errorFields.includes('email')
37+
}"
38+
/>
39+
</div>
40+
41+
<div class="form-group mt-3 col-12">
42+
<label class="form-label" for="groupType">{{
43+
'NAV.ORGANISATIONS' | translate
44+
}}</label
45+
>*
46+
<mat-form-field appearance="outline">
47+
<mat-label>{{ 'NAV.ORGANISATIONS' | translate }}</mat-label>
48+
<mat-select
49+
multiple
50+
name="organisations"
51+
[compareWith]="compare"
52+
[(ngModel)]="
53+
createNewKombitUserFromFrontend.requestedOrganizations
54+
"
55+
panelClass="overflow-x-hidden"
56+
aria-required="true"
57+
>
58+
<mat-select-search
59+
[formControl]="organisationsFilterCtrl"
60+
></mat-select-search>
61+
62+
<mat-option
63+
*ngFor="let org of filteredOrganisations | async"
64+
[value]="org"
65+
>{{ org.name }}</mat-option
66+
>
67+
</mat-select>
68+
</mat-form-field>
69+
</div>
70+
</div>
71+
<div class="form-group mt-3">
72+
<button class="btn btn-primary ml-2" type="submit">
73+
{{ 'USERS.SAVE' | translate }}
74+
</button>
75+
</div>
76+
</form>
77+
</div>
78+
</div>
79+
</div>
80+
</div>

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

Whitespace-only changes.

0 commit comments

Comments
 (0)