-
Notifications
You must be signed in to change notification settings - Fork 319
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9291 from truenas/NAS-125497
NAS-125497 / 24.04 / Fix what happens when trying to use user with reduced privileges
- Loading branch information
Showing
124 changed files
with
739 additions
and
706 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 20 additions & 55 deletions
75
src/app/directives/common/has-roles/has-roles.directive.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,88 +1,53 @@ | ||
import { createHostFactory, mockProvider, Spectator } from '@ngneat/spectator/jest'; | ||
import { BehaviorSubject } from 'rxjs'; | ||
import { Role } from 'app/enums/role.enum'; | ||
import { LoggedInUser } from 'app/interfaces/ds-cache.interface'; | ||
import { AuthService } from 'app/services/auth/auth.service'; | ||
import { HasRolesDirective } from './has-roles.directive'; | ||
|
||
describe('HasRolesDirective', () => { | ||
let spectator: Spectator<HasRolesDirective>; | ||
const currentUser$ = new BehaviorSubject<LoggedInUser>(null); | ||
|
||
const createHost = createHostFactory({ | ||
component: HasRolesDirective, | ||
providers: [ | ||
mockProvider(AuthService, { | ||
user$: currentUser$, | ||
}), | ||
mockProvider(AuthService), | ||
], | ||
}); | ||
|
||
it('does not show an element when there is no logged in user', () => { | ||
it('does not show an element when user doe not have correct roles', () => { | ||
spectator = createHost( | ||
'<div *ixHasRoles="[Role.Readonly]">Content</div>', | ||
{ | ||
hostProps: { Role }, | ||
providers: [ | ||
mockProvider(AuthService, { | ||
hasRole: jest.fn(() => false), | ||
}), | ||
], | ||
}, | ||
); | ||
|
||
expect(spectator.query('div')).not.toExist(); | ||
}); | ||
|
||
it('shows an element when user has a FullAdmin role regardless of roles on the element', () => { | ||
currentUser$.next({ | ||
privilege: { | ||
roles: { | ||
$set: [Role.FullAdmin], | ||
}, | ||
}, | ||
} as LoggedInUser); | ||
|
||
spectator = createHost( | ||
'<div *ixHasRoles="[Role.DatasetWrite]">Content</div>', | ||
{ | ||
hostProps: { Role }, | ||
}, | ||
); | ||
const authService = spectator.inject(AuthService); | ||
|
||
expect(spectator.query('div')).toHaveText('Content'); | ||
expect(authService.hasRole).toHaveBeenCalledWith([Role.Readonly]); | ||
expect(spectator.query('div')).not.toExist(); | ||
}); | ||
|
||
it('shows an element when one of the user`s roles matches one of the roles required on the element', () => { | ||
currentUser$.next({ | ||
privilege: { | ||
roles: { | ||
$set: [Role.DatasetRead, Role.DatasetWrite], | ||
}, | ||
}, | ||
} as LoggedInUser); | ||
|
||
it('shows an element when user has correct roles', () => { | ||
spectator = createHost( | ||
'<div *ixHasRoles="[Role.DatasetRead, Role.Readonly]">Content</div>', | ||
'<div *ixHasRoles="[Role.NetworkInterfaceWrite]">Content</div>', | ||
{ | ||
hostProps: { Role }, | ||
providers: [ | ||
mockProvider(AuthService, { | ||
hasRole: jest.fn(() => true), | ||
}), | ||
], | ||
}, | ||
); | ||
|
||
expect(spectator.query('div')).toHaveText('Content'); | ||
}); | ||
|
||
it('does not show an element when none of the user`s roles matches any of the roles required on the element', () => { | ||
currentUser$.next({ | ||
privilege: { | ||
roles: { | ||
$set: [Role.DatasetRead, Role.DatasetWrite], | ||
}, | ||
}, | ||
} as LoggedInUser); | ||
|
||
spectator = createHost( | ||
'<div *ixHasRoles="[Role.Readonly]">Content</div>', | ||
{ | ||
hostProps: { Role }, | ||
}, | ||
); | ||
const authService = spectator.inject(AuthService); | ||
|
||
expect(spectator.query('div')).not.toExist(); | ||
expect(authService.hasRole).toHaveBeenCalledWith([Role.NetworkInterfaceWrite]); | ||
expect(spectator.query('div')).toExist(); | ||
}); | ||
}); |
27 changes: 3 additions & 24 deletions
27
src/app/directives/common/has-roles/has-roles.directive.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,45 +1,24 @@ | ||
import { | ||
ChangeDetectorRef, | ||
Directive, Input, TemplateRef, ViewContainerRef, | ||
} from '@angular/core'; | ||
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; | ||
import { UntilDestroy } from '@ngneat/until-destroy'; | ||
import { Role } from 'app/enums/role.enum'; | ||
import { AuthService } from 'app/services/auth/auth.service'; | ||
|
||
@UntilDestroy() | ||
@Directive({ selector: '[ixHasRoles]' }) | ||
export class HasRolesDirective { | ||
private currentUserRoles: Role[] = []; | ||
|
||
@Input() set ixHasRoles(roles: Role[]) { | ||
this.viewContainer.clear(); | ||
|
||
if (this.checkRoles(roles)) { | ||
if (this.authService.hasRole(roles)) { | ||
this.viewContainer.createEmbeddedView(this.templateRef); | ||
} | ||
} | ||
|
||
constructor( | ||
private templateRef: TemplateRef<unknown>, | ||
private viewContainer: ViewContainerRef, | ||
private cdr: ChangeDetectorRef, | ||
private authService: AuthService, | ||
) { | ||
this.authService.user$.pipe(untilDestroyed(this)).subscribe((user) => { | ||
this.currentUserRoles = user?.privilege?.roles?.$set || []; | ||
this.cdr.markForCheck(); | ||
}); | ||
} | ||
|
||
private checkRoles(roles: Role[]): boolean { | ||
if (!roles?.length || !this.currentUserRoles?.length) { | ||
return false; | ||
} | ||
|
||
if (this.currentUserRoles.includes(Role.FullAdmin)) { | ||
return true; | ||
} | ||
|
||
return roles.some((role) => this.currentUserRoles.includes(role)); | ||
} | ||
) {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { marker as T } from '@biesbjerg/ngx-translate-extract-marker'; | ||
|
||
export default { | ||
minimalRolesTooltip: T('Only Readonly, Sharing Manager or Full Admin roles are supported in WebUI.'), | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,4 +23,5 @@ export interface PrivilegeRole { | |
name: Role; | ||
title: string; | ||
includes: Role[]; | ||
builtin: boolean; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.