@trailmix-cms/cms 0.4.4 → 0.7.1

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 (266) hide show
  1. package/dist/auth.guard.d.ts +5 -13
  2. package/dist/auth.guard.d.ts.map +1 -1
  3. package/dist/auth.guard.js +23 -91
  4. package/dist/auth.guard.js.map +1 -1
  5. package/dist/collections/account.collection.d.ts +5 -3
  6. package/dist/collections/account.collection.d.ts.map +1 -1
  7. package/dist/collections/account.collection.js +15 -8
  8. package/dist/collections/account.collection.js.map +1 -1
  9. package/dist/collections/api-key.collection.d.ts +54 -0
  10. package/dist/collections/api-key.collection.d.ts.map +1 -0
  11. package/dist/collections/api-key.collection.js +142 -0
  12. package/dist/collections/api-key.collection.js.map +1 -0
  13. package/dist/collections/index.d.ts +4 -2
  14. package/dist/collections/index.d.ts.map +1 -1
  15. package/dist/collections/index.js +9 -5
  16. package/dist/collections/index.js.map +1 -1
  17. package/dist/collections/organization.collection.d.ts +20 -0
  18. package/dist/collections/organization.collection.d.ts.map +1 -0
  19. package/dist/collections/{file.collection.js → organization.collection.js} +17 -17
  20. package/dist/collections/organization.collection.js.map +1 -0
  21. package/dist/collections/role.collection.d.ts +32 -0
  22. package/dist/collections/role.collection.d.ts.map +1 -0
  23. package/dist/collections/role.collection.js +90 -0
  24. package/dist/collections/role.collection.js.map +1 -0
  25. package/dist/collections/security-audit.collection.d.ts +30 -0
  26. package/dist/collections/security-audit.collection.d.ts.map +1 -0
  27. package/dist/collections/security-audit.collection.js +79 -0
  28. package/dist/collections/security-audit.collection.js.map +1 -0
  29. package/dist/constants/cms-collection-names.d.ts +4 -2
  30. package/dist/constants/cms-collection-names.d.ts.map +1 -1
  31. package/dist/constants/cms-collection-names.js +4 -2
  32. package/dist/constants/cms-collection-names.js.map +1 -1
  33. package/dist/constants/provider-symbols.d.ts +10 -12
  34. package/dist/constants/provider-symbols.d.ts.map +1 -1
  35. package/dist/constants/provider-symbols.js +10 -12
  36. package/dist/constants/provider-symbols.js.map +1 -1
  37. package/dist/controllers/account.controller.d.ts +11 -15
  38. package/dist/controllers/account.controller.d.ts.map +1 -1
  39. package/dist/controllers/account.controller.js +69 -13
  40. package/dist/controllers/account.controller.js.map +1 -1
  41. package/dist/controllers/api-keys.controller.d.ts +13 -0
  42. package/dist/controllers/api-keys.controller.d.ts.map +1 -0
  43. package/dist/controllers/api-keys.controller.js +125 -0
  44. package/dist/controllers/api-keys.controller.js.map +1 -0
  45. package/dist/controllers/audit.controller.d.ts.map +1 -1
  46. package/dist/controllers/audit.controller.js +3 -3
  47. package/dist/controllers/audit.controller.js.map +1 -1
  48. package/dist/controllers/audits.controller.d.ts +10 -0
  49. package/dist/controllers/audits.controller.d.ts.map +1 -0
  50. package/dist/controllers/audits.controller.js +107 -0
  51. package/dist/controllers/audits.controller.js.map +1 -0
  52. package/dist/controllers/global-roles.controller.d.ts +16 -0
  53. package/dist/controllers/global-roles.controller.d.ts.map +1 -0
  54. package/dist/controllers/global-roles.controller.js +137 -0
  55. package/dist/controllers/global-roles.controller.js.map +1 -0
  56. package/dist/controllers/index.d.ts +6 -1
  57. package/dist/controllers/index.d.ts.map +1 -1
  58. package/dist/controllers/index.js +6 -1
  59. package/dist/controllers/index.js.map +1 -1
  60. package/dist/controllers/organization-roles.controller.d.ts +16 -0
  61. package/dist/controllers/organization-roles.controller.d.ts.map +1 -0
  62. package/dist/controllers/organization-roles.controller.js +145 -0
  63. package/dist/controllers/organization-roles.controller.js.map +1 -0
  64. package/dist/controllers/organizations.controller.d.ts +65 -0
  65. package/dist/controllers/organizations.controller.d.ts.map +1 -0
  66. package/dist/controllers/organizations.controller.js +140 -0
  67. package/dist/controllers/organizations.controller.js.map +1 -0
  68. package/dist/controllers/security-audits.controller.d.ts +11 -0
  69. package/dist/controllers/security-audits.controller.d.ts.map +1 -0
  70. package/dist/controllers/security-audits.controller.js +130 -0
  71. package/dist/controllers/security-audits.controller.js.map +1 -0
  72. package/dist/decorators/account.decorator.d.ts +1 -3
  73. package/dist/decorators/account.decorator.d.ts.map +1 -1
  74. package/dist/decorators/account.decorator.js +3 -10
  75. package/dist/decorators/account.decorator.js.map +1 -1
  76. package/dist/decorators/audit-context.decorator.d.ts +6 -0
  77. package/dist/decorators/audit-context.decorator.d.ts.map +1 -1
  78. package/dist/decorators/audit-context.decorator.js +12 -3
  79. package/dist/decorators/audit-context.decorator.js.map +1 -1
  80. package/dist/decorators/auth.decorator.d.ts +5 -3
  81. package/dist/decorators/auth.decorator.d.ts.map +1 -1
  82. package/dist/decorators/auth.decorator.js +38 -3
  83. package/dist/decorators/auth.decorator.js.map +1 -1
  84. package/dist/decorators/index.d.ts +4 -0
  85. package/dist/decorators/index.d.ts.map +1 -0
  86. package/dist/decorators/index.js +20 -0
  87. package/dist/decorators/index.js.map +1 -0
  88. package/dist/dto/account.dto.d.ts +33 -0
  89. package/dist/dto/account.dto.d.ts.map +1 -0
  90. package/dist/dto/account.dto.js +14 -0
  91. package/dist/dto/account.dto.js.map +1 -0
  92. package/dist/dto/api-key.dto.d.ts +89 -0
  93. package/dist/dto/api-key.dto.d.ts.map +1 -0
  94. package/dist/dto/api-key.dto.js +27 -0
  95. package/dist/dto/api-key.dto.js.map +1 -0
  96. package/dist/dto/audit.dto.d.ts +11 -5
  97. package/dist/dto/audit.dto.d.ts.map +1 -1
  98. package/dist/dto/audit.dto.js +1 -1
  99. package/dist/dto/audit.dto.js.map +1 -1
  100. package/dist/dto/global-role.dto.d.ts +99 -0
  101. package/dist/dto/global-role.dto.d.ts.map +1 -0
  102. package/dist/dto/global-role.dto.js +26 -0
  103. package/dist/dto/global-role.dto.js.map +1 -0
  104. package/dist/dto/organization-role.dto.d.ts +107 -0
  105. package/dist/dto/organization-role.dto.d.ts.map +1 -0
  106. package/dist/dto/organization-role.dto.js +26 -0
  107. package/dist/dto/organization-role.dto.js.map +1 -0
  108. package/dist/dto/organization.dto.d.ts +57 -0
  109. package/dist/dto/organization.dto.d.ts.map +1 -0
  110. package/dist/dto/organization.dto.js +32 -0
  111. package/dist/dto/organization.dto.js.map +1 -0
  112. package/dist/dto/security-audit.dto.d.ts +95 -0
  113. package/dist/dto/security-audit.dto.d.ts.map +1 -0
  114. package/dist/dto/security-audit.dto.js +26 -0
  115. package/dist/dto/security-audit.dto.js.map +1 -0
  116. package/dist/index.d.ts +7 -2
  117. package/dist/index.d.ts.map +1 -1
  118. package/dist/index.js +8 -3
  119. package/dist/index.js.map +1 -1
  120. package/dist/managers/global-role.manager.d.ts +42 -0
  121. package/dist/managers/global-role.manager.d.ts.map +1 -0
  122. package/dist/managers/global-role.manager.js +117 -0
  123. package/dist/managers/global-role.manager.js.map +1 -0
  124. package/dist/managers/index.d.ts +4 -0
  125. package/dist/managers/index.d.ts.map +1 -0
  126. package/dist/managers/index.js +20 -0
  127. package/dist/managers/index.js.map +1 -0
  128. package/dist/managers/organization-role.manager.d.ts +47 -0
  129. package/dist/managers/organization-role.manager.d.ts.map +1 -0
  130. package/dist/managers/organization-role.manager.js +218 -0
  131. package/dist/managers/organization-role.manager.js.map +1 -0
  132. package/dist/managers/organization.manager.d.ts +39 -0
  133. package/dist/managers/organization.manager.d.ts.map +1 -0
  134. package/dist/managers/organization.manager.js +196 -0
  135. package/dist/managers/organization.manager.js.map +1 -0
  136. package/dist/module.d.ts +92 -0
  137. package/dist/module.d.ts.map +1 -0
  138. package/dist/module.js +137 -0
  139. package/dist/module.js.map +1 -0
  140. package/dist/pipes/api-key.pipe.d.ts +8 -0
  141. package/dist/pipes/api-key.pipe.d.ts.map +1 -0
  142. package/dist/pipes/api-key.pipe.js +28 -0
  143. package/dist/pipes/api-key.pipe.js.map +1 -0
  144. package/dist/pipes/organization.pipe.d.ts +8 -0
  145. package/dist/pipes/organization.pipe.d.ts.map +1 -0
  146. package/dist/pipes/organization.pipe.js +28 -0
  147. package/dist/pipes/organization.pipe.js.map +1 -0
  148. package/dist/pipes/role.pipe.d.ts +8 -0
  149. package/dist/pipes/{file.pipe.d.ts.map → role.pipe.d.ts.map} +1 -1
  150. package/dist/pipes/{file.pipe.js → role.pipe.js} +8 -8
  151. package/dist/pipes/{file.pipe.js.map → role.pipe.js.map} +1 -1
  152. package/dist/services/account.service.d.ts +0 -2
  153. package/dist/services/account.service.d.ts.map +1 -1
  154. package/dist/services/account.service.js +1 -37
  155. package/dist/services/account.service.js.map +1 -1
  156. package/dist/services/api-key.service.d.ts +42 -0
  157. package/dist/services/api-key.service.d.ts.map +1 -0
  158. package/dist/services/api-key.service.js +306 -0
  159. package/dist/services/api-key.service.js.map +1 -0
  160. package/dist/services/auth.service.d.ts +40 -0
  161. package/dist/services/auth.service.d.ts.map +1 -0
  162. package/dist/services/auth.service.js +227 -0
  163. package/dist/services/auth.service.js.map +1 -0
  164. package/dist/services/authorization.service.d.ts +44 -9
  165. package/dist/services/authorization.service.d.ts.map +1 -1
  166. package/dist/services/authorization.service.js +107 -41
  167. package/dist/services/authorization.service.js.map +1 -1
  168. package/dist/services/feature.service.d.ts +23 -0
  169. package/dist/services/feature.service.d.ts.map +1 -0
  170. package/dist/services/feature.service.js +49 -0
  171. package/dist/services/feature.service.js.map +1 -0
  172. package/dist/services/global-role.service.d.ts +17 -0
  173. package/dist/services/global-role.service.d.ts.map +1 -0
  174. package/dist/services/global-role.service.js +99 -0
  175. package/dist/services/global-role.service.js.map +1 -0
  176. package/dist/services/index.d.ts +9 -0
  177. package/dist/services/index.d.ts.map +1 -0
  178. package/dist/services/index.js +25 -0
  179. package/dist/services/index.js.map +1 -0
  180. package/dist/services/organization-role.service.d.ts +33 -0
  181. package/dist/services/organization-role.service.d.ts.map +1 -0
  182. package/dist/services/organization-role.service.js +102 -0
  183. package/dist/services/organization-role.service.js.map +1 -0
  184. package/dist/services/organization.service.d.ts +29 -0
  185. package/dist/services/organization.service.d.ts.map +1 -0
  186. package/dist/services/organization.service.js +95 -0
  187. package/dist/services/organization.service.js.map +1 -0
  188. package/dist/types/feature-config.d.ts +9 -0
  189. package/dist/types/feature-config.d.ts.map +1 -0
  190. package/dist/types/feature-config.js +3 -0
  191. package/dist/types/feature-config.js.map +1 -0
  192. package/dist/types/hooks/auth-guard-hook.d.ts.map +1 -0
  193. package/dist/types/hooks/auth-guard-hook.js.map +1 -0
  194. package/dist/types/hooks/index.d.ts +3 -0
  195. package/dist/types/hooks/index.d.ts.map +1 -0
  196. package/dist/types/hooks/index.js +19 -0
  197. package/dist/types/hooks/index.js.map +1 -0
  198. package/dist/types/hooks/organization-delete-hook.d.ts +20 -0
  199. package/dist/types/hooks/organization-delete-hook.d.ts.map +1 -0
  200. package/dist/types/hooks/organization-delete-hook.js +3 -0
  201. package/dist/types/hooks/organization-delete-hook.js.map +1 -0
  202. package/dist/types/index.d.ts +5 -0
  203. package/dist/types/index.d.ts.map +1 -0
  204. package/dist/types/index.js +21 -0
  205. package/dist/types/index.js.map +1 -0
  206. package/dist/types/request-principal.d.ts +9 -0
  207. package/dist/types/request-principal.d.ts.map +1 -0
  208. package/dist/types/request-principal.js +3 -0
  209. package/dist/types/request-principal.js.map +1 -0
  210. package/dist/utils/provider-helpers.d.ts +6 -1
  211. package/dist/utils/provider-helpers.d.ts.map +1 -1
  212. package/dist/utils/provider-helpers.js +11 -1
  213. package/dist/utils/provider-helpers.js.map +1 -1
  214. package/package.json +52 -17
  215. package/test/unit/collections/api-key.collection.spec.ts +416 -0
  216. package/test/unit/managers/global-role.manager.spec.ts +269 -0
  217. package/test/unit/managers/organization-role.manager.spec.ts +632 -0
  218. package/test/unit/managers/organization.manager.spec.ts +395 -0
  219. package/test/unit/module.spec.ts +596 -0
  220. package/test/unit/services/account.service.spec.ts +90 -0
  221. package/test/unit/services/api-key.service.spec.ts +1244 -0
  222. package/test/unit/services/auth.service.spec.ts +790 -0
  223. package/test/unit/services/authorization.service.spec.ts +636 -0
  224. package/test/unit/services/feature.service.spec.ts +56 -0
  225. package/test/unit/services/global-role.service.spec.ts +289 -0
  226. package/test/unit/services/organization-role.service.spec.ts +300 -0
  227. package/test/unit/services/organization.service.spec.ts +385 -0
  228. package/test/utils/auth-guard.ts +114 -0
  229. package/test/utils/base.ts +16 -0
  230. package/test/utils/entities/account.ts +13 -0
  231. package/test/utils/entities/api-key.ts +15 -0
  232. package/test/utils/entities/audit.ts +18 -0
  233. package/test/utils/entities/index.ts +6 -0
  234. package/test/utils/entities/mapping.ts +20 -0
  235. package/test/utils/entities/organization.ts +13 -0
  236. package/test/utils/entities/role.ts +21 -0
  237. package/test/utils/entities/security-audit.ts +16 -0
  238. package/test/utils/index.ts +4 -0
  239. package/test/utils/models/audit-context.ts +10 -0
  240. package/test/utils/models/authorization.ts +7 -0
  241. package/test/utils/models/global-role.ts +22 -0
  242. package/test/utils/models/index.ts +5 -0
  243. package/test/utils/models/organization-role.ts +23 -0
  244. package/test/utils/models/publishable.ts +7 -0
  245. package/tsconfig.build.json +36 -0
  246. package/tsconfig.build.tsbuildinfo +1 -0
  247. package/dist/auth-guard-hook.d.ts.map +0 -1
  248. package/dist/auth-guard-hook.js.map +0 -1
  249. package/dist/cms.module.d.ts +0 -8
  250. package/dist/cms.module.d.ts.map +0 -1
  251. package/dist/cms.module.js +0 -44
  252. package/dist/cms.module.js.map +0 -1
  253. package/dist/cms.providers.d.ts +0 -120
  254. package/dist/cms.providers.d.ts.map +0 -1
  255. package/dist/cms.providers.js +0 -126
  256. package/dist/cms.providers.js.map +0 -1
  257. package/dist/collections/file.collection.d.ts +0 -21
  258. package/dist/collections/file.collection.d.ts.map +0 -1
  259. package/dist/collections/file.collection.js.map +0 -1
  260. package/dist/collections/text.collection.d.ts +0 -20
  261. package/dist/collections/text.collection.d.ts.map +0 -1
  262. package/dist/collections/text.collection.js +0 -56
  263. package/dist/collections/text.collection.js.map +0 -1
  264. package/dist/pipes/file.pipe.d.ts +0 -8
  265. /package/dist/{auth-guard-hook.d.ts → types/hooks/auth-guard-hook.d.ts} +0 -0
  266. /package/dist/{auth-guard-hook.js → types/hooks/auth-guard-hook.js} +0 -0
