mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
94207: Fix ResourcePolicyService.updateTarget
Follow "await invalidation" pattern ~ DataService.deleteByHref
This commit is contained in:
@@ -15,12 +15,13 @@ import { ActionType } from './models/action-type.model';
|
||||
import { RequestParam } from '../cache/models/request-param.model';
|
||||
import { PageInfo } from '../shared/page-info.model';
|
||||
import { buildPaginatedList } from '../data/paginated-list.model';
|
||||
import { createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils';
|
||||
import { createPendingRemoteDataObject, createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils';
|
||||
import { RestResponse } from '../cache/response.models';
|
||||
import { RequestEntry } from '../data/request-entry.model';
|
||||
import { FindListOptions } from '../data/find-list-options.model';
|
||||
import { EPersonDataService } from '../eperson/eperson-data.service';
|
||||
import { GroupDataService } from '../eperson/group-data.service';
|
||||
import { RestRequestMethod } from '../data/rest-request-method';
|
||||
|
||||
describe('ResourcePolicyService', () => {
|
||||
let scheduler: TestScheduler;
|
||||
@@ -128,6 +129,14 @@ describe('ResourcePolicyService', () => {
|
||||
getBrowseEndpoint: hot('a', {
|
||||
a: ePersonEndpoint
|
||||
}),
|
||||
getIDHrefObs: cold('a', {
|
||||
a: 'https://rest.api/rest/api/eperson/epersons/' + epersonUUID
|
||||
}),
|
||||
});
|
||||
groupService = jasmine.createSpyObj('groupService', {
|
||||
getIDHrefObs: cold('a', {
|
||||
a: 'https://rest.api/rest/api/eperson/groups/' + groupUUID
|
||||
}),
|
||||
});
|
||||
objectCache = {} as ObjectCacheService;
|
||||
const notificationsService = {} as NotificationsService;
|
||||
@@ -153,6 +162,7 @@ describe('ResourcePolicyService', () => {
|
||||
spyOn((service as any).dataService, 'findByHref').and.callThrough();
|
||||
spyOn((service as any).dataService, 'searchBy').and.callThrough();
|
||||
spyOn((service as any).dataService, 'getSearchByHref').and.returnValue(observableOf(requestURL));
|
||||
spyOn((service as any).dataService, 'invalidateByHref').and.returnValue(observableOf(requestURL));
|
||||
});
|
||||
|
||||
describe('create', () => {
|
||||
@@ -336,14 +346,56 @@ describe('ResourcePolicyService', () => {
|
||||
});
|
||||
|
||||
describe('updateTarget', () => {
|
||||
it('should create a new PUT request for eperson', () => {
|
||||
const targetType = 'eperson';
|
||||
|
||||
const result = service.updateTarget(resourcePolicyId, requestURL, epersonUUID, targetType);
|
||||
const expected = cold('a|', {
|
||||
a: resourcePolicyRD
|
||||
beforeEach(() => {
|
||||
scheduler.schedule(() => service.create(resourcePolicy, resourceUUID, epersonUUID));
|
||||
});
|
||||
expect(result).toBeObservable(expected);
|
||||
|
||||
it('should send a PUT request to update the EPerson', () => {
|
||||
service.updateTarget(resourcePolicyId, requestURL, epersonUUID, 'eperson');
|
||||
scheduler.flush();
|
||||
|
||||
expect(requestService.send).toHaveBeenCalledWith(jasmine.objectContaining({
|
||||
method: RestRequestMethod.PUT,
|
||||
uuid: requestUUID,
|
||||
href: `${resourcePolicy._links.self.href}/eperson`,
|
||||
body: 'https://rest.api/rest/api/eperson/epersons/' + epersonUUID,
|
||||
}));
|
||||
});
|
||||
|
||||
it('should send a PUT request to update the Group', () => {
|
||||
service.updateTarget(resourcePolicyId, requestURL, groupUUID, 'group');
|
||||
scheduler.flush();
|
||||
|
||||
expect(requestService.send).toHaveBeenCalledWith(jasmine.objectContaining({
|
||||
method: RestRequestMethod.PUT,
|
||||
uuid: requestUUID,
|
||||
href: `${resourcePolicy._links.self.href}/group`,
|
||||
body: 'https://rest.api/rest/api/eperson/groups/' + groupUUID,
|
||||
}));
|
||||
});
|
||||
|
||||
it('should invalidate the ResourcePolicy if the PUT request succeeds', () => {
|
||||
service.updateTarget(resourcePolicyId, requestURL, epersonUUID, 'eperson');
|
||||
scheduler.flush();
|
||||
|
||||
expect((service as any).dataService.invalidateByHref).toHaveBeenCalledWith(resourcePolicy._links.self.href);
|
||||
});
|
||||
|
||||
it('should only emit when invalidation is complete', () => {
|
||||
const RD = {
|
||||
p: createPendingRemoteDataObject(),
|
||||
s: createSuccessfulRemoteDataObject({}),
|
||||
};
|
||||
const response$ = cold('(s|)', RD);
|
||||
const invalidate$ = cold('--(d|)', { d: true });
|
||||
|
||||
(rdbService.buildFromRequestUUID as any).and.returnValue(response$);
|
||||
((service as any).dataService.invalidateByHref).and.returnValue(invalidate$);
|
||||
|
||||
const out$ = service.updateTarget(resourcePolicyId, requestURL, groupUUID, 'group');
|
||||
scheduler.flush();
|
||||
|
||||
expect(out$).toBeObservable(cold('--(s|)', RD));
|
||||
});
|
||||
});
|
||||
|
||||
|
@@ -3,7 +3,7 @@ import { Injectable } from '@angular/core';
|
||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||
|
||||
import { Store } from '@ngrx/store';
|
||||
import { Observable } from 'rxjs';
|
||||
import { AsyncSubject, Observable } from 'rxjs';
|
||||
import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
|
||||
import { dataService } from '../cache/builders/build-decorators';
|
||||
|
||||
@@ -23,7 +23,7 @@ import { PaginatedList } from '../data/paginated-list.model';
|
||||
import { ActionType } from './models/action-type.model';
|
||||
import { RequestParam } from '../cache/models/request-param.model';
|
||||
import { isNotEmpty } from '../../shared/empty.util';
|
||||
import { map, take } from 'rxjs/operators';
|
||||
import { filter, first, map, switchMap } from 'rxjs/operators';
|
||||
import { NoContent } from '../shared/NoContent.model';
|
||||
import { getFirstCompletedRemoteData } from '../shared/operators';
|
||||
import { CoreState } from '../core-state.model';
|
||||
@@ -37,7 +37,6 @@ import { HALLink } from '../shared/hal-link.model';
|
||||
import { EPersonDataService } from '../eperson/eperson-data.service';
|
||||
import { GroupDataService } from '../eperson/group-data.service';
|
||||
|
||||
|
||||
/**
|
||||
* A private DataService implementation to delegate specific methods to.
|
||||
*/
|
||||
@@ -241,13 +240,8 @@ export class ResourcePolicyService {
|
||||
* @param targetType the type of the target (eperson or group) to which the permission is being granted
|
||||
*/
|
||||
updateTarget(resourcePolicyId: string, resourcePolicyHref: string, targetUUID: string, targetType: string): Observable<RemoteData<any>> {
|
||||
|
||||
const targetService = targetType === 'eperson' ? this.ePersonService : this.groupService;
|
||||
|
||||
const targetEndpoint$ = targetService.getBrowseEndpoint().pipe(
|
||||
take(1),
|
||||
map((endpoint: string) =>`${endpoint}/${targetUUID}`),
|
||||
);
|
||||
const targetEndpoint$ = targetService.getIDHrefObs(targetUUID);
|
||||
|
||||
const options: HttpOptions = Object.create({});
|
||||
let headers = new HttpHeaders();
|
||||
@@ -256,9 +250,9 @@ export class ResourcePolicyService {
|
||||
|
||||
const requestId = this.requestService.generateRequestId();
|
||||
|
||||
this.requestService.setStaleByHrefSubstring(`${this.dataService.getLinkPath()}/${resourcePolicyId}/${targetType}`);
|
||||
|
||||
targetEndpoint$.subscribe((targetEndpoint) => {
|
||||
targetEndpoint$.pipe(
|
||||
first(),
|
||||
).subscribe((targetEndpoint) => {
|
||||
const resourceEndpoint = resourcePolicyHref + '/' + targetType;
|
||||
const request = new PutRequest(requestId, resourceEndpoint, targetEndpoint, options);
|
||||
Object.assign(request, {
|
||||
@@ -269,8 +263,35 @@ export class ResourcePolicyService {
|
||||
this.requestService.send(request);
|
||||
});
|
||||
|
||||
return this.rdbService.buildFromRequestUUID(requestId);
|
||||
const response$ = this.rdbService.buildFromRequestUUID(requestId);
|
||||
|
||||
const invalidated$ = new AsyncSubject<boolean>();
|
||||
response$.pipe(
|
||||
getFirstCompletedRemoteData(),
|
||||
switchMap((rd: RemoteData<any>) => {
|
||||
if (rd.hasSucceeded) {
|
||||
return this.dataService.invalidateByHref(resourcePolicyHref);
|
||||
} else {
|
||||
return [undefined];
|
||||
}
|
||||
}),
|
||||
).subscribe(() => {
|
||||
invalidated$.next(true);
|
||||
invalidated$.complete();
|
||||
});
|
||||
|
||||
return response$.pipe(
|
||||
switchMap((rd: RemoteData<NoContent>) => {
|
||||
if (rd.hasSucceeded) {
|
||||
return invalidated$.pipe(
|
||||
filter((invalidated: boolean) => invalidated),
|
||||
map(() => rd)
|
||||
);
|
||||
} else {
|
||||
return [rd];
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user