@loomcore/api 0.0.59 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +50 -0
  3. package/dist/__tests__/common-test.utils.d.ts +29 -60
  4. package/dist/__tests__/common-test.utils.js +88 -166
  5. package/dist/__tests__/index.d.ts +6 -0
  6. package/dist/__tests__/index.js +6 -0
  7. package/dist/__tests__/models/category.model.d.ts +8 -0
  8. package/dist/__tests__/models/category.model.js +6 -0
  9. package/dist/__tests__/models/product.model.d.ts +17 -0
  10. package/dist/__tests__/models/product.model.js +10 -0
  11. package/dist/__tests__/models/test-entity.model.d.ts +11 -0
  12. package/dist/__tests__/models/test-entity.model.js +10 -0
  13. package/dist/__tests__/models/test-item.model.d.ts +12 -0
  14. package/dist/__tests__/models/test-item.model.js +9 -0
  15. package/dist/__tests__/mongo-db.test-database.d.ts +15 -0
  16. package/dist/__tests__/mongo-db.test-database.js +74 -0
  17. package/dist/__tests__/postgres-test-migrations/001-create-test-entities-table.migration.d.ts +11 -0
  18. package/dist/__tests__/postgres-test-migrations/001-create-test-entities-table.migration.js +59 -0
  19. package/dist/__tests__/postgres-test-migrations/002-create-categories-table.migration.d.ts +11 -0
  20. package/dist/__tests__/postgres-test-migrations/002-create-categories-table.migration.js +52 -0
  21. package/dist/__tests__/postgres-test-migrations/003-create-products-table.migration.d.ts +11 -0
  22. package/dist/__tests__/postgres-test-migrations/003-create-products-table.migration.js +62 -0
  23. package/dist/__tests__/postgres-test-migrations/004-create-test-users-table.migration.d.ts +11 -0
  24. package/dist/__tests__/postgres-test-migrations/004-create-test-users-table.migration.js +66 -0
  25. package/dist/__tests__/postgres-test-migrations/005-create-test-items-table.migration.d.ts +11 -0
  26. package/dist/__tests__/postgres-test-migrations/005-create-test-items-table.migration.js +50 -0
  27. package/dist/__tests__/postgres-test-migrations/run-test-migrations.d.ts +2 -0
  28. package/dist/__tests__/postgres-test-migrations/run-test-migrations.js +22 -0
  29. package/dist/__tests__/postgres.test-database.d.ts +13 -0
  30. package/dist/__tests__/postgres.test-database.js +85 -0
  31. package/dist/__tests__/test-database.interface.d.ts +7 -0
  32. package/dist/__tests__/test-express-app.d.ts +9 -7
  33. package/dist/__tests__/test-express-app.js +38 -48
  34. package/dist/__tests__/test-objects.d.ts +23 -0
  35. package/dist/__tests__/test-objects.js +45 -0
  36. package/dist/config/base-api-config.d.ts +2 -2
  37. package/dist/config/base-api-config.js +2 -2
  38. package/dist/controllers/api.controller.d.ts +1 -5
  39. package/dist/controllers/api.controller.js +4 -11
  40. package/dist/controllers/auth.controller.d.ts +2 -2
  41. package/dist/controllers/auth.controller.js +4 -5
  42. package/dist/controllers/organizations.controller.d.ts +2 -2
  43. package/dist/controllers/organizations.controller.js +4 -4
  44. package/dist/controllers/users.controller.d.ts +2 -2
  45. package/dist/controllers/users.controller.js +2 -2
  46. package/dist/databases/index.d.ts +1 -0
  47. package/dist/databases/index.js +1 -0
  48. package/dist/databases/models/constants.d.ts +1 -0
  49. package/dist/databases/models/constants.js +1 -0
  50. package/dist/databases/models/database.d.ts +3 -0
  51. package/dist/databases/models/database.interface.d.ts +28 -0
  52. package/dist/databases/models/delete-result.d.ts +5 -0
  53. package/dist/databases/models/delete-result.js +8 -0
  54. package/dist/databases/models/index.d.ts +5 -0
  55. package/dist/databases/models/index.js +5 -0
  56. package/dist/databases/models/update-result.d.ts +5 -0
  57. package/dist/databases/models/update-result.js +8 -0
  58. package/dist/databases/mongo-db/commands/index.d.ts +8 -0
  59. package/dist/databases/mongo-db/commands/index.js +8 -0
  60. package/dist/databases/mongo-db/commands/mongo-batch-update.command.d.ts +4 -0
  61. package/dist/databases/mongo-db/commands/mongo-batch-update.command.js +41 -0
  62. package/dist/databases/mongo-db/commands/mongo-create-many.command.d.ts +5 -0
  63. package/dist/databases/mongo-db/commands/mongo-create-many.command.js +17 -0
  64. package/dist/databases/mongo-db/commands/mongo-create.command.d.ts +5 -0
  65. package/dist/databases/mongo-db/commands/mongo-create.command.js +17 -0
  66. package/dist/databases/mongo-db/commands/mongo-delete-by-id.command.d.ts +3 -0
  67. package/dist/databases/mongo-db/commands/mongo-delete-by-id.command.js +14 -0
  68. package/dist/databases/mongo-db/commands/mongo-delete-many.command.d.ts +4 -0
  69. package/dist/databases/mongo-db/commands/mongo-delete-many.command.js +9 -0
  70. package/dist/databases/mongo-db/commands/mongo-full-updateby-id.command.d.ts +3 -0
  71. package/dist/databases/mongo-db/commands/mongo-full-updateby-id.command.js +25 -0
  72. package/dist/databases/mongo-db/commands/mongo-partial-update-by-id.command.d.ts +3 -0
  73. package/dist/databases/mongo-db/commands/mongo-partial-update-by-id.command.js +25 -0
  74. package/dist/databases/mongo-db/commands/mongo-update.command.d.ts +4 -0
  75. package/dist/databases/mongo-db/commands/mongo-update.command.js +19 -0
  76. package/dist/databases/mongo-db/index.d.ts +4 -0
  77. package/dist/databases/mongo-db/index.js +4 -0
  78. package/dist/databases/mongo-db/models/no-sql-pipeline.d.ts +15 -0
  79. package/dist/databases/mongo-db/models/no-sql-pipeline.interface.d.ts +11 -0
  80. package/dist/databases/mongo-db/models/no-sql-pipeline.js +43 -0
  81. package/dist/databases/mongo-db/mongo-db.database.d.ts +32 -0
  82. package/dist/databases/mongo-db/mongo-db.database.js +65 -0
  83. package/dist/databases/mongo-db/queries/index.d.ts +6 -0
  84. package/dist/databases/mongo-db/queries/index.js +6 -0
  85. package/dist/databases/mongo-db/queries/mongo-find-one.query.d.ts +3 -0
  86. package/dist/databases/mongo-db/queries/mongo-find-one.query.js +9 -0
  87. package/dist/databases/mongo-db/queries/mongo-find.query.d.ts +3 -0
  88. package/dist/databases/mongo-db/queries/mongo-find.query.js +9 -0
  89. package/dist/databases/mongo-db/queries/mongo-get-all.query.d.ts +3 -0
  90. package/dist/databases/mongo-db/queries/mongo-get-all.query.js +17 -0
  91. package/dist/databases/mongo-db/queries/mongo-get-by-id.query.d.ts +4 -0
  92. package/dist/databases/mongo-db/queries/mongo-get-by-id.query.js +17 -0
  93. package/dist/databases/mongo-db/queries/mongo-get-count.query.d.ts +2 -0
  94. package/dist/databases/mongo-db/queries/mongo-get-count.query.js +5 -0
  95. package/dist/databases/mongo-db/queries/mongo-get.query.d.ts +4 -0
  96. package/dist/databases/mongo-db/queries/mongo-get.query.js +14 -0
  97. package/dist/databases/mongo-db/utils/build-find-options.util.d.ts +3 -0
  98. package/dist/databases/mongo-db/utils/build-find-options.util.js +15 -0
  99. package/dist/databases/mongo-db/utils/build-no-sql-match.util.d.ts +3 -0
  100. package/dist/databases/mongo-db/utils/build-no-sql-match.util.js +59 -0
  101. package/dist/databases/mongo-db/utils/convert-object-ids-to-strings.util.d.ts +1 -0
  102. package/dist/databases/mongo-db/utils/convert-object-ids-to-strings.util.js +32 -0
  103. package/dist/databases/mongo-db/utils/convert-operations-to-pipeline.util.d.ts +3 -0
  104. package/dist/databases/mongo-db/utils/convert-operations-to-pipeline.util.js +68 -0
  105. package/dist/databases/mongo-db/utils/convert-query-options-to-pipeline.util.d.ts +3 -0
  106. package/dist/databases/mongo-db/utils/convert-query-options-to-pipeline.util.js +31 -0
  107. package/dist/databases/mongo-db/utils/convert-strings-to-object-ids.util.d.ts +3 -0
  108. package/dist/databases/mongo-db/utils/convert-strings-to-object-ids.util.js +72 -0
  109. package/dist/databases/mongo-db/utils/index.d.ts +7 -0
  110. package/dist/databases/mongo-db/utils/index.js +7 -0
  111. package/dist/databases/operations/join.operation.d.ts +7 -0
  112. package/dist/databases/operations/join.operation.js +12 -0
  113. package/dist/databases/operations/operation.d.ts +2 -0
  114. package/dist/databases/postgres/commands/postgres-batch-update.command.d.ts +4 -0
  115. package/dist/databases/postgres/commands/postgres-batch-update.command.js +56 -0
  116. package/dist/databases/postgres/commands/postgres-create-many.command.d.ts +6 -0
  117. package/dist/databases/postgres/commands/postgres-create-many.command.js +63 -0
  118. package/dist/databases/postgres/commands/postgres-create.command.d.ts +6 -0
  119. package/dist/databases/postgres/commands/postgres-create.command.js +29 -0
  120. package/dist/databases/postgres/commands/postgres-delete-by-id.command.d.ts +3 -0
  121. package/dist/databases/postgres/commands/postgres-delete-by-id.command.js +6 -0
  122. package/dist/databases/postgres/commands/postgres-delete-many.command.d.ts +4 -0
  123. package/dist/databases/postgres/commands/postgres-delete-many.command.js +13 -0
  124. package/dist/databases/postgres/commands/postgres-full-update-by-id.command.d.ts +4 -0
  125. package/dist/databases/postgres/commands/postgres-full-update-by-id.command.js +72 -0
  126. package/dist/databases/postgres/commands/postgres-partial-update-by-id.command.d.ts +4 -0
  127. package/dist/databases/postgres/commands/postgres-partial-update-by-id.command.js +42 -0
  128. package/dist/databases/postgres/commands/postgres-update.command.d.ts +5 -0
  129. package/dist/databases/postgres/commands/postgres-update.command.js +48 -0
  130. package/dist/databases/postgres/migrations/001-create-migrations-table.migration.d.ts +11 -0
  131. package/dist/databases/postgres/migrations/001-create-migrations-table.migration.js +52 -0
  132. package/dist/databases/postgres/migrations/002-create-organizations-table.migration.d.ts +11 -0
  133. package/dist/databases/postgres/migrations/002-create-organizations-table.migration.js +55 -0
  134. package/dist/databases/postgres/migrations/003-create-users-table.migration.d.ts +11 -0
  135. package/dist/databases/postgres/migrations/003-create-users-table.migration.js +65 -0
  136. package/dist/databases/postgres/migrations/004-create-refresh-token-table.migration.d.ts +11 -0
  137. package/dist/databases/postgres/migrations/004-create-refresh-token-table.migration.js +57 -0
  138. package/dist/databases/postgres/migrations/index.d.ts +3 -0
  139. package/dist/databases/postgres/migrations/index.js +3 -0
  140. package/dist/databases/postgres/migrations/migration.interface.d.ts +6 -0
  141. package/dist/databases/postgres/migrations/migration.interface.js +1 -0
  142. package/dist/databases/postgres/migrations/setup-for-auth.migration.d.ts +2 -0
  143. package/dist/databases/postgres/migrations/setup-for-auth.migration.js +18 -0
  144. package/dist/databases/postgres/migrations/setup-for-multitenant.migration.d.ts +2 -0
  145. package/dist/databases/postgres/migrations/setup-for-multitenant.migration.js +16 -0
  146. package/dist/databases/postgres/postgres.database.d.ts +31 -0
  147. package/dist/databases/postgres/postgres.database.js +69 -0
  148. package/dist/databases/postgres/queries/postgres-find-one.query.d.ts +3 -0
  149. package/dist/databases/postgres/queries/postgres-find-one.query.js +13 -0
  150. package/dist/databases/postgres/queries/postgres-find.query.d.ts +3 -0
  151. package/dist/databases/postgres/queries/postgres-find.query.js +11 -0
  152. package/dist/databases/postgres/queries/postgres-get-all.query.d.ts +3 -0
  153. package/dist/databases/postgres/queries/postgres-get-all.query.js +14 -0
  154. package/dist/databases/postgres/queries/postgres-get-by-id.query.d.ts +4 -0
  155. package/dist/databases/postgres/queries/postgres-get-by-id.query.js +26 -0
  156. package/dist/databases/postgres/queries/postgres-get-count.query.d.ts +2 -0
  157. package/dist/databases/postgres/queries/postgres-get-count.query.js +4 -0
  158. package/dist/databases/postgres/queries/postgres-get.query.d.ts +4 -0
  159. package/dist/databases/postgres/queries/postgres-get.query.js +26 -0
  160. package/dist/databases/postgres/utils/build-count-query.d.ts +3 -0
  161. package/dist/databases/postgres/utils/build-count-query.js +7 -0
  162. package/dist/databases/postgres/utils/build-join-clauses.d.ts +2 -0
  163. package/dist/databases/postgres/utils/build-join-clauses.js +12 -0
  164. package/dist/databases/postgres/utils/build-order-by-clause.d.ts +2 -0
  165. package/dist/databases/postgres/utils/build-order-by-clause.js +8 -0
  166. package/dist/databases/postgres/utils/build-pagination-clause.d.ts +2 -0
  167. package/dist/databases/postgres/utils/build-pagination-clause.js +9 -0
  168. package/dist/databases/postgres/utils/build-select-clause.d.ts +3 -0
  169. package/dist/databases/postgres/utils/build-select-clause.js +28 -0
  170. package/dist/databases/postgres/utils/build-where-clause.d.ts +5 -0
  171. package/dist/databases/postgres/utils/build-where-clause.js +50 -0
  172. package/dist/databases/postgres/utils/columns-and-values-from-entity.d.ts +5 -0
  173. package/dist/databases/postgres/utils/columns-and-values-from-entity.js +9 -0
  174. package/dist/databases/postgres/utils/convert-null-to-undefined.util.d.ts +2 -0
  175. package/dist/databases/postgres/utils/convert-null-to-undefined.util.js +70 -0
  176. package/dist/databases/postgres/utils/transform-join-results.d.ts +2 -0
  177. package/dist/databases/postgres/utils/transform-join-results.js +33 -0
  178. package/dist/databases/utils/get-property-schema.util.d.ts +2 -0
  179. package/dist/databases/utils/get-property-schema.util.js +15 -0
  180. package/dist/databases/utils/index.d.ts +1 -0
  181. package/dist/databases/utils/index.js +1 -0
  182. package/dist/models/base-api-config.interface.d.ts +3 -2
  183. package/dist/models/index.d.ts +1 -1
  184. package/dist/models/index.js +1 -1
  185. package/dist/models/refresh-token.model.d.ts +18 -0
  186. package/dist/models/refresh-token.model.js +13 -0
  187. package/dist/services/auth.service.d.ts +11 -18
  188. package/dist/services/auth.service.js +29 -50
  189. package/dist/services/generic-api-service/generic-api-service.interface.d.ts +29 -0
  190. package/dist/services/generic-api-service/generic-api-service.interface.js +1 -0
  191. package/dist/services/generic-api-service/generic-api.service.d.ts +37 -0
  192. package/dist/services/generic-api-service/generic-api.service.js +178 -0
  193. package/dist/services/index.d.ts +2 -2
  194. package/dist/services/index.js +2 -2
  195. package/dist/services/multi-tenant-api.service.d.ts +9 -6
  196. package/dist/services/multi-tenant-api.service.js +10 -18
  197. package/dist/services/organization.service.d.ts +5 -5
  198. package/dist/services/organization.service.js +9 -6
  199. package/dist/services/password-reset-token.service.d.ts +3 -3
  200. package/dist/services/password-reset-token.service.js +5 -5
  201. package/dist/services/tenant-query-decorator.d.ts +1 -1
  202. package/dist/services/tenant-query-decorator.js +1 -1
  203. package/dist/services/user.service.d.ts +4 -6
  204. package/dist/services/user.service.js +4 -10
  205. package/dist/services/utils/audit-for-create.util.d.ts +2 -0
  206. package/dist/services/utils/audit-for-create.util.js +9 -0
  207. package/dist/services/utils/audit-for-update.util.d.ts +2 -0
  208. package/dist/services/utils/audit-for-update.util.js +7 -0
  209. package/dist/services/utils/strip-sender-provided-system-properties.util.d.ts +2 -0
  210. package/dist/services/utils/strip-sender-provided-system-properties.util.js +15 -0
  211. package/dist/utils/api.utils.js +2 -1
  212. package/dist/utils/index.d.ts +0 -1
  213. package/dist/utils/index.js +0 -1
  214. package/package.json +17 -6
  215. package/dist/services/generic-api-service.interface.d.ts +0 -27
  216. package/dist/services/generic-api.service.d.ts +0 -50
  217. package/dist/services/generic-api.service.js +0 -424
  218. package/dist/utils/db.utils.d.ts +0 -27
  219. package/dist/utils/db.utils.js +0 -318
  220. /package/dist/{controllers/api-controller.utils.d.ts → __tests__/test-database.interface.js} +0 -0
  221. /package/dist/{controllers/api-controller.utils.js → databases/models/database.interface.js} +0 -0
  222. /package/dist/{models/types/index.d.ts → databases/models/database.js} +0 -0
  223. /package/dist/{models/types/index.js → databases/mongo-db/models/no-sql-pipeline.interface.js} +0 -0
  224. /package/dist/{services/generic-api-service.interface.js → databases/operations/operation.js} +0 -0
