71429: Feedback 2020-06-23

This commit is contained in:
Kristof De Langhe
2020-06-24 13:05:58 +02:00
parent 72381f4083
commit 0cef62ff48
10 changed files with 185 additions and 168 deletions

View File

@@ -24,7 +24,7 @@ import { NotificationsService } from '../../../../shared/notifications/notificat
import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model';
import { AuthService } from '../../../../core/auth/auth.service'; import { AuthService } from '../../../../core/auth/auth.service';
import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service'; import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service';
import { FeatureType } from '../../../../core/data/feature-authorization/feature-type'; import { FeatureID } from '../../../../core/data/feature-authorization/feature-id';
@Component({ @Component({
selector: 'ds-eperson-form', selector: 'ds-eperson-form',
@@ -245,7 +245,7 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
}); });
})); }));
this.canImpersonate$ = this.epersonService.getActiveEPerson().pipe( this.canImpersonate$ = this.epersonService.getActiveEPerson().pipe(
switchMap((eperson) => this.authorizationService.isAuthenticated(FeatureType.LoginOnBehalfOf, hasValue(eperson) ? eperson.self : undefined)) switchMap((eperson) => this.authorizationService.isAuthenticated(FeatureID.LoginOnBehalfOf, hasValue(eperson) ? eperson.self : undefined))
); );
}); });
} }

View File

