Skip to content

Commit 77c8644

Browse files
authored
fix: #873 admin role bug (#874)
1 parent 7bb376e commit 77c8644

File tree

6 files changed

+40
-13
lines changed

6 files changed

+40
-13
lines changed

admin/src/app/header/header.component.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
<header class="app-header app-header--solid" id="header">
22
<nav class="navbar navbar-expand-md justify-content-between">
3-
<a class="navbar-brand" title="Forest Operations Map - FOM" routerLink="/home">
3+
<a class="navbar-brand"
4+
title="Forest Operations Map - FOM"
5+
[routerLink]="!isAdminRoleOnly() ? '/home' : null"
6+
[style.pointerEvents]="!isAdminRoleOnly() ? 'auto' : 'none'"
7+
[attr.tabindex]="!isAdminRoleOnly() ? 0 : -1">
48
<span class="navbar-brand__title">
59
Forest Operations Map - Admin
610
</span>

admin/src/app/header/header.component.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,25 @@ export class HeaderComponent implements OnInit {
3535
this.user = this.cognitoService.getUser();
3636
}
3737

38+
isAdminRoleOnly(): boolean {
39+
return this.user && this.user.isAdmin && !this.user.isMinistry && !this.user.isForestClient;
40+
}
41+
3842
ngOnInit() {
43+
// user is not authorized.
3944
if (!this.user || !this.user.isAuthorizedForAdminSite()) {
4045
// If on not-authorized page, or if just logged out, don't redirect to not-authorized page as would cause an infinite loop.
4146
if (window.location.href.indexOf('/not-authorized') == -1 && window.location.href.indexOf("loggedout=true") == -1) {
4247
this.router.navigate(['/not-authorized']);
4348
}
4449
}
50+
51+
// user has admin role only
52+
if (this.user && this.isAdminRoleOnly()) {
53+
this.router.navigate(['/analytics-dashboard']);
54+
return;
55+
}
56+
4557
}
4658

4759
async navigateToLogout() {

admin/src/core/services/mock-user.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import { User } from "@utility/security/user";
22

33
export function getFakeUser():User {
4-
const userType:string = 'AllAccess'; // NoAccess, ForestClient, Ministry, AllAccess
4+
const userType:string = 'AllAccess'; // NoAccess, ForestClient, Ministry, AdminOnly, AllAccess
55
switch (userType) {
66
case 'NoAccess':
77
return getFakeNoAccessUser();
88
case 'ForestClient':
99
return getFakeForestClientUser();
1010
case 'Ministry':
1111
return getFakeMinistryUser();
12+
case 'AdminOnly':
13+
return getFakeAdminOnlyUser();
1214
case 'AllAccess':
1315
return getFakeAllAccessUser();
1416
default:
@@ -57,3 +59,13 @@ export function getFakeAllAccessUser(): User {
5759
user.clientIds.push('00132188');
5860
return user;
5961
}
62+
63+
export function getFakeAdminOnlyUser(): User {
64+
const user = new User();
65+
user.userName = 'fakeAdminOnlyUser';
66+
user.displayName = 'Admin Only User';
67+
user.isAdmin = true;
68+
user.isMinistry = false;
69+
user.isForestClient = false;
70+
return user;
71+
}

api/src/core/security/admin.guard.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@ describe('AdminOperationGuard', () => {
88

99
beforeEach(() => {
1010
guard = new AdminOperationGuard();
11-
mockRequest = { headers: { user: { isAuthorizedForAdminOperation: jest.fn() } } };
11+
mockRequest = { headers: { user: { isAdmin: false } } };
1212
mockContext = {
1313
switchToHttp: () => ({ getRequest: () => mockRequest })
1414
} as Partial<ExecutionContext>;
1515
});
1616

1717
it('should allow access if user is authorized', () => {
18-
mockRequest.headers.user.isAuthorizedForAdminOperation.mockReturnValue(true);
18+
mockRequest.headers.user.isAdmin = true;
1919
expect(guard.canActivate(mockContext as ExecutionContext)).toBe(true);
2020
});
2121

2222
it('should throw ForbiddenException if user is not authorized', () => {
23-
mockRequest.headers.user.isAuthorizedForAdminOperation.mockReturnValue(false);
23+
mockRequest.headers.user.isAdmin = false;
2424
expect(() => guard.canActivate(mockContext as ExecutionContext)).toThrow(ForbiddenException);
2525
});
2626

@@ -29,7 +29,7 @@ describe('AdminOperationGuard', () => {
2929
expect(() => guard.canActivate(mockContext as ExecutionContext)).toThrow(ForbiddenException);
3030
});
3131

32-
it('should throw ForbiddenException if user object cannot determine isAuthorizedForAdminOperation', () => {
32+
it('should throw ForbiddenException if user object is missing isAdmin', () => {
3333
mockRequest.headers.user = {};
3434
expect(() => guard.canActivate(mockContext as ExecutionContext)).toThrow(ForbiddenException);
3535
});

api/src/core/security/admin.guard.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ import {
44
Injectable,
55
ForbiddenException,
66
} from '@nestjs/common';
7+
import { User } from '@utility/security/user';
78

89
@Injectable()
910
export class AdminOperationGuard implements CanActivate {
1011
canActivate(context: ExecutionContext): boolean {
1112
const request = context.switchToHttp().getRequest();
12-
const user = request.headers['user'];
13+
const user: User = request.headers['user'];
1314

14-
if (!user?.isAuthorizedForAdminOperation?.()) {
15+
if (!user?.isAdmin) {
1516
throw new ForbiddenException();
1617
}
1718
return true;

libs/utility/src/security/user.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,11 @@ export class User {
66
isForestClient: boolean = false;
77
isAdmin: boolean = false;
88
clientIds: string[] = [];
9-
10-
isAuthorizedForAdminOperation():boolean {
11-
return this.isAdmin;
12-
}
139

1410
isAuthorizedForAdminSite():boolean {
15-
return this.isMinistry || this.isForestClient;
11+
// A user is authorized for FOM admin site if it has any of the roles (ministry, forest client, or admin).
12+
// However, curently for admin role the user can only access Analytics Dashboard.
13+
return this.isMinistry || this.isForestClient || this.isAdmin;
1614
}
1715

1816
isAuthorizedForClientId(clientId:string):boolean {

0 commit comments

Comments
 (0)