Skip to content

Commit

Permalink
chore: Refactor role/access stores into more logical domains
Browse files Browse the repository at this point in the history
  • Loading branch information
sighphyre authored and ivarconr committed Jan 11, 2022
1 parent f97f8b0 commit 30de5f4
Show file tree
Hide file tree
Showing 15 changed files with 264 additions and 327 deletions.
128 changes: 22 additions & 106 deletions src/lib/db/access-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
IAccessStore,
IRole,
IUserPermission,
IUserRole,
} from '../types/stores/access-store';
import {
IAvailablePermissions,
Expand Down Expand Up @@ -61,10 +60,6 @@ export class AccessStore implements IAccessStore {
await this.db.batchInsert(T.PERMISSIONS, rows);
}

async getRoleByName(name: string): Promise<IRole> {
return this.db(T.ROLES).where({ name }).first();
}

async delete(key: number): Promise<void> {
await this.db(T.ROLES).where({ id: key }).del();
}
Expand Down Expand Up @@ -186,34 +181,17 @@ export class AccessStore implements IAccessStore {
});
}

async getRoles(): Promise<IRole[]> {
return this.db
.select(['id', 'name', 'type', 'description'])
.from<IRole>(T.ROLES);
}

async getRoleWithId(id: number): Promise<IRole> {
return this.db
.select(['id', 'name', 'type', 'description'])
.where('id', id)
.first()
.from<IRole>(T.ROLES);
}

async getProjectRoles(): Promise<IRole[]> {
return this.db
.select(['id', 'name', 'type', 'description'])
.from<IRole>(T.ROLES)
.where('type', 'custom')
.orWhere('type', 'project');
}

