1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-12-22 19:07:54 +01:00

fix: add foreign key constraint to role_permissions table

This commit is contained in:
FredrikOseberg 2024-09-26 10:37:42 +02:00
parent 2406b10ca3
commit d84092e08a
No known key found for this signature in database
GPG Key ID: 282FD8A6D8F9BCF0
7 changed files with 111 additions and 4 deletions

View File

@ -1,4 +1,4 @@
import type { Db, IUnleashConfig } from '../../server-impl';
import type { Db, IUnleashConfig, Knex } from '../../server-impl';
import GroupStore from '../../db/group-store';
import { AccountStore } from '../../db/account-store';
import RoleStore from '../../db/role-store';
@ -17,6 +17,11 @@ import {
createFakeEventsService,
} from '../events/createEventsService';
// We need this function to satisfy the type expectations of withTransactional
export const curriedCreateAccessService =
(config: IUnleashConfig) => (db: Knex) =>
createAccessService(db, config);
export const createAccessService = (
db: Db,
config: IUnleashConfig,
@ -33,6 +38,7 @@ export const createAccessService = (
{ getLogger },
eventService,
);
return new AccessService(
{ accessStore, accountStore, roleStore, environmentStore },
{ getLogger },

View File

@ -108,6 +108,15 @@ export interface AccessWithRoles {
const isProjectPermission = (permission) => PROJECT_ADMIN.includes(permission);
export const cleanPermissions = (permissions: PermissionRef[] | undefined) => {
return permissions?.map((permission) => {
if (permission.environment === '') {
return { ...permission, environment: null };
}
return permission;
});
};
export class AccessService {
private store: IAccessStore;
@ -721,7 +730,8 @@ export class AccessService {
roleType,
};
const rolePermissions = role.permissions;
const rolePermissions = cleanPermissions(role.permissions);
const newRole = await this.roleStore.create(baseRole);
if (rolePermissions) {
if (roleType === CUSTOM_ROOT_ROLE_TYPE) {
@ -770,7 +780,9 @@ export class AccessService {
description: role.description,
roleType,
};
const rolePermissions = role.permissions;
const rolePermissions = cleanPermissions(role.permissions);
const updatedRole = await this.roleStore.update(baseRole);
const existingPermissions = await this.store.getPermissionsForRole(
role.id,

View File

@ -0,0 +1,59 @@
import { cleanPermissions } from './access-service';
test('should convert all empty strings to null', () => {
const permissions = [
{
name: 'UPDATE_PROJECT',
environment: '',
},
{
name: 'UPDATE_FEATURE_VARIANTS',
environment: '',
},
{
name: 'READ_PROJECT_API_TOKEN',
environment: '',
},
{
name: 'CREATE_PROJECT_API_TOKEN',
environment: '',
},
{
name: 'DELETE_PROJECT_API_TOKEN',
environment: '',
},
{
name: 'UPDATE_PROJECT_SEGMENT',
environment: '',
},
];
const result = cleanPermissions(permissions);
expect(result).toEqual([
{
name: 'UPDATE_PROJECT',
environment: null,
},
{
name: 'UPDATE_FEATURE_VARIANTS',
environment: null,
},
{
name: 'READ_PROJECT_API_TOKEN',
environment: null,
},
{
name: 'CREATE_PROJECT_API_TOKEN',
environment: null,
},
{
name: 'DELETE_PROJECT_API_TOKEN',
environment: null,
},
{
name: 'UPDATE_PROJECT_SEGMENT',
environment: null,
},
]);
});

View File

@ -1,4 +1,5 @@
import type {
IUnleash,
IUnleashConfig,
IUnleashServices,
IUnleashStores,
@ -65,12 +66,14 @@ import ConfigurationRevisionService from '../features/feature-toggle/configurati
import {
createEnvironmentService,
createEventsService,
createFakeAccessService,
createFakeEnvironmentService,
createFakeEventsService,
createFakeProjectService,
createFeatureLifecycleService,
createFeatureToggleService,
createProjectService,
curriedCreateAccessService,
} from '../features';
import EventAnnouncerService from './event-announcer-service';
import { createGroupService } from '../features/group/createGroupService';
@ -166,6 +169,11 @@ export const createServices = (
groupService,
eventService,
);
const transactionalAccessService = db
? withTransactional(curriedCreateAccessService(config), db)
: withFakeTransactional(createFakeAccessService(config).accessService);
const apiTokenService = db
? createApiTokenService(db, config)
: createFakeApiTokenService(config).apiTokenService;
@ -403,6 +411,7 @@ export const createServices = (
return {
accessService,
transactionalAccessService,
accountService,
addonService,
eventAnnouncerService,

View File

@ -419,7 +419,7 @@ export interface IPermission {
name: string;
displayName: string;
type: string;
environment?: string;
environment?: string | null;
}
export interface IEnvironmentPermission {

View File

@ -58,6 +58,7 @@ import type { IntegrationEventsService } from '../features/integration-events/in
import type { OnboardingService } from '../features/onboarding/onboarding-service';
export interface IUnleashServices {
transactionalAccessService: WithTransactional<AccessService>;
accessService: AccessService;
accountService: AccountService;
addonService: AddonService;

View File

@ -0,0 +1,20 @@
exports.up = function (db, cb) {
db.runSql(
`
UPDATE role_permission SET environment = null where environment = '';
DELETE FROM role_permission WHERE environment IS NOT NULL AND environment NOT IN (SELECT name FROM environments);
ALTER TABLE role_permission ADD CONSTRAINT fk_role_permission_environment FOREIGN KEY (environment) REFERENCES environments(name) ON DELETE CASCADE;
`,
cb
);
};
exports.down = function (db, cb) {
db.runSql(
`
ALTER TABLE role_permission
DROP CONSTRAINT IF EXISTS fk_role_permission_environment;
`,
cb
);
};