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: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"scripts": {
"check-types": "tsc --noEmit",
"clean": "rimraf lib",
"eslint": "eslint . --cache",
"eslint": "eslint . --cache --max-warnings=0",
"eslint-fix": "npm run eslint -- --fix",
"prepare": "npm run tsc",
"prettier": "prettier --check .",
Expand Down
51 changes: 51 additions & 0 deletions src/roc/Roc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ export interface IRocConfig {
accessToken?: string;
}

export type RocGroupPermission =
| 'delete'
| 'read'
| 'write'
| 'create'
| 'readGroup'
| 'writeGroup'
| 'createGroup'
| 'readImport'
| 'owner'
| 'addAttachment';

function createAxios(url: string, accessToken?: string) {
return axios.create({
baseURL: url,
Expand Down Expand Up @@ -182,6 +194,45 @@ export default class Roc<PublicUserInfo = unknown, PrivateUserInfo = unknown> {
return response.data;
}

public async addUserToGroup(
groupName: string,
user: string,
axiosOptions?: RocAxiosRequestOptions,
) {
const response = await this.dbRequest.put<Ok>(
`group/${groupName}/user/${user}`,
axiosOptions,
);
return response.data;
}

public async addPermissionToGroup(
groupName: string,
permission: RocGroupPermission,
) {
const response = await this.dbRequest.put<Ok>(
`group/${groupName}/right/${permission}`,
);
return response.data;
}

public async removeUserFromGroup(groupName: string, user: string) {
const response = await this.dbRequest.delete<Ok>(
`group/${groupName}/user/${user}`,
);
return response.data;
}

public async removePermissionFromGroup(
groupName: string,
permission: RocGroupPermission,
) {
const response = await this.dbRequest.delete<Ok>(
`group/${groupName}/right/${permission}`,
);
return response.data;
}

public async getGroup(
name: string,
axiosOptions?: RocAxiosRequestOptions,
Expand Down
214 changes: 146 additions & 68 deletions src/roc/__tests__/group.test.ts
Original file line number Diff line number Diff line change
@@ -1,90 +1,168 @@
import { beforeAll, expect, test } from 'vitest';
import { beforeAll, describe, expect, it } from 'vitest';

import { resetTestDatabase, testRoc } from '../../testUtils.ts';
import type { Ok } from '../../types.ts';
import type { RocGroupPermission } from '../Roc.ts';

const ok: Ok = { ok: true };

beforeAll(async () => {
await resetTestDatabase();
});

test('create group', async () => {
const group = await testRoc.createGroup('group1');
// Makes sure we are testing all the possible permissions defined by the types
const groupMap: Record<RocGroupPermission, true> = {
addAttachment: true,
create: true,
createGroup: true,
delete: true,
owner: true,
read: true,
readGroup: true,
readImport: true,
write: true,
writeGroup: true,
};
const allGroups = Object.keys(groupMap) as RocGroupPermission[];

expect(group).toStrictEqual({ ok: true });
});
describe('create and update groups', () => {
it('create group', async () => {
const group = await testRoc.createGroup('group1');

expect(group).toStrictEqual(ok);
});

it('add user to group', async () => {
const groupName = crypto.randomUUID();
await testRoc.createGroup(groupName);
const data = await testRoc.addUserToGroup(groupName, 'john@doe.com');

test('get group', async () => {
const group = await testRoc.getGroup('group1');
expect(data).toStrictEqual(ok);

expect(group).toMatchObject({
$owners: ['admin@cheminfo.org'],
$type: 'group',
customUsers: [],
name: 'group1',
rights: [],
users: [],
const group = await testRoc.getGroup(groupName);

expect(group.users).toStrictEqual(['john@doe.com']);
});
});

test('get group info', async () => {
const groupInfo = await testRoc.getGroupInfo('group1');
it('removes user from group', async () => {
const groupName = crypto.randomUUID();
await testRoc.createGroup(groupName);
await testRoc.addUserToGroup(groupName, 'john@doe.com');
const data = await testRoc.removeUserFromGroup(groupName, 'john@doe.com');

expect(data).toStrictEqual(ok);

const group = await testRoc.getGroup(groupName);

expect(groupInfo).toMatchObject({
name: 'group1',
rights: [],
users: [],
expect(group.users).toStrictEqual([]);
});
});

test('get group info with ldap info', async () => {
const groupInfo = await testRoc.getGroupInfo('group1', {
ldapInfo: true,
it('add permission to group', async () => {
const groupName = crypto.randomUUID();
await testRoc.createGroup(groupName);
const data = await testRoc.addPermissionToGroup(groupName, 'read');

expect(data).toStrictEqual(ok);

const group = await testRoc.getGroup(groupName);

expect(group.rights).toStrictEqual(['read']);
});

expect(groupInfo).toMatchObject({
name: 'group1',
rights: [],
users: [],
ldapInfo: [],
it('adds permission to group', async () => {
const groupName = crypto.randomUUID();
await testRoc.createGroup(groupName);
for (const permission of allGroups) {
// rest-on-couch does not support concurrent requests without the possibility of conflicts.
// eslint-disable-next-line no-await-in-loop
await testRoc.addPermissionToGroup(groupName, permission);
}
const group = await testRoc.getGroup(groupName);

expect(group.rights.toSorted()).toStrictEqual(allGroups);
});
});

test('get groups info', async () => {
await testRoc.createGroup('group2');
const groupsInfo = await testRoc.getGroupsInfo();

expect(groupsInfo).toMatchInlineSnapshot(`
[
{
"name": "group1",
"rights": [],
"users": [],
},
{
"name": "group2",
"rights": [],
"users": [],
},
]
`);
it('remove permissions from group', async () => {
const groupName = crypto.randomUUID();
await testRoc.createGroup(groupName);
await testRoc.addPermissionToGroup(groupName, 'read');
const data = await testRoc.removePermissionFromGroup(groupName, 'read');

expect(data).toStrictEqual(ok);

const group = await testRoc.getGroup(groupName);

expect(group.rights).toStrictEqual([]);
});
});

test('get groups info with ldap info', async () => {
const groupsInfo = await testRoc.getGroupsInfo({ ldapInfo: true });

expect(groupsInfo).toMatchInlineSnapshot(`
[
{
"ldapInfo": [],
"name": "group1",
"rights": [],
"users": [],
},
{
"ldapInfo": [],
"name": "group2",
"rights": [],
"users": [],
},
]
`);
describe('get groups', () => {
it('get group', async () => {
const groupName = crypto.randomUUID();
await testRoc.createGroup(groupName);
const group = await testRoc.getGroup(groupName);

expect(group).toMatchObject({
$owners: ['admin@cheminfo.org'],
$type: 'group',
customUsers: [],
name: groupName,
rights: [],
users: [],
});
});

it('get group info', async () => {
const groupName = crypto.randomUUID();
await testRoc.createGroup(groupName);
const groupInfo = await testRoc.getGroupInfo(groupName);

expect(groupInfo).toMatchObject({
name: groupName,
rights: [],
users: [],
});
});

it('get group info with ldap info', async () => {
const groupName = crypto.randomUUID();
await testRoc.createGroup(groupName);
const groupInfo = await testRoc.getGroupInfo(groupName, {
ldapInfo: true,
});

expect(groupInfo).toMatchObject({
name: groupName,
rights: [],
users: [],
ldapInfo: [],
});
});

it('get groups info', async () => {
const groupName = crypto.randomUUID();
await testRoc.createGroup(groupName);
const groupsInfo = await testRoc.getGroupsInfo();
const group = groupsInfo.find((g) => g.name === groupName);

expect(group).toStrictEqual({
name: groupName,
rights: [],
users: [],
});
});

it('get groups info with ldap info', async () => {
const groupName = crypto.randomUUID();
await testRoc.createGroup(groupName);
const groupsInfo = await testRoc.getGroupsInfo({ ldapInfo: true });
const group = groupsInfo.find((g) => g.name === groupName);

expect(group).toStrictEqual({
ldapInfo: [],
name: groupName,
rights: [],
users: [],
});
});
});
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"include": ["./src/**/*", "vitest.config.ts"],
"compilerOptions": {
"outDir": "./lib",
"lib": ["DOM"],
"lib": ["DOM", "ES2023"],
"types": ["node"]
}
}