JobContext.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import { Types } from "mongoose";
  2. import BaseModule from "./BaseModule";
  3. import Job from "./Job";
  4. import JobQueue from "./JobQueue";
  5. import { Log } from "./LogBook";
  6. import { SessionSchema } from "./models/schemas/sessions/schema";
  7. import { JobOptions } from "./types/JobOptions";
  8. import { Jobs, Modules } from "./types/Modules";
  9. import { Models } from "./types/Models";
  10. export default class JobContext {
  11. public readonly job: Job;
  12. public readonly jobQueue: JobQueue;
  13. private _session?: SessionSchema;
  14. private readonly _socketId?: string;
  15. public constructor(
  16. job: Job,
  17. options?: { session?: SessionSchema; socketId?: string }
  18. ) {
  19. this.job = job;
  20. this.jobQueue = JobQueue.getPrimaryInstance();
  21. this._session = options?.session;
  22. this._socketId = options?.socketId;
  23. }
  24. /**
  25. * Log a message in the context of the current job, which automatically sets the category and data
  26. *
  27. * @param log - Log message or object
  28. */
  29. public log(log: string | Omit<Log, "timestamp" | "category">) {
  30. return this.job.log(log);
  31. }
  32. public getSession() {
  33. return this._session;
  34. }
  35. public setSession(session?: SessionSchema) {
  36. this._session = session;
  37. }
  38. public getSocketId() {
  39. return this._socketId;
  40. }
  41. /**
  42. * executeJob - Execute a job
  43. *
  44. * @param moduleName - Module name
  45. * @param jobName - Job name
  46. * @param params - Params
  47. */
  48. public async executeJob<
  49. ModuleNameType extends keyof Jobs & keyof Modules,
  50. JobNameType extends keyof Jobs[ModuleNameType] &
  51. keyof Omit<Modules[ModuleNameType], keyof BaseModule>,
  52. PayloadType extends "payload" extends keyof Jobs[ModuleNameType][JobNameType]
  53. ? Jobs[ModuleNameType][JobNameType]["payload"] extends undefined
  54. ? Record<string, never>
  55. : Jobs[ModuleNameType][JobNameType]["payload"]
  56. : Record<string, never>,
  57. ReturnType = "returns" extends keyof Jobs[ModuleNameType][JobNameType]
  58. ? Jobs[ModuleNameType][JobNameType]["returns"]
  59. : never
  60. >(
  61. moduleName: ModuleNameType,
  62. jobName: JobNameType,
  63. payload: PayloadType,
  64. options?: JobOptions
  65. ): Promise<ReturnType> {
  66. return new Job(jobName.toString(), moduleName, payload, {
  67. session: this._session,
  68. socketId: this._socketId,
  69. ...(options ?? {})
  70. }).execute();
  71. }
  72. public async getModel(model: keyof Models) {
  73. return this.executeJob("data", "getModel", model);
  74. }
  75. public async getUser() {
  76. if (!this._session?.userId)
  77. throw new Error("No user found for session");
  78. const User = await this.getModel("users");
  79. const user = await User.findById(this._session.userId);
  80. if (!user) throw new Error("No user found for session");
  81. return user;
  82. }
  83. public async assertLoggedIn() {
  84. if (!this._session?.userId)
  85. throw new Error("No user found for session");
  86. }
  87. public async getUserPermissions() {
  88. return this.executeJob("api", "getUserPermissions", {});
  89. }
  90. public async getUserModelPermissions({
  91. modelName,
  92. modelId
  93. }: {
  94. modelName: keyof Models;
  95. modelId?: Types.ObjectId;
  96. }) {
  97. return this.executeJob("api", "getUserModelPermissions", {
  98. modelName,
  99. modelId
  100. });
  101. }
  102. public async assertPermission(permission: string) {
  103. let hasPermission = false;
  104. const [, moduleName, modelOrJobName, jobName, modelId] =
  105. /^([a-z]+)\.([a-z]+)\.([A-z]+)\.?([A-z0-9]+)?$/.exec(permission) ??
  106. [];
  107. if (moduleName === "data" && modelOrJobName && jobName) {
  108. const permissions = await this.getUserModelPermissions({
  109. modelName: modelOrJobName,
  110. modelId
  111. });
  112. hasPermission = permissions[`data.${modelOrJobName}.${jobName}`];
  113. } else {
  114. const permissions = await this.getUserPermissions();
  115. hasPermission = permissions[permission];
  116. }
  117. if (!hasPermission) throw new Error("Insufficient permissions");
  118. }
  119. }