diff --git a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts index 9e3bcc88c0..10c4dd5bfc 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts +++ b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts @@ -7,9 +7,9 @@ import { DynamicInputModel } from '@ng-dynamic-forms/core'; import { TranslateService } from '@ngx-translate/core'; -import { Subscription, combineLatest, of } from 'rxjs'; +import { Subscription, combineLatest, of, interval } from 'rxjs'; import { Observable } from 'rxjs/internal/Observable'; -import { take } from 'rxjs/operators'; +import { flatMap, map, switchMap, take } from 'rxjs/operators'; import { RestResponse } from '../../../../core/cache/response.models'; import { PaginatedList } from '../../../../core/data/paginated-list'; import { RemoteData } from '../../../../core/data/remote-data'; @@ -23,6 +23,8 @@ import { FormBuilderService } from '../../../../shared/form/builder/form-builder import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; import { AuthService } from '../../../../core/auth/auth.service'; +import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service'; +import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; @Component({ selector: 'ds-eperson-form', @@ -120,9 +122,8 @@ export class EPersonFormComponent implements OnInit, OnDestroy { /** * Observable whether or not the admin is allowed to impersonate the EPerson - * TODO: Initialize the observable once the REST API supports this (currently hardcoded to return true) */ - canImpersonate$: Observable = of(true); + canImpersonate$: Observable; /** * List of subscriptions @@ -158,7 +159,8 @@ export class EPersonFormComponent implements OnInit, OnDestroy { private formBuilderService: FormBuilderService, private translateService: TranslateService, private notificationsService: NotificationsService, - private authService: AuthService) { + private authService: AuthService, + private authorizationService: AuthorizationDataService) { this.subs.push(this.epersonService.getActiveEPerson().subscribe((eperson: EPerson) => { this.epersonInitial = eperson; if (hasValue(eperson)) { @@ -242,6 +244,9 @@ export class EPersonFormComponent implements OnInit, OnDestroy { requireCertificate: eperson != null ? eperson.requireCertificate : false }); })); + this.canImpersonate$ = this.epersonService.getActiveEPerson().pipe( + switchMap((eperson) => this.authorizationService.isAuthenticated(eperson.self, undefined, 'loginOnBehalfOf')) + ); }); } diff --git a/src/app/core/data/feature-authorization/authorization-data.service.ts b/src/app/core/data/feature-authorization/authorization-data.service.ts index 57a02435dc..1a827c413e 100644 --- a/src/app/core/data/feature-authorization/authorization-data.service.ts +++ b/src/app/core/data/feature-authorization/authorization-data.service.ts @@ -20,7 +20,7 @@ import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model import { Observable } from 'rxjs/internal/Observable'; import { RemoteData } from '../remote-data'; import { PaginatedList } from '../paginated-list'; -import { find, skipWhile, switchMap, tap } from 'rxjs/operators'; +import { find, map, skipWhile, switchMap, tap } from 'rxjs/operators'; import { hasValue, isNotEmpty } from '../../../shared/empty.util'; import { RequestParam } from '../../cache/models/request-param.model'; import { AuthorizationSearchParams } from './authorization-search-params'; @@ -50,6 +50,20 @@ export class AuthorizationDataService extends DataService { super(); } + /** + * Checks if an {@link EPerson} (or anonymous) has access to a specific object within a {@link Feature} + * @param objectUrl URL to the object to search {@link Authorization}s for. + * If not provided, the repository's {@link Site} will be used. + * @param ePersonUuid UUID of the {@link EPerson} to search {@link Authorization}s for. + * 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 + */ + isAuthenticated(objectUrl?: string, ePersonUuid?: string, featureId?: string): Observable { + return this.searchByObject(objectUrl, ePersonUuid, featureId).pipe( + map((authorizationRD) => (authorizationRD.statusCode !== 401 && hasValue(authorizationRD.payload) && isNotEmpty(authorizationRD.payload.page))) + ); + } + /** * Search for a list of {@link Authorization}s using the "object" search endpoint and providing optional object url, * {@link EPerson} uuid and/or {@link Feature} id