Skip to content

Commit d1bcb9f

Browse files
committed
Request-a-copy: Use wrapped ItemWithSupp.. and base item comps, except download link
1 parent 58d0e7f commit d1bcb9f

39 files changed

Lines changed: 145 additions & 2199 deletions

File tree

src/app/core/auth/access-token.resolver.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ import {
1717
} from '../shared/operators';
1818
import { AuthService } from './auth.service';
1919

20+
/**
21+
* Resolve an ItemRequest based on the accessToken in the query params
22+
* Used in item-page-routes.ts to resolve the item request for all Item page components
23+
* @param route
24+
* @param state
25+
* @param router
26+
* @param authService
27+
* @param itemRequestDataService
28+
*/
2029
export const accessTokenResolver: ResolveFn<ItemRequest> = (
2130
route,
2231
state,
@@ -25,21 +34,23 @@ export const accessTokenResolver: ResolveFn<ItemRequest> = (
2534
itemRequestDataService: ItemRequestDataService = inject(ItemRequestDataService),
2635
): Observable<ItemRequest> => {
2736
const accessToken = route.queryParams.accessToken;
37+
// Set null object if accesstoken is empty
2838
if ( !hasValue(accessToken) ) {
2939
return null;
3040
}
31-
// Get
41+
// Get the item request from the server
3242
return itemRequestDataService.getSanitizedRequestByAccessToken(accessToken).pipe(
3343
getFirstCompletedRemoteData(),
44+
// Handle authorization errors, not found errors and forbidden errors as normal
3445
redirectOn4xx(router, authService),
46+
// Get payload of the item request
3547
getFirstSucceededRemoteDataPayload(),
3648
tap(request => {
3749
if (!hasValue(request)) {
38-
console.dir('no request found for access token', accessToken);
50+
// If the request is not found, redirect to 403 Forbidden
3951
router.navigateByUrl(getForbiddenRoute());
4052
}
41-
console.dir('found request: ', request);
42-
console.dir(request);
53+
// Return the resolved item request object
4354
return request;
4455
}),
4556
);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Item } from './item.model';
2+
import { ItemRequest } from './item-request.model';
3+
4+
/**
5+
* This model represents an item with supplementary data, e.g. an ItemRequest object
6+
* to help components determine how the Item or its data/bitstream should be delivered
7+
* and presented to the users, but not part of the actual database model.
8+
*/
9+
export class ItemWithSupplementaryData extends Item {
10+
/**
11+
* An item request. This is used to determine how the item should be delivered.
12+
* A valid accessToken is resolved to this object in the accessTokenResolver
13+
*/
14+
itemRequest: ItemRequest;
15+
16+
constructor(itemRequest: ItemRequest) {
17+
super();
18+
this.itemRequest = itemRequest;
19+
}
20+
}

src/app/core/shared/media-viewer-item.model.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,9 @@ export class MediaViewerItem {
2323
* Incoming Bitsream thumbnail
2424
*/
2525
thumbnail: string;
26+
27+
/**
28+
* Access token, if accessed via a Request-a-Copy link
29+
*/
30+
accessToken: string;
2631
}

src/app/item-page/access-by-token/field-components/file-download-link/item-secure-file-download-link.component.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
<a [routerLink]="(bitstreamPath$| async)?.routerLink" class="dont-break-out" [queryParams]="(bitstreamPath$| async)?.queryParams" [target]="isBlank ? '_blank': '_self'" [ngClass]="cssClasses">
1+
<a [routerLink]="(bitstreamPath$| async)?.routerLink" class="dont-break-out"
2+
[queryParams]="(bitstreamPath$| async)?.queryParams"
3+
[target]="isBlank ? '_blank': '_self'"
4+
[ngClass]="cssClasses"
5+
[attr.aria-label]="('file-download-link.download' | translate) + dsoNameService.getName(bitstream)">
26
<!-- If the user cannot download the file by auth or token, show a lock icon -->
37
<span role="img" *ngIf="(canDownload$ | async) === false && (canDownloadWithToken$ | async) === false" [attr.aria-label]="'file-download-link.restricted' | translate" class="pr-1"><i class="fas fa-lock"></i></span>
48
<!-- If the user can download the file by token, and NOT normally show a lock open icon -->

src/app/item-page/access-by-token/field-components/file-download-link/item-secure-file-download-link.component.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@ import {
2323
getBitstreamDownloadWithAccessTokenRoute,
2424
getBitstreamRequestACopyRoute,
2525
} from '../../../../app-routing-paths';
26+
import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service';
2627
import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service';
2728
import { FeatureID } from '../../../../core/data/feature-authorization/feature-id';
2829
import { Bitstream } from '../../../../core/shared/bitstream.model';
2930
import { Item } from '../../../../core/shared/item.model';
3031
import { ItemRequest } from '../../../../core/shared/item-request.model';
32+
import { ItemWithSupplementaryData } from '../../../../core/shared/item-with-supplementary-data.model';
3133
import {
3234
hasValue,
3335
isNotEmpty,
@@ -54,6 +56,9 @@ export class ItemSecureFileDownloadLinkComponent implements OnInit {
5456
*/
5557
@Input() bitstream: Bitstream;
5658

59+
/**
60+
* Item that owns the linked bitstream
61+
*/
5762
@Input() item: Item;
5863

5964
/**
@@ -66,15 +71,14 @@ export class ItemSecureFileDownloadLinkComponent implements OnInit {
6671
*/
6772
@Input() isBlank = false;
6873

69-
@Input() itemRequest: ItemRequest;
70-
7174
@Input() enableRequestACopy = true;
7275

7376
bitstreamPath$: Observable<{
7477
routerLink: string,
7578
queryParams: any,
7679
}>;
77-
80+
// ItemRequest object with access token, expiry, etc.
81+
itemRequest: ItemRequest;
7882
// authorized to download normally
7983
canDownload$: Observable<boolean>;
8084
// authorized to download with token
@@ -84,6 +88,7 @@ export class ItemSecureFileDownloadLinkComponent implements OnInit {
8488

8589
constructor(
8690
private authorizationService: AuthorizationDataService,
91+
protected dsoNameService: DSONameService,
8792
) {
8893
}
8994

@@ -92,6 +97,9 @@ export class ItemSecureFileDownloadLinkComponent implements OnInit {
9297
* (for a given bitstream), and ability to request a copy of a bitstream.
9398
*/
9499
ngOnInit() {
100+
if (this.item instanceof ItemWithSupplementaryData) {
101+
this.itemRequest = this.item.itemRequest;
102+
}
95103
this.canDownload$ = this.authorizationService.isAuthorized(FeatureID.CanDownload, isNotEmpty(this.bitstream) ? this.bitstream.self : undefined);
96104
this.canDownloadWithToken$ = observableOf(this.itemRequest ? (this.itemRequest.allfiles !== false || this.itemRequest.bitstreamId === this.bitstream.uuid) : false);
97105
this.canRequestACopy$ = this.authorizationService.isAuthorized(FeatureID.CanRequestACopy, isNotEmpty(this.bitstream) ? this.bitstream.self : undefined);

src/app/item-page/access-by-token/field-components/file-section/item-secure-file-section.component.html

Lines changed: 0 additions & 87 deletions
This file was deleted.

src/app/item-page/access-by-token/field-components/file-section/item-secure-file-section.component.scss

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/app/item-page/access-by-token/field-components/file-section/item-secure-file-section.component.spec.ts

Lines changed: 0 additions & 96 deletions
This file was deleted.

0 commit comments

Comments
 (0)