@venizia/ignis-kernel 0.4.6 → 0.4.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/LICENSE.md +1 -4
- package/dist/esm/base/applications/artifact-group.d.ts.map +1 -1
- package/dist/esm/base/applications/artifact-group.js +4 -1
- package/dist/esm/base/applications/artifact-group.js.map +1 -1
- package/dist/esm/base/applications/artifact-index.d.ts.map +1 -1
- package/dist/esm/base/applications/artifact-index.js +2 -1
- package/dist/esm/base/applications/artifact-index.js.map +1 -1
- package/dist/esm/base/applications/cors.d.ts +12 -10
- package/dist/esm/base/applications/cors.d.ts.map +1 -1
- package/dist/esm/base/applications/cors.js +37 -35
- package/dist/esm/base/applications/cors.js.map +1 -1
- package/dist/esm/base/applications/rest.js +11 -11
- package/dist/esm/base/applications/rest.js.map +1 -1
- package/dist/esm/base/auth/authenticate/common/codecs.js +2 -2
- package/dist/esm/base/auth/authenticate/common/codecs.js.map +1 -1
- package/dist/esm/base/auth/authenticate/strategies/strategy-registry.d.ts +1 -1
- package/dist/esm/base/auth/authenticate/strategies/strategy-registry.js +1 -1
- package/dist/esm/base/auth/authenticate/strategies/strategy-registry.js.map +1 -1
- package/dist/esm/base/auth/authorize/providers/authorization.provider.d.ts.map +1 -1
- package/dist/esm/base/auth/authorize/providers/authorization.provider.js +14 -11
- package/dist/esm/base/auth/authorize/providers/authorization.provider.js.map +1 -1
- package/dist/esm/base/auth/authorize/providers/request-domain.d.ts +14 -11
- package/dist/esm/base/auth/authorize/providers/request-domain.d.ts.map +1 -1
- package/dist/esm/base/auth/authorize/providers/request-domain.js +42 -39
- package/dist/esm/base/auth/authorize/providers/request-domain.js.map +1 -1
- package/dist/esm/base/auth/base/abstract-auth-registry.js +2 -2
- package/dist/esm/base/auth/base/abstract-auth-registry.js.map +1 -1
- package/dist/esm/base/auth/models/requests/change-password.schema.js +3 -3
- package/dist/esm/base/auth/models/requests/change-password.schema.js.map +1 -1
- package/dist/esm/base/auth/models/requests/sign-in.schema.js +5 -5
- package/dist/esm/base/auth/models/requests/sign-in.schema.js.map +1 -1
- package/dist/esm/base/components/controller/rest/rest.component.js +2 -2
- package/dist/esm/base/components/controller/rest/rest.component.js.map +1 -1
- package/dist/esm/base/controllers/common/index.d.ts +0 -1
- package/dist/esm/base/controllers/common/index.d.ts.map +1 -1
- package/dist/esm/base/controllers/common/index.js +0 -1
- package/dist/esm/base/controllers/common/index.js.map +1 -1
- package/dist/esm/base/controllers/common/schema-builders.d.ts +0 -5
- package/dist/esm/base/controllers/common/schema-builders.d.ts.map +1 -1
- package/dist/esm/base/controllers/common/schema-builders.js +0 -14
- package/dist/esm/base/controllers/common/schema-builders.js.map +1 -1
- package/dist/esm/base/controllers/context.d.ts +7 -2
- package/dist/esm/base/controllers/context.d.ts.map +1 -1
- package/dist/esm/base/controllers/context.js +7 -4
- package/dist/esm/base/controllers/context.js.map +1 -1
- package/dist/esm/base/controllers/factory/controller.d.ts +33 -1
- package/dist/esm/base/controllers/factory/controller.d.ts.map +1 -1
- package/dist/esm/base/controllers/factory/controller.js +90 -6
- package/dist/esm/base/controllers/factory/controller.js.map +1 -1
- package/dist/esm/base/controllers/factory/crud/persistable.d.ts.map +1 -1
- package/dist/esm/base/controllers/factory/crud/persistable.js +40 -25
- package/dist/esm/base/controllers/factory/crud/persistable.js.map +1 -1
- package/dist/esm/base/controllers/factory/crud/readable.d.ts.map +1 -1
- package/dist/esm/base/controllers/factory/crud/readable.js +4 -3
- package/dist/esm/base/controllers/factory/crud/readable.js.map +1 -1
- package/dist/esm/base/controllers/factory/definition.d.ts +1 -8
- package/dist/esm/base/controllers/factory/definition.d.ts.map +1 -1
- package/dist/esm/base/controllers/factory/definition.js +17 -24
- package/dist/esm/base/controllers/factory/definition.js.map +1 -1
- package/dist/esm/base/controllers/factory/index.d.ts +0 -1
- package/dist/esm/base/controllers/factory/index.d.ts.map +1 -1
- package/dist/esm/base/controllers/factory/index.js +0 -1
- package/dist/esm/base/controllers/factory/index.js.map +1 -1
- package/dist/esm/base/controllers/rest/abstract.d.ts.map +1 -1
- package/dist/esm/base/controllers/rest/abstract.js +6 -6
- package/dist/esm/base/controllers/rest/abstract.js.map +1 -1
- package/dist/esm/base/controllers/rest/base.d.ts +0 -5
- package/dist/esm/base/controllers/rest/base.d.ts.map +1 -1
- package/dist/esm/base/controllers/rest/base.js +14 -14
- package/dist/esm/base/controllers/rest/base.js.map +1 -1
- package/dist/esm/base/datasources/abstract.js +2 -2
- package/dist/esm/base/datasources/abstract.js.map +1 -1
- package/dist/esm/base/events/event-bus.js +4 -4
- package/dist/esm/base/events/event-bus.js.map +1 -1
- package/dist/esm/base/metadata/injectable.d.ts +7 -4
- package/dist/esm/base/metadata/injectable.d.ts.map +1 -1
- package/dist/esm/base/metadata/injectable.js +26 -23
- package/dist/esm/base/metadata/injectable.js.map +1 -1
- package/dist/esm/base/metadata/model-metadata.d.ts +27 -13
- package/dist/esm/base/metadata/model-metadata.d.ts.map +1 -1
- package/dist/esm/base/metadata/model-metadata.js +56 -26
- package/dist/esm/base/metadata/model-metadata.js.map +1 -1
- package/dist/esm/base/metadata/persistents.d.ts.map +1 -1
- package/dist/esm/base/metadata/persistents.js +21 -13
- package/dist/esm/base/metadata/persistents.js.map +1 -1
- package/dist/esm/base/metadata/routes/controller.d.ts.map +1 -1
- package/dist/esm/base/metadata/routes/controller.js +5 -2
- package/dist/esm/base/metadata/routes/controller.js.map +1 -1
- package/dist/esm/base/middlewares/app-error/app-error.middleware.js +7 -7
- package/dist/esm/base/middlewares/app-error/app-error.middleware.js.map +1 -1
- package/dist/esm/base/middlewares/app-error/database.handler.d.ts +14 -12
- package/dist/esm/base/middlewares/app-error/database.handler.d.ts.map +1 -1
- package/dist/esm/base/middlewares/app-error/database.handler.js +37 -35
- package/dist/esm/base/middlewares/app-error/database.handler.js.map +1 -1
- package/dist/esm/base/middlewares/app-error/zod.handler.d.ts +28 -23
- package/dist/esm/base/middlewares/app-error/zod.handler.d.ts.map +1 -1
- package/dist/esm/base/middlewares/app-error/zod.handler.js +56 -53
- package/dist/esm/base/middlewares/app-error/zod.handler.js.map +1 -1
- package/dist/esm/base/middlewares/emoji-favicon/emoji-favicon.middleware.d.ts +6 -4
- package/dist/esm/base/middlewares/emoji-favicon/emoji-favicon.middleware.d.ts.map +1 -1
- package/dist/esm/base/middlewares/emoji-favicon/emoji-favicon.middleware.js +14 -12
- package/dist/esm/base/middlewares/emoji-favicon/emoji-favicon.middleware.js.map +1 -1
- package/dist/esm/base/middlewares/form-body/form-body.middleware.d.ts +15 -11
- package/dist/esm/base/middlewares/form-body/form-body.middleware.d.ts.map +1 -1
- package/dist/esm/base/middlewares/form-body/form-body.middleware.js +25 -21
- package/dist/esm/base/middlewares/form-body/form-body.middleware.js.map +1 -1
- package/dist/esm/base/models/common/schemas.d.ts +184 -105
- package/dist/esm/base/models/common/schemas.d.ts.map +1 -1
- package/dist/esm/base/models/common/schemas.js +105 -54
- package/dist/esm/base/models/common/schemas.js.map +1 -1
- package/dist/esm/base/models/common/utilities.d.ts +10 -5
- package/dist/esm/base/models/common/utilities.d.ts.map +1 -1
- package/dist/esm/base/models/common/utilities.js +22 -16
- package/dist/esm/base/models/common/utilities.js.map +1 -1
- package/dist/esm/base/repositories/common/types/results.d.ts +15 -7
- package/dist/esm/base/repositories/common/types/results.d.ts.map +1 -1
- package/dist/esm/base/repositories/common/types/results.js +16 -7
- package/dist/esm/base/repositories/common/types/results.js.map +1 -1
- package/dist/esm/base/repositories/core/abstract.d.ts.map +1 -1
- package/dist/esm/base/repositories/core/abstract.js +5 -3
- package/dist/esm/base/repositories/core/abstract.js.map +1 -1
- package/dist/esm/base/repositories/query-schemas/index.d.ts +1 -1
- package/dist/esm/base/repositories/query-schemas/index.d.ts.map +1 -1
- package/dist/esm/base/repositories/query-schemas/index.js +3 -3
- package/dist/esm/base/repositories/query-schemas/index.js.map +1 -1
- package/dist/esm/helpers/inversion/common/relation-builder.js.map +1 -1
- package/dist/esm/helpers/inversion/index.d.ts +1 -1
- package/dist/esm/helpers/inversion/index.d.ts.map +1 -1
- package/dist/esm/helpers/inversion/index.js +1 -1
- package/dist/esm/helpers/inversion/index.js.map +1 -1
- package/dist/esm/helpers/inversion/mixins/repository.mixin.d.ts.map +1 -1
- package/dist/esm/helpers/inversion/mixins/repository.mixin.js +5 -5
- package/dist/esm/helpers/inversion/mixins/repository.mixin.js.map +1 -1
- package/dist/esm/metadata.d.ts +1 -1
- package/dist/esm/metadata.d.ts.map +1 -1
- package/dist/esm/metadata.js +1 -1
- package/dist/esm/metadata.js.map +1 -1
- package/dist/esm/repository.d.ts +2 -2
- package/dist/esm/repository.d.ts.map +1 -1
- package/dist/esm/repository.js +2 -2
- package/dist/esm/repository.js.map +1 -1
- package/dist/esm/utilities/index.d.ts +1 -1
- package/dist/esm/utilities/index.d.ts.map +1 -1
- package/dist/esm/utilities/index.js +1 -1
- package/dist/esm/utilities/index.js.map +1 -1
- package/dist/esm/utilities/not-supported.utility.d.ts +11 -0
- package/dist/esm/utilities/not-supported.utility.d.ts.map +1 -0
- package/dist/esm/utilities/not-supported.utility.js +19 -0
- package/dist/esm/utilities/not-supported.utility.js.map +1 -0
- package/package.json +6 -7
- package/dist/esm/base/controllers/common/html-response.d.ts +0 -70
- package/dist/esm/base/controllers/common/html-response.d.ts.map +0 -1
- package/dist/esm/base/controllers/common/html-response.js +0 -30
- package/dist/esm/base/controllers/common/html-response.js.map +0 -1
- package/dist/esm/base/controllers/factory/authorize-guard.d.ts +0 -19
- package/dist/esm/base/controllers/factory/authorize-guard.d.ts.map +0 -1
- package/dist/esm/base/controllers/factory/authorize-guard.js +0 -56
- package/dist/esm/base/controllers/factory/authorize-guard.js.map +0 -1
- package/dist/esm/base/controllers/factory/helper.d.ts +0 -2
- package/dist/esm/base/controllers/factory/helper.d.ts.map +0 -1
- package/dist/esm/base/controllers/factory/helper.js +0 -2
- package/dist/esm/base/controllers/factory/helper.js.map +0 -1
- package/dist/esm/base/controllers/factory/repository-injection.d.ts +0 -14
- package/dist/esm/base/controllers/factory/repository-injection.d.ts.map +0 -1
- package/dist/esm/base/controllers/factory/repository-injection.js +0 -27
- package/dist/esm/base/controllers/factory/repository-injection.js.map +0 -1
- package/dist/esm/base/metadata/model-settings.d.ts +0 -11
- package/dist/esm/base/metadata/model-settings.d.ts.map +0 -1
- package/dist/esm/base/metadata/model-settings.js +0 -30
- package/dist/esm/base/metadata/model-settings.js.map +0 -1
- package/dist/esm/utilities/error.utility.d.ts +0 -8
- package/dist/esm/utilities/error.utility.d.ts.map +0 -1
- package/dist/esm/utilities/error.utility.js +0 -14
- package/dist/esm/utilities/error.utility.js.map +0 -1
|
@@ -1,46 +1,49 @@
|
|
|
1
1
|
import { AuthorizationDomainScopes, AuthorizationDomainSources } from '../common/constants/index.js';
|
|
2
|
-
/**
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
/** Reads the domain of an authorization check off the request. */
|
|
3
|
+
export class RequestDomainResolver {
|
|
4
|
+
/** Read a domain value from a declarative source on the Hono context. */
|
|
5
|
+
static readDeclarative(opts) {
|
|
6
|
+
const { source, context } = opts;
|
|
7
|
+
switch (source.from) {
|
|
8
|
+
case AuthorizationDomainSources.PARAM: {
|
|
9
|
+
return context.req.param(source.key) ?? null;
|
|
10
|
+
}
|
|
11
|
+
case AuthorizationDomainSources.HEADER: {
|
|
12
|
+
return context.req.header(source.key) ?? null;
|
|
13
|
+
}
|
|
14
|
+
case AuthorizationDomainSources.QUERY: {
|
|
15
|
+
return context.req.query(source.key) ?? null;
|
|
16
|
+
}
|
|
17
|
+
case AuthorizationDomainSources.CONTEXT: {
|
|
18
|
+
const value = context.get(source.key);
|
|
19
|
+
return value == null ? null : String(value);
|
|
20
|
+
}
|
|
21
|
+
default: {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
8
24
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
25
|
+
}
|
|
26
|
+
/** Resolve the request domain, precedence spec.domain (method | declarative) -> options.domainResolver -> SYSTEM_WIDE, as a casbin domain string ("<type>_<id>") or the SYSTEM_WIDE sentinel. */
|
|
27
|
+
static async resolveRequestDomain(opts) {
|
|
28
|
+
const { spec, context, options } = opts;
|
|
29
|
+
if (typeof spec.domain === 'function') {
|
|
30
|
+
const resolved = await spec.domain({ context });
|
|
31
|
+
return resolved
|
|
32
|
+
? [resolved.type, resolved.id].join('_')
|
|
33
|
+
: AuthorizationDomainScopes.SYSTEM_WIDE;
|
|
14
34
|
}
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
return
|
|
35
|
+
if (spec.domain) {
|
|
36
|
+
const id = RequestDomainResolver.readDeclarative({ source: spec.domain, context });
|
|
37
|
+
return id ? [spec.domain.type, id].join('_') : AuthorizationDomainScopes.SYSTEM_WIDE;
|
|
18
38
|
}
|
|
19
|
-
|
|
20
|
-
|
|
39
|
+
const globalResolver = options?.domainResolver ?? null;
|
|
40
|
+
if (globalResolver) {
|
|
41
|
+
const resolved = await globalResolver({ context });
|
|
42
|
+
return resolved
|
|
43
|
+
? [resolved.type, resolved.id].join('_')
|
|
44
|
+
: AuthorizationDomainScopes.SYSTEM_WIDE;
|
|
21
45
|
}
|
|
46
|
+
return AuthorizationDomainScopes.SYSTEM_WIDE;
|
|
22
47
|
}
|
|
23
|
-
}
|
|
24
|
-
/** Resolve the request domain, precedence spec.domain (method | declarative) -> options.domainResolver -> SYSTEM_WIDE, as a casbin domain string ("<type>_<id>") or the SYSTEM_WIDE sentinel. */
|
|
25
|
-
export const resolveRequestDomain = async (opts) => {
|
|
26
|
-
const { spec, context, options } = opts;
|
|
27
|
-
if (typeof spec.domain === 'function') {
|
|
28
|
-
const resolved = await spec.domain({ context });
|
|
29
|
-
return resolved
|
|
30
|
-
? [resolved.type, resolved.id].join('_')
|
|
31
|
-
: AuthorizationDomainScopes.SYSTEM_WIDE;
|
|
32
|
-
}
|
|
33
|
-
if (spec.domain) {
|
|
34
|
-
const id = readDeclarative({ source: spec.domain, context });
|
|
35
|
-
return id ? [spec.domain.type, id].join('_') : AuthorizationDomainScopes.SYSTEM_WIDE;
|
|
36
|
-
}
|
|
37
|
-
const globalResolver = options?.domainResolver ?? null;
|
|
38
|
-
if (globalResolver) {
|
|
39
|
-
const resolved = await globalResolver({ context });
|
|
40
|
-
return resolved
|
|
41
|
-
? [resolved.type, resolved.id].join('_')
|
|
42
|
-
: AuthorizationDomainScopes.SYSTEM_WIDE;
|
|
43
|
-
}
|
|
44
|
-
return AuthorizationDomainScopes.SYSTEM_WIDE;
|
|
45
|
-
};
|
|
48
|
+
}
|
|
46
49
|
//# sourceMappingURL=request-domain.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-domain.js","sourceRoot":"","sources":["../../../../../../src/base/auth/authorize/providers/request-domain.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAO5F,
|
|
1
|
+
{"version":3,"file":"request-domain.js","sourceRoot":"","sources":["../../../../../../src/base/auth/authorize/providers/request-domain.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAO5F,kEAAkE;AAClE,MAAM,OAAO,qBAAqB;IAChC,yEAAyE;IACzE,MAAM,CAAC,eAAe,CAAC,IAGtB;QACC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QACjC,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;YACpB,KAAK,0BAA0B,CAAC,KAAK,CAAC,CAAC,CAAC;gBACtC,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;YAC/C,CAAC;YACD,KAAK,0BAA0B,CAAC,MAAM,CAAC,CAAC,CAAC;gBACvC,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;YAChD,CAAC;YACD,KAAK,0BAA0B,CAAC,KAAK,CAAC,CAAC,CAAC;gBACtC,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;YAC/C,CAAC;YACD,KAAK,0BAA0B,CAAC,OAAO,CAAC,CAAC,CAAC;gBACxC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAU,CAAC,CAAC;gBAC7C,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC9C,CAAC;YACD,OAAO,CAAC,CAAC,CAAC;gBACR,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAED,iMAAiM;IACjM,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,IAIjC;QACC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QAExC,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YACtC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;YAChD,OAAO,QAAQ;gBACb,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;gBACxC,CAAC,CAAC,yBAAyB,CAAC,WAAW,CAAC;QAC5C,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,EAAE,GAAG,qBAAqB,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;YACnF,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,yBAAyB,CAAC,WAAW,CAAC;QACvF,CAAC;QAED,MAAM,cAAc,GAAG,OAAO,EAAE,cAAc,IAAI,IAAI,CAAC;QACvD,IAAI,cAAc,EAAE,CAAC;YACnB,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;YACnD,OAAO,QAAQ;gBACb,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;gBACxC,CAAC,CAAC,yBAAyB,CAAC,WAAW,CAAC;QAC5C,CAAC;QAED,OAAO,yBAAyB,CAAC,WAAW,CAAC;IAC/C,CAAC;CACF","sourcesContent":["import type { TContext } from '@/base/controllers/common/types';\nimport type { TNullable } from '@venizia/ignis-helpers/common';\nimport type { Env } from 'hono';\nimport { AuthorizationDomainScopes, AuthorizationDomainSources } from '../common/constants';\nimport type {\n IAuthorizationDomainSource,\n IAuthorizationSpec,\n IAuthorizeOptions,\n} from '../common/types';\n\n/** Reads the domain of an authorization check off the request. */\nexport class RequestDomainResolver {\n /** Read a domain value from a declarative source on the Hono context. */\n static readDeclarative(opts: {\n source: IAuthorizationDomainSource;\n context: TContext<Env, string>;\n }): TNullable<string> {\n const { source, context } = opts;\n switch (source.from) {\n case AuthorizationDomainSources.PARAM: {\n return context.req.param(source.key) ?? null;\n }\n case AuthorizationDomainSources.HEADER: {\n return context.req.header(source.key) ?? null;\n }\n case AuthorizationDomainSources.QUERY: {\n return context.req.query(source.key) ?? null;\n }\n case AuthorizationDomainSources.CONTEXT: {\n const value = context.get(source.key as any);\n return value == null ? null : String(value);\n }\n default: {\n return null;\n }\n }\n }\n\n /** Resolve the request domain, precedence spec.domain (method | declarative) -> options.domainResolver -> SYSTEM_WIDE, as a casbin domain string (\"<type>_<id>\") or the SYSTEM_WIDE sentinel. */\n static async resolveRequestDomain(opts: {\n spec: IAuthorizationSpec;\n context: TContext<Env, string>;\n options: TNullable<IAuthorizeOptions>;\n }): Promise<string> {\n const { spec, context, options } = opts;\n\n if (typeof spec.domain === 'function') {\n const resolved = await spec.domain({ context });\n return resolved\n ? [resolved.type, resolved.id].join('_')\n : AuthorizationDomainScopes.SYSTEM_WIDE;\n }\n\n if (spec.domain) {\n const id = RequestDomainResolver.readDeclarative({ source: spec.domain, context });\n return id ? [spec.domain.type, id].join('_') : AuthorizationDomainScopes.SYSTEM_WIDE;\n }\n\n const globalResolver = options?.domainResolver ?? null;\n if (globalResolver) {\n const resolved = await globalResolver({ context });\n return resolved\n ? [resolved.type, resolved.id].join('_')\n : AuthorizationDomainScopes.SYSTEM_WIDE;\n }\n\n return AuthorizationDomainScopes.SYSTEM_WIDE;\n }\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ObjectUtility } from '@venizia/ignis-helpers/common';
|
|
2
2
|
import { BindingScopes } from '@venizia/ignis-inversion';
|
|
3
3
|
import { BaseHelper, getError } from '@venizia/ignis-helpers/core';
|
|
4
4
|
export class AbstractAuthRegistry extends BaseHelper {
|
|
@@ -7,7 +7,7 @@ export class AbstractAuthRegistry extends BaseHelper {
|
|
|
7
7
|
this.descriptors = new Map();
|
|
8
8
|
}
|
|
9
9
|
getKey(opts) {
|
|
10
|
-
if (!opts?.name || isEmpty({ value: opts.name })) {
|
|
10
|
+
if (!opts?.name || ObjectUtility.isEmpty({ value: opts.name })) {
|
|
11
11
|
throw getError({ message: `[getKey] Invalid name | name: ${opts.name}` });
|
|
12
12
|
}
|
|
13
13
|
return [this.getBindingPrefix(), opts.name].join('.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abstract-auth-registry.js","sourceRoot":"","sources":["../../../../../src/base/auth/base/abstract-auth-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"abstract-auth-registry.js","sourceRoot":"","sources":["../../../../../src/base/auth/base/abstract-auth-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAGzD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAOnE,MAAM,OAAgB,oBAA4B,SAAQ,UAAU;IAGlE,YAAY,IAAuB;QACjC,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,CAAC,WAAW,GAAG,IAAI,GAAG,EAAE,CAAC;IAC/B,CAAC;IAID,MAAM,CAAC,IAAsB;QAC3B,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAC/D,MAAM,QAAQ,CAAC,EAAE,OAAO,EAAE,iCAAiC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC5E,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxD,CAAC;IAED;;;;OAIG;IACH,GAAG,CAAC,IAAsB;QACxB,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,8FAA8F;IAC9F,QAAQ;QACN,OAAO,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,cAAc;QACZ,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;QACvD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,QAAQ,CAAC;gBACb,OAAO,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,uBAAuB;aAC1D,CAAC,CAAC;QACL,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAES,kBAAkB,CAAC,IAI5B;QACC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;QAEzC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;QAC/D,SAAS;aACN,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;aACpC,OAAO,CAAC,MAAM,CAAC;aACf,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;IAES,iBAAiB,CAAC,IAAsB;QAChD,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;QACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAE5C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,QAAQ,CAAC;gBACb,OAAO,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,2BAA2B,IAAI,EAAE;aACpE,CAAC,CAAC;QACL,CAAC;QAED,MAAM,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAC;QAC/B,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAQ;YACpC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC;SAC3B,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,QAAQ,CAAC;gBACb,OAAO,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,wBAAwB,IAAI,EAAE;aACjE,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF","sourcesContent":["import { ObjectUtility } from '@venizia/ignis-helpers/common';\nimport { BindingScopes } from '@venizia/ignis-inversion';\nimport type { Container } from '@/helpers/inversion/container';\nimport type { TClass } from '@venizia/ignis-helpers/common';\nimport { BaseHelper, getError } from '@venizia/ignis-helpers/core';\n\nexport type TRegistryDescriptor<TItem> = {\n container: Container;\n targetClass: TClass<TItem>;\n};\n\nexport abstract class AbstractAuthRegistry<TItem> extends BaseHelper {\n protected descriptors: Map<string, TRegistryDescriptor<TItem>>;\n\n constructor(opts: { scope: string }) {\n super(opts);\n this.descriptors = new Map();\n }\n\n protected abstract getBindingPrefix(): string;\n\n getKey(opts: { name: string }): string {\n if (!opts?.name || ObjectUtility.isEmpty({ value: opts.name })) {\n throw getError({ message: `[getKey] Invalid name | name: ${opts.name}` });\n }\n\n return [this.getBindingPrefix(), opts.name].join('.');\n }\n\n /**\n * Whether a name resolves. The registry is the only source of truth for that: the strategy type is\n * open (`TAuthStrategy` accepts any string), so nothing upstream can tell a registered name from a\n * typo. `AuthenticateStrategy.isValid` knows the two built-ins only and must not be used here.\n */\n has(opts: { name: string }): boolean {\n return this.descriptors.has(opts.name);\n }\n\n /** Every registered name, for a caller building its own startup check or an error message. */\n getNames(): string[] {\n return [...this.descriptors.keys()];\n }\n\n getDefaultName(): string {\n const firstName = this.descriptors.keys().next().value;\n if (!firstName) {\n throw getError({\n message: `[${this.constructor.name}] No items registered`,\n });\n }\n return firstName;\n }\n\n protected registerDescriptor(opts: {\n container: Container;\n target: TClass<TItem>;\n name: string;\n }): void {\n const { container, target, name } = opts;\n\n this.descriptors.set(name, { container, targetClass: target });\n container\n .bind({ key: this.getKey({ name }) })\n .toClass(target)\n .setScope(BindingScopes.SINGLETON);\n }\n\n reset(): void {\n this.descriptors.clear();\n }\n\n protected resolveDescriptor(opts: { name: string }): TItem {\n const { name } = opts;\n const metadata = this.descriptors.get(name);\n\n if (!metadata) {\n throw getError({\n message: `[${this.constructor.name}] Descriptor not found: ${name}`,\n });\n }\n\n const { container } = metadata;\n const instance = container.get<TItem>({\n key: this.getKey({ name }),\n });\n\n if (!instance) {\n throw getError({\n message: `[${this.constructor.name}] Failed to resolve: ${name}`,\n });\n }\n\n return instance;\n }\n}\n"]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OpenApiSchemas } from '../../../models/common/index.js';
|
|
2
2
|
import { z } from '@hono/zod-openapi';
|
|
3
3
|
export const ChangePasswordRequestSchema = z
|
|
4
4
|
.object({
|
|
5
5
|
scheme: z.string(),
|
|
6
|
-
oldCredential: requiredString({ min: 8 }),
|
|
7
|
-
newCredential: requiredString({ min: 8 }),
|
|
6
|
+
oldCredential: OpenApiSchemas.requiredString({ min: 8 }),
|
|
7
|
+
newCredential: OpenApiSchemas.requiredString({ min: 8 }),
|
|
8
8
|
userId: z.string().or(z.number()),
|
|
9
9
|
})
|
|
10
10
|
.openapi({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"change-password.schema.js","sourceRoot":"","sources":["../../../../../../src/base/auth/models/requests/change-password.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"change-password.schema.js","sourceRoot":"","sources":["../../../../../../src/base/auth/models/requests/change-password.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAEtC,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC;KACzC,MAAM,CAAC;IACN,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,aAAa,EAAE,cAAc,CAAC,cAAc,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IACxD,aAAa,EAAE,cAAc,CAAC,cAAc,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IACxD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;CAClC,CAAC;KACD,OAAO,CAAC;IACP,QAAQ,EAAE;QACR;YACE,MAAM,EAAE,OAAO;YACf,aAAa,EAAE,cAAc;YAC7B,aAAa,EAAE,cAAc;YAC7B,MAAM,EAAE,SAAS;SAClB;KACF;CACF,CAAC,CAAC","sourcesContent":["import { OpenApiSchemas } from '@/base/models/common';\nimport { z } from '@hono/zod-openapi';\n\nexport const ChangePasswordRequestSchema = z\n .object({\n scheme: z.string(),\n oldCredential: OpenApiSchemas.requiredString({ min: 8 }),\n newCredential: OpenApiSchemas.requiredString({ min: 8 }),\n userId: z.string().or(z.number()),\n })\n .openapi({\n examples: [\n {\n scheme: 'basic',\n oldCredential: 'old_password',\n newCredential: 'new_password',\n userId: 'user-id',\n },\n ],\n });\n\nexport type TChangePasswordRequest = z.infer<typeof ChangePasswordRequestSchema>;\n"]}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OpenApiSchemas } from '../../../models/common/index.js';
|
|
2
2
|
import { z } from '@hono/zod-openapi';
|
|
3
3
|
export const SignInRequestSchema = z
|
|
4
4
|
.object({
|
|
5
5
|
identifier: z
|
|
6
6
|
.object({
|
|
7
|
-
scheme: requiredString({ min: 4 }),
|
|
8
|
-
value: requiredString({ min: 8 }),
|
|
7
|
+
scheme: OpenApiSchemas.requiredString({ min: 4 }),
|
|
8
|
+
value: OpenApiSchemas.requiredString({ min: 8 }),
|
|
9
9
|
})
|
|
10
10
|
.openapi({
|
|
11
11
|
required: ['scheme', 'value'],
|
|
@@ -13,8 +13,8 @@ export const SignInRequestSchema = z
|
|
|
13
13
|
}),
|
|
14
14
|
credential: z
|
|
15
15
|
.object({
|
|
16
|
-
scheme: requiredString(),
|
|
17
|
-
value: requiredString({ min: 8 }),
|
|
16
|
+
scheme: OpenApiSchemas.requiredString(),
|
|
17
|
+
value: OpenApiSchemas.requiredString({ min: 8 }),
|
|
18
18
|
})
|
|
19
19
|
.openapi({
|
|
20
20
|
required: ['scheme', 'value'],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sign-in.schema.js","sourceRoot":"","sources":["../../../../../../src/base/auth/models/requests/sign-in.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"sign-in.schema.js","sourceRoot":"","sources":["../../../../../../src/base/auth/models/requests/sign-in.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAEtC,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC;KACjC,MAAM,CAAC;IACN,UAAU,EAAE,CAAC;SACV,MAAM,CAAC;QACN,MAAM,EAAE,cAAc,CAAC,cAAc,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;QACjD,KAAK,EAAE,cAAc,CAAC,cAAc,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;KACjD,CAAC;SACD,OAAO,CAAC;QACP,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC;QAC7B,WAAW,EAAE,oBAAoB;KAClC,CAAC;IACJ,UAAU,EAAE,CAAC;SACV,MAAM,CAAC;QACN,MAAM,EAAE,cAAc,CAAC,cAAc,EAAE;QACvC,KAAK,EAAE,cAAc,CAAC,cAAc,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;KACjD,CAAC;SACD,OAAO,CAAC;QACP,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC;QAC7B,WAAW,EAAE,oBAAoB;KAClC,CAAC;IACJ,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC;QACtC,WAAW,EAAE,uBAAuB;KACrC,CAAC;CACH,CAAC;KACD,OAAO,CAAC;IACP,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC;IACtC,QAAQ,EAAE;QACR;YACE,UAAU,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,eAAe,EAAE;YAC1D,UAAU,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE;SACxD;QACD;YACE,UAAU,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,eAAe,EAAE;YAC1D,UAAU,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE;YACvD,QAAQ,EAAE,eAAe;SAC1B;KACF;CACF,CAAC,CAAC","sourcesContent":["import { OpenApiSchemas } from '@/base/models/common';\nimport { z } from '@hono/zod-openapi';\n\nexport const SignInRequestSchema = z\n .object({\n identifier: z\n .object({\n scheme: OpenApiSchemas.requiredString({ min: 4 }),\n value: OpenApiSchemas.requiredString({ min: 8 }),\n })\n .openapi({\n required: ['scheme', 'value'],\n description: 'Sign-In Identifier',\n }),\n credential: z\n .object({\n scheme: OpenApiSchemas.requiredString(),\n value: OpenApiSchemas.requiredString({ min: 8 }),\n })\n .openapi({\n required: ['scheme', 'value'],\n description: 'Sign-In Credential',\n }),\n clientId: z.string().optional().openapi({\n description: 'Authenticate Provider',\n }),\n })\n .openapi({\n required: ['identifier', 'credential'],\n examples: [\n {\n identifier: { scheme: 'username', value: 'test_username' },\n credential: { scheme: 'basic', value: 'test_password' },\n },\n {\n identifier: { scheme: 'username', value: 'test_username' },\n credential: { scheme: 'basic', value: 'test_password' },\n clientId: 'auth-provider',\n },\n ],\n });\n\nexport type TSignInRequest = z.infer<typeof SignInRequestSchema>;\n"]}
|
|
@@ -3,7 +3,7 @@ import { BindingNamespaces } from '../../../../common/bindings.js';
|
|
|
3
3
|
import { Binding, BindingValueTypes, MetadataRegistry } from '../../../../helpers/inversion/index.js';
|
|
4
4
|
import { BaseComponent } from '../../base.js';
|
|
5
5
|
import { getError } from '@venizia/ignis-helpers/core';
|
|
6
|
-
import { HTTP,
|
|
6
|
+
import { HTTP, ObjectUtility } from '@venizia/ignis-helpers/common';
|
|
7
7
|
import { RestBindingKeys } from './common/types.js';
|
|
8
8
|
const DEFAULT_OPTIONS = {};
|
|
9
9
|
/**
|
|
@@ -42,7 +42,7 @@ export class RestComponent extends BaseComponent {
|
|
|
42
42
|
if (metadata?.transport === ControllerTransports.GRPC) {
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
|
-
if (!metadata?.path || isEmpty({ value: metadata.path })) {
|
|
45
|
+
if (!metadata?.path || ObjectUtility.isEmpty({ value: metadata.path })) {
|
|
46
46
|
throw getError({
|
|
47
47
|
statusCode: HTTP.ResultCodes.RS_5.InternalServerError,
|
|
48
48
|
message: `[registerControllers] key: '${binding.key}' | Invalid controller metadata, 'path' is required for controller metadata`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rest.component.js","sourceRoot":"","sources":["../../../../../../src/base/components/controller/rest/rest.component.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAE3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"rest.component.js","sourceRoot":"","sources":["../../../../../../src/base/components/controller/rest/rest.component.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RestApplication } from '@/base/applications/rest';\nimport { ControllerTransports } from '@/base/controllers/common/constants';\nimport type { AbstractRestController } from '@/base/controllers/rest/abstract';\nimport { BindingNamespaces } from '@/common/bindings';\nimport { Binding, BindingValueTypes, MetadataRegistry } from '@/helpers/inversion';\nimport { BaseComponent } from '../../base';\nimport type { Env, Schema } from 'hono';\nimport { getError } from '@venizia/ignis-helpers/core';\nimport { HTTP, ObjectUtility } from '@venizia/ignis-helpers/common';\nimport type { IRestComponentConfig } from './common/types';\nimport { RestBindingKeys } from './common/types';\n\nconst DEFAULT_OPTIONS: IRestComponentConfig = {};\n\n/**\n * Generic over the same Hono env/schema/base-path `RestApplication` is: a bare `RestApplication`\n * parameter (defaulting to `RestApplication<Env, {}, '/'>`) fails to typecheck when passed `this`\n * from inside a differently-instantiated generic `RestApplication` subclass - `defaultHook`'s\n * contravariance makes the defaulted instantiation incompatible with an arbitrary one. Matching the\n * caller's own instantiation here removes the mismatch instead of widening to `any`.\n */\nexport class RestComponent<\n AppEnv extends Env = Env,\n AppSchema extends Schema = {},\n BasePath extends string = '/',\n> extends BaseComponent {\n constructor(private application: RestApplication<AppEnv, AppSchema, BasePath>) {\n super({\n scope: RestComponent.name,\n initDefault: { enable: true, container: application },\n bindings: {\n [RestBindingKeys.REST_COMPONENT_OPTIONS]: Binding.bind<IRestComponentConfig>({\n key: RestBindingKeys.REST_COMPONENT_OPTIONS,\n }).toValue(DEFAULT_OPTIONS),\n },\n });\n }\n\n override async binding(): Promise<void> {\n const logger = this.logger.for(this.binding.name);\n const router = this.application.getRootRouter();\n\n await this.application.drainByTag<AbstractRestController>({\n tag: BindingNamespaces.CONTROLLER,\n configured: new Set<string>(),\n onEach: async ({ binding }) => {\n const target = binding.getBindingMeta({ type: BindingValueTypes.CLASS });\n if (!target) {\n return;\n }\n\n const metadata = MetadataRegistry.getInstance().getControllerMetadata({ target });\n\n // Skip gRPC controllers - they are configured by GrpcComponent\n if (metadata?.transport === ControllerTransports.GRPC) {\n return;\n }\n\n if (!metadata?.path || ObjectUtility.isEmpty({ value: metadata.path })) {\n throw getError({\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n message: `[registerControllers] key: '${binding.key}' | Invalid controller metadata, 'path' is required for controller metadata`,\n });\n }\n\n const instance = this.application.get<AbstractRestController>({\n key: binding.key,\n isOptional: false,\n });\n\n if (!instance) {\n logger.debug('No binding instance | key: %s', binding.key);\n return;\n }\n\n await instance.configure();\n router.route(metadata.path, instance.getRouter());\n\n logger.info('Configured REST controller | key: %s | path: %s', binding.key, metadata.path);\n },\n });\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/base/controllers/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAE5B,cAAc,WAAW,CAAC;AAC1B,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/base/controllers/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAE5B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,SAAS,CAAC"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export * from './constants.js';
|
|
2
2
|
// Carries zod. Kept out of `constants.ts` so importing `Container` does not pull zod into a bundle.
|
|
3
3
|
export * from './schemas.js';
|
|
4
|
-
export * from './html-response.js';
|
|
5
4
|
export * from './schema-builders.js';
|
|
6
5
|
export * from './types/index.js';
|
|
7
6
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/base/controllers/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,oGAAoG;AACpG,cAAc,WAAW,CAAC;AAC1B,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/base/controllers/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,oGAAoG;AACpG,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,SAAS,CAAC","sourcesContent":["export * from './constants';\n// Carries zod. Kept out of `constants.ts` so importing `Container` does not pull zod into a bundle.\nexport * from './schemas';\nexport * from './schema-builders';\nexport * from './types';\n"]}
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import { z } from '@hono/zod-openapi';
|
|
2
|
-
export declare const requiredString: (opts?: {
|
|
3
|
-
min?: number;
|
|
4
|
-
max?: number;
|
|
5
|
-
fixed?: number;
|
|
6
|
-
}) => z.ZodString;
|
|
7
2
|
export declare const AnyObjectSchema: z.ZodObject<{}, z.core.$catchall<z.ZodAny>>;
|
|
8
3
|
export type TAnyObjectSchema = z.ZodObject<z.ZodRawShape>;
|
|
9
4
|
export type TInferSchema<T extends z.ZodType> = z.infer<T>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-builders.d.ts","sourceRoot":"","sources":["../../../../../src/base/controllers/common/schema-builders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAEtC,eAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"schema-builders.d.ts","sourceRoot":"","sources":["../../../../../src/base/controllers/common/schema-builders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAEtC,eAAO,MAAM,eAAe,6CAE1B,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;AAC1D,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -1,18 +1,4 @@
|
|
|
1
1
|
import { z } from '@hono/zod-openapi';
|
|
2
|
-
export const requiredString = (opts) => {
|
|
3
|
-
const { min, max, fixed } = opts ?? {};
|
|
4
|
-
let rs = z.string().nonempty();
|
|
5
|
-
if (min) {
|
|
6
|
-
rs = rs.min(min);
|
|
7
|
-
}
|
|
8
|
-
if (max) {
|
|
9
|
-
rs = rs.max(max);
|
|
10
|
-
}
|
|
11
|
-
if (fixed) {
|
|
12
|
-
rs = rs.length(fixed);
|
|
13
|
-
}
|
|
14
|
-
return rs;
|
|
15
|
-
};
|
|
16
2
|
export const AnyObjectSchema = z.object().catchall(z.any()).openapi({
|
|
17
3
|
description: 'Unknown schema',
|
|
18
4
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-builders.js","sourceRoot":"","sources":["../../../../../src/base/controllers/common/schema-builders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAEtC,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"schema-builders.js","sourceRoot":"","sources":["../../../../../src/base/controllers/common/schema-builders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAEtC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC;IAClE,WAAW,EAAE,gBAAgB;CAC9B,CAAC,CAAC","sourcesContent":["import { z } from '@hono/zod-openapi';\n\nexport const AnyObjectSchema = z.object().catchall(z.any()).openapi({\n description: 'Unknown schema',\n});\n\nexport type TAnyObjectSchema = z.ZodObject<z.ZodRawShape>;\nexport type TInferSchema<T extends z.ZodType> = z.infer<T>;\n"]}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { TContext } from './common/types/index.js';
|
|
2
2
|
import type { Env } from 'hono';
|
|
3
|
-
/** Casts
|
|
4
|
-
export declare
|
|
3
|
+
/** Casts of the Hono context that the types cannot prove. */
|
|
4
|
+
export declare class ContextUtility {
|
|
5
|
+
/** Casts middleware context to TContext (safe -- structurally identical to Context). */
|
|
6
|
+
static asTypedContext<E extends Env>(opts: {
|
|
7
|
+
context: unknown;
|
|
8
|
+
}): TContext<E, string>;
|
|
9
|
+
}
|
|
5
10
|
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/base/controllers/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAEhC,wFAAwF;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/base/controllers/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAEhC,6DAA6D;AAC7D,qBAAa,cAAc;IACzB,wFAAwF;IACxF,MAAM,CAAC,cAAc,CAAC,CAAC,SAAS,GAAG,EAAE,IAAI,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CAGtF"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
/** Casts
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/** Casts of the Hono context that the types cannot prove. */
|
|
2
|
+
export class ContextUtility {
|
|
3
|
+
/** Casts middleware context to TContext (safe -- structurally identical to Context). */
|
|
4
|
+
static asTypedContext(opts) {
|
|
5
|
+
return opts.context;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
5
8
|
//# sourceMappingURL=context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../src/base/controllers/context.ts"],"names":[],"mappings":"AAGA,wFAAwF;
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../src/base/controllers/context.ts"],"names":[],"mappings":"AAGA,6DAA6D;AAC7D,MAAM,OAAO,cAAc;IACzB,wFAAwF;IACxF,MAAM,CAAC,cAAc,CAAgB,IAA0B;QAC7D,OAAO,IAAI,CAAC,OAA8B,CAAC;IAC7C,CAAC;CACF","sourcesContent":["import type { TContext } from './common/types';\nimport type { Env } from 'hono';\n\n/** Casts of the Hono context that the types cannot prove. */\nexport class ContextUtility {\n /** Casts middleware context to TContext (safe -- structurally identical to Context). */\n static asTypedContext<E extends Env>(opts: { context: unknown }): TContext<E, string> {\n return opts.context as TContext<E, string>;\n }\n}\n"]}
|
|
@@ -1,13 +1,28 @@
|
|
|
1
|
+
import type { IAuthorizationSpec } from '../../auth/authorize/common/types/index.js';
|
|
1
2
|
import type { AbstractEntity } from '../../models/index.js';
|
|
2
3
|
import type { AbstractRepository } from '../../repositories/index.js';
|
|
3
4
|
import type { TAnyObjectSchema } from '../common/schema-builders.js';
|
|
4
|
-
import type { AnyType, ValueOrPromise } from '@venizia/ignis-helpers/common';
|
|
5
|
+
import type { AnyType, TClass, ValueOrPromise } from '@venizia/ignis-helpers/common';
|
|
5
6
|
import { BaseHelper } from '@venizia/ignis-helpers/core';
|
|
6
7
|
import type { Env, Schema } from 'hono';
|
|
7
8
|
import type { ICrudControllerOptions, ICustomizableRoutes, TEntityDataObject, TEntityPersistObject } from '../common/index.js';
|
|
8
9
|
/** Factory for generating typed CRUD controllers from entity definitions. */
|
|
9
10
|
export declare class ControllerFactory extends BaseHelper {
|
|
11
|
+
/** The generated routes that change data: the ones that must never be answered by a `read` permission. */
|
|
12
|
+
private static readonly WRITE_VERBS;
|
|
10
13
|
constructor();
|
|
14
|
+
/**
|
|
15
|
+
* Injects `repositories.<repositoryName>` into constructor parameter 0 of a factory-generated
|
|
16
|
+
* controller, so a subclass needs no constructor. Recorded as metadata rather than a parameter
|
|
17
|
+
* decorator, which Bun drops in some configurations. A subclass that declares its own `@inject` at
|
|
18
|
+
* index 0 wins, and a sibling subclass keeps the factory's key.
|
|
19
|
+
*/
|
|
20
|
+
static registerRepositoryInjection(opts: {
|
|
21
|
+
target: TClass<unknown>;
|
|
22
|
+
factoryName: string;
|
|
23
|
+
controllerName: string;
|
|
24
|
+
repositoryName: string;
|
|
25
|
+
}): void;
|
|
11
26
|
static defineCrudController<TEntity extends AbstractEntity<TAnyObjectSchema> = AbstractEntity<TAnyObjectSchema>, Routes extends ICustomizableRoutes = ICustomizableRoutes, RouteEnv extends Env = Env, RouteSchema extends Schema = {}, BasePath extends string = '/', ConfigurableOptions extends object = {}, TDataObject extends object = TEntityDataObject<TEntity>, TPersistObject extends object = TEntityPersistObject<TEntity>>(defOpts: ICrudControllerOptions<TEntity, Routes>): {
|
|
12
27
|
new (repository: AbstractRepository<TDataObject, TPersistObject, AnyType>): {
|
|
13
28
|
/** Registers each CRUD route whose handler tier supplies it, honoring enabledRoutes/readonly. */
|
|
@@ -206,5 +221,22 @@ export declare class ControllerFactory extends BaseHelper {
|
|
|
206
221
|
getLogger(): import("@venizia/ignis-helpers/core").ILogger;
|
|
207
222
|
};
|
|
208
223
|
};
|
|
224
|
+
private static describeSpec;
|
|
225
|
+
/**
|
|
226
|
+
* Refuses a CRUD controller whose enabled write verb would inherit a controller-level `authorize`
|
|
227
|
+
* that is only a `read` permission: the verb would then answer to anyone who may read.
|
|
228
|
+
*
|
|
229
|
+
* A write verb is fine when it declares its own `authorize` (a spec, an array, or `{ skip: true }`),
|
|
230
|
+
* skips authentication, is not enabled, or the controller is `readonly`. Only the literal action
|
|
231
|
+
* `read` is detected; a custom action name is the application's own vocabulary. An array counts when
|
|
232
|
+
* every spec in it is `read`, since the specs of one route must all pass.
|
|
233
|
+
*/
|
|
234
|
+
static assertWriteVerbsDeclareAuthorize(opts: {
|
|
235
|
+
controllerName: string;
|
|
236
|
+
authorize: IAuthorizationSpec | IAuthorizationSpec[] | undefined;
|
|
237
|
+
routes: ICustomizableRoutes | undefined;
|
|
238
|
+
readonly: boolean | undefined;
|
|
239
|
+
enabledRoutes: Array<keyof ICustomizableRoutes> | undefined;
|
|
240
|
+
}): void;
|
|
209
241
|
}
|
|
210
242
|
//# sourceMappingURL=controller.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../../src/base/controllers/factory/controller.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../../src/base/controllers/factory/controller.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAGlF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACrF,OAAO,EAAE,UAAU,EAAY,MAAM,6BAA6B,CAAC;AAEnE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,KAAK,EACV,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACrB,MAAM,WAAW,CAAC;AAInB,6EAA6E;AAC7E,qBAAa,iBAAkB,SAAQ,UAAU;IAC/C,0GAA0G;IAC1G,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAMxB;;IAMX;;;;;OAKG;IACH,MAAM,CAAC,2BAA2B,CAAC,IAAI,EAAE;QACvC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QACxB,WAAW,EAAE,MAAM,CAAC;QACpB,cAAc,EAAE,MAAM,CAAC;QACvB,cAAc,EAAE,MAAM,CAAC;KACxB,GAAG,IAAI;IAoBR,MAAM,CAAC,oBAAoB,CACzB,OAAO,SAAS,cAAc,CAAC,gBAAgB,CAAC,GAAG,cAAc,CAAC,gBAAgB,CAAC,EACnF,MAAM,SAAS,mBAAmB,GAAG,mBAAmB,EACxD,QAAQ,SAAS,GAAG,GAAG,GAAG,EAC1B,WAAW,SAAS,MAAM,GAAG,EAAE,EAC/B,QAAQ,SAAS,MAAM,GAAG,GAAG,EAC7B,mBAAmB,SAAS,MAAM,GAAG,EAAE,EACvC,WAAW,SAAS,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,EACvD,cAAc,SAAS,MAAM,GAAG,oBAAoB,CAAC,OAAO,CAAC,EAC7D,OAAO,EAAE,sBAAsB,CAAC,OAAO,EAAE,MAAM,CAAC;yBAiDtB,kBAAkB,CAAC,WAAW,EAAE,cAAc,EAAE,OAAO,CAAC;YAUhF,iGAAiG;uBAC7E,cAAc,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAxDxC,CAAH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAiJD,OAAO,CAAC,MAAM,CAAC,YAAY;IAK3B;;;;;;;;OAQG;IACH,MAAM,CAAC,gCAAgC,CAAC,IAAI,EAAE;QAC5C,cAAc,EAAE,MAAM,CAAC;QACvB,SAAS,EAAE,kBAAkB,GAAG,kBAAkB,EAAE,GAAG,SAAS,CAAC;QACjE,MAAM,EAAE,mBAAmB,GAAG,SAAS,CAAC;QACxC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;QAC9B,aAAa,EAAE,KAAK,CAAC,MAAM,mBAAmB,CAAC,GAAG,SAAS,CAAC;KAC7D,GAAG,IAAI;CAgDT"}
|
|
@@ -1,15 +1,47 @@
|
|
|
1
|
+
import { AuthorizationActions } from '../../auth/authorize/common/constants/index.js';
|
|
1
2
|
import { SchemaTypes } from '../../models/common/constants.js';
|
|
3
|
+
import { BindingNamespaces } from '../../../common/bindings.js';
|
|
4
|
+
import { BindingKeys, MetadataRegistry } from '../../../helpers/inversion/index.js';
|
|
2
5
|
import { BaseHelper, getError } from '@venizia/ignis-helpers/core';
|
|
3
6
|
import { isClass } from '@venizia/ignis-inversion';
|
|
4
7
|
import { PersistableCrudController } from './crud/index.js';
|
|
5
|
-
import {
|
|
6
|
-
import { defineControllerRouteConfigs } from './definition.js';
|
|
7
|
-
import { registerFactoryRepositoryInjection } from './repository-injection.js';
|
|
8
|
+
import { RouteConfigResolver } from './definition.js';
|
|
8
9
|
/** Factory for generating typed CRUD controllers from entity definitions. */
|
|
9
10
|
export class ControllerFactory extends BaseHelper {
|
|
11
|
+
/** The generated routes that change data: the ones that must never be answered by a `read` permission. */
|
|
12
|
+
static { this.WRITE_VERBS = [
|
|
13
|
+
'create',
|
|
14
|
+
'updateById',
|
|
15
|
+
'updateBy',
|
|
16
|
+
'deleteById',
|
|
17
|
+
'deleteBy',
|
|
18
|
+
]; }
|
|
10
19
|
constructor() {
|
|
11
20
|
super({ scope: ControllerFactory.name });
|
|
12
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Injects `repositories.<repositoryName>` into constructor parameter 0 of a factory-generated
|
|
24
|
+
* controller, so a subclass needs no constructor. Recorded as metadata rather than a parameter
|
|
25
|
+
* decorator, which Bun drops in some configurations. A subclass that declares its own `@inject` at
|
|
26
|
+
* index 0 wins, and a sibling subclass keeps the factory's key.
|
|
27
|
+
*/
|
|
28
|
+
static registerRepositoryInjection(opts) {
|
|
29
|
+
const { target, factoryName, controllerName, repositoryName } = opts;
|
|
30
|
+
if (!repositoryName) {
|
|
31
|
+
throw getError({
|
|
32
|
+
message: `[${factoryName}] Invalid repository name | controller: ${controllerName} | repository.name must name the repository binding`,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
MetadataRegistry.getInstance().setInjectMetadata({
|
|
36
|
+
target,
|
|
37
|
+
index: 0,
|
|
38
|
+
metadata: {
|
|
39
|
+
key: BindingKeys.build({ namespace: BindingNamespaces.REPOSITORY, key: repositoryName }),
|
|
40
|
+
index: 0,
|
|
41
|
+
isOptional: false,
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
13
45
|
static defineCrudController(defOpts) {
|
|
14
46
|
const { controller, entity, authenticate, authorize, routes } = defOpts;
|
|
15
47
|
const { name, basePath = 'unknown_path', isStrict = { path: true, requestSchema: true }, } = controller;
|
|
@@ -18,7 +50,7 @@ export class ControllerFactory extends BaseHelper {
|
|
|
18
50
|
message: `[defineCrudController] Invalid controller basePath | name: ${name} | basePath: ${basePath}`,
|
|
19
51
|
});
|
|
20
52
|
}
|
|
21
|
-
assertWriteVerbsDeclareAuthorize({
|
|
53
|
+
ControllerFactory.assertWriteVerbsDeclareAuthorize({
|
|
22
54
|
controllerName: name,
|
|
23
55
|
authorize,
|
|
24
56
|
routes,
|
|
@@ -27,7 +59,7 @@ export class ControllerFactory extends BaseHelper {
|
|
|
27
59
|
});
|
|
28
60
|
const entityClass = isClass(entity) ? entity : entity();
|
|
29
61
|
const entityInstance = new entityClass();
|
|
30
|
-
const routeDefinitions = defineControllerRouteConfigs({
|
|
62
|
+
const routeDefinitions = RouteConfigResolver.defineControllerRouteConfigs({
|
|
31
63
|
isStrict: isStrict.requestSchema ?? true,
|
|
32
64
|
idType: entityInstance.getIdType(),
|
|
33
65
|
authenticate,
|
|
@@ -121,7 +153,7 @@ export class ControllerFactory extends BaseHelper {
|
|
|
121
153
|
}
|
|
122
154
|
};
|
|
123
155
|
Object.defineProperty(controllerClass, 'name', { value: name, configurable: true });
|
|
124
|
-
|
|
156
|
+
ControllerFactory.registerRepositoryInjection({
|
|
125
157
|
target: controllerClass,
|
|
126
158
|
factoryName: 'defineCrudController',
|
|
127
159
|
controllerName: name,
|
|
@@ -129,5 +161,57 @@ export class ControllerFactory extends BaseHelper {
|
|
|
129
161
|
});
|
|
130
162
|
return controllerClass;
|
|
131
163
|
}
|
|
164
|
+
static describeSpec(opts) {
|
|
165
|
+
const { spec } = opts;
|
|
166
|
+
return `{ action: ${String(spec.action)}, resource: ${String(spec.resource)} }`;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Refuses a CRUD controller whose enabled write verb would inherit a controller-level `authorize`
|
|
170
|
+
* that is only a `read` permission: the verb would then answer to anyone who may read.
|
|
171
|
+
*
|
|
172
|
+
* A write verb is fine when it declares its own `authorize` (a spec, an array, or `{ skip: true }`),
|
|
173
|
+
* skips authentication, is not enabled, or the controller is `readonly`. Only the literal action
|
|
174
|
+
* `read` is detected; a custom action name is the application's own vocabulary. An array counts when
|
|
175
|
+
* every spec in it is `read`, since the specs of one route must all pass.
|
|
176
|
+
*/
|
|
177
|
+
static assertWriteVerbsDeclareAuthorize(opts) {
|
|
178
|
+
const { controllerName, authorize, routes, readonly, enabledRoutes } = opts;
|
|
179
|
+
if (readonly || authorize == null) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const specs = Array.isArray(authorize) ? authorize : [authorize];
|
|
183
|
+
const isReadOnlyPermission = specs.length > 0 && specs.every((spec) => spec.action === AuthorizationActions.READ);
|
|
184
|
+
if (!isReadOnlyPermission) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const offending = ControllerFactory.WRITE_VERBS.filter((verb) => {
|
|
188
|
+
const isEnabled = enabledRoutes
|
|
189
|
+
? enabledRoutes.includes(verb)
|
|
190
|
+
: routes?.[verb]?.enabled !== false;
|
|
191
|
+
if (!isEnabled) {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
const route = routes?.[verb];
|
|
195
|
+
return route?.authenticate?.skip !== true && route?.authorize == null;
|
|
196
|
+
});
|
|
197
|
+
if (offending.length === 0) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const inherited = specs.map((spec) => ControllerFactory.describeSpec({ spec })).join(', ');
|
|
201
|
+
const verbs = offending.map((verb) => `${controllerName}.${verb}`).join(', ');
|
|
202
|
+
const hasBulkVerb = offending.some((verb) => verb === 'updateBy' || verb === 'deleteBy');
|
|
203
|
+
throw getError({
|
|
204
|
+
message: [
|
|
205
|
+
`[defineCrudController] Write routes would inherit a read-only authorize | controller: ${controllerName} | routes: ${verbs} | inherited: ${inherited}`,
|
|
206
|
+
'Anyone allowed to read could then create, update or delete.',
|
|
207
|
+
`Fix: declare routes.<verb>.authorize for each of them (a spec, an array or { skip: true }), or set controller.readonly, or leave them out of controller.enabledRoutes.`,
|
|
208
|
+
...(hasBulkVerb
|
|
209
|
+
? [
|
|
210
|
+
'updateBy and deleteBy are bulk routes on the collection and are generated unless controller.enabledRoutes lists the routes you want, so dropping them there closes this too.',
|
|
211
|
+
]
|
|
212
|
+
: []),
|
|
213
|
+
].join(' | '),
|
|
214
|
+
});
|
|
215
|
+
}
|
|
132
216
|
}
|
|
133
217
|
//# sourceMappingURL=controller.js.map
|