2021-03-11 22:51:58 +01:00
|
|
|
import test from 'ava';
|
|
|
|
|
|
|
|
import sinon from 'sinon';
|
|
|
|
|
|
|
|
import rbacMiddleware from './rbac-middleware';
|
|
|
|
import getLogger from '../../test/fixtures/no-logger';
|
|
|
|
import ffStore from '../../test/fixtures/fake-feature-toggle-store';
|
|
|
|
import User from '../user';
|
|
|
|
import perms from '../permissions';
|
2021-04-22 10:07:10 +02:00
|
|
|
import { IUnleashConfig } from '../types/option';
|
|
|
|
import createConfig from '../create-config';
|
2021-03-11 22:51:58 +01:00
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
let config: IUnleashConfig;
|
2021-03-11 22:51:58 +01:00
|
|
|
let featureToggleStore: any;
|
|
|
|
|
|
|
|
test.beforeEach(() => {
|
|
|
|
featureToggleStore = ffStore();
|
2021-04-22 10:07:10 +02:00
|
|
|
config = createConfig({ getLogger });
|
2021-03-11 22:51:58 +01:00
|
|
|
});
|
|
|
|
|
2021-04-12 20:25:03 +02:00
|
|
|
test('should add checkRbac to request', t => {
|
2021-04-22 10:07:10 +02:00
|
|
|
const accessService = {
|
|
|
|
hasPermission: sinon.fake(),
|
|
|
|
};
|
2021-03-11 22:51:58 +01:00
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
const func = rbacMiddleware(config, { featureToggleStore }, accessService);
|
2021-03-11 22:51:58 +01:00
|
|
|
|
|
|
|
const cb = sinon.fake();
|
|
|
|
|
|
|
|
const req = sinon.fake();
|
|
|
|
|
|
|
|
func(req, undefined, cb);
|
|
|
|
|
|
|
|
t.truthy(req.checkRbac);
|
|
|
|
t.is(typeof req.checkRbac, 'function');
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should give api-user ADMIN permission', async t => {
|
2021-04-22 10:07:10 +02:00
|
|
|
const accessService = {
|
|
|
|
hasPermission: sinon.fake(),
|
|
|
|
};
|
2021-03-11 22:51:58 +01:00
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
const func = rbacMiddleware(config, { featureToggleStore }, accessService);
|
2021-03-11 22:51:58 +01:00
|
|
|
|
|
|
|
const cb = sinon.fake();
|
|
|
|
const req: any = {
|
|
|
|
user: new User({
|
|
|
|
username: 'api',
|
|
|
|
permissions: [perms.ADMIN],
|
|
|
|
isAPI: true,
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
|
|
|
|
func(req, undefined, cb);
|
|
|
|
|
|
|
|
const hasAccess = await req.checkRbac(perms.ADMIN);
|
|
|
|
|
|
|
|
t.true(hasAccess);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should not give api-user ADMIN permission', async t => {
|
2021-04-22 10:07:10 +02:00
|
|
|
const accessService = {
|
|
|
|
hasPermission: sinon.fake(),
|
|
|
|
};
|
2021-03-11 22:51:58 +01:00
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
const func = rbacMiddleware(config, { featureToggleStore }, accessService);
|
2021-03-11 22:51:58 +01:00
|
|
|
|
|
|
|
const cb = sinon.fake();
|
|
|
|
const req: any = {
|
|
|
|
user: new User({
|
|
|
|
username: 'api',
|
|
|
|
permissions: [perms.CLIENT],
|
|
|
|
isAPI: true,
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
|
|
|
|
func(req, undefined, cb);
|
|
|
|
|
|
|
|
const hasAccess = await req.checkRbac(perms.ADMIN);
|
|
|
|
|
|
|
|
t.false(hasAccess);
|
2021-04-22 10:07:10 +02:00
|
|
|
t.is(accessService.hasPermission.callCount, 0);
|
2021-03-11 22:51:58 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
test('should not allow user to miss userId', async t => {
|
2021-04-22 10:07:10 +02:00
|
|
|
const accessService = {
|
|
|
|
hasPermission: sinon.fake(),
|
|
|
|
};
|
2021-03-11 22:51:58 +01:00
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
const func = rbacMiddleware(config, { featureToggleStore }, accessService);
|
2021-03-11 22:51:58 +01:00
|
|
|
|
|
|
|
const cb = sinon.fake();
|
|
|
|
const req: any = {
|
|
|
|
user: new User({
|
|
|
|
username: 'user',
|
|
|
|
permissions: [perms.ADMIN],
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
|
|
|
|
func(req, undefined, cb);
|
|
|
|
|
|
|
|
const hasAccess = await req.checkRbac(perms.ADMIN);
|
|
|
|
|
|
|
|
t.false(hasAccess);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should return false for missing user', async t => {
|
2021-04-22 10:07:10 +02:00
|
|
|
const accessService = {
|
|
|
|
hasPermission: sinon.fake(),
|
|
|
|
};
|
2021-03-11 22:51:58 +01:00
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
const func = rbacMiddleware(config, { featureToggleStore }, accessService);
|
2021-03-11 22:51:58 +01:00
|
|
|
|
|
|
|
const cb = sinon.fake();
|
|
|
|
const req: any = {};
|
|
|
|
|
|
|
|
func(req, undefined, cb);
|
|
|
|
|
|
|
|
const hasAccess = await req.checkRbac(perms.ADMIN);
|
|
|
|
|
|
|
|
t.false(hasAccess);
|
2021-04-22 10:07:10 +02:00
|
|
|
t.is(accessService.hasPermission.callCount, 0);
|
2021-03-11 22:51:58 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
test('should verify permission for root resource', async t => {
|
|
|
|
const accessService = {
|
|
|
|
hasPermission: sinon.fake(),
|
|
|
|
};
|
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
const func = rbacMiddleware(config, { featureToggleStore }, accessService);
|
2021-03-11 22:51:58 +01:00
|
|
|
|
|
|
|
const cb = sinon.fake();
|
|
|
|
const req: any = {
|
|
|
|
user: new User({
|
|
|
|
username: 'user',
|
|
|
|
id: 1,
|
|
|
|
}),
|
|
|
|
params: {},
|
|
|
|
};
|
|
|
|
|
|
|
|
func(req, undefined, cb);
|
|
|
|
|
|
|
|
await req.checkRbac(perms.ADMIN);
|
|
|
|
|
|
|
|
t.true(accessService.hasPermission.calledOnce);
|
|
|
|
t.is(accessService.hasPermission.firstArg, req.user);
|
|
|
|
t.is(accessService.hasPermission.args[0][1], perms.ADMIN);
|
|
|
|
t.is(accessService.hasPermission.args[0][2], undefined);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should lookup projectId from params', async t => {
|
|
|
|
const accessService = {
|
|
|
|
hasPermission: sinon.fake(),
|
|
|
|
};
|
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
const func = rbacMiddleware(config, { featureToggleStore }, accessService);
|
2021-03-11 22:51:58 +01:00
|
|
|
|
|
|
|
const cb = sinon.fake();
|
|
|
|
const req: any = {
|
|
|
|
user: new User({
|
|
|
|
username: 'user',
|
|
|
|
id: 1,
|
|
|
|
}),
|
|
|
|
params: {
|
|
|
|
projectId: 'some-proj',
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
func(req, undefined, cb);
|
|
|
|
|
|
|
|
await req.checkRbac(perms.UPDATE_PROJECT);
|
|
|
|
|
|
|
|
t.is(accessService.hasPermission.args[0][2], req.params.projectId);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should lookup projectId from feature toggle', async t => {
|
|
|
|
const projectId = 'some-project-33';
|
|
|
|
const featureName = 'some-feature-toggle';
|
|
|
|
|
|
|
|
const accessService = {
|
|
|
|
hasPermission: sinon.fake(),
|
|
|
|
};
|
|
|
|
|
|
|
|
featureToggleStore.getProjectId = sinon.fake.returns(projectId);
|
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
const func = rbacMiddleware(config, { featureToggleStore }, accessService);
|
2021-03-11 22:51:58 +01:00
|
|
|
|
|
|
|
const cb = sinon.fake();
|
|
|
|
const req: any = {
|
|
|
|
user: new User({
|
|
|
|
username: 'user',
|
|
|
|
id: 1,
|
|
|
|
}),
|
|
|
|
params: {
|
|
|
|
featureName,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
func(req, undefined, cb);
|
|
|
|
|
|
|
|
await req.checkRbac(perms.UPDATE_FEATURE);
|
|
|
|
|
|
|
|
t.is(accessService.hasPermission.args[0][2], projectId);
|
|
|
|
t.is(featureToggleStore.getProjectId.firstArg, featureName);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should lookup projectId from data', async t => {
|
|
|
|
const projectId = 'some-project-33';
|
|
|
|
const featureName = 'some-feature-toggle';
|
|
|
|
|
|
|
|
const accessService = {
|
|
|
|
hasPermission: sinon.fake(),
|
|
|
|
};
|
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
const func = rbacMiddleware(config, { featureToggleStore }, accessService);
|
2021-03-11 22:51:58 +01:00
|
|
|
|
|
|
|
const cb = sinon.fake();
|
|
|
|
const req: any = {
|
|
|
|
user: new User({
|
|
|
|
username: 'user',
|
|
|
|
id: 1,
|
|
|
|
}),
|
|
|
|
params: {},
|
|
|
|
body: {
|
|
|
|
featureName,
|
|
|
|
project: projectId,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
func(req, undefined, cb);
|
|
|
|
|
|
|
|
await req.checkRbac(perms.CREATE_FEATURE);
|
|
|
|
|
|
|
|
t.is(accessService.hasPermission.args[0][2], projectId);
|
|
|
|
});
|