1
0
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:
sighphyre 2022-01-03 11:19:24 +02:00 committed by Ivar Conradi Østhus
parent 42a5105736
commit c547b8a2b9
No known key found for this signature in database
GPG Key ID: 31AC596886B0BD09
13 changed files with 305 additions and 260 deletions

View File

@ -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();
}

View File

@ -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);

View File

@ -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,

View File

@ -224,6 +224,7 @@ export interface IPermission {
id: number;
name: string;
displayName: string;
type: string;
environment?: string;
}

View File

@ -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';

View File

@ -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,

View File

@ -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>;
}

View File

@ -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);
};

View File

@ -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,
);
};

View File

@ -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,
);

View File

@ -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',
),

View File

@ -17,6 +17,7 @@ class AccessServiceMock extends AccessService {
accessStore: undefined,
userStore: undefined,
roleStore: undefined,
environmentStore: undefined,
},
{ getLogger: noLoggerProvider },
);

View File

@ -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.');
}