Skip to content

Commit 293ba84

Browse files
committed
94273: Make isAuthorized depend on the target object
This ensures that a successful ItemDataService.setWithdrawn call invalidates all related authorizations
1 parent 7c13db2 commit 293ba84

2 files changed

Lines changed: 64 additions & 6 deletions

File tree

src/app/core/data/feature-authorization/authorization-data.service.spec.ts

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { SiteDataService } from '../site-data.service';
33
import { AuthService } from '../../auth/auth.service';
44
import { Site } from '../../shared/site.model';
55
import { EPerson } from '../../eperson/models/eperson.model';
6-
import { of as observableOf } from 'rxjs';
6+
import { of as observableOf, combineLatest as observableCombineLatest, Observable } from 'rxjs';
77
import { FeatureID } from './feature-id';
88
import { hasValue } from '../../../shared/empty.util';
99
import { RequestParam } from '../../cache/models/request-param.model';
@@ -17,6 +17,7 @@ describe('AuthorizationDataService', () => {
1717
let service: AuthorizationDataService;
1818
let siteService: SiteDataService;
1919
let authService: AuthService;
20+
let objectCache;
2021

2122
let site: Site;
2223
let ePerson: EPerson;
@@ -43,7 +44,11 @@ describe('AuthorizationDataService', () => {
4344
isAuthenticated: () => observableOf(true),
4445
getAuthenticatedUserFromStore: () => observableOf(ePerson)
4546
} as AuthService;
46-
service = new AuthorizationDataService(requestService, undefined, undefined, undefined, undefined, undefined, undefined, undefined, authService, siteService);
47+
objectCache = jasmine.createSpyObj('objectCache', {
48+
addDependency: undefined,
49+
removeDependents: undefined,
50+
});
51+
service = new AuthorizationDataService(requestService, undefined, undefined, objectCache, undefined, undefined, undefined, undefined, authService, siteService);
4752
}
4853

4954
beforeEach(() => {
@@ -110,6 +115,43 @@ describe('AuthorizationDataService', () => {
110115
expect(service.searchBy).toHaveBeenCalledWith('object', createExpected(objectUrl, ePersonUuid, FeatureID.LoginOnBehalfOf), true, true);
111116
});
112117
});
118+
119+
describe('dependencies', () => {
120+
let addDependencySpy;
121+
122+
beforeEach(() => {
123+
(service.searchBy as any).and.returnValue(observableOf('searchBy RD$'));
124+
addDependencySpy = spyOn(service as any, 'addDependency');
125+
});
126+
127+
it('should add a dependency on the objectUrl', (done) => {
128+
addDependencySpy.and.callFake((href$: Observable<string>, dependsOn$: Observable<string>) => {
129+
observableCombineLatest([href$, dependsOn$]).subscribe(([href, dependsOn]) => {
130+
expect(href).toBe('searchBy RD$');
131+
expect(dependsOn).toBe('object-href');
132+
});
133+
});
134+
135+
service.searchByObject(FeatureID.AdministratorOf, 'object-href').subscribe(() => {
136+
expect(addDependencySpy).toHaveBeenCalled();
137+
done();
138+
});
139+
});
140+
141+
it('should add a dependency on the Site object if no objectUrl is given', (done) => {
142+
addDependencySpy.and.callFake((object$: Observable<any>, dependsOn$: Observable<string>) => {
143+
observableCombineLatest([object$, dependsOn$]).subscribe(([object, dependsOn]) => {
144+
expect(object).toBe('searchBy RD$');
145+
expect(dependsOn).toBe('test-site-href');
146+
});
147+
});
148+
149+
service.searchByObject(FeatureID.AdministratorOf).subscribe(() => {
150+
expect(addDependencySpy).toHaveBeenCalled();
151+
done();
152+
});
153+
});
154+
});
113155
});
114156

115157
describe('isAuthorized', () => {

src/app/core/data/feature-authorization/authorization-data.service.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ import { followLink, FollowLinkConfig } from '../../../shared/utils/follow-link-
1818
import { RemoteData } from '../remote-data';
1919
import { PaginatedList } from '../paginated-list.model';
2020
import { catchError, map, switchMap } from 'rxjs/operators';
21-
import { hasValue, isNotEmpty } from '../../../shared/empty.util';
21+
import { hasNoValue, hasValue, isNotEmpty } from '../../../shared/empty.util';
2222
import { RequestParam } from '../../cache/models/request-param.model';
2323
import { AuthorizationSearchParams } from './authorization-search-params';
24-
import { addSiteObjectUrlIfEmpty, oneAuthorizationMatchesFeature } from './authorization-utils';
24+
import { oneAuthorizationMatchesFeature } from './authorization-utils';
2525
import { FeatureID } from './feature-id';
2626
import { getFirstCompletedRemoteData } from '../../shared/operators';
2727
import { CoreState } from '../../core-state.model';
@@ -102,12 +102,28 @@ export class AuthorizationDataService extends DataService<Authorization> {
102102
* {@link HALLink}s should be automatically resolved
103103
*/
104104
searchByObject(featureId?: FeatureID, objectUrl?: string, ePersonUuid?: string, options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig<Authorization>[]): Observable<RemoteData<PaginatedList<Authorization>>> {
105-
return observableOf(new AuthorizationSearchParams(objectUrl, ePersonUuid, featureId)).pipe(
106-
addSiteObjectUrlIfEmpty(this.siteService),
105+
const objectUrl$ = observableOf(objectUrl).pipe(
106+
switchMap((url) => {
107+
if (hasNoValue(url)) {
108+
return this.siteService.find().pipe(
109+
map((site) => site.self)
110+
);
111+
} else {
112+
return observableOf(url);
113+
}
114+
}),
115+
);
116+
117+
const out$ = objectUrl$.pipe(
118+
map((url: string) => new AuthorizationSearchParams(url, ePersonUuid, featureId)),
107119
switchMap((params: AuthorizationSearchParams) => {
108120
return this.searchBy(this.searchByObjectPath, this.createSearchOptions(params.objectUrl, options, params.ePersonUuid, params.featureId), useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow);
109121
})
110122
);
123+
124+
this.addDependency(out$, objectUrl$);
125+
126+
return out$;
111127
}
112128

113129
/**

0 commit comments

Comments
 (0)