Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 3 additions & 0 deletions src/api-docs/schemas/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ export default {
type: 'string'
}
}
},
environment: {
type: 'string'
}
}
},
Expand Down
8 changes: 4 additions & 4 deletions src/helpers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export function validatePagingArgs(args) {
return true;
}

export async function verifyOwnership(admin, element, domainId, action, routerType, cascade = false) {
export async function verifyOwnership(admin, element, domainId, action, routerType, cascade = false, environment = undefined) {
const domain = await getDomainById(domainId);
if (admin._id.equals(domain.owner)) {
return element;
Expand All @@ -121,15 +121,15 @@ export async function verifyOwnership(admin, element, domainId, action, routerTy
const teams = await getTeams({ _id: { $in: admin.teams }, domain: domain._id, active: true });
if (!teams.length || !admin.teams.length) {
throw new PermissionError('It was not possible to find any team that allows you to proceed with this operation');
}
}

let hasPermission = [];
let allowedElement;
for (const team of teams) {
if (cascade) {
allowedElement = await verifyPermissionsCascade(team, element, action, routerType);
allowedElement = await verifyPermissionsCascade(team, element, action, routerType, environment);
} else {
allowedElement = await verifyPermissions(team, element, action, routerType);
allowedElement = await verifyPermissions(team, element, action, routerType, environment);
}

if (allowedElement) {
Expand Down
18 changes: 13 additions & 5 deletions src/helpers/permission.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { ActionTypes, RouterTypes } from '../models/permission';
import { getPermission, getPermissions } from '../services/permission';

export async function verifyPermissions(team, element, action, routerType) {
export async function verifyPermissions(team, element, action, routerType, environment) {
const permission = await getPermission({
_id: { $in: team.permissions },
action: { $in: [action, ActionTypes.ALL] },
active: true,
router: { $in: [routerType, RouterTypes.ALL] }
});

if (!permission) {
if (!permission || !verifyEnvironment(permission, environment)) {
return undefined;
}

return verifyIdentifiers(permission, element);
}

export async function verifyPermissionsCascade(team, element, action, routerType) {
export async function verifyPermissionsCascade(team, element, action, routerType, environment) {
let orStatement = [];
if (routerType === RouterTypes.DOMAIN) {
orStatement = [
Expand Down Expand Up @@ -49,9 +49,9 @@ export async function verifyPermissionsCascade(team, element, action, routerType
});

const matchedPermission = foundPermission.filter(value => value.router === routerType);
if (matchedPermission.length) {
if (matchedPermission.length && verifyEnvironment(matchedPermission[0], environment)) {
return verifyIdentifiers(matchedPermission[0], element);
} else if (foundPermission[0]) {
} else if (foundPermission[0] && verifyEnvironment(foundPermission[0], environment)) {
return element;
}
}
Expand All @@ -73,4 +73,12 @@ function verifyIdentifiers(permission, element) {
}

return element;
}

function verifyEnvironment(permission, environment) {
if (permission.environments?.length) {
return environment && permission.environments.includes(environment);
}

return true;
}
6 changes: 4 additions & 2 deletions src/routers/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ router.get('/admin/me', auth, async (req, res) => {
router.post('/admin/collaboration/permission', auth, [
check('domain', 'Domain Id is required').isMongoId(),
check('action', 'Array of actions is required').isArray({ min: 1 }),
check('router', 'Router name is required').isLength({ min: 1 })
check('router', 'Router name is required').isLength({ min: 1 }),
check('environment').isString().optional()
], validate, async (req, res) => {
const element = {
_id: req.body.element?.id,
Expand All @@ -112,7 +113,8 @@ router.post('/admin/collaboration/permission', auth, [
let result = [];
for (const action_perm of req.body.action) {
try {
await verifyOwnership(req.admin, element, req.body.domain, action_perm, req.body.router);
await verifyOwnership(req.admin, element, req.body.domain, action_perm,
req.body.router, false, req.body.environment);
result.push({ action: action_perm.toString(), result: 'ok' });
} catch (e) {
result.push({ action : action_perm.toString(), result: 'nok' });
Expand Down
22 changes: 21 additions & 1 deletion tests/admin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import { Team } from '../src/models/team';
import swaggerDocument from '../src/api-docs/swagger-document';
import { RouterTypes } from '../src/models/permission';
import { EnvType } from '../src/models/environment';

afterAll(async () => {
await new Promise(resolve => setTimeout(resolve, 1000));
Expand Down Expand Up @@ -954,7 +955,8 @@ describe('Testing Admin collaboration endpoint - Reading permissions', () => {
.send({
domain: domainId,
action: ['READ', 'UPDATE', 'CREATE'],
router: RouterTypes.GROUP
router: RouterTypes.GROUP,
environment: EnvType.DEFAULT
})
.expect(200);

Expand All @@ -967,6 +969,24 @@ describe('Testing Admin collaboration endpoint - Reading permissions', () => {
const create = response.body.filter(permission => permission.action === 'CREATE');
expect(create[0].result).toEqual('nok');
});

test('ADMIN_SUITE - Should read permissions given request - Access forbidden for staging', async () => {
const response = await request(app)
.post('/admin/collaboration/permission')
.set('Authorization', `Bearer ${token}`)
.send({
domain: domainId,
action: ['READ'],
router: RouterTypes.GROUP,
environment: 'staging'
})
.expect(200);

expect(response.body.length > 0).toEqual(true);

const read = response.body.filter(permission => permission.action === 'READ');
expect(read[0].result).toEqual('nok');
});
});


Expand Down
3 changes: 2 additions & 1 deletion tests/fixtures/db_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ export const permission1 = {
_id: permission1Id,
action: ActionTypes.READ,
active: true,
router: RouterTypes.GROUP
router: RouterTypes.GROUP,
environments: [EnvType.DEFAULT, 'dev']
};

export const component1Id = new mongoose.Types.ObjectId();
Expand Down
12 changes: 11 additions & 1 deletion tests/fixtures/db_team_permission.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ export const permission1 = {
router: RouterTypes.CONFIG
};

export const permission11Id = new mongoose.Types.ObjectId();
export const permission11 = {
_id: permission11Id,
action: ActionTypes.UPDATE,
active: true,
router: RouterTypes.CONFIG,
environments: ['dev']
};

export const permission2Id = new mongoose.Types.ObjectId();
export const permission2 = {
_id: permission2Id,
Expand Down Expand Up @@ -118,7 +127,7 @@ export const team1 = {
domain: domainId,
name: 'Team 1',
active: true,
permissions: [permission1Id, permission2Id, permission3Id]
permissions: [permission1Id, permission11Id, permission2Id, permission3Id]
};

export const team2Id = new mongoose.Types.ObjectId();
Expand Down Expand Up @@ -188,6 +197,7 @@ export const setupDatabase = async () => {
await new GroupConfig(groupConfig2Document).save();
await new Config(configDocument).save();
await new Permission(permission1).save();
await new Permission(permission11).save();
await new Permission(permission2).save();
await new Permission(permission21).save();
await new Permission(permission22).save();
Expand Down
110 changes: 83 additions & 27 deletions tests/unit-test/verify-ownership.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,33 @@ import {
setupDatabase,
adminMasterAccount,
adminAccount,
adminAccount2,
adminAccount3,
domainDocument,
groupConfig2Document,
configDocument,
domainId,
team1Id,
permission1Id,
permission11Id,
permission2Id,
permission3Id,
adminAccount2,
team1Id,
adminAccount3,
permission21Id,
permission4Id,
permission22Id
permission22Id,
permission3Id,
permission4Id
} from '../fixtures/db_team_permission';
import { PermissionError } from '../../src/exceptions';

const disableAllPermissions = async () => {
await changePermissionStatus(permission1Id, false);
await changePermissionStatus(permission11Id, false);
await changePermissionStatus(permission2Id, false);
await changePermissionStatus(permission21Id, false);
await changePermissionStatus(permission22Id, false);
await changePermissionStatus(permission3Id, false);
await changePermissionStatus(permission4Id, false);
};

const changePermissionStatus = async (permissionId, status) => {
const permission = await Permission.findById(permissionId).exec();
permission.active = status;
Expand All @@ -50,15 +61,7 @@ afterAll(async () => {

describe('Success tests', () => {
beforeAll(setupDatabase);

beforeEach(async () => {
await changePermissionStatus(permission1Id, false);
await changePermissionStatus(permission2Id, false);
await changePermissionStatus(permission21Id, false);
await changePermissionStatus(permission22Id, false);
await changePermissionStatus(permission3Id, false);
await changePermissionStatus(permission4Id, false);
});
beforeEach(disableAllPermissions);

test('UNIT_TEAM_PERMISSION_SUITE - Should allow access - Element owner', async () => {
try {
Expand All @@ -69,7 +72,7 @@ describe('Success tests', () => {
ActionTypes.READ,
RouterTypes.DOMAIN);

expect(element._id).toEqual(domainDocument._id);
expect(element).toMatchObject(domainDocument);
} catch (e) {
expect(e).toBeNull();
}
Expand All @@ -89,7 +92,51 @@ describe('Success tests', () => {
ActionTypes.READ,
RouterTypes.GROUP);

expect(element._id).toEqual(groupConfig2Document._id);
expect(element).toMatchObject(groupConfig2Document);
} catch (e) {
expect(e).toBeNull();
}
});

test('UNIT_TEAM_PERMISSION_SUITE - Should allow access - Member has permission to environment', async () => {
//given
//enabled Update - Switcher (update only in dev environment)
await changePermissionStatus(permission11Id, true);

//test
try {
const element = await verifyOwnership(
adminAccount,
configDocument,
domainDocument,
ActionTypes.UPDATE,
RouterTypes.CONFIG,
false,
'dev');

expect(element).toMatchObject(configDocument);
} catch (e) {
expect(e).toBeNull();
}
});

test('UNIT_TEAM_PERMISSION_SUITE - Should allow access - Member has permission to environment - Cascade', async () => {
//given
//enabled Update - Switcher (update only in dev environment)
await changePermissionStatus(permission11Id, true);

//test
try {
const element = await verifyOwnership(
adminAccount,
configDocument,
domainDocument,
ActionTypes.UPDATE,
RouterTypes.CONFIG,
true,
'dev');

expect(element).toMatchObject(configDocument);
} catch (e) {
expect(e).toBeNull();
}
Expand All @@ -113,7 +160,7 @@ describe('Success tests', () => {
RouterTypes.GROUP,
true);

expect(element._id).toEqual(groupConfig2Document._id);
expect(element).toMatchObject(groupConfig2Document);
} catch (e) {
expect(e).toBeNull();
}
Expand Down Expand Up @@ -254,15 +301,7 @@ describe('Success tests', () => {

describe('Error tests', () => {
beforeAll(setupDatabase);

beforeEach(async () => {
await changePermissionStatus(permission1Id, false);
await changePermissionStatus(permission2Id, false);
await changePermissionStatus(permission21Id, false);
await changePermissionStatus(permission22Id, false);
await changePermissionStatus(permission3Id, false);
await changePermissionStatus(permission4Id, false);
});
beforeEach(disableAllPermissions);

test('UNIT_TEAM_PERMISSION_SUITE - Should NOT allow access - Permission innactive', async () => {
await changePermissionStatus(permission2Id, false);
Expand Down Expand Up @@ -344,4 +383,21 @@ describe('Error tests', () => {
}).rejects.toThrow(new PermissionError(`Action forbidden`));
});

test('UNIT_TEAM_PERMISSION_SUITE - Should NOT allow access - Member does not have permission to environment', async () => {
//given
//enabled Update - Switcher (update only in dev environment)
await changePermissionStatus(permission11Id, true);

expect(async () => {
await verifyOwnership(
adminAccount,
configDocument,
domainDocument,
ActionTypes.UPDATE,
RouterTypes.CONFIG,
false,
'default');
}).rejects.toThrow(new PermissionError(`Action forbidden`));
});

});