From 2b86ee02d30c99f37c6bda816b0914a3faa6f78d Mon Sep 17 00:00:00 2001 From: Daniel Kostro Date: Mon, 2 Mar 2020 09:41:51 +0100 Subject: [PATCH] feat: add getGroupsInfo route (#218) --- API.md | 21 +++++++++++---------- src/couch/group.js | 29 +++++++++++++++++++++++++++++ src/server/middleware/couch.js | 4 ++++ src/server/routes/api.js | 1 + test/data/data.js | 1 + test/unit/group.js | 16 ++++++++++++++++ 6 files changed, 62 insertions(+), 10 deletions(-) diff --git a/API.md b/API.md index 031ea690..f7ac2703 100644 --- a/API.md +++ b/API.md @@ -52,16 +52,17 @@ ### Groups -| Method | Route | Action | Description | -| :----: | :------------------------------------- | :-----------------------------------: | :--------------------------------------------------: | -| GET | `/db/:dbname/groups` | Get all groups | | -| GET | `/db/:dbname/group/:name` | Get a group by name | | -| PUT | `/db/:dbname/group/:name` | Create a group | | -| DELETE | `/db/:dbname/group/:name` | Remove a group | | -| PUT | `/db/:dbname/group/:name/user/:user` | Add a user to an existing group | Group must exist. No-op if user is already in group | -| DELETE | `/db/:dbname/group/:name/user/:user` | Remove a user from an existing group | Group must exist. No-op if user is not in group | -| PUT | `/db/:dbname/group/:name/right/:right` | Add a right to an existing group | Group must exist. No-op if group already has right | -| DELETE | `/db/:dbname/group/:name/right/:right` | Remove a right from an existing group | Group must exist. No-op if group does not have right | +| Method | Route | Action | Description | +| :----: | :------------------------------------- | :-----------------------------------: | :----------------------------------------------------------------------------: | +| GET | `/db/:dbname/groups` | Get all groups | | +| GET | `/db/:dbname/groups/info` | Get all groups' info | Returns name and description for all groups regardless of rights on that group | +| GET | `/db/:dbname/group/:name` | Get a group by name | | +| PUT | `/db/:dbname/group/:name` | Create a group | | +| DELETE | `/db/:dbname/group/:name` | Remove a group | | +| PUT | `/db/:dbname/group/:name/user/:user` | Add a user to an existing group | Group must exist. No-op if user is already in group | +| DELETE | `/db/:dbname/group/:name/user/:user` | Remove a user from an existing group | Group must exist. No-op if user is not in group | +| PUT | `/db/:dbname/group/:name/right/:right` | Add a right to an existing group | Group must exist. No-op if group already has right | +| DELETE | `/db/:dbname/group/:name/right/:right` | Remove a right from an existing group | Group must exist. No-op if group does not have right | ### Tokens diff --git a/src/couch/group.js b/src/couch/group.js index 98276eae..d2c4405f 100644 --- a/src/couch/group.js +++ b/src/couch/group.js @@ -152,6 +152,35 @@ const methods = { } }, + /** + * Return info about every group + * Only contains the group's name and description + * Does not return the list of user's or type of group + * @param {*} user + */ + async getGroupsInfo(user) { + debug.trace('getGroupsInfo (%s)', user); + + if (user === 'anonymous') { + throw new CouchError( + 'user must be authenticated to get groups info', + 'unauthorized', + ); + } + await this.open(); + + const groups = await this._db.queryView( + 'documentByType', + { key: 'group', include_docs: true }, + { onlyDoc: true }, + ); + + return groups.map((group) => ({ + name: group.name, + description: group.description, + })); + }, + /** * Returns a list of groups that grant a given right to the user * @param {string} user diff --git a/src/server/middleware/couch.js b/src/server/middleware/couch.js index 658ddfa7..dd073513 100644 --- a/src/server/middleware/couch.js +++ b/src/server/middleware/couch.js @@ -289,6 +289,10 @@ exports.getGroups = composeWithError(async (ctx) => { ctx.body = await ctx.state.couch.getGroups(ctx.state.userEmail); }); +exports.getGroupsInfo = composeWithError(async (ctx) => { + ctx.body = await ctx.state.couch.getGroupsInfo(ctx.state.userEmail); +}); + exports.getGroupUsers = composeWithError(async (ctx) => { const group = await ctx.state.couch.getDocByRights( ctx.params.uuid, diff --git a/src/server/routes/api.js b/src/server/routes/api.js index d295a9ce..dc67431f 100644 --- a/src/server/routes/api.js +++ b/src/server/routes/api.js @@ -80,6 +80,7 @@ router.post( // Groups router.get('/:dbname/groups', couch.getGroups); +router.get('/:dbname/groups/info', couch.getGroupsInfo); router.get('/:dbname/group/:name', couch.getGroup); router.put('/:dbname/group/:name', couch.createGroup); router.put( diff --git a/test/data/data.js b/test/data/data.js index 88b95349..54e154f2 100644 --- a/test/data/data.js +++ b/test/data/data.js @@ -13,6 +13,7 @@ function populate(db) { $type: 'group', $owners: ['a@a.com'], name: 'groupA', + description: 'groupA description', users: ['a@a.com'], rights: ['create', 'write', 'delete', 'read'], }), diff --git a/test/unit/group.js b/test/unit/group.js index a255787f..877b905b 100644 --- a/test/unit/group.js +++ b/test/unit/group.js @@ -84,6 +84,22 @@ describe('group methods', () => { }); }); + test('getGroupsInfo should return name and description all the groups', () => { + return couch.getGroupsInfo('a@a.com').then(function(groups) { + expect(groups.length).toEqual(2); + expect(groups[0]).toMatchObject({ + name: 'groupA', + description: 'groupA description', + }); + }); + }); + + test('getGroupsInfo should throw if user is anonymous', () => { + return expect(couch.getGroupsInfo('anonymous')).rejects.toThrow( + /user must be authenticated to get groups info/, + ); + }); + test('getGroups should return groups when owner not owner but has global readGroup right', () => { return couch.getGroups('b@b.com').then(function(docs) { expect(docs).toHaveLength(2);