Skip to content

Commit 75c2f56

Browse files
authored
Merge pull request #175 from IQSS/165-get-collection-user-permissions
Adds GetCollectionUserPermissions use case
2 parents 0ea8141 + 3f8ee0a commit 75c2f56

File tree

13 files changed

+303
-1
lines changed

13 files changed

+303
-1
lines changed

docs/useCases.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ The different use cases currently available in the package are classified below,
1212
- [Collections read use cases](#collections-read-use-cases)
1313
- [Get a Collection](#get-a-collection)
1414
- [Get Collection Facets](#get-collection-facets)
15+
- [Get User Permissions on a Collection](#get-user-permissions-on-a-collection)
1516
- [Collections write use cases](#collections-write-use-cases)
1617
- [Create a Collection](#create-a-collection)
1718
- [Datasets](#Datasets)
@@ -129,6 +130,34 @@ The `collectionIdOrAlias` is a generic collection identifier, which can be eithe
129130

130131
If no collection identifier is specified, the default collection identifier; `root` will be used. If you want to search for a different collection, you must add the collection identifier as a parameter in the use case call.
131132

133+
#### Get User Permissions on a Collection
134+
135+
Returns an instance of [CollectionUserPermissions](../src/collections/domain/models/CollectionUserPermissions.ts) that includes the permissions that the calling user has on a particular Collection.
136+
137+
##### Example call:
138+
139+
```typescript
140+
import { getCollectionUserPermissions } from '@iqss/dataverse-client-javascript'
141+
142+
/* ... */
143+
144+
const collectionIdOrAlias = 12345
145+
146+
getCollectionUserPermissions
147+
.execute(collectionIdOrAlias)
148+
.then((permissions: CollectionUserPermissions) => {
149+
/* ... */
150+
})
151+
152+
/* ... */
153+
```
154+
155+
_See [use case](../src/collections/domain/useCases/GetCollectionUserPermissions.ts) implementation_.
156+
157+
The `collectionIdOrAlias` is a generic collection identifier, which can be either a string (for queries by CollectionAlias), or a number (for queries by CollectionId).
158+
159+
If no collection identifier is specified, the default collection identifier; `root` will be used. If you want to search for a different collection, you must add the collection identifier as a parameter in the use case call.
160+
132161
### Collections Write Use Cases
133162

134163
#### Create a Collection
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export interface CollectionUserPermissions {
2+
canAddCollection: boolean
3+
canAddDataset: boolean
4+
canViewUnpublishedCollection: boolean
5+
canEditCollection: boolean
6+
canManageCollectionPermissions: boolean
7+
canPublishCollection: boolean
8+
canDeleteCollection: boolean
9+
}

src/collections/domain/repositories/ICollectionsRepository.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { CollectionDTO } from '../dtos/CollectionDTO'
22
import { Collection } from '../models/Collection'
3+
import { CollectionUserPermissions } from '../models/CollectionUserPermissions'
34

45
export interface ICollectionsRepository {
56
getCollection(collectionIdOrAlias: number | string): Promise<Collection>
@@ -8,4 +9,7 @@ export interface ICollectionsRepository {
89
parentCollectionId: number | string
910
): Promise<number>
1011
getCollectionFacets(collectionIdOrAlias: number | string): Promise<string[]>
12+
getCollectionUserPermissions(
13+
collectionIdOrAlias: number | string
14+
): Promise<CollectionUserPermissions>
1115
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { UseCase } from '../../../core/domain/useCases/UseCase'
2+
import { CollectionUserPermissions } from '../models/CollectionUserPermissions'
3+
import { ICollectionsRepository } from '../repositories/ICollectionsRepository'
4+
5+
export class GetCollectionUserPermissions implements UseCase<CollectionUserPermissions> {
6+
private collectionsRepository: ICollectionsRepository
7+
8+
constructor(collectionsRepository: ICollectionsRepository) {
9+
this.collectionsRepository = collectionsRepository
10+
}
11+
12+
/**
13+
* Returns an instance of CollectionUserPermissions that includes the permissions that the calling user has on a particular Collection.
14+
*
15+
* @param {number | string} [collectionIdOrAlias = 'root'] - A generic collection identifier, which can be either a string (for queries by CollectionAlias), or a number (for queries by CollectionId)
16+
* If this parameter is not set, the default value is: 'root'
17+
* @returns {Promise<CollectionUserPermissions>}
18+
*/
19+
async execute(collectionIdOrAlias: number | string): Promise<CollectionUserPermissions> {
20+
return await this.collectionsRepository.getCollectionUserPermissions(collectionIdOrAlias)
21+
}
22+
}

src/collections/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { CreateCollection } from './domain/useCases/CreateCollection'
22
import { GetCollection } from './domain/useCases/GetCollection'
33
import { GetCollectionFacets } from './domain/useCases/GetCollectionFacets'
4+
import { GetCollectionUserPermissions } from './domain/useCases/GetCollectionUserPermissions'
45

56
import { CollectionsRepository } from './infra/repositories/CollectionsRepository'
67

@@ -9,7 +10,9 @@ const collectionsRepository = new CollectionsRepository()
910
const getCollection = new GetCollection(collectionsRepository)
1011
const createCollection = new CreateCollection(collectionsRepository)
1112
const getCollectionFacets = new GetCollectionFacets(collectionsRepository)
13+
const getCollectionUserPermissions = new GetCollectionUserPermissions(collectionsRepository)
1214

13-
export { getCollection, createCollection, getCollectionFacets }
15+
export { getCollection, createCollection, getCollectionFacets, getCollectionUserPermissions }
1416
export { Collection, CollectionInputLevel } from './domain/models/Collection'
17+
export { CollectionUserPermissions } from './domain/models/CollectionUserPermissions'
1518
export { CollectionDTO, CollectionInputLevelDTO } from './domain/dtos/CollectionDTO'

src/collections/infra/repositories/CollectionsRepository.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { ICollectionsRepository } from '../../domain/repositories/ICollectionsRe
33
import { transformCollectionResponseToCollection } from './transformers/collectionTransformers'
44
import { Collection, ROOT_COLLECTION_ALIAS } from '../../domain/models/Collection'
55
import { CollectionDTO } from '../../domain/dtos/CollectionDTO'
6+
import { CollectionUserPermissions } from '../../domain/models/CollectionUserPermissions'
7+
import { transformCollectionUserPermissionsResponseToCollectionUserPermissions } from './transformers/collectionUserPermissionsTransformers'
68

79
export interface NewCollectionRequestPayload {
810
alias: string
@@ -86,4 +88,19 @@ export class CollectionsRepository extends ApiRepository implements ICollections
8688
throw error
8789
})
8890
}
91+
92+
public async getCollectionUserPermissions(
93+
collectionIdOrAlias: number | string
94+
): Promise<CollectionUserPermissions> {
95+
return this.doGet(
96+
`/${this.collectionsResourceName}/${collectionIdOrAlias}/userPermissions`,
97+
true
98+
)
99+
.then((response) =>
100+
transformCollectionUserPermissionsResponseToCollectionUserPermissions(response)
101+
)
102+
.catch((error) => {
103+
throw error
104+
})
105+
}
89106
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export interface CollectionUserPermissionsPayload {
2+
canAddDataverse: boolean
3+
canAddDataset: boolean
4+
canViewUnpublishedDataverse: boolean
5+
canEditDataverse: boolean
6+
canManageDataversePermissions: boolean
7+
canPublishDataverse: boolean
8+
canDeleteDataverse: boolean
9+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { AxiosResponse } from 'axios'
2+
import { CollectionUserPermissions } from '../../../domain/models/CollectionUserPermissions'
3+
4+
export const transformCollectionUserPermissionsResponseToCollectionUserPermissions = (
5+
response: AxiosResponse
6+
): CollectionUserPermissions => {
7+
const collectionUserPermissionsPayload = response.data.data
8+
return {
9+
canAddCollection: collectionUserPermissionsPayload.canAddDataverse,
10+
canAddDataset: collectionUserPermissionsPayload.canAddDataset,
11+
canViewUnpublishedCollection: collectionUserPermissionsPayload.canViewUnpublishedDataverse,
12+
canEditCollection: collectionUserPermissionsPayload.canEditDataverse,
13+
canManageCollectionPermissions: collectionUserPermissionsPayload.canManageDataversePermissions,
14+
canPublishCollection: collectionUserPermissionsPayload.canPublishDataverse,
15+
canDeleteCollection: collectionUserPermissionsPayload.canDeleteDataverse
16+
}
17+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import {
2+
ApiConfig,
3+
CollectionUserPermissions,
4+
ReadError,
5+
getCollectionUserPermissions
6+
} from '../../../src'
7+
import { TestConstants } from '../../testHelpers/TestConstants'
8+
import { DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ApiConfig'
9+
import { ROOT_COLLECTION_ALIAS } from '../../../src/collections/domain/models/Collection'
10+
11+
describe('execute', () => {
12+
beforeEach(async () => {
13+
ApiConfig.init(
14+
TestConstants.TEST_API_URL,
15+
DataverseApiAuthMechanism.API_KEY,
16+
process.env.TEST_API_KEY
17+
)
18+
})
19+
20+
test('should return user permissions when a valid collection alias is provided', async () => {
21+
let actual: CollectionUserPermissions
22+
try {
23+
actual = await getCollectionUserPermissions.execute(ROOT_COLLECTION_ALIAS)
24+
} catch (error) {
25+
throw new Error('Permissions should be retrieved')
26+
} finally {
27+
expect(actual.canAddDataset).toBe(true)
28+
expect(actual.canAddCollection).toBe(true)
29+
expect(actual.canDeleteCollection).toBe(true)
30+
expect(actual.canEditCollection).toBe(true)
31+
expect(actual.canManageCollectionPermissions).toBe(true)
32+
expect(actual.canPublishCollection).toBe(true)
33+
expect(actual.canViewUnpublishedCollection).toBe(true)
34+
}
35+
})
36+
37+
test('should throw an error when collection does not exist', async () => {
38+
expect.assertions(2)
39+
let readError: ReadError
40+
try {
41+
await getCollectionUserPermissions.execute(TestConstants.TEST_DUMMY_COLLECTION_ID)
42+
throw new Error('Use case should throw an error')
43+
} catch (error) {
44+
readError = error
45+
} finally {
46+
expect(readError).toBeInstanceOf(ReadError)
47+
expect(readError.message).toEqual(
48+
`There was an error when reading the resource. Reason was: [404] Can't find dataverse with identifier='${TestConstants.TEST_DUMMY_COLLECTION_ID}'`
49+
)
50+
}
51+
})
52+
})

test/integration/collections/CollectionsRepository.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,4 +165,29 @@ describe('CollectionsRepository', () => {
165165
).rejects.toThrow(expectedError)
166166
})
167167
})
168+
169+
describe('getCollectionUserPermissions', () => {
170+
test('should return user permissions', async () => {
171+
const actual = await sut.getCollectionUserPermissions('root')
172+
expect(actual.canAddDataset).toBe(true)
173+
expect(actual.canAddCollection).toBe(true)
174+
expect(actual.canDeleteCollection).toBe(true)
175+
expect(actual.canEditCollection).toBe(true)
176+
expect(actual.canManageCollectionPermissions).toBe(true)
177+
expect(actual.canPublishCollection).toBe(true)
178+
expect(actual.canViewUnpublishedCollection).toBe(true)
179+
})
180+
181+
test('should return error when collection does not exist', async () => {
182+
const nonExistentCollectionAlias = 'nonExistentCollection'
183+
184+
const expectedError = new ReadError(
185+
`[404] Can't find dataverse with identifier='${nonExistentCollectionAlias}'`
186+
)
187+
188+
await expect(sut.getCollectionUserPermissions(nonExistentCollectionAlias)).rejects.toThrow(
189+
expectedError
190+
)
191+
})
192+
})
168193
})

0 commit comments

Comments
 (0)