corsair 0.1.18 → 0.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/endpoints/bind.d.ts.map +1 -1
- package/dist/core/endpoints/bind.js +21 -18
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/permissions/index.d.ts +20 -5
- package/dist/core/permissions/index.d.ts.map +1 -1
- package/dist/core/permissions/index.js +49 -10
- package/dist/db/index.d.ts +4 -4
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bind.d.ts","sourceRoot":"","sources":["../../../core/endpoints/bind.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAGrD,OAAO,KAAK,EACX,qBAAqB,EAErB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,MAAM,YAAY,CAAC;AAMpB;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,EACxC,SAAS,EACT,KAAK,EACL,GAAG,EACH,IAAI,EACJ,QAAQ,EACR,aAAa,EACb,WAAgB,EAChB,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,QAAQ,EACR,cAAc,GACd,EAAE;IACF,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC3C,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,mBAAmB,CAAC;IACnC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,mGAAmG;IACnG,iBAAiB,CAAC,EAAE;QACnB,IAAI,EAAE,cAAc,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;KAC7C,CAAC;IACF,sGAAsG;IACtG,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACjD,gFAAgF;IAChF,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,qEAAqE;IACrE,cAAc,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;CACpE,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"bind.d.ts","sourceRoot":"","sources":["../../../core/endpoints/bind.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAGrD,OAAO,KAAK,EACX,qBAAqB,EAErB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,MAAM,YAAY,CAAC;AAMpB;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,EACxC,SAAS,EACT,KAAK,EACL,GAAG,EACH,IAAI,EACJ,QAAQ,EACR,aAAa,EACb,WAAgB,EAChB,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,QAAQ,EACR,cAAc,GACd,EAAE;IACF,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC3C,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,mBAAmB,CAAC;IACnC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,mGAAmG;IACnG,iBAAiB,CAAC,EAAE;QACnB,IAAI,EAAE,cAAc,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;KAC7C,CAAC;IACF,sGAAsG;IACtG,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACjD,gFAAgF;IAChF,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,qEAAqE;IACrE,cAAc,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;CACpE,GAAG,IAAI,CA2JP"}
|
|
@@ -33,9 +33,10 @@ export function bindEndpointsRecursively({ endpoints, hooks, ctx, tree, pluginId
|
|
|
33
33
|
const operationPath = [...currentPath, key].join('.');
|
|
34
34
|
const boundFn = async (args) => {
|
|
35
35
|
// ── Permission guard ────────────────────────────────────────────────────────────────
|
|
36
|
+
let onPermissionComplete;
|
|
36
37
|
if (permissionsConfig) {
|
|
37
38
|
const meta = endpointMeta?.[operationPath];
|
|
38
|
-
const permResult = await enforcePermission({
|
|
39
|
+
const { result: permResult, onComplete } = await enforcePermission({
|
|
39
40
|
pluginId,
|
|
40
41
|
endpointPath: operationPath,
|
|
41
42
|
args,
|
|
@@ -51,6 +52,7 @@ export function bindEndpointsRecursively({ endpoints, hooks, ctx, tree, pluginId
|
|
|
51
52
|
});
|
|
52
53
|
if (permResult === 'blocked')
|
|
53
54
|
return null;
|
|
55
|
+
onPermissionComplete = onComplete;
|
|
54
56
|
}
|
|
55
57
|
const call = async (attemptNumber, callCtx, callArgs) => {
|
|
56
58
|
try {
|
|
@@ -105,24 +107,25 @@ export function bindEndpointsRecursively({ endpoints, hooks, ctx, tree, pluginId
|
|
|
105
107
|
};
|
|
106
108
|
const key = keyBuilder ? await keyBuilder(ctx, 'endpoint') : undefined;
|
|
107
109
|
if (!endpointHooks?.before && !endpointHooks?.after) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return (async () => {
|
|
111
|
-
const ctxWithKey = { ...ctx, key };
|
|
112
|
-
const beforeResult = endpointHooks.before
|
|
113
|
-
? await endpointHooks.before(ctxWithKey, args)
|
|
114
|
-
: {
|
|
115
|
-
ctx: ctxWithKey,
|
|
116
|
-
args,
|
|
117
|
-
continue: true,
|
|
118
|
-
passToAfter: undefined,
|
|
119
|
-
};
|
|
120
|
-
if (beforeResult.continue === false)
|
|
121
|
-
return;
|
|
122
|
-
const res = await call(0, beforeResult.ctx, beforeResult.args);
|
|
123
|
-
await endpointHooks.after?.(beforeResult.ctx, res, beforeResult.passToAfter);
|
|
110
|
+
const res = await call(0, { ...ctx, key }, args);
|
|
111
|
+
await onPermissionComplete?.();
|
|
124
112
|
return res;
|
|
125
|
-
}
|
|
113
|
+
}
|
|
114
|
+
const ctxWithKey = { ...ctx, key };
|
|
115
|
+
const beforeResult = endpointHooks.before
|
|
116
|
+
? await endpointHooks.before(ctxWithKey, args)
|
|
117
|
+
: {
|
|
118
|
+
ctx: ctxWithKey,
|
|
119
|
+
args,
|
|
120
|
+
continue: true,
|
|
121
|
+
passToAfter: undefined,
|
|
122
|
+
};
|
|
123
|
+
if (beforeResult.continue === false)
|
|
124
|
+
return;
|
|
125
|
+
const res = await call(0, beforeResult.ctx, beforeResult.args);
|
|
126
|
+
await endpointHooks.after?.(beforeResult.ctx, res, beforeResult.passToAfter);
|
|
127
|
+
await onPermissionComplete?.();
|
|
128
|
+
return res;
|
|
126
129
|
};
|
|
127
130
|
tree[key] = boundFn;
|
|
128
131
|
}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -38,7 +38,7 @@ export type { AllProviders, AuthTypes, BaseProviders } from './constants';
|
|
|
38
38
|
export type { BindEndpoints, BoundEndpointFn, BoundEndpointTree, CorsairContext, CorsairEndpoint, EndpointPathsOf, EndpointTree, } from './endpoints';
|
|
39
39
|
export type { CorsairErrorHandler, ErrorContext, ErrorHandler, ErrorHandlerAndMatchFunction, ErrorMatcher, RetryStrategies, RetryStrategy, } from './errors';
|
|
40
40
|
export type { CorsairInspectMethods, EndpointSchemaResult } from './inspect';
|
|
41
|
-
export type { EnforcePermissionOptions } from './permissions';
|
|
41
|
+
export type { EnforcePermissionOptions, EnforcePermissionResult } from './permissions';
|
|
42
42
|
export type { BeforeHookResult, CorsairIntegration, CorsairKeyBuilder, CorsairKeyBuilderBase, CorsairPlugin, CorsairPluginContext, EndpointHooks, EndpointMetaEntry, EndpointRiskLevel, KeyBuilderContext, PermissionMode, PermissionPolicy, PluginEndpointMeta, PluginPermissionsConfig, RequiredPluginEndpointMeta, RequiredPluginEndpointSchemas, RequiredPluginWebhookSchemas, WebhookHooks, } from './plugins';
|
|
43
43
|
export type { Bivariant, UnionToIntersection } from './utils';
|
|
44
44
|
export type { BindWebhooks, BoundWebhook, BoundWebhookTree, CorsairWebhook, CorsairWebhookHandler, CorsairWebhookMatcher, RawWebhookRequest, WebhookPathsOf, WebhookRequest, WebhookResponse, WebhookTree, } from './webhooks';
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../core/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAG7D,OAAO,KAAK,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAGhF,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAMnE,eAAO,MAAM,gBAAgB,eAAiC,CAAC;AAE/D,MAAM,MAAM,qBAAqB,GAAG;IACnC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;IAClC,QAAQ,EAAE,eAAe,GAAG,SAAS,CAAC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE;QACV,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;KAC9B,CAAC;CACF,CAAC;AAMF;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,CAAC,OAAO,SAAS,SAAS,aAAa,EAAE,EAC3E,MAAM,EAAE,kBAAkB,CAAC,OAAO,CAAC,GAAG;IAAE,YAAY,EAAE,IAAI,CAAA;CAAE,GAC1D,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAEjC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,CAAC,OAAO,SAAS,SAAS,aAAa,EAAE,EAC3E,MAAM,EAAE,kBAAkB,CAAC,OAAO,CAAC,GAAG;IAAE,YAAY,CAAC,EAAE,KAAK,GAAG,SAAS,CAAA;CAAE,GACxE,yBAAyB,CAAC,OAAO,CAAC,CAAC;AA6EtC,YAAY,EACX,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,EACnB,cAAc,EACd,qBAAqB,EACrB,wBAAwB,EACxB,4BAA4B,EAC5B,gBAAgB,GAChB,MAAM,QAAQ,CAAC;AAEhB,OAAO,EACN,gBAAgB,EAChB,uBAAuB,EACvB,2BAA2B,EAC3B,aAAa,EACb,UAAU,EACV,cAAc,EACd,aAAa,EACb,UAAU,EACV,cAAc,EACd,WAAW,EACX,oBAAoB,EACpB,wBAAwB,EACxB,eAAe,GACf,MAAM,QAAQ,CAAC;AAEhB,YAAY,EACX,aAAa,EACb,yBAAyB,EACzB,oBAAoB,GACpB,MAAM,UAAU,CAAC;AAElB,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE1E,YAAY,EACX,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,eAAe,EACf,YAAY,GACZ,MAAM,aAAa,CAAC;AAErB,YAAY,EACX,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACZ,4BAA4B,EAC5B,YAAY,EACZ,eAAe,EACf,aAAa,GACb,MAAM,UAAU,CAAC;AAElB,YAAY,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAC7E,YAAY,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../core/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,13 +17,28 @@ export type EnforcePermissionOptions = {
|
|
|
17
17
|
db?: CorsairDatabase;
|
|
18
18
|
timeoutMs?: number;
|
|
19
19
|
};
|
|
20
|
+
export type EnforcePermissionResult = {
|
|
21
|
+
result: 'allow' | 'blocked';
|
|
22
|
+
/**
|
|
23
|
+
* Called by the endpoint binding layer after the endpoint executes successfully.
|
|
24
|
+
* Marks the permission record as 'completed' (single-use approval consumed).
|
|
25
|
+
* Only present when an 'approved' record was found and the call is allowed through.
|
|
26
|
+
*/
|
|
27
|
+
onComplete?: () => Promise<void>;
|
|
28
|
+
};
|
|
20
29
|
/**
|
|
21
30
|
* Evaluates the permission policy and returns whether the action is allowed.
|
|
22
31
|
*
|
|
23
|
-
*
|
|
24
|
-
* - `'
|
|
25
|
-
* - `'
|
|
26
|
-
*
|
|
32
|
+
* Lifecycle:
|
|
33
|
+
* - `'allow'` → policy permits, caller proceeds normally
|
|
34
|
+
* - `'deny'` → blocked by policy mode; no DB record created
|
|
35
|
+
* - `'require_approval'` → checks for an existing matching permission record first:
|
|
36
|
+
* - `pending` (not expired) → already waiting for approval, returns 'blocked'
|
|
37
|
+
* - `approved` (not expired) → approved and ready; returns 'allow' + onComplete callback
|
|
38
|
+
* that marks the record 'completed' after the endpoint runs
|
|
39
|
+
* - otherwise → creates a new 'pending' record, returns 'blocked'
|
|
40
|
+
*
|
|
41
|
+
* Falls back to deny if no database is configured.
|
|
27
42
|
*/
|
|
28
|
-
export declare function enforcePermission(opts: EnforcePermissionOptions): Promise<
|
|
43
|
+
export declare function enforcePermission(opts: EnforcePermissionOptions): Promise<EnforcePermissionResult>;
|
|
29
44
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../core/permissions/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EACX,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,MAAM,YAAY,CAAC;AAgBpB,4HAA4H;AAC5H,wBAAgB,kBAAkB,CACjC,SAAS,EAAE,iBAAiB,EAC5B,IAAI,EAAE,cAAc,EACpB,QAAQ,CAAC,EAAE,gBAAgB,GACzB,gBAAgB,CAGlB;AAMD,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAsBxD;AAMD,MAAM,MAAM,wBAAwB,GAAG;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,qFAAqF;IACrF,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,SAAS,EAAE,iBAAiB,CAAC;IAC7B,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,kGAAkG;IAClG,EAAE,CAAC,EAAE,eAAe,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../core/permissions/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EACX,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,MAAM,YAAY,CAAC;AAgBpB,4HAA4H;AAC5H,wBAAgB,kBAAkB,CACjC,SAAS,EAAE,iBAAiB,EAC5B,IAAI,EAAE,cAAc,EACpB,QAAQ,CAAC,EAAE,gBAAgB,GACzB,gBAAgB,CAGlB;AAMD,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAsBxD;AAMD,MAAM,MAAM,wBAAwB,GAAG;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,qFAAqF;IACrF,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,SAAS,EAAE,iBAAiB,CAAC;IAC7B,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,kGAAkG;IAClG,EAAE,CAAC,EAAE,eAAe,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACrC,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iBAAiB,CACtC,IAAI,EAAE,wBAAwB,GAC5B,OAAO,CAAC,uBAAuB,CAAC,CA4FlC"}
|
|
@@ -45,24 +45,64 @@ export function parseDurationMs(duration) {
|
|
|
45
45
|
/**
|
|
46
46
|
* Evaluates the permission policy and returns whether the action is allowed.
|
|
47
47
|
*
|
|
48
|
-
*
|
|
49
|
-
* - `'
|
|
50
|
-
* - `'
|
|
51
|
-
*
|
|
48
|
+
* Lifecycle:
|
|
49
|
+
* - `'allow'` → policy permits, caller proceeds normally
|
|
50
|
+
* - `'deny'` → blocked by policy mode; no DB record created
|
|
51
|
+
* - `'require_approval'` → checks for an existing matching permission record first:
|
|
52
|
+
* - `pending` (not expired) → already waiting for approval, returns 'blocked'
|
|
53
|
+
* - `approved` (not expired) → approved and ready; returns 'allow' + onComplete callback
|
|
54
|
+
* that marks the record 'completed' after the endpoint runs
|
|
55
|
+
* - otherwise → creates a new 'pending' record, returns 'blocked'
|
|
56
|
+
*
|
|
57
|
+
* Falls back to deny if no database is configured.
|
|
52
58
|
*/
|
|
53
59
|
export async function enforcePermission(opts) {
|
|
54
60
|
const policy = evaluatePermission(opts.riskLevel, opts.mode, opts.override);
|
|
55
61
|
if (policy === 'allow')
|
|
56
|
-
return 'allow';
|
|
62
|
+
return { result: 'allow' };
|
|
57
63
|
const irreversibleNote = opts.meta?.irreversible ? ' (irreversible)' : '';
|
|
58
64
|
const description = opts.meta?.description
|
|
59
65
|
? `${opts.meta.description}${irreversibleNote}`
|
|
60
66
|
: `${opts.pluginId}.${opts.endpointPath}${irreversibleNote}`;
|
|
61
67
|
if (policy === 'deny' || !opts.db) {
|
|
62
68
|
console.log(`[corsair/${opts.pluginId}] '${opts.endpointPath}' blocked — denied by permission mode '${opts.mode}'.`, `\n Action: ${description}`, `\n To allow this, update the permission mode or add an override in your corsair config.`);
|
|
63
|
-
return 'blocked';
|
|
69
|
+
return { result: 'blocked' };
|
|
70
|
+
}
|
|
71
|
+
const argsJson = JSON.stringify(opts.args);
|
|
72
|
+
const now = new Date().toISOString();
|
|
73
|
+
// Check for an existing, non-expired permission record for this plugin + endpoint + args
|
|
74
|
+
const existing = await opts.db.db
|
|
75
|
+
.selectFrom('corsair_permissions')
|
|
76
|
+
.selectAll()
|
|
77
|
+
.where('plugin', '=', opts.pluginId)
|
|
78
|
+
.where('endpoint', '=', opts.endpointPath)
|
|
79
|
+
.where('args', '=', argsJson)
|
|
80
|
+
.where('expires_at', '>', now)
|
|
81
|
+
.where('status', 'in', ['pending', 'approved'])
|
|
82
|
+
.orderBy('created_at', 'desc')
|
|
83
|
+
.limit(1)
|
|
84
|
+
.executeTakeFirst();
|
|
85
|
+
if (existing) {
|
|
86
|
+
if (existing.status === 'approved') {
|
|
87
|
+
// Single-use: let the call through; onComplete will mark it 'completed'
|
|
88
|
+
const db = opts.db;
|
|
89
|
+
const permissionId = existing.id;
|
|
90
|
+
return {
|
|
91
|
+
result: 'allow',
|
|
92
|
+
onComplete: async () => {
|
|
93
|
+
await db.db
|
|
94
|
+
.updateTable('corsair_permissions')
|
|
95
|
+
.set({ status: 'completed', updated_at: new Date() })
|
|
96
|
+
.where('id', '=', permissionId)
|
|
97
|
+
.execute();
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
// status === 'pending': already waiting for approval, don't create a duplicate
|
|
102
|
+
console.log(`[corsair/${opts.pluginId}] '${opts.endpointPath}' blocked — approval already pending.`, `\n Action: ${description}`, `\n Permission ID: ${existing.id}`, `\n Use the token to approve or deny this request.`);
|
|
103
|
+
return { result: 'blocked' };
|
|
64
104
|
}
|
|
65
|
-
//
|
|
105
|
+
// No existing actionable record — create a new pending approval request
|
|
66
106
|
const id = uuidv4();
|
|
67
107
|
const token = randomBytes(32).toString('hex');
|
|
68
108
|
const timeoutMs = opts.timeoutMs ?? 10 * 60 * 1_000;
|
|
@@ -76,12 +116,11 @@ export async function enforcePermission(opts) {
|
|
|
76
116
|
token,
|
|
77
117
|
plugin: opts.pluginId,
|
|
78
118
|
endpoint: opts.endpointPath,
|
|
79
|
-
|
|
80
|
-
args: JSON.stringify(opts.args),
|
|
119
|
+
args: argsJson,
|
|
81
120
|
status: 'pending',
|
|
82
121
|
expires_at: expiresAt,
|
|
83
122
|
})
|
|
84
123
|
.execute();
|
|
85
124
|
console.log(`[corsair/${opts.pluginId}] '${opts.endpointPath}' blocked — approval required.`, `\n Action: ${description}`, `\n Permission ID: ${id}`, `\n Permission token: ${token}`, `\n Expires at: ${expiresAt}`, `\n Use the token to approve or deny this request.`);
|
|
86
|
-
return 'blocked';
|
|
125
|
+
return { result: 'blocked' };
|
|
87
126
|
}
|
package/dist/db/index.d.ts
CHANGED
|
@@ -122,14 +122,14 @@ export declare const CorsairPermissionsSchema: z.ZodObject<{
|
|
|
122
122
|
/** Full public review page URL (ngrok URL + path + token query param) */
|
|
123
123
|
review_url: z.ZodOptional<z.ZodString>;
|
|
124
124
|
/** Current state of the approval request */
|
|
125
|
-
status: z.ZodDefault<z.ZodEnum<["pending", "approved", "denied", "expired"]>>;
|
|
125
|
+
status: z.ZodDefault<z.ZodEnum<["pending", "approved", "completed", "denied", "expired"]>>;
|
|
126
126
|
/** ISO8601 timestamp — when this request becomes invalid */
|
|
127
127
|
expires_at: z.ZodString;
|
|
128
128
|
}, "strip", z.ZodTypeAny, {
|
|
129
129
|
id: string;
|
|
130
130
|
created_at: Date;
|
|
131
131
|
updated_at: Date;
|
|
132
|
-
status: "pending" | "approved" | "denied" | "expired";
|
|
132
|
+
status: "pending" | "completed" | "approved" | "denied" | "expired";
|
|
133
133
|
token: string;
|
|
134
134
|
plugin: string;
|
|
135
135
|
endpoint: string;
|
|
@@ -147,7 +147,7 @@ export declare const CorsairPermissionsSchema: z.ZodObject<{
|
|
|
147
147
|
endpoint: string;
|
|
148
148
|
args: string;
|
|
149
149
|
expires_at: string;
|
|
150
|
-
status?: "pending" | "approved" | "denied" | "expired" | undefined;
|
|
150
|
+
status?: "pending" | "completed" | "approved" | "denied" | "expired" | undefined;
|
|
151
151
|
session_id?: string | undefined;
|
|
152
152
|
callback_url?: string | undefined;
|
|
153
153
|
review_url?: string | undefined;
|
|
@@ -164,7 +164,7 @@ export type CorsairPermissionInsert = {
|
|
|
164
164
|
session_id?: string;
|
|
165
165
|
callback_url?: string;
|
|
166
166
|
review_url?: string;
|
|
167
|
-
status?: 'pending' | 'approved' | 'denied' | 'expired';
|
|
167
|
+
status?: 'pending' | 'approved' | 'completed' | 'denied' | 'expired';
|
|
168
168
|
expires_at: string;
|
|
169
169
|
};
|
|
170
170
|
export type CorsairTableName = 'corsair_integrations' | 'corsair_accounts' | 'corsair_entities' | 'corsair_events' | 'corsair_permissions' | (string & {});
|
package/dist/db/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../db/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;EAYpC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAM3E,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;EAehC,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAMnE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkBhC,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAMlE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;EAgB9B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAM/D,eAAO,MAAM,wBAAwB;;;;IAKpC,uFAAuF;;IAEvF,uCAAuC;;IAEvC,6DAA6D;;IAE7D,6EAA6E;;IAE7E,8FAA8F;;IAE9F,gFAAgF;;IAEhF,yEAAyE;;IAEzE,4CAA4C;;IAI5C,4DAA4D;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAE3D,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAEzE,MAAM,MAAM,uBAAuB,GAAG;IACrC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,IAAI,CAAC;IAClB,UAAU,CAAC,EAAE,IAAI,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../db/index.ts"],"names":[],"mappings":"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"}
|
package/dist/db/index.js
CHANGED
|
@@ -89,7 +89,7 @@ export const CorsairPermissionsSchema = z.object({
|
|
|
89
89
|
review_url: z.string().optional(),
|
|
90
90
|
/** Current state of the approval request */
|
|
91
91
|
status: z
|
|
92
|
-
.enum(['pending', 'approved', 'denied', 'expired'])
|
|
92
|
+
.enum(['pending', 'approved', 'completed', 'denied', 'expired'])
|
|
93
93
|
.default('pending'),
|
|
94
94
|
/** ISO8601 timestamp — when this request becomes invalid */
|
|
95
95
|
expires_at: z.string(),
|