Skip to content

Commit 205715c

Browse files
authored
Merge pull request #376 from IQSS/365-set-dataset-license-and-custom-terms-use-case
Set Dataset License and Custom Terms Use Case
2 parents 421af81 + 77f854a commit 205715c

File tree

10 files changed

+349
-2
lines changed

10 files changed

+349
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel
88

99
### Added
1010

11+
- Datasets: Added `updateDatasetLicense` use case and repository method to support Dataverse endpoint `PUT /datasets/{id}/license`, for updating dataset license or custom terms
1112
- New Use Case: [Get Collections For Linking Use Case](./docs/useCases.md#get-collections-for-linking).
1213
- New Use Case: [Create a Dataset Template](./docs/useCases.md#create-a-dataset-template) under Collections.
1314

docs/useCases.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ The different use cases currently available in the package are classified below,
4646
- [Datasets write use cases](#datasets-write-use-cases)
4747
- [Create a Dataset](#create-a-dataset)
4848
- [Update a Dataset](#update-a-dataset)
49+
- [Update a Dataset License](#update-a-dataset-license)
4950
- [Publish a Dataset](#publish-a-dataset)
5051
- [Deaccession a Dataset](#deaccession-a-dataset)
5152
- [Delete a Draft Dataset](#delete-a-draft-dataset)
@@ -1079,6 +1080,43 @@ updateDataset.execute(datasetId, datasetDTO)
10791080

10801081
_See [use case](../src/datasets/domain/useCases/UpdateDataset.ts) implementation_.
10811082

1083+
#### Update a Dataset License
1084+
1085+
Updates the license of a dataset by applying it to the draft version. If no draft exists, a new one is automatically created by the API. Supports predefined licenses (by name) or custom terms of use and access.
1086+
1087+
##### Example calls:
1088+
1089+
```typescript
1090+
import {
1091+
updateDatasetLicense,
1092+
DatasetLicenseUpdateRequest
1093+
} from '@iqss/dataverse-client-javascript'
1094+
1095+
/* ... */
1096+
1097+
const datasetId = 1
1098+
1099+
const predefinedPayload: DatasetLicenseUpdateRequest = { name: 'CC BY 4.0' }
1100+
await updateDatasetLicense.execute(datasetId, predefinedPayload)
1101+
1102+
const customPayload: DatasetLicenseUpdateRequest = {
1103+
customTerms: {
1104+
termsOfUse: 'Your terms of use',
1105+
confidentialityDeclaration: 'Your confidentiality declaration',
1106+
specialPermissions: 'Your special permissions',
1107+
restrictions: 'Your restrictions',
1108+
citationRequirements: 'Your citation requirements',
1109+
depositorRequirements: 'Your depositor requirements',
1110+
conditions: 'Your conditions',
1111+
disclaimer: 'Your disclaimer'
1112+
}
1113+
}
1114+
1115+
updateDatasetLicense.execute(datasetId, customPayload)
1116+
```
1117+
1118+
_See [use case](../src/datasets/domain/useCases/UpdateDatasetLicense.ts) implementation_.
1119+
10821120
The `datasetId` parameter can be a string, for persistent identifiers, or a number, for numeric identifiers.
10831121

10841122
#### Publish a Dataset
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { CustomTerms } from '../models/Dataset'
2+
3+
export interface DatasetLicenseUpdateRequest {
4+
name?: string
5+
customTerms?: CustomTerms
6+
}

src/datasets/domain/repositories/IDatasetsRepository.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { CitationFormat } from '../models/CitationFormat'
1414
import { FormattedCitation } from '../models/FormattedCitation'
1515
import { DatasetTemplate } from '../models/DatasetTemplate'
1616
import { DatasetType } from '../models/DatasetType'
17+
import { DatasetLicenseUpdateRequest } from '../dtos/DatasetLicenseUpdateRequest'
1718
import { DatasetTypeDTO } from '../dtos/DatasetTypeDTO'
1819

1920
export interface IDatasetsRepository {
@@ -95,4 +96,8 @@ export interface IDatasetsRepository {
9596
licenses: string[]
9697
): Promise<void>
9798
deleteDatasetType(datasetTypeId: number): Promise<void>
99+
updateDatasetLicense(
100+
datasetId: number | string,
101+
payload: DatasetLicenseUpdateRequest
102+
): Promise<void>
98103
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { UseCase } from '../../../core/domain/useCases/UseCase'
2+
import { IDatasetsRepository } from '../repositories/IDatasetsRepository'
3+
import { DatasetLicenseUpdateRequest } from '../dtos/DatasetLicenseUpdateRequest'
4+
5+
export class UpdateDatasetLicense implements UseCase<void> {
6+
private readonly datasetsRepository: IDatasetsRepository
7+
8+
constructor(datasetsRepository: IDatasetsRepository) {
9+
this.datasetsRepository = datasetsRepository
10+
}
11+
12+
/**
13+
* Updates the license of a dataset by applying it to the draft version. If no draft exists, a new one is created by the API.
14+
* Supports either predefined license by name or custom terms of use and access.
15+
*
16+
* @param {number | string} datasetId - The dataset identifier, which can be a string (for persistent identifiers), or a number (for numeric identifiers).
17+
* @param {DatasetLicenseUpdateRequest} payload - The payload containing the license name or custom terms of use and access.
18+
* @returns {Promise<void>} - This method does not return anything upon successful completion.
19+
*/
20+
async execute(datasetId: number | string, payload: DatasetLicenseUpdateRequest): Promise<void> {
21+
return this.datasetsRepository.updateDatasetLicense(datasetId, payload)
22+
}
23+
}

src/datasets/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { SetAvailableLicensesForDatasetType } from './domain/useCases/SetAvailab
3232
import { DeleteDatasetType } from './domain/useCases/DeleteDatasetType'
3333
import { GetDatasetCitationInOtherFormats } from './domain/useCases/GetDatasetCitationInOtherFormats'
3434
import { GetDatasetTemplates } from './domain/useCases/GetDatasetTemplates'
35+
import { UpdateDatasetLicense } from './domain/useCases/UpdateDatasetLicense'
3536

3637
const datasetsRepository = new DatasetsRepository()
3738

@@ -80,6 +81,7 @@ const setAvailableLicensesForDatasetType = new SetAvailableLicensesForDatasetTyp
8081
const deleteDatasetType = new DeleteDatasetType(datasetsRepository)
8182
const getDatasetCitationInOtherFormats = new GetDatasetCitationInOtherFormats(datasetsRepository)
8283
const getDatasetTemplates = new GetDatasetTemplates(datasetsRepository)
84+
const updateDatasetLicense = new UpdateDatasetLicense(datasetsRepository)
8385

8486
export {
8587
getDataset,
@@ -109,7 +111,8 @@ export {
109111
addDatasetType,
110112
linkDatasetTypeWithMetadataBlocks,
111113
setAvailableLicensesForDatasetType,
112-
deleteDatasetType
114+
deleteDatasetType,
115+
updateDatasetLicense
113116
}
114117
export { DatasetNotNumberedVersion } from './domain/models/DatasetNotNumberedVersion'
115118
export { DatasetUserPermissions } from './domain/models/DatasetUserPermissions'
@@ -136,6 +139,7 @@ export {
136139
DatasetMetadataBlockValuesDTO,
137140
DatasetMetadataChildFieldValueDTO
138141
} from './domain/dtos/DatasetDTO'
142+
export { DatasetLicenseUpdateRequest } from './domain/dtos/DatasetLicenseUpdateRequest'
139143
export { DatasetDeaccessionDTO } from './domain/dtos/DatasetDeaccessionDTO'
140144
export { CreatedDatasetIdentifiers } from './domain/models/CreatedDatasetIdentifiers'
141145
export { VersionUpdateType } from './domain/models/Dataset'

src/datasets/infra/repositories/DatasetsRepository.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { DatasetTemplate } from '../../domain/models/DatasetTemplate'
2929
import { DatasetTemplatePayload } from './transformers/DatasetTemplatePayload'
3030
import { transformDatasetTemplatePayloadToDatasetTemplate } from './transformers/datasetTemplateTransformers'
3131
import { DatasetType } from '../../domain/models/DatasetType'
32+
import { DatasetLicenseUpdateRequest } from '../../domain/dtos/DatasetLicenseUpdateRequest'
3233
import { DatasetTypeDTO } from '../../domain/dtos/DatasetTypeDTO'
3334

3435
export interface GetAllDatasetPreviewsQueryParams {
@@ -484,4 +485,18 @@ export class DatasetsRepository extends ApiRepository implements IDatasetsReposi
484485
throw error
485486
})
486487
}
488+
489+
public async updateDatasetLicense(
490+
datasetId: number | string,
491+
payload: DatasetLicenseUpdateRequest
492+
): Promise<void> {
493+
return this.doPut(
494+
this.buildApiEndpoint(this.datasetsResourceName, 'license', datasetId),
495+
payload
496+
)
497+
.then(() => undefined)
498+
.catch((error) => {
499+
throw error
500+
})
501+
}
487502
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import {
2+
ApiConfig,
3+
createDataset,
4+
getDataset,
5+
publishDataset,
6+
updateDatasetLicense,
7+
DatasetLicenseUpdateRequest
8+
} from '../../../src'
9+
import { TestConstants } from '../../testHelpers/TestConstants'
10+
import { DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ApiConfig'
11+
import {
12+
waitForNoLocks,
13+
deleteUnpublishedDatasetViaApi,
14+
deletePublishedDatasetViaApi
15+
} from '../../testHelpers/datasets/datasetHelper'
16+
import { DatasetNotNumberedVersion, VersionUpdateType } from '../../../src/datasets'
17+
18+
describe('execute', () => {
19+
beforeEach(async () => {
20+
ApiConfig.init(
21+
TestConstants.TEST_API_URL,
22+
DataverseApiAuthMechanism.API_KEY,
23+
process.env.TEST_API_KEY
24+
)
25+
})
26+
27+
test('should update the license of a draft dataset (predefined by name)', async () => {
28+
const created = await createDataset.execute(TestConstants.TEST_NEW_DATASET_DTO)
29+
30+
const payload: DatasetLicenseUpdateRequest = { name: 'CC BY 4.0' }
31+
const response = await updateDatasetLicense.execute(created.numericId, payload)
32+
33+
expect(response).toBeUndefined()
34+
35+
const after = await getDataset.execute(
36+
created.numericId,
37+
DatasetNotNumberedVersion.DRAFT,
38+
false,
39+
false
40+
)
41+
expect(after.license?.name).toBe('CC BY 4.0')
42+
43+
await deleteUnpublishedDatasetViaApi(created.numericId)
44+
})
45+
46+
test('should update the license of a published dataset (custom terms creates draft)', async () => {
47+
const created = await createDataset.execute(TestConstants.TEST_NEW_DATASET_DTO)
48+
49+
await publishDataset.execute(created.numericId, VersionUpdateType.MAJOR)
50+
await waitForNoLocks(created.numericId, 10)
51+
52+
const payload: DatasetLicenseUpdateRequest = {
53+
customTerms: {
54+
termsOfUse: 'Updated terms of use (functional test)'
55+
}
56+
}
57+
const response = await updateDatasetLicense.execute(created.numericId, payload)
58+
59+
expect(response).toBeUndefined()
60+
61+
const draft = await getDataset.execute(
62+
created.numericId,
63+
DatasetNotNumberedVersion.DRAFT,
64+
false,
65+
false
66+
)
67+
expect(draft.license).toBeUndefined()
68+
expect(draft.termsOfUse.customTerms?.termsOfUse).toBe('Updated terms of use (functional test)')
69+
70+
await deletePublishedDatasetViaApi(created.persistentId)
71+
})
72+
})

0 commit comments

Comments
 (0)