Explorar el Código

feat: Cache user permissions

Owen Diffey hace 1 año
padre
commit
c34dc9733c
Se han modificado 2 ficheros con 45 adiciones y 3 borrados
  1. 19 1
      backend/src/models/schemas/users/config.ts
  2. 26 2
      backend/src/modules/APIModule.ts

+ 19 - 1
backend/src/models/schemas/users/config.ts

@@ -1 +1,19 @@
-export default { documentVersion: 4 };
+import CacheModule from "@/modules/CacheModule";
+
+export default {
+	documentVersion: 4,
+	eventListeners: {
+		"model.users.updated": ({ doc }) => {
+			CacheModule.removeMany([
+				`user-permissions.${doc._id}`,
+				`model-permissions.*.user.${doc._id}`
+			]);
+		},
+		"model.users.deleted": ({ oldDoc }) => {
+			CacheModule.removeMany([
+				`user-permissions.${oldDoc._id}`,
+				`model-permissions.*.user.${oldDoc._id}`
+			]);
+		}
+	}
+};

+ 26 - 2
backend/src/modules/APIModule.ts

@@ -13,6 +13,7 @@ import ModuleManager from "@/ModuleManager";
 import JobQueue from "@/JobQueue";
 import DataModule from "@/modules/DataModule";
 import EventsModule from "./EventsModule";
+import CacheModule from "./CacheModule";
 
 export class APIModule extends BaseModule {
 	private _subscriptions: Record<string, Set<string>>;
@@ -23,7 +24,7 @@ export class APIModule extends BaseModule {
 	public constructor() {
 		super("api");
 
-		this._dependentModules = ["data", "events", "websocket"];
+		this._dependentModules = ["cache", "data", "events", "websocket"];
 
 		this._subscriptions = {};
 
@@ -199,6 +200,12 @@ export class APIModule extends BaseModule {
 
 		if (!user) return permissions.guest;
 
+		const cacheKey = `user-permissions.${user._id}`;
+
+		const cached = await CacheModule.get(cacheKey);
+
+		if (cached) return cached;
+
 		const roles: UserRole[] = [user.role];
 
 		let rolePermissions: Record<string, boolean> = {};
@@ -207,6 +214,8 @@ export class APIModule extends BaseModule {
 				rolePermissions = { ...rolePermissions, ...permissions[role] };
 		});
 
+		await CacheModule.set(cacheKey, rolePermissions, 360);
+
 		return rolePermissions;
 	}
 
@@ -220,6 +229,17 @@ export class APIModule extends BaseModule {
 		const user = await context.getUser().catch(() => null);
 		const permissions = await context.getUserPermissions();
 
+		let cacheKey = `model-permissions.${modelName}`;
+
+		if (modelId) cacheKey += `.${modelId}`;
+
+		if (user) cacheKey += `.user.${user._id}`;
+		else cacheKey += `.guest`;
+
+		const cached = await CacheModule.get(cacheKey);
+
+		if (cached) return cached;
+
 		const Model = await DataModule.getModel(modelName);
 
 		if (!Model) throw new Error("Model not found");
@@ -277,7 +297,11 @@ export class APIModule extends BaseModule {
 				})
 		);
 
-		return Object.fromEntries(jobs);
+		const modelPermissions = Object.fromEntries(jobs);
+
+		await CacheModule.set(cacheKey, modelPermissions, 360);
+
+		return modelPermissions;
 	}
 
 	private async _subscriptionCallback(channel: string, value?: any) {