DataModuleJob.ts 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import { HydratedDocument, Model, isValidObjectId } from "mongoose";
  2. import Job, { JobOptions } from "@/Job";
  3. import DataModule from "../DataModule";
  4. import { UserSchema } from "./models/users/schema";
  5. export default abstract class DataModuleJob extends Job {
  6. protected static _modelName: string;
  7. protected static _isBulk = false;
  8. protected static _hasPermission:
  9. | boolean
  10. | CallableFunction
  11. | (boolean | CallableFunction)[] = false;
  12. public constructor(payload?: unknown, options?: JobOptions) {
  13. super(DataModule, payload, options);
  14. }
  15. public static override getName() {
  16. return `${this._modelName}.${super.getName()}`;
  17. }
  18. public override getName() {
  19. return `${
  20. (this.constructor as typeof DataModuleJob)._modelName
  21. }.${super.getName()}`;
  22. }
  23. public static getModelName() {
  24. return this._modelName;
  25. }
  26. public getModelName() {
  27. return (this.constructor as typeof DataModuleJob)._modelName;
  28. }
  29. public static isBulk() {
  30. return this._isBulk;
  31. }
  32. public isBulk() {
  33. return (this.constructor as typeof DataModuleJob)._isBulk;
  34. }
  35. public static async hasPermission(
  36. model: HydratedDocument<Model<any>>,
  37. user: HydratedDocument<UserSchema> | null
  38. ) {
  39. const options = Array.isArray(this._hasPermission)
  40. ? this._hasPermission
  41. : [this._hasPermission];
  42. return options.reduce(async (previous, option) => {
  43. if (await previous) return true;
  44. if (typeof option === "boolean") return option;
  45. if (typeof option === "function") return option(model, user);
  46. return false;
  47. }, Promise.resolve(false));
  48. }
  49. protected override async _authorize() {
  50. const modelIds = this._payload?.modelIds ?? this._payload?._ids;
  51. // If this job is a bulk job, and all model ids are valid object ids
  52. if (this.isBulk()) {
  53. if (modelIds.some((modelId: unknown) => !isValidObjectId(modelId)))
  54. throw new Error(
  55. `One or more model id is invalid: ${modelIds
  56. .filter((modelId: unknown) => !isValidObjectId(modelId))
  57. .join(", ")}`
  58. );
  59. const permissions = modelIds.map(
  60. (modelId: string) => `${this.getPath()}.${modelId}`
  61. );
  62. await this._context.assertPermissions(permissions);
  63. return;
  64. }
  65. const modelId = this._payload?.modelId ?? this._payload?._id;
  66. // If this job is not a bulk job, and the model id is a valid object id
  67. if (!this.isBulk() && modelId) {
  68. if (!isValidObjectId(modelId))
  69. throw new Error(`Model id is invalid: ${modelId}`);
  70. await this._context.assertPermission(
  71. `${this.getPath()}.${modelId}`
  72. );
  73. return;
  74. }
  75. await this._context.assertPermission(this.getPath());
  76. }
  77. }