Skip to content

Commit e96dc58

Browse files
authored
Merge pull request #349 from switcherapi/feat_348
Closes #348 - Added permission query to GraphQL endpoint
2 parents 99147a7 + 73067e0 commit e96dc58

File tree

6 files changed

+198
-0
lines changed

6 files changed

+198
-0
lines changed

requests/Switcher API.postman_collection.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5602,6 +5602,30 @@
56025602
}
56035603
},
56045604
"response": []
5605+
},
5606+
{
5607+
"name": "Client - Permission (Adm-GraphQL)",
5608+
"request": {
5609+
"method": "POST",
5610+
"header": [],
5611+
"body": {
5612+
"mode": "graphql",
5613+
"graphql": {
5614+
"query": "{\r\n # permission(domain: \"5e0ece606f4f994eac9007ae\", actions: [\"UPDATE\", \"DELETE\"], router: \"GROUP\") {\r\n permission(\r\n domain: \"5e0ece606f4f994eac9007ae\", \r\n parent: \"5e0ece916f4f994eac9007b0\", \r\n actions: [\"UPDATE\", \"DELETE\"],\r\n router: \"SWITCHER\") {\r\n id\r\n name\r\n permissions {\r\n action\r\n result\r\n }\r\n }\r\n}",
5615+
"variables": ""
5616+
}
5617+
},
5618+
"url": {
5619+
"raw": "{{url}}/adm-graphql",
5620+
"host": [
5621+
"{{url}}"
5622+
],
5623+
"path": [
5624+
"adm-graphql"
5625+
]
5626+
}
5627+
},
5628+
"response": []
56055629
}
56065630
]
56075631
},

src/client/permission-resolvers.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { verifyOwnership } from '../helpers';
2+
import { RouterTypes } from '../models/permission';
3+
import { getConfigs } from '../services/config';
4+
import { getGroupConfigs } from '../services/group-config';
5+
6+
export async function resolvePermission(args, admin) {
7+
let elements;
8+
if (args.router === RouterTypes.GROUP) {
9+
elements = await getGroupConfigs({ domain: args.domain }, true);
10+
} else if (args.router === RouterTypes.CONFIG) {
11+
elements = await getConfigs({ domain: args.domain, group: args.parent }, true);
12+
} else {
13+
return [];
14+
}
15+
16+
let result = [];
17+
for (const element of elements) {
18+
result.push({
19+
id: element._id,
20+
name: element.name || element.key,
21+
permissions: []
22+
});
23+
24+
for (const action_perm of args.actions) {
25+
try {
26+
await verifyOwnership(admin, element, args.domain, action_perm, args.router);
27+
result[result.length - 1].permissions.push({ action: action_perm.toString(), result: 'ok' });
28+
} catch (e) {
29+
result[result.length - 1].permissions.push({ action: action_perm.toString(), result: 'nok' });
30+
}
31+
}
32+
}
33+
34+
return result;
35+
}

src/client/permission-type.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { GraphQLObjectType, GraphQLString, GraphQLList } from 'graphql';
2+
3+
const elementPermissionsType = new GraphQLObjectType({
4+
name: 'permissions',
5+
fields: {
6+
action: {
7+
type: GraphQLString
8+
},
9+
result: {
10+
type: GraphQLString
11+
}
12+
}
13+
});
14+
15+
export const permissionType = new GraphQLObjectType({
16+
name: 'permission',
17+
fields: {
18+
id: {
19+
type: GraphQLString
20+
},
21+
name: {
22+
type: GraphQLString
23+
},
24+
permissions: {
25+
type: GraphQLList(elementPermissionsType)
26+
}
27+
}
28+
});

src/client/schema.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { EnvType } from '../models/environment';
44
import { strategyInputType, criteriaType } from './criteria-type';
55
import { resolveConfigByKey, resolveDomain } from './resolvers';
66
import { resolveConfiguration } from './configuration-resolvers';
7+
import { permissionType } from './permission-type';
8+
import { resolvePermission } from './permission-resolvers';
79

810
const queryType = new GraphQLObjectType({
911
name: 'Query',
@@ -85,6 +87,26 @@ const queryType = new GraphQLObjectType({
8587
return resolveConfiguration(args, context);
8688
}
8789
},
90+
permission: {
91+
type: new GraphQLList(permissionType),
92+
args: {
93+
domain: {
94+
type: GraphQLString
95+
},
96+
parent: {
97+
type: GraphQLString
98+
},
99+
actions: {
100+
type: new GraphQLList(GraphQLString)
101+
},
102+
router: {
103+
type: GraphQLString
104+
}
105+
},
106+
resolve: async (_source, args, context) => {
107+
return resolvePermission(args, context.admin);
108+
}
109+
}
88110
}
89111
});
90112

tests/client-api.test.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
adminAccountId,
2929
slack
3030
} from './fixtures/db_client';
31+
import { RouterTypes } from '../src/models/permission';
3132

