permission system - permission formatting
This commit is contained in:
parent
d889f92643
commit
2f5d9d3f01
15 changed files with 352 additions and 18 deletions
10
src/command/permissionCommand.ts
Normal file
10
src/command/permissionCommand.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { PermissionString } from "../type/permissionTypes";
|
||||||
|
|
||||||
|
export interface CreatePermissionCommand {
|
||||||
|
permission: PermissionString;
|
||||||
|
userId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeletePermissionCommand {
|
||||||
|
id: number;
|
||||||
|
}
|
48
src/command/permissionCommandHandler.ts
Normal file
48
src/command/permissionCommandHandler.ts
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import { dataSource } from "../data-source";
|
||||||
|
import { permission } from "../entity/permission";
|
||||||
|
import InternalException from "../exceptions/internalException";
|
||||||
|
import UserService from "../service/userService";
|
||||||
|
import { CreatePermissionCommand, DeletePermissionCommand } from "./permissionCommand";
|
||||||
|
|
||||||
|
export default abstract class PermissionCommandHandler {
|
||||||
|
/**
|
||||||
|
* @description grant permission to user
|
||||||
|
* @param CreatePermissionCommand
|
||||||
|
* @returns {Promise<number>}
|
||||||
|
*/
|
||||||
|
static async create(createPermission: CreatePermissionCommand): Promise<number> {
|
||||||
|
return await dataSource
|
||||||
|
.createQueryBuilder()
|
||||||
|
.insert()
|
||||||
|
.into(permission)
|
||||||
|
.values({
|
||||||
|
permission: createPermission.permission,
|
||||||
|
user: await UserService.getById(createPermission.userId),
|
||||||
|
})
|
||||||
|
.execute()
|
||||||
|
.then((result) => {
|
||||||
|
return result.identifiers[0].id;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw new InternalException("Failed saving permission");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description remove permission to user
|
||||||
|
* @param DeletePermissionCommand
|
||||||
|
* @returns {Promise<any>}
|
||||||
|
*/
|
||||||
|
static async deleteByToken(deletePermission: DeletePermissionCommand): Promise<any> {
|
||||||
|
return await dataSource
|
||||||
|
.createQueryBuilder()
|
||||||
|
.delete()
|
||||||
|
.from(permission)
|
||||||
|
.where("permission.id = :id", { id: deletePermission.id })
|
||||||
|
.execute()
|
||||||
|
.then((res) => {})
|
||||||
|
.catch((err) => {
|
||||||
|
throw new InternalException("failed permission removal");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,17 +1,15 @@
|
||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import { JWTHelper } from "../helpers/jwtHelper";
|
import { JWTHelper } from "../helpers/jwtHelper";
|
||||||
import { JWTData, JWTToken } from "../type/jwtTypes";
|
import { JWTToken } from "../type/jwtTypes";
|
||||||
import InternalException from "../exceptions/internalException";
|
import InternalException from "../exceptions/internalException";
|
||||||
import RefreshCommandHandler from "../command/refreshCommandHandler";
|
import RefreshCommandHandler from "../command/refreshCommandHandler";
|
||||||
import { CreateRefreshCommand, DeleteRefreshCommand } from "../command/refreshCommand";
|
import { CreateRefreshCommand, DeleteRefreshCommand } from "../command/refreshCommand";
|
||||||
import UserService from "../service/userService";
|
import UserService from "../service/userService";
|
||||||
import speakeasy from "speakeasy";
|
import speakeasy from "speakeasy";
|
||||||
import UnauthorizedRequestException from "../exceptions/unauthorizedRequestException";
|
import UnauthorizedRequestException from "../exceptions/unauthorizedRequestException";
|
||||||
import QRCode from "qrcode";
|
|
||||||
import { CreateUserCommand } from "../command/userCommand";
|
|
||||||
import UserCommandHandler from "../command/userCommandHandler";
|
|
||||||
import RefreshService from "../service/refreshService";
|
import RefreshService from "../service/refreshService";
|
||||||
import BadRequestException from "../exceptions/badRequestException";
|
import PermissionService from "../service/permissionService";
|
||||||
|
import PermissionHelper from "../helpers/permissionHelper";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Check authentication status by token
|
* @description Check authentication status by token
|
||||||
|
@ -23,7 +21,7 @@ export async function login(req: Request, res: Response): Promise<any> {
|
||||||
let username = req.body.username;
|
let username = req.body.username;
|
||||||
let totp = req.body.totp;
|
let totp = req.body.totp;
|
||||||
|
|
||||||
let { id, secret } = await UserService.getByUsername(username);
|
let { id, secret, mail, firstname, lastname } = await UserService.getByUsername(username);
|
||||||
|
|
||||||
let valid = speakeasy.totp.verify({
|
let valid = speakeasy.totp.verify({
|
||||||
secret: secret,
|
secret: secret,
|
||||||
|
@ -36,10 +34,17 @@ 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 permissionStrings = permissions.map((e) => e.permission);
|
||||||
|
let permissionObject = PermissionHelper.convertToObject(permissionStrings);
|
||||||
|
|
||||||
let jwtData: JWTToken = {
|
let jwtData: JWTToken = {
|
||||||
userId: id,
|
userId: id,
|
||||||
|
mail: mail,
|
||||||
username: username,
|
username: username,
|
||||||
rights: [],
|
firstname: firstname,
|
||||||
|
lastname: lastname,
|
||||||
|
permissions: permissionObject,
|
||||||
};
|
};
|
||||||
|
|
||||||
let accessToken: string;
|
let accessToken: string;
|
||||||
|
@ -96,12 +101,19 @@ export async function refresh(req: Request, res: Response): Promise<any> {
|
||||||
throw new UnauthorizedRequestException("user not identified with token and refresh");
|
throw new UnauthorizedRequestException("user not identified with token and refresh");
|
||||||
}
|
}
|
||||||
|
|
||||||
let { id, username } = await UserService.getById(tokenUserId);
|
let { id, username, mail, firstname, lastname } = await UserService.getById(tokenUserId);
|
||||||
|
|
||||||
|
let permissions = await PermissionService.getByUser(id);
|
||||||
|
let permissionStrings = permissions.map((e) => e.permission);
|
||||||
|
let permissionObject = PermissionHelper.convertToObject(permissionStrings);
|
||||||
|
|
||||||
let jwtData: JWTToken = {
|
let jwtData: JWTToken = {
|
||||||
userId: id,
|
userId: id,
|
||||||
|
mail: mail,
|
||||||
username: username,
|
username: username,
|
||||||
rights: [],
|
firstname: firstname,
|
||||||
|
lastname: lastname,
|
||||||
|
permissions: permissionObject,
|
||||||
};
|
};
|
||||||
|
|
||||||
let accessToken: string;
|
let accessToken: string;
|
||||||
|
|
|
@ -16,6 +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 PermissionCommandHandler from "../command/permissionCommandHandler";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description start first user
|
* @description start first user
|
||||||
|
@ -98,7 +100,7 @@ export async function verifyInvite(req: Request, res: Response): Promise<any> {
|
||||||
* @param res {Response} Express res object
|
* @param res {Response} Express res object
|
||||||
* @returns {Promise<*>}
|
* @returns {Promise<*>}
|
||||||
*/
|
*/
|
||||||
export async function finishInvite(req: Request, res: Response): Promise<any> {
|
export async function finishInvite(req: Request, res: Response, grantAdmin: boolean = false): Promise<any> {
|
||||||
let mail = req.body.mail;
|
let mail = req.body.mail;
|
||||||
let token = req.body.token;
|
let token = req.body.token;
|
||||||
let totp = req.body.totp;
|
let totp = req.body.totp;
|
||||||
|
@ -127,10 +129,23 @@ export async function finishInvite(req: Request, res: Response): Promise<any> {
|
||||||
};
|
};
|
||||||
let id = await UserCommandHandler.create(createUser);
|
let id = await UserCommandHandler.create(createUser);
|
||||||
|
|
||||||
|
if (grantAdmin) {
|
||||||
|
let createPermission: CreatePermissionCommand = {
|
||||||
|
permission: "*",
|
||||||
|
userId: id,
|
||||||
|
};
|
||||||
|
await PermissionCommandHandler.create(createPermission);
|
||||||
|
}
|
||||||
|
|
||||||
let jwtData: JWTToken = {
|
let jwtData: JWTToken = {
|
||||||
userId: id,
|
userId: id,
|
||||||
|
mail: mail,
|
||||||
username: username,
|
username: username,
|
||||||
rights: [],
|
firstname: firstname,
|
||||||
|
lastname: lastname,
|
||||||
|
permissions: {
|
||||||
|
...(grantAdmin ? { admin: true } : {}),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let accessToken: string;
|
let accessToken: string;
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
import "dotenv/config";
|
import "dotenv/config";
|
||||||
import "reflect-metadata";
|
import "reflect-metadata";
|
||||||
import { DataSource } from "typeorm";
|
import { DataSource } from "typeorm";
|
||||||
|
import { DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME } from "./env.defaults";
|
||||||
|
|
||||||
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 { 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 { DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME } from "./env.defaults";
|
import { Permissions1724661484664 } from "./migrations/1724661484664-permissions";
|
||||||
|
|
||||||
const dataSource = new DataSource({
|
const dataSource = new DataSource({
|
||||||
type: "mysql",
|
type: "mysql",
|
||||||
|
@ -21,8 +23,8 @@ 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],
|
entities: [user, refresh, invite, permission],
|
||||||
migrations: [Initial1724317398939, RefreshPrimaryChange1724573307851, Invite1724579024939],
|
migrations: [Initial1724317398939, RefreshPrimaryChange1724573307851, Invite1724579024939, Permissions1724661484664],
|
||||||
migrationsRun: true,
|
migrationsRun: true,
|
||||||
migrationsTransactionMode: "each",
|
migrationsTransactionMode: "each",
|
||||||
subscribers: [],
|
subscribers: [],
|
||||||
|
|
15
src/entity/permission.ts
Normal file
15
src/entity/permission.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { Column, Entity, ManyToOne, PrimaryColumn } from "typeorm";
|
||||||
|
import { user } from "./user";
|
||||||
|
import { PermissionObject, PermissionString } from "../type/permissionTypes";
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class permission {
|
||||||
|
@PrimaryColumn({ type: "int" })
|
||||||
|
userId: number;
|
||||||
|
|
||||||
|
@PrimaryColumn({ type: "varchar", length: 255 })
|
||||||
|
permission: PermissionString;
|
||||||
|
|
||||||
|
@ManyToOne(() => user)
|
||||||
|
user: user;
|
||||||
|
}
|
7
src/exceptions/forbiddenRequestException.ts
Normal file
7
src/exceptions/forbiddenRequestException.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import CustomRequestException from "./customRequestException";
|
||||||
|
|
||||||
|
export default class ForbiddenRequestException extends CustomRequestException {
|
||||||
|
constructor(msg: string) {
|
||||||
|
super(403, msg);
|
||||||
|
}
|
||||||
|
}
|
124
src/helpers/permissionHelper.ts
Normal file
124
src/helpers/permissionHelper.ts
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
import { Request, Response } from "express";
|
||||||
|
import {
|
||||||
|
PermissionModule,
|
||||||
|
permissionModules,
|
||||||
|
PermissionObject,
|
||||||
|
PermissionSection,
|
||||||
|
PermissionString,
|
||||||
|
PermissionType,
|
||||||
|
permissionTypes,
|
||||||
|
} from "../type/permissionTypes";
|
||||||
|
import ForbiddenRequestException from "../exceptions/forbiddenRequestException";
|
||||||
|
|
||||||
|
export default class PermissionHelper {
|
||||||
|
static passCheckMiddleware(
|
||||||
|
section: PermissionSection,
|
||||||
|
module: PermissionModule,
|
||||||
|
requiredPermissions: Array<PermissionType> | "*"
|
||||||
|
): (req: Request, res: Response, next: Function) => void {
|
||||||
|
return (req: Request, res: Response, next: Function) => {
|
||||||
|
const permissions = req.rights;
|
||||||
|
|
||||||
|
if (permissions.admin) {
|
||||||
|
next();
|
||||||
|
} else if (permissions?.[section]?.all) {
|
||||||
|
next();
|
||||||
|
} else if (permissions?.[section]?.all) {
|
||||||
|
next();
|
||||||
|
} else if (permissions?.[section]?.[module] == "*") {
|
||||||
|
next();
|
||||||
|
} else if (
|
||||||
|
(permissions?.[section]?.[module] as Array<PermissionType>).some((e: PermissionType) =>
|
||||||
|
requiredPermissions.includes(e)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
throw new ForbiddenRequestException(
|
||||||
|
`missing permission for ${section}.${module}.${
|
||||||
|
Array.isArray(requiredPermissions) ? requiredPermissions.join("|") : requiredPermissions
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static convertToObject(permissions: Array<PermissionString>): PermissionObject {
|
||||||
|
if (permissions.includes("*")) {
|
||||||
|
return {
|
||||||
|
admin: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
let output: PermissionObject = {};
|
||||||
|
let splitPermissions = permissions.map((e) => e.split(".")) as Array<
|
||||||
|
[PermissionSection, PermissionModule | PermissionType | "*", PermissionType | "*"]
|
||||||
|
>;
|
||||||
|
for (let split of splitPermissions) {
|
||||||
|
if (!output[split[0]]) {
|
||||||
|
output[split[0]] = {};
|
||||||
|
}
|
||||||
|
if (split[1] == "*" || output[split[0]].all == "*") {
|
||||||
|
output[split[0]] = { all: "*" };
|
||||||
|
} else if (permissionTypes.includes(split[1] as PermissionType)) {
|
||||||
|
if (!output[split[0]].all || !Array.isArray(output[split[0]].all)) {
|
||||||
|
output[split[0]].all = [];
|
||||||
|
}
|
||||||
|
const permissionIndex = permissionTypes.indexOf(split[1] as PermissionType);
|
||||||
|
const appliedPermissions = permissionTypes.slice(0, permissionIndex + 1);
|
||||||
|
output[split[0]].all = appliedPermissions;
|
||||||
|
} else {
|
||||||
|
if (split[2] == "*" || output[split[0]][split[1] as PermissionModule] == "*") {
|
||||||
|
output[split[0]][split[1] as PermissionModule] = "*";
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
!output[split[0]][split[1] as PermissionModule] ||
|
||||||
|
!Array.isArray(output[split[0]][split[1] as PermissionModule])
|
||||||
|
) {
|
||||||
|
output[split[0]][split[1] as PermissionModule] = [];
|
||||||
|
}
|
||||||
|
const permissionIndex = permissionTypes.indexOf(split[2] as PermissionType);
|
||||||
|
const appliedPermissions = permissionTypes.slice(0, permissionIndex + 1);
|
||||||
|
output[split[0]][split[1] as PermissionModule] = appliedPermissions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
static convertToStringArray(permissions: PermissionObject): Array<PermissionString> {
|
||||||
|
if (permissions.admin) {
|
||||||
|
return ["*"];
|
||||||
|
}
|
||||||
|
let output: Array<PermissionString> = [];
|
||||||
|
let sections = Object.keys(permissions) as Array<PermissionSection>;
|
||||||
|
for (let section of sections) {
|
||||||
|
if (permissions[section].all) {
|
||||||
|
let types = permissions[section].all;
|
||||||
|
if (types == "*") {
|
||||||
|
output.push(`${section}.*`);
|
||||||
|
} else {
|
||||||
|
for (let type of types) {
|
||||||
|
output.push(`${section}.${type}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let modules = Object.keys(permissions[section]) as Array<PermissionModule>;
|
||||||
|
for (let module of modules) {
|
||||||
|
let types = permissions[section][module];
|
||||||
|
if (types == "*") {
|
||||||
|
output.push(`${section}.${module}.*`);
|
||||||
|
} else {
|
||||||
|
for (let type of types) {
|
||||||
|
output.push(`${section}.${module}.${type}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getWhatToAdd() {}
|
||||||
|
|
||||||
|
static getWhatToRemove() {}
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ declare global {
|
||||||
export interface Request {
|
export interface Request {
|
||||||
userId: string;
|
userId: string;
|
||||||
username: string;
|
username: string;
|
||||||
rights: Array<string>;
|
rights: PermissionObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ dataSource.initialize();
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
import router from "./routes/index";
|
import router from "./routes/index";
|
||||||
|
import { PermissionObject } from "./type/permissionTypes";
|
||||||
router(app);
|
router(app);
|
||||||
app.listen(SERVER_PORT, () => {
|
app.listen(SERVER_PORT, () => {
|
||||||
console.log(`listening on *:${SERVER_PORT}`);
|
console.log(`listening on *:${SERVER_PORT}`);
|
||||||
|
|
46
src/migrations/1724661484664-permissions.ts
Normal file
46
src/migrations/1724661484664-permissions.ts
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import { MigrationInterface, QueryRunner, Table, TableForeignKey } from "typeorm";
|
||||||
|
|
||||||
|
export class Permissions1724661484664 implements MigrationInterface {
|
||||||
|
name = "Permissions1724661484664";
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.createTable(
|
||||||
|
new Table({
|
||||||
|
name: "permission",
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: "permission",
|
||||||
|
type: "varchar",
|
||||||
|
length: "255",
|
||||||
|
isPrimary: true,
|
||||||
|
isNullable: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "userId",
|
||||||
|
type: "int",
|
||||||
|
isPrimary: true,
|
||||||
|
isNullable: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
await queryRunner.createForeignKey(
|
||||||
|
"permission",
|
||||||
|
new TableForeignKey({
|
||||||
|
columnNames: ["userId"],
|
||||||
|
referencedColumnNames: ["id"],
|
||||||
|
referencedTableName: "user",
|
||||||
|
onDelete: "No Action",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
const table = await queryRunner.getTable("permission");
|
||||||
|
const foreignKey = table.foreignKeys.find((fk) => fk.columnNames.indexOf("userId") !== -1);
|
||||||
|
await queryRunner.dropForeignKey("permission", foreignKey);
|
||||||
|
await queryRunner.dropTable("permission");
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ router.post(
|
||||||
);
|
);
|
||||||
|
|
||||||
router.put("/", ParamaterPassCheckHelper.requiredIncludedMiddleware(["mail", "token", "totp"]), async (req, res) => {
|
router.put("/", ParamaterPassCheckHelper.requiredIncludedMiddleware(["mail", "token", "totp"]), async (req, res) => {
|
||||||
await finishInvite(req, res);
|
await finishInvite(req, res, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
24
src/service/permissionService.ts
Normal file
24
src/service/permissionService.ts
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import { dataSource } from "../data-source";
|
||||||
|
import { permission } from "../entity/permission";
|
||||||
|
import InternalException from "../exceptions/internalException";
|
||||||
|
|
||||||
|
export default abstract class PermissionService {
|
||||||
|
/**
|
||||||
|
* @description get permission by user
|
||||||
|
* @param user number
|
||||||
|
* @returns {Promise<Array<permission>>}
|
||||||
|
*/
|
||||||
|
static async getByUser(userId: number): Promise<Array<permission>> {
|
||||||
|
return await dataSource
|
||||||
|
.getRepository(permission)
|
||||||
|
.createQueryBuilder("permission")
|
||||||
|
.where("permission.userId = :userId", { userId: userId })
|
||||||
|
.getMany()
|
||||||
|
.then((res) => {
|
||||||
|
return res;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw new InternalException("permission not found by user");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,16 @@
|
||||||
|
import { PermissionObject } from "./permissionTypes";
|
||||||
|
|
||||||
export type JWTData = {
|
export type JWTData = {
|
||||||
[key: string]: string | number | Array<string>;
|
[key: string]: string | number | PermissionObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type JWTToken = {
|
export type JWTToken = {
|
||||||
userId: number;
|
userId: number;
|
||||||
|
mail: string;
|
||||||
username: string;
|
username: string;
|
||||||
rights: Array<string>;
|
firstname: string;
|
||||||
|
lastname: string;
|
||||||
|
permissions: PermissionObject;
|
||||||
} & JWTData;
|
} & JWTData;
|
||||||
|
|
||||||
export type JWTRefresh = {
|
export type JWTRefresh = {
|
||||||
|
|
24
src/type/permissionTypes.ts
Normal file
24
src/type/permissionTypes.ts
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
export type PermissionSection = "club" | "settings" | "user";
|
||||||
|
|
||||||
|
export type PermissionModule = "protocoll" | "user";
|
||||||
|
|
||||||
|
export type PermissionType = "read" | "create" | "update" | "delete";
|
||||||
|
|
||||||
|
export type PermissionString =
|
||||||
|
| `${PermissionSection}.${PermissionModule}.${PermissionType}` // für spezifische Berechtigungen
|
||||||
|
| `${PermissionSection}.${PermissionModule}.*` // für alle Berechtigungen in einem Modul
|
||||||
|
| `${PermissionSection}.${PermissionType}` // für spezifische Berechtigungen in einem Abschnitt
|
||||||
|
| `${PermissionSection}.*` // für alle Berechtigungen in einem Abschnitt
|
||||||
|
| "*"; // für Admin
|
||||||
|
|
||||||
|
export type PermissionObject = {
|
||||||
|
[section in PermissionSection]?: {
|
||||||
|
[module in PermissionModule]?: Array<PermissionType> | "*";
|
||||||
|
} & { all?: Array<PermissionType> | "*" };
|
||||||
|
} & {
|
||||||
|
admin?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const permissionSections: Array<PermissionSection> = ["club", "settings", "user"];
|
||||||
|
export const permissionModules: Array<PermissionModule> = ["protocoll", "user"];
|
||||||
|
export const permissionTypes: Array<PermissionType> = ["read", "create", "update", "delete"];
|
1
src/viewmodel/permissionViewModel.ts
Normal file
1
src/viewmodel/permissionViewModel.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export interface PermissionViewModel {}
|
Loading…
Reference in a new issue