@trailmix-cms/cms 0.4.3 → 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.
- package/dist/auth.guard.d.ts +5 -13
- package/dist/auth.guard.d.ts.map +1 -1
- package/dist/auth.guard.js +23 -91
- package/dist/auth.guard.js.map +1 -1
- package/dist/collections/account.collection.d.ts +5 -3
- package/dist/collections/account.collection.d.ts.map +1 -1
- package/dist/collections/account.collection.js +15 -8
- package/dist/collections/account.collection.js.map +1 -1
- package/dist/collections/api-key.collection.d.ts +54 -0
- package/dist/collections/api-key.collection.d.ts.map +1 -0
- package/dist/collections/api-key.collection.js +142 -0
- package/dist/collections/api-key.collection.js.map +1 -0
- package/dist/collections/index.d.ts +4 -2
- package/dist/collections/index.d.ts.map +1 -1
- package/dist/collections/index.js +9 -5
- package/dist/collections/index.js.map +1 -1
- package/dist/collections/organization.collection.d.ts +20 -0
- package/dist/collections/organization.collection.d.ts.map +1 -0
- package/dist/collections/{file.collection.js → organization.collection.js} +17 -17
- package/dist/collections/organization.collection.js.map +1 -0
- package/dist/collections/role.collection.d.ts +32 -0
- package/dist/collections/role.collection.d.ts.map +1 -0
- package/dist/collections/role.collection.js +90 -0
- package/dist/collections/role.collection.js.map +1 -0
- package/dist/collections/security-audit.collection.d.ts +30 -0
- package/dist/collections/security-audit.collection.d.ts.map +1 -0
- package/dist/collections/security-audit.collection.js +79 -0
- package/dist/collections/security-audit.collection.js.map +1 -0
- package/dist/constants/cms-collection-names.d.ts +4 -2
- package/dist/constants/cms-collection-names.d.ts.map +1 -1
- package/dist/constants/cms-collection-names.js +4 -2
- package/dist/constants/cms-collection-names.js.map +1 -1
- package/dist/constants/provider-symbols.d.ts +10 -12
- package/dist/constants/provider-symbols.d.ts.map +1 -1
- package/dist/constants/provider-symbols.js +10 -12
- package/dist/constants/provider-symbols.js.map +1 -1
- package/dist/controllers/account.controller.d.ts +11 -15
- package/dist/controllers/account.controller.d.ts.map +1 -1
- package/dist/controllers/account.controller.js +69 -13
- package/dist/controllers/account.controller.js.map +1 -1
- package/dist/controllers/api-keys.controller.d.ts +13 -0
- package/dist/controllers/api-keys.controller.d.ts.map +1 -0
- package/dist/controllers/api-keys.controller.js +125 -0
- package/dist/controllers/api-keys.controller.js.map +1 -0
- package/dist/controllers/audit.controller.d.ts.map +1 -1
- package/dist/controllers/audit.controller.js +3 -3
- package/dist/controllers/audit.controller.js.map +1 -1
- package/dist/controllers/audits.controller.d.ts +10 -0
- package/dist/controllers/audits.controller.d.ts.map +1 -0
- package/dist/controllers/audits.controller.js +107 -0
- package/dist/controllers/audits.controller.js.map +1 -0
- package/dist/controllers/global-roles.controller.d.ts +16 -0
- package/dist/controllers/global-roles.controller.d.ts.map +1 -0
- package/dist/controllers/global-roles.controller.js +137 -0
- package/dist/controllers/global-roles.controller.js.map +1 -0
- package/dist/controllers/index.d.ts +6 -1
- package/dist/controllers/index.d.ts.map +1 -1
- package/dist/controllers/index.js +6 -1
- package/dist/controllers/index.js.map +1 -1
- package/dist/controllers/organization-roles.controller.d.ts +16 -0
- package/dist/controllers/organization-roles.controller.d.ts.map +1 -0
- package/dist/controllers/organization-roles.controller.js +145 -0
- package/dist/controllers/organization-roles.controller.js.map +1 -0
- package/dist/controllers/organizations.controller.d.ts +65 -0
- package/dist/controllers/organizations.controller.d.ts.map +1 -0
- package/dist/controllers/organizations.controller.js +140 -0
- package/dist/controllers/organizations.controller.js.map +1 -0
- package/dist/controllers/security-audits.controller.d.ts +11 -0
- package/dist/controllers/security-audits.controller.d.ts.map +1 -0
- package/dist/controllers/security-audits.controller.js +130 -0
- package/dist/controllers/security-audits.controller.js.map +1 -0
- package/dist/decorators/account.decorator.d.ts +1 -3
- package/dist/decorators/account.decorator.d.ts.map +1 -1
- package/dist/decorators/account.decorator.js +3 -10
- package/dist/decorators/account.decorator.js.map +1 -1
- package/dist/decorators/audit-context.decorator.d.ts +6 -0
- package/dist/decorators/audit-context.decorator.d.ts.map +1 -1
- package/dist/decorators/audit-context.decorator.js +12 -3
- package/dist/decorators/audit-context.decorator.js.map +1 -1
- package/dist/decorators/auth.decorator.d.ts +5 -3
- package/dist/decorators/auth.decorator.d.ts.map +1 -1
- package/dist/decorators/auth.decorator.js +38 -3
- package/dist/decorators/auth.decorator.js.map +1 -1
- package/dist/decorators/index.d.ts +4 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +20 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/dto/account.dto.d.ts +33 -0
- package/dist/dto/account.dto.d.ts.map +1 -0
- package/dist/dto/account.dto.js +14 -0
- package/dist/dto/account.dto.js.map +1 -0
- package/dist/dto/api-key.dto.d.ts +89 -0
- package/dist/dto/api-key.dto.d.ts.map +1 -0
- package/dist/dto/api-key.dto.js +27 -0
- package/dist/dto/api-key.dto.js.map +1 -0
- package/dist/dto/audit.dto.d.ts +11 -5
- package/dist/dto/audit.dto.d.ts.map +1 -1
- package/dist/dto/audit.dto.js +1 -1
- package/dist/dto/audit.dto.js.map +1 -1
- package/dist/dto/global-role.dto.d.ts +99 -0
- package/dist/dto/global-role.dto.d.ts.map +1 -0
- package/dist/dto/global-role.dto.js +26 -0
- package/dist/dto/global-role.dto.js.map +1 -0
- package/dist/dto/organization-role.dto.d.ts +107 -0
- package/dist/dto/organization-role.dto.d.ts.map +1 -0
- package/dist/dto/organization-role.dto.js +26 -0
- package/dist/dto/organization-role.dto.js.map +1 -0
- package/dist/dto/organization.dto.d.ts +57 -0
- package/dist/dto/organization.dto.d.ts.map +1 -0
- package/dist/dto/organization.dto.js +32 -0
- package/dist/dto/organization.dto.js.map +1 -0
- package/dist/dto/security-audit.dto.d.ts +95 -0
- package/dist/dto/security-audit.dto.d.ts.map +1 -0
- package/dist/dto/security-audit.dto.js +26 -0
- package/dist/dto/security-audit.dto.js.map +1 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/managers/global-role.manager.d.ts +42 -0
- package/dist/managers/global-role.manager.d.ts.map +1 -0
- package/dist/managers/global-role.manager.js +117 -0
- package/dist/managers/global-role.manager.js.map +1 -0
- package/dist/managers/index.d.ts +4 -0
- package/dist/managers/index.d.ts.map +1 -0
- package/dist/managers/index.js +20 -0
- package/dist/managers/index.js.map +1 -0
- package/dist/managers/organization-role.manager.d.ts +47 -0
- package/dist/managers/organization-role.manager.d.ts.map +1 -0
- package/dist/managers/organization-role.manager.js +218 -0
- package/dist/managers/organization-role.manager.js.map +1 -0
- package/dist/managers/organization.manager.d.ts +39 -0
- package/dist/managers/organization.manager.d.ts.map +1 -0
- package/dist/managers/organization.manager.js +196 -0
- package/dist/managers/organization.manager.js.map +1 -0
- package/dist/module.d.ts +92 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +137 -0
- package/dist/module.js.map +1 -0
- package/dist/pipes/api-key.pipe.d.ts +8 -0
- package/dist/pipes/api-key.pipe.d.ts.map +1 -0
- package/dist/pipes/api-key.pipe.js +28 -0
- package/dist/pipes/api-key.pipe.js.map +1 -0
- package/dist/pipes/organization.pipe.d.ts +8 -0
- package/dist/pipes/organization.pipe.d.ts.map +1 -0
- package/dist/pipes/organization.pipe.js +28 -0
- package/dist/pipes/organization.pipe.js.map +1 -0
- package/dist/pipes/role.pipe.d.ts +8 -0
- package/dist/pipes/{file.pipe.d.ts.map → role.pipe.d.ts.map} +1 -1
- package/dist/pipes/{file.pipe.js → role.pipe.js} +8 -8
- package/dist/pipes/{file.pipe.js.map → role.pipe.js.map} +1 -1
- package/dist/services/account.service.d.ts +0 -2
- package/dist/services/account.service.d.ts.map +1 -1
- package/dist/services/account.service.js +1 -37
- package/dist/services/account.service.js.map +1 -1
- package/dist/services/api-key.service.d.ts +42 -0
- package/dist/services/api-key.service.d.ts.map +1 -0
- package/dist/services/api-key.service.js +306 -0
- package/dist/services/api-key.service.js.map +1 -0
- package/dist/services/auth.service.d.ts +40 -0
- package/dist/services/auth.service.d.ts.map +1 -0
- package/dist/services/auth.service.js +227 -0
- package/dist/services/auth.service.js.map +1 -0
- package/dist/services/authorization.service.d.ts +44 -9
- package/dist/services/authorization.service.d.ts.map +1 -1
- package/dist/services/authorization.service.js +107 -41
- package/dist/services/authorization.service.js.map +1 -1
- package/dist/services/feature.service.d.ts +23 -0
- package/dist/services/feature.service.d.ts.map +1 -0
- package/dist/services/feature.service.js +49 -0
- package/dist/services/feature.service.js.map +1 -0
- package/dist/services/global-role.service.d.ts +17 -0
- package/dist/services/global-role.service.d.ts.map +1 -0
- package/dist/services/global-role.service.js +99 -0
- package/dist/services/global-role.service.js.map +1 -0
- package/dist/services/index.d.ts +9 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +25 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/organization-role.service.d.ts +33 -0
- package/dist/services/organization-role.service.d.ts.map +1 -0
- package/dist/services/organization-role.service.js +102 -0
- package/dist/services/organization-role.service.js.map +1 -0
- package/dist/services/organization.service.d.ts +29 -0
- package/dist/services/organization.service.d.ts.map +1 -0
- package/dist/services/organization.service.js +95 -0
- package/dist/services/organization.service.js.map +1 -0
- package/dist/types/feature-config.d.ts +9 -0
- package/dist/types/feature-config.d.ts.map +1 -0
- package/dist/types/feature-config.js +3 -0
- package/dist/types/feature-config.js.map +1 -0
- package/dist/types/hooks/auth-guard-hook.d.ts.map +1 -0
- package/dist/types/hooks/auth-guard-hook.js.map +1 -0
- package/dist/types/hooks/index.d.ts +3 -0
- package/dist/types/hooks/index.d.ts.map +1 -0
- package/dist/types/hooks/index.js +19 -0
- package/dist/types/hooks/index.js.map +1 -0
- package/dist/types/hooks/organization-delete-hook.d.ts +20 -0
- package/dist/types/hooks/organization-delete-hook.d.ts.map +1 -0
- package/dist/types/hooks/organization-delete-hook.js +3 -0
- package/dist/types/hooks/organization-delete-hook.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +21 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/request-principal.d.ts +9 -0
- package/dist/types/request-principal.d.ts.map +1 -0
- package/dist/types/request-principal.js +3 -0
- package/dist/types/request-principal.js.map +1 -0
- package/dist/utils/provider-helpers.d.ts +6 -1
- package/dist/utils/provider-helpers.d.ts.map +1 -1
- package/dist/utils/provider-helpers.js +11 -1
- package/dist/utils/provider-helpers.js.map +1 -1
- package/package.json +59 -17
- package/test/unit/collections/api-key.collection.spec.ts +416 -0
- package/test/unit/managers/global-role.manager.spec.ts +269 -0
- package/test/unit/managers/organization-role.manager.spec.ts +632 -0
- package/test/unit/managers/organization.manager.spec.ts +395 -0
- package/test/unit/module.spec.ts +596 -0
- package/test/unit/services/account.service.spec.ts +90 -0
- package/test/unit/services/api-key.service.spec.ts +1244 -0
- package/test/unit/services/auth.service.spec.ts +790 -0
- package/test/unit/services/authorization.service.spec.ts +636 -0
- package/test/unit/services/feature.service.spec.ts +56 -0
- package/test/unit/services/global-role.service.spec.ts +289 -0
- package/test/unit/services/organization-role.service.spec.ts +300 -0
- package/test/unit/services/organization.service.spec.ts +385 -0
- package/test/utils/auth-guard.ts +114 -0
- package/test/utils/base.ts +16 -0
- package/test/utils/entities/account.ts +13 -0
- package/test/utils/entities/api-key.ts +15 -0
- package/test/utils/entities/audit.ts +18 -0
- package/test/utils/entities/index.ts +6 -0
- package/test/utils/entities/mapping.ts +20 -0
- package/test/utils/entities/organization.ts +13 -0
- package/test/utils/entities/role.ts +21 -0
- package/test/utils/entities/security-audit.ts +16 -0
- package/test/utils/index.ts +4 -0
- package/test/utils/models/audit-context.ts +10 -0
- package/test/utils/models/authorization.ts +7 -0
- package/test/utils/models/global-role.ts +22 -0
- package/test/utils/models/index.ts +5 -0
- package/test/utils/models/organization-role.ts +23 -0
- package/test/utils/models/publishable.ts +7 -0
- package/tsconfig.build.json +36 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/dist/auth-guard-hook.d.ts.map +0 -1
- package/dist/auth-guard-hook.js.map +0 -1
- package/dist/cms.module.d.ts +0 -8
- package/dist/cms.module.d.ts.map +0 -1
- package/dist/cms.module.js +0 -44
- package/dist/cms.module.js.map +0 -1
- package/dist/cms.providers.d.ts +0 -120
- package/dist/cms.providers.d.ts.map +0 -1
- package/dist/cms.providers.js +0 -126
- package/dist/cms.providers.js.map +0 -1
- package/dist/collections/file.collection.d.ts +0 -21
- package/dist/collections/file.collection.d.ts.map +0 -1
- package/dist/collections/file.collection.js.map +0 -1
- package/dist/collections/text.collection.d.ts +0 -20
- package/dist/collections/text.collection.d.ts.map +0 -1
- package/dist/collections/text.collection.js +0 -56
- package/dist/collections/text.collection.js.map +0 -1
- package/dist/pipes/file.pipe.d.ts +0 -8
- /package/dist/{auth-guard-hook.d.ts → types/hooks/auth-guard-hook.d.ts} +0 -0
- /package/dist/{auth-guard-hook.js → types/hooks/auth-guard-hook.js} +0 -0
package/dist/auth.guard.d.ts
CHANGED
|
@@ -1,24 +1,16 @@
|
|
|
1
1
|
import { Reflector } from '@nestjs/core';
|
|
2
2
|
import { CanActivate, ExecutionContext } from '@nestjs/common';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { AppConfig } from './config';
|
|
6
|
-
import { AccountService } from './services/account.service';
|
|
7
|
-
import { AuthGuardHook } from './auth-guard-hook';
|
|
3
|
+
import { AuthService } from './services/auth.service';
|
|
4
|
+
import { type RequestPrincipal } from './types';
|
|
8
5
|
declare module 'fastify' {
|
|
9
6
|
interface FastifyRequest {
|
|
10
|
-
|
|
7
|
+
principal: RequestPrincipal;
|
|
11
8
|
}
|
|
12
9
|
}
|
|
13
10
|
export declare class AuthGuard implements CanActivate {
|
|
14
11
|
private reflector;
|
|
15
|
-
private
|
|
16
|
-
|
|
17
|
-
private authGuardHook?;
|
|
18
|
-
private readonly logger;
|
|
19
|
-
private readonly clerkClient;
|
|
20
|
-
constructor(reflector: Reflector, accountService: AccountService, configService: ConfigService<AppConfig>, authGuardHook?: AuthGuardHook | undefined);
|
|
12
|
+
private authService;
|
|
13
|
+
constructor(reflector: Reflector, authService: AuthService);
|
|
21
14
|
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
22
|
-
private getAccount;
|
|
23
15
|
}
|
|
24
16
|
//# sourceMappingURL=auth.guard.d.ts.map
|
package/dist/auth.guard.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.guard.d.ts","sourceRoot":"","sources":["../src/auth.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAc,WAAW,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"auth.guard.d.ts","sourceRoot":"","sources":["../src/auth.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAc,WAAW,EAAE,gBAAgB,EAA2E,MAAM,gBAAgB,CAAC;AAIpJ,OAAO,EAAc,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,OAAO,QAAQ,SAAS,CAAC;IACrB,UAAU,cAAc;QACpB,SAAS,EAAE,gBAAgB,CAAA;KAC9B;CACJ;AAED,qBACa,SAAU,YAAW,WAAW;IAErC,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,WAAW;gBADX,SAAS,EAAE,SAAS,EACpB,WAAW,EAAE,WAAW;IAG9B,WAAW,CACb,OAAO,EAAE,gBAAgB,GAC1B,OAAO,CAAC,OAAO,CAAC;CAyCtB"}
|
package/dist/auth.guard.js
CHANGED
|
@@ -8,38 +8,21 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
8
8
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
9
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
10
|
};
|
|
11
|
-
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
-
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
-
};
|
|
14
|
-
var AuthGuard_1;
|
|
15
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
12
|
exports.AuthGuard = void 0;
|
|
17
13
|
const core_1 = require("@nestjs/core");
|
|
18
14
|
const common_1 = require("@nestjs/common");
|
|
19
|
-
const fastify_1 = require("@clerk/fastify");
|
|
20
|
-
const models_1 = require("@trailmix-cms/models");
|
|
21
|
-
const config_1 = require("@nestjs/config");
|
|
22
15
|
const auth_decorator_1 = require("./decorators/auth.decorator");
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
let AuthGuard = AuthGuard_1 = class AuthGuard {
|
|
16
|
+
const auth_service_1 = require("./services/auth.service");
|
|
17
|
+
let AuthGuard = class AuthGuard {
|
|
26
18
|
reflector;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
authGuardHook;
|
|
30
|
-
logger = new common_1.Logger(AuthGuard_1.name);
|
|
31
|
-
clerkClient;
|
|
32
|
-
constructor(reflector, accountService, configService, authGuardHook) {
|
|
19
|
+
authService;
|
|
20
|
+
constructor(reflector, authService) {
|
|
33
21
|
this.reflector = reflector;
|
|
34
|
-
this.
|
|
35
|
-
this.configService = configService;
|
|
36
|
-
this.authGuardHook = authGuardHook;
|
|
37
|
-
this.clerkClient = (0, fastify_1.createClerkClient)({
|
|
38
|
-
secretKey: this.configService.get('CLERK_SECRET_KEY'),
|
|
39
|
-
});
|
|
22
|
+
this.authService = authService;
|
|
40
23
|
}
|
|
41
24
|
async canActivate(context) {
|
|
42
|
-
const
|
|
25
|
+
const requiredGlobalRoles = this.reflector.getAllAndOverride(auth_decorator_1.ROLES_KEY, [
|
|
43
26
|
context.getHandler(),
|
|
44
27
|
context.getClass(),
|
|
45
28
|
]);
|
|
@@ -47,82 +30,31 @@ let AuthGuard = AuthGuard_1 = class AuthGuard {
|
|
|
47
30
|
context.getHandler(),
|
|
48
31
|
context.getClass(),
|
|
49
32
|
]);
|
|
33
|
+
const requiredPrincipalTypes = this.reflector.getAllAndOverride(auth_decorator_1.PRINCIPAL_TYPES_KEY, [
|
|
34
|
+
context.getHandler(),
|
|
35
|
+
context.getClass(),
|
|
36
|
+
]);
|
|
50
37
|
const request = context.switchToHttp().getRequest();
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
38
|
+
const requestUrl = request.url;
|
|
39
|
+
const principal = await this.authService.getPrincipal(context);
|
|
40
|
+
const authResult = await this.authService.validateAuth(principal, allowAnonymous, requiredPrincipalTypes, requiredGlobalRoles, requestUrl);
|
|
41
|
+
if (authResult !== auth_service_1.AuthResult.IsValid) {
|
|
42
|
+
if (authResult === auth_service_1.AuthResult.Unauthorized) {
|
|
43
|
+
throw new common_1.UnauthorizedException('Unauthorized request');
|
|
55
44
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
request.account = account;
|
|
59
|
-
if (allowAnonymous) {
|
|
60
|
-
return true;
|
|
61
|
-
}
|
|
62
|
-
// If no roles are required, allow any authenticated user
|
|
63
|
-
if (requiredRoles.length == 0) {
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
66
|
-
// Check if user has required role
|
|
67
|
-
const hasRole = requiredRoles.some((role) => account?.roles?.includes(role))
|
|
68
|
-
|| account?.roles?.includes(models_1.Role.Admin);
|
|
69
|
-
if (!hasRole) {
|
|
70
|
-
throw new common_1.ForbiddenException('You are not authorized to access this resource');
|
|
71
|
-
}
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
async getAccount(context) {
|
|
75
|
-
const request = context.switchToHttp().getRequest();
|
|
76
|
-
const auth = (0, fastify_1.getAuth)(request);
|
|
77
|
-
if (!auth.userId) {
|
|
78
|
-
return {};
|
|
79
|
-
}
|
|
80
|
-
// TODO: Cache user
|
|
81
|
-
// const cachedUser = await this.userCache.getUser(auth.userId);
|
|
82
|
-
// if (cachedUser) {
|
|
83
|
-
// return {
|
|
84
|
-
// account: cachedUser.account,
|
|
85
|
-
// userPublicMetadata: cachedUser.metadata,
|
|
86
|
-
// };
|
|
87
|
-
// }
|
|
88
|
-
const user = await this.clerkClient.users.getUser(auth.userId);
|
|
89
|
-
const accountExists = await this.accountService.getAccount(auth.userId);
|
|
90
|
-
if (accountExists) {
|
|
91
|
-
return {
|
|
92
|
-
account: accountExists,
|
|
93
|
-
userPublicMetadata: user.publicMetadata,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
const account = await this.accountService.upsertAccount(auth.userId);
|
|
97
|
-
// TODO: Lock this step to prevent race conditions
|
|
98
|
-
if (this.authGuardHook) {
|
|
99
|
-
const authGuardHookresult = await this.authGuardHook.onHook(account);
|
|
100
|
-
if (!authGuardHookresult) {
|
|
101
|
-
this.logger.error('Failed to validate account using auth guard hook', {
|
|
102
|
-
userId: auth.userId,
|
|
103
|
-
accountId: account?._id,
|
|
104
|
-
});
|
|
105
|
-
throw new common_1.InternalServerErrorException('Failed to validate account using auth guard hook');
|
|
45
|
+
if (authResult === auth_service_1.AuthResult.Forbidden) {
|
|
46
|
+
throw new common_1.ForbiddenException('You are not authorized to access this resource');
|
|
106
47
|
}
|
|
48
|
+
throw new common_1.InternalServerErrorException('Failed to validate authentication');
|
|
107
49
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
// account: account!,
|
|
111
|
-
// metadata: user.publicMetadata,
|
|
112
|
-
// });
|
|
113
|
-
return {
|
|
114
|
-
account,
|
|
115
|
-
userPublicMetadata: user.publicMetadata,
|
|
116
|
-
};
|
|
50
|
+
request.principal = principal;
|
|
51
|
+
return true;
|
|
117
52
|
}
|
|
118
53
|
};
|
|
119
54
|
exports.AuthGuard = AuthGuard;
|
|
120
|
-
exports.AuthGuard = AuthGuard =
|
|
55
|
+
exports.AuthGuard = AuthGuard = __decorate([
|
|
121
56
|
(0, common_1.Injectable)(),
|
|
122
|
-
__param(3, (0, common_1.Optional)()),
|
|
123
|
-
__param(3, (0, common_1.Inject)(constants_1.PROVIDER_SYMBOLS.TRAILMIXCMS_CMS_AUTH_GUARD_HOOK)),
|
|
124
57
|
__metadata("design:paramtypes", [core_1.Reflector,
|
|
125
|
-
|
|
126
|
-
config_1.ConfigService, Object])
|
|
58
|
+
auth_service_1.AuthService])
|
|
127
59
|
], AuthGuard);
|
|
128
60
|
//# sourceMappingURL=auth.guard.js.map
|
package/dist/auth.guard.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.guard.js","sourceRoot":"","sources":["../src/auth.guard.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.guard.js","sourceRoot":"","sources":["../src/auth.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,uCAAyC;AACzC,2CAAoJ;AAGpJ,gEAAkG;AAClG,0DAAkE;AAU3D,IAAM,SAAS,GAAf,MAAM,SAAS;IAEN;IACA;IAFZ,YACY,SAAoB,EACpB,WAAwB;QADxB,cAAS,GAAT,SAAS,CAAW;QACpB,gBAAW,GAAX,WAAW,CAAa;IAChC,CAAC;IAEL,KAAK,CAAC,WAAW,CACb,OAAyB;QAEzB,MAAM,mBAAmB,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAwC,0BAAS,EAAE;YAC3G,OAAO,CAAC,UAAU,EAAE;YACpB,OAAO,CAAC,QAAQ,EAAE;SACrB,CAAC,CAAC;QAEH,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAU,oCAAmB,EAAE;YAClF,OAAO,CAAC,UAAU,EAAE;YACpB,OAAO,CAAC,QAAQ,EAAE;SACrB,CAAC,CAAC;QAEH,MAAM,sBAAsB,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAA6B,oCAAmB,EAAE;YAC7G,OAAO,CAAC,UAAU,EAAE;YACpB,OAAO,CAAC,QAAQ,EAAE;SACrB,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAkB,CAAC;QACpE,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC;QAE/B,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAC/D,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,YAAY,CAClD,SAAS,EACT,cAAc,EACd,sBAAsB,EACtB,mBAAmB,EACnB,UAAU,CACb,CAAC;QAEF,IAAI,UAAU,KAAK,yBAAU,CAAC,OAAO,EAAE,CAAC;YACpC,IAAI,UAAU,KAAK,yBAAU,CAAC,YAAY,EAAE,CAAC;gBACzC,MAAM,IAAI,8BAAqB,CAAC,sBAAsB,CAAC,CAAC;YAC5D,CAAC;YACD,IAAI,UAAU,KAAK,yBAAU,CAAC,SAAS,EAAE,CAAC;gBACtC,MAAM,IAAI,2BAAkB,CAAC,gDAAgD,CAAC,CAAC;YACnF,CAAC;YACD,MAAM,IAAI,qCAA4B,CAAC,mCAAmC,CAAC,CAAC;QAChF,CAAC;QAED,OAAO,CAAC,SAAS,GAAG,SAAU,CAAC;QAC/B,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ,CAAA;AAjDY,8BAAS;oBAAT,SAAS;IADrB,IAAA,mBAAU,GAAE;qCAGc,gBAAS;QACP,0BAAW;GAH3B,SAAS,CAiDrB"}
|
|
@@ -3,15 +3,17 @@ import { OnModuleInit } from '@nestjs/common';
|
|
|
3
3
|
import { ZodType } from 'zod';
|
|
4
4
|
import { Account } from '@trailmix-cms/models';
|
|
5
5
|
import { Collections, DatabaseService, AuditedCollection } from '@trailmix-cms/db';
|
|
6
|
-
import { CollectionConfig } from '../types
|
|
6
|
+
import { type CollectionConfig } from '../types';
|
|
7
7
|
type Record = Account.Entity;
|
|
8
8
|
export declare class AccountCollection<T extends Record = Record> extends AuditedCollection<T> implements OnModuleInit {
|
|
9
9
|
protected readonly entitySchema: ZodType<OptionalUnlessRequiredId<T>>;
|
|
10
|
-
protected readonly setup: (collection: Collection<T>) => Promise<void>;
|
|
11
10
|
protected readonly config: CollectionConfig;
|
|
11
|
+
protected readonly setup: ((collection: Collection<T>) => Promise<void>) | null;
|
|
12
|
+
protected readonly databaseService: DatabaseService;
|
|
13
|
+
protected readonly auditCollection: Collections.AuditCollection;
|
|
12
14
|
private readonly logger;
|
|
13
15
|
protected readonly collectionName: "account";
|
|
14
|
-
constructor(entitySchema: ZodType<OptionalUnlessRequiredId<T>>, setup: (collection: Collection<T>) => Promise<void
|
|
16
|
+
constructor(entitySchema: ZodType<OptionalUnlessRequiredId<T>>, config: CollectionConfig, setup: ((collection: Collection<T>) => Promise<void>) | null, collection: Collection<T>, databaseService: DatabaseService, auditCollection: Collections.AuditCollection);
|
|
15
17
|
onModuleInit(): Promise<void>;
|
|
16
18
|
}
|
|
17
19
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account.collection.d.ts","sourceRoot":"","sources":["../../src/collections/account.collection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAA8B,YAAY,
|
|
1
|
+
{"version":3,"file":"account.collection.d.ts","sourceRoot":"","sources":["../../src/collections/account.collection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAA8B,YAAY,EAAY,MAAM,gBAAgB,CAAC;AACpF,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,eAAe,EAAsB,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGvG,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;AAG5B,qBACa,iBAAiB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,iBAAiB,CAAC,CAAC,CAAE,YAAW,YAAY;IAK7D,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC;IACrE,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,gBAAgB;IAChC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI;IAEnI,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,eAAe;IACnD,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,eAAe;IATnE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;IAC5D,SAAS,CAAC,QAAQ,CAAC,cAAc,YAAkB;gBAGa,YAAY,EAAE,OAAO,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC,EAClD,MAAM,EAAE,gBAAgB,EACb,KAAK,EAAE,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,EAC/F,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,EAC1C,eAAe,EAAE,eAAe,EAChC,eAAe,EAAE,WAAW,CAAC,eAAe;IAK7D,YAAY;CASrB"}
|
|
@@ -21,32 +21,39 @@ const constants_1 = require("../constants");
|
|
|
21
21
|
const collectionName = constants_1.CMSCollectionName.Account;
|
|
22
22
|
let AccountCollection = class AccountCollection extends db_1.AuditedCollection {
|
|
23
23
|
entitySchema;
|
|
24
|
-
setup;
|
|
25
24
|
config;
|
|
25
|
+
setup;
|
|
26
|
+
databaseService;
|
|
27
|
+
auditCollection;
|
|
26
28
|
logger = new common_1.Logger(this.constructor.name);
|
|
27
29
|
collectionName = collectionName;
|
|
28
|
-
constructor(entitySchema,
|
|
30
|
+
constructor(entitySchema, config, setup, collection, databaseService, auditCollection) {
|
|
29
31
|
super(collection, databaseService, auditCollection);
|
|
30
32
|
this.entitySchema = entitySchema;
|
|
31
|
-
this.setup = setup;
|
|
32
33
|
this.config = config;
|
|
34
|
+
this.setup = setup;
|
|
35
|
+
this.databaseService = databaseService;
|
|
36
|
+
this.auditCollection = auditCollection;
|
|
33
37
|
}
|
|
34
38
|
async onModuleInit() {
|
|
35
39
|
this.logger.verbose(`creating custom indexes for collection_${collectionName}`);
|
|
36
40
|
if (!this.config.disableDefaultIndexes) {
|
|
37
41
|
await this.collection.createIndex({ user_id: 1 }, { unique: true, sparse: true });
|
|
38
42
|
}
|
|
39
|
-
|
|
43
|
+
if (this.setup) {
|
|
44
|
+
await this.setup(this.collection);
|
|
45
|
+
}
|
|
40
46
|
}
|
|
41
47
|
};
|
|
42
48
|
exports.AccountCollection = AccountCollection;
|
|
43
49
|
exports.AccountCollection = AccountCollection = __decorate([
|
|
44
50
|
(0, common_1.Injectable)(),
|
|
45
|
-
__param(0, (0, common_1.Inject)(constants_1.PROVIDER_SYMBOLS.
|
|
46
|
-
__param(1, (0, common_1.Inject)(constants_1.PROVIDER_SYMBOLS.
|
|
47
|
-
__param(2, (0, common_1.
|
|
51
|
+
__param(0, (0, common_1.Inject)(constants_1.PROVIDER_SYMBOLS.ACCOUNT_SCHEMA)),
|
|
52
|
+
__param(1, (0, common_1.Inject)(constants_1.PROVIDER_SYMBOLS.ACCOUNT_CONFIG)),
|
|
53
|
+
__param(2, (0, common_1.Optional)()),
|
|
54
|
+
__param(2, (0, common_1.Inject)(constants_1.PROVIDER_SYMBOLS.ACCOUNT_SETUP)),
|
|
48
55
|
__param(3, (0, db_1.DocumentCollection)(collectionName)),
|
|
49
|
-
__metadata("design:paramtypes", [zod_1.ZodType,
|
|
56
|
+
__metadata("design:paramtypes", [zod_1.ZodType, Object, Object, mongodb_1.Collection,
|
|
50
57
|
db_1.DatabaseService, db_1.Collections.AuditCollection])
|
|
51
58
|
], AccountCollection);
|
|
52
59
|
//# sourceMappingURL=account.collection.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account.collection.js","sourceRoot":"","sources":["../../src/collections/account.collection.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,qCAA+D;AAC/D,
|
|
1
|
+
{"version":3,"file":"account.collection.js","sourceRoot":"","sources":["../../src/collections/account.collection.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,qCAA+D;AAC/D,2CAAoF;AACpF,6BAA8B;AAE9B,yCAAuG;AAEvG,4CAAmE;AAInE,MAAM,cAAc,GAAG,6BAAiB,CAAC,OAAO,CAAC;AAG1C,IAAM,iBAAiB,GAAvB,MAAM,iBAA6C,SAAQ,sBAAoB;IAKlB;IACA;IACW;IAEpD;IACA;IATN,MAAM,GAAG,IAAI,eAAM,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACzC,cAAc,GAAG,cAAc,CAAC;IAEnD,YACgE,YAAkD,EAClD,MAAwB,EACb,KAA4D,EAC/F,UAAyB,EAC1C,eAAgC,EAChC,eAA4C;QAE/D,KAAK,CAAC,UAAU,EAAE,eAAe,EAAE,eAAe,CAAC,CAAC;QAPQ,iBAAY,GAAZ,YAAY,CAAsC;QAClD,WAAM,GAAN,MAAM,CAAkB;QACb,UAAK,GAAL,KAAK,CAAuD;QAEhH,oBAAe,GAAf,eAAe,CAAiB;QAChC,oBAAe,GAAf,eAAe,CAA6B;IAGnE,CAAC;IAED,KAAK,CAAC,YAAY;QACd,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,0CAA0C,cAAc,EAAE,CAAC,CAAA;QAC/E,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,qBAAqB,EAAE,CAAC;YACrC,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACtF,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtC,CAAC;IACL,CAAC;CACJ,CAAA;AAxBY,8CAAiB;4BAAjB,iBAAiB;IAD7B,IAAA,mBAAU,GAAE;IAMJ,WAAA,IAAA,eAAM,EAAC,4BAAgB,CAAC,cAAc,CAAC,CAAA;IACvC,WAAA,IAAA,eAAM,EAAC,4BAAgB,CAAC,cAAc,CAAC,CAAA;IACvC,WAAA,IAAA,iBAAQ,GAAE,CAAA;IAAE,WAAA,IAAA,eAAM,EAAC,4BAAgB,CAAC,aAAa,CAAC,CAAA;IAClD,WAAA,IAAA,uBAAkB,EAAC,cAAc,CAAC,CAAA;qCAHuC,aAAO,kBAGjC,oBAAU;QACtB,oBAAe,EACf,gBAAW,CAAC,eAAe;GAV1D,iBAAiB,CAwB7B"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ClientSession, Collection, ObjectId } from 'mongodb';
|
|
2
|
+
import { DatabaseService, Collections, AuditedCollection } from '@trailmix-cms/db';
|
|
3
|
+
import * as trailmixModels from '@trailmix-cms/models';
|
|
4
|
+
import { Utils } from '@trailmix-cms/db';
|
|
5
|
+
type Record = trailmixModels.ApiKey.Entity;
|
|
6
|
+
export declare class ApiKeyCollection extends AuditedCollection<Record> {
|
|
7
|
+
protected readonly collection: Collection<Record>;
|
|
8
|
+
protected readonly databaseService: DatabaseService;
|
|
9
|
+
protected readonly auditCollection: Collections.AuditCollection;
|
|
10
|
+
private readonly logger;
|
|
11
|
+
readonly collectionName: "api-key";
|
|
12
|
+
readonly entitySchema: import("zod").ZodObject<{
|
|
13
|
+
_id: import("zod").ZodCodec<import("zod").ZodString, import("zod").ZodCustom<import("bson").ObjectId, import("bson").ObjectId>>;
|
|
14
|
+
created_at: import("zod").ZodCodec<import("zod").ZodISODateTime, import("zod").ZodDate>;
|
|
15
|
+
updated_at: import("zod").ZodOptional<import("zod").ZodCodec<import("zod").ZodISODateTime, import("zod").ZodDate>>;
|
|
16
|
+
api_key: import("zod").ZodString;
|
|
17
|
+
name: import("zod").ZodOptional<import("zod").ZodString>;
|
|
18
|
+
disabled: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
19
|
+
expires_at: import("zod").ZodOptional<import("zod").ZodCodec<import("zod").ZodISODateTime, import("zod").ZodDate>>;
|
|
20
|
+
scope_type: import("zod").ZodEnum<{
|
|
21
|
+
account: "account";
|
|
22
|
+
organization: "organization";
|
|
23
|
+
global: "global";
|
|
24
|
+
}>;
|
|
25
|
+
scope_id: import("zod").ZodOptional<import("zod").ZodCodec<import("zod").ZodString, import("zod").ZodCustom<import("bson").ObjectId, import("bson").ObjectId>>>;
|
|
26
|
+
}, import("zod/v4/core").$strip>;
|
|
27
|
+
constructor(collection: Collection<Record>, databaseService: DatabaseService, auditCollection: Collections.AuditCollection);
|
|
28
|
+
onModuleInit(): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Generates a new API key with the format: <prefix>_<random characters>
|
|
31
|
+
* @param prefix Optional prefix for the API key
|
|
32
|
+
* @param length Length of the random string
|
|
33
|
+
* @returns A randomly generated API key prefixed with the prefix if provided
|
|
34
|
+
*/
|
|
35
|
+
private static generateApiKey;
|
|
36
|
+
/**
|
|
37
|
+
* Creates a new APIKey record with retry logic for duplicate API keys
|
|
38
|
+
* @param params The parameters for the API key
|
|
39
|
+
* @param auditContext The audit context for the operation
|
|
40
|
+
* @param options The options for the API key
|
|
41
|
+
* @param options.maxRetries Maximum number of retry attempts if duplicate key is encountered (default: 10)
|
|
42
|
+
* @param options.prefix Optional prefix for the API key
|
|
43
|
+
* @param options.length Length of the random string
|
|
44
|
+
* @returns The created APIKey record
|
|
45
|
+
* @throws Error if max retries exceeded or if insert fails for non-duplicate reasons
|
|
46
|
+
*/
|
|
47
|
+
create(params: Omit<Utils.Creatable<trailmixModels.ApiKey.Entity>, 'api_key'>, auditContext: trailmixModels.AuditContext.Model, options?: {
|
|
48
|
+
maxRetries: number;
|
|
49
|
+
prefix?: string;
|
|
50
|
+
length: number;
|
|
51
|
+
}, session?: ClientSession): Promise<Record>;
|
|
52
|
+
}
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=api-key.collection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-key.collection.d.ts","sourceRoot":"","sources":["../../src/collections/api-key.collection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAoB,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEhF,OAAO,EAAsB,eAAe,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGvG,OAAO,KAAK,cAAc,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,KAAK,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC;AAG3C,qBACa,gBAAiB,SAAQ,iBAAiB,CAAC,MAAM,CAAC;IAOvD,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC;IACjD,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,eAAe;IACnD,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,eAAe;IARnE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;IAC5D,SAAgB,cAAc,YAAkB;IAChD,SAAgB,YAAY;;;;;;;;;;;;;;qCAAgC;gBAIrC,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC,EAC9B,eAAe,EAAE,eAAe,EAChC,eAAe,EAAE,WAAW,CAAC,eAAe;IAK7D,YAAY;IAKlB;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAO7B;;;;;;;;;;OAUG;IACG,MAAM,CACR,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,EACtE,YAAY,EAAE,cAAc,CAAC,YAAY,CAAC,KAAK,EAC/C,OAAO,GAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAmC,EACjG,OAAO,CAAC,EAAE,aAAa,GACxB,OAAO,CAAC,MAAM,CAAC;CA6CrB"}
|
|
@@ -0,0 +1,142 @@
|
|
|
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 ApiKeyCollection_1;
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.ApiKeyCollection = void 0;
|
|
50
|
+
const mongodb_1 = require("mongodb");
|
|
51
|
+
const common_1 = require("@nestjs/common");
|
|
52
|
+
const db_1 = require("@trailmix-cms/db");
|
|
53
|
+
const constants_1 = require("../constants");
|
|
54
|
+
const crypto_1 = require("crypto");
|
|
55
|
+
const trailmixModels = __importStar(require("@trailmix-cms/models"));
|
|
56
|
+
const collectionName = constants_1.CMSCollectionName.ApiKey;
|
|
57
|
+
let ApiKeyCollection = ApiKeyCollection_1 = class ApiKeyCollection extends db_1.AuditedCollection {
|
|
58
|
+
collection;
|
|
59
|
+
databaseService;
|
|
60
|
+
auditCollection;
|
|
61
|
+
logger = new common_1.Logger(this.constructor.name);
|
|
62
|
+
collectionName = collectionName;
|
|
63
|
+
entitySchema = trailmixModels.ApiKey.schema;
|
|
64
|
+
constructor(collection, databaseService, auditCollection) {
|
|
65
|
+
super(collection, databaseService, auditCollection);
|
|
66
|
+
this.collection = collection;
|
|
67
|
+
this.databaseService = databaseService;
|
|
68
|
+
this.auditCollection = auditCollection;
|
|
69
|
+
}
|
|
70
|
+
async onModuleInit() {
|
|
71
|
+
this.logger.verbose(`creating custom indexes for collection_${collectionName}`);
|
|
72
|
+
await this.collection.createIndex({ api_key: 1 }, { unique: true });
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Generates a new API key with the format: <prefix>_<random characters>
|
|
76
|
+
* @param prefix Optional prefix for the API key
|
|
77
|
+
* @param length Length of the random string
|
|
78
|
+
* @returns A randomly generated API key prefixed with the prefix if provided
|
|
79
|
+
*/
|
|
80
|
+
static generateApiKey(prefix, length = 32) {
|
|
81
|
+
// Generate random bytes and convert to hex
|
|
82
|
+
const randomBytesBuffer = (0, crypto_1.randomBytes)(length);
|
|
83
|
+
const randomString = randomBytesBuffer.toString('hex');
|
|
84
|
+
return [prefix, randomString].filter(Boolean).join('_');
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Creates a new APIKey record with retry logic for duplicate API keys
|
|
88
|
+
* @param params The parameters for the API key
|
|
89
|
+
* @param auditContext The audit context for the operation
|
|
90
|
+
* @param options The options for the API key
|
|
91
|
+
* @param options.maxRetries Maximum number of retry attempts if duplicate key is encountered (default: 10)
|
|
92
|
+
* @param options.prefix Optional prefix for the API key
|
|
93
|
+
* @param options.length Length of the random string
|
|
94
|
+
* @returns The created APIKey record
|
|
95
|
+
* @throws Error if max retries exceeded or if insert fails for non-duplicate reasons
|
|
96
|
+
*/
|
|
97
|
+
async create(params, auditContext, options = { maxRetries: 10, length: 32 }, session) {
|
|
98
|
+
const { maxRetries, prefix, length } = options;
|
|
99
|
+
let attempts = 0;
|
|
100
|
+
return this.databaseService.withTransaction({ session }, async (session) => {
|
|
101
|
+
while (attempts < maxRetries) {
|
|
102
|
+
try {
|
|
103
|
+
const apiKey = ApiKeyCollection_1.generateApiKey(prefix, length);
|
|
104
|
+
const doc = {
|
|
105
|
+
api_key: apiKey,
|
|
106
|
+
...params,
|
|
107
|
+
};
|
|
108
|
+
const result = await this.insertOne(doc, auditContext);
|
|
109
|
+
this.logger.verbose(`Successfully created APIKey with id ${result._id} on attempt ${attempts + 1}`);
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
// Check if error is a duplicate key error (MongoDB error code 11000)
|
|
114
|
+
if (error instanceof mongodb_1.MongoServerError && error.code === 11000) {
|
|
115
|
+
attempts++;
|
|
116
|
+
this.logger.warn(`Duplicate API key detected on attempt ${attempts}, retrying with new key...`);
|
|
117
|
+
if (attempts >= maxRetries) {
|
|
118
|
+
this.logger.error(`Failed to create APIKey after ${maxRetries} attempts due to duplicate keys`);
|
|
119
|
+
throw new Error(`Failed to create APIKey: generated ${maxRetries} duplicate API keys. This is extremely unlikely.`);
|
|
120
|
+
}
|
|
121
|
+
// Continue to retry with a new key
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
// Re-throw non-duplicate errors
|
|
125
|
+
this.logger.error(`Failed to create APIKey: ${error}`);
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// This should never be reached, but TypeScript requires it
|
|
131
|
+
throw new Error('Unexpected error in create method');
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
exports.ApiKeyCollection = ApiKeyCollection;
|
|
136
|
+
exports.ApiKeyCollection = ApiKeyCollection = ApiKeyCollection_1 = __decorate([
|
|
137
|
+
(0, common_1.Injectable)(),
|
|
138
|
+
__param(0, (0, db_1.DocumentCollection)(collectionName)),
|
|
139
|
+
__metadata("design:paramtypes", [mongodb_1.Collection,
|
|
140
|
+
db_1.DatabaseService, db_1.Collections.AuditCollection])
|
|
141
|
+
], ApiKeyCollection);
|
|
142
|
+
//# sourceMappingURL=api-key.collection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-key.collection.js","sourceRoot":"","sources":["../../src/collections/api-key.collection.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { AccountCollection } from './account.collection';
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
2
|
+
export { OrganizationCollection } from './organization.collection';
|
|
3
|
+
export { RoleCollection } from './role.collection';
|
|
4
|
+
export { SecurityAuditCollection } from './security-audit.collection';
|
|
5
|
+
export { ApiKeyCollection } from './api-key.collection';
|
|
4
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/collections/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/collections/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ApiKeyCollection = exports.SecurityAuditCollection = exports.RoleCollection = exports.OrganizationCollection = exports.AccountCollection = void 0;
|
|
4
4
|
var account_collection_1 = require("./account.collection");
|
|
5
5
|
Object.defineProperty(exports, "AccountCollection", { enumerable: true, get: function () { return account_collection_1.AccountCollection; } });
|
|
6
|
-
var
|
|
7
|
-
Object.defineProperty(exports, "
|
|
8
|
-
var
|
|
9
|
-
Object.defineProperty(exports, "
|
|
6
|
+
var organization_collection_1 = require("./organization.collection");
|
|
7
|
+
Object.defineProperty(exports, "OrganizationCollection", { enumerable: true, get: function () { return organization_collection_1.OrganizationCollection; } });
|
|
8
|
+
var role_collection_1 = require("./role.collection");
|
|
9
|
+
Object.defineProperty(exports, "RoleCollection", { enumerable: true, get: function () { return role_collection_1.RoleCollection; } });
|
|
10
|
+
var security_audit_collection_1 = require("./security-audit.collection");
|
|
11
|
+
Object.defineProperty(exports, "SecurityAuditCollection", { enumerable: true, get: function () { return security_audit_collection_1.SecurityAuditCollection; } });
|
|
12
|
+
var api_key_collection_1 = require("./api-key.collection");
|
|
13
|
+
Object.defineProperty(exports, "ApiKeyCollection", { enumerable: true, get: function () { return api_key_collection_1.ApiKeyCollection; } });
|
|
10
14
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/collections/index.ts"],"names":[],"mappings":";;;AAAA,2DAAyD;AAAhD,uHAAA,iBAAiB,OAAA;AAC1B,qDAAmD;AAA1C,iHAAA,cAAc,OAAA;AACvB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/collections/index.ts"],"names":[],"mappings":";;;AAAA,2DAAyD;AAAhD,uHAAA,iBAAiB,OAAA;AAC1B,qEAAmE;AAA1D,iIAAA,sBAAsB,OAAA;AAC/B,qDAAmD;AAA1C,iHAAA,cAAc,OAAA;AACvB,yEAAsE;AAA7D,oIAAA,uBAAuB,OAAA;AAChC,2DAAwD;AAA/C,sHAAA,gBAAgB,OAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Collection, OptionalUnlessRequiredId } from 'mongodb';
|
|
2
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
3
|
+
import { DatabaseService, Collections, AuditedCollection } from '@trailmix-cms/db';
|
|
4
|
+
import * as trailmixModels from '@trailmix-cms/models';
|
|
5
|
+
import { ZodType } from 'zod';
|
|
6
|
+
import { type CollectionConfig } from '../types';
|
|
7
|
+
type Record = trailmixModels.Organization.Entity;
|
|
8
|
+
export declare class OrganizationCollection<T extends Record = Record> extends AuditedCollection<T> implements OnModuleInit {
|
|
9
|
+
protected readonly entitySchema: ZodType<OptionalUnlessRequiredId<T>>;
|
|
10
|
+
protected readonly setup: ((collection: Collection<T>) => Promise<void>) | null;
|
|
11
|
+
protected readonly config: CollectionConfig;
|
|
12
|
+
protected readonly databaseService: DatabaseService;
|
|
13
|
+
protected readonly auditCollection: Collections.AuditCollection;
|
|
14
|
+
private readonly logger;
|
|
15
|
+
readonly collectionName: "organization";
|
|
16
|
+
constructor(entitySchema: ZodType<OptionalUnlessRequiredId<T>>, setup: ((collection: Collection<T>) => Promise<void>) | null, config: CollectionConfig, collection: Collection<T>, databaseService: DatabaseService, auditCollection: Collections.AuditCollection);
|
|
17
|
+
onModuleInit(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=organization.collection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organization.collection.d.ts","sourceRoot":"","sources":["../../src/collections/organization.collection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAsB,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AACpF,OAAO,EAAsB,eAAe,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAEvG,OAAO,KAAK,cAAc,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAC9B,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD,KAAK,MAAM,GAAG,cAAc,CAAC,YAAY,CAAC,MAAM,CAAC;AAGjD,qBACa,sBAAsB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,iBAAiB,CAAC,CAAC,CAAE,YAAW,YAAY;IAK7D,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC;IAC1D,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI;IAC1F,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,gBAAgB;IAEzF,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,eAAe;IACnD,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,eAAe;IATnE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;IAC5D,SAAgB,cAAc,iBAAkB;gBAGqB,YAAY,EAAE,OAAO,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC,EACvC,KAAK,EAAE,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,EACvE,MAAM,EAAE,gBAAgB,EACrD,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,EAC1C,eAAe,EAAE,eAAe,EAChC,eAAe,EAAE,WAAW,CAAC,eAAe;IAK7D,YAAY;CASrB"}
|