Merge pull request #1454 from atmire/w2p-85979_canChangePassword-ui-change

Disallow Shibboleth users to change password
This commit is contained in:
Tim Donohue
2022-01-04 10:09:04 -06:00
committed by GitHub
4 changed files with 50 additions and 5 deletions

View File

@@ -13,6 +13,7 @@ export enum FeatureID {
CanManageGroup = 'canManageGroup', CanManageGroup = 'canManageGroup',
IsCollectionAdmin = 'isCollectionAdmin', IsCollectionAdmin = 'isCollectionAdmin',
IsCommunityAdmin = 'isCommunityAdmin', IsCommunityAdmin = 'isCommunityAdmin',
CanChangePassword = 'canChangePassword',
CanDownload = 'canDownload', CanDownload = 'canDownload',
CanRequestACopy = 'canRequestACopy', CanRequestACopy = 'canRequestACopy',
CanManageVersions = 'canManageVersions', CanManageVersions = 'canManageVersions',

View File

@@ -7,7 +7,7 @@
<ds-profile-page-metadata-form [user]="user"></ds-profile-page-metadata-form> <ds-profile-page-metadata-form [user]="user"></ds-profile-page-metadata-form>
</div> </div>
</div> </div>
<div class="card mb-4"> <div *ngIf="canChangePassword$ | async" class="card mb-4 security-section">
<div class="card-header">{{'profile.card.security' | translate}}</div> <div class="card-header">{{'profile.card.security' | translate}}</div>
<div class="card-body"> <div class="card-body">
<ds-profile-page-security-form <ds-profile-page-security-form

View File

@@ -13,10 +13,13 @@ import { NotificationsService } from '../shared/notifications/notifications.serv
import { authReducer } from '../core/auth/auth.reducer'; import { authReducer } from '../core/auth/auth.reducer';
import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils'; import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils';
import { createPaginatedList } from '../shared/testing/utils.test'; import { createPaginatedList } from '../shared/testing/utils.test';
import { of as observableOf } from 'rxjs'; import { BehaviorSubject, of as observableOf } from 'rxjs';
import { AuthService } from '../core/auth/auth.service'; import { AuthService } from '../core/auth/auth.service';
import { RestResponse } from '../core/cache/response.models'; import { RestResponse } from '../core/cache/response.models';
import { provideMockStore } from '@ngrx/store/testing'; import { provideMockStore } from '@ngrx/store/testing';
import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service';
import { getTestScheduler } from 'jasmine-marbles';
import { By } from '@angular/platform-browser';
describe('ProfilePageComponent', () => { describe('ProfilePageComponent', () => {
let component: ProfilePageComponent; let component: ProfilePageComponent;
@@ -28,10 +31,13 @@ describe('ProfilePageComponent', () => {
let epersonService; let epersonService;
let notificationsService; let notificationsService;
const canChangePassword = new BehaviorSubject(true);
function init() { function init() {
user = Object.assign(new EPerson(), { user = Object.assign(new EPerson(), {
id: 'userId', id: 'userId',
groups: createSuccessfulRemoteDataObject$(createPaginatedList([])) groups: createSuccessfulRemoteDataObject$(createPaginatedList([])),
_links: {self: {href: 'test.com/uuid/1234567654321'}}
}); });
initialState = { initialState = {
core: { core: {
@@ -74,6 +80,7 @@ describe('ProfilePageComponent', () => {
{ provide: EPersonDataService, useValue: epersonService }, { provide: EPersonDataService, useValue: epersonService },
{ provide: NotificationsService, useValue: notificationsService }, { provide: NotificationsService, useValue: notificationsService },
{ provide: AuthService, useValue: authService }, { provide: AuthService, useValue: authService },
{ provide: AuthorizationDataService, useValue: jasmine.createSpyObj('authorizationService', { isAuthorized: canChangePassword }) },
provideMockStore({ initialState }), provideMockStore({ initialState }),
], ],
schemas: [NO_ERRORS_SCHEMA] schemas: [NO_ERRORS_SCHEMA]
@@ -183,7 +190,7 @@ describe('ProfilePageComponent', () => {
component.setPasswordValue('testest'); component.setPasswordValue('testest');
component.setInvalid(false); component.setInvalid(false);
operations = [{op: 'add', path: '/password', value: 'testest'}]; operations = [{ op: 'add', path: '/password', value: 'testest' }];
result = component.updateSecurity(); result = component.updateSecurity();
}); });
@@ -196,4 +203,36 @@ describe('ProfilePageComponent', () => {
}); });
}); });
}); });
describe('canChangePassword$', () => {
describe('when the user is allowed to change their password', () => {
beforeEach(() => {
canChangePassword.next(true);
});
it('should contain true', () => {
getTestScheduler().expectObservable(component.canChangePassword$).toBe('(a)', { a: true });
});
it('should show the security section on the page', () => {
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('.security-section'))).not.toBeNull();
});
});
describe('when the user is not allowed to change their password', () => {
beforeEach(() => {
canChangePassword.next(false);
});
it('should contain false', () => {
getTestScheduler().expectObservable(component.canChangePassword$).toBe('(a)', { a: false });
});
it('should not show the security section on the page', () => {
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('.security-section'))).toBeNull();
});
});
});
}); });

View File

@@ -18,6 +18,8 @@ import { hasValue, isNotEmpty } from '../shared/empty.util';
import { followLink } from '../shared/utils/follow-link-config.model'; import { followLink } from '../shared/utils/follow-link-config.model';
import { AuthService } from '../core/auth/auth.service'; import { AuthService } from '../core/auth/auth.service';
import { Operation } from 'fast-json-patch'; import { Operation } from 'fast-json-patch';
import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service';
import { FeatureID } from '../core/data/feature-authorization/feature-id';
@Component({ @Component({
selector: 'ds-profile-page', selector: 'ds-profile-page',
@@ -67,11 +69,13 @@ export class ProfilePageComponent implements OnInit {
* The authenticated user * The authenticated user
*/ */
private currentUser: EPerson; private currentUser: EPerson;
canChangePassword$: Observable<boolean>;
constructor(private authService: AuthService, constructor(private authService: AuthService,
private notificationsService: NotificationsService, private notificationsService: NotificationsService,
private translate: TranslateService, private translate: TranslateService,
private epersonService: EPersonDataService) { private epersonService: EPersonDataService,
private authorizationService: AuthorizationDataService) {
} }
ngOnInit(): void { ngOnInit(): void {
@@ -83,6 +87,7 @@ export class ProfilePageComponent implements OnInit {
tap((user: EPerson) => this.currentUser = user) tap((user: EPerson) => this.currentUser = user)
); );
this.groupsRD$ = this.user$.pipe(switchMap((user: EPerson) => user.groups)); this.groupsRD$ = this.user$.pipe(switchMap((user: EPerson) => user.groups));
this.canChangePassword$ = this.user$.pipe(switchMap((user: EPerson) => this.authorizationService.isAuthorized(FeatureID.CanChangePassword, user._links.self.href)));
} }
/** /**