Skip to content

Commit 4dd5c4c

Browse files
committed
feat: update use cases of guestbook and access
1 parent bba1993 commit 4dd5c4c

24 files changed

Lines changed: 616 additions & 2 deletions

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel
1717
- New Use Case: [Delete a Template](./docs/useCases.md#delete-a-template) under Templates.
1818
- New Use Case: [Update Terms of Access](./docs/useCases.md#update-terms-of-access).
1919
- Guestbooks: Added use cases and repository support for guestbook creation, listing, and enabling/disabling.
20+
- Guestbooks: Added dataset-level guestbook assignment and removal support via `assignDatasetGuestbook` (`PUT /api/datasets/{identifier}/guestbook`) and `removeDatasetGuestbook` (`DELETE /api/datasets/{identifier}/guestbook`).
21+
- Access: Added signed-URL GET use cases for `access/datafile`, `access/datafiles`, `access/dataset`, and `access/dataset/{id}/versions/{versionId}` endpoints using `?signed=true` (authenticated users only).
2022
- Access: Added a dedicated `access` module for guestbook-at-request and download terms/guestbook submission endpoints.
2123

2224
### Changed

docs/useCases.md

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,14 @@ The different use cases currently available in the package are classified below,
130130
- [Guestbooks write use cases](#guestbooks-write-use-cases)
131131
- [Create a Guestbook](#create-a-guestbook)
132132
- [Set Guestbook Enabled](#set-guestbook-enabled)
133+
- [Assign Dataset Guestbook](#assign-dataset-guestbook)
134+
- [Remove Dataset Guestbook](#remove-dataset-guestbook)
133135
- [Access](#Access)
136+
- [Access read use cases](#access-read-use-cases)
137+
- [Get Signed Datafile Download URL](#get-signed-datafile-download-url)
138+
- [Get Signed Datafiles Download URL](#get-signed-datafiles-download-url)
139+
- [Get Signed Dataset Download URL](#get-signed-dataset-download-url)
140+
- [Get Signed Dataset Version Download URL](#get-signed-dataset-version-download-url)
134141
- [Access write use cases](#access-write-use-cases)
135142
- [Submit Guestbook For Datafile Download](#submit-guestbook-for-datafile-download)
136143
- [Submit Guestbook For Datafiles Download](#submit-guestbook-for-datafiles-download)
@@ -2840,6 +2847,9 @@ const guestbook: CreateGuestbookDTO = {
28402847
nameRequired: true,
28412848
institutionRequired: false,
28422849
positionRequired: false,
2850+
email: 'test@gmail.com',
2851+
institution: 'Harvard University',
2852+
position: 'Researcher',
28432853
customQuestions: [
28442854
{
28452855
question: 'Describe yourself',
@@ -2877,8 +2887,113 @@ setGuestbookEnabled.execute(collectionIdOrAlias, guestbookId, false).then(() =>
28772887

28782888
_See [use case](../src/guestbooks/domain/useCases/SetGuestbookEnabled.ts) implementation_.
28792889

2890+
#### Assign Dataset Guestbook
2891+
2892+
Assigns a guestbook to a dataset using `PUT /api/datasets/{identifier}/guestbook`.
2893+
2894+
##### Example call:
2895+
2896+
```typescript
2897+
import { assignDatasetGuestbook } from '@iqss/dataverse-client-javascript'
2898+
2899+
const datasetIdOrPersistentId = 123
2900+
const guestbookId = 456
2901+
2902+
assignDatasetGuestbook.execute(datasetIdOrPersistentId, guestbookId).then(() => {
2903+
/* ... */
2904+
})
2905+
```
2906+
2907+
_See [use case](../src/guestbooks/domain/useCases/AssignDatasetGuestbook.ts) implementation_.
2908+
2909+
#### Remove Dataset Guestbook
2910+
2911+
Removes the guestbook assignment for a dataset using `DELETE /api/datasets/{identifier}/guestbook`.
2912+
2913+
##### Example call:
2914+
2915+
```typescript
2916+
import { removeDatasetGuestbook } from '@iqss/dataverse-client-javascript'
2917+
2918+
const datasetIdOrPersistentId = 123
2919+
2920+
removeDatasetGuestbook.execute(datasetIdOrPersistentId).then(() => {
2921+
/* ... */
2922+
})
2923+
```
2924+
2925+
_See [use case](../src/guestbooks/domain/useCases/RemoveDatasetGuestbook.ts) implementation_.
2926+
28802927
## Access
28812928

2929+
### Access Read Use Cases
2930+
2931+
#### Get Signed Datafile Download URL
2932+
2933+
Returns a signed URL for downloading a single datafile using `GET /api/access/datafile/{fileId:.+}?signed=true`.
2934+
2935+
##### Example call:
2936+
2937+
```typescript
2938+
import { getSignedDatafileDownloadUrl } from '@iqss/dataverse-client-javascript'
2939+
2940+
getSignedDatafileDownloadUrl.execute(10).then((signedUrl: string) => {
2941+
/* ... */
2942+
})
2943+
```
2944+
2945+
_See [use case](../src/access/domain/useCases/GetSignedDatafileDownloadUrl.ts) implementation_.
2946+
2947+
#### Get Signed Datafiles Download URL
2948+
2949+
Returns a signed URL for downloading multiple datafiles using `GET /api/access/datafiles/{fileIds}?signed=true`.
2950+
2951+
##### Example call:
2952+
2953+
```typescript
2954+
import { getSignedDatafilesDownloadUrl } from '@iqss/dataverse-client-javascript'
2955+
2956+
getSignedDatafilesDownloadUrl.execute([10, 11]).then((signedUrl: string) => {
2957+
/* ... */
2958+
})
2959+
```
2960+
2961+
_See [use case](../src/access/domain/useCases/GetSignedDatafilesDownloadUrl.ts) implementation_.
2962+
2963+
#### Get Signed Dataset Download URL
2964+
2965+
Returns a signed URL for downloading a dataset using `GET /api/access/dataset/{id}?signed=true`.
2966+
2967+
##### Example call:
2968+
2969+
```typescript
2970+
import { getSignedDatasetDownloadUrl } from '@iqss/dataverse-client-javascript'
2971+
2972+
getSignedDatasetDownloadUrl.execute(10).then((signedUrl: string) => {
2973+
/* ... */
2974+
})
2975+
```
2976+
2977+
_See [use case](../src/access/domain/useCases/GetSignedDatasetDownloadUrl.ts) implementation_.
2978+
2979+
#### Get Signed Dataset Version Download URL
2980+
2981+
Returns a signed URL for downloading a dataset version using `GET /api/access/dataset/{id}/versions/{versionId}?signed=true`.
2982+
2983+
##### Example call:
2984+
2985+
```typescript
2986+
import { getSignedDatasetVersionDownloadUrl } from '@iqss/dataverse-client-javascript'
2987+
2988+
getSignedDatasetVersionDownloadUrl.execute(10, '1.0').then((signedUrl: string) => {
2989+
/* ... */
2990+
})
2991+
```
2992+
2993+
Signed URLs are only available to authenticated users. Guest users will receive an error when requesting `signed=true`.
2994+
2995+
_See [use case](../src/access/domain/useCases/GetSignedDatasetVersionDownloadUrl.ts) implementation_.
2996+
28822997
### Access Write Use Cases
28832998

28842999
#### Submit Guestbook For Datafile Download

src/access/domain/repositories/IAccessRepository.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
import { GuestbookResponseDTO } from '../dtos/GuestbookResponseDTO'
22

33
export interface IAccessRepository {
4+
getSignedDatafileDownloadUrl(fileId: number | string): Promise<string>
5+
6+
getSignedDatafilesDownloadUrl(fileIds: string | Array<number | string>): Promise<string>
7+
8+
getSignedDatasetDownloadUrl(datasetId: number | string): Promise<string>
9+
10+
getSignedDatasetVersionDownloadUrl(datasetId: number | string, versionId: string): Promise<string>
11+
412
submitGuestbookForDatafileDownload(
513
fileId: number | string,
614
guestbookResponse: GuestbookResponseDTO
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { UseCase } from '../../../core/domain/useCases/UseCase'
2+
import { IAccessRepository } from '../repositories/IAccessRepository'
3+
4+
export class GetSignedDatafileDownloadUrl implements UseCase<string> {
5+
constructor(private readonly accessRepository: IAccessRepository) {}
6+
7+
/**
8+
* Returns a signed URL for downloading a single datafile.
9+
*
10+
* @param {number | string} fileId - Datafile identifier (numeric id or persistent id).
11+
* @returns {Promise<string>} - Signed URL for the download.
12+
*/
13+
async execute(fileId: number | string): Promise<string> {
14+
return await this.accessRepository.getSignedDatafileDownloadUrl(fileId)
15+
}
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { UseCase } from '../../../core/domain/useCases/UseCase'
2+
import { IAccessRepository } from '../repositories/IAccessRepository'
3+
4+
export class GetSignedDatafilesDownloadUrl implements UseCase<string> {
5+
constructor(private readonly accessRepository: IAccessRepository) {}
6+
7+
/**
8+
* Returns a signed URL for downloading multiple datafiles.
9+
*
10+
* @param {string | Array<number | string>} fileIds - Comma-separated ids or array of datafile ids.
11+
* @returns {Promise<string>} - Signed URL for the download.
12+
*/
13+
async execute(fileIds: string | Array<number | string>): Promise<string> {
14+
return await this.accessRepository.getSignedDatafilesDownloadUrl(fileIds)
15+
}
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { UseCase } from '../../../core/domain/useCases/UseCase'
2+
import { IAccessRepository } from '../repositories/IAccessRepository'
3+
4+
export class GetSignedDatasetDownloadUrl implements UseCase<string> {
5+
constructor(private readonly accessRepository: IAccessRepository) {}
6+
7+
/**
8+
* Returns a signed URL for downloading all files in a dataset.
9+
*
10+
* @param {number | string} datasetId - Dataset identifier (numeric id or persistent id).
11+
* @returns {Promise<string>} - Signed URL for the download.
12+
*/
13+
async execute(datasetId: number | string): Promise<string> {
14+
return await this.accessRepository.getSignedDatasetDownloadUrl(datasetId)
15+
}
16+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { UseCase } from '../../../core/domain/useCases/UseCase'
2+
import { IAccessRepository } from '../repositories/IAccessRepository'
3+
4+
export class GetSignedDatasetVersionDownloadUrl implements UseCase<string> {
5+
constructor(private readonly accessRepository: IAccessRepository) {}
6+
7+
/**
8+
* Returns a signed URL for downloading all files in a specific dataset version.
9+
*
10+
* @param {number | string} datasetId - Dataset identifier (numeric id or persistent id).
11+
* @param {string} versionId - Dataset version id.
12+
* @returns {Promise<string>} - Signed URL for the download.
13+
*/
14+
async execute(datasetId: number | string, versionId: string): Promise<string> {
15+
return await this.accessRepository.getSignedDatasetVersionDownloadUrl(datasetId, versionId)
16+
}
17+
}

src/access/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
import { AccessRepository } from './infra/repositories/AccessRepository'
2+
import { GetSignedDatafileDownloadUrl } from './domain/useCases/GetSignedDatafileDownloadUrl'
3+
import { GetSignedDatafilesDownloadUrl } from './domain/useCases/GetSignedDatafilesDownloadUrl'
4+
import { GetSignedDatasetDownloadUrl } from './domain/useCases/GetSignedDatasetDownloadUrl'
5+
import { GetSignedDatasetVersionDownloadUrl } from './domain/useCases/GetSignedDatasetVersionDownloadUrl'
26
import { SubmitGuestbookForDatafileDownload } from './domain/useCases/SubmitGuestbookForDatafileDownload'
37
import { SubmitGuestbookForDatafilesDownload } from './domain/useCases/SubmitGuestbookForDatafilesDownload'
48
import { SubmitGuestbookForDatasetDownload } from './domain/useCases/SubmitGuestbookForDatasetDownload'
59
import { SubmitGuestbookForDatasetVersionDownload } from './domain/useCases/SubmitGuestbookForDatasetVersionDownload'
610

711
const accessRepository = new AccessRepository()
812

13+
const getSignedDatafileDownloadUrl = new GetSignedDatafileDownloadUrl(accessRepository)
14+
const getSignedDatafilesDownloadUrl = new GetSignedDatafilesDownloadUrl(accessRepository)
15+
const getSignedDatasetDownloadUrl = new GetSignedDatasetDownloadUrl(accessRepository)
16+
const getSignedDatasetVersionDownloadUrl = new GetSignedDatasetVersionDownloadUrl(accessRepository)
917
const submitGuestbookForDatafileDownload = new SubmitGuestbookForDatafileDownload(accessRepository)
1018
const submitGuestbookForDatafilesDownload = new SubmitGuestbookForDatafilesDownload(
1119
accessRepository
@@ -16,6 +24,10 @@ const submitGuestbookForDatasetVersionDownload = new SubmitGuestbookForDatasetVe
1624
)
1725

1826
export {
27+
getSignedDatafileDownloadUrl,
28+
getSignedDatafilesDownloadUrl,
29+
getSignedDatasetDownloadUrl,
30+
getSignedDatasetVersionDownloadUrl,
1931
submitGuestbookForDatafileDownload,
2032
submitGuestbookForDatafilesDownload,
2133
submitGuestbookForDatasetDownload,

src/access/infra/repositories/AccessRepository.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,61 @@ import { IAccessRepository } from '../../domain/repositories/IAccessRepository'
55
export class AccessRepository extends ApiRepository implements IAccessRepository {
66
private readonly accessResourceName = 'access'
77

8+
public async getSignedDatafileDownloadUrl(fileId: number | string): Promise<string> {
9+
const endpoint = this.buildApiEndpoint(`${this.accessResourceName}/datafile`, undefined, fileId)
10+
return this.doGet(endpoint, true, { signed: true })
11+
.then((response) => response.data.data.signedUrl)
12+
.catch((error) => {
13+
throw error
14+
})
15+
}
16+
17+
public async getSignedDatafilesDownloadUrl(
18+
fileIds: string | Array<number | string>
19+
): Promise<string> {
20+
return this.doGet(
21+
this.buildApiEndpoint(
22+
this.accessResourceName,
23+
`datafiles/${Array.isArray(fileIds) ? fileIds.join(',') : fileIds}`
24+
),
25+
true,
26+
{ signed: true }
27+
)
28+
.then((response) => response.data.data.signedUrl)
29+
.catch((error) => {
30+
throw error
31+
})
32+
}
33+
34+
public async getSignedDatasetDownloadUrl(datasetId: number | string): Promise<string> {
35+
const endpoint = this.buildApiEndpoint(
36+
`${this.accessResourceName}/dataset`,
37+
undefined,
38+
datasetId
39+
)
40+
return this.doGet(endpoint, true, { signed: true })
41+
.then((response) => response.data.data.signedUrl)
42+
.catch((error) => {
43+
throw error
44+
})
45+
}
46+
47+
public async getSignedDatasetVersionDownloadUrl(
48+
datasetId: number | string,
49+
versionId: string
50+
): Promise<string> {
51+
const endpoint = this.buildApiEndpoint(
52+
`${this.accessResourceName}/dataset`,
53+
`versions/${versionId}`,
54+
datasetId
55+
)
56+
return this.doGet(endpoint, true, { signed: true })
57+
.then((response) => response.data.data.signedUrl)
58+
.catch((error) => {
59+
throw error
60+
})
61+
}
62+
863
public async submitGuestbookForDatafileDownload(
964
fileId: number | string,
1065
guestbookResponse: GuestbookResponseDTO

src/guestbooks/domain/dtos/CreateGuestbookDTO.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,8 @@ export interface CreateGuestbookDTO {
2121
nameRequired: boolean
2222
institutionRequired: boolean
2323
positionRequired: boolean
24+
email: string
25+
institution: string
26+
position: string
2427
customQuestions: CreateGuestbookCustomQuestionDTO[]
2528
}

0 commit comments

Comments
 (0)