Skip to content
Merged
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
25 changes: 25 additions & 0 deletions docs/useCases.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ The different use cases currently available in the package are classified below,
- [Delete Current API Token](#delete-current-api-token)
- [Recreate Current API Token](#recreate-current-api-token)
- [Register User](#register-user)
- [Roles](#Roles)
- [Roles read use cases](#roles-read-use-cases)
- [Get User Selectable Roles](#get-user-selectable-roles)
- [Info](#Info)
- [Get Dataverse Backend Version](#get-dataverse-backend-version)
- [Get Maximum Embargo Duration In Months](#get-maximum-embargo-duration-in-months)
Expand Down Expand Up @@ -1842,6 +1845,28 @@ registerUser.execute(userDTO)

_See [use case](../src/users/domain/useCases/RegisterUser.ts) implementation_.

## Roles

### Get User Selectable Roles

Returns a [Role](../src/roles/domain/models/Role.ts) array that the calling user can use as filters when searching within their data.

##### Example call:

```typescript
import { getUserSelectableRoles } from '@iqss/dataverse-client-javascript'

/* ... */

getUserSelectableRoles.execute().then((roles: Role[]) => {
/* ... */
})

/* ... */
```

_See [use case](../src/roles/domain/useCases/GetUserSelectableRoles.ts) implementation_.

## Info

#### Get Dataverse Backend Version
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from './core'
export * from './info'
export * from './users'
export * from './roles'
export * from './auth'
export * from './datasets'
export * from './collections'
Expand Down
7 changes: 7 additions & 0 deletions src/roles/domain/models/Role.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface Role {
id: number
name: string
alias: string
description: string
permissions: string[]
}
5 changes: 5 additions & 0 deletions src/roles/domain/repositories/IRolesRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Role } from '../models/Role'

export interface IRolesRepository {
getUserSelectableRoles(): Promise<Role[]>
}
7 changes: 7 additions & 0 deletions src/roles/domain/repositories/transformers/RolePayload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface RolePayload {
id: number
name: string
alias: string
description: string
permissions: string[]
}
15 changes: 15 additions & 0 deletions src/roles/domain/repositories/transformers/roleTransformers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { AxiosResponse } from 'axios'
import { Role } from '../../models/Role'
import { RolePayload } from './RolePayload'

export const transformRolesUserSelectableResponseToRoles = (response: AxiosResponse): Role[] => {
const roleUserSelectablePayload = response.data.data as RolePayload[]

return roleUserSelectablePayload.map((role: RolePayload) => ({
id: role.id,
name: role.name,
alias: role.alias,
description: role.description,
permissions: role.permissions
}))
}
16 changes: 16 additions & 0 deletions src/roles/domain/useCases/GetUserSelectableRoles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { UseCase } from '../../../core/domain/useCases/UseCase'
import { Role } from '../models/Role'
import { IRolesRepository } from '../repositories/IRolesRepository'

export class GetUserSelectableRoles implements UseCase<Role[]> {
constructor(private readonly rolesRepository: IRolesRepository) {}

/**
* Returns the appropriate roles that the calling user can use as filters when searching within their data.
*
* @returns {Promise<Role[]>} - A promise that resolves to an array of Role instances.
*/
async execute(): Promise<Role[]> {
return (await this.rolesRepository.getUserSelectableRoles()) as Role[]
}
}
10 changes: 10 additions & 0 deletions src/roles/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { RolesRepository } from './infra/repositories/RolesRepository'
import { GetUserSelectableRoles } from './domain/useCases/GetUserSelectableRoles'

const rolesRepository = new RolesRepository()

const getUserSelectableRoles = new GetUserSelectableRoles(rolesRepository)

export { getUserSelectableRoles }

export { Role } from './domain/models/Role'
15 changes: 15 additions & 0 deletions src/roles/infra/repositories/RolesRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ApiRepository } from '../../../core/infra/repositories/ApiRepository'
import { IRolesRepository } from '../../domain/repositories/IRolesRepository'
import { Role } from '../../domain/models/Role'
import { transformRolesUserSelectableResponseToRoles } from '../../domain/repositories/transformers/roleTransformers'

export class RolesRepository extends ApiRepository implements IRolesRepository {
private readonly rolesResourceName: string = 'roles'
public async getUserSelectableRoles(): Promise<Role[]> {
return this.doGet(`/${this.rolesResourceName}/userSelectable`, true)
.then((response) => transformRolesUserSelectableResponseToRoles(response))
.catch((error) => {
throw error
})
}
}
23 changes: 23 additions & 0 deletions test/integration/roles/RolesRepository.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {
ApiConfig,
DataverseApiAuthMechanism
} from '../../../src/core/infra/repositories/ApiConfig'
import { TestConstants } from '../../testHelpers/TestConstants'
import { RolesRepository } from '../../../src/roles/infra/repositories/RolesRepository'
import { createSuperAdminRoleArray } from '../../testHelpers/roles/roleHelper'

describe('RolesRepository', () => {
const sut: RolesRepository = new RolesRepository()

describe('getUserSelectableRoles', () => {
test('should return list of selectable roles for authenticated user', async () => {
ApiConfig.init(
TestConstants.TEST_API_URL,
DataverseApiAuthMechanism.API_KEY,
process.env.TEST_API_KEY
)
const actual = await sut.getUserSelectableRoles()
expect(actual).toStrictEqual(createSuperAdminRoleArray())
})
})
})
116 changes: 116 additions & 0 deletions test/testHelpers/roles/roleHelper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { Role } from '../../../src/roles/domain/models/Role'

export const createRoleModel = (): Role => {
return {
id: 1,
name: 'admin',
alias: 'Admin',
description:
'A person who has all permissions for dataverses, datasets, and files, including approving requests for restricted data.',
permissions: [
'AddDataverse',
'AddDataset',
'ViewUnpublishedDataverse',
'ViewUnpublishedDataset'
]
}
}
export const createRoleModelArray = (count: number): Role[] => {
return Array.from({ length: count }, (_, index) => ({
id: index + 1,
name: `role${index + 1}`,
alias: `Role ${index + 1}`,
description: `Description for role ${index + 1}`,
permissions: [`Permission${index + 1}`]
}))
}

export const createSuperAdminRoleArray = (): Role[] => {
return [
{
alias: 'admin',
name: 'Admin',
permissions: [
'AddDataverse',
'AddDataset',
'ViewUnpublishedDataverse',
'ViewUnpublishedDataset',
'DownloadFile',
'EditDataverse',
'EditDataset',
'ManageDataversePermissions',
'ManageDatasetPermissions',
'ManageFilePermissions',
'PublishDataverse',
'PublishDataset',
'DeleteDataverse',
'DeleteDatasetDraft'
],
description:
'A person who has all permissions for dataverses, datasets, and files, including approving requests for restricted data.',
id: 1
},
{
alias: 'fileDownloader',
name: 'File Downloader',
permissions: ['DownloadFile'],
description: 'A person who can download a published file.',
id: 2
},
{
alias: 'fullContributor',
name: 'Dataverse + Dataset Creator',
permissions: ['AddDataverse', 'AddDataset'],
description: 'A person who can add subdataverses and datasets within a dataverse.',
id: 3
},
{
alias: 'dvContributor',
name: 'Dataverse Creator',
permissions: ['AddDataverse'],
description: 'A person who can add subdataverses within a dataverse.',
id: 4
},
{
alias: 'dsContributor',
name: 'Dataset Creator',
permissions: ['AddDataset'],
description: 'A person who can add datasets within a dataverse.',
id: 5
},
{
alias: 'contributor',
name: 'Contributor',
permissions: ['ViewUnpublishedDataset', 'DownloadFile', 'EditDataset', 'DeleteDatasetDraft'],
description:
'For datasets, a person who can edit License + Terms, and then submit them for review.',
id: 6
},
{
alias: 'curator',
name: 'Curator',
permissions: [
'AddDataverse',
'AddDataset',
'ViewUnpublishedDataverse',
'ViewUnpublishedDataset',
'DownloadFile',
'EditDataset',
'ManageDatasetPermissions',
'ManageFilePermissions',
'PublishDataset',
'DeleteDatasetDraft'
],
description:
'For datasets, a person who can edit License + Terms, edit Permissions, and publish datasets.',
id: 7
},
{
alias: 'member',
name: 'Member',
permissions: ['ViewUnpublishedDataverse', 'ViewUnpublishedDataset', 'DownloadFile'],
description: 'A person who can view both unpublished dataverses and datasets.',
id: 8
}
]
}
25 changes: 25 additions & 0 deletions test/unit/roles/GetUserSelectableRoles.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ReadError } from '../../../src'
import { IRolesRepository } from '../../../src/roles/domain/repositories/IRolesRepository'
import { createRoleModelArray } from '../../testHelpers/roles/roleHelper'
import { GetUserSelectableRoles } from '../../../src/roles/domain/useCases/GetUserSelectableRoles'

describe('execute', () => {
test('should return roles array on repository success', async () => {
const rolesRepositoryStub: IRolesRepository = {} as IRolesRepository
const testRoles = createRoleModelArray(5)
rolesRepositoryStub.getUserSelectableRoles = jest.fn().mockResolvedValue(testRoles)
const sut = new GetUserSelectableRoles(rolesRepositoryStub)

const actual = await sut.execute()

expect(actual).toEqual(testRoles)
})

test('should return error result on repository error', async () => {
const rolesRepositoryStub: IRolesRepository = {} as IRolesRepository
rolesRepositoryStub.getUserSelectableRoles = jest.fn().mockRejectedValue(new ReadError())
const sut = new GetUserSelectableRoles(rolesRepositoryStub)

await expect(sut.execute()).rejects.toThrow(ReadError)
})
})