@camstack/server 1.2.9 → 1.2.10
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.
|
@@ -1225,11 +1225,11 @@ class AddonRegistryService {
|
|
|
1225
1225
|
if (initResult?.customActions && initResult.actionHandlers) {
|
|
1226
1226
|
const handlers = initResult.actionHandlers;
|
|
1227
1227
|
try {
|
|
1228
|
-
this.customActionRegistry.registerAddon(id, initResult.customActions, (action, input) => {
|
|
1228
|
+
this.customActionRegistry.registerAddon(id, initResult.customActions, (action, input, caller) => {
|
|
1229
1229
|
const fn = handlers[action];
|
|
1230
1230
|
if (!fn)
|
|
1231
1231
|
throw new Error(`addon '${id}' has no handler for custom action '${action}'`);
|
|
1232
|
-
return fn(input);
|
|
1232
|
+
return fn(input, caller);
|
|
1233
1233
|
});
|
|
1234
1234
|
}
|
|
1235
1235
|
catch (err) {
|
|
@@ -2987,7 +2987,7 @@ class AddonRegistryService {
|
|
|
2987
2987
|
});
|
|
2988
2988
|
return;
|
|
2989
2989
|
}
|
|
2990
|
-
this.customActionRegistry.registerAddon(addonId, catalog, (action, input) => this.dispatchForkedCustomAction(addonId, action, input));
|
|
2990
|
+
this.customActionRegistry.registerAddon(addonId, catalog, (action, input, caller) => this.dispatchForkedCustomAction(addonId, action, input, caller));
|
|
2991
2991
|
this.logger.info('Runner addon custom actions registered', {
|
|
2992
2992
|
tags: { addonId },
|
|
2993
2993
|
meta: { runnerId },
|
|
@@ -2999,11 +2999,15 @@ class AddonRegistryService {
|
|
|
2999
2999
|
* routing + the child-availability error; there is no broker fallback after
|
|
3000
3000
|
* the per-addon Moleculer broker was removed.
|
|
3001
3001
|
*/
|
|
3002
|
-
async dispatchForkedCustomAction(addonId, action, input) {
|
|
3002
|
+
async dispatchForkedCustomAction(addonId, action, input, caller) {
|
|
3003
3003
|
return this.addonCallGateway.callForked(addonId, {
|
|
3004
3004
|
target: 'custom',
|
|
3005
3005
|
action,
|
|
3006
3006
|
args: input,
|
|
3007
|
+
// Additive: only carry `caller` when the hub actually forwarded one (the
|
|
3008
|
+
// router populates it exclusively for a `caller:'required'` action of an
|
|
3009
|
+
// authenticated request). Never blanket; never from client input.
|
|
3010
|
+
...(caller ? { caller } : {}),
|
|
3007
3011
|
});
|
|
3008
3012
|
}
|
|
3009
3013
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/server",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.10",
|
|
4
4
|
"private": false,
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -33,20 +33,19 @@
|
|
|
33
33
|
]
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@camstack/addon-admin-ui": "1.2.
|
|
37
|
-
"@camstack/addon-advanced-notifier": "1.2.4",
|
|
36
|
+
"@camstack/addon-admin-ui": "1.2.7",
|
|
38
37
|
"@camstack/addon-agent-ui": "1.2.4",
|
|
39
38
|
"@camstack/addon-auth": "1.2.4",
|
|
40
39
|
"@camstack/addon-decoder-nodeav": "1.2.4",
|
|
41
|
-
"@camstack/addon-notifiers": "1.2.
|
|
42
|
-
"@camstack/addon-pipeline": "1.2.
|
|
43
|
-
"@camstack/addon-pipeline-orchestrator": "1.2.
|
|
44
|
-
"@camstack/addon-post-analysis": "1.2.
|
|
40
|
+
"@camstack/addon-notifiers": "1.2.5",
|
|
41
|
+
"@camstack/addon-pipeline": "1.2.8",
|
|
42
|
+
"@camstack/addon-pipeline-orchestrator": "1.2.9",
|
|
43
|
+
"@camstack/addon-post-analysis": "1.2.8",
|
|
45
44
|
"@camstack/sdk": "1.2.4",
|
|
46
45
|
"@camstack/shm-ring": "1.1.4",
|
|
47
|
-
"@camstack/system": "1.2.
|
|
48
|
-
"@camstack/types": "1.2.
|
|
49
|
-
"@camstack/ui-library": "1.2.
|
|
46
|
+
"@camstack/system": "1.2.9",
|
|
47
|
+
"@camstack/types": "1.2.9",
|
|
48
|
+
"@camstack/ui-library": "1.2.6",
|
|
50
49
|
"@fastify/compress": "^9.0.0",
|
|
51
50
|
"@fastify/cookie": "^11.0.2",
|
|
52
51
|
"@fastify/cors": "^11.2.0",
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createAddonsCustomProcedures = createAddonsCustomProcedures;
|
|
4
|
-
/**
|
|
5
|
-
* `api.addons.custom` — generic dispatcher for addon-defined custom actions.
|
|
6
|
-
*
|
|
7
|
-
* Task 7.2 of the device-proxy redesign. Addons declare a catalog of
|
|
8
|
-
* custom actions at boot via `AddonInitResult.customActions` + a single
|
|
9
|
-
* `handleCustomAction(action, input)` handler. The catalog is registered
|
|
10
|
-
* with a per-process `CustomActionRegistry` (Task 7.1). This endpoint is
|
|
11
|
-
* the single tRPC entry point that resolves an `(addonId, action)` pair,
|
|
12
|
-
* validates input + output against the action's Zod schemas, enforces the
|
|
13
|
-
* action's declared auth level, and dispatches to the addon handler.
|
|
14
|
-
*
|
|
15
|
-
* The factory returns a record of procedures (not a router) so the caller
|
|
16
|
-
* can spread it into the existing `addons` namespace:
|
|
17
|
-
*
|
|
18
|
-
* trpcRouter({
|
|
19
|
-
* ...existingAddonsProcedures,
|
|
20
|
-
* ...createAddonsCustomProcedures({ getCustomActionRegistry: ... }),
|
|
21
|
-
* })
|
|
22
|
-
*
|
|
23
|
-
* This avoids `mergeRouters` (which requires sharing the `t` instance
|
|
24
|
-
* across modules) while still mounting the procedure at `api.addons.custom`.
|
|
25
|
-
*/
|
|
26
|
-
const zod_1 = require("zod");
|
|
27
|
-
const server_1 = require("@trpc/server");
|
|
28
|
-
const trpc_middleware_js_1 = require("./trpc/trpc.middleware.js");
|
|
29
|
-
/**
|
|
30
|
-
* Build the procedure record for the `custom` endpoint.
|
|
31
|
-
*
|
|
32
|
-
* The OUTER procedure is `protectedProcedure` — every caller must be
|
|
33
|
-
* authenticated. The INNER per-action auth declared in `spec.auth` is
|
|
34
|
-
* enforced manually by `ensureAuth` because the auth level is not known
|
|
35
|
-
* until after the registry lookup.
|
|
36
|
-
*/
|
|
37
|
-
function createAddonsCustomProcedures(deps) {
|
|
38
|
-
return {
|
|
39
|
-
custom: trpc_middleware_js_1.protectedProcedure
|
|
40
|
-
.input(zod_1.z.object({
|
|
41
|
-
addonId: zod_1.z.string().min(1),
|
|
42
|
-
action: zod_1.z.string().min(1),
|
|
43
|
-
input: zod_1.z.unknown(),
|
|
44
|
-
}))
|
|
45
|
-
.output(zod_1.z.unknown())
|
|
46
|
-
.mutation(async ({ input, ctx }) => {
|
|
47
|
-
const registry = deps.getCustomActionRegistry();
|
|
48
|
-
const entry = registry.resolve(input.addonId, input.action);
|
|
49
|
-
if (!entry) {
|
|
50
|
-
throw new server_1.TRPCError({
|
|
51
|
-
code: 'NOT_FOUND',
|
|
52
|
-
message: `addon '${input.addonId}' has no custom action '${input.action}'`,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
// Per-action authorization. The outer procedure already requires
|
|
56
|
-
// authentication; here we additionally enforce the declared role
|
|
57
|
-
// when it's stricter than 'protected'.
|
|
58
|
-
ensureAuth(ctx, entry.spec.auth);
|
|
59
|
-
// Validate input against the action's declared Zod schema.
|
|
60
|
-
const parsedInput = entry.spec.input.parse(input.input);
|
|
61
|
-
// Dispatch through the addon handler.
|
|
62
|
-
const result = await entry.handler(parsedInput);
|
|
63
|
-
// Validate the addon's output. Crash-early on misbehaving addons.
|
|
64
|
-
return entry.spec.output.parse(result);
|
|
65
|
-
}),
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Enforce the action's declared auth level.
|
|
70
|
-
*
|
|
71
|
-
* Mirrors the role checks performed by `protectedProcedure` and
|
|
72
|
-
* `adminProcedure` in trpc.middleware.ts:
|
|
73
|
-
* - public: no auth
|
|
74
|
-
* - protected: any authenticated user
|
|
75
|
-
* - admin: isAdmin only (scoped tokens bounce)
|
|
76
|
-
*/
|
|
77
|
-
function ensureAuth(ctx, level) {
|
|
78
|
-
if (level === 'public')
|
|
79
|
-
return;
|
|
80
|
-
if (!ctx.user) {
|
|
81
|
-
throw new server_1.TRPCError({ code: 'UNAUTHORIZED' });
|
|
82
|
-
}
|
|
83
|
-
if (level === 'protected')
|
|
84
|
-
return;
|
|
85
|
-
if (level === 'admin') {
|
|
86
|
-
if (!ctx.user.isAdmin) {
|
|
87
|
-
throw new server_1.TRPCError({ code: 'FORBIDDEN', message: 'custom action requires admin' });
|
|
88
|
-
}
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
}
|