3233
const changeStrategy = async (strategyId, newOperation, status, environment) => {
3334
const strategy = await ConfigStrategy.findById(strategyId);
@@ -928,4 +929,71 @@ describe('Testing domain [Adm-GraphQL] ', () => {
928929
expect(req.statusCode).toBe(200);
929930
expect(JSON.parse(req.text)).toMatchObject(JSON.parse(expected));
930931
});
932+
933+
test('CLIENT_SUITE - Should return list of Groups permissions', async () => {
934+
const req = await request(app)
935+
.post('/adm-graphql')
936+
.set('Authorization', `Bearer ${adminMasterAccountToken}`)
937+
.send(graphqlUtils.permissionsQuery(domainId, undefined, `"UPDATE","DELETE"`, RouterTypes.GROUP));
938+
939+
const exptected = '[{"action":"UPDATE","result":"ok"},{"action":"DELETE","result":"ok"}]';
940+
expect(req.statusCode).toBe(200);
941+
expect(JSON.parse(req.text)).not.toBe(null);
942+
expect(JSON.parse(req.text).data.permission[0].name).toBe("Group Test");
943+
expect(JSON.parse(req.text).data.permission[0].permissions).toMatchObject(JSON.parse(exptected));
944+
});
945+
946+
test('CLIENT_SUITE - Should return list of Groups permissions - Unauthorized access', async () => {
947+
const req = await request(app)
948+
.post('/adm-graphql')
949+
.set('Authorization', `Bearer ${adminAccountToken}`)
950+
.send(graphqlUtils.permissionsQuery(domainId, undefined, `"UPDATE","DELETE"`, RouterTypes.GROUP));
951+
952+
const exptected = '[{"action":"UPDATE","result":"nok"},{"action":"DELETE","result":"nok"}]';
953+
expect(req.statusCode).toBe(200);
954+
expect(JSON.parse(req.text)).not.toBe(null);
955+
expect(JSON.parse(req.text).data.permission[0].name).toBe("Group Test");
956+
expect(JSON.parse(req.text).data.permission[0].permissions).toMatchObject(JSON.parse(exptected));
957+
});
958+
959+
test('CLIENT_SUITE - Should return list of Configs permissions', async () => {
960+
const req = await request(app)
961+
.post('/adm-graphql')
962+
.set('Authorization', `Bearer ${adminMasterAccountToken}`)
963+
.send(graphqlUtils.permissionsQuery(domainId, groupConfigId, `"UPDATE","DELETE"`, RouterTypes.CONFIG));
964+
965+
const exptected = '[{"action":"UPDATE","result":"ok"},{"action":"DELETE","result":"ok"}]';
966+
expect(req.statusCode).toBe(200);
967+
expect(JSON.parse(req.text)).not.toBe(null);
968+
expect(JSON.parse(req.text).data.permission[0].name).toBe("TEST_CONFIG_KEY");
969+
expect(JSON.parse(req.text).data.permission[1].name).toBe("TEST_CONFIG_KEY_PRD_QA");
970+
expect(JSON.parse(req.text).data.permission[0].permissions).toMatchObject(JSON.parse(exptected));
971+
expect(JSON.parse(req.text).data.permission[1].permissions).toMatchObject(JSON.parse(exptected));
972+
});
973+
974+
test('CLIENT_SUITE - Should return list of Configs permissions - Unauthorized access', async () => {
975+
const req = await request(app)
976+
.post('/adm-graphql')
977+
.set('Authorization', `Bearer ${adminAccountToken}`)
978+
.send(graphqlUtils.permissionsQuery(domainId, groupConfigId, `"UPDATE","DELETE"`, RouterTypes.CONFIG));
979+
980+
const exptected = '[{"action":"UPDATE","result":"nok"},{"action":"DELETE","result":"nok"}]';
981+
expect(req.statusCode).toBe(200);
982+
expect(JSON.parse(req.text)).not.toBe(null);
983+
expect(JSON.parse(req.text).data.permission[0].name).toBe("TEST_CONFIG_KEY");
984+
expect(JSON.parse(req.text).data.permission[1].name).toBe("TEST_CONFIG_KEY_PRD_QA");
985+
expect(JSON.parse(req.text).data.permission[0].permissions).toMatchObject(JSON.parse(exptected));
986+
expect(JSON.parse(req.text).data.permission[1].permissions).toMatchObject(JSON.parse(exptected));
987+
});
988+
989+
test('CLIENT_SUITE - Should NOT return list of permissions - Invalid router', async () => {
990+
const req = await request(app)
991+
.post('/adm-graphql')
992+
.set('Authorization', `Bearer ${adminAccountToken}`)
993+
.send(graphqlUtils.permissionsQuery(domainId, undefined, `"UPDATE","DELETE"`, RouterTypes.DOMAIN));
994+
995+
expect(req.statusCode).toBe(200);
996+
expect(JSON.parse(req.text)).not.toBe(null);
997+
expect(JSON.parse(req.text).data.permission).toStrictEqual([]);
998+
});
931999
});

tests/graphql-utils/index.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,27 @@ export const buildEntries = (entries) => {
6363
return `${entries.map(createStrategyInput)}`;
6464
};
6565

66+
export const permissionsQuery = (domainId, parentId, actions, router) => {
67+
return {
68+
query: `
69+
{
70+
permission(
71+
domain: "${domainId}",
72+
parent: "${parentId}",
73+
actions: [${actions}],
74+
router: "${router}"
75+
) {
76+
id,
77+
name,
78+
permissions {
79+
action
80+
result
81+
}
82+
}
83+
}
84+
`};
85+
};
86+
6687
export const expected100 = `
6788
{
6889
"data": {

0 commit comments

Comments
 (0)