GetModelPermissions.ts 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import { isObjectIdOrHexString } from "mongoose";
  2. import CacheModule from "@/modules/CacheModule";
  3. import DataModule from "@/modules/DataModule";
  4. import ModuleManager from "@/ModuleManager";
  5. import GetPermissions from "./GetPermissions";
  6. import DataModuleJob from "@/modules/DataModule/DataModuleJob";
  7. import { forEachIn } from "@/utils/forEachIn";
  8. export default class GetModelPermissions extends DataModuleJob {
  9. protected static _modelName = "users";
  10. protected static _hasPermission = true;
  11. protected override async _validate() {
  12. if (typeof this._payload !== "object" || this._payload === null)
  13. throw new Error("Payload must be an object");
  14. if (typeof this._payload.modelName !== "string")
  15. throw new Error("Model name must be a string");
  16. if (
  17. !isObjectIdOrHexString(this._payload.modelId) &&
  18. typeof this._payload.modelId !== "undefined" &&
  19. this._payload.modelId !== null
  20. )
  21. throw new Error("Model Id must be an ObjectId or undefined");
  22. }
  23. protected override async _authorize() {}
  24. protected async _execute() {
  25. const { modelName, modelId } = this._payload;
  26. const user = await this._context.getUser().catch(() => null);
  27. const permissions = await this._context.executeJob(GetPermissions);
  28. let cacheKey = `model-permissions.${modelName}`;
  29. if (modelId) cacheKey += `.${modelId}`;
  30. if (user) cacheKey += `.user.${user._id}`;
  31. else cacheKey += `.guest`;
  32. const cached = await CacheModule.get(cacheKey);
  33. if (cached) return cached;
  34. const Model = await DataModule.getModel(modelName);
  35. if (!Model) throw new Error("Model not found");
  36. const model = modelId ? await Model.findById(modelId) : null;
  37. if (modelId && !model) throw new Error("Model not found");
  38. const { completed: jobs } = await forEachIn(
  39. Object.entries(
  40. ModuleManager.getModule("data")?.getJobs() ?? {}
  41. ).filter(
  42. ([jobName]) =>
  43. jobName.startsWith(modelName.toString()) &&
  44. (modelId ? true : !jobName.endsWith("ById"))
  45. ),
  46. async ([jobName, Job]) => {
  47. jobName = `data.${jobName}`;
  48. let hasPermission = permissions[jobName];
  49. if (!hasPermission && modelId)
  50. hasPermission =
  51. permissions[`${jobName}.*`] ||
  52. permissions[`${jobName}.${modelId}`];
  53. if (hasPermission) return [jobName, true];
  54. if (typeof Job.hasPermission === "function") {
  55. hasPermission = await Job.hasPermission(model, user);
  56. }
  57. return [jobName, !!hasPermission];
  58. }
  59. );
  60. const modelPermissions = Object.fromEntries(jobs);
  61. await CacheModule.set(cacheKey, modelPermissions, 360);
  62. return modelPermissions;
  63. }
  64. }