Refactor Realtime event handling and permissions management; introduce EnableRealtimeEventsOn interface

This commit is contained in:
Simon Larsen
2024-09-26 11:59:11 +01:00
parent 8afa3810a1
commit 2e5ec1df6f
11 changed files with 59 additions and 60 deletions

View File

@@ -1,3 +1,4 @@
import EnableRealtimeEventsOn from "../../../Server/Types/Realtime/EnableRealtimeEventsOn";
import Route from "../../../Types/API/Route";
import AnalyticsTableEngine from "../../../Types/AnalyticsDatabase/AnalyticsTableEngine";
import AnalyticsTableColumn from "../../../Types/AnalyticsDatabase/TableColumn";
@@ -19,7 +20,6 @@ import Permission, {
UserTenantAccessPermission,
} from "../../../Types/Permission";
import Text from "../../../Types/Text";
import { EnableRealtimeEventsOn } from "../../../Utils/Realtime";
import CommonModel from "./CommonModel";
export type AnalyticsBaseModelType = { new (): AnalyticsBaseModel };

View File

@@ -25,7 +25,7 @@ export const getModelTypeByName: GetModelTypeByName = (
tableName: string,
): (new () => AnalyticsBaseModel) | null => {
if (modelTypeMap[tableName]) {
return modelTypeMap[tableName];
return modelTypeMap[tableName] || null;
}
const modelType: { new (): AnalyticsBaseModel } | undefined =

View File

@@ -1,3 +1,4 @@
import EnableRealtimeEventsOn from "../../../Server/Types/Realtime/EnableRealtimeEventsOn";
import Route from "../../../Types/API/Route";
import { ColumnAccessControl } from "../../../Types/BaseDatabase/AccessControl";
import ColumnBillingAccessControl from "../../../Types/BaseDatabase/ColumnBillingAccessControl";
@@ -36,7 +37,6 @@ import {
UpdateDateColumn,
VersionColumn,
} from "typeorm";
import { EnableRealtimeEventsOn } from "../../../Utils/Realtime";
export type DbTypes =
| string

View File

@@ -317,7 +317,7 @@ export const getModelTypeByName: GetModelTypeByNameFunction = (
tableName: string,
): { new (): BaseModel } | null => {
if (modelTypeMap[tableName]) {
return modelTypeMap[tableName];
return modelTypeMap[tableName] || null;
}
const modelType: { new (): BaseModel } | undefined = AllModelTypes.find(

View File

@@ -313,7 +313,7 @@ export class Service extends DatabaseService<StatusPage> {
): Promise<boolean> {
try {
// token decode.
const token: string | undefined = CookieUtil.getCookie(
const token: string | undefined = CookieUtil.getCookieFromExpressRequest(
req,
CookieUtil.getUserTokenKey(statusPageId),
);

View File

@@ -0,0 +1,5 @@
export default interface EnableRealtimeEventsOn {
create?: boolean | undefined;
update?: boolean | undefined;
delete?: boolean | undefined;
}

View File

@@ -14,13 +14,15 @@ import RealtimeUtil, {
import UserMiddleware from "../Middleware/UserAuthorization";
import JSONWebTokenData from "../../Types/JsonWebTokenData";
import JSONWebToken from "./JsonWebToken";
import {
import Permission, {
UserGlobalAccessPermission,
UserTenantAccessPermission,
} from "../../Types/Permission";
import AccessTokenService from "../Services/AccessTokenService";
import ModelPermission from "../../Types/BaseDatabase/ModelPermission";
import { getModelTypeByName } from "../../Models/DatabaseModels/Index";
import { getModelTypeByName as getAnalyticsModelTypeByname } from "../../Models/AnalyticsModels/Index";
import DatabaseRequestType from "../Types/BaseDatabase/DatabaseRequestType";
import ModelPermission from "../../Types/BaseDatabase/ModelPermission";
export default abstract class Realtime {
private static socketServer: SocketServer | null = null;
@@ -179,7 +181,7 @@ export default abstract class Realtime {
// check if the user has access to this model
if (
userTenantAccessPermission &&
ModelPermission.hasPermissionsByModelName(
this.hasPermissionsByModelName(
userTenantAccessPermission,
data.modelName,
databaseRequestType,
@@ -291,4 +293,47 @@ export default abstract class Realtime {
this.socketServer!.to(roomId).emit(roomId, jsonObject);
this.socketServer!.to(modelRoomId).emit(modelRoomId, jsonObject);
}
public static hasPermissionsByModelName(
userProjectPermissions: UserTenantAccessPermission | Array<Permission>,
modelName: string,
requestType: DatabaseRequestType,
): boolean {
let modelPermissions: Array<Permission> = [];
let modelType:
| { new (): BaseModel }
| { new (): AnalyticsBaseModel }
| null = getModelTypeByName(modelName);
if (!modelType) {
// check if it is an analytics model
modelType = getAnalyticsModelTypeByname(modelName);
if (!modelType) {
return false;
}
}
if (requestType === DatabaseRequestType.Create) {
modelPermissions = new modelType().getCreatePermissions();
}
if (requestType === DatabaseRequestType.Read) {
modelPermissions = new modelType().getReadPermissions();
}
if (requestType === DatabaseRequestType.Update) {
modelPermissions = new modelType().getUpdatePermissions();
}
if (requestType === DatabaseRequestType.Delete) {
modelPermissions = new modelType().getDeletePermissions();
}
return ModelPermission.hasPermissions(
userProjectPermissions,
modelPermissions,
);
}
}

View File

@@ -1,56 +1,11 @@
import { getModelTypeByName } from "../../Models/DatabaseModels/Index";
import { getModelTypeByName as getAnalyticsModelTypeByname } from "../../Models/AnalyticsModels/Index";
import Permission, {
PermissionHelper,
UserPermission,
UserTenantAccessPermission,
instanceOfUserTenantAccessPermission,
} from "../Permission";
import BaseModel from "../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
import AnalyticsBaseModel from "../../Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel";
import DatabaseRequestType from "../../Server/Types/BaseDatabase/DatabaseRequestType";
export default class ModelPermission {
public static hasPermissionsByModelName(
userProjectPermissions: UserTenantAccessPermission | Array<Permission>,
modelName: string,
requestType: DatabaseRequestType,
): boolean {
let modelPermissions: Array<Permission> = [];
let modelType:
| { new (): BaseModel }
| { new (): AnalyticsBaseModel }
| null = getModelTypeByName(modelName);
if (!modelType) {
// check if it is an analytics model
modelType = getAnalyticsModelTypeByname(modelName);
if (!modelType) {
return false;
}
}
if (requestType === DatabaseRequestType.Create) {
modelPermissions = new modelType().getCreatePermissions();
}
if (requestType === DatabaseRequestType.Read) {
modelPermissions = new modelType().getReadPermissions();
}
if (requestType === DatabaseRequestType.Update) {
modelPermissions = new modelType().getUpdatePermissions();
}
if (requestType === DatabaseRequestType.Delete) {
modelPermissions = new modelType().getDeletePermissions();
}
return this.hasPermissions(userProjectPermissions, modelPermissions);
}
public static hasPermissions(
userProjectPermissions: UserTenantAccessPermission | Array<Permission>,
modelPermissions: Array<Permission>,

View File

@@ -1,4 +1,4 @@
import { EnableRealtimeEventsOn } from "../../Utils/Realtime";
import EnableRealtimeEventsOn from "../../Server/Types/Realtime/EnableRealtimeEventsOn";
import GenericFunction from "../GenericFunction";
import IconProp from "../Icon/IconProp";

View File

@@ -19,12 +19,6 @@ export interface ListenToModelEventJSON {
modelId?: string | undefined;
}
export interface EnableRealtimeEventsOn {
create?: boolean | undefined;
update?: boolean | undefined;
delete?: boolean | undefined;
}
export default class RealtimeUtil {
public static getRoomId(
tenantId: string | ObjectID,