浏览代码

refactor: change permission scope delimiter for jobs and events

Kristian Vos 8 月之前
父节点
当前提交
1e93eb6545

+ 20 - 5
backend/src/JobContext.ts

@@ -13,7 +13,8 @@ import {
 import { GetPermissionsResult } from "./modules/DataModule/models/users/jobs/GetPermissions";
 
 const permissionRegex =
-	/^(?<moduleName>[a-z]+)\.(?<modelOrJobName>[A-z]+)\.(?<jobName>[A-z]+)(?:\.(?<modelId>[A-z0-9]{24}))?(?:\.(?<extra>[A-z]+))?$/;
+	// eslint-disable-next-line max-len
+	/^(?<moduleName>[a-z]+)\.(?<modelOrJobName>[A-z]+)\.(?<jobName>[A-z]+)(?::(?:(?<modelId>[A-z0-9]{24})(?:\.(?<extraAfterModelId>[A-z]+))?|(?<extraAfterColon>[A-z]+)))?$/;
 
 export default class JobContext {
 	public readonly job: Job;
@@ -99,8 +100,15 @@ export default class JobContext {
 	public async assertPermission(permission: string) {
 		let hasPermission = false;
 
-		const { moduleName, modelOrJobName, jobName, modelId, extra } =
-			permissionRegex.exec(permission)?.groups ?? {};
+		const {
+			moduleName,
+			modelOrJobName,
+			jobName,
+			modelId,
+			extraAfterModelId,
+			extraAfterColon
+		} = permissionRegex.exec(permission)?.groups ?? {};
+		const extra = extraAfterModelId || extraAfterColon;
 
 		if (moduleName === "data" && modelOrJobName && jobName) {
 			const GetModelPermissions = DataModule.getJob(
@@ -140,8 +148,15 @@ export default class JobContext {
 		});
 
 		const permissionData = permissions.map(permission => {
-			const { moduleName, modelOrJobName, jobName, modelId, extra } =
-				permissionRegex.exec(permission)?.groups ?? {};
+			const {
+				moduleName,
+				modelOrJobName,
+				jobName,
+				modelId,
+				extraAfterModelId,
+				extraAfterColon
+			} = permissionRegex.exec(permission)?.groups ?? {};
+			const extra = extraAfterModelId || extraAfterColon;
 
 			return {
 				permission,

+ 1 - 1
backend/src/modules/DataModule/models/stations/jobs/Index.ts

@@ -47,7 +47,7 @@ export default class Index extends DataModuleJob {
 				(user && (isOwner(station, user) || isDj(station, user))) ||
 				(this._payload?.adminFilter &&
 					(await this._context
-						.assertPermission("data.stations.index.adminFilter")
+						.assertPermission("data.stations.index:adminFilter")
 						.then(() => true)
 						.catch(() => false)))
 			)

+ 15 - 3
backend/src/modules/DataModule/models/users/permissions.ts

@@ -191,9 +191,21 @@ const admin = {
 	// 	  }
 	// 	: {})
 
-	"event.data.news.created": true, // For now, only admins can subscribe to these, but that's just temporary
-	"event.data.news.updated.*": true,
-	"event.data.news.deleted.*": true
+	"event.data.minifiedUsers.created": true,
+	"event.data.minifiedUsers.updated:*": true,
+	"event.data.minifiedUsers.deleted:*": true,
+
+	"event.data.news.created": true,
+	"event.data.news.updated:*": true,
+	"event.data.news.deleted:*": true,
+
+	"event.data.stations.created": true,
+	"event.data.stations.updated:*": true,
+	"event.data.stations.deleted:*": true,
+
+	"event.data.users.created": true,
+	"event.data.users.updated:*": true,
+	"event.data.users.deleted:*": true
 };
 
 const permissions: Record<

+ 11 - 4
backend/src/modules/EventsModule.ts

@@ -19,7 +19,7 @@ import { GetSingleModelPermissionsResult } from "@/modules/DataModule/models/use
 
 const permissionRegex =
 	// eslint-disable-next-line max-len
-	/^event.(?<moduleName>[a-z]+)\.(?<modelOrEventName>[A-z]+)\.(?<eventName>[A-z]+)(?:\.(?<modelId>[A-z0-9]{24}))?(?:\.(?<extra>[A-z]+))?$/;
+	/^event.(?<moduleName>[a-z]+)\.(?<modelOrEventName>[A-z]+)\.(?<eventName>[A-z]+)(?::(?:(?<modelId>[A-z0-9]{24})(?:\.(?<extraAfterModelId>[A-z]+))?|(?<extraAfterColon>[A-z]+)))?$/;
 
 export class EventsModule extends BaseModule {
 	/**
@@ -206,14 +206,21 @@ export class EventsModule extends BaseModule {
 	/**
 	 * Like JobContext assertPermission, checks if the current user has permission to subscribe to the event associated
 	 * with the provided permission.
-	 * Permission can be for example "event.data.news.created" or "event.data.news.updated.6687eec103808fe513c937ff"
+	 * Permission can be for example "event.data.news.created" or "event.data.news.updated:6687eec103808fe513c937ff"
 	 */
 	public async assertPermission(permission: string) {
 		console.log("Assert permission", permission);
 		let hasPermission = false;
 
-		const { moduleName, modelOrEventName, eventName, modelId, extra } =
-			permissionRegex.exec(permission)?.groups ?? {};
+		const {
+			moduleName,
+			modelOrEventName,
+			eventName,
+			modelId,
+			extraAfterModelId,
+			extraAfterColon
+		} = permissionRegex.exec(permission)?.groups ?? {};
+		const extra = extraAfterModelId || extraAfterColon;
 
 		if (moduleName === "data" && modelOrEventName && eventName) {
 			const GetModelPermissions = DataModule.getJob(

+ 3 - 3
backend/src/modules/EventsModule/jobs/Subscribe.spec.ts

@@ -235,7 +235,7 @@ describe("Subscribe job", async function () {
 		describe("data.news.updated:${modelId}", function () {
 			const modelId = new mongoose.Types.ObjectId();
 			const channel = `data.news.updated:${modelId}`;
-			const permission = `event.data.news.updated.${modelId}`;
+			const permission = `event.data.news.updated:${modelId}`;
 
 			it("should work for admins for all news", async function () {
 				const job = getJob({
@@ -294,7 +294,7 @@ describe("Subscribe job", async function () {
 		describe("data.news.deleted:${modelId}", function () {
 			const modelId = new mongoose.Types.ObjectId();
 			const channel = `data.news.deleted:${modelId}`;
-			const permission = `event.data.news.deleted.${modelId}`;
+			const permission = `event.data.news.deleted:${modelId}`;
 
 			it("should work for admins for all news", async function () {
 				const job = getJob({
@@ -372,7 +372,7 @@ describe("Subscribe job", async function () {
 		describe("data.news.unpublished:${modelId}", function () {
 			// const modelId = new mongoose.Types.ObjectId();
 			// const channel = `data.news.unpublished:${modelId}`;
-			// const permission = `event.data.news.unpublished.${modelId}`;
+			// const permission = `event.data.news.unpublished:${modelId}`;
 
 			it("should work for admins for all news");
 			// it("should work for admins for all news", async function () {

+ 1 - 1
backend/src/modules/EventsModule/jobs/Subscribe.ts

@@ -24,7 +24,7 @@ export default class Subscribe extends Job {
 		// Path can be for example data.news.created. Scope will be anything after ":", but isn't required, so could be undefined
 		const { path, scope } = Event.parseKey(channel);
 
-		const permission = scope ? `event.${path}.${scope}` : `event.${path}`;
+		const permission = scope ? `event.${path}:${scope}` : `event.${path}`;
 
 		await EventsModule.assertPermission(permission);
 	}

+ 1 - 1
backend/src/modules/EventsModule/jobs/SubscribeMany.ts

@@ -30,7 +30,7 @@ export default class SubscribeMany extends Job {
 			const { path, scope } = Event.parseKey(channel);
 
 			const permission = scope
-				? `event.${path}.${scope}`
+				? `event.${path}:${scope}`
 				: `event.${path}`;
 
 			await EventsModule.assertPermission(permission);