GetModelPermissions.ts 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import { Types, isObjectIdOrHexString } from "mongoose";
  2. import CacheModule from "@/modules/CacheModule";
  3. import DataModule from "@/modules/DataModule";
  4. import { Models } from "@/types/Models";
  5. import ModuleManager from "@/ModuleManager";
  6. import GetPermissions from "./GetPermissions";
  7. import DataModuleJob from "@/modules/DataModule/DataModuleJob";
  8. export default class GetModelPermissions extends DataModuleJob {
  9. protected static _modelName: keyof Models = "users";
  10. protected static _hasPermission = true;
  11. protected override async _validate() {
  12. if (typeof this._payload !== "object")
  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. modelName,
  26. modelId
  27. }: {
  28. modelName: keyof Models;
  29. modelId?: Types.ObjectId;
  30. }) {
  31. const user = await this._context.getUser().catch(() => null);
  32. const permissions = await this._context.executeJob(GetPermissions);
  33. let cacheKey = `model-permissions.${modelName}`;
  34. if (modelId) cacheKey += `.${modelId}`;
  35. if (user) cacheKey += `.user.${user._id}`;
  36. else cacheKey += `.guest`;
  37. const cached = await CacheModule.get(cacheKey);
  38. if (cached) return cached;
  39. const Model = await DataModule.getModel(modelName);
  40. if (!Model) throw new Error("Model not found");
  41. const model = modelId ? await Model.findById(modelId) : null;
  42. if (modelId && !model) throw new Error("Model not found");
  43. const jobs = await Promise.all(
  44. Object.entries(ModuleManager.getModule("data")?.getJobs() ?? {})
  45. .filter(
  46. ([jobName]) =>
  47. jobName.startsWith(modelName.toString()) &&
  48. (modelId ? true : !jobName.endsWith("ById"))
  49. )
  50. .map(async ([jobName, Job]) => {
  51. jobName = `data.${jobName}`;
  52. let hasPermission = permissions[jobName];
  53. if (!hasPermission && modelId)
  54. hasPermission =
  55. permissions[`${jobName}.*`] ||
  56. permissions[`${jobName}.${modelId}`];
  57. if (hasPermission) return [jobName, true];
  58. if (typeof Job.hasPermission === "function") {
  59. hasPermission = await Job.hasPermission(model, user);
  60. }
  61. return [jobName, !!hasPermission];
  62. })
  63. );
  64. const modelPermissions = Object.fromEntries(jobs);
  65. await CacheModule.set(cacheKey, modelPermissions, 360);
  66. return modelPermissions;
  67. }
  68. }