Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel

### Added

- Datasets: Added `updateDatasetLicense` use case and repository method to support Dataverse endpoint `PUT /datasets/{id}/license`, for updating dataset license or custom terms

### Changed

### Fixed
Expand Down
38 changes: 38 additions & 0 deletions docs/useCases.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ The different use cases currently available in the package are classified below,
- [Datasets write use cases](#datasets-write-use-cases)
- [Create a Dataset](#create-a-dataset)
- [Update a Dataset](#update-a-dataset)
- [Update a Dataset License](#update-a-dataset-license)
- [Publish a Dataset](#publish-a-dataset)
- [Deaccession a Dataset](#deaccession-a-dataset)
- [Delete a Draft Dataset](#delete-a-draft-dataset)
Expand Down Expand Up @@ -977,6 +978,43 @@ updateDataset.execute(datasetId, datasetDTO)

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

#### Update a Dataset License

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.

##### Example calls:

```typescript
import {
updateDatasetLicense,
DatasetLicenseUpdateRequest
} from '@iqss/dataverse-client-javascript'

/* ... */

const datasetId = 1

const predefinedPayload: DatasetLicenseUpdateRequest = { name: 'CC BY 4.0' }
await updateDatasetLicense.execute(datasetId, predefinedPayload)

const customPayload: DatasetLicenseUpdateRequest = {
customTerms: {
termsOfUse: 'Your terms of use',
confidentialityDeclaration: 'Your confidentiality declaration',
specialPermissions: 'Your special permissions',
restrictions: 'Your restrictions',
citationRequirements: 'Your citation requirements',
depositorRequirements: 'Your depositor requirements',
conditions: 'Your conditions',
disclaimer: 'Your disclaimer'
}
}

updateDatasetLicense.execute(datasetId, customPayload)
```

_See [use case](../src/datasets/domain/useCases/UpdateDatasetLicense.ts) implementation_.

The `datasetId` parameter can be a string, for persistent identifiers, or a number, for numeric identifiers.

#### Publish a Dataset
Expand Down
6 changes: 6 additions & 0 deletions src/datasets/domain/dtos/DatasetLicenseUpdateRequest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { CustomTerms } from '../models/Dataset'

export interface DatasetLicenseUpdateRequest {
name?: string
customTerms?: CustomTerms
}
5 changes: 5 additions & 0 deletions src/datasets/domain/repositories/IDatasetsRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { CitationFormat } from '../models/CitationFormat'
import { FormattedCitation } from '../models/FormattedCitation'
import { DatasetTemplate } from '../models/DatasetTemplate'
import { DatasetType } from '../models/DatasetType'
import { DatasetLicenseUpdateRequest } from '../dtos/DatasetLicenseUpdateRequest'

export interface IDatasetsRepository {
getDataset(
Expand Down Expand Up @@ -89,4 +90,8 @@ export interface IDatasetsRepository {
licenses: string[]
): Promise<void>
deleteDatasetType(datasetTypeId: number): Promise<void>
updateDatasetLicense(
datasetId: number | string,
payload: DatasetLicenseUpdateRequest
): Promise<void>
}
23 changes: 23 additions & 0 deletions src/datasets/domain/useCases/UpdateDatasetLicense.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { UseCase } from '../../../core/domain/useCases/UseCase'
import { IDatasetsRepository } from '../repositories/IDatasetsRepository'
import { DatasetLicenseUpdateRequest } from '../dtos/DatasetLicenseUpdateRequest'

export class UpdateDatasetLicense implements UseCase<void> {
private readonly datasetsRepository: IDatasetsRepository

constructor(datasetsRepository: IDatasetsRepository) {
this.datasetsRepository = datasetsRepository
}

/**
* 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.
* Supports either predefined license by name or custom terms of use and access.
*
* @param {number | string} datasetId - The dataset identifier, which can be a string (for persistent identifiers), or a number (for numeric identifiers).
* @param {DatasetLicenseUpdateRequest} payload - The payload containing the license name or custom terms of use and access.
* @returns {Promise<void>} - This method does not return anything upon successful completion.
*/
async execute(datasetId: number | string, payload: DatasetLicenseUpdateRequest): Promise<void> {
return this.datasetsRepository.updateDatasetLicense(datasetId, payload)
}
}
6 changes: 5 additions & 1 deletion src/datasets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { SetAvailableLicensesForDatasetType } from './domain/useCases/SetAvailab
import { DeleteDatasetType } from './domain/useCases/DeleteDatasetType'
import { GetDatasetCitationInOtherFormats } from './domain/useCases/GetDatasetCitationInOtherFormats'
import { GetDatasetTemplates } from './domain/useCases/GetDatasetTemplates'
import { UpdateDatasetLicense } from './domain/useCases/UpdateDatasetLicense'

const datasetsRepository = new DatasetsRepository()

Expand Down Expand Up @@ -80,6 +81,7 @@ const setAvailableLicensesForDatasetType = new SetAvailableLicensesForDatasetTyp
const deleteDatasetType = new DeleteDatasetType(datasetsRepository)
const getDatasetCitationInOtherFormats = new GetDatasetCitationInOtherFormats(datasetsRepository)
const getDatasetTemplates = new GetDatasetTemplates(datasetsRepository)
const updateDatasetLicense = new UpdateDatasetLicense(datasetsRepository)

export {
getDataset,
Expand Down Expand Up @@ -109,7 +111,8 @@ export {
addDatasetType,
linkDatasetTypeWithMetadataBlocks,
setAvailableLicensesForDatasetType,
deleteDatasetType
deleteDatasetType,
updateDatasetLicense
}
export { DatasetNotNumberedVersion } from './domain/models/DatasetNotNumberedVersion'
export { DatasetUserPermissions } from './domain/models/DatasetUserPermissions'
Expand All @@ -136,6 +139,7 @@ export {
DatasetMetadataBlockValuesDTO,
DatasetMetadataChildFieldValueDTO
} from './domain/dtos/DatasetDTO'
export { DatasetLicenseUpdateRequest } from './domain/dtos/DatasetLicenseUpdateRequest'
export { DatasetDeaccessionDTO } from './domain/dtos/DatasetDeaccessionDTO'
export { CreatedDatasetIdentifiers } from './domain/models/CreatedDatasetIdentifiers'
export { VersionUpdateType } from './domain/models/Dataset'
Expand Down
15 changes: 15 additions & 0 deletions src/datasets/infra/repositories/DatasetsRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { DatasetTemplate } from '../../domain/models/DatasetTemplate'
import { DatasetTemplatePayload } from './transformers/DatasetTemplatePayload'
import { transformDatasetTemplatePayloadToDatasetTemplate } from './transformers/datasetTemplateTransformers'
import { DatasetType } from '../../domain/models/DatasetType'
import { DatasetLicenseUpdateRequest } from '../../domain/dtos/DatasetLicenseUpdateRequest'

export interface GetAllDatasetPreviewsQueryParams {
per_page?: number
Expand Down Expand Up @@ -448,4 +449,18 @@ export class DatasetsRepository extends ApiRepository implements IDatasetsReposi
throw error
})
}

public async updateDatasetLicense(
datasetId: number | string,
payload: DatasetLicenseUpdateRequest
): Promise<void> {
return this.doPut(
this.buildApiEndpoint(this.datasetsResourceName, 'license', datasetId),
payload
)
.then(() => undefined)
.catch((error) => {
throw error
})
}
}
72 changes: 72 additions & 0 deletions test/functional/datasets/UpdateDatasetLicense.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import {
ApiConfig,
createDataset,
getDataset,
publishDataset,
updateDatasetLicense,
DatasetLicenseUpdateRequest
} from '../../../src'
import { TestConstants } from '../../testHelpers/TestConstants'
import { DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ApiConfig'
import {
waitForNoLocks,
deleteUnpublishedDatasetViaApi,
deletePublishedDatasetViaApi
} from '../../testHelpers/datasets/datasetHelper'
import { DatasetNotNumberedVersion, VersionUpdateType } from '../../../src/datasets'

describe('execute', () => {
beforeEach(async () => {
ApiConfig.init(
TestConstants.TEST_API_URL,
DataverseApiAuthMechanism.API_KEY,
process.env.TEST_API_KEY
)
})

test('should update the license of a draft dataset (predefined by name)', async () => {
const created = await createDataset.execute(TestConstants.TEST_NEW_DATASET_DTO)

const payload: DatasetLicenseUpdateRequest = { name: 'CC BY 4.0' }
const response = await updateDatasetLicense.execute(created.numericId, payload)

expect(response).toBeUndefined()

const after = await getDataset.execute(
created.numericId,
DatasetNotNumberedVersion.DRAFT,
false,
false
)
expect(after.license?.name).toBe('CC BY 4.0')

await deleteUnpublishedDatasetViaApi(created.numericId)
})

test('should update the license of a published dataset (custom terms creates draft)', async () => {
const created = await createDataset.execute(TestConstants.TEST_NEW_DATASET_DTO)

await publishDataset.execute(created.numericId, VersionUpdateType.MAJOR)
await waitForNoLocks(created.numericId, 10)

const payload: DatasetLicenseUpdateRequest = {
customTerms: {
termsOfUse: 'Updated terms of use (functional test)'
}
}
const response = await updateDatasetLicense.execute(created.numericId, payload)

expect(response).toBeUndefined()

const draft = await getDataset.execute(
created.numericId,
DatasetNotNumberedVersion.DRAFT,
false,
false
)
expect(draft.license).toBeUndefined()
expect(draft.termsOfUse.customTerms?.termsOfUse).toBe('Updated terms of use (functional test)')

await deletePublishedDatasetViaApi(created.persistentId)
})
})
Loading
Loading