roles and permissions
This commit is contained in:
parent
d77c3ca1a5
commit
9808100d81
21 changed files with 389 additions and 59 deletions
10
src/command/rolePermissionCommand.ts
Normal file
10
src/command/rolePermissionCommand.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { PermissionString } from "../type/permissionTypes";
|
||||||
|
|
||||||
|
export interface CreateRolePermissionCommand {
|
||||||
|
permission: PermissionString;
|
||||||
|
roleId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeleteRolePermissionCommand {
|
||||||
|
id: number;
|
||||||
|
}
|
48
src/command/rolePermissionCommandHandler.ts
Normal file
48
src/command/rolePermissionCommandHandler.ts
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import { dataSource } from "../data-source";
|
||||||
|
import { rolePermission } from "../entity/role_permission";
|
||||||
|
import InternalException from "../exceptions/internalException";
|
||||||
|
import RoleService from "../service/roleService";
|
||||||
|
import { CreateRolePermissionCommand, DeleteRolePermissionCommand } from "./rolePermissionCommand";
|
||||||
|
|
||||||
|
export default abstract class UserPermissionCommandHandler {
|
||||||
|
/**
|
||||||
|
* @description grant permission to user
|
||||||
|
* @param CreateRolePermissionCommand
|
||||||
|
* @returns {Promise<number>}
|
||||||
|
*/
|
||||||
|
static async create(createPermission: CreateRolePermissionCommand): Promise<number> {
|
||||||
|
return await dataSource
|
||||||
|
.createQueryBuilder()
|
||||||
|
.insert()
|
||||||
|
.into(rolePermission)
|
||||||
|
.values({
|
||||||
|
permission: createPermission.permission,
|
||||||
|
role: await RoleService.getById(createPermission.roleId),
|
||||||
|
})
|
||||||
|
.execute()
|
||||||
|
.then((result) => {
|
||||||
|
return result.identifiers[0].id;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw new InternalException("Failed saving role permission");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description remove permission from role
|
||||||
|
* @param DeleteRolePermissionCommand
|
||||||
|
* @returns {Promise<any>}
|
||||||
|
*/
|
||||||
|
static async deleteByToken(deletePermission: DeleteRolePermissionCommand): Promise<any> {
|
||||||
|
return await dataSource
|
||||||
|
.createQueryBuilder()
|
||||||
|
.delete()
|
||||||
|
.from(rolePermission)
|
||||||
|
.where("permission.id = :id", { id: deletePermission.id })
|
||||||
|
.execute()
|
||||||
|
.then((res) => {})
|
||||||
|
.catch((err) => {
|
||||||
|
throw new InternalException("failed role permission removal");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
import { PermissionString } from "../type/permissionTypes";
|
import { PermissionString } from "../type/permissionTypes";
|
||||||
|
|
||||||
export interface CreatePermissionCommand {
|
export interface CreateUserPermissionCommand {
|
||||||
permission: PermissionString;
|
permission: PermissionString;
|
||||||
userId: number;
|
userId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DeletePermissionCommand {
|
export interface DeleteUserPermissionCommand {
|
||||||
id: number;
|
id: number;
|
||||||
}
|
}
|
|
@ -1,20 +1,20 @@
|
||||||
import { dataSource } from "../data-source";
|
import { dataSource } from "../data-source";
|
||||||
import { permission } from "../entity/permission";
|
import { userPermission } from "../entity/user_permission";
|
||||||
import InternalException from "../exceptions/internalException";
|
import InternalException from "../exceptions/internalException";
|
||||||
import UserService from "../service/userService";
|
import UserService from "../service/userService";
|
||||||
import { CreatePermissionCommand, DeletePermissionCommand } from "./permissionCommand";
|
import { CreateUserPermissionCommand, DeleteUserPermissionCommand } from "./userPermissionCommand";
|
||||||
|
|
||||||
export default abstract class PermissionCommandHandler {
|
export default abstract class UserPermissionCommandHandler {
|
||||||
/**
|
/**
|
||||||
* @description grant permission to user
|
* @description grant permission to user
|
||||||
* @param CreatePermissionCommand
|
* @param CreateUserPermissionCommand
|
||||||
* @returns {Promise<number>}
|
* @returns {Promise<number>}
|
||||||
*/
|
*/
|
||||||
static async create(createPermission: CreatePermissionCommand): Promise<number> {
|
static async create(createPermission: CreateUserPermissionCommand): Promise<number> {
|
||||||
return await dataSource
|
return await dataSource
|
||||||
.createQueryBuilder()
|
.createQueryBuilder()
|
||||||
.insert()
|
.insert()
|
||||||
.into(permission)
|
.into(userPermission)
|
||||||
.values({
|
.values({
|
||||||
permission: createPermission.permission,
|
permission: createPermission.permission,
|
||||||
user: await UserService.getById(createPermission.userId),
|
user: await UserService.getById(createPermission.userId),
|
||||||
|
@ -24,25 +24,25 @@ export default abstract class PermissionCommandHandler {
|
||||||
return result.identifiers[0].id;
|
return result.identifiers[0].id;
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
throw new InternalException("Failed saving permission");
|
throw new InternalException("Failed saving user permission");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description remove permission to user
|
* @description remove permission to user
|
||||||
* @param DeletePermissionCommand
|
* @param DeleteUserPermissionCommand
|
||||||
* @returns {Promise<any>}
|
* @returns {Promise<any>}
|
||||||
*/
|
*/
|
||||||
static async deleteByToken(deletePermission: DeletePermissionCommand): Promise<any> {
|
static async deleteByToken(deletePermission: DeleteUserPermissionCommand): Promise<any> {
|
||||||
return await dataSource
|
return await dataSource
|
||||||
.createQueryBuilder()
|
.createQueryBuilder()
|
||||||
.delete()
|
.delete()
|
||||||
.from(permission)
|
.from(userPermission)
|
||||||
.where("permission.id = :id", { id: deletePermission.id })
|
.where("permission.id = :id", { id: deletePermission.id })
|
||||||
.execute()
|
.execute()
|
||||||
.then((res) => {})
|
.then((res) => {})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
throw new InternalException("failed permission removal");
|
throw new InternalException("failed user permission removal");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,8 +8,9 @@ import UserService from "../service/userService";
|
||||||
import speakeasy from "speakeasy";
|
import speakeasy from "speakeasy";
|
||||||
import UnauthorizedRequestException from "../exceptions/unauthorizedRequestException";
|
import UnauthorizedRequestException from "../exceptions/unauthorizedRequestException";
|
||||||
import RefreshService from "../service/refreshService";
|
import RefreshService from "../service/refreshService";
|
||||||
import PermissionService from "../service/permissionService";
|
import UserPermissionService from "../service/userPermissionService";
|
||||||
import PermissionHelper from "../helpers/permissionHelper";
|
import PermissionHelper from "../helpers/permissionHelper";
|
||||||
|
import RolePermissionService from "../service/rolePermissionService";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Check authentication status by token
|
* @description Check authentication status by token
|
||||||
|
@ -34,9 +35,12 @@ export async function login(req: Request, res: Response): Promise<any> {
|
||||||
throw new UnauthorizedRequestException("Token not valid or expired");
|
throw new UnauthorizedRequestException("Token not valid or expired");
|
||||||
}
|
}
|
||||||
|
|
||||||
let permissions = await PermissionService.getByUser(id);
|
let userPermissions = await UserPermissionService.getByUser(id);
|
||||||
let permissionStrings = permissions.map((e) => e.permission);
|
let userPermissionStrings = userPermissions.map((e) => e.permission);
|
||||||
let permissionObject = PermissionHelper.convertToObject(permissionStrings);
|
let userRoles = await UserService.getAssignedRolesByUserId(id);
|
||||||
|
let rolePermissions = await RolePermissionService.getByRoles(userRoles.map((e) => e.id));
|
||||||
|
let rolePermissionStrings = rolePermissions.map((e) => e.permission);
|
||||||
|
let permissionObject = PermissionHelper.convertToObject([...userPermissionStrings, ...rolePermissionStrings]);
|
||||||
|
|
||||||
let jwtData: JWTToken = {
|
let jwtData: JWTToken = {
|
||||||
userId: id,
|
userId: id,
|
||||||
|
@ -103,7 +107,7 @@ export async function refresh(req: Request, res: Response): Promise<any> {
|
||||||
|
|
||||||
let { id, username, mail, firstname, lastname } = await UserService.getById(tokenUserId);
|
let { id, username, mail, firstname, lastname } = await UserService.getById(tokenUserId);
|
||||||
|
|
||||||
let permissions = await PermissionService.getByUser(id);
|
let permissions = await UserPermissionService.getByUser(id);
|
||||||
let permissionStrings = permissions.map((e) => e.permission);
|
let permissionStrings = permissions.map((e) => e.permission);
|
||||||
let permissionObject = PermissionHelper.convertToObject(permissionStrings);
|
let permissionObject = PermissionHelper.convertToObject(permissionStrings);
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@ import InviteService from "../service/inviteService";
|
||||||
import UserService from "../service/userService";
|
import UserService from "../service/userService";
|
||||||
import CustomRequestException from "../exceptions/customRequestException";
|
import CustomRequestException from "../exceptions/customRequestException";
|
||||||
import { CLUB_NAME } from "../env.defaults";
|
import { CLUB_NAME } from "../env.defaults";
|
||||||
import { CreatePermissionCommand } from "../command/permissionCommand";
|
import { CreateUserPermissionCommand } from "../command/userPermissionCommand";
|
||||||
import PermissionCommandHandler from "../command/permissionCommandHandler";
|
import UserPermissionCommandHandler from "../command/userPermissionCommandHandler";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description start first user
|
* @description start first user
|
||||||
|
@ -130,11 +130,11 @@ export async function finishInvite(req: Request, res: Response, grantAdmin: bool
|
||||||
let id = await UserCommandHandler.create(createUser);
|
let id = await UserCommandHandler.create(createUser);
|
||||||
|
|
||||||
if (grantAdmin) {
|
if (grantAdmin) {
|
||||||
let createPermission: CreatePermissionCommand = {
|
let createPermission: CreateUserPermissionCommand = {
|
||||||
permission: "*",
|
permission: "*",
|
||||||
userId: id,
|
userId: id,
|
||||||
};
|
};
|
||||||
await PermissionCommandHandler.create(createPermission);
|
await UserPermissionCommandHandler.create(createPermission);
|
||||||
}
|
}
|
||||||
|
|
||||||
let jwtData: JWTToken = {
|
let jwtData: JWTToken = {
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
import { Request, Response } from "express";
|
|
||||||
import { permissionModules, permissionSections, permissionTypes } from "../type/permissionTypes";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description sections of permissions
|
|
||||||
* @param req {Request} Express req object
|
|
||||||
* @param res {Response} Express res object
|
|
||||||
* @returns {Promise<*>}
|
|
||||||
*/
|
|
||||||
export async function getSections(req: Request, res: Response): Promise<any> {
|
|
||||||
res.json(permissionSections);
|
|
||||||
}
|
|
|
@ -6,12 +6,15 @@ import { DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME, DB_TYPE } from "./env.defau
|
||||||
import { user } from "./entity/user";
|
import { user } from "./entity/user";
|
||||||
import { refresh } from "./entity/refresh";
|
import { refresh } from "./entity/refresh";
|
||||||
import { invite } from "./entity/invite";
|
import { invite } from "./entity/invite";
|
||||||
import { permission } from "./entity/permission";
|
import { userPermission } from "./entity/user_permission";
|
||||||
|
|
||||||
import { Initial1724317398939 } from "./migrations/1724317398939-initial";
|
import { Initial1724317398939 } from "./migrations/1724317398939-initial";
|
||||||
import { RefreshPrimaryChange1724573307851 } from "./migrations/1724573307851-refreshPrimaryChange";
|
import { RefreshPrimaryChange1724573307851 } from "./migrations/1724573307851-refreshPrimaryChange";
|
||||||
import { Invite1724579024939 } from "./migrations/1724579024939-invite";
|
import { Invite1724579024939 } from "./migrations/1724579024939-invite";
|
||||||
import { Permissions1724661484664 } from "./migrations/1724661484664-permissions";
|
import { Permissions1724661484664 } from "./migrations/1724661484664-permissions";
|
||||||
|
import { role } from "./entity/role";
|
||||||
|
import { rolePermission } from "./entity/role_permission";
|
||||||
|
import { RolePermission1724771491085 } from "./migrations/1724771491085-role_permission";
|
||||||
|
|
||||||
const dataSource = new DataSource({
|
const dataSource = new DataSource({
|
||||||
type: DB_TYPE as any,
|
type: DB_TYPE as any,
|
||||||
|
@ -23,8 +26,14 @@ const dataSource = new DataSource({
|
||||||
synchronize: false,
|
synchronize: false,
|
||||||
logging: process.env.NODE_ENV ? true : ["schema", "error", "warn", "log", "migration"],
|
logging: process.env.NODE_ENV ? true : ["schema", "error", "warn", "log", "migration"],
|
||||||
bigNumberStrings: false,
|
bigNumberStrings: false,
|
||||||
entities: [user, refresh, invite, permission],
|
entities: [user, refresh, invite, userPermission, role, rolePermission],
|
||||||
migrations: [Initial1724317398939, RefreshPrimaryChange1724573307851, Invite1724579024939, Permissions1724661484664],
|
migrations: [
|
||||||
|
Initial1724317398939,
|
||||||
|
RefreshPrimaryChange1724573307851,
|
||||||
|
Invite1724579024939,
|
||||||
|
Permissions1724661484664,
|
||||||
|
RolePermission1724771491085,
|
||||||
|
],
|
||||||
migrationsRun: true,
|
migrationsRun: true,
|
||||||
migrationsTransactionMode: "each",
|
migrationsTransactionMode: "each",
|
||||||
subscribers: [],
|
subscribers: [],
|
||||||
|
|
14
src/entity/role.ts
Normal file
14
src/entity/role.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import { Column, Entity, ManyToMany, PrimaryColumn } from "typeorm";
|
||||||
|
import { user } from "./user";
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class role {
|
||||||
|
@PrimaryColumn({ generated: "increment", type: "int" })
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@Column({ type: "varchar", length: 255 })
|
||||||
|
role: string;
|
||||||
|
|
||||||
|
@ManyToMany(() => user, (user) => user.roles)
|
||||||
|
users: user[];
|
||||||
|
}
|
15
src/entity/role_permission.ts
Normal file
15
src/entity/role_permission.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { Column, Entity, ManyToOne, PrimaryColumn } from "typeorm";
|
||||||
|
import { PermissionString } from "../type/permissionTypes";
|
||||||
|
import { role } from "./role";
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class rolePermission {
|
||||||
|
@PrimaryColumn({ type: "int" })
|
||||||
|
roleId: number;
|
||||||
|
|
||||||
|
@PrimaryColumn({ type: "varchar", length: 255 })
|
||||||
|
permission: PermissionString;
|
||||||
|
|
||||||
|
@ManyToOne(() => role)
|
||||||
|
role: role;
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import { Column, Entity, PrimaryColumn } from "typeorm";
|
import { Column, Entity, JoinTable, ManyToMany, PrimaryColumn } from "typeorm";
|
||||||
import { refresh } from "./refresh";
|
import { role } from "./role";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class user {
|
export class user {
|
||||||
|
@ -20,4 +20,10 @@ export class user {
|
||||||
|
|
||||||
@Column({ type: "varchar", length: 255 })
|
@Column({ type: "varchar", length: 255 })
|
||||||
secret: string;
|
secret: string;
|
||||||
|
|
||||||
|
@ManyToMany(() => role, (role) => role.users)
|
||||||
|
@JoinTable({
|
||||||
|
name: "user_roles",
|
||||||
|
})
|
||||||
|
roles: role[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { user } from "./user";
|
||||||
import { PermissionObject, PermissionString } from "../type/permissionTypes";
|
import { PermissionObject, PermissionString } from "../type/permissionTypes";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class permission {
|
export class userPermission {
|
||||||
@PrimaryColumn({ type: "int" })
|
@PrimaryColumn({ type: "int" })
|
||||||
userId: number;
|
userId: number;
|
||||||
|
|
|
@ -32,6 +32,22 @@ export default class PermissionHelper {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static canSection(
|
||||||
|
permissions: PermissionObject,
|
||||||
|
type: PermissionType | "admin",
|
||||||
|
section: PermissionSection
|
||||||
|
): boolean {
|
||||||
|
if (type == "admin") return permissions.admin ?? false;
|
||||||
|
if (permissions.admin) return true;
|
||||||
|
if (
|
||||||
|
permissions[section]?.all == "*" ||
|
||||||
|
permissions[section]?.all?.includes(type) ||
|
||||||
|
permissions[section] != undefined
|
||||||
|
)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static passCheckMiddleware(
|
static passCheckMiddleware(
|
||||||
requiredPermissions: PermissionType | "admin",
|
requiredPermissions: PermissionType | "admin",
|
||||||
section: PermissionSection,
|
section: PermissionSection,
|
||||||
|
@ -52,6 +68,25 @@ export default class PermissionHelper {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static sectionPassCheckMiddleware(
|
||||||
|
requiredPermissions: PermissionType | "admin",
|
||||||
|
section: PermissionSection
|
||||||
|
): (req: Request, res: Response, next: Function) => void {
|
||||||
|
return (req: Request, res: Response, next: Function) => {
|
||||||
|
const permissions = req.permissions;
|
||||||
|
|
||||||
|
if (this.canSection(permissions, requiredPermissions, section)) {
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
throw new ForbiddenRequestException(
|
||||||
|
`missing permission for ${section}.${module}.${
|
||||||
|
Array.isArray(requiredPermissions) ? requiredPermissions.join("|") : requiredPermissions
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static convertToObject(permissions: Array<PermissionString>): PermissionObject {
|
static convertToObject(permissions: Array<PermissionString>): PermissionObject {
|
||||||
if (permissions.includes("*")) {
|
if (permissions.includes("*")) {
|
||||||
return {
|
return {
|
||||||
|
|
123
src/migrations/1724771491085-role_permission.ts
Normal file
123
src/migrations/1724771491085-role_permission.ts
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
import { MigrationInterface, QueryRunner, Table, TableForeignKey } from "typeorm";
|
||||||
|
|
||||||
|
export class RolePermission1724771491085 implements MigrationInterface {
|
||||||
|
name = "RolePermission1724771491085";
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.createTable(
|
||||||
|
new Table({
|
||||||
|
name: "role",
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: "id",
|
||||||
|
type: "int",
|
||||||
|
isPrimary: true,
|
||||||
|
isNullable: false,
|
||||||
|
isGenerated: true,
|
||||||
|
generationStrategy: "increment",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "role",
|
||||||
|
type: "varchar",
|
||||||
|
length: "255",
|
||||||
|
isNullable: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
await queryRunner.createTable(
|
||||||
|
new Table({
|
||||||
|
name: "role_permission",
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: "permission",
|
||||||
|
type: "varchar",
|
||||||
|
length: "255",
|
||||||
|
isPrimary: true,
|
||||||
|
isNullable: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "roleId",
|
||||||
|
type: "int",
|
||||||
|
isPrimary: true,
|
||||||
|
isNullable: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
await queryRunner.renameTable("permission", "user_permission");
|
||||||
|
|
||||||
|
await queryRunner.createTable(
|
||||||
|
new Table({
|
||||||
|
name: "user_roles",
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: "userId",
|
||||||
|
type: "int",
|
||||||
|
isPrimary: true,
|
||||||
|
isNullable: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "roleId",
|
||||||
|
type: "int",
|
||||||
|
isPrimary: true,
|
||||||
|
isNullable: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
await queryRunner.createForeignKey(
|
||||||
|
"role_permission",
|
||||||
|
new TableForeignKey({
|
||||||
|
columnNames: ["roleId"],
|
||||||
|
referencedColumnNames: ["id"],
|
||||||
|
referencedTableName: "role",
|
||||||
|
onDelete: "No Action",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
await queryRunner.createForeignKey(
|
||||||
|
"user_roles",
|
||||||
|
new TableForeignKey({
|
||||||
|
columnNames: ["userId"],
|
||||||
|
referencedColumnNames: ["id"],
|
||||||
|
referencedTableName: "user",
|
||||||
|
onDelete: "No Action",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
await queryRunner.createForeignKey(
|
||||||
|
"user_roles",
|
||||||
|
new TableForeignKey({
|
||||||
|
columnNames: ["roleId"],
|
||||||
|
referencedColumnNames: ["id"],
|
||||||
|
referencedTableName: "role",
|
||||||
|
onDelete: "No Action",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
const user_roles = await queryRunner.getTable("user_roles");
|
||||||
|
const roles_foreignKey = user_roles.foreignKeys.find((fk) => fk.columnNames.indexOf("roleId") !== -1);
|
||||||
|
const user_foreignKey = user_roles.foreignKeys.find((fk) => fk.columnNames.indexOf("userId") !== -1);
|
||||||
|
await queryRunner.dropForeignKey("user_roles", roles_foreignKey);
|
||||||
|
await queryRunner.dropForeignKey("user_roles", user_foreignKey);
|
||||||
|
await queryRunner.dropTable("user_roles");
|
||||||
|
|
||||||
|
const role_permission = await queryRunner.getTable("role_permission");
|
||||||
|
const permission_foreignKey = role_permission.foreignKeys.find((fk) => fk.columnNames.indexOf("roleId") !== -1);
|
||||||
|
await queryRunner.dropForeignKey("role_permission", permission_foreignKey);
|
||||||
|
await queryRunner.dropTable("role_permission");
|
||||||
|
|
||||||
|
await queryRunner.dropTable("role");
|
||||||
|
|
||||||
|
await queryRunner.renameTable("user_permission", "permission");
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,7 +8,6 @@ import errorHandler from "../middleware/errorHandler";
|
||||||
|
|
||||||
import setup from "./setup";
|
import setup from "./setup";
|
||||||
import auth from "./auth";
|
import auth from "./auth";
|
||||||
import permission from "./permission";
|
|
||||||
import PermissionHelper from "../helpers/permissionHelper";
|
import PermissionHelper from "../helpers/permissionHelper";
|
||||||
|
|
||||||
export default (app: Express) => {
|
export default (app: Express) => {
|
||||||
|
@ -25,6 +24,6 @@ export default (app: Express) => {
|
||||||
app.use("/setup", allowSetup, setup);
|
app.use("/setup", allowSetup, setup);
|
||||||
app.use("/auth", auth);
|
app.use("/auth", auth);
|
||||||
app.use(authenticate);
|
app.use(authenticate);
|
||||||
app.use("/permission", PermissionHelper.passCheckMiddleware("admin", "user"), permission);
|
app.use("/secured", PermissionHelper.passCheckMiddleware("admin", "user"), (req, res) => {});
|
||||||
app.use(errorHandler);
|
app.use(errorHandler);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
import express from "express";
|
|
||||||
import { getSections } from "../controller/permissionController";
|
|
||||||
|
|
||||||
var router = express.Router({ mergeParams: true });
|
|
||||||
|
|
||||||
router.get("/sections", async (req, res) => {
|
|
||||||
await getSections(req, res);
|
|
||||||
});
|
|
||||||
|
|
||||||
export default router;
|
|
44
src/service/rolePermissionService.ts
Normal file
44
src/service/rolePermissionService.ts
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import { dataSource } from "../data-source";
|
||||||
|
import { rolePermission } from "../entity/role_permission";
|
||||||
|
import { userPermission } from "../entity/user_permission";
|
||||||
|
import InternalException from "../exceptions/internalException";
|
||||||
|
|
||||||
|
export default abstract class RolePermissionService {
|
||||||
|
/**
|
||||||
|
* @description get permission by role
|
||||||
|
* @param roleId number
|
||||||
|
* @returns {Promise<Array<rolePermission>>}
|
||||||
|
*/
|
||||||
|
static async getByRole(roleId: number): Promise<Array<rolePermission>> {
|
||||||
|
return await dataSource
|
||||||
|
.getRepository(rolePermission)
|
||||||
|
.createQueryBuilder("permission")
|
||||||
|
.where("permission.roleId = :roleId", { roleId: roleId })
|
||||||
|
.getMany()
|
||||||
|
.then((res) => {
|
||||||
|
return res;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw new InternalException("permissions not found by role");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description get permission by roles
|
||||||
|
* @param roleIds Array<number>
|
||||||
|
* @returns {Promise<Array<rolePermission>>}
|
||||||
|
*/
|
||||||
|
static async getByRoles(roleIds: Array<number>): Promise<Array<rolePermission>> {
|
||||||
|
return await dataSource
|
||||||
|
.getRepository(rolePermission)
|
||||||
|
.createQueryBuilder("permission")
|
||||||
|
.where("permission.roleId IN (:...roleIds)", { roleIds: roleIds })
|
||||||
|
.getMany()
|
||||||
|
.then((res) => {
|
||||||
|
return res;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw new InternalException("permissions not found by roles");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
24
src/service/roleService.ts
Normal file
24
src/service/roleService.ts
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import { dataSource } from "../data-source";
|
||||||
|
import { role } from "../entity/role";
|
||||||
|
import InternalException from "../exceptions/internalException";
|
||||||
|
|
||||||
|
export default abstract class RoleService {
|
||||||
|
/**
|
||||||
|
* @description get role by id
|
||||||
|
* @param id number
|
||||||
|
* @returns {Promise<role>}
|
||||||
|
*/
|
||||||
|
static async getById(id: number): Promise<role> {
|
||||||
|
return await dataSource
|
||||||
|
.getRepository(role)
|
||||||
|
.createQueryBuilder("role")
|
||||||
|
.where("role.id = :id", { id: id })
|
||||||
|
.getOneOrFail()
|
||||||
|
.then((res) => {
|
||||||
|
return res;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw new InternalException("role not found by id");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +1,16 @@
|
||||||
import { dataSource } from "../data-source";
|
import { dataSource } from "../data-source";
|
||||||
import { permission } from "../entity/permission";
|
import { userPermission } from "../entity/user_permission";
|
||||||
import InternalException from "../exceptions/internalException";
|
import InternalException from "../exceptions/internalException";
|
||||||
|
|
||||||
export default abstract class PermissionService {
|
export default abstract class UserPermissionService {
|
||||||
/**
|
/**
|
||||||
* @description get permission by user
|
* @description get permission by user
|
||||||
* @param user number
|
* @param userId number
|
||||||
* @returns {Promise<Array<permission>>}
|
* @returns {Promise<Array<userPermission>>}
|
||||||
*/
|
*/
|
||||||
static async getByUser(userId: number): Promise<Array<permission>> {
|
static async getByUser(userId: number): Promise<Array<userPermission>> {
|
||||||
return await dataSource
|
return await dataSource
|
||||||
.getRepository(permission)
|
.getRepository(userPermission)
|
||||||
.createQueryBuilder("permission")
|
.createQueryBuilder("permission")
|
||||||
.where("permission.userId = :userId", { userId: userId })
|
.where("permission.userId = :userId", { userId: userId })
|
||||||
.getMany()
|
.getMany()
|
|
@ -1,4 +1,5 @@
|
||||||
import { dataSource } from "../data-source";
|
import { dataSource } from "../data-source";
|
||||||
|
import { role } from "../entity/role";
|
||||||
import { user } from "../entity/user";
|
import { user } from "../entity/user";
|
||||||
import InternalException from "../exceptions/internalException";
|
import InternalException from "../exceptions/internalException";
|
||||||
|
|
||||||
|
@ -81,4 +82,24 @@ export default abstract class UserService {
|
||||||
throw new InternalException("could not count users");
|
throw new InternalException("could not count users");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description get roles assigned to user
|
||||||
|
* @param userId number
|
||||||
|
* @returns {Promise<Array<role>>}
|
||||||
|
*/
|
||||||
|
static async getAssignedRolesByUserId(userId: number): Promise<Array<role>> {
|
||||||
|
return await dataSource
|
||||||
|
.getRepository(user)
|
||||||
|
.createQueryBuilder("user")
|
||||||
|
.leftJoinAndSelect("user.roles", "roles")
|
||||||
|
.where("user.id = :id", { id: userId })
|
||||||
|
.getOneOrFail()
|
||||||
|
.then((res) => {
|
||||||
|
return res.roles;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw new InternalException("could not get roles for user");
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ export type PermissionModule =
|
||||||
| "user"
|
| "user"
|
||||||
| "role";
|
| "role";
|
||||||
|
|
||||||
export type PermissionType = "create" | "read" | "update" | "delete";
|
export type PermissionType = "read" | "create" | "update" | "delete";
|
||||||
|
|
||||||
export type PermissionString =
|
export type PermissionString =
|
||||||
| `${PermissionSection}.${PermissionModule}.${PermissionType}` // für spezifische Berechtigungen
|
| `${PermissionSection}.${PermissionModule}.${PermissionType}` // für spezifische Berechtigungen
|
||||||
|
|
Loading…
Reference in a new issue