Skip to content

Commit 714ec57

Browse files
authored
Merge pull request #338 from switcherapi/staging
Improved Slack env settings to use value pattern #335
2 parents 34249df + a74e55d commit 714ec57

File tree

5 files changed

+157
-116
lines changed

5 files changed

+157
-116
lines changed

src/helpers/index.js

Lines changed: 5 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import { BadRequestError, PermissionError } from '../exceptions';
22
import { EnvType } from '../models/environment';
3-
import { ActionTypes, RouterTypes } from '../models/permission';
43
import { getDomainById } from '../services/domain';
54
import { getEnvironments } from '../services/environment';
65
import { getTeams } from '../services/team';
7-
import { getPermission, getPermissions } from '../services/permission';
6+
import { verifyPermissions, verifyPermissionsCascade } from './permission';
87

98
export async function checkEnvironmentStatusRemoval(domainId, environmentName, strategy = false) {
109
const environment = await getEnvironments({ domain: domainId }, ['_id', 'name']);
@@ -41,6 +40,10 @@ export function parseJSON(str) {
4140
}
4241
}
4342

43+
export function containsValue(arr, value) {
44+
return arr?.filter(item => item.match(value)).length > 0;
45+
}
46+
4447
export function formatInput(input,
4548
options = {
4649
toUpper: false,
@@ -105,79 +108,4 @@ export async function verifyOwnership(admin, element, domainId, action, routerTy
105108
}
106109

107110
return element;
108-
}
109-
110-
async function verifyPermissions(team, element, action, routerType) {
111-
const permission = await getPermission({
112-
_id: { $in: team.permissions },
113-
action: { $in: [action, ActionTypes.ALL] },
114-
active: true,
115-
router: { $in: [routerType, RouterTypes.ALL] }
116-
});
117-
118-
if (permission) {
119-
return verifyIdentifiers(permission, element);
120-
} else {
121-
throw new PermissionError(`Permission not found for this operation: '${action}' - '${routerType}'`);
122-
}
123-
}
124-
125-
async function verifyPermissionsCascade(team, element, action, routerType) {
126-
let orStatement = [];
127-
if (routerType === RouterTypes.DOMAIN) {
128-
orStatement = [
129-
{ router: routerType },
130-
{ router: RouterTypes.GROUP },
131-
{ router: RouterTypes.CONFIG },
132-
{ router: RouterTypes.STRATEGY },
133-
{ router: RouterTypes.ALL }
134-
];
135-
} else if (routerType === RouterTypes.GROUP) {
136-
orStatement = [
137-
{ router: routerType },
138-
{ router: RouterTypes.CONFIG },
139-
{ router: RouterTypes.STRATEGY },
140-
{ router: RouterTypes.ALL }
141-
];
142-
} else if (routerType === RouterTypes.CONFIG || routerType === RouterTypes.STRATEGY) {
143-
orStatement = [
144-
{ router: routerType },
145-
{ router: RouterTypes.STRATEGY },
146-
{ router: RouterTypes.ALL }
147-
];
148-
}
149-
150-
const foundPermission = await getPermissions({
151-
_id: { $in: team.permissions },
152-
action: { $in: [action, ActionTypes.ALL] },
153-
active: true,
154-
$or: orStatement
155-
});
156-
157-
const matchedPermission = foundPermission.filter(value => value.router === routerType);
158-
if (matchedPermission.length) {
159-
return verifyIdentifiers(matchedPermission[0], element);
160-
} else if (foundPermission[0]) {
161-
return element;
162-
}
163-
}
164-
165-
function verifyIdentifiers(permission, element) {
166-
if (permission.identifiedBy) {
167-
if (Array.isArray(element)) {
168-
if (permission.values.length) {
169-
element = element.filter(child => permission.values.includes(child[`${permission.identifiedBy}`]));
170-
if (element.length) {
171-
return element;
172-
}
173-
}
174-
} else {
175-
if (permission.values.includes(element[`${permission.identifiedBy}`])) {
176-
return element;
177-
}
178-
}
179-
} else {
180-
return element;
181-
}
182-
throw new PermissionError('It was not possible to match the requiring element to the current permission');
183111
}

src/helpers/permission.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { PermissionError } from '../exceptions';
2+
import { ActionTypes, RouterTypes } from '../models/permission';
3+
import { getPermission, getPermissions } from '../services/permission';
4+
5+
export async function verifyPermissions(team, element, action, routerType) {
6+
const permission = await getPermission({
7+
_id: { $in: team.permissions },
8+
action: { $in: [action, ActionTypes.ALL] },
9+
active: true,
10+
router: { $in: [routerType, RouterTypes.ALL] }
11+
});
12+
13+
if (permission) {
14+
return verifyIdentifiers(permission, element);
15+
} else {
16+
throw new PermissionError(`Permission not found for this operation: '${action}' - '${routerType}'`);
17+
}
18+
}
19+
20+
export async function verifyPermissionsCascade(team, element, action, routerType) {
21+
let orStatement = [];
22+
if (routerType === RouterTypes.DOMAIN) {
23+
orStatement = [
24+
{ router: routerType },
25+
{ router: RouterTypes.GROUP },
26+
{ router: RouterTypes.CONFIG },
27+
{ router: RouterTypes.STRATEGY },
28+
{ router: RouterTypes.ALL }
29+
];
30+
} else if (routerType === RouterTypes.GROUP) {
31+
orStatement = [
32+
{ router: routerType },
33+
{ router: RouterTypes.CONFIG },
34+
{ router: RouterTypes.STRATEGY },
35+
{ router: RouterTypes.ALL }
36+
];
37+
} else if (routerType === RouterTypes.CONFIG || routerType === RouterTypes.STRATEGY) {
38+
orStatement = [
39+
{ router: routerType },
40+
{ router: RouterTypes.STRATEGY },
41+
{ router: RouterTypes.ALL }
42+
];
43+
}
44+
45+
const foundPermission = await getPermissions({
46+
_id: { $in: team.permissions },
47+
action: { $in: [action, ActionTypes.ALL] },
48+
active: true,
49+
$or: orStatement
50+
});
51+
52+
const matchedPermission = foundPermission.filter(value => value.router === routerType);
53+
if (matchedPermission.length) {
54+
return verifyIdentifiers(matchedPermission[0], element);
55+
} else if (foundPermission[0]) {
56+
return element;
57+
}
58+
}
59+
60+
function verifyIdentifiers(permission, element) {
61+
if (permission.identifiedBy) {
62+
if (Array.isArray(element)) {
63+
if (permission.values.length) {
64+
element = element.filter(child => permission.values.includes(child[`${permission.identifiedBy}`]));
65+
if (element.length) {
66+
return element;
67+
}
68+
}
69+
} else {
70+
if (permission.values.includes(element[`${permission.identifiedBy}`])) {
71+
return element;
72+
}
73+
}
74+
} else {
75+
return element;
76+
}
77+
throw new PermissionError('It was not possible to match the requiring element to the current permission');
78+
}

src/services/slack.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { getConfig } from './config';
77
import { getDomainById } from './domain';
88
import { getEnvironment } from './environment';
99
import { getGroupConfig } from './group-config';
10+
import { containsValue } from '../helpers';
1011

1112
/**
1213
* Validates if ticket already exists, if so, return it.
@@ -160,10 +161,10 @@ export async function validateTicket(ticket_content, enterprise_id, team_id) {
160161
const ticket = await canCreateTicket(slack, ticket_content);
161162
const { ignored_environments, frozen_environments } = slack.settings;
162163

163-
if (frozen_environments?.includes(ticket_content.environment))
164+
if (containsValue(frozen_environments, ticket_content.environment))
164165
return { result: TicketValidationType.FROZEN_ENVIRONMENT };
165166

166-
if (ignored_environments?.includes(ticket_content.environment)) {
167+
if (containsValue(ignored_environments, ticket_content.environment)) {
167168
await approveChange(slack.domain, ticket_content);
168169
return { result: TicketValidationType.IGNORED_ENVIRONMENT };
169170
}

tests/unit-test/helpers.test.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
const { formatInput, containsValue } = require('../../src/helpers');
2+
3+
describe('Test formatInput', () => {
4+
5+
test('Should return error - Non alphanumeric input', () => {
6+
try {
7+
formatInput('Spaces are not allowed here');
8+
} catch (e) {
9+
expect(e.message).toBe('Invalid input format. Use only alphanumeric digits.');
10+
}
11+
});
12+
13+
test('Should NOT return error - Spaces allowed', () => {
14+
try {
15+
const input = formatInput('Spaces are not allowed here', { allowSpace: true });
16+
expect(input).toBe('Spaces are not allowed here');
17+
} catch (e) {
18+
expect(e.message).toBe(null);
19+
}
20+
});
21+
22+
test('Should format input - To upper case', () => {
23+
const input = formatInput('uppercaseme', { toUpper: true });
24+
expect(input).toBe('UPPERCASEME');
25+
});
26+
27+
test('Should format input - To lower case', () => {
28+
const input = formatInput('UPPERCASEME', { toLower: true });
29+
expect(input).toBe('uppercaseme');
30+
});
31+
32+
test('Should format input - Replace spaces for underscore', () => {
33+
const input = formatInput('NEW SCORE', { autoUnderscore: true });
34+
expect(input).toBe('NEW_SCORE');
35+
});
36+
37+
});
38+
39+
describe('Test containsValue', () => {
40+
41+
test('Should return true when value exists in array', () => {
42+
const result = containsValue(['value1', 'value2'], 'value1');
43+
expect(result).toBeTruthy();
44+
});
45+
46+
test('Should return false when value does not exist in array', () => {
47+
const result = containsValue(['value1', 'value2'], 'value3');
48+
expect(result).toBeFalsy();
49+
});
50+
51+
test('Should return true when partial value exists in array', () => {
52+
const result = containsValue(['value1', 'value2'], 'value');
53+
expect(result).toBeTruthy();
54+
});
55+
56+
test('Should return false for case sensitive values', () => {
57+
const result = containsValue(['value1', 'value2'], 'Value1');
58+
expect(result).toBeFalsy();
59+
});
60+
61+
test('Should return false when array is empty', () => {
62+
const result = containsValue([], 'value1');
63+
expect(result).toBeFalsy();
64+
});
65+
66+
test('Should return false when array is undefined', () => {
67+
const result = containsValue(undefined, 'value1');
68+
expect(result).toBeFalsy();
69+
});
70+
71+
});

tests/unit-test/router-index.test.js

Lines changed: 0 additions & 37 deletions
This file was deleted.

0 commit comments

Comments
 (0)