@@ -0,0 +1,306 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __metadata = (this && this.__metadata) || function (k, v) {
42
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
43
+ };
44
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
45
+ return function (target, key) { decorator(target, key, paramIndex); }
46
+ };
47
+ var ApiKeyService_1;
48
+ Object.defineProperty(exports, "__esModule", { value: true });
49
+ exports.ApiKeyService = void 0;
50
+ const common_1 = require("@nestjs/common");
51
+ const trailmixModels = __importStar(require("@trailmix-cms/models"));
52
+ const collections_1 = require("../collections");
53
+ const authorization_service_1 = require("./authorization.service");
54
+ const feature_service_1 = require("./feature.service");
55
+ let ApiKeyService = ApiKeyService_1 = class ApiKeyService {
56
+ apiKeyCollection;
57
+ securityAuditCollection;
58
+ featureService;
59
+ authorizationService;
60
+ organizationCollection;
61
+ logger = new common_1.Logger(ApiKeyService_1.name);
62
+ constructor(apiKeyCollection, securityAuditCollection, featureService, authorizationService, organizationCollection) {
63
+ this.apiKeyCollection = apiKeyCollection;
64
+ this.securityAuditCollection = securityAuditCollection;
65
+ this.featureService = featureService;
66
+ this.authorizationService = authorizationService;
67
+ this.organizationCollection = organizationCollection;
68
+ }
69
+ /**
70
+ * Create a new API key with scope validation and authorization checks
71
+ */
72
+ async createApiKey(params, principal, auditContext) {
73
+ this.logger.log(`Creating API key with scope ${params.scope_type} for principal ${principal.entity._id}`);
74
+ // Check if scopes are configured and validate the requested scope
75
+ const allowedScopes = this.featureService.getApiKeyScopes();
76
+ if (!allowedScopes.includes(params.scope_type)) {
77
+ await this.securityAuditCollection.insertOne({
78
+ event_type: trailmixModels.SecurityAuditEventType.UnauthorizedAccess,
79
+ principal_id: principal.entity._id,
80
+ principal_type: principal.principal_type,
81
+ message: `Unauthorized attempt to create API key with scope ${params.scope_type} which is not in the allowed scopes`,
82
+ source: ApiKeyService_1.name,
83
+ });
84
+ throw new common_1.BadRequestException(`Scope type ${params.scope_type} is not allowed. Allowed scopes: ${allowedScopes.join(', ')}`);
85
+ }
86
+ const isGlobalAdmin = await this.authorizationService.isGlobalAdmin(principal.entity._id, principal.principal_type);
87
+ switch (params.scope_type) {
88
+ case trailmixModels.ApiKeyScope.Global: {
89
+ // Global-scoped: principal must be a global admin
90
+ if (!isGlobalAdmin) {
91
+ await this.securityAuditCollection.insertOne({
92
+ event_type: trailmixModels.SecurityAuditEventType.UnauthorizedAccess,
93
+ principal_id: principal.entity._id,
94
+ principal_type: principal.principal_type,
95
+ message: 'Unauthorized attempt to create global-scoped API key',
96
+ source: ApiKeyService_1.name,
97
+ });
98
+ throw new common_1.BadRequestException('Invalid scope type');
99
+ }
100
+ if (params.scope_id) {
101
+ throw new common_1.BadRequestException('Scope ID is not allowed for global-scoped API keys');
102
+ }
103
+ const apiKey = await this.apiKeyCollection.create(params, auditContext);
104
+ this.logger.log(`Successfully created API key ${apiKey._id} with scope ${params.scope_type}`);
105
+ return apiKey;
106
+ }
107
+ case trailmixModels.ApiKeyScope.Account: {
108
+ // Account-scoped: principal must be the account owner
109
+ if (!params.scope_id) {
110
+ throw new common_1.BadRequestException('Scope ID is required for account-scoped API keys');
111
+ }
112
+ if (isGlobalAdmin) {
113
+ const apiKey = await this.apiKeyCollection.create(params, auditContext);
114
+ this.logger.log(`Successfully created API key ${apiKey._id} with scope ${params.scope_type}`);
115
+ return apiKey;
116
+ }
117
+ if (principal.principal_type !== trailmixModels.Principal.Account) {
118
+ throw new common_1.BadRequestException('Only accounts can create account-scoped API keys');
119
+ }
120
+ if (!principal.entity._id.equals(params.scope_id)) {
121
+ await this.securityAuditCollection.insertOne({
122
+ event_type: trailmixModels.SecurityAuditEventType.UnauthorizedAccess,
123
+ principal_id: principal.entity._id,
124
+ principal_type: principal.principal_type,
125
+ message: 'Unauthorized attempt to create account-scoped API key for another principal',
126
+ source: ApiKeyService_1.name,
127
+ });
128
+ throw new common_1.BadRequestException('Scope ID must match principal ID for account-scoped API keys');
129
+ }
130
+ const apiKey = await this.apiKeyCollection.create(params, auditContext);
131
+ this.logger.log(`Successfully created API key ${apiKey._id} with scope ${params.scope_type}`);
132
+ return apiKey;
133
+ }
134
+ case trailmixModels.ApiKeyScope.Organization: {
135
+ // Organization-scoped: principal must have admin/owner role on the organization
136
+ if (!this.featureService.isOrganizationsEnabled()) {
137
+ this.logger.warn('Organizations feature must be enabled to create organization-scoped API keys');
138
+ throw new common_1.BadRequestException();
139
+ }
140
+ if (!this.organizationCollection) {
141
+ this.logger.error('Organization collections and services are not available despite organizations feature being enabled');
142
+ throw new common_1.InternalServerErrorException();
143
+ }
144
+ if (!params.scope_id) {
145
+ throw new common_1.BadRequestException('Scope ID is required for organization-scoped API keys');
146
+ }
147
+ if (isGlobalAdmin) {
148
+ const apiKey = await this.apiKeyCollection.create(params, auditContext);
149
+ this.logger.log(`Successfully created API key ${apiKey._id} with scope ${params.scope_type}`);
150
+ return apiKey;
151
+ }
152
+ const requiredRoles = [trailmixModels.RoleValue.Admin, trailmixModels.RoleValue.Owner];
153
+ // Check if user has admin or owner role on the organization
154
+ const accessResult = await this.authorizationService.resolveOrganizationAuthorization({
155
+ principal,
156
+ rolesAllowList: requiredRoles,
157
+ principalTypeAllowList: [trailmixModels.Principal.Account],
158
+ organizationId: params.scope_id,
159
+ });
160
+ if (!accessResult.hasAccess) {
161
+ await this.securityAuditCollection.insertOne({
162
+ event_type: trailmixModels.SecurityAuditEventType.UnauthorizedAccess,
163
+ principal_id: principal.entity._id,
164
+ principal_type: principal.principal_type,
165
+ message: `Unauthorized attempt to create organization-scoped API key for organization ${params.scope_id}`,
166
+ source: ApiKeyService_1.name,
167
+ });
168
+ // If the principal has at least reader organization role, throw a forbidden exception since they have access to the organization
169
+ if (accessResult.organizationRoles.some(role => [
170
+ trailmixModels.RoleValue.Owner,
171
+ trailmixModels.RoleValue.Admin,
172
+ trailmixModels.RoleValue.User,
173
+ trailmixModels.RoleValue.Reader,
174
+ ].includes(role.role))) {
175
+ throw new common_1.ForbiddenException(`Insufficient permissions to create API keys for organization ${params.scope_id}. You must have at lesat one of ${requiredRoles} role on the organization.`);
176
+ }
177
+ throw new common_1.BadRequestException(`Organization ${params.scope_id} does not exist `);
178
+ }
179
+ const apiKey = await this.apiKeyCollection.create(params, auditContext);
180
+ this.logger.log(`Successfully created API key ${apiKey._id} with scope ${params.scope_type}`);
181
+ return apiKey;
182
+ }
183
+ default: {
184
+ throw new common_1.InternalServerErrorException('Invalid scope type');
185
+ }
186
+ }
187
+ }
188
+ /**
189
+ * Get API keys with filtering based on principal permissions
190
+ */
191
+ async getApiKeys(principal, queryParams) {
192
+ this.logger.log(`Getting API keys for principal ${principal.entity._id}`);
193
+ const isGlobalAdmin = await this.authorizationService.isGlobalAdmin(principal.entity._id, principal.principal_type);
194
+ if (isGlobalAdmin) {
195
+ const filter = {
196
+ ...(queryParams.name ? { name: queryParams.name } : {}),
197
+ ...(queryParams.disabled ? { disabled: queryParams.disabled } : {}),
198
+ ...(queryParams.scope_type ? { "scope.type": queryParams.scope_type } : {}),
199
+ ...(queryParams.scope_id ? { "scope.id": queryParams.scope_id } : {}),
200
+ };
201
+ const apiKeys = await this.apiKeyCollection.find(filter);
202
+ return {
203
+ items: apiKeys,
204
+ count: apiKeys.length,
205
+ };
206
+ }
207
+ // Non global admins
208
+ if (!queryParams.scope_type) {
209
+ throw new common_1.BadRequestException('Scope type is required');
210
+ }
211
+ // Global-scoped API keys are not supported for non-global admins
212
+ if (queryParams.scope_type?.includes(trailmixModels.ApiKeyScope.Global)) {
213
+ await this.securityAuditCollection.insertOne({
214
+ event_type: trailmixModels.SecurityAuditEventType.UnauthorizedAccess,
215
+ principal_id: principal.entity._id,
216
+ principal_type: principal.principal_type,
217
+ message: 'Unauthorized attempt to get global-scoped API keys for non-global admins',
218
+ source: ApiKeyService_1.name,
219
+ });
220
+ throw new common_1.BadRequestException('Global-scoped API keys are not supported for non-global admins');
221
+ }
222
+ switch (queryParams.scope_type) {
223
+ case trailmixModels.ApiKeyScope.Account: {
224
+ // Account-scoped API keys
225
+ const filter = {
226
+ ...(queryParams.name ? { name: queryParams.name } : {}),
227
+ ...(queryParams.disabled ? { disabled: queryParams.disabled } : {}),
228
+ "scope.type": trailmixModels.ApiKeyScope.Account,
229
+ "scope.id": principal.entity._id,
230
+ };
231
+ const apiKeys = await this.apiKeyCollection.find(filter);
232
+ return {
233
+ items: apiKeys,
234
+ count: apiKeys.length,
235
+ };
236
+ }
237
+ case trailmixModels.ApiKeyScope.Organization: {
238
+ // Organization-scoped API keys
239
+ if (!this.featureService.isOrganizationsEnabled()) {
240
+ throw new common_1.BadRequestException('Organizations feature must be enabled to query organization-scoped API keys');
241
+ }
242
+ if (!queryParams.scope_id) {
243
+ throw new common_1.BadRequestException('Scope ID is required for organization-scoped API keys');
244
+ }
245
+ const organization_id = queryParams.scope_id;
246
+ const requiredRoles = [trailmixModels.RoleValue.Admin, trailmixModels.RoleValue.Owner];
247
+ // Check if user has admin or owner role on the organization
248
+ const accessResult = await this.authorizationService.resolveOrganizationAuthorization({
249
+ principal,
250
+ rolesAllowList: requiredRoles,
251
+ principalTypeAllowList: [trailmixModels.Principal.Account],
252
+ organizationId: organization_id,
253
+ });
254
+ if (!accessResult.hasAccess) {
255
+ throw new common_1.ForbiddenException(`Insufficient permissions to create API keys for organization ${organization_id}. You must have at lesat one of ${requiredRoles} role on the organization.`);
256
+ }
257
+ const filter = {
258
+ ...(queryParams.name ? { name: queryParams.name } : {}),
259
+ ...(queryParams.disabled ? { disabled: queryParams.disabled } : {}),
260
+ "scope.type": trailmixModels.ApiKeyScope.Organization,
261
+ "scope.id": organization_id,
262
+ };
263
+ const apiKeys = await this.apiKeyCollection.find(filter);
264
+ return {
265
+ items: apiKeys,
266
+ count: apiKeys.length,
267
+ };
268
+ }
269
+ default: {
270
+ throw new common_1.InternalServerErrorException('Invalid scope type');
271
+ }
272
+ }
273
+ }
274
+ /**
275
+ * Get a single API key by entity, checking authorization
276
+ */
277
+ async getApiKey(apiKey, principal) {
278
+ const hasAccess = await this.authorizationService.authorizeApiKeyAccessForPrincipal(principal, apiKey.scope_type, apiKey.scope_id);
279
+ if (!hasAccess) {
280
+ throw new common_1.NotFoundException('API key not found');
281
+ }
282
+ return apiKey;
283
+ }
284
+ /**
285
+ * Delete an API key, checking authorization first
286
+ */
287
+ async deleteApiKey(apiKey, principal, auditContext) {
288
+ const hasAccess = await this.authorizationService.authorizeApiKeyAccessForPrincipal(principal, apiKey.scope_type, apiKey.scope_id);
289
+ if (!hasAccess) {
290
+ throw new common_1.NotFoundException('API key not found');
291
+ }
292
+ await this.apiKeyCollection.deleteOne(apiKey._id, auditContext);
293
+ this.logger.log(`Successfully deleted API key ${apiKey._id}`);
294
+ }
295
+ };
296
+ exports.ApiKeyService = ApiKeyService;
297
+ exports.ApiKeyService = ApiKeyService = ApiKeyService_1 = __decorate([
298
+ (0, common_1.Injectable)(),
299
+ __param(4, (0, common_1.Optional)()),
300
+ __param(4, (0, common_1.Inject)(collections_1.OrganizationCollection)),
301
+ __metadata("design:paramtypes", [collections_1.ApiKeyCollection,
302
+ collections_1.SecurityAuditCollection,
303
+ feature_service_1.FeatureService,
304
+ authorization_service_1.AuthorizationService, Object])
305
+ ], ApiKeyService);
306
+ //# sourceMappingURL=api-key.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-key.service.js","sourceRoot":"","sources":["../../src/services/api-key.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { ExecutionContext } from '@nestjs/common';
2
+ import * as trailmixModels from '@trailmix-cms/models';
3
+ import { ApiKeyCollection, SecurityAuditCollection } from '../collections';
4
+ import { AccountService } from './account.service';
5
+ import { GlobalRoleService } from './global-role.service';
6
+ import { type AuthGuardHook, type RequestPrincipal } from '../types';
7
+ export declare const AuthResult: {
8
+ readonly IsValid: "isValid";
9
+ readonly Unauthorized: "unauthorized";
10
+ readonly Forbidden: "forbidden";
11
+ };
12
+ export type AuthResult = typeof AuthResult[keyof typeof AuthResult];
13
+ export declare class AuthService {
14
+ private accountService;
15
+ private globalRoleService;
16
+ private securityAuditCollection;
17
+ private authGuardHook?;
18
+ private apiKeyCollection?;
19
+ private readonly logger;
20
+ constructor(accountService: AccountService, globalRoleService: GlobalRoleService, securityAuditCollection: SecurityAuditCollection, authGuardHook?: AuthGuardHook | undefined, apiKeyCollection?: ApiKeyCollection | undefined);
21
+ /**
22
+ * Validate authentication and authorization for a request
23
+ * @param principal The principal from the request (null if not authenticated)
24
+ * @param allowAnonymous Whether anonymous access is allowed
25
+ * @param requiredPrincipalTypes Required principal types
26
+ * @param requiredGlobalRoles Required global roles
27
+ * @param requestUrl The request URL for audit logging
28
+ * @returns AuthResult
29
+ */
30
+ validateAuth(principal: RequestPrincipal | null, allowAnonymous: boolean, requiredPrincipalTypes: trailmixModels.Principal[], requiredGlobalRoles: (trailmixModels.RoleValue | string)[], requestUrl: string): Promise<AuthResult>;
31
+ /**
32
+ * Get the principal from the request context
33
+ * @param context The execution context
34
+ * @returns The principal or null if not found
35
+ */
36
+ getPrincipal(context: ExecutionContext): Promise<RequestPrincipal | null>;
37
+ private getAccount;
38
+ private getApiKey;
39
+ }
40
+ //# sourceMappingURL=auth.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.service.d.ts","sourceRoot":"","sources":["../../src/services/auth.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGtH,OAAO,KAAK,cAAc,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAErE,eAAO,MAAM,UAAU;;;;CAIb,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC;AAEpE,qBACa,WAAW;IAIhB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,iBAAiB;IACzB,OAAO,CAAC,uBAAuB;IACuB,OAAO,CAAC,aAAa,CAAC;IAChE,OAAO,CAAC,gBAAgB,CAAC;IAPzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;gBAG3C,cAAc,EAAE,cAAc,EAC9B,iBAAiB,EAAE,iBAAiB,EACpC,uBAAuB,EAAE,uBAAuB,EACM,aAAa,CAAC,EAAE,aAAa,YAAA,EACvE,gBAAgB,CAAC,EAAE,gBAAgB,YAAA;IAG3D;;;;;;;;OAQG;IACG,YAAY,CACd,SAAS,EAAE,gBAAgB,GAAG,IAAI,EAClC,cAAc,EAAE,OAAO,EACvB,sBAAsB,EAAE,cAAc,CAAC,SAAS,EAAE,EAClD,mBAAmB,EAAE,CAAC,cAAc,CAAC,SAAS,GAAG,MAAM,CAAC,EAAE,EAC1D,UAAU,EAAE,MAAM,GACnB,OAAO,CAAC,UAAU,CAAC;IAwEtB;;;;OAIG;IACG,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAqBjE,UAAU;YA+CV,SAAS;CAqB1B"}
@@ -0,0 +1,227 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __metadata = (this && this.__metadata) || function (k, v) {
42
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
43
+ };
44
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
45
+ return function (target, key) { decorator(target, key, paramIndex); }
46
+ };
47
+ var AuthService_1;
48
+ Object.defineProperty(exports, "__esModule", { value: true });
49
+ exports.AuthService = exports.AuthResult = void 0;
50
+ const common_1 = require("@nestjs/common");
51
+ const fastify_1 = require("@clerk/fastify");
52
+ const trailmixModels = __importStar(require("@trailmix-cms/models"));
53
+ const collections_1 = require("../collections");
54
+ const account_service_1 = require("./account.service");
55
+ const global_role_service_1 = require("./global-role.service");
56
+ const constants_1 = require("../constants");
57
+ exports.AuthResult = {
58
+ IsValid: 'isValid',
59
+ Unauthorized: 'unauthorized',
60
+ Forbidden: 'forbidden',
61
+ };
62
+ let AuthService = AuthService_1 = class AuthService {
63
+ accountService;
64
+ globalRoleService;
65
+ securityAuditCollection;
66
+ authGuardHook;
67
+ apiKeyCollection;
68
+ logger = new common_1.Logger(AuthService_1.name);
69
+ constructor(accountService, globalRoleService, securityAuditCollection, authGuardHook, apiKeyCollection) {
70
+ this.accountService = accountService;
71
+ this.globalRoleService = globalRoleService;
72
+ this.securityAuditCollection = securityAuditCollection;
73
+ this.authGuardHook = authGuardHook;
74
+ this.apiKeyCollection = apiKeyCollection;
75
+ }
76
+ /**
77
+ * Validate authentication and authorization for a request
78
+ * @param principal The principal from the request (null if not authenticated)
79
+ * @param allowAnonymous Whether anonymous access is allowed
80
+ * @param requiredPrincipalTypes Required principal types
81
+ * @param requiredGlobalRoles Required global roles
82
+ * @param requestUrl The request URL for audit logging
83
+ * @returns AuthResult
84
+ */
85
+ async validateAuth(principal, allowAnonymous, requiredPrincipalTypes, requiredGlobalRoles, requestUrl) {
86
+ if (!principal) {
87
+ if (allowAnonymous) {
88
+ return exports.AuthResult.IsValid;
89
+ }
90
+ return exports.AuthResult.Unauthorized;
91
+ }
92
+ if (allowAnonymous) {
93
+ return exports.AuthResult.IsValid;
94
+ }
95
+ // Check if principal type is required, if no required principal types, allow any principal type
96
+ if (requiredPrincipalTypes.length > 0 && !requiredPrincipalTypes.includes(principal.principal_type)) {
97
+ await this.securityAuditCollection.insertOne({
98
+ event_type: trailmixModels.SecurityAuditEventType.UnauthorizedAccess,
99
+ principal_id: principal.entity._id,
100
+ principal_type: principal.principal_type,
101
+ message: `Unauthorized access to ${requestUrl}, required principal type not found: ${requiredPrincipalTypes.join(', ')}`,
102
+ source: AuthService_1.name,
103
+ });
104
+ return exports.AuthResult.Forbidden;
105
+ }
106
+ // If no roles are required, allow any authenticated principal
107
+ if (requiredGlobalRoles.length == 0) {
108
+ return exports.AuthResult.IsValid;
109
+ }
110
+ const globalRoleAssignments = await this.globalRoleService.find({
111
+ principal_id: principal.entity._id,
112
+ principal_type: principal.principal_type,
113
+ });
114
+ if (!globalRoleAssignments) {
115
+ await this.securityAuditCollection.insertOne({
116
+ event_type: trailmixModels.SecurityAuditEventType.UnauthorizedAccess,
117
+ principal_id: principal.entity._id,
118
+ principal_type: principal.principal_type,
119
+ message: `Unauthorized access to ${requestUrl}, no global role assignments found`,
120
+ source: AuthService_1.name,
121
+ });
122
+ return exports.AuthResult.Forbidden;
123
+ }
124
+ // Check if user has required role or is global admin
125
+ const hasRole = requiredGlobalRoles.some((role) => globalRoleAssignments.some((assignment) => assignment.role === role)) ||
126
+ globalRoleAssignments.some((assignment) => assignment.role === trailmixModels.RoleValue.Admin);
127
+ if (!hasRole) {
128
+ await this.securityAuditCollection.insertOne({
129
+ event_type: trailmixModels.SecurityAuditEventType.UnauthorizedAccess,
130
+ principal_id: principal.entity._id,
131
+ principal_type: principal.principal_type,
132
+ message: `Unauthorized access to ${requestUrl}, required role not found: ${requiredGlobalRoles.join(', ')}`,
133
+ source: AuthService_1.name,
134
+ });
135
+ return exports.AuthResult.Forbidden;
136
+ }
137
+ return exports.AuthResult.IsValid;
138
+ }
139
+ /**
140
+ * Get the principal from the request context
141
+ * @param context The execution context
142
+ * @returns The principal or null if not found
143
+ */
144
+ async getPrincipal(context) {
145
+ const apiKey = await this.getApiKey(context);
146
+ if (apiKey) {
147
+ return {
148
+ entity: apiKey,
149
+ principal_type: trailmixModels.Principal.ApiKey,
150
+ };
151
+ }
152
+ const account = await this.getAccount(context);
153
+ if (!account) {
154
+ return null;
155
+ }
156
+ return {
157
+ entity: account,
158
+ principal_type: trailmixModels.Principal.Account,
159
+ };
160
+ }
161
+ async getAccount(context) {
162
+ const request = context.switchToHttp().getRequest();
163
+ const auth = (0, fastify_1.getAuth)(request);
164
+ if (!auth.userId) {
165
+ return null;
166
+ }
167
+ // TODO: Cache user
168
+ // const cachedUser = await this.userCache.getUser(auth.userId);
169
+ // if (cachedUser) {
170
+ // return {
171
+ // account: cachedUser.account,
172
+ // userPublicMetadata: cachedUser.metadata,
173
+ // };
174
+ // }
175
+ const existingAccount = await this.accountService.getAccount(auth.userId);
176
+ if (existingAccount) {
177
+ return existingAccount;
178
+ }
179
+ const account = await this.accountService.upsertAccount(auth.userId);
180
+ // TODO: Lock this step to prevent race conditions
181
+ this.logger.log(`Validating account using auth guard hook: ${auth.userId}`);
182
+ this.logger.log(`Auth guard hook: ${this.authGuardHook}`);
183
+ if (this.authGuardHook) {
184
+ const authGuardHookresult = await this.authGuardHook.onHook(account);
185
+ if (!authGuardHookresult) {
186
+ this.logger.error('Failed to validate account using auth guard hook', {
187
+ userId: auth.userId,
188
+ accountId: account?._id,
189
+ });
190
+ throw new Error('Failed to validate account using auth guard hook');
191
+ }
192
+ }
193
+ // TODO: Cache user
194
+ // await this.userCache.cacheUser(auth.userId, {
195
+ // account: account!,
196
+ // metadata: user.publicMetadata,
197
+ // });
198
+ return account;
199
+ }
200
+ async getApiKey(context) {
201
+ if (!this.apiKeyCollection) {
202
+ return null;
203
+ }
204
+ const request = context.switchToHttp().getRequest();
205
+ const apiKey = request.headers[trailmixModels.API_KEY_HEADER];
206
+ if (!apiKey) {
207
+ return null;
208
+ }
209
+ // TODO: Cache api key
210
+ const apiKeyEntity = await this.apiKeyCollection.findOne({ api_key: apiKey });
211
+ if (!apiKeyEntity || apiKeyEntity.disabled) {
212
+ return null;
213
+ }
214
+ return apiKeyEntity;
215
+ }
216
+ };
217
+ exports.AuthService = AuthService;
218
+ exports.AuthService = AuthService = AuthService_1 = __decorate([
219
+ (0, common_1.Injectable)(),
220
+ __param(3, (0, common_1.Optional)()),
221
+ __param(3, (0, common_1.Inject)(constants_1.PROVIDER_SYMBOLS.AUTH_GUARD_HOOK)),
222
+ __param(4, (0, common_1.Optional)()),
223
+ __metadata("design:paramtypes", [account_service_1.AccountService,
224
+ global_role_service_1.GlobalRoleService,
225
+ collections_1.SecurityAuditCollection, Object, collections_1.ApiKeyCollection])
226
+ ], AuthService);
227
+ //# sourceMappingURL=auth.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.service.js","sourceRoot":"","sources":["../../src/services/auth.service.ts"],"names":[],"mappings":"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"}