@classytic/arc 1.1.0 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +247 -794
- package/bin/arc.js +91 -52
- package/dist/EventTransport-BD2U0BTc.d.mts +100 -0
- package/dist/EventTransport-BD2U0BTc.d.mts.map +1 -0
- package/dist/HookSystem-BsGV-j2l.mjs +405 -0
- package/dist/HookSystem-BsGV-j2l.mjs.map +1 -0
- package/dist/ResourceRegistry-DsN4KJjV.mjs +250 -0
- package/dist/ResourceRegistry-DsN4KJjV.mjs.map +1 -0
- package/dist/adapters/index.d.mts +5 -0
- package/dist/adapters/index.mjs +3 -0
- package/dist/audit/index.d.mts +82 -0
- package/dist/audit/index.d.mts.map +1 -0
- package/dist/audit/index.mjs +276 -0
- package/dist/audit/index.mjs.map +1 -0
- package/dist/audit/mongodb.d.mts +5 -0
- package/dist/audit/mongodb.mjs +3 -0
- package/dist/audited-C3T5DTUx.mjs +141 -0
- package/dist/audited-C3T5DTUx.mjs.map +1 -0
- package/dist/auth/index.d.mts +189 -0
- package/dist/auth/index.d.mts.map +1 -0
- package/dist/auth/index.mjs +1102 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/auth/redis-session.d.mts +44 -0
- package/dist/auth/redis-session.d.mts.map +1 -0
- package/dist/auth/redis-session.mjs +76 -0
- package/dist/auth/redis-session.mjs.map +1 -0
- package/dist/betterAuthOpenApi-BrHKeSAx.mjs +250 -0
- package/dist/betterAuthOpenApi-BrHKeSAx.mjs.map +1 -0
- package/dist/cache/index.d.mts +146 -0
- package/dist/cache/index.d.mts.map +1 -0
- package/dist/cache/index.mjs +92 -0
- package/dist/cache/index.mjs.map +1 -0
- package/dist/caching-Bl28lYsR.mjs +94 -0
- package/dist/caching-Bl28lYsR.mjs.map +1 -0
- package/dist/chunk-C7Uep-_p.mjs +20 -0
- package/dist/circuitBreaker-DeY4FCjs.mjs +1097 -0
- package/dist/circuitBreaker-DeY4FCjs.mjs.map +1 -0
- package/dist/cli/commands/describe.d.mts +19 -0
- package/dist/cli/commands/describe.d.mts.map +1 -0
- package/dist/cli/commands/describe.mjs +239 -0
- package/dist/cli/commands/describe.mjs.map +1 -0
- package/dist/cli/commands/docs.d.mts +14 -0
- package/dist/cli/commands/docs.d.mts.map +1 -0
- package/dist/cli/commands/docs.mjs +53 -0
- package/dist/cli/commands/docs.mjs.map +1 -0
- package/dist/cli/commands/{generate.d.ts → generate.d.mts} +3 -1
- package/dist/cli/commands/generate.d.mts.map +1 -0
- package/dist/cli/commands/generate.mjs +358 -0
- package/dist/cli/commands/generate.mjs.map +1 -0
- package/dist/cli/commands/{init.d.ts → init.d.mts} +12 -8
- package/dist/cli/commands/init.d.mts.map +1 -0
- package/dist/cli/commands/{init.js → init.mjs} +807 -616
- package/dist/cli/commands/init.mjs.map +1 -0
- package/dist/cli/commands/introspect.d.mts +11 -0
- package/dist/cli/commands/introspect.d.mts.map +1 -0
- package/dist/cli/commands/introspect.mjs +76 -0
- package/dist/cli/commands/introspect.mjs.map +1 -0
- package/dist/cli/index.d.mts +17 -0
- package/dist/cli/index.d.mts.map +1 -0
- package/dist/cli/index.mjs +157 -0
- package/dist/cli/index.mjs.map +1 -0
- package/dist/constants-DdXFXQtN.mjs +85 -0
- package/dist/constants-DdXFXQtN.mjs.map +1 -0
- package/dist/core/index.d.mts +5 -0
- package/dist/core/index.mjs +4 -0
- package/dist/createApp-CUgNqegw.mjs +560 -0
- package/dist/createApp-CUgNqegw.mjs.map +1 -0
- package/dist/defineResource-k0_BDn8v.mjs +2197 -0
- package/dist/defineResource-k0_BDn8v.mjs.map +1 -0
- package/dist/discovery/index.d.mts +47 -0
- package/dist/discovery/index.d.mts.map +1 -0
- package/dist/discovery/index.mjs +110 -0
- package/dist/discovery/index.mjs.map +1 -0
- package/dist/docs/index.d.mts +163 -0
- package/dist/docs/index.d.mts.map +1 -0
- package/dist/docs/index.mjs +73 -0
- package/dist/docs/index.mjs.map +1 -0
- package/dist/elevation-BRy3yFWT.mjs +113 -0
- package/dist/elevation-BRy3yFWT.mjs.map +1 -0
- package/dist/elevation-B_2dRLVP.d.mts +88 -0
- package/dist/elevation-B_2dRLVP.d.mts.map +1 -0
- package/dist/errorHandler-BbcgBmIH.d.mts +73 -0
- package/dist/errorHandler-BbcgBmIH.d.mts.map +1 -0
- package/dist/errorHandler-C1okiriz.mjs +109 -0
- package/dist/errorHandler-C1okiriz.mjs.map +1 -0
- package/dist/errors-B9bZok84.mjs +212 -0
- package/dist/errors-B9bZok84.mjs.map +1 -0
- package/dist/errors-ChKiFz62.d.mts +125 -0
- package/dist/errors-ChKiFz62.d.mts.map +1 -0
- package/dist/eventPlugin-CTrLH3mt.d.mts +125 -0
- package/dist/eventPlugin-CTrLH3mt.d.mts.map +1 -0
- package/dist/eventPlugin-DGR_B2on.mjs +230 -0
- package/dist/eventPlugin-DGR_B2on.mjs.map +1 -0
- package/dist/events/index.d.mts +54 -0
- package/dist/events/index.d.mts.map +1 -0
- package/dist/events/index.mjs +52 -0
- package/dist/events/index.mjs.map +1 -0
- package/dist/events/transports/redis-stream-entry.d.mts +2 -0
- package/dist/events/transports/redis-stream-entry.mjs +178 -0
- package/dist/events/transports/redis-stream-entry.mjs.map +1 -0
- package/dist/events/transports/redis.d.mts +77 -0
- package/dist/events/transports/redis.d.mts.map +1 -0
- package/dist/events/transports/redis.mjs +125 -0
- package/dist/events/transports/redis.mjs.map +1 -0
- package/dist/externalPaths-DlINfKbP.d.mts +51 -0
- package/dist/externalPaths-DlINfKbP.d.mts.map +1 -0
- package/dist/factory/index.d.mts +64 -0
- package/dist/factory/index.d.mts.map +1 -0
- package/dist/factory/index.mjs +3 -0
- package/dist/fastifyAdapter-BkrGrlFi.d.mts +217 -0
- package/dist/fastifyAdapter-BkrGrlFi.d.mts.map +1 -0
- package/dist/fields-DyaDVX4J.d.mts +110 -0
- package/dist/fields-DyaDVX4J.d.mts.map +1 -0
- package/dist/fields-iagOozy0.mjs +115 -0
- package/dist/fields-iagOozy0.mjs.map +1 -0
- package/dist/hooks/index.d.mts +4 -0
- package/dist/hooks/index.mjs +3 -0
- package/dist/idempotency/index.d.mts +97 -0
- package/dist/idempotency/index.d.mts.map +1 -0
- package/dist/idempotency/index.mjs +320 -0
- package/dist/idempotency/index.mjs.map +1 -0
- package/dist/idempotency/mongodb.d.mts +2 -0
- package/dist/idempotency/mongodb.mjs +115 -0
- package/dist/idempotency/mongodb.mjs.map +1 -0
- package/dist/idempotency/redis.d.mts +2 -0
- package/dist/idempotency/redis.mjs +104 -0
- package/dist/idempotency/redis.mjs.map +1 -0
- package/dist/index.d.mts +261 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +105 -0
- package/dist/index.mjs.map +1 -0
- package/dist/integrations/event-gateway.d.mts +47 -0
- package/dist/integrations/event-gateway.d.mts.map +1 -0
- package/dist/integrations/event-gateway.mjs +44 -0
- package/dist/integrations/event-gateway.mjs.map +1 -0
- package/dist/integrations/index.d.mts +5 -0
- package/dist/integrations/index.mjs +1 -0
- package/dist/integrations/jobs.d.mts +104 -0
- package/dist/integrations/jobs.d.mts.map +1 -0
- package/dist/integrations/jobs.mjs +124 -0
- package/dist/integrations/jobs.mjs.map +1 -0
- package/dist/integrations/streamline.d.mts +61 -0
- package/dist/integrations/streamline.d.mts.map +1 -0
- package/dist/integrations/streamline.mjs +126 -0
- package/dist/integrations/streamline.mjs.map +1 -0
- package/dist/integrations/websocket.d.mts +83 -0
- package/dist/integrations/websocket.d.mts.map +1 -0
- package/dist/integrations/websocket.mjs +289 -0
- package/dist/integrations/websocket.mjs.map +1 -0
- package/dist/interface-B01JvPVc.d.mts +78 -0
- package/dist/interface-B01JvPVc.d.mts.map +1 -0
- package/dist/interface-CZe8IkMf.d.mts +55 -0
- package/dist/interface-CZe8IkMf.d.mts.map +1 -0
- package/dist/interface-Ch8HU9uM.d.mts +1098 -0
- package/dist/interface-Ch8HU9uM.d.mts.map +1 -0
- package/dist/introspectionPlugin-rFdO8ZUa.mjs +54 -0
- package/dist/introspectionPlugin-rFdO8ZUa.mjs.map +1 -0
- package/dist/keys-BqNejWup.mjs +43 -0
- package/dist/keys-BqNejWup.mjs.map +1 -0
- package/dist/logger-Df2O2WsW.mjs +79 -0
- package/dist/logger-Df2O2WsW.mjs.map +1 -0
- package/dist/memory-cQgelFOj.mjs +144 -0
- package/dist/memory-cQgelFOj.mjs.map +1 -0
- package/dist/migrations/index.d.mts +157 -0
- package/dist/migrations/index.d.mts.map +1 -0
- package/dist/migrations/index.mjs +261 -0
- package/dist/migrations/index.mjs.map +1 -0
- package/dist/mongodb-BfJVlUJH.mjs +94 -0
- package/dist/mongodb-BfJVlUJH.mjs.map +1 -0
- package/dist/mongodb-CGzRbfAK.d.mts +119 -0
- package/dist/mongodb-CGzRbfAK.d.mts.map +1 -0
- package/dist/mongodb-JN-9JA7K.d.mts +72 -0
- package/dist/mongodb-JN-9JA7K.d.mts.map +1 -0
- package/dist/openapi-G3Cw7XuM.mjs +524 -0
- package/dist/openapi-G3Cw7XuM.mjs.map +1 -0
- package/dist/org/index.d.mts +69 -0
- package/dist/org/index.d.mts.map +1 -0
- package/dist/org/index.mjs +514 -0
- package/dist/org/index.mjs.map +1 -0
- package/dist/org/types.d.mts +83 -0
- package/dist/org/types.d.mts.map +1 -0
- package/dist/org/types.mjs +1 -0
- package/dist/permissions/index.d.mts +279 -0
- package/dist/permissions/index.d.mts.map +1 -0
- package/dist/permissions/index.mjs +579 -0
- package/dist/permissions/index.mjs.map +1 -0
- package/dist/plugins/index.d.mts +173 -0
- package/dist/plugins/index.d.mts.map +1 -0
- package/dist/plugins/index.mjs +523 -0
- package/dist/plugins/index.mjs.map +1 -0
- package/dist/plugins/response-cache.d.mts +88 -0
- package/dist/plugins/response-cache.d.mts.map +1 -0
- package/dist/plugins/response-cache.mjs +284 -0
- package/dist/plugins/response-cache.mjs.map +1 -0
- package/dist/plugins/tracing-entry.d.mts +2 -0
- package/dist/plugins/tracing-entry.mjs +186 -0
- package/dist/plugins/tracing-entry.mjs.map +1 -0
- package/dist/pluralize-CEweyOEm.mjs +87 -0
- package/dist/pluralize-CEweyOEm.mjs.map +1 -0
- package/dist/policies/{index.d.ts → index.d.mts} +204 -169
- package/dist/policies/index.d.mts.map +1 -0
- package/dist/policies/index.mjs +322 -0
- package/dist/policies/index.mjs.map +1 -0
- package/dist/presets/{index.d.ts → index.d.mts} +63 -131
- package/dist/presets/index.d.mts.map +1 -0
- package/dist/presets/index.mjs +144 -0
- package/dist/presets/index.mjs.map +1 -0
- package/dist/presets/multiTenant.d.mts +25 -0
- package/dist/presets/multiTenant.d.mts.map +1 -0
- package/dist/presets/multiTenant.mjs +114 -0
- package/dist/presets/multiTenant.mjs.map +1 -0
- package/dist/presets-BITljm96.mjs +120 -0
- package/dist/presets-BITljm96.mjs.map +1 -0
- package/dist/presets-DzSMwlKj.d.mts +58 -0
- package/dist/presets-DzSMwlKj.d.mts.map +1 -0
- package/dist/prisma-DJbMt3yf.mjs +628 -0
- package/dist/prisma-DJbMt3yf.mjs.map +1 -0
- package/dist/prisma-Dg9GoVdj.d.mts +275 -0
- package/dist/prisma-Dg9GoVdj.d.mts.map +1 -0
- package/dist/queryCachePlugin-7THaI5mt.d.mts +72 -0
- package/dist/queryCachePlugin-7THaI5mt.d.mts.map +1 -0
- package/dist/queryCachePlugin-DMBnp2Q0.mjs +139 -0
- package/dist/queryCachePlugin-DMBnp2Q0.mjs.map +1 -0
- package/dist/redis-D-JAeLtm.d.mts +50 -0
- package/dist/redis-D-JAeLtm.d.mts.map +1 -0
- package/dist/redis-stream-Bdh_vUU8.d.mts +104 -0
- package/dist/redis-stream-Bdh_vUU8.d.mts.map +1 -0
- package/dist/registry/index.d.mts +12 -0
- package/dist/registry/index.d.mts.map +1 -0
- package/dist/registry/index.mjs +4 -0
- package/dist/requestContext-QQD6ROJc.mjs +56 -0
- package/dist/requestContext-QQD6ROJc.mjs.map +1 -0
- package/dist/schemaConverter-BwrmWroW.mjs +99 -0
- package/dist/schemaConverter-BwrmWroW.mjs.map +1 -0
- package/dist/schemas/index.d.mts +64 -0
- package/dist/schemas/index.d.mts.map +1 -0
- package/dist/schemas/index.mjs +83 -0
- package/dist/schemas/index.mjs.map +1 -0
- package/dist/scope/index.d.mts +22 -0
- package/dist/scope/index.d.mts.map +1 -0
- package/dist/scope/index.mjs +66 -0
- package/dist/scope/index.mjs.map +1 -0
- package/dist/sessionManager-jPKLbHE0.d.mts +187 -0
- package/dist/sessionManager-jPKLbHE0.d.mts.map +1 -0
- package/dist/sse-B3c3_yZp.mjs +124 -0
- package/dist/sse-B3c3_yZp.mjs.map +1 -0
- package/dist/testing/index.d.mts +908 -0
- package/dist/testing/index.d.mts.map +1 -0
- package/dist/testing/index.mjs +1977 -0
- package/dist/testing/index.mjs.map +1 -0
- package/dist/tracing-Cc7vVQPp.d.mts +71 -0
- package/dist/tracing-Cc7vVQPp.d.mts.map +1 -0
- package/dist/typeGuards-DhMNLuvU.mjs +10 -0
- package/dist/typeGuards-DhMNLuvU.mjs.map +1 -0
- package/dist/types/index.d.mts +947 -0
- package/dist/types/index.d.mts.map +1 -0
- package/dist/types/index.mjs +15 -0
- package/dist/types/index.mjs.map +1 -0
- package/dist/types-Beqn1Un7.mjs +39 -0
- package/dist/types-Beqn1Un7.mjs.map +1 -0
- package/dist/types-CIgB7UUl.d.mts +446 -0
- package/dist/types-CIgB7UUl.d.mts.map +1 -0
- package/dist/types-aYB4V7uN.d.mts +87 -0
- package/dist/types-aYB4V7uN.d.mts.map +1 -0
- package/dist/utils/index.d.mts +748 -0
- package/dist/utils/index.d.mts.map +1 -0
- package/dist/utils/index.mjs +6 -0
- package/package.json +194 -68
- package/dist/BaseController-DVAiHxEQ.d.ts +0 -233
- package/dist/adapters/index.d.ts +0 -237
- package/dist/adapters/index.js +0 -668
- package/dist/arcCorePlugin-CsShQdyP.d.ts +0 -273
- package/dist/audit/index.d.ts +0 -195
- package/dist/audit/index.js +0 -319
- package/dist/auth/index.d.ts +0 -47
- package/dist/auth/index.js +0 -174
- package/dist/cli/commands/docs.d.ts +0 -11
- package/dist/cli/commands/docs.js +0 -474
- package/dist/cli/commands/generate.js +0 -334
- package/dist/cli/commands/introspect.d.ts +0 -8
- package/dist/cli/commands/introspect.js +0 -338
- package/dist/cli/index.d.ts +0 -4
- package/dist/cli/index.js +0 -3269
- package/dist/core/index.d.ts +0 -220
- package/dist/core/index.js +0 -2786
- package/dist/createApp-Ce9wl8W9.d.ts +0 -77
- package/dist/docs/index.d.ts +0 -166
- package/dist/docs/index.js +0 -658
- package/dist/errors-8WIxGS_6.d.ts +0 -122
- package/dist/events/index.d.ts +0 -117
- package/dist/events/index.js +0 -89
- package/dist/factory/index.d.ts +0 -38
- package/dist/factory/index.js +0 -1652
- package/dist/hooks/index.d.ts +0 -4
- package/dist/hooks/index.js +0 -199
- package/dist/idempotency/index.d.ts +0 -323
- package/dist/idempotency/index.js +0 -500
- package/dist/index-B4t03KQ0.d.ts +0 -1366
- package/dist/index.d.ts +0 -135
- package/dist/index.js +0 -4756
- package/dist/migrations/index.d.ts +0 -185
- package/dist/migrations/index.js +0 -274
- package/dist/org/index.d.ts +0 -129
- package/dist/org/index.js +0 -220
- package/dist/permissions/index.d.ts +0 -144
- package/dist/permissions/index.js +0 -103
- package/dist/plugins/index.d.ts +0 -46
- package/dist/plugins/index.js +0 -1069
- package/dist/policies/index.js +0 -196
- package/dist/presets/index.js +0 -384
- package/dist/presets/multiTenant.d.ts +0 -39
- package/dist/presets/multiTenant.js +0 -112
- package/dist/registry/index.d.ts +0 -16
- package/dist/registry/index.js +0 -253
- package/dist/testing/index.d.ts +0 -618
- package/dist/testing/index.js +0 -48020
- package/dist/types/index.d.ts +0 -4
- package/dist/types/index.js +0 -8
- package/dist/types-B99TBmFV.d.ts +0 -76
- package/dist/types-BvckRbs2.d.ts +0 -143
- package/dist/utils/index.d.ts +0 -679
- package/dist/utils/index.js +0 -931
package/dist/org/index.js
DELETED
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
import fp from 'fastify-plugin';
|
|
2
|
-
|
|
3
|
-
// src/org/orgScopePlugin.ts
|
|
4
|
-
function createOrgContext(orgId, options = {}) {
|
|
5
|
-
return {
|
|
6
|
-
organizationId: orgId,
|
|
7
|
-
orgScope: options.orgScope ?? "explicit",
|
|
8
|
-
orgRoles: options.orgRoles ?? [],
|
|
9
|
-
...options
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
var orgScopePlugin = async (fastify, opts = {}) => {
|
|
13
|
-
const {
|
|
14
|
-
header = "x-organization-id",
|
|
15
|
-
bypassRoles = ["superadmin"],
|
|
16
|
-
userOrgsPath = "organizations",
|
|
17
|
-
validateMembership
|
|
18
|
-
} = opts;
|
|
19
|
-
if (!fastify.hasRequestDecorator("context")) {
|
|
20
|
-
fastify.decorateRequest("context", void 0);
|
|
21
|
-
}
|
|
22
|
-
if (!fastify.hasRequestDecorator("organizationId")) {
|
|
23
|
-
fastify.decorateRequest("organizationId", void 0);
|
|
24
|
-
}
|
|
25
|
-
fastify.decorate("organizationScoped", function organizationScoped(options = {}) {
|
|
26
|
-
const { required = true } = options;
|
|
27
|
-
return async function organizationScopePreHandler(request, reply) {
|
|
28
|
-
const user = request.user;
|
|
29
|
-
const userWithRoles = user;
|
|
30
|
-
const roles = Array.isArray(userWithRoles?.roles) ? userWithRoles.roles : userWithRoles?.roles ? [String(userWithRoles.roles)] : [];
|
|
31
|
-
const orgIdFromHeader = request.headers[header]?.toString().trim();
|
|
32
|
-
const isAuthenticated = !!user;
|
|
33
|
-
const isSuperadmin = bypassRoles.some((role) => roles.includes(role));
|
|
34
|
-
const req = request;
|
|
35
|
-
req.context = req.context ?? {};
|
|
36
|
-
if (!orgIdFromHeader) {
|
|
37
|
-
if (isSuperadmin) {
|
|
38
|
-
request.log?.debug?.({ msg: "Superadmin - no org filter required" });
|
|
39
|
-
req.context.orgScope = "global";
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
if (required) {
|
|
43
|
-
reply.code(403).send({
|
|
44
|
-
success: false,
|
|
45
|
-
error: "Organization context required",
|
|
46
|
-
code: "ORG_HEADER_REQUIRED",
|
|
47
|
-
message: "x-organization-id header required"
|
|
48
|
-
});
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
request.log?.debug?.({ msg: "No org filter - showing all public data" });
|
|
52
|
-
req.context.orgScope = "public";
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
if (!isAuthenticated) {
|
|
56
|
-
request.log?.warn?.({
|
|
57
|
-
msg: "Organization filtering requires authentication",
|
|
58
|
-
headerOrgId: orgIdFromHeader
|
|
59
|
-
});
|
|
60
|
-
reply.code(401).send({
|
|
61
|
-
success: false,
|
|
62
|
-
error: "Authentication required to filter by organization",
|
|
63
|
-
code: "AUTH_REQUIRED_FOR_ORG"
|
|
64
|
-
});
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
if (isSuperadmin) {
|
|
68
|
-
request.log?.debug?.({
|
|
69
|
-
msg: "Superadmin accessing organization",
|
|
70
|
-
orgId: orgIdFromHeader
|
|
71
|
-
});
|
|
72
|
-
req.organizationId = orgIdFromHeader;
|
|
73
|
-
req.context.organizationId = orgIdFromHeader;
|
|
74
|
-
req.context.orgScope = "bypass";
|
|
75
|
-
req.context.bypassReason = "superadmin";
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
const userOrgs = user?.[userOrgsPath] ?? [];
|
|
79
|
-
let hasAccess = false;
|
|
80
|
-
if (validateMembership) {
|
|
81
|
-
hasAccess = await validateMembership(user, orgIdFromHeader);
|
|
82
|
-
} else {
|
|
83
|
-
hasAccess = userOrgs.some((org) => {
|
|
84
|
-
const memberOrgId = org.organizationId?.toString() ?? String(org);
|
|
85
|
-
return memberOrgId === orgIdFromHeader;
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
if (!hasAccess) {
|
|
89
|
-
request.log?.warn?.({
|
|
90
|
-
msg: "Access denied - user not member of organization",
|
|
91
|
-
userId: user._id ?? user.id,
|
|
92
|
-
requestedOrgId: orgIdFromHeader,
|
|
93
|
-
userOrgIds: userOrgs.map((o) => o.organizationId?.toString() ?? String(o))
|
|
94
|
-
});
|
|
95
|
-
reply.code(403).send({
|
|
96
|
-
success: false,
|
|
97
|
-
error: "No access to this organization",
|
|
98
|
-
code: "ORG_ACCESS_DENIED"
|
|
99
|
-
});
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
req.organizationId = orgIdFromHeader;
|
|
103
|
-
req.context.organizationId = orgIdFromHeader;
|
|
104
|
-
req.context.orgScope = "member";
|
|
105
|
-
const orgMembership = userOrgs.find((o) => {
|
|
106
|
-
const memberOrgId = o.organizationId?.toString() ?? String(o);
|
|
107
|
-
return memberOrgId === orgIdFromHeader;
|
|
108
|
-
});
|
|
109
|
-
req.context.orgRoles = orgMembership?.roles ?? [];
|
|
110
|
-
request.log?.debug?.({
|
|
111
|
-
msg: "Organization context set",
|
|
112
|
-
orgId: orgIdFromHeader,
|
|
113
|
-
userId: user._id ?? user.id,
|
|
114
|
-
orgRoles: req.context.orgRoles
|
|
115
|
-
});
|
|
116
|
-
};
|
|
117
|
-
});
|
|
118
|
-
fastify.decorate("createOrgContext", createOrgContext);
|
|
119
|
-
fastify.log?.info?.("Organization scope plugin registered");
|
|
120
|
-
};
|
|
121
|
-
var orgScopePlugin_default = fp(orgScopePlugin, {
|
|
122
|
-
name: "arc-org-scope",
|
|
123
|
-
fastify: "5.x"
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
// src/org/orgGuard.ts
|
|
127
|
-
function orgGuard(options = {}) {
|
|
128
|
-
const {
|
|
129
|
-
requireOrgContext = true,
|
|
130
|
-
roles = [],
|
|
131
|
-
allowGlobal = false
|
|
132
|
-
} = options;
|
|
133
|
-
return async function orgGuardMiddleware(request, reply) {
|
|
134
|
-
const context = request.context ?? {};
|
|
135
|
-
const user = request.user;
|
|
136
|
-
const userWithRoles = user;
|
|
137
|
-
if (allowGlobal && userWithRoles?.roles?.includes("superadmin")) {
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
if (requireOrgContext && !context.organizationId) {
|
|
141
|
-
reply.code(403).send({
|
|
142
|
-
success: false,
|
|
143
|
-
error: "Organization context required",
|
|
144
|
-
code: "ORG_CONTEXT_REQUIRED",
|
|
145
|
-
message: "This endpoint requires an organization context. Please specify organization via x-organization-id header."
|
|
146
|
-
});
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
if (roles.length > 0 && context.organizationId) {
|
|
150
|
-
const contextWithRoles = context;
|
|
151
|
-
const userOrgRoles = contextWithRoles.orgRoles ?? [];
|
|
152
|
-
const hasRequiredRole = roles.some((role) => userOrgRoles.includes(role));
|
|
153
|
-
if (!hasRequiredRole && !userWithRoles?.roles?.includes("superadmin")) {
|
|
154
|
-
reply.code(403).send({
|
|
155
|
-
success: false,
|
|
156
|
-
error: "Insufficient organization permissions",
|
|
157
|
-
code: "ORG_ROLE_REQUIRED",
|
|
158
|
-
message: `This action requires one of these organization roles: ${roles.join(", ")}`,
|
|
159
|
-
required: roles,
|
|
160
|
-
current: userOrgRoles
|
|
161
|
-
});
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
function requireOrg() {
|
|
168
|
-
return orgGuard({ requireOrgContext: true });
|
|
169
|
-
}
|
|
170
|
-
function requireOrgRole(...roles) {
|
|
171
|
-
return orgGuard({ requireOrgContext: true, roles });
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// src/org/orgMembership.ts
|
|
175
|
-
async function orgMembershipCheck(user, orgId, options = {}) {
|
|
176
|
-
const {
|
|
177
|
-
userOrgsPath = "organizations",
|
|
178
|
-
bypassRoles = ["superadmin"],
|
|
179
|
-
validateFromDb
|
|
180
|
-
} = options;
|
|
181
|
-
if (!user || !orgId) return false;
|
|
182
|
-
const userWithRoles = user;
|
|
183
|
-
const userRoles = userWithRoles.roles ?? [];
|
|
184
|
-
if (bypassRoles.some((role) => userRoles.includes(role))) {
|
|
185
|
-
return true;
|
|
186
|
-
}
|
|
187
|
-
const userOrgs = user[userOrgsPath] ?? [];
|
|
188
|
-
const isMemberFromUser = userOrgs.some((o) => {
|
|
189
|
-
const memberOrgId = o.organizationId?.toString() ?? String(o);
|
|
190
|
-
return memberOrgId === orgId.toString();
|
|
191
|
-
});
|
|
192
|
-
if (isMemberFromUser) return true;
|
|
193
|
-
if (validateFromDb) {
|
|
194
|
-
const userId = (user._id ?? user.id)?.toString();
|
|
195
|
-
if (userId) {
|
|
196
|
-
return validateFromDb(userId, orgId);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
return false;
|
|
200
|
-
}
|
|
201
|
-
function getOrgRoles(user, orgId, options = {}) {
|
|
202
|
-
const { userOrgsPath = "organizations" } = options;
|
|
203
|
-
if (!user || !orgId) return [];
|
|
204
|
-
const userOrgs = user[userOrgsPath] ?? [];
|
|
205
|
-
const membership = userOrgs.find((o) => {
|
|
206
|
-
const memberOrgId = o.organizationId?.toString() ?? String(o);
|
|
207
|
-
return memberOrgId === orgId.toString();
|
|
208
|
-
});
|
|
209
|
-
const membershipRoles = membership;
|
|
210
|
-
return membershipRoles?.roles ?? [];
|
|
211
|
-
}
|
|
212
|
-
function hasOrgRole(user, orgId, roles, options = {}) {
|
|
213
|
-
const userOrgRoles = getOrgRoles(user, orgId, options);
|
|
214
|
-
const requiredRoles = Array.isArray(roles) ? roles : [roles];
|
|
215
|
-
const userWithRoles = user;
|
|
216
|
-
if (userWithRoles?.roles?.includes("superadmin")) return true;
|
|
217
|
-
return requiredRoles.some((role) => userOrgRoles.includes(role));
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
export { createOrgContext, getOrgRoles, hasOrgRole, orgGuard, orgMembershipCheck, orgScopePlugin_default as orgScopePlugin, orgScopePlugin as orgScopePluginFn, requireOrg, requireOrgRole };
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import { P as PermissionCheck, a as PermissionContext } from '../types-B99TBmFV.js';
|
|
2
|
-
export { b as PermissionResult, U as UserBase } from '../types-B99TBmFV.js';
|
|
3
|
-
import 'fastify';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Permission System
|
|
7
|
-
*
|
|
8
|
-
* Clean, function-based permission system.
|
|
9
|
-
* PermissionCheck is THE ONLY way to define permissions.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```typescript
|
|
13
|
-
* import { allowPublic, requireAuth, requireRoles } from '@classytic/arc/permissions';
|
|
14
|
-
*
|
|
15
|
-
* defineResource({
|
|
16
|
-
* permissions: {
|
|
17
|
-
* list: allowPublic(),
|
|
18
|
-
* get: allowPublic(),
|
|
19
|
-
* create: requireAuth(),
|
|
20
|
-
* update: requireRoles(['admin', 'editor']),
|
|
21
|
-
* delete: requireRoles(['admin']),
|
|
22
|
-
* }
|
|
23
|
-
* });
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Allow public access (no authentication required)
|
|
29
|
-
*
|
|
30
|
-
* @example
|
|
31
|
-
* ```typescript
|
|
32
|
-
* permissions: {
|
|
33
|
-
* list: allowPublic(),
|
|
34
|
-
* get: allowPublic(),
|
|
35
|
-
* }
|
|
36
|
-
* ```
|
|
37
|
-
*/
|
|
38
|
-
declare function allowPublic(): PermissionCheck;
|
|
39
|
-
/**
|
|
40
|
-
* Require authentication (any authenticated user)
|
|
41
|
-
*
|
|
42
|
-
* @example
|
|
43
|
-
* ```typescript
|
|
44
|
-
* permissions: {
|
|
45
|
-
* create: requireAuth(),
|
|
46
|
-
* update: requireAuth(),
|
|
47
|
-
* }
|
|
48
|
-
* ```
|
|
49
|
-
*/
|
|
50
|
-
declare function requireAuth(): PermissionCheck;
|
|
51
|
-
/**
|
|
52
|
-
* Require specific roles
|
|
53
|
-
*
|
|
54
|
-
* @param roles - Required roles (user needs at least one)
|
|
55
|
-
* @param options - Optional bypass roles
|
|
56
|
-
*
|
|
57
|
-
* @example
|
|
58
|
-
* ```typescript
|
|
59
|
-
* permissions: {
|
|
60
|
-
* create: requireRoles(['admin', 'editor']),
|
|
61
|
-
* delete: requireRoles(['admin']),
|
|
62
|
-
* }
|
|
63
|
-
*
|
|
64
|
-
* // With bypass roles
|
|
65
|
-
* permissions: {
|
|
66
|
-
* update: requireRoles(['owner'], { bypassRoles: ['admin', 'superadmin'] }),
|
|
67
|
-
* }
|
|
68
|
-
* ```
|
|
69
|
-
*/
|
|
70
|
-
declare function requireRoles(roles: readonly string[], options?: {
|
|
71
|
-
bypassRoles?: readonly string[];
|
|
72
|
-
}): PermissionCheck;
|
|
73
|
-
/**
|
|
74
|
-
* Require resource ownership
|
|
75
|
-
*
|
|
76
|
-
* Returns filters to scope queries to user's owned resources.
|
|
77
|
-
*
|
|
78
|
-
* @param ownerField - Field containing owner ID (default: 'userId')
|
|
79
|
-
* @param options - Optional bypass roles
|
|
80
|
-
*
|
|
81
|
-
* @example
|
|
82
|
-
* ```typescript
|
|
83
|
-
* permissions: {
|
|
84
|
-
* update: requireOwnership('userId'),
|
|
85
|
-
* delete: requireOwnership('createdBy', { bypassRoles: ['admin'] }),
|
|
86
|
-
* }
|
|
87
|
-
* ```
|
|
88
|
-
*/
|
|
89
|
-
declare function requireOwnership(ownerField?: string, options?: {
|
|
90
|
-
bypassRoles?: readonly string[];
|
|
91
|
-
}): PermissionCheck;
|
|
92
|
-
/**
|
|
93
|
-
* Combine multiple checks - ALL must pass (AND logic)
|
|
94
|
-
*
|
|
95
|
-
* @example
|
|
96
|
-
* ```typescript
|
|
97
|
-
* permissions: {
|
|
98
|
-
* update: allOf(
|
|
99
|
-
* requireAuth(),
|
|
100
|
-
* requireRoles(['editor']),
|
|
101
|
-
* requireOwnership('createdBy')
|
|
102
|
-
* ),
|
|
103
|
-
* }
|
|
104
|
-
* ```
|
|
105
|
-
*/
|
|
106
|
-
declare function allOf(...checks: PermissionCheck[]): PermissionCheck;
|
|
107
|
-
/**
|
|
108
|
-
* Combine multiple checks - ANY must pass (OR logic)
|
|
109
|
-
*
|
|
110
|
-
* @example
|
|
111
|
-
* ```typescript
|
|
112
|
-
* permissions: {
|
|
113
|
-
* update: anyOf(
|
|
114
|
-
* requireRoles(['admin']),
|
|
115
|
-
* requireOwnership('createdBy')
|
|
116
|
-
* ),
|
|
117
|
-
* }
|
|
118
|
-
* ```
|
|
119
|
-
*/
|
|
120
|
-
declare function anyOf(...checks: PermissionCheck[]): PermissionCheck;
|
|
121
|
-
/**
|
|
122
|
-
* Deny all access
|
|
123
|
-
*
|
|
124
|
-
* @example
|
|
125
|
-
* ```typescript
|
|
126
|
-
* permissions: {
|
|
127
|
-
* delete: denyAll('Deletion not allowed'),
|
|
128
|
-
* }
|
|
129
|
-
* ```
|
|
130
|
-
*/
|
|
131
|
-
declare function denyAll(reason?: string): PermissionCheck;
|
|
132
|
-
/**
|
|
133
|
-
* Dynamic permission based on context
|
|
134
|
-
*
|
|
135
|
-
* @example
|
|
136
|
-
* ```typescript
|
|
137
|
-
* permissions: {
|
|
138
|
-
* update: when((ctx) => ctx.data?.status === 'draft'),
|
|
139
|
-
* }
|
|
140
|
-
* ```
|
|
141
|
-
*/
|
|
142
|
-
declare function when(condition: (ctx: PermissionContext) => boolean | Promise<boolean>): PermissionCheck;
|
|
143
|
-
|
|
144
|
-
export { PermissionCheck, PermissionContext, allOf, allowPublic, anyOf, denyAll, requireAuth, requireOwnership, requireRoles, when };
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
// src/permissions/index.ts
|
|
2
|
-
function allowPublic() {
|
|
3
|
-
const check = () => true;
|
|
4
|
-
check._isPublic = true;
|
|
5
|
-
return check;
|
|
6
|
-
}
|
|
7
|
-
function requireAuth() {
|
|
8
|
-
const check = (ctx) => {
|
|
9
|
-
if (!ctx.user) {
|
|
10
|
-
return { granted: false, reason: "Authentication required" };
|
|
11
|
-
}
|
|
12
|
-
return true;
|
|
13
|
-
};
|
|
14
|
-
return check;
|
|
15
|
-
}
|
|
16
|
-
function requireRoles(roles, options) {
|
|
17
|
-
const check = (ctx) => {
|
|
18
|
-
if (!ctx.user) {
|
|
19
|
-
return { granted: false, reason: "Authentication required" };
|
|
20
|
-
}
|
|
21
|
-
const userRoles = ctx.user.roles ?? [];
|
|
22
|
-
if (options?.bypassRoles?.some((r) => userRoles.includes(r))) {
|
|
23
|
-
return true;
|
|
24
|
-
}
|
|
25
|
-
if (roles.some((r) => userRoles.includes(r))) {
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
28
|
-
return {
|
|
29
|
-
granted: false,
|
|
30
|
-
reason: `Required roles: ${roles.join(", ")}`
|
|
31
|
-
};
|
|
32
|
-
};
|
|
33
|
-
check._roles = roles;
|
|
34
|
-
return check;
|
|
35
|
-
}
|
|
36
|
-
function requireOwnership(ownerField = "userId", options) {
|
|
37
|
-
return (ctx) => {
|
|
38
|
-
if (!ctx.user) {
|
|
39
|
-
return { granted: false, reason: "Authentication required" };
|
|
40
|
-
}
|
|
41
|
-
const userRoles = ctx.user.roles ?? [];
|
|
42
|
-
if (options?.bypassRoles?.some((r) => userRoles.includes(r))) {
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
const userId = ctx.user.id ?? ctx.user._id;
|
|
46
|
-
return {
|
|
47
|
-
granted: true,
|
|
48
|
-
filters: { [ownerField]: userId }
|
|
49
|
-
};
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
function allOf(...checks) {
|
|
53
|
-
return async (ctx) => {
|
|
54
|
-
let mergedFilters = {};
|
|
55
|
-
for (const check of checks) {
|
|
56
|
-
const result = await check(ctx);
|
|
57
|
-
const normalized = typeof result === "boolean" ? { granted: result } : result;
|
|
58
|
-
if (!normalized.granted) {
|
|
59
|
-
return normalized;
|
|
60
|
-
}
|
|
61
|
-
if (normalized.filters) {
|
|
62
|
-
mergedFilters = { ...mergedFilters, ...normalized.filters };
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return {
|
|
66
|
-
granted: true,
|
|
67
|
-
filters: Object.keys(mergedFilters).length > 0 ? mergedFilters : void 0
|
|
68
|
-
};
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
function anyOf(...checks) {
|
|
72
|
-
return async (ctx) => {
|
|
73
|
-
const reasons = [];
|
|
74
|
-
for (const check of checks) {
|
|
75
|
-
const result = await check(ctx);
|
|
76
|
-
const normalized = typeof result === "boolean" ? { granted: result } : result;
|
|
77
|
-
if (normalized.granted) {
|
|
78
|
-
return normalized;
|
|
79
|
-
}
|
|
80
|
-
if (normalized.reason) {
|
|
81
|
-
reasons.push(normalized.reason);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return {
|
|
85
|
-
granted: false,
|
|
86
|
-
reason: reasons.join("; ")
|
|
87
|
-
};
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
function denyAll(reason = "Access denied") {
|
|
91
|
-
return () => ({ granted: false, reason });
|
|
92
|
-
}
|
|
93
|
-
function when(condition) {
|
|
94
|
-
return async (ctx) => {
|
|
95
|
-
const result = await condition(ctx);
|
|
96
|
-
return {
|
|
97
|
-
granted: result,
|
|
98
|
-
reason: result ? void 0 : "Condition not met"
|
|
99
|
-
};
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export { allOf, allowPublic, anyOf, denyAll, requireAuth, requireOwnership, requireRoles, when };
|
package/dist/plugins/index.d.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
export { k as ArcCore, A as ArcCorePluginOptions, G as GracefulShutdownOptions, b as HealthCheck, H as HealthOptions, R as RequestIdOptions, T as TracingOptions, f as arcCorePlugin, j as arcCorePluginFn, d as createSpan, e as gracefulShutdownPlugin, g as gracefulShutdownPluginFn, a as healthPlugin, h as healthPluginFn, i as isTracingAvailable, _ as requestIdPlugin, r as requestIdPluginFn, t as traced, c as tracingPlugin } from '../arcCorePlugin-CsShQdyP.js';
|
|
2
|
-
import { FastifyInstance, FastifyRequest } from 'fastify';
|
|
3
|
-
import '../index-B4t03KQ0.js';
|
|
4
|
-
import 'mongoose';
|
|
5
|
-
import '../types-B99TBmFV.js';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Error Handler Plugin
|
|
9
|
-
*
|
|
10
|
-
* Global error handling for Arc applications.
|
|
11
|
-
* Catches all errors and returns a consistent JSON response.
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* import { errorHandlerPlugin } from '@classytic/arc/plugins';
|
|
15
|
-
*
|
|
16
|
-
* await fastify.register(errorHandlerPlugin, {
|
|
17
|
-
* includeStack: process.env.NODE_ENV !== 'production',
|
|
18
|
-
* onError: (error, request) => {
|
|
19
|
-
* // Log to external service (Sentry, etc.)
|
|
20
|
-
* Sentry.captureException(error);
|
|
21
|
-
* }
|
|
22
|
-
* });
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
interface ErrorHandlerOptions {
|
|
26
|
-
/**
|
|
27
|
-
* Include stack trace in error responses (default: false in production)
|
|
28
|
-
*/
|
|
29
|
-
includeStack?: boolean;
|
|
30
|
-
/**
|
|
31
|
-
* Custom error callback for logging to external services
|
|
32
|
-
*/
|
|
33
|
-
onError?: (error: Error, request: FastifyRequest) => void | Promise<void>;
|
|
34
|
-
/**
|
|
35
|
-
* Map specific error types to custom responses
|
|
36
|
-
*/
|
|
37
|
-
errorMap?: Record<string, {
|
|
38
|
-
statusCode: number;
|
|
39
|
-
code: string;
|
|
40
|
-
message?: string;
|
|
41
|
-
}>;
|
|
42
|
-
}
|
|
43
|
-
declare function errorHandlerPluginFn(fastify: FastifyInstance, options?: ErrorHandlerOptions): Promise<void>;
|
|
44
|
-
declare const errorHandlerPlugin: typeof errorHandlerPluginFn;
|
|
45
|
-
|
|
46
|
-
export { type ErrorHandlerOptions, errorHandlerPlugin, errorHandlerPlugin as errorHandlerPluginFn };
|