@@ -1,12 +1,14 @@
1
- import { Db, UpdateResult } from 'mongodb';
2
1
  import { Request, Response } from 'express';
3
2
  import { IUserContext, IUser, ITokenResponse, ILoginResponse } from '@loomcore/common/models';
4
- import { GenericApiService } from './generic-api.service.js';
3
+ import { GenericApiService } from './generic-api-service/generic-api.service.js';
4
+ import { UpdateResult } from '../databases/models/update-result.js';
5
+ import { IRefreshToken } from '../models/refresh-token.model.js';
6
+ import { IDatabase } from '../databases/models/index.js';
5
7
  export declare class AuthService extends GenericApiService<IUser> {
6
- private refreshTokensCollection;
8
+ private refreshTokenService;
7
9
  private passwordResetTokenService;
8
10
  private emailService;
9
- constructor(db: Db);
11
+ constructor(database: IDatabase);
10
12
  attemptLogin(req: Request, res: Response, email: string, password: string): Promise<ILoginResponse | null>;
11
13
  logUserIn(userContext: IUserContext, deviceId: string): Promise<{
12
14
  tokens: {
@@ -20,25 +22,18 @@ export declare class AuthService extends GenericApiService<IUser> {
20
22
  getUserByEmail(email: string): Promise<IUser | null>;
21
23
  createUser(userContext: IUserContext, user: IUser): Promise<IUser | null>;
22
24
  requestTokenUsingRefreshToken(req: Request): Promise<ITokenResponse | null>;
23
- changeLoggedInUsersPassword(userContext: IUserContext, body: any): Promise<UpdateResult<import("bson").Document>>;
25
+ changeLoggedInUsersPassword(userContext: IUserContext, body: any): Promise<UpdateResult>;
24
26
  changePassword(userContext: IUserContext, queryObject: any, password: string): Promise<UpdateResult>;
25
27
  createNewTokens(userId: string, deviceId: string, refreshTokenExpiresOn: number): Promise<{
26
28
  accessToken: string;
27
29
  refreshToken: any;
28
30
  expiresOn: number;
29
31
  } | null>;
30
- getActiveRefreshToken(refreshToken: string, deviceId: string): Promise<import("mongodb").WithId<import("bson").Document> | null>;
31
- createNewRefreshToken(userId: string, deviceId: string, existingExpiresOn?: number | null): Promise<{
32
- token: string;
33
- deviceId: string;
34
- userId: string;
35
- expiresOn: number;
36
- created: Date;
37
- createdBy: string;
38
- } | null>;
32
+ getActiveRefreshToken(userContext: IUserContext, refreshToken: string, deviceId: string): Promise<IRefreshToken | null>;
33
+ createNewRefreshToken(userId: string, deviceId: string, existingExpiresOn?: number | null, orgId?: string): Promise<IRefreshToken | null>;
39
34
  sendResetPasswordEmail(emailAddress: string): Promise<void>;
40
35
  resetPassword(email: string, passwordResetToken: string, password: string): Promise<UpdateResult>;
41
- deleteRefreshTokensForDevice(deviceId: string): Promise<import("mongodb").DeleteResult>;
36
+ deleteRefreshTokensForDevice(deviceId: string): Promise<import("../databases/models/delete-result.js").DeleteResult>;
42
37
  generateJwt(payload: any): string;
43
38
  generateRefreshToken(): string;
44
39
  generateDeviceId(): string;
@@ -47,8 +42,6 @@ export declare class AuthService extends GenericApiService<IUser> {
47
42
  getExpiresOnFromSeconds(expiresInSeconds: number): number;
48
43
  getExpiresOnFromMinutes(expiresInMinutes: number): number;
49
44
  getExpiresOnFromDays(expiresInDays: number): number;
50
- prepareEntity(userContext: IUserContext, entity: IUser | Partial<IUser>, isCreate: boolean): Promise<IUser | Partial<IUser>>;
51
- transformList(users: IUser[]): IUser[];
52
- transformSingle(user: IUser): IUser;
45
+ preprocessEntity(userContext: IUserContext, entity: Partial<IUser>, isCreate: boolean, allowId: boolean): Promise<Partial<IUser>>;
53
46
  private updateLastLoggedIn;
54
47
  }
@@ -1,22 +1,22 @@
1
- import { ObjectId } from 'mongodb';
2
1
  import moment from 'moment';
3
2
  import crypto from 'crypto';
4
3
  import { EmptyUserContext, passwordValidator, UserSpec, getSystemUserContext } from '@loomcore/common/models';
5
4
  import { entityUtils } from '@loomcore/common/utils';
6
5
  import { BadRequestError, ServerError } from '../errors/index.js';
7
6
  import { JwtService, EmailService } from './index.js';
8
- import { GenericApiService } from './generic-api.service.js';
7
+ import { GenericApiService } from './generic-api-service/generic-api.service.js';
9
8
  import { PasswordResetTokenService } from './password-reset-token.service.js';
10
9
  import { passwordUtils } from '../utils/index.js';
11
10
  import { config } from '../config/index.js';
11
+ import { refreshTokenModelSpec } from '../models/refresh-token.model.js';
12
12
  export class AuthService extends GenericApiService {
13
- refreshTokensCollection;
13
+ refreshTokenService;
14
14
  passwordResetTokenService;
15
15
  emailService;
16
- constructor(db) {
17
- super(db, 'users', 'user', UserSpec);
18
- this.refreshTokensCollection = db.collection('refreshTokens');
19
- this.passwordResetTokenService = new PasswordResetTokenService(db);
16
+ constructor(database) {
17
+ super(database, 'users', 'user', UserSpec);
18
+ this.refreshTokenService = new GenericApiService(database, 'refreshTokens', 'refreshToken', refreshTokenModelSpec);
19
+ this.passwordResetTokenService = new PasswordResetTokenService(database);
20
20
  this.emailService = new EmailService();
21
21
  }
22
22
  async attemptLogin(req, res, email, password) {
@@ -40,7 +40,7 @@ export class AuthService extends GenericApiService {
40
40
  async logUserIn(userContext, deviceId) {
41
41
  const payload = userContext;
42
42
  const accessToken = this.generateJwt(payload);
43
- const refreshTokenObject = await this.createNewRefreshToken(userContext.user._id.toString(), deviceId);
43
+ const refreshTokenObject = await this.createNewRefreshToken(userContext.user._id, deviceId, null, userContext._orgId);
44
44
  const accessTokenExpiresOn = this.getExpiresOnFromSeconds(config.auth.jwtExpirationInSeconds);
45
45
  let loginResponse = null;
46
46
  if (refreshTokenObject) {
@@ -51,20 +51,17 @@ export class AuthService extends GenericApiService {
51
51
  };
52
52
  this.updateLastLoggedIn(userContext.user._id)
53
53
  .catch(err => console.log(`Error updating lastLoggedIn: ${err}`));
54
- userContext.user = this.transformSingle(userContext.user);
54
+ userContext.user = this.postprocessEntity(userContext, userContext.user);
55
55
  loginResponse = { tokens: tokenResponse, userContext };
56
56
  }
57
57
  return loginResponse;
58
58
  }
59
59
  async getUserById(id) {
60
- if (!entityUtils.isValidObjectId(id)) {
61
- throw new BadRequestError('id is not a valid ObjectId');
62
- }
63
- const user = await this.findOne(EmptyUserContext, { _id: new ObjectId(id) });
60
+ const user = await this.findOne(EmptyUserContext, { filters: { _id: { eq: id } } });
64
61
  return user;
65
62
  }
66
63
  async getUserByEmail(email) {
67
- const user = await this.findOne(EmptyUserContext, { email: email.toLowerCase() });
64
+ const user = await this.findOne(EmptyUserContext, { filters: { email: { eq: email.toLowerCase() } } });
68
65
  return user;
69
66
  }
70
67
  async createUser(userContext, user) {
@@ -75,9 +72,9 @@ export class AuthService extends GenericApiService {
75
72
  const refreshToken = req.query.refreshToken;
76
73
  const deviceId = this.getDeviceIdFromCookie(req);
77
74
  let tokens = null;
78
- if (refreshToken && typeof refreshToken === 'string' && deviceId) {
75
+ if (refreshToken && typeof refreshToken === 'string' && deviceId && typeof deviceId === 'string') {
79
76
  let userId = null;
80
- const activeRefreshToken = await this.getActiveRefreshToken(refreshToken, deviceId);
77
+ const activeRefreshToken = await this.getActiveRefreshToken(EmptyUserContext, refreshToken, deviceId);
81
78
  if (activeRefreshToken) {
82
79
  userId = activeRefreshToken.userId;
83
80
  if (userId) {
@@ -88,36 +85,31 @@ export class AuthService extends GenericApiService {
88
85
  return tokens;
89
86
  }
90
87
  async changeLoggedInUsersPassword(userContext, body) {
91
- const queryObject = { _id: new ObjectId(userContext.user._id) };
88
+ const queryObject = { _id: userContext.user._id };
92
89
  const result = await this.changePassword(userContext, queryObject, body.password);
93
90
  return result;
94
91
  }
95
92
  async changePassword(userContext, queryObject, password) {
96
- const hashedPassword = await passwordUtils.hashPassword(password);
97
- const updates = { password: hashedPassword, _lastPasswordChange: moment().utc().toDate() };
93
+ const updates = { password: password, _lastPasswordChange: moment().utc().toDate() };
98
94
  const updatedUsers = await super.update(userContext, queryObject, updates);
99
95
  const result = {
100
- acknowledged: true,
101
- modifiedCount: updatedUsers.length,
102
- upsertedId: null,
103
- upsertedCount: 0,
104
- matchedCount: updatedUsers.length
96
+ success: true,
97
+ count: updatedUsers.length,
105
98
  };
106
99
  return result;
107
100
  }
108
101
  async createNewTokens(userId, deviceId, refreshTokenExpiresOn) {
109
102
  let createdRefreshTokenObject = null;
110
- const newRefreshToken = await this.createNewRefreshToken(userId, deviceId, refreshTokenExpiresOn);
111
- let user = null;
103
+ const user = await this.getUserById(userId);
104
+ const newRefreshToken = await this.createNewRefreshToken(userId, deviceId, refreshTokenExpiresOn, user?._orgId);
112
105
  if (newRefreshToken) {
113
106
  createdRefreshTokenObject = newRefreshToken;
114
- user = await this.getUserById(userId);
115
107
  }
116
108
  let tokenResponse = null;
117
109
  if (user && createdRefreshTokenObject) {
118
110
  const payload = {
119
111
  user: user,
120
- _orgId: user._orgId ? String(user._orgId) : undefined
112
+ _orgId: user._orgId
121
113
  };
122
114
  const accessToken = this.generateJwt(payload);
123
115
  const accessTokenExpiresOn = this.getExpiresOnFromSeconds(config.auth.jwtExpirationInSeconds);
@@ -129,8 +121,8 @@ export class AuthService extends GenericApiService {
129
121
  }
130
122
  return tokenResponse;
131
123
  }
132
- async getActiveRefreshToken(refreshToken, deviceId) {
133
- const refreshTokenResult = await this.refreshTokensCollection.findOne({ token: refreshToken, deviceId: deviceId });
124
+ async getActiveRefreshToken(userContext, refreshToken, deviceId) {
125
+ const refreshTokenResult = await this.refreshTokenService.findOne(userContext, { filters: { token: { eq: refreshToken }, deviceId: { eq: deviceId } } });
134
126
  let activeRefreshToken = null;
135
127
  if (refreshTokenResult) {
136
128
  const now = Date.now();
@@ -141,9 +133,10 @@ export class AuthService extends GenericApiService {
141
133
  }
142
134
  return activeRefreshToken;
143
135
  }
144
- async createNewRefreshToken(userId, deviceId, existingExpiresOn = null) {
136
+ async createNewRefreshToken(userId, deviceId, existingExpiresOn = null, orgId) {
145
137
  const expiresOn = existingExpiresOn ? existingExpiresOn : this.getExpiresOnFromDays(config.auth.refreshTokenExpirationInDays);
146
138
  const newRefreshToken = {
139
+ _orgId: orgId,
147
140
  token: this.generateRefreshToken(),
148
141
  deviceId,
149
142
  userId,
@@ -152,12 +145,8 @@ export class AuthService extends GenericApiService {
152
145
  createdBy: userId
153
146
  };
154
147
  const deleteResult = await this.deleteRefreshTokensForDevice(deviceId);
155
- const insertResult = await this.refreshTokensCollection.insertOne(newRefreshToken);
156
- let tokenResult = null;
157
- if (insertResult.insertedId) {
158
- tokenResult = newRefreshToken;
159
- }
160
- return tokenResult;
148
+ const insertResult = await this.refreshTokenService.create(EmptyUserContext, newRefreshToken);
149
+ return insertResult;
161
150
  }
162
151
  async sendResetPasswordEmail(emailAddress) {
163
152
  const expiresOn = this.getExpiresOnFromMinutes(config.auth.passwordResetTokenExpirationInMinutes);
@@ -190,7 +179,7 @@ export class AuthService extends GenericApiService {
190
179
  return result;
191
180
  }
192
181
  deleteRefreshTokensForDevice(deviceId) {
193
- return this.refreshTokensCollection.deleteMany({ deviceId: deviceId });
182
+ return this.refreshTokenService.deleteMany(EmptyUserContext, { filters: { deviceId: { eq: deviceId } } });
194
183
  }
195
184
  generateJwt(payload) {
196
185
  if (payload._orgId !== undefined) {
@@ -242,7 +231,7 @@ export class AuthService extends GenericApiService {
242
231
  getExpiresOnFromDays(expiresInDays) {
243
232
  return Date.now() + expiresInDays * 24 * 60 * 60 * 1000;
244
233
  }
245
- async prepareEntity(userContext, entity, isCreate) {
234
+ async preprocessEntity(userContext, entity, isCreate, allowId) {
246
235
  if (entity.email) {
247
236
  entity.email = entity.email.toLowerCase();
248
237
  }
@@ -253,26 +242,16 @@ export class AuthService extends GenericApiService {
253
242
  if (isCreate && !entity.roles) {
254
243
  entity.roles = ["user"];
255
244
  }
256
- const preparedEntity = await super.prepareEntity(userContext, entity, isCreate);
245
+ const preparedEntity = await super.preprocessEntity(userContext, entity, isCreate, allowId);
257
246
  return preparedEntity;
258
247
  }
259
- transformList(users) {
260
- return super.transformList(users);
261
- }
262
- transformSingle(user) {
263
- return super.transformSingle(user);
264
- }
265
248
  async updateLastLoggedIn(userId) {
266
249
  try {
267
- if (!entityUtils.isValidObjectId(userId)) {
268
- throw new BadRequestError('userId is not a valid ObjectId');
269
- }
270
250
  const updates = { _lastLoggedIn: moment().utc().toDate() };
271
251
  const systemUserContext = getSystemUserContext();
272
252
  await this.partialUpdateById(systemUserContext, userId, updates);
273
253
  }
274
254
  catch (error) {
275
- console.log(`Failed to update lastLoggedIn for user ${userId}: ${error}`);
276
255
  }
277
256
  }
278
257
  }
@@ -0,0 +1,29 @@
1
+ import { ValueError } from '@sinclair/typebox/errors';
2
+ import { IUserContext, IEntity, IPagedResult, IQueryOptions } from '@loomcore/common/models';
3
+ import { DeleteResult } from '../../databases/models/delete-result.js';
4
+ import { Operation } from '../../databases/operations/operation.js';
5
+ export interface IGenericApiService<T extends IEntity> {
6
+ validate(doc: any, isPartial?: boolean): ValueError[] | null;
7
+ validateMany(docs: any[], isPartial?: boolean): ValueError[] | null;
8
+ prepareQuery(userContext: IUserContext | undefined, queryObject: IQueryOptions, operations: Operation[]): {
9
+ queryObject: IQueryOptions;
10
+ operations: Operation[];
11
+ };
12
+ preprocessEntity(userContext: IUserContext, entity: Partial<T>, isCreate: boolean, allowId: boolean): Promise<Partial<T>>;
13
+ postprocessEntity(userContext: IUserContext, entity: T): T;
14
+ getAll(userContext: IUserContext): Promise<T[]>;
15
+ get(userContext: IUserContext, queryOptions: IQueryOptions): Promise<IPagedResult<T>>;
16
+ getById(userContext: IUserContext, id: string): Promise<T>;
17
+ getCount(userContext: IUserContext): Promise<number>;
18
+ create(userContext: IUserContext, entity: Partial<T>): Promise<T | null>;
19
+ createMany(userContext: IUserContext, entities: Partial<T>[]): Promise<T[]>;
20
+ batchUpdate(userContext: IUserContext, entities: Partial<T>[]): Promise<T[]>;
21
+ fullUpdateById(userContext: IUserContext, id: string, entity: T): Promise<T>;
22
+ partialUpdateById(userContext: IUserContext, id: string, entity: Partial<T>): Promise<T>;
23
+ partialUpdateByIdWithoutPreAndPostProcessing(userContext: IUserContext, id: string, entity: T): Promise<T>;
24
+ update(userContext: IUserContext, queryObject: IQueryOptions, entity: Partial<T>): Promise<T[]>;
25
+ deleteById(userContext: IUserContext, id: string): Promise<DeleteResult>;
26
+ deleteMany(userContext: IUserContext, queryObject: IQueryOptions): Promise<DeleteResult>;
27
+ find(userContext: IUserContext, queryObject: IQueryOptions, options?: any): Promise<T[]>;
28
+ findOne(userContext: IUserContext, queryObject: IQueryOptions, options?: any): Promise<T | null>;
29
+ }
@@ -0,0 +1,37 @@
1
+ import { ValueError } from '@sinclair/typebox/errors';
2
+ import { IUserContext, IEntity, IQueryOptions, IPagedResult, IModelSpec } from '@loomcore/common/models';
3
+ import { IGenericApiService } from './generic-api-service.interface.js';
4
+ import { Operation } from '../../databases/operations/operation.js';
5
+ import { DeleteResult } from '../../databases/models/delete-result.js';
6
+ import { IDatabase } from '../../databases/models/index.js';
7
+ export declare class GenericApiService<T extends IEntity> implements IGenericApiService<T> {
8
+ protected database: IDatabase;
9
+ protected pluralResourceName: string;
10
+ protected singularResourceName: string;
11
+ protected modelSpec: IModelSpec;
12
+ constructor(database: IDatabase, pluralResourceName: string, singularResourceName: string, modelSpec: IModelSpec);
13
+ getAll(userContext: IUserContext): Promise<T[]>;
14
+ prepareQuery(userContext: IUserContext | undefined, queryObject: IQueryOptions, operations: Operation[]): {
15
+ queryObject: IQueryOptions;
16
+ operations: Operation[];
17
+ };
18
+ validate(doc: any, isPartial?: boolean): ValueError[] | null;
19
+ validateMany(docs: any[], isPartial?: boolean): ValueError[] | null;
20
+ preprocessEntity(userContext: IUserContext, entity: Partial<T>, isCreate: boolean, allowId?: boolean): Promise<Partial<T>>;
21
+ postprocessEntity(userContext: IUserContext, entity: T): T;
22
+ get(userContext: IUserContext, queryOptions?: IQueryOptions): Promise<IPagedResult<T>>;
23
+ protected prepareQueryOptions(userContext: IUserContext | undefined, queryOptions: IQueryOptions): IQueryOptions;
24
+ getById(userContext: IUserContext, id: string): Promise<T>;
25
+ getCount(userContext: IUserContext): Promise<number>;
26
+ create(userContext: IUserContext, entity: Partial<T>): Promise<T | null>;
27
+ createMany(userContext: IUserContext, entities: Partial<T>[]): Promise<T[]>;
28
+ batchUpdate(userContext: IUserContext, entities: Partial<T>[]): Promise<T[]>;
29
+ fullUpdateById(userContext: IUserContext, id: string, entity: T): Promise<T>;
30
+ partialUpdateById(userContext: IUserContext, id: string, entity: Partial<T>): Promise<T>;
31
+ partialUpdateByIdWithoutPreAndPostProcessing(userContext: IUserContext, id: string, entity: Partial<T>): Promise<T>;
32
+ update(userContext: IUserContext, queryObject: IQueryOptions, entity: Partial<T>): Promise<T[]>;
33
+ deleteById(userContext: IUserContext, id: string): Promise<DeleteResult>;
34
+ deleteMany(userContext: IUserContext, queryObject: IQueryOptions): Promise<DeleteResult>;
35
+ find(userContext: IUserContext, queryObject: IQueryOptions): Promise<T[]>;
36
+ findOne(userContext: IUserContext, queryObject: IQueryOptions): Promise<T | null>;
37
+ }
@@ -0,0 +1,178 @@
1
+ import _ from 'lodash';
2
+ import { DefaultQueryOptions } from '@loomcore/common/models';
3
+ import { entityUtils } from '@loomcore/common/utils';
4
+ import { stripSenderProvidedSystemProperties } from '../utils/strip-sender-provided-system-properties.util.js';
5
+ import { auditForCreate } from '../utils/audit-for-create.util.js';
6
+ import { auditForUpdate } from '../utils/audit-for-update.util.js';
7
+ import { IdNotFoundError, ServerError } from '../../errors/index.js';
8
+ export class GenericApiService {
9
+ database;
10
+ pluralResourceName;
11
+ singularResourceName;
12
+ modelSpec;
13
+ constructor(database, pluralResourceName, singularResourceName, modelSpec) {
14
+ this.pluralResourceName = pluralResourceName;
15
+ this.singularResourceName = singularResourceName;
16
+ this.modelSpec = modelSpec;
17
+ this.database = database;
18
+ }
19
+ async getAll(userContext) {
20
+ const { operations } = this.prepareQuery(userContext, {}, []);
21
+ const entities = await this.database.getAll(operations, this.pluralResourceName);
22
+ return entities.map(entity => this.postprocessEntity(userContext, entity));
23
+ }
24
+ prepareQuery(userContext, queryObject, operations) {
25
+ return { queryObject, operations };
26
+ }
27
+ validate(doc, isPartial = false) {
28
+ const validator = isPartial ? this.modelSpec.partialValidator : this.modelSpec.validator;
29
+ return entityUtils.validate(validator, doc);
30
+ }
31
+ validateMany(docs, isPartial = false) {
32
+ const validator = isPartial ? this.modelSpec.partialValidator : this.modelSpec.validator;
33
+ let allErrors = [];
34
+ for (const doc of docs) {
35
+ const errors = entityUtils.validate(validator, doc);
36
+ if (errors && errors.length > 0) {
37
+ allErrors.push(...errors);
38
+ }
39
+ }
40
+ return allErrors.length > 0 ? allErrors : null;
41
+ }
42
+ async preprocessEntity(userContext, entity, isCreate, allowId = true) {
43
+ let preparedEntity = _.clone(entity);
44
+ stripSenderProvidedSystemProperties(userContext, preparedEntity, allowId);
45
+ if (this.modelSpec.isAuditable) {
46
+ if (isCreate) {
47
+ auditForCreate(userContext, preparedEntity);
48
+ }
49
+ else {
50
+ auditForUpdate(userContext, preparedEntity);
51
+ }
52
+ }
53
+ if (!this.modelSpec?.fullSchema) {
54
+ throw new ServerError(`Cannot prepare entity: No model specification with schema provided for ${this.pluralResourceName}`);
55
+ }
56
+ let cleanedEntity = preparedEntity;
57
+ if (this.modelSpec) {
58
+ cleanedEntity = this.modelSpec.decode(preparedEntity);
59
+ }
60
+ preparedEntity = this.database.preprocessEntity(cleanedEntity, this.modelSpec.fullSchema);
61
+ return preparedEntity;
62
+ }
63
+ postprocessEntity(userContext, entity) {
64
+ return this.database.postprocessEntity(entity, this.modelSpec.fullSchema);
65
+ }
66
+ async get(userContext, queryOptions = { ...DefaultQueryOptions }) {
67
+ const preparedOptions = this.prepareQueryOptions(userContext, queryOptions);
68
+ const { operations } = this.prepareQuery(userContext, {}, []);
69
+ const pagedResult = await this.database.get(operations, preparedOptions, this.modelSpec, this.pluralResourceName);
70
+ const transformedEntities = (pagedResult.entities || []).map(entity => this.postprocessEntity(userContext, entity));
71
+ return {
72
+ ...pagedResult,
73
+ entities: transformedEntities
74
+ };
75
+ }
76
+ prepareQueryOptions(userContext, queryOptions) {
77
+ return queryOptions;
78
+ }
79
+ async getById(userContext, id) {
80
+ const { operations, queryObject } = this.prepareQuery(userContext, {}, []);
81
+ const entity = await this.database.getById(operations, queryObject, id, this.pluralResourceName);
82
+ if (!entity) {
83
+ throw new IdNotFoundError();
84
+ }
85
+ return this.postprocessEntity(userContext, entity);
86
+ }
87
+ async getCount(userContext) {
88
+ this.prepareQuery(userContext, {}, []);
89
+ return await this.database.getCount(this.pluralResourceName);
90
+ }
91
+ async create(userContext, entity) {
92
+ let createdEntity = null;
93
+ const preparedEntity = await this.preprocessEntity(userContext, entity, true, true);
94
+ const insertResult = await this.database.create(preparedEntity, this.pluralResourceName);
95
+ if (insertResult.insertedId) {
96
+ createdEntity = this.postprocessEntity(userContext, insertResult.entity);
97
+ }
98
+ return createdEntity;
99
+ }
100
+ async createMany(userContext, entities) {
101
+ let createdEntities = [];
102
+ if (entities.length) {
103
+ const preparedEntities = await Promise.all(entities.map(entity => this.preprocessEntity(userContext, entity, true, true)));
104
+ const insertResult = await this.database.createMany(preparedEntities, this.pluralResourceName);
105
+ if (insertResult.insertedIds) {
106
+ createdEntities = insertResult.entities.map(entity => this.postprocessEntity(userContext, entity));
107
+ }
108
+ }
109
+ return createdEntities;
110
+ }
111
+ async batchUpdate(userContext, entities) {
112
+ if (!entities || entities.length === 0) {
113
+ return [];
114
+ }
115
+ const preparedEntities = await Promise.all(entities.map(entity => this.preprocessEntity(userContext, entity, false, true)));
116
+ const { queryObject, operations } = this.prepareQuery(userContext, {}, []);
117
+ const rawUpdatedEntities = await this.database.batchUpdate(preparedEntities, operations, queryObject, this.pluralResourceName);
118
+ const updatedEntities = rawUpdatedEntities.map(entity => this.postprocessEntity(userContext, entity));
119
+ return updatedEntities;
120
+ }
121
+ async fullUpdateById(userContext, id, entity) {
122
+ const { operations, queryObject } = this.prepareQuery(userContext, {}, []);
123
+ const existingEntity = await this.database.getById(operations, queryObject, id, this.pluralResourceName);
124
+ if (!existingEntity) {
125
+ throw new IdNotFoundError();
126
+ }
127
+ const auditProperties = {
128
+ _created: existingEntity._created,
129
+ _createdBy: existingEntity._createdBy,
130
+ };
131
+ const preparedEntity = await this.preprocessEntity(userContext, entity, false, true);
132
+ Object.assign(preparedEntity, auditProperties);
133
+ const rawUpdatedEntity = await this.database.fullUpdateById(operations, id, preparedEntity, this.pluralResourceName);
134
+ const updatedEntity = this.postprocessEntity(userContext, rawUpdatedEntity);
135
+ return updatedEntity;
136
+ }
137
+ async partialUpdateById(userContext, id, entity) {
138
+ const { operations } = this.prepareQuery(userContext, {}, []);
139
+ const preparedEntity = await this.preprocessEntity(userContext, entity, false, true);
140
+ const rawUpdatedEntity = await this.database.partialUpdateById(operations, id, preparedEntity, this.pluralResourceName);
141
+ const updatedEntity = this.postprocessEntity(userContext, rawUpdatedEntity);
142
+ return updatedEntity;
143
+ }
144
+ async partialUpdateByIdWithoutPreAndPostProcessing(userContext, id, entity) {
145
+ const preparedEntity = this.database.preprocessEntity(entity, this.modelSpec.fullSchema);
146
+ const rawUpdatedEntity = await this.database.partialUpdateById([], id, preparedEntity, this.pluralResourceName);
147
+ return this.database.postprocessEntity(rawUpdatedEntity, this.modelSpec.fullSchema);
148
+ }
149
+ async update(userContext, queryObject, entity) {
150
+ const { queryObject: preparedQuery, operations } = this.prepareQuery(userContext, queryObject, []);
151
+ const preparedEntity = await this.preprocessEntity(userContext, entity, false, true);
152
+ const rawUpdatedEntities = await this.database.update(preparedQuery, preparedEntity, operations, this.pluralResourceName);
153
+ const updatedEntities = rawUpdatedEntities.map(entity => this.postprocessEntity(userContext, entity));
154
+ return updatedEntities;
155
+ }
156
+ async deleteById(userContext, id) {
157
+ const deleteResult = await this.database.deleteById(id, this.pluralResourceName);
158
+ if (deleteResult.count <= 0) {
159
+ throw new IdNotFoundError();
160
+ }
161
+ return deleteResult;
162
+ }
163
+ async deleteMany(userContext, queryObject) {
164
+ const { queryObject: preparedQuery, operations } = this.prepareQuery(userContext, queryObject, []);
165
+ const deleteResult = await this.database.deleteMany(preparedQuery, this.pluralResourceName);
166
+ return deleteResult;
167
+ }
168
+ async find(userContext, queryObject) {
169
+ const { queryObject: preparedQuery, operations } = this.prepareQuery(userContext, queryObject, []);
170
+ const rawEntities = await this.database.find(preparedQuery, this.pluralResourceName);
171
+ return rawEntities.map(entity => this.postprocessEntity(userContext, entity));
172
+ }
173
+ async findOne(userContext, queryObject) {
174
+ const { queryObject: preparedQuery, operations } = this.prepareQuery(userContext, queryObject, []);
175
+ const rawEntity = await this.database.findOne(preparedQuery, this.pluralResourceName);
176
+ return rawEntity ? this.postprocessEntity(userContext, rawEntity) : null;
177
+ }
178
+ }
@@ -1,7 +1,7 @@
1
1
  export * from './auth.service.js';
2
2
  export * from './email.service.js';
3
- export * from './generic-api.service.js';
4
- export * from './generic-api-service.interface.js';
3
+ export * from './generic-api-service/generic-api.service.js';
4
+ export * from './generic-api-service/generic-api-service.interface.js';
5
5
  export * from './jwt.service.js';
6
6
  export * from './multi-tenant-api.service.js';
7
7
  export * from './organization.service.js';
@@ -1,7 +1,7 @@
1
1
  export * from './auth.service.js';
2
2
  export * from './email.service.js';
3
- export * from './generic-api.service.js';
4
- export * from './generic-api-service.interface.js';
3
+ export * from './generic-api-service/generic-api.service.js';
4
+ export * from './generic-api-service/generic-api-service.interface.js';
5
5
  export * from './jwt.service.js';
6
6
  export * from './multi-tenant-api.service.js';
7
7
  export * from './organization.service.js';
@@ -1,10 +1,13 @@
1
- import { Db } from 'mongodb';
2
1
  import { IUserContext, IEntity, IQueryOptions, IModelSpec } from '@loomcore/common/models';
3
- import { GenericApiService } from './generic-api.service.js';
2
+ import { Operation } from '../databases/operations/operation.js';
3
+ import { GenericApiService } from './generic-api-service/generic-api.service.js';
4
+ import { IDatabase } from '../databases/models/index.js';
4
5
  export declare class MultiTenantApiService<T extends IEntity> extends GenericApiService<T> {
5
6
  private tenantDecorator?;
6
- constructor(db: Db, pluralResourceName: string, singularResourceName: string, modelSpec?: IModelSpec);
7
- protected prepareQuery(userContext: IUserContext, query: any): any;
8
- protected prepareQueryOptions(userContext: IUserContext, queryOptions: IQueryOptions): IQueryOptions;
9
- protected prepareEntity(userContext: IUserContext, entity: T, isCreate: boolean, allowId?: boolean): Promise<T | Partial<T>>;
7
+ constructor(database: IDatabase, pluralResourceName: string, singularResourceName: string, modelSpec: IModelSpec);
8
+ prepareQuery(userContext: IUserContext, queryOptions: IQueryOptions, operations: Operation[]): {
9
+ queryObject: IQueryOptions;
10
+ operations: Operation[];
11
+ };
12
+ preprocessEntity(userContext: IUserContext, entity: Partial<T>, isCreate: boolean, allowId?: boolean): Promise<Partial<T>>;
10
13
  }
@@ -1,41 +1,33 @@
1
- import { GenericApiService } from './generic-api.service.js';
2
1
  import { TenantQueryDecorator } from './tenant-query-decorator.js';
3
2
  import { BadRequestError } from '../errors/bad-request.error.js';
4
3
  import { config } from '../config/base-api-config.js';
4
+ import { GenericApiService } from './generic-api-service/generic-api.service.js';
5
5
  export class MultiTenantApiService extends GenericApiService {
6
6
  tenantDecorator;
7
- constructor(db, pluralResourceName, singularResourceName, modelSpec) {
8
- super(db, pluralResourceName, singularResourceName, modelSpec);
7
+ constructor(database, pluralResourceName, singularResourceName, modelSpec) {
8
+ super(database, pluralResourceName, singularResourceName, modelSpec);
9
9
  if (config?.app?.isMultiTenant) {
10
10
  this.tenantDecorator = new TenantQueryDecorator();
11
11
  }
12
12
  }
13
- prepareQuery(userContext, query) {
13
+ prepareQuery(userContext, queryOptions, operations) {
14
14
  if (!config?.app?.isMultiTenant) {
15
- return super.prepareQuery(userContext, query);
15
+ return super.prepareQuery(userContext, queryOptions, operations);
16
16
  }
17
17
  if (!userContext || !userContext._orgId) {
18
18
  throw new BadRequestError('A valid userContext was not provided to MultiTenantApiService.prepareQuery');
19
19
  }
20
- return this.tenantDecorator.applyTenantToQuery(userContext, query, this.pluralResourceName);
20
+ const queryObject = this.tenantDecorator.applyTenantToQuery(userContext, queryOptions, this.pluralResourceName);
21
+ return { queryObject, operations };
21
22
  }
22
- prepareQueryOptions(userContext, queryOptions) {
23
+ async preprocessEntity(userContext, entity, isCreate, allowId = false) {
23
24
  if (!config?.app?.isMultiTenant) {
24
- return super.prepareQueryOptions(userContext, queryOptions);
25
- }
26
- if (!userContext || !userContext._orgId) {
27
- throw new BadRequestError('A valid userContext was not provided to MultiTenantApiService.prepareQueryOptions');
28
- }
29
- return this.tenantDecorator.applyTenantToQueryOptions(userContext, queryOptions, this.pluralResourceName);
30
- }
31
- async prepareEntity(userContext, entity, isCreate, allowId = false) {
32
- if (!config?.app?.isMultiTenant) {
33
- return super.prepareEntity(userContext, entity, isCreate, allowId);
25
+ return super.preprocessEntity(userContext, entity, isCreate, allowId);
34
26
  }
35
27
  if (!userContext || !userContext._orgId) {
36
28
  throw new BadRequestError('A valid userContext was not provided to MultiTenantApiService.prepareEntity');
37
29
  }
38
- const preparedEntity = await super.prepareEntity(userContext, entity, isCreate, allowId);
30
+ const preparedEntity = await super.preprocessEntity(userContext, entity, isCreate, allowId);
39
31
  const orgIdField = this.tenantDecorator.getOrgIdField();
40
32
  preparedEntity[orgIdField] = userContext._orgId;
41
33
  return preparedEntity;
@@ -1,9 +1,9 @@
1
- import { Db } from 'mongodb';
2
- import { GenericApiService } from './generic-api.service.js';
1
+ import { GenericApiService } from './generic-api-service/generic-api.service.js';
3
2
  import { IOrganization, IUserContext } from '@loomcore/common/models';
3
+ import { IDatabase } from '../databases/models/database.interface.js';
4
4
  export declare class OrganizationService extends GenericApiService<IOrganization> {
5
- constructor(db: Db);
6
- getAuthTokenByRepoCode(userContext: IUserContext, orgId: string): Promise<string | null | undefined>;
5
+ constructor(database: IDatabase);
6
+ getAuthTokenByRepoCode(userContext: IUserContext, orgId: string): Promise<string | null>;
7
7
  validateRepoAuthToken(userContext: IUserContext, orgCode: string, authToken: string): Promise<string | null>;
8
- getMetaOrg(userContext: IUserContext): Promise<IOrganization>;
8
+ getMetaOrg(userContext: IUserContext): Promise<IOrganization | null>;
9
9
  }