@@ -19,7 +19,7 @@ import { MenuComponent } from '../../shared/menu/menu.component';
import { MenuService } from '../../shared/menu/menu.service'; import { MenuService } from '../../shared/menu/menu.service';
import { CSSVariableService } from '../../shared/sass-helper/sass-helper.service'; import { CSSVariableService } from '../../shared/sass-helper/sass-helper.service';
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
import { FeatureType } from '../../core/data/feature-authorization/feature-type'; import { FeatureID } from '../../core/data/feature-authorization/feature-id';
/** /**
* Component representing the admin sidebar * Component representing the admin sidebar
@@ -73,32 +73,31 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit {
* Set and calculate all initial values of the instance variables * Set and calculate all initial values of the instance variables
*/ */
ngOnInit(): void { ngOnInit(): void {
this.authorizationService.isAuthenticated(FeatureType.AdministratorOf).subscribe((authorized) => { this.createMenu();
this.createMenu(authorized); this.createSiteAdministratorMenuSections();
super.ngOnInit(); super.ngOnInit();
this.sidebarWidth = this.variableService.getVariable('sidebarItemsWidth'); this.sidebarWidth = this.variableService.getVariable('sidebarItemsWidth');
this.authService.isAuthenticated() this.authService.isAuthenticated()
.subscribe((loggedIn: boolean) => { .subscribe((loggedIn: boolean) => {
if (loggedIn) { if (loggedIn) {
this.menuService.showMenu(this.menuID); this.menuService.showMenu(this.menuID);
} }
}); });
this.menuCollapsed.pipe(first()) this.menuCollapsed.pipe(first())
.subscribe((collapsed: boolean) => { .subscribe((collapsed: boolean) => {
this.sidebarOpen = !collapsed; this.sidebarOpen = !collapsed;
this.sidebarClosed = collapsed; this.sidebarClosed = collapsed;
}); });
this.sidebarExpanded = combineLatestObservable(this.menuCollapsed, this.menuPreviewCollapsed) this.sidebarExpanded = combineLatestObservable(this.menuCollapsed, this.menuPreviewCollapsed)
.pipe( .pipe(
map(([collapsed, previewCollapsed]) => (!collapsed || !previewCollapsed)) map(([collapsed, previewCollapsed]) => (!collapsed || !previewCollapsed))
); );
});
} }
/** /**
* Initialize all menu sections and items for this menu * Initialize all menu sections and items for this menu
*/ */
createMenu(isAdministratorOfSite: boolean) { createMenu() {
const menuList = [ const menuList = [
/* News */ /* News */
{ {
@@ -310,99 +309,6 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit {
} as LinkMenuItemModel, } as LinkMenuItemModel,
}, },
/* Access Control */
{
id: 'access_control',
active: false,
visible: isAdministratorOfSite,
model: {
type: MenuItemType.TEXT,
text: 'menu.section.access_control'
} as TextMenuItemModel,
icon: 'key',
index: 4
},
{
id: 'access_control_people',
parentID: 'access_control',
active: false,
visible: isAdministratorOfSite,
model: {
type: MenuItemType.LINK,
text: 'menu.section.access_control_people',
link: '/admin/access-control/epeople'
} as LinkMenuItemModel,
},
{
id: 'access_control_groups',
parentID: 'access_control',
active: false,
visible: isAdministratorOfSite,
model: {
type: MenuItemType.LINK,
text: 'menu.section.access_control_groups',
link: '/admin/access-control/groups'
} as LinkMenuItemModel,
},
{
id: 'access_control_authorizations',
parentID: 'access_control',
active: false,
visible: isAdministratorOfSite,
model: {
type: MenuItemType.LINK,
text: 'menu.section.access_control_authorizations',
link: ''
} as LinkMenuItemModel,
},
/* Admin Search */
{
id: 'admin_search',
active: false,
visible: isAdministratorOfSite,
model: {
type: MenuItemType.LINK,
text: 'menu.section.admin_search',
link: '/admin/search'
} as LinkMenuItemModel,
icon: 'search',
index: 5
},
/* Registries */
{
id: 'registries',
active: false,
visible: isAdministratorOfSite,
model: {
type: MenuItemType.TEXT,
text: 'menu.section.registries'
} as TextMenuItemModel,
icon: 'list',
index: 6
},
{
id: 'registries_metadata',
parentID: 'registries',
active: false,
visible: isAdministratorOfSite,
model: {
type: MenuItemType.LINK,
text: 'menu.section.registries_metadata',
link: 'admin/registries/metadata'
} as LinkMenuItemModel,
},
{
id: 'registries_format',
parentID: 'registries',
active: false,
visible: isAdministratorOfSite,
model: {
type: MenuItemType.LINK,
text: 'menu.section.registries_format',
link: 'admin/registries/bitstream-formats'
} as LinkMenuItemModel,
},
/* Curation tasks */ /* Curation tasks */
{ {
id: 'curation_tasks', id: 'curation_tasks',
@@ -444,24 +350,130 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit {
icon: 'cogs', icon: 'cogs',
index: 9 index: 9
}, },
/* Workflow */
{
id: 'workflow',
active: false,
visible: isAdministratorOfSite,
model: {
type: MenuItemType.LINK,
text: 'menu.section.workflow',
link: '/admin/workflow'
} as LinkMenuItemModel,
icon: 'user-check',
index: 10
},
]; ];
menuList.forEach((menuSection) => this.menuService.addSection(this.menuID, Object.assign(menuSection, { menuList.forEach((menuSection) => this.menuService.addSection(this.menuID, Object.assign(menuSection, {
shouldPersistOnRouteChange: true shouldPersistOnRouteChange: true
}))); })));
}
/**
* Create menu sections dependent on whether or not the current user is a site administrator
*/
createSiteAdministratorMenuSections() {
this.authorizationService.isAuthenticated(FeatureID.AdministratorOf).subscribe((authorized) => {
const menuList = [
/* Access Control */
{
id: 'access_control',
active: false,
visible: authorized,
model: {
type: MenuItemType.TEXT,
text: 'menu.section.access_control'
} as TextMenuItemModel,
icon: 'key',
index: 4
},
{
id: 'access_control_people',
parentID: 'access_control',
active: false,
visible: authorized,
model: {
type: MenuItemType.LINK,
text: 'menu.section.access_control_people',
link: '/admin/access-control/epeople'
} as LinkMenuItemModel,
},
{
id: 'access_control_groups',
parentID: 'access_control',
active: false,
visible: authorized,
model: {
type: MenuItemType.LINK,
text: 'menu.section.access_control_groups',
link: '/admin/access-control/groups'
} as LinkMenuItemModel,
},
{
id: 'access_control_authorizations',
parentID: 'access_control',
active: false,
visible: authorized,
model: {
type: MenuItemType.LINK,
text: 'menu.section.access_control_authorizations',
link: ''
} as LinkMenuItemModel,
},
/* Admin Search */
{
id: 'admin_search',
active: false,
visible: authorized,
model: {
type: MenuItemType.LINK,
text: 'menu.section.admin_search',
link: '/admin/search'
} as LinkMenuItemModel,
icon: 'search',
index: 5
},
/* Registries */
{
id: 'registries',
active: false,
visible: authorized,
model: {
type: MenuItemType.TEXT,
text: 'menu.section.registries'
} as TextMenuItemModel,
icon: 'list',
index: 6
},
{
id: 'registries_metadata',
parentID: 'registries',
active: false,
visible: authorized,
model: {
type: MenuItemType.LINK,
text: 'menu.section.registries_metadata',
link: 'admin/registries/metadata'
} as LinkMenuItemModel,
},
{
id: 'registries_format',
parentID: 'registries',
active: false,
visible: authorized,
model: {
type: MenuItemType.LINK,
text: 'menu.section.registries_format',
link: 'admin/registries/bitstream-formats'
} as LinkMenuItemModel,
},
/* Workflow */
{
id: 'workflow',
active: false,
visible: authorized,
model: {
type: MenuItemType.LINK,
text: 'menu.section.workflow',
link: '/admin/workflow'
} as LinkMenuItemModel,
icon: 'user-check',
index: 10
},
];
menuList.forEach((menuSection) => this.menuService.addSection(this.menuID, Object.assign(menuSection, {
shouldPersistOnRouteChange: true
})));
});
} }
/** /**

View File

@@ -5,7 +5,7 @@ import { Site } from '../../shared/site.model';
import { EPerson } from '../../eperson/models/eperson.model'; import { EPerson } from '../../eperson/models/eperson.model';
import { of as observableOf } from 'rxjs'; import { of as observableOf } from 'rxjs';
import { FindListOptions } from '../request.models'; import { FindListOptions } from '../request.models';
import { FeatureType } from './feature-type'; import { FeatureID } from './feature-id';
import { hasValue } from '../../../shared/empty.util'; import { hasValue } from '../../../shared/empty.util';
import { RequestParam } from '../../cache/models/request-param.model'; import { RequestParam } from '../../cache/models/request-param.model';
import { Authorization } from '../../shared/authorization.model'; import { Authorization } from '../../shared/authorization.model';
@@ -51,7 +51,7 @@ describe('AuthorizationDataService', () => {
const objectUrl = 'fake-object-url'; const objectUrl = 'fake-object-url';
const ePersonUuid = 'fake-eperson-uuid'; const ePersonUuid = 'fake-eperson-uuid';
function createExpected(objectUrl: string, ePersonUuid?: string, featureId?: FeatureType): FindListOptions { function createExpected(objectUrl: string, ePersonUuid?: string, featureId?: FeatureID): FindListOptions {
const searchParams = [new RequestParam('uri', objectUrl)]; const searchParams = [new RequestParam('uri', objectUrl)];
if (hasValue(featureId)) { if (hasValue(featureId)) {
searchParams.push(new RequestParam('feature', featureId)); searchParams.push(new RequestParam('feature', featureId));
@@ -74,31 +74,31 @@ describe('AuthorizationDataService', () => {
describe('when no arguments except for a feature are provided and a user is authenticated', () => { describe('when no arguments except for a feature are provided and a user is authenticated', () => {
beforeEach(() => { beforeEach(() => {
service.searchByObject(FeatureType.LoginOnBehalfOf).subscribe(); service.searchByObject(FeatureID.LoginOnBehalfOf).subscribe();
}); });
it('should call searchBy with the site\'s url, authenticated user\'s uuid and the feature', () => { it('should call searchBy with the site\'s url, authenticated user\'s uuid and the feature', () => {
expect(service.searchBy).toHaveBeenCalledWith('object', createExpected(site.self, ePerson.uuid, FeatureType.LoginOnBehalfOf)); expect(service.searchBy).toHaveBeenCalledWith('object', createExpected(site.self, ePerson.uuid, FeatureID.LoginOnBehalfOf));
}); });
}); });
describe('when a feature and object url are provided, but no user uuid and a user is authenticated', () => { describe('when a feature and object url are provided, but no user uuid and a user is authenticated', () => {
beforeEach(() => { beforeEach(() => {
service.searchByObject(FeatureType.LoginOnBehalfOf, objectUrl).subscribe(); service.searchByObject(FeatureID.LoginOnBehalfOf, objectUrl).subscribe();
}); });
it('should call searchBy with the object\'s url, authenticated user\'s uuid and the feature', () => { it('should call searchBy with the object\'s url, authenticated user\'s uuid and the feature', () => {
expect(service.searchBy).toHaveBeenCalledWith('object', createExpected(objectUrl, ePerson.uuid, FeatureType.LoginOnBehalfOf)); expect(service.searchBy).toHaveBeenCalledWith('object', createExpected(objectUrl, ePerson.uuid, FeatureID.LoginOnBehalfOf));
}); });
}); });
describe('when all arguments are provided', () => { describe('when all arguments are provided', () => {
beforeEach(() => { beforeEach(() => {
service.searchByObject(FeatureType.LoginOnBehalfOf, objectUrl, ePersonUuid).subscribe(); service.searchByObject(FeatureID.LoginOnBehalfOf, objectUrl, ePersonUuid).subscribe();
}); });
it('should call searchBy with the object\'s url, user\'s uuid and the feature', () => { it('should call searchBy with the object\'s url, user\'s uuid and the feature', () => {
expect(service.searchBy).toHaveBeenCalledWith('object', createExpected(objectUrl, ePersonUuid, FeatureType.LoginOnBehalfOf)); expect(service.searchBy).toHaveBeenCalledWith('object', createExpected(objectUrl, ePersonUuid, FeatureID.LoginOnBehalfOf));
}); });
}); });

View File

@@ -25,7 +25,7 @@ import { hasValue, isNotEmpty } from '../../../shared/empty.util';
import { RequestParam } from '../../cache/models/request-param.model'; import { RequestParam } from '../../cache/models/request-param.model';
import { AuthorizationSearchParams } from './authorization-search-params'; import { AuthorizationSearchParams } from './authorization-search-params';
import { addAuthenticatedUserUuidIfEmpty, addSiteObjectUrlIfEmpty } from './authorization-utils'; import { addAuthenticatedUserUuidIfEmpty, addSiteObjectUrlIfEmpty } from './authorization-utils';
import { FeatureType } from './feature-type'; import { FeatureID } from './feature-id';
/** /**
* A service to retrieve {@link Authorization}s from the REST API * A service to retrieve {@link Authorization}s from the REST API
@@ -59,7 +59,7 @@ export class AuthorizationDataService extends DataService<Authorization> {
* If not provided, the UUID of the currently authenticated {@link EPerson} will be used. * If not provided, the UUID of the currently authenticated {@link EPerson} will be used.
* @param featureId ID of the {@link Feature} to check {@link Authorization} for * @param featureId ID of the {@link Feature} to check {@link Authorization} for
*/ */
isAuthenticated(featureId?: FeatureType, objectUrl?: string, ePersonUuid?: string): Observable<boolean> { isAuthenticated(featureId?: FeatureID, objectUrl?: string, ePersonUuid?: string): Observable<boolean> {
return this.searchByObject(featureId, objectUrl, ePersonUuid).pipe( return this.searchByObject(featureId, objectUrl, ePersonUuid).pipe(
map((authorizationRD) => (authorizationRD.statusCode !== 401 && hasValue(authorizationRD.payload) && isNotEmpty(authorizationRD.payload.page))) map((authorizationRD) => (authorizationRD.statusCode !== 401 && hasValue(authorizationRD.payload) && isNotEmpty(authorizationRD.payload.page)))
); );
@@ -76,7 +76,7 @@ export class AuthorizationDataService extends DataService<Authorization> {
* @param options {@link FindListOptions} to provide pagination and/or additional arguments * @param options {@link FindListOptions} to provide pagination and/or additional arguments
* @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved
*/ */
searchByObject(featureId?: FeatureType, objectUrl?: string, ePersonUuid?: string, options: FindListOptions = {}, ...linksToFollow: Array<FollowLinkConfig<Authorization>>): Observable<RemoteData<PaginatedList<Authorization>>> { searchByObject(featureId?: FeatureID, objectUrl?: string, ePersonUuid?: string, options: FindListOptions = {}, ...linksToFollow: Array<FollowLinkConfig<Authorization>>): Observable<RemoteData<PaginatedList<Authorization>>> {
return observableOf(new AuthorizationSearchParams(objectUrl, ePersonUuid, featureId)).pipe( return observableOf(new AuthorizationSearchParams(objectUrl, ePersonUuid, featureId)).pipe(
addSiteObjectUrlIfEmpty(this.siteService), addSiteObjectUrlIfEmpty(this.siteService),
addAuthenticatedUserUuidIfEmpty(this.authService), addAuthenticatedUserUuidIfEmpty(this.authService),
@@ -101,14 +101,12 @@ export class AuthorizationDataService extends DataService<Authorization> {
return hrefObs.pipe( return hrefObs.pipe(
find((href: string) => hasValue(href)), find((href: string) => hasValue(href)),
tap((href: string) => { tap((href: string) => {
this.requestService.removeByHrefSubstring(href);
const request = new FindListRequest(this.requestService.generateRequestId(), href, options); const request = new FindListRequest(this.requestService.generateRequestId(), href, options);
this.requestService.configure(request); this.requestService.configure(request);
} }
), ),
switchMap((href) => this.requestService.getByHref(href)), switchMap((href) => this.requestService.getByHref(href)),
skipWhile((requestEntry) => hasValue(requestEntry) && requestEntry.completed),
switchMap((href) => switchMap((href) =>
this.rdbService.buildList<Authorization>(hrefObs, ...linksToFollow) as Observable<RemoteData<PaginatedList<Authorization>>> this.rdbService.buildList<Authorization>(hrefObs, ...linksToFollow) as Observable<RemoteData<PaginatedList<Authorization>>>
) )
@@ -122,7 +120,7 @@ export class AuthorizationDataService extends DataService<Authorization> {
* @param ePersonUuid Optional parameter value to add to {@link RequestParam} "eperson" * @param ePersonUuid Optional parameter value to add to {@link RequestParam} "eperson"
* @param featureId Optional parameter value to add to {@link RequestParam} "feature" * @param featureId Optional parameter value to add to {@link RequestParam} "feature"
*/ */
private createSearchOptions(objectUrl: string, options: FindListOptions = {}, ePersonUuid?: string, featureId?: FeatureType): FindListOptions { private createSearchOptions(objectUrl: string, options: FindListOptions = {}, ePersonUuid?: string, featureId?: FeatureID): FindListOptions {
let params = []; let params = [];
if (isNotEmpty(options.searchParams)) { if (isNotEmpty(options.searchParams)) {
params = [...options.searchParams]; params = [...options.searchParams];

View File

@@ -1,11 +1,14 @@
import { FeatureType } from './feature-type'; import { FeatureID } from './feature-id';
/**
* Search parameters for retrieving authorizations from the REST API
*/
export class AuthorizationSearchParams { export class AuthorizationSearchParams {
objectUrl: string; objectUrl: string;
ePersonUuid: string; ePersonUuid: string;
featureId: FeatureType; featureId: FeatureID;
constructor(objectUrl?: string, ePersonUuid?: string, featureId?: FeatureType) { constructor(objectUrl?: string, ePersonUuid?: string, featureId?: FeatureID) {
this.objectUrl = objectUrl; this.objectUrl = objectUrl;
this.ePersonUuid = ePersonUuid; this.ePersonUuid = ePersonUuid;
this.featureId = featureId; this.featureId = featureId;

View File

@@ -1,6 +1,6 @@
import { FeatureAuthorizationGuard } from './feature-authorization.guard'; import { FeatureAuthorizationGuard } from './feature-authorization.guard';
import { AuthorizationDataService } from '../authorization-data.service'; import { AuthorizationDataService } from '../authorization-data.service';
import { FeatureType } from '../feature-type'; import { FeatureID } from '../feature-id';
import { of as observableOf } from 'rxjs'; import { of as observableOf } from 'rxjs';
/** /**
@@ -9,14 +9,14 @@ import { of as observableOf } from 'rxjs';
*/ */
class FeatureAuthorizationGuardImpl extends FeatureAuthorizationGuard { class FeatureAuthorizationGuardImpl extends FeatureAuthorizationGuard {
constructor(protected authorizationService: AuthorizationDataService, constructor(protected authorizationService: AuthorizationDataService,
protected featureType: FeatureType, protected featureId: FeatureID,
protected objectUrl: string, protected objectUrl: string,
protected ePersonUuid: string) { protected ePersonUuid: string) {
super(authorizationService); super(authorizationService);
} }
getFeatureType(): FeatureType { getFeatureID(): FeatureID {
return this.featureType; return this.featureId;
} }
getObjectUrl(): string { getObjectUrl(): string {
@@ -32,19 +32,19 @@ describe('FeatureAuthorizationGuard', () => {
let guard: FeatureAuthorizationGuard; let guard: FeatureAuthorizationGuard;
let authorizationService: AuthorizationDataService; let authorizationService: AuthorizationDataService;
let featureType: FeatureType; let featureId: FeatureID;
let objectUrl: string; let objectUrl: string;
let ePersonUuid: string; let ePersonUuid: string;
function init() { function init() {
featureType = FeatureType.LoginOnBehalfOf; featureId = FeatureID.LoginOnBehalfOf;
objectUrl = 'fake-object-url'; objectUrl = 'fake-object-url';
ePersonUuid = 'fake-eperson-uuid'; ePersonUuid = 'fake-eperson-uuid';
authorizationService = jasmine.createSpyObj('authorizationService', { authorizationService = jasmine.createSpyObj('authorizationService', {
isAuthenticated: observableOf(true) isAuthenticated: observableOf(true)
}); });
guard = new FeatureAuthorizationGuardImpl(authorizationService, featureType, objectUrl, ePersonUuid); guard = new FeatureAuthorizationGuardImpl(authorizationService, featureId, objectUrl, ePersonUuid);
} }
beforeEach(() => { beforeEach(() => {
@@ -54,14 +54,14 @@ describe('FeatureAuthorizationGuard', () => {
describe('canActivate', () => { describe('canActivate', () => {
it('should call authorizationService.isAuthenticated with the appropriate arguments', () => { it('should call authorizationService.isAuthenticated with the appropriate arguments', () => {
guard.canActivate(undefined, undefined).subscribe(); guard.canActivate(undefined, undefined).subscribe();
expect(authorizationService.isAuthenticated).toHaveBeenCalledWith(featureType, objectUrl, ePersonUuid); expect(authorizationService.isAuthenticated).toHaveBeenCalledWith(featureId, objectUrl, ePersonUuid);
}); });
}); });
describe('canLoad', () => { describe('canLoad', () => {
it('should call authorizationService.isAuthenticated with the appropriate arguments', () => { it('should call authorizationService.isAuthenticated with the appropriate arguments', () => {
guard.canLoad(undefined, undefined).subscribe(); guard.canLoad(undefined, undefined).subscribe();
expect(authorizationService.isAuthenticated).toHaveBeenCalledWith(featureType, objectUrl, ePersonUuid); expect(authorizationService.isAuthenticated).toHaveBeenCalledWith(featureId, objectUrl, ePersonUuid);
}); });
}); });
}); });

View File

@@ -1,6 +1,6 @@
import { ActivatedRouteSnapshot, CanActivate, CanLoad, Route, RouterStateSnapshot, UrlSegment } from '@angular/router'; import { ActivatedRouteSnapshot, CanActivate, CanLoad, Route, RouterStateSnapshot, UrlSegment } from '@angular/router';
import { AuthorizationDataService } from '../authorization-data.service'; import { AuthorizationDataService } from '../authorization-data.service';
import { FeatureType } from '../feature-type'; import { FeatureID } from '../feature-id';
import { Observable } from 'rxjs/internal/Observable'; import { Observable } from 'rxjs/internal/Observable';
/** /**
@@ -16,23 +16,21 @@ export abstract class FeatureAuthorizationGuard implements CanActivate, CanLoad
* True when user has authorization rights for the feature and object provided * True when user has authorization rights for the feature and object provided
*/ */
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> { canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.authorizationService.isAuthenticated(this.getFeatureType(), this.getObjectUrl(), this.getEPersonUuid()); return this.authorizationService.isAuthenticated(this.getFeatureID(), this.getObjectUrl(), this.getEPersonUuid());
} }
/** /**
* True when user has authorization rights for the feature and object provided * True when user has authorization rights for the feature and object provided
*/ */
canLoad(route: Route, segments: UrlSegment[]): Observable<boolean> { canLoad(route: Route, segments: UrlSegment[]): Observable<boolean> {
return this.authorizationService.isAuthenticated(this.getFeatureType(), this.getObjectUrl(), this.getEPersonUuid()); return this.authorizationService.isAuthenticated(this.getFeatureID(), this.getObjectUrl(), this.getEPersonUuid());
} }
/** /**
* The type of feature to check authorization for * The type of feature to check authorization for
* Override this method to define a feature * Override this method to define a feature
*/ */
getFeatureType(): FeatureType { abstract getFeatureID(): FeatureID;
return undefined;
}
/** /**
* The URL of the object to check if the user has authorized rights for * The URL of the object to check if the user has authorized rights for

View File

@@ -1,6 +1,6 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { FeatureAuthorizationGuard } from './feature-authorization.guard'; import { FeatureAuthorizationGuard } from './feature-authorization.guard';
import { FeatureType } from '../feature-type'; import { FeatureID } from '../feature-id';
import { AuthorizationDataService } from '../authorization-data.service'; import { AuthorizationDataService } from '../authorization-data.service';
/** /**
@@ -18,7 +18,7 @@ export class SiteAdministratorGuard extends FeatureAuthorizationGuard {
/** /**
* Check administrator authorization rights * Check administrator authorization rights
*/ */
getFeatureType(): FeatureType { getFeatureID(): FeatureID {
return FeatureType.AdministratorOf; return FeatureID.AdministratorOf;
} }
} }

View File

@@ -1,7 +1,7 @@
/** /**
* Enum object for all possible {@link Feature} types * Enum object for all possible {@link Feature} IDs
*/ */
export enum FeatureType { export enum FeatureID {
LoginOnBehalfOf = 'loginOnBehalfOf', LoginOnBehalfOf = 'loginOnBehalfOf',
AdministratorOf = 'administratorOf' AdministratorOf = 'administratorOf'
} }

View File

@@ -1,7 +1,8 @@
import { typedObject } from '../cache/builders/build-decorators'; import { typedObject } from '../cache/builders/build-decorators';
import { autoserialize, inheritSerialization } from 'cerialize'; import { autoserialize, deserialize, inheritSerialization } from 'cerialize';
import { FEATURE } from './feature.resource-type'; import { FEATURE } from './feature.resource-type';
import { DSpaceObject } from './dspace-object.model'; import { DSpaceObject } from './dspace-object.model';
import { HALLink } from './hal-link.model';
/** /**
* Class representing a DSpace Feature * Class representing a DSpace Feature
@@ -28,4 +29,9 @@ export class Feature extends DSpaceObject {
*/ */
@autoserialize @autoserialize
resourcetypes: string[]; resourcetypes: string[];
@deserialize
_links: {
self: HALLink;
};
} }