mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-07 01:16:28 +02:00
wip: environment for permissions
This commit is contained in:
parent
cc66cc4adf
commit
2ec427190e
@ -67,7 +67,7 @@ export class AccessStore implements IAccessStore {
|
||||
async getPermissionsForUser(userId: number): Promise<IUserPermission[]> {
|
||||
const stopTimer = this.timer('getPermissionsForUser');
|
||||
const rows = await this.db
|
||||
.select('project', 'permission')
|
||||
.select('project', 'permission', 'environment')
|
||||
.from<IUserPermission>(`${T.ROLE_PERMISSION} AS rp`)
|
||||
.leftJoin(`${T.ROLE_USER} AS ur`, 'ur.role_id', 'rp.role_id')
|
||||
.where('ur.user_id', '=', userId);
|
||||
@ -78,7 +78,7 @@ export class AccessStore implements IAccessStore {
|
||||
async getPermissionsForRole(roleId: number): Promise<IUserPermission[]> {
|
||||
const stopTimer = this.timer('getPermissionsForRole');
|
||||
const rows = await this.db
|
||||
.select('project', 'permission')
|
||||
.select('project', 'permission', 'environment')
|
||||
.from<IUserPermission>(`${T.ROLE_PERMISSION}`)
|
||||
.where('role_id', '=', roleId);
|
||||
stopTimer();
|
||||
@ -195,11 +195,13 @@ export class AccessStore implements IAccessStore {
|
||||
role_id: number,
|
||||
permissions: string[],
|
||||
projectId?: string,
|
||||
environment?: string,
|
||||
): Promise<void> {
|
||||
const rows = permissions.map((permission) => ({
|
||||
role_id,
|
||||
project: projectId,
|
||||
permission,
|
||||
environment,
|
||||
}));
|
||||
return this.db.batchInsert(T.ROLE_PERMISSION, rows);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import {
|
||||
} from '../types/model';
|
||||
|
||||
export const ALL_PROJECTS = '*';
|
||||
export const ALL_ENVS = '*';
|
||||
|
||||
const PROJECT_DESCRIPTION = {
|
||||
OWNER: 'Users with this role have full control over the project, and can add and manage other users within the project context, manage feature toggles within the project, and control advanced project features like archiving and deleting the project.',
|
||||
@ -81,9 +82,10 @@ export class AccessService {
|
||||
user: User,
|
||||
permission: string,
|
||||
projectId?: string,
|
||||
environment?: string,
|
||||
): Promise<boolean> {
|
||||
this.logger.info(
|
||||
`Checking permission=${permission}, userId=${user.id} projectId=${projectId}`,
|
||||
`Checking permission=${permission}, userId=${user.id}, projectId=${projectId}, environment=${environment}`,
|
||||
);
|
||||
|
||||
try {
|
||||
@ -96,6 +98,12 @@ export class AccessService {
|
||||
p.project === projectId ||
|
||||
p.project === ALL_PROJECTS,
|
||||
)
|
||||
.filter(
|
||||
(p) =>
|
||||
!p.environment ||
|
||||
p.environment === environment ||
|
||||
p.environment === ALL_ENVS,
|
||||
)
|
||||
.some(
|
||||
(p) =>
|
||||
p.permission === permission || p.permission === ADMIN,
|
||||
|
@ -1,4 +1,3 @@
|
||||
// Special
|
||||
export const ADMIN = 'ADMIN';
|
||||
export const CLIENT = 'CLIENT';
|
||||
export const NONE = 'NONE';
|
||||
@ -6,21 +5,32 @@ export const NONE = 'NONE';
|
||||
export const CREATE_FEATURE = 'CREATE_FEATURE';
|
||||
export const UPDATE_FEATURE = 'UPDATE_FEATURE';
|
||||
export const DELETE_FEATURE = 'DELETE_FEATURE';
|
||||
|
||||
export const CREATE_FEATURE_STRATEGY = 'CREATE_FEATURE_STRATEGY';
|
||||
export const UPDATE_FEATURE_STRATEGY = 'UPDATE_FEATURE_STRATEGY';
|
||||
export const DELETE_FEATURE_STRATEGY = 'DELETE_FEATURE_STRATEGY';
|
||||
export const UPDATE_FEATURE_ENVIRONMENT = 'UPDATE_FEATURE_ENVIRONMENT';
|
||||
|
||||
export const CREATE_STRATEGY = 'CREATE_STRATEGY';
|
||||
export const UPDATE_STRATEGY = 'UPDATE_STRATEGY';
|
||||
export const DELETE_STRATEGY = 'DELETE_STRATEGY';
|
||||
|
||||
export const UPDATE_APPLICATION = 'UPDATE_APPLICATION';
|
||||
export const CREATE_CONTEXT_FIELD = 'CREATE_CONTEXT_FIELD';
|
||||
export const UPDATE_CONTEXT_FIELD = 'UPDATE_CONTEXT_FIELD';
|
||||
export const DELETE_CONTEXT_FIELD = 'DELETE_CONTEXT_FIELD';
|
||||
|
||||
export const CREATE_PROJECT = 'CREATE_PROJECT';
|
||||
export const UPDATE_PROJECT = 'UPDATE_PROJECT';
|
||||
export const DELETE_PROJECT = 'DELETE_PROJECT';
|
||||
|
||||
export const CREATE_ADDON = 'CREATE_ADDON';
|
||||
export const UPDATE_ADDON = 'UPDATE_ADDON';
|
||||
export const DELETE_ADDON = 'DELETE_ADDON';
|
||||
|
||||
export const READ_ROLE = 'READ_ROLE';
|
||||
export const UPDATE_ROLE = 'UPDATE_ROLE';
|
||||
|
||||
export const UPDATE_API_TOKEN = 'UPDATE_API_TOKEN';
|
||||
export const CREATE_API_TOKEN = 'CREATE_API_TOKEN';
|
||||
export const DELETE_API_TOKEN = 'DELETE_API_TOKEN';
|
||||
|
@ -2,6 +2,7 @@ import { Store } from './store';
|
||||
|
||||
export interface IUserPermission {
|
||||
project?: string;
|
||||
environment?: string;
|
||||
permission: string;
|
||||
}
|
||||
|
||||
@ -39,6 +40,7 @@ export interface IAccessStore extends Store<IRole, number> {
|
||||
role_id: number,
|
||||
permissions: string[],
|
||||
projectId?: string,
|
||||
environment?: string,
|
||||
): Promise<void>;
|
||||
removePermissionFromRole(
|
||||
roleId: number,
|
||||
|
@ -0,0 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
exports.up = function (db, cb) {
|
||||
db.runSql(
|
||||
'ALTER TABLE role_permission ADD COLUMN environment varchar(255);',
|
||||
cb,
|
||||
);
|
||||
};
|
||||
|
||||
exports.down = function (db, cb) {
|
||||
db.runSql('ALTER TABLE role_permission DROP COLUMN environment', cb);
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
import dbInit from '../helpers/database-init';
|
||||
import dbInit, { ITestDb } from '../helpers/database-init';
|
||||
import getLogger from '../../fixtures/no-logger';
|
||||
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
@ -9,9 +9,10 @@ import {
|
||||
|
||||
import * as permissions from '../../../lib/types/permissions';
|
||||
import { RoleName } from '../../../lib/types/model';
|
||||
import { IUnleashStores } from '../../../lib/types';
|
||||
|
||||
let db;
|
||||
let stores;
|
||||
let db: ITestDb;
|
||||
let stores: IUnleashStores;
|
||||
let accessService;
|
||||
|
||||
let editorUser;
|
||||
@ -453,3 +454,49 @@ test('should not crash if user does not have permission', async () => {
|
||||
|
||||
expect(hasAccess).toBe(false);
|
||||
});
|
||||
|
||||
test('should support permission with "ALL" environment requirement', async () => {
|
||||
const { userStore, accessStore } = stores;
|
||||
|
||||
const user = await userStore.insert({
|
||||
name: 'Some User',
|
||||
email: 'randomEnv1@getunleash.io',
|
||||
});
|
||||
|
||||
await accessService.setUserRootRole(user.id, readRole.id);
|
||||
|
||||
const customRole = await accessStore.createRole(
|
||||
'Power user',
|
||||
'custom',
|
||||
'default',
|
||||
'Grants access to modify all environments',
|
||||
);
|
||||
|
||||
const { CREATE_FEATURE_STRATEGY } = permissions;
|
||||
|
||||
await accessStore.addPermissionsToRole(
|
||||
customRole.id,
|
||||
[CREATE_FEATURE_STRATEGY],
|
||||
'default',
|
||||
ALL_PROJECTS,
|
||||
);
|
||||
|
||||
await accessStore.addUserToRole(user.id, customRole.id);
|
||||
|
||||
const hasAccess = await accessService.hasPermission(
|
||||
user,
|
||||
CREATE_FEATURE_STRATEGY,
|
||||
'default',
|
||||
'production',
|
||||
);
|
||||
|
||||
expect(hasAccess).toBe(true);
|
||||
|
||||
const hasNotAccess = await accessService.hasPermission(
|
||||
user,
|
||||
CREATE_FEATURE_STRATEGY,
|
||||
'default',
|
||||
'development',
|
||||
);
|
||||
expect(hasNotAccess).toBe(true);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user