async getRolesForProject(projectId: string): Promise<IRole[]> {
return this.db
.select(['r.id', 'r.name', 'r.type', 'ru.project', 'r.description'])
.from<IRole>(`${T.ROLE_USER} as ru`)
.innerJoin(`${T.ROLES} as r`, 'ru.role_id', 'r.id')
.where('project', projectId);
async addEnvironmentPermissionsToRole(
role_id: number,
permissions: IPermission[],
): Promise<void> {
const rows = permissions.map((x) => {
return {
role_id,
permission_id: x.id,
};
});
this.db.batchInsert(T.ROLE_PERMISSION, rows);
}

async unlinkUserRoles(userId: number): Promise<void> {
Expand All @@ -224,19 +202,17 @@ export class AccessStore implements IAccessStore {
.delete();
}

async getRootRoles(): Promise<IRole[]> {
return this.db
.select(['id', 'name', 'type', 'description'])
.from<IRole>(T.ROLES)
.andWhere('type', 'root');
}

async removeRolesForProject(projectId: string): Promise<void> {
return this.db(T.ROLE_USER)
.where({
project: projectId,
})
.delete();
async getProjectUserIdsForRole(
roleId: number,
projectId?: string,
): Promise<number[]> {
const rows = await this.db
.select(['user_id'])
.from<IRole>(`${T.ROLE_USER} AS ru`)
.join(`${T.ROLES} as r`, 'ru.role_id', 'id')
.where('r.id', roleId)
.andWhere('ru.project', projectId);
return rows.map((r) => r.user_id);
}

async getRolesForUserId(userId: number): Promise<IRole[]> {
Expand All @@ -255,19 +231,6 @@ export class AccessStore implements IAccessStore {
return rows.map((r) => r.user_id);
}

async getProjectUserIdsForRole(
roleId: number,
projectId?: string,
): Promise<number[]> {
const rows = await this.db
.select(['user_id'])
.from<IRole>(`${T.ROLE_USER} AS ru`)
.join(`${T.ROLES} as r`, 'ru.role_id', 'id')
.where('r.id', roleId)
.andWhere('ru.project', projectId);
return rows.map((r) => r.user_id);
}

async addUserToRole(
userId: number,
roleId: number,
Expand Down Expand Up @@ -308,39 +271,6 @@ export class AccessStore implements IAccessStore {
.delete();
}

async createRole(
name: string,
type: string,
description?: string,
): Promise<IRole> {
const [id] = await this.db(T.ROLES)
.insert({
name,
description,
type,
})
.returning('id');
return {
id,
name,
description,
type,
};
}

async addEnvironmentPermissionsToRole(
role_id: number,
permissions: IPermission[],
): Promise<void> {
const rows = permissions.map((x) => {
return {
role_id,
permission_id: x.id,
};
});
this.db.batchInsert(T.ROLE_PERMISSION, rows);
}

async addPermissionsToRole(
role_id: number,
permissions: string[],
Expand Down Expand Up @@ -388,18 +318,4 @@ export class AccessStore implements IAccessStore {
})
.delete();
}

async getRootRoleForAllUsers(): Promise<IUserRole[]> {
const rows = await this.db
.select('id', 'user_id')
.distinctOn('user_id')
.from(`${T.ROLES} AS r`)
.leftJoin(`${T.ROLE_USER} AS ru`, 'r.id', 'ru.role_id')
.where('r.type', '=', 'root');

return rows.map((row) => ({
roleId: +row.id,
userId: +row.user_id,
}));
}
}
84 changes: 76 additions & 8 deletions src/lib/db/role-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@ import {
ICustomRoleInsert,
ICustomRoleUpdate,
} from 'lib/types/stores/role-store';
import { IRole, IUserRole } from 'lib/types/stores/access-store';

const T = {
ROLE_USER: 'role_user',
ROLES: 'roles',
};

const TABLE = 'roles';
const COLUMNS = ['id', 'name', 'description', 'type'];

interface IRoleRow {
Expand All @@ -34,14 +39,14 @@ export default class RoleStore {
async getAll(): Promise<ICustomRole[]> {
const rows = await this.db
.select(COLUMNS)
.from(TABLE)
.from(T.ROLES)
.orderBy('name', 'asc');

return rows.map(this.mapRow);
}

async create(role: ICustomRoleInsert): Promise<ICustomRole> {
const row = await this.db(TABLE)
const row = await this.db(T.ROLES)
.insert({
name: role.name,
description: role.description,
Expand All @@ -52,16 +57,16 @@ export default class RoleStore {
}

async delete(id: number): Promise<void> {
return this.db(TABLE).where({ id }).del();
return this.db(T.ROLES).where({ id }).del();
}

async get(id: number): Promise<ICustomRole> {
const rows = await this.db.select(COLUMNS).from(TABLE).where({ id });
const rows = await this.db.select(COLUMNS).from(T.ROLES).where({ id });
return this.mapRow(rows[0]);
}

async update(role: ICustomRoleUpdate): Promise<ICustomRole> {
const rows = await this.db(TABLE)
const rows = await this.db(T.ROLES)
.where({
id: role.id,
})
Expand All @@ -76,15 +81,15 @@ export default class RoleStore {

async exists(id: number): Promise<boolean> {
const result = await this.db.raw(
`SELECT EXISTS (SELECT 1 FROM ${TABLE} WHERE id = ?) AS present`,
`SELECT EXISTS (SELECT 1 FROM ${T.ROLES} WHERE id = ?) AS present`,
[id],
);
const { present } = result.rows[0];
return present;
}

async deleteAll(): Promise<void> {
return this.db(TABLE).del();
return this.db(T.ROLES).del();
}

mapRow(row: IRoleRow): ICustomRole {
Expand All @@ -100,6 +105,69 @@ export default class RoleStore {
};
}

async getRoles(): Promise<IRole[]> {
return this.db
.select(['id', 'name', 'type', 'description'])
.from<IRole>(T.ROLES);
}

async getRoleWithId(id: number): Promise<IRole> {
return this.db
.select(['id', 'name', 'type', 'description'])
.where('id', id)
.first()
.from<IRole>(T.ROLES);
}

async getProjectRoles(): Promise<IRole[]> {
return this.db
.select(['id', 'name', 'type', 'description'])
.from<IRole>(T.ROLES)
.where('type', 'custom')
.orWhere('type', 'project');
}

async getRolesForProject(projectId: string): Promise<IRole[]> {
return this.db
.select(['r.id', 'r.name', 'r.type', 'ru.project', 'r.description'])
.from<IRole>(`${T.ROLE_USER} as ru`)
.innerJoin(`${T.ROLES} as r`, 'ru.role_id', 'r.id')
.where('project', projectId);
}

async getRootRoles(): Promise<IRole[]> {
return this.db
.select(['id', 'name', 'type', 'description'])
.from<IRole>(T.ROLES)
.where('type', 'root');
}

async removeRolesForProject(projectId: string): Promise<void> {
return this.db(T.ROLE_USER)
.where({
project: projectId,
})
.delete();
}

async getRootRoleForAllUsers(): Promise<IUserRole[]> {
const rows = await this.db
.select('id', 'user_id')
.distinctOn('user_id')
.from(`${T.ROLES} AS r`)
.leftJoin(`${T.ROLE_USER} AS ru`, 'r.id', 'ru.role_id')
.where('r.type', '=', 'root');

return rows.map((row) => ({
roleId: +row.id,
userId: +row.user_id,
}));
}

async getRoleByName(name: string): Promise<IRole> {
return this.db(T.ROLES).where({ name }).first();
}

destroy(): void {}
}

Expand Down

0 comments on commit 30de5f4

Please sign in to comment.