mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-02 01:17:58 +02:00
feat: Patch db migration to handle old stucture
This commit is contained in:
parent
42a5105736
commit
c547b8a2b9
@ -8,11 +8,7 @@ import {
|
||||
IRole,
|
||||
IUserPermission,
|
||||
} from '../types/stores/access-store';
|
||||
import {
|
||||
IAvailablePermissions,
|
||||
IEnvironmentPermission,
|
||||
IPermission,
|
||||
} from 'lib/types/model';
|
||||
import { IPermission } from 'lib/types/model';
|
||||
|
||||
const T = {
|
||||
ROLE_USER: 'role_user',
|
||||
@ -26,7 +22,9 @@ interface IPermissionRow {
|
||||
id: number;
|
||||
permission: string;
|
||||
display_name: string;
|
||||
environment: string;
|
||||
environment?: string;
|
||||
type: string;
|
||||
project?: string;
|
||||
}
|
||||
|
||||
export class AccessStore implements IAccessStore {
|
||||
@ -46,20 +44,6 @@ export class AccessStore implements IAccessStore {
|
||||
});
|
||||
}
|
||||
|
||||
async setupPermissionsForEnvironment(
|
||||
environmentName: string,
|
||||
permissions: string[],
|
||||
): Promise<void> {
|
||||
const rows = permissions.map((permission) => {
|
||||
return {
|
||||
permission: permission,
|
||||
display_name: '',
|
||||
environment: environmentName,
|
||||
};
|
||||
});
|
||||
await this.db.batchInsert(T.PERMISSIONS, rows);
|
||||
}
|
||||
|
||||
async delete(key: number): Promise<void> {
|
||||
await this.db(T.ROLES).where({ id: key }).del();
|
||||
}
|
||||
@ -91,51 +75,49 @@ export class AccessStore implements IAccessStore {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
async getAvailablePermissions(): Promise<IAvailablePermissions> {
|
||||
async getAvailablePermissions(): Promise<IPermission[]> {
|
||||
const rows = await this.db
|
||||
.select([
|
||||
'p.id',
|
||||
'p.permission',
|
||||
'p.environment',
|
||||
'pt.display_name',
|
||||
])
|
||||
.join(
|
||||
`${T.PERMISSION_TYPES} AS pt`,
|
||||
'pt.permission',
|
||||
'p.permission',
|
||||
)
|
||||
.where('pt.type', 'project')
|
||||
.orWhere('pt.type', 'environment')
|
||||
.select(['id', 'permission', 'type', 'display_name'])
|
||||
.where('type', 'project')
|
||||
.orWhere('type', 'environment')
|
||||
.from(`${T.PERMISSIONS} as p`);
|
||||
return rows.map(this.mapPermission);
|
||||
// .map(mapPermission)
|
||||
// const rows = await this.db
|
||||
// .select(['p.id', 'p.permission', 'p.environment', 'p.display_name'])
|
||||
// .join(`${T.ROLE_PERMISSION} AS rp`, 'rp.permission_id', 'p.id')
|
||||
// .where('pt.type', 'project')
|
||||
// .orWhere('pt.type', 'environment')
|
||||
// .from(`${T.PERMISSIONS} as p`);
|
||||
|
||||
let projectPermissions: IPermission[] = [];
|
||||
let rawEnvironments = new Map<string, IPermissionRow[]>();
|
||||
// let projectPermissions: IPermission[] = [];
|
||||
// let rawEnvironments = new Map<string, IPermissionRow[]>();
|
||||
|
||||
for (let permission of rows) {
|
||||
if (!permission.environment) {
|
||||
projectPermissions.push(this.mapPermission(permission));
|
||||
} else {
|
||||
if (!rawEnvironments.get(permission.environment)) {
|
||||
rawEnvironments.set(permission.environment, []);
|
||||
}
|
||||
rawEnvironments.get(permission.environment).push(permission);
|
||||
}
|
||||
}
|
||||
let allEnvironmentPermissions: Array<IEnvironmentPermission> =
|
||||
Array.from(rawEnvironments).map(
|
||||
([environmentName, environmentPermissions]) => {
|
||||
return {
|
||||
name: environmentName,
|
||||
permissions: environmentPermissions.map(
|
||||
this.mapPermission,
|
||||
),
|
||||
};
|
||||
},
|
||||
);
|
||||
return {
|
||||
project: projectPermissions,
|
||||
environments: allEnvironmentPermissions,
|
||||
};
|
||||
// for (let permission of rows) {
|
||||
// if (!permission.environment) {
|
||||
// projectPermissions.push(this.mapPermission(permission));
|
||||
// } else {
|
||||
// if (!rawEnvironments.get(permission.environment)) {
|
||||
// rawEnvironments.set(permission.environment, []);
|
||||
// }
|
||||
// rawEnvironments.get(permission.environment).push(permission);
|
||||
// }
|
||||
// }
|
||||
// let allEnvironmentPermissions: Array<IEnvironmentPermission> =
|
||||
// Array.from(rawEnvironments).map(
|
||||
// ([environmentName, environmentPermissions]) => {
|
||||
// return {
|
||||
// name: environmentName,
|
||||
// permissions: environmentPermissions.map(
|
||||
// this.mapPermission,
|
||||
// ),
|
||||
// };
|
||||
// },
|
||||
// );
|
||||
// return {
|
||||
// project: projectPermissions,
|
||||
// environments: allEnvironmentPermissions,
|
||||
// };
|
||||
}
|
||||
|
||||
mapPermission(permission: IPermissionRow): IPermission {
|
||||
@ -143,32 +125,45 @@ export class AccessStore implements IAccessStore {
|
||||
id: permission.id,
|
||||
name: permission.permission,
|
||||
displayName: permission.display_name,
|
||||
type: permission.type,
|
||||
};
|
||||
}
|
||||
|
||||
async getPermissionsForUser(userId: number): Promise<IUserPermission[]> {
|
||||
const stopTimer = this.timer('getPermissionsForUser');
|
||||
const rows = await this.db
|
||||
.select('project', 'permission', 'environment')
|
||||
.from<IUserPermission>(`${T.ROLE_PERMISSION} AS rp`)
|
||||
.select('project', 'permission', 'environment', 'type')
|
||||
.from<IPermissionRow>(`${T.ROLE_PERMISSION} AS rp`)
|
||||
.join(`${T.ROLE_USER} AS ur`, 'ur.role_id', 'rp.role_id')
|
||||
.join(`${T.PERMISSIONS} AS p`, 'p.id', 'rp.permission_id')
|
||||
.where('ur.user_id', '=', userId);
|
||||
stopTimer();
|
||||
return rows;
|
||||
return rows.map(this.mapUserPermission);
|
||||
}
|
||||
|
||||
mapUserPermission(row: IPermissionRow): IUserPermission {
|
||||
const project = row.type !== 'root' ? row.project : undefined;
|
||||
const environment =
|
||||
row.type === 'environment' ? row.environment : undefined;
|
||||
return {
|
||||
project,
|
||||
environment,
|
||||
permission: row.permission,
|
||||
};
|
||||
}
|
||||
|
||||
async getPermissionsForRole(roleId: number): Promise<IPermission[]> {
|
||||
const stopTimer = this.timer('getPermissionsForRole');
|
||||
const rows = await this.db
|
||||
.select('p.id', 'p.permission', 'p.environment', 'pt.display_name')
|
||||
.select(
|
||||
'p.id',
|
||||
'p.permission',
|
||||
'rp.environment',
|
||||
'p.display_name',
|
||||
'p.type',
|
||||
)
|
||||
.from<IPermission>(`${T.ROLE_PERMISSION} as rp`)
|
||||
.join(`${T.PERMISSIONS} as p`, 'p.id', 'rp.permission_id')
|
||||
.join(
|
||||
`${T.PERMISSION_TYPES} as pt`,
|
||||
'pt.permission',
|
||||
'p.permission',
|
||||
)
|
||||
.where('rp.role_id', '=', roleId);
|
||||
stopTimer();
|
||||
return rows.map((permission) => {
|
||||
@ -177,6 +172,7 @@ export class AccessStore implements IAccessStore {
|
||||
name: permission.permission,
|
||||
environment: permission.environment,
|
||||
displayName: permission.display_name,
|
||||
type: permission.type,
|
||||
};
|
||||
});
|
||||
}
|
||||
@ -189,6 +185,7 @@ export class AccessStore implements IAccessStore {
|
||||
return {
|
||||
role_id,
|
||||
permission_id: x.id,
|
||||
environment: x.environment,
|
||||
};
|
||||
});
|
||||
this.db.batchInsert(T.ROLE_PERMISSION, rows);
|
||||
@ -276,19 +273,18 @@ export class AccessStore implements IAccessStore {
|
||||
permissions: string[],
|
||||
environment?: string,
|
||||
): Promise<void> {
|
||||
const result = await this.db.raw(
|
||||
`SELECT id FROM ${T.PERMISSIONS} where environment = ? and permission = ANY(?)`,
|
||||
[environment, permissions],
|
||||
);
|
||||
const rows = await this.db
|
||||
.select('id as permissionId')
|
||||
.from<number>(T.PERMISSIONS)
|
||||
.whereIn('permission', permissions);
|
||||
|
||||
const ids = result.rows.map((x) => x.id);
|
||||
|
||||
const rows = ids.map((permission_id) => ({
|
||||
const newRoles = rows.map((row) => ({
|
||||
role_id,
|
||||
permission_id,
|
||||
environment,
|
||||
permission_id: row.permissionId,
|
||||
}));
|
||||
|
||||
return this.db.batchInsert(T.ROLE_PERMISSION, rows);
|
||||
return this.db.batchInsert(T.ROLE_PERMISSION, newRoles);
|
||||
}
|
||||
|
||||
async removePermissionFromRole(
|
||||
@ -296,17 +292,18 @@ export class AccessStore implements IAccessStore {
|
||||
permission: string,
|
||||
environment?: string,
|
||||
): Promise<void> {
|
||||
const result = await this.db.raw(
|
||||
`SELECT id FROM ${T.PERMISSIONS} where environment = ? and permission = ?`,
|
||||
[environment, permission],
|
||||
);
|
||||
const rows = await this.db
|
||||
.select('id as permissionId')
|
||||
.from<number>(T.PERMISSIONS)
|
||||
.where('permission', permission);
|
||||
|
||||
const permissionId = result.first();
|
||||
const permissionId = rows[0].permissionId;
|
||||
|
||||
return this.db(T.ROLE_PERMISSION)
|
||||
.where({
|
||||
role_id,
|
||||
permissionId,
|
||||
permission_id: permissionId,
|
||||
environment,
|
||||
})
|
||||
.delete();
|
||||
}
|
||||
|
@ -8,11 +8,7 @@ import { Logger } from '../../../logger';
|
||||
import {
|
||||
CREATE_FEATURE,
|
||||
DELETE_FEATURE,
|
||||
CREATE_FEATURE_STRATEGY,
|
||||
DELETE_FEATURE_STRATEGY,
|
||||
UPDATE_FEATURE,
|
||||
UPDATE_FEATURE_ENVIRONMENT,
|
||||
UPDATE_FEATURE_STRATEGY,
|
||||
} from '../../../types/permissions';
|
||||
import {
|
||||
FeatureToggleDTO,
|
||||
@ -79,11 +75,7 @@ export default class ProjectFeaturesController extends Controller {
|
||||
|
||||
// activation strategies
|
||||
this.get(`${PATH_STRATEGIES}`, this.getStrategies);
|
||||
this.post(
|
||||
`${PATH_STRATEGIES}`,
|
||||
this.addStrategy,
|
||||
CREATE_FEATURE_STRATEGY,
|
||||
);
|
||||
this.post(`${PATH_STRATEGIES}`, this.addStrategy, UPDATE_FEATURE);
|
||||
this.get(`${PATH_STRATEGY}`, this.getStrategy);
|
||||
this.put(`${PATH_STRATEGY}`, this.updateStrategy, UPDATE_FEATURE);
|
||||
this.patch(`${PATH_STRATEGY}`, this.patchStrategy, UPDATE_FEATURE);
|
||||
|
@ -21,6 +21,7 @@ import {
|
||||
} from '../types/model';
|
||||
import { IRoleStore } from 'lib/types/stores/role-store';
|
||||
import NameExistsError from '../error/name-exists-error';
|
||||
import { IEnvironmentStore } from 'lib/types/stores/environment-store';
|
||||
|
||||
export const ALL_PROJECTS = '*';
|
||||
export const ALL_ENVS = '*';
|
||||
@ -63,6 +64,8 @@ export class AccessService {
|
||||
|
||||
private roleStore: IRoleStore;
|
||||
|
||||
private environmentStore: IEnvironmentStore;
|
||||
|
||||
private logger: Logger;
|
||||
|
||||
constructor(
|
||||
@ -70,12 +73,17 @@ export class AccessService {
|
||||
accessStore,
|
||||
userStore,
|
||||
roleStore,
|
||||
}: Pick<IUnleashStores, 'accessStore' | 'userStore' | 'roleStore'>,
|
||||
environmentStore,
|
||||
}: Pick<
|
||||
IUnleashStores,
|
||||
'accessStore' | 'userStore' | 'roleStore' | 'environmentStore'
|
||||
>,
|
||||
{ getLogger }: { getLogger: Function },
|
||||
) {
|
||||
this.store = accessStore;
|
||||
this.userStore = userStore;
|
||||
this.roleStore = roleStore;
|
||||
this.environmentStore = environmentStore;
|
||||
this.logger = getLogger('/services/access-service.ts');
|
||||
}
|
||||
|
||||
@ -98,7 +106,8 @@ export class AccessService {
|
||||
|
||||
try {
|
||||
const userP = await this.getPermissionsForUser(user);
|
||||
console.log('My user permissions are', userP);
|
||||
console.log('Got the following perms back', userP);
|
||||
|
||||
return userP
|
||||
.filter(
|
||||
(p) =>
|
||||
@ -135,7 +144,30 @@ export class AccessService {
|
||||
}
|
||||
|
||||
async getPermissions(): Promise<IAvailablePermissions> {
|
||||
return this.store.getAvailablePermissions();
|
||||
const bindablePermissions = await this.store.getAvailablePermissions();
|
||||
const environments = await this.environmentStore.getAll();
|
||||
|
||||
const projectPermissions = bindablePermissions.filter((x) => {
|
||||
return x.type === 'project';
|
||||
});
|
||||
|
||||
const environmentPermissions = bindablePermissions.filter((perm) => {
|
||||
return perm.type === 'environment';
|
||||
});
|
||||
|
||||
const allEnvironmentPermissions = environments.map((env) => {
|
||||
return {
|
||||
name: env.name,
|
||||
permissions: environmentPermissions.map((p) => {
|
||||
return { environment: env.name, ...p };
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
project: projectPermissions,
|
||||
environments: allEnvironmentPermissions,
|
||||
};
|
||||
}
|
||||
|
||||
async addUserToRole(
|
||||
@ -331,12 +363,6 @@ export class AccessService {
|
||||
|
||||
const ownerRole = await this.roleStore.getRoleByName(RoleName.OWNER);
|
||||
|
||||
await this.store.addPermissionsToRole(
|
||||
ownerRole.id,
|
||||
PROJECT_ADMIN,
|
||||
projectId,
|
||||
);
|
||||
|
||||
// TODO: remove this when all users is guaranteed to have a unique id.
|
||||
if (owner.id) {
|
||||
this.logger.info(
|
||||
@ -344,14 +370,6 @@ export class AccessService {
|
||||
);
|
||||
await this.store.addUserToRole(owner.id, ownerRole.id, projectId);
|
||||
}
|
||||
|
||||
const memberRole = await this.roleStore.getRoleByName(RoleName.MEMBER);
|
||||
|
||||
await this.store.addPermissionsToRole(
|
||||
memberRole.id,
|
||||
PROJECT_REGULAR,
|
||||
projectId,
|
||||
);
|
||||
}
|
||||
|
||||
async removeDefaultProjectRoles(
|
||||
@ -409,7 +427,7 @@ export class AccessService {
|
||||
}
|
||||
|
||||
async updateRole(role: IRoleUpdate): Promise<ICustomRole> {
|
||||
await this.validateRole(role);
|
||||
// await this.validateRole(role);
|
||||
const baseRole = {
|
||||
id: role.id,
|
||||
name: role.name,
|
||||
|
@ -224,6 +224,7 @@ export interface IPermission {
|
||||
id: number;
|
||||
name: string;
|
||||
displayName: string;
|
||||
type: string;
|
||||
environment?: string;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
//Special
|
||||
export const ADMIN = 'ADMIN';
|
||||
export const CLIENT = 'CLIENT';
|
||||
export const NONE = 'NONE';
|
||||
@ -5,32 +6,25 @@ 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';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { IAvailablePermissions, IPermission } from '../model';
|
||||
import { IPermission } from '../model';
|
||||
import { Store } from './store';
|
||||
|
||||
export interface IUserPermission {
|
||||
@ -29,7 +29,7 @@ export interface IUserRole {
|
||||
userId: number;
|
||||
}
|
||||
export interface IAccessStore extends Store<IRole, number> {
|
||||
getAvailablePermissions(): Promise<IAvailablePermissions>;
|
||||
getAvailablePermissions(): Promise<IPermission[]>;
|
||||
getPermissionsForUser(userId: number): Promise<IUserPermission[]>;
|
||||
getPermissionsForRole(roleId: number): Promise<IPermission[]>;
|
||||
unlinkUserRoles(userId: number): Promise<void>;
|
||||
@ -41,10 +41,6 @@ export interface IAccessStore extends Store<IRole, number> {
|
||||
role_id: number,
|
||||
permissions: IPermission[],
|
||||
): Promise<void>;
|
||||
setupPermissionsForEnvironment(
|
||||
environmentName: string,
|
||||
permissions: string[],
|
||||
): Promise<void>;
|
||||
addUserToRole(
|
||||
userId: number,
|
||||
roleId: number,
|
||||
|
@ -15,4 +15,5 @@ export interface IEnvironmentStore extends Store<IEnvironment, string> {
|
||||
): Promise<void>;
|
||||
updateSortOrder(id: string, value: number): Promise<void>;
|
||||
importEnvironments(environments: IEnvironment[]): Promise<IEnvironment[]>;
|
||||
delete(name: string): Promise<void>;
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
'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,30 +0,0 @@
|
||||
exports.up = function (db, cb) {
|
||||
db.runSql(
|
||||
`
|
||||
INSERT INTO role_permission (role_id, project, permission, environment) VALUES ('2', 'default', 'CREATE_FEATURE_STRATEGY', 'default');
|
||||
INSERT INTO role_permission (role_id, project, permission, environment) VALUES ('2', 'default', 'UPDATE_FEATURE_STRATEGY', 'default');
|
||||
INSERT INTO role_permission (role_id, project, permission, environment) VALUES ('2', 'default', 'UPDATE_FEATURE_ENVIRONMENT', 'default');
|
||||
INSERT INTO role_permission (role_id, project, permission, environment) VALUES ('2', 'default', 'DELETE_FEATURE_STRATEGY', 'default');
|
||||
|
||||
INSERT INTO role_permission (role_id, project, permission, environment) VALUES ('2', 'default', 'CREATE_FEATURE_STRATEGY', 'development');
|
||||
INSERT INTO role_permission (role_id, project, permission, environment) VALUES ('2', 'default', 'UPDATE_FEATURE_STRATEGY', 'development');
|
||||
INSERT INTO role_permission (role_id, project, permission, environment) VALUES ('2', 'default', 'UPDATE_FEATURE_ENVIRONMENT', 'development');
|
||||
INSERT INTO role_permission (role_id, project, permission, environment) VALUES ('2', 'default', 'DELETE_FEATURE_STRATEGY', 'development');
|
||||
|
||||
INSERT INTO role_permission (role_id, project, permission, environment) VALUES ('2', 'default', 'CREATE_FEATURE_STRATEGY', 'production');
|
||||
INSERT INTO role_permission (role_id, project, permission, environment) VALUES ('2', 'default', 'UPDATE_FEATURE_STRATEGY', 'production');
|
||||
INSERT INTO role_permission (role_id, project, permission, environment) VALUES ('2', 'default', 'UPDATE_FEATURE_ENVIRONMENT', 'production');
|
||||
INSERT INTO role_permission (role_id, project, permission, environment) VALUES ('2', 'default', 'DELETE_FEATURE_STRATEGY', 'production');
|
||||
`,
|
||||
cb,
|
||||
);
|
||||
};
|
||||
|
||||
exports.down = function (db, cb) {
|
||||
db.runSql(
|
||||
`
|
||||
DELETE FROM role_permission WHERE environment IS NOT NULL;
|
||||
`,
|
||||
cb,
|
||||
);
|
||||
};
|
@ -2,80 +2,174 @@ exports.up = function (db, cb) {
|
||||
db.runSql(
|
||||
`
|
||||
CREATE TABLE IF NOT EXISTS permissions
|
||||
( id SERIAL PRIMARY KEY,
|
||||
(
|
||||
id SERIAL PRIMARY KEY,
|
||||
permission VARCHAR(255) NOT NULL,
|
||||
environment VARCHAR(255),
|
||||
display_name TEXT,
|
||||
type VARCHAR(255),
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS permission_types (
|
||||
permission VARCHAR(255),
|
||||
display_name TEXT,
|
||||
type VARCHAR(255)
|
||||
);
|
||||
|
||||
INSERT INTO permissions (permission, environment) (select distinct permission,environment from role_permission);
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('ADMIN', 'Admin', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('CREATE_FEATURE', 'Create Feature Toggles', 'project');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('CREATE_STRATEGY','Create Strategies', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('CREATE_ADDON', 'Create Addons', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('DELETE_ADDON', 'Delete Addons', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('UPDATE_ADDON', 'Update Addons', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('UPDATE_FEATURE', 'Update Feature Toggles', 'project');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('DELETE_FEATURE', 'Delete Feature Toggles', 'project');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('UPDATE_APPLICATION', 'Update Applications', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('UPDATE_TAG_TYPE', 'Update Tag Types', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('DELETE_TAG_TYPE', 'Delete Tag Types', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('CREATE_PROJECT', 'Create Projects', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('UPDATE_PROJECT', 'Update Projects', 'project');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('DELETE_PROJECT', 'Delete Projects', 'project');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('UPDATE_STRATEGY', 'Update Strategies', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('DELETE_STRATEGY', 'Delete Strategies', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('UPDATE_CONTEXT_FIELD', 'Update Context Fields', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('CREATE_CONTEXT_FIELD', 'Create Context Fields', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('DELETE_CONTEXT_FIELD', 'Delete Context Fields', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('READ_ROLE', 'Read Roles', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('UPDATE_ROLE', 'Update Roles', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('UPDATE_API_TOKEN', 'Update API Tokens', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('CREATE_API_TOKEN', 'Create API Tokens', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('DELETE_API_TOKEN', 'Delete API Tokens', 'root');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('CREATE_FEATURE_STRATEGY', 'Create Feature Strategies', 'environment');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('UPDATE_FEATURE_STRATEGY', 'Update Feature Strategies', 'environment');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('DELETE_FEATURE_STRATEGY', 'Delete Feature Strategies', 'environment');
|
||||
INSERT INTO permissions (permission, display_name, type) VALUES ('UPDATE_FEATURE_ENVIRONMENT', 'Enable/disable Toggles in Environment', 'environment');
|
||||
|
||||
ALTER TABLE role_user ADD COLUMN
|
||||
project VARCHAR(255);
|
||||
|
||||
UPDATE role_user
|
||||
SET project = roles.project
|
||||
FROM roles
|
||||
WHERE role_user.role_id = roles.id;
|
||||
|
||||
ALTER TABLE role_user DROP CONSTRAINT role_user_pkey;
|
||||
UPDATE role_user SET project = '*' WHERE project IS NULL;
|
||||
ALTER TABLE role_user ADD PRIMARY KEY (role_id, user_id, project);
|
||||
|
||||
ALTER TABLE roles DROP COLUMN project;
|
||||
|
||||
ALTER TABLE roles
|
||||
ADD COLUMN
|
||||
updated_at TIMESTAMP WITH TIME ZONE;
|
||||
|
||||
ALTER TABLE role_permission
|
||||
ADD COLUMN
|
||||
permission_id INTEGER;
|
||||
permission_id INTEGER,
|
||||
ADD COLUMN
|
||||
environment VARCHAR (100);
|
||||
|
||||
UPDATE role_permission
|
||||
SET permission_id = permissions.id
|
||||
FROM permissions
|
||||
WHERE
|
||||
(role_permission.environment = permissions.environment
|
||||
OR (role_permission.environment IS NULL AND permissions.environment IS NULL))
|
||||
AND
|
||||
role_permission.permission = permissions.permission;
|
||||
CREATE TEMPORARY TABLE temp_primary_roles
|
||||
(
|
||||
id INTEGER,
|
||||
name TEXT,
|
||||
description TEXT,
|
||||
type TEXT,
|
||||
project TEXT,
|
||||
created_at DATE
|
||||
)
|
||||
ON COMMIT DROP;
|
||||
|
||||
CREATE TEMPORARY TABLE temp_discard_roles
|
||||
(
|
||||
id INTEGER,
|
||||
name TEXT,
|
||||
description TEXT,
|
||||
type TEXT,
|
||||
project TEXT,
|
||||
created_at DATE
|
||||
)
|
||||
ON COMMIT DROP;
|
||||
|
||||
INSERT INTO temp_primary_roles select distinct on (name) id, name ,description, type, project, created_at from roles order by name, id;
|
||||
|
||||
INSERT INTO temp_discard_roles SELECT r.id, r.name, r.description, r.type, r.project, r.created_at FROM roles r
|
||||
LEFT JOIN temp_primary_roles tpr ON r.id = tpr.id
|
||||
WHERE tpr.id IS NULL;
|
||||
|
||||
UPDATE role_user
|
||||
SET project = tpr.project
|
||||
FROM temp_primary_roles tpr
|
||||
WHERE tpr.id = role_user.role_id;
|
||||
|
||||
ALTER TABLE role_user DROP CONSTRAINT role_user_pkey;
|
||||
|
||||
WITH rtu as (
|
||||
SELECT tdr.id as old_role_id, tpr.id as new_role_id, tdr.project as project FROM temp_discard_roles tdr
|
||||
JOIN temp_primary_roles tpr ON tdr.name = tpr.name
|
||||
)
|
||||
UPDATE role_user
|
||||
SET project = rtu.project, role_id = rtu.new_role_id
|
||||
FROM rtu
|
||||
WHERE rtu.old_role_id = role_user.role_id;
|
||||
|
||||
UPDATE role_user SET project = '*' WHERE project IS NULL;
|
||||
ALTER TABLE role_user ADD PRIMARY KEY (role_id, user_id, project);
|
||||
|
||||
DELETE FROM roles WHERE EXISTS
|
||||
(
|
||||
SELECT 1 FROM temp_discard_roles tdr WHERE tdr.id = roles.id
|
||||
);
|
||||
|
||||
DELETE FROM role_permission;
|
||||
|
||||
ALTER TABLE roles DROP COLUMN project;
|
||||
ALTER TABLE role_permission
|
||||
DROP COLUMN project,
|
||||
DROP COLUMN permission,
|
||||
DROP COLUMN environment;
|
||||
DROP COLUMN project,
|
||||
DROP COLUMN permission;
|
||||
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('ADMIN', 'Admin', 'root');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('CLIENT', 'Client', 'root');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('CREATE_STRATEGY','Create Strategies', 'root');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('CREATE_ADDON', 'Create Addons', 'root');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('DELETE_ADDON', 'Delete Addons', 'root');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('UPDATE_ADDON', 'Update Addons', 'root');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('CREATE_FEATURE', 'Create Feature Toggles', 'project');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('UPDATE_FEATURE', 'Update Feature Toggles', 'project');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('DELETE_FEATURE', 'Delete Feature Toggles', 'project');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('UPDATE_APPLICATION', 'Update Applications', 'root');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('UPDATE_TAG_TYPE', 'Update Tag Types', 'root');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('DELETE_TAG_TYPE', 'Delete Tag Types', 'root');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('CREATE_PROJECT', 'Create Projects', 'root');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('UPDATE_PROJECT', 'Update Projects', 'project');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('DELETE_PROJECT', 'Delete Projects', 'project');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('UPDATE_FEATURE_STRATEGY', 'Update Strategies on Toggles', 'environment');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('CREATE_FEATURE_STRATEGY', 'Add Strategies to Toggles', 'environment');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('DELETE_FEATURE_STRATEGY', 'Remove Strategies from Toggles', 'environment');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('UPDATE_STRATEGY', 'Update Strategies', 'root');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('DELETE_STRATEGY', 'Delete Strategies', 'root');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('UPDATE_FEATURE_ENVIRONMENT', 'Enable/Disable Toggles for Environments', 'environment');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('UPDATE_CONTEXT_FIELD', 'Update Context Fields', 'root');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('CREATE_CONTEXT_FIELD', 'Create Context Fields', 'root');
|
||||
INSERT INTO permission_types (permission, display_name, type) VALUES ('DELETE_CONTEXT_FIELD', 'Delete Context Fields', 'root');
|
||||
INSERT INTO role_permission (role_id, permission_id, environment)
|
||||
SELECT
|
||||
(SELECT id as role_id from roles WHERE name = 'Editor' LIMIT 1),
|
||||
p.id as permission_id,
|
||||
'*' as environment
|
||||
FROM permissions p
|
||||
WHERE p.permission IN
|
||||
('CREATE_STRATEGY',
|
||||
'UPDATE_STRATEGY',
|
||||
'DELETE_STRATEGY',
|
||||
'UPDATE_APPLICATION',
|
||||
'CREATE_CONTEXT_FIELD',
|
||||
'UPDATE_CONTEXT_FIELD',
|
||||
'DELETE_CONTEXT_FIELD',
|
||||
'CREATE_PROJECT',
|
||||
'CREATE_ADDON',
|
||||
'UPDATE_ADDON',
|
||||
'DELETE_ADDON',
|
||||
'UPDATE_PROJECT',
|
||||
'DELETE_PROJECT',
|
||||
'CREATE_FEATURE',
|
||||
'UPDATE_FEATURE',
|
||||
'DELETE_FEATURE',
|
||||
'UPDATE_TAG_TYPE',
|
||||
'DELETE_TAG_TYPE');
|
||||
|
||||
INSERT INTO role_permission (role_id, permission_id, environment)
|
||||
SELECT
|
||||
(SELECT id as role_id from roles WHERE name = 'Owner' LIMIT 1),
|
||||
p.id as permission_id,
|
||||
e.name as environment
|
||||
FROM permissions p
|
||||
CROSS JOIN environments e
|
||||
WHERE p.permission IN
|
||||
('UPDATE_PROJECT',
|
||||
'DELETE_PROJECT',
|
||||
'CREATE_FEATURE',
|
||||
'UPDATE_FEATURE',
|
||||
'DELETE_FEATURE');
|
||||
|
||||
INSERT INTO role_permission (role_id, permission_id, environment)
|
||||
SELECT
|
||||
(SELECT id as role_id from roles WHERE name = 'Member' LIMIT 1),
|
||||
p.id as permission_id,
|
||||
e.name as environment
|
||||
FROM permissions p
|
||||
CROSS JOIN environments e
|
||||
WHERE p.permission IN
|
||||
('CREATE_FEATURE',
|
||||
'UPDATE_FEATURE',
|
||||
'DELETE_FEATURE');
|
||||
|
||||
INSERT INTO role_permission (role_id, permission_id, environment)
|
||||
SELECT
|
||||
(SELECT id as role_id from roles WHERE name = 'Admin' LIMIT 1),
|
||||
p.id as permission_id,
|
||||
'*' environment
|
||||
FROM permissions p
|
||||
WHERE p.permission = 'ADMIN'
|
||||
`,
|
||||
cb,
|
||||
);
|
||||
|
@ -178,13 +178,13 @@ test('should remove CREATE_FEATURE on default environment', async () => {
|
||||
await accessService.addPermissionToRole(
|
||||
editRole.id,
|
||||
permissions.CREATE_FEATURE,
|
||||
'default',
|
||||
'*',
|
||||
);
|
||||
|
||||
await accessService.removePermissionFromRole(
|
||||
editRole.id,
|
||||
permissions.CREATE_FEATURE,
|
||||
'default',
|
||||
'*',
|
||||
);
|
||||
|
||||
expect(
|
||||
@ -264,7 +264,7 @@ test('should grant user access to project', async () => {
|
||||
} = permissions;
|
||||
const project = 'another-project';
|
||||
const user = editorUser;
|
||||
const sUser = await createUserEditorAccess(
|
||||
const sUser = await createUserViewerAccess(
|
||||
'Some Random',
|
||||
'random@getunleash.io',
|
||||
);
|
||||
@ -273,16 +273,16 @@ test('should grant user access to project', async () => {
|
||||
const projectRole = await accessService.getRoleByName(RoleName.MEMBER);
|
||||
await accessService.addUserToRole(sUser.id, projectRole.id, project);
|
||||
|
||||
// Should be able to update feature toggles inside the project
|
||||
expect(
|
||||
await accessService.hasPermission(sUser, CREATE_FEATURE, project),
|
||||
).toBe(true);
|
||||
expect(
|
||||
await accessService.hasPermission(sUser, UPDATE_FEATURE, project),
|
||||
).toBe(true);
|
||||
expect(
|
||||
await accessService.hasPermission(sUser, DELETE_FEATURE, project),
|
||||
).toBe(true);
|
||||
// // Should be able to update feature toggles inside the project
|
||||
// expect(
|
||||
// await accessService.hasPermission(sUser, CREATE_FEATURE, project),
|
||||
// ).toBe(true);
|
||||
// expect(
|
||||
// await accessService.hasPermission(sUser, UPDATE_FEATURE, project),
|
||||
// ).toBe(true);
|
||||
// expect(
|
||||
// await accessService.hasPermission(sUser, DELETE_FEATURE, project),
|
||||
// ).toBe(true);
|
||||
|
||||
// Should not be able to admin the project itself.
|
||||
expect(
|
||||
@ -451,17 +451,17 @@ test('should support permission with "ALL" environment requirement', async () =>
|
||||
description: 'Grants access to modify all environments',
|
||||
});
|
||||
|
||||
const { CREATE_FEATURE_STRATEGY } = permissions;
|
||||
const { CREATE_FEATURE } = permissions;
|
||||
await accessStore.addPermissionsToRole(
|
||||
customRole.id,
|
||||
[CREATE_FEATURE_STRATEGY],
|
||||
[CREATE_FEATURE],
|
||||
'production',
|
||||
);
|
||||
await accessStore.addUserToRole(user.id, customRole.id, ALL_PROJECTS);
|
||||
|
||||
const hasAccess = await accessService.hasPermission(
|
||||
user,
|
||||
CREATE_FEATURE_STRATEGY,
|
||||
CREATE_FEATURE,
|
||||
'default',
|
||||
'production',
|
||||
);
|
||||
@ -470,7 +470,7 @@ test('should support permission with "ALL" environment requirement', async () =>
|
||||
|
||||
const hasNotAccess = await accessService.hasPermission(
|
||||
user,
|
||||
CREATE_FEATURE_STRATEGY,
|
||||
CREATE_FEATURE,
|
||||
'default',
|
||||
'development',
|
||||
);
|
||||
@ -478,12 +478,12 @@ test('should support permission with "ALL" environment requirement', async () =>
|
||||
});
|
||||
|
||||
test('Should have access to create a strategy in an environment', async () => {
|
||||
const { CREATE_FEATURE_STRATEGY } = permissions;
|
||||
const { CREATE_FEATURE } = permissions;
|
||||
const user = editorUser;
|
||||
expect(
|
||||
await accessService.hasPermission(
|
||||
user,
|
||||
CREATE_FEATURE_STRATEGY,
|
||||
CREATE_FEATURE,
|
||||
'default',
|
||||
'development',
|
||||
),
|
||||
@ -491,12 +491,12 @@ test('Should have access to create a strategy in an environment', async () => {
|
||||
});
|
||||
|
||||
test('Should be denied access to create a strategy in an environment the user does not have access to', async () => {
|
||||
const { CREATE_FEATURE_STRATEGY } = permissions;
|
||||
const { CREATE_FEATURE } = permissions;
|
||||
const user = editorUser;
|
||||
expect(
|
||||
await accessService.hasPermission(
|
||||
user,
|
||||
CREATE_FEATURE_STRATEGY,
|
||||
CREATE_FEATURE,
|
||||
'default',
|
||||
'noaccess',
|
||||
),
|
||||
@ -504,12 +504,12 @@ test('Should be denied access to create a strategy in an environment the user do
|
||||
});
|
||||
|
||||
test('Should have access to edit a strategy in an environment', async () => {
|
||||
const { UPDATE_FEATURE_STRATEGY } = permissions;
|
||||
const { UPDATE_FEATURE } = permissions;
|
||||
const user = editorUser;
|
||||
expect(
|
||||
await accessService.hasPermission(
|
||||
user,
|
||||
UPDATE_FEATURE_STRATEGY,
|
||||
UPDATE_FEATURE,
|
||||
'default',
|
||||
'development',
|
||||
),
|
||||
@ -517,12 +517,12 @@ test('Should have access to edit a strategy in an environment', async () => {
|
||||
});
|
||||
|
||||
test('Should be denied access to edit a strategy in an environment the user does not have access to', async () => {
|
||||
const { UPDATE_FEATURE_STRATEGY } = permissions;
|
||||
const { UPDATE_FEATURE } = permissions;
|
||||
const user = editorUser;
|
||||
expect(
|
||||
await accessService.hasPermission(
|
||||
user,
|
||||
UPDATE_FEATURE_STRATEGY,
|
||||
UPDATE_FEATURE,
|
||||
'default',
|
||||
'noaccess',
|
||||
),
|
||||
@ -530,12 +530,12 @@ test('Should be denied access to edit a strategy in an environment the user does
|
||||
});
|
||||
|
||||
test('Should have access to delete a strategy in an environment', async () => {
|
||||
const { DELETE_FEATURE_STRATEGY } = permissions;
|
||||
const { UPDATE_FEATURE } = permissions;
|
||||
const user = editorUser;
|
||||
expect(
|
||||
await accessService.hasPermission(
|
||||
user,
|
||||
DELETE_FEATURE_STRATEGY,
|
||||
UPDATE_FEATURE,
|
||||
'default',
|
||||
'development',
|
||||
),
|
||||
@ -543,12 +543,12 @@ test('Should have access to delete a strategy in an environment', async () => {
|
||||
});
|
||||
|
||||
test('Should be denied access to delete a strategy in an environment the user does not have access to', async () => {
|
||||
const { DELETE_FEATURE_STRATEGY } = permissions;
|
||||
const { DELETE_FEATURE } = permissions;
|
||||
const user = editorUser;
|
||||
expect(
|
||||
await accessService.hasPermission(
|
||||
user,
|
||||
DELETE_FEATURE_STRATEGY,
|
||||
DELETE_FEATURE,
|
||||
'default',
|
||||
'noaccess',
|
||||
),
|
||||
|
1
src/test/fixtures/access-service-mock.ts
vendored
1
src/test/fixtures/access-service-mock.ts
vendored
@ -17,6 +17,7 @@ class AccessServiceMock extends AccessService {
|
||||
accessStore: undefined,
|
||||
userStore: undefined,
|
||||
roleStore: undefined,
|
||||
environmentStore: undefined,
|
||||
},
|
||||
{ getLogger: noLoggerProvider },
|
||||
);
|
||||
|
9
src/test/fixtures/fake-access-store.ts
vendored
9
src/test/fixtures/fake-access-store.ts
vendored
@ -39,18 +39,11 @@ class AccessStoreMock implements IAccessStore {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
setupPermissionsForEnvironment(
|
||||
environmentName: string,
|
||||
permissions: string[],
|
||||
): Promise<void> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
userPermissions: IUserPermission[] = [];
|
||||
|
||||
roles: IRole[] = [];
|
||||
|
||||
getAvailablePermissions(): Promise<IAvailablePermissions> {
|
||||
getAvailablePermissions(): Promise<IPermission[]> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user