Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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 '../../domain/models/Dataset'
Comment thread
ChengShi-1 marked this conversation as resolved.
Outdated

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