@selvajs/server 1.5.0-beta.1 → 1.5.0-beta.11
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 +17 -17
- package/dist/access/guards.d.ts.map +1 -1
- package/dist/access/guards.js +2 -6
- package/dist/access/guards.js.map +1 -1
- package/dist/api/bodies.d.ts +0 -2
- package/dist/api/bodies.d.ts.map +1 -1
- package/dist/api/deps.d.ts +16 -1
- package/dist/api/deps.d.ts.map +1 -1
- package/dist/api/deps.js +3 -1
- package/dist/api/deps.js.map +1 -1
- package/dist/api/errors.d.ts +11 -0
- package/dist/api/errors.d.ts.map +1 -1
- package/dist/api/errors.js +15 -1
- package/dist/api/errors.js.map +1 -1
- package/dist/api/idempotency-http.d.ts.map +1 -0
- package/dist/api/idempotency-http.js.map +1 -0
- package/dist/api/idempotency.d.ts +58 -0
- package/dist/api/idempotency.d.ts.map +1 -0
- package/dist/api/idempotency.js +130 -0
- package/dist/api/idempotency.js.map +1 -0
- package/dist/api/index.d.ts +3 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +3 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/openapi.d.ts +84 -0
- package/dist/api/openapi.d.ts.map +1 -0
- package/dist/api/openapi.js +247 -0
- package/dist/api/openapi.js.map +1 -0
- package/dist/api/rate-limit.d.ts +57 -0
- package/dist/api/rate-limit.d.ts.map +1 -0
- package/dist/api/rate-limit.js +108 -0
- package/dist/api/rate-limit.js.map +1 -0
- package/dist/api/respond.d.ts +14 -9
- package/dist/api/respond.d.ts.map +1 -1
- package/dist/api/respond.js +49 -17
- package/dist/api/respond.js.map +1 -1
- package/dist/api/scope.d.ts +3 -0
- package/dist/api/scope.d.ts.map +1 -1
- package/dist/api/scope.js +8 -2
- package/dist/api/scope.js.map +1 -1
- package/dist/compute/index.d.ts +0 -1
- package/dist/compute/index.d.ts.map +1 -1
- package/dist/compute/index.js +0 -1
- package/dist/compute/index.js.map +1 -1
- package/dist/definitions/definition-service.d.ts.map +1 -1
- package/dist/definitions/definition-service.js +7 -1
- package/dist/definitions/definition-service.js.map +1 -1
- package/dist/definitions/index.d.ts +1 -1
- package/dist/definitions/index.d.ts.map +1 -1
- package/dist/definitions/index.js +1 -1
- package/dist/definitions/index.js.map +1 -1
- package/dist/definitions/visibility.d.ts +35 -1
- package/dist/definitions/visibility.d.ts.map +1 -1
- package/dist/definitions/visibility.js +91 -5
- package/dist/definitions/visibility.js.map +1 -1
- package/dist/handlers/apiTokens.d.ts +46 -5
- package/dist/handlers/apiTokens.d.ts.map +1 -1
- package/dist/handlers/apiTokens.js +70 -20
- package/dist/handlers/apiTokens.js.map +1 -1
- package/dist/handlers/definitions.d.ts +7 -1
- package/dist/handlers/definitions.d.ts.map +1 -1
- package/dist/handlers/definitions.js +28 -9
- package/dist/handlers/definitions.js.map +1 -1
- package/dist/handlers/index.d.ts +2 -1
- package/dist/handlers/index.d.ts.map +1 -1
- package/dist/handlers/index.js +2 -1
- package/dist/handlers/index.js.map +1 -1
- package/dist/handlers/me.d.ts.map +1 -1
- package/dist/handlers/me.js +9 -1
- package/dist/handlers/me.js.map +1 -1
- package/dist/handlers/oauthConsent.d.ts +49 -0
- package/dist/handlers/oauthConsent.d.ts.map +1 -0
- package/dist/handlers/oauthConsent.js +76 -0
- package/dist/handlers/oauthConsent.js.map +1 -0
- package/dist/handlers/projects.d.ts +5 -0
- package/dist/handlers/projects.d.ts.map +1 -1
- package/dist/handlers/projects.js +19 -3
- package/dist/handlers/projects.js.map +1 -1
- package/dist/handlers/services.d.ts +1 -1
- package/dist/handlers/services.d.ts.map +1 -1
- package/dist/handlers/services.js.map +1 -1
- package/dist/http/api-token.d.ts +27 -3
- package/dist/http/api-token.d.ts.map +1 -1
- package/dist/http/api-token.js +62 -6
- package/dist/http/api-token.js.map +1 -1
- package/dist/http/csrf.d.ts +18 -0
- package/dist/http/csrf.d.ts.map +1 -0
- package/dist/http/csrf.js +37 -0
- package/dist/http/csrf.js.map +1 -0
- package/dist/http/index.d.ts +2 -1
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/index.js +2 -1
- package/dist/http/index.js.map +1 -1
- package/dist/oauth/index.d.ts +163 -0
- package/dist/oauth/index.d.ts.map +1 -0
- package/dist/oauth/index.js +466 -0
- package/dist/oauth/index.js.map +1 -0
- package/dist/organizations/index.d.ts +1 -0
- package/dist/organizations/index.d.ts.map +1 -1
- package/dist/organizations/index.js +1 -0
- package/dist/organizations/index.js.map +1 -1
- package/dist/organizations/user-memberships.d.ts +11 -0
- package/dist/organizations/user-memberships.d.ts.map +1 -0
- package/dist/organizations/user-memberships.js +23 -0
- package/dist/organizations/user-memberships.js.map +1 -0
- package/dist/testing/harness.d.ts +3 -1
- package/dist/testing/harness.d.ts.map +1 -1
- package/dist/testing/harness.js +6 -1
- package/dist/testing/harness.js.map +1 -1
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +1 -1
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/scenarios.d.ts +6 -0
- package/dist/testing/scenarios.d.ts.map +1 -1
- package/dist/testing/scenarios.js +12 -1
- package/dist/testing/scenarios.js.map +1 -1
- package/dist/tokens/api-token-codec.d.ts +2 -2
- package/dist/tokens/api-token-codec.js +2 -2
- package/dist/tokens/api-token-holder.d.ts +30 -0
- package/dist/tokens/api-token-holder.d.ts.map +1 -0
- package/dist/tokens/api-token-holder.js +27 -0
- package/dist/tokens/api-token-holder.js.map +1 -0
- package/dist/tokens/index.d.ts +1 -0
- package/dist/tokens/index.d.ts.map +1 -1
- package/dist/tokens/index.js +1 -0
- package/dist/tokens/index.js.map +1 -1
- package/package.json +15 -10
- package/dist/compute/idempotency-http.d.ts.map +0 -1
- package/dist/compute/idempotency-http.js.map +0 -1
- /package/dist/{compute → api}/idempotency-http.d.ts +0 -0
- /package/dist/{compute → api}/idempotency-http.js +0 -0
package/dist/api/respond.js
CHANGED
|
@@ -7,16 +7,11 @@
|
|
|
7
7
|
* to build an `ApiRequest` and call `runHandler`; one that does not can reuse
|
|
8
8
|
* `toErrorBody` and serialize itself.
|
|
9
9
|
*/
|
|
10
|
-
import { ApiErrorCode, isApiError } from './errors.js';
|
|
10
|
+
import { ApiErrorCode, isApiError, toErrorBody } from './errors.js';
|
|
11
11
|
import { actionForMethod, assertScope } from './scope.js';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
body.fields = err.fields;
|
|
16
|
-
if (err.details)
|
|
17
|
-
body.details = err.details;
|
|
18
|
-
return body;
|
|
19
|
-
}
|
|
12
|
+
import { chargeApiRateLimit, defaultApiRateLimiter, rateLimitedResponse, withRateLimitHeaders } from './rate-limit.js';
|
|
13
|
+
import { defaultApiIdempotencyStore, fingerprintBody, idempotencyCallerId, readIdempotencyKey, requestFingerprint, runIdempotent } from './idempotency.js';
|
|
14
|
+
export { toErrorBody } from './errors.js';
|
|
20
15
|
function toResponse(result) {
|
|
21
16
|
if (result instanceof Response)
|
|
22
17
|
return result;
|
|
@@ -29,14 +24,8 @@ function toResponse(result) {
|
|
|
29
24
|
});
|
|
30
25
|
}
|
|
31
26
|
/** Run a handler and serialize whatever comes out, including failures. */
|
|
32
|
-
export async function runHandler(handler, req, { fallback, mapError, action, scopeTarget }) {
|
|
33
|
-
|
|
34
|
-
if (req.ctx?.apiScope) {
|
|
35
|
-
assertScope(req.ctx, action ?? actionForMethod(req.request.method), scopeTarget ? await scopeTarget(req) : undefined);
|
|
36
|
-
}
|
|
37
|
-
return toResponse(await handler(req));
|
|
38
|
-
}
|
|
39
|
-
catch (err) {
|
|
27
|
+
export async function runHandler(handler, req, { fallback, mapError, action, scopeTarget, anyScope, idempotent }) {
|
|
28
|
+
const fail = (err) => {
|
|
40
29
|
if (isApiError(err)) {
|
|
41
30
|
return toResponse({ status: err.status, body: toErrorBody(err) });
|
|
42
31
|
}
|
|
@@ -55,6 +44,49 @@ export async function runHandler(handler, req, { fallback, mapError, action, sco
|
|
|
55
44
|
status: 500,
|
|
56
45
|
body: { message: fallback, code: ApiErrorCode.INTERNAL }
|
|
57
46
|
});
|
|
47
|
+
};
|
|
48
|
+
let verdict;
|
|
49
|
+
try {
|
|
50
|
+
// Charged before the scope check: `scopeTarget` may read the database,
|
|
51
|
+
// and a throttled key must not reach it.
|
|
52
|
+
const limiter = req.deps.apiRateLimiter === undefined ? defaultApiRateLimiter() : req.deps.apiRateLimiter;
|
|
53
|
+
verdict = await chargeApiRateLimit(req.ctx, limiter);
|
|
54
|
+
if (verdict && !verdict.allowed)
|
|
55
|
+
return rateLimitedResponse(verdict);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
return fail(err);
|
|
59
|
+
}
|
|
60
|
+
let res;
|
|
61
|
+
try {
|
|
62
|
+
if (req.ctx?.apiScope && !anyScope) {
|
|
63
|
+
assertScope(req.ctx, action ?? actionForMethod(req.request.method), scopeTarget ? await scopeTarget(req) : undefined);
|
|
64
|
+
}
|
|
65
|
+
const run = async () => {
|
|
66
|
+
try {
|
|
67
|
+
return toResponse(await handler(req));
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
return fail(err);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const clientKey = idempotent && req.ctx ? readIdempotencyKey(req.request) : null;
|
|
74
|
+
if (clientKey && req.ctx) {
|
|
75
|
+
const fingerprint = await requestFingerprint(req.request.method, req.url, await fingerprintBody(req.request));
|
|
76
|
+
res = await runIdempotent({
|
|
77
|
+
store: req.deps.idempotency ?? defaultApiIdempotencyStore(),
|
|
78
|
+
callerId: idempotencyCallerId(req.ctx),
|
|
79
|
+
clientKey,
|
|
80
|
+
fingerprint
|
|
81
|
+
}, run);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
res = await run();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
res = fail(err);
|
|
58
89
|
}
|
|
90
|
+
return withRateLimitHeaders(res, verdict);
|
|
59
91
|
}
|
|
60
92
|
//# sourceMappingURL=respond.js.map
|
package/dist/api/respond.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"respond.js","sourceRoot":"","sources":["../../src/api/respond.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAY,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"respond.js","sourceRoot":"","sources":["../../src/api/respond.ts"],"names":[],"mappings":"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"}
|
package/dist/api/scope.d.ts
CHANGED
|
@@ -17,6 +17,9 @@ export declare function projectScopeTarget(param?: string): (req: ApiRequest) =>
|
|
|
17
17
|
/**
|
|
18
18
|
* Scope target for routes addressed by a definition guid param. Loads the
|
|
19
19
|
* record so a project-scoped key reaches the definitions inside its project.
|
|
20
|
+
*
|
|
21
|
+
* A definition outside the key's org resolves like a missing one: otherwise the
|
|
22
|
+
* 403 detail would confirm the guid exists and name its project.
|
|
20
23
|
*/
|
|
21
24
|
export declare function definitionScopeTarget(param?: string): (req: ApiRequest) => Promise<ScopeTarget>;
|
|
22
25
|
//# sourceMappingURL=scope.d.ts.map
|
package/dist/api/scope.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/api/scope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAE9D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAC1B,GAAG,EAAE,cAAc,GAAG,SAAS,EAC/B,MAAM,EAAE,cAAc,EACtB,MAAM,CAAC,EAAE,WAAW,GAClB,IAAI,CAMN;AAeD,wEAAwE;AACxE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG1D;AAQD,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,KAAK,SAAO,IACtC,KAAK,UAAU,KAAG,WAAW,CACrC;AAED
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/api/scope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAE9D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAC1B,GAAG,EAAE,cAAc,GAAG,SAAS,EAC/B,MAAM,EAAE,cAAc,EACtB,MAAM,CAAC,EAAE,WAAW,GAClB,IAAI,CAMN;AAeD,wEAAwE;AACxE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG1D;AAQD,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,KAAK,SAAO,IACtC,KAAK,UAAU,KAAG,WAAW,CACrC;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,SAAS,IACrC,KAAK,UAAU,KAAG,OAAO,CAAC,WAAW,CAAC,CAQpD"}
|
package/dist/api/scope.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { scopeAllows } from '@selvajs/platform';
|
|
1
|
+
import { outsideTokenOrg, scopeAllows } from '@selvajs/platform';
|
|
2
2
|
import { apiError, ApiErrorCode } from './errors.js';
|
|
3
3
|
/** The default action for a method: reads are `read`, everything else `write`. */
|
|
4
4
|
export function actionForMethod(method) {
|
|
@@ -50,6 +50,9 @@ export function projectScopeTarget(param = 'id') {
|
|
|
50
50
|
/**
|
|
51
51
|
* Scope target for routes addressed by a definition guid param. Loads the
|
|
52
52
|
* record so a project-scoped key reaches the definitions inside its project.
|
|
53
|
+
*
|
|
54
|
+
* A definition outside the key's org resolves like a missing one: otherwise the
|
|
55
|
+
* 403 detail would confirm the guid exists and name its project.
|
|
53
56
|
*/
|
|
54
57
|
export function definitionScopeTarget(param = 'guid') {
|
|
55
58
|
return async (req) => {
|
|
@@ -57,7 +60,10 @@ export function definitionScopeTarget(param = 'guid') {
|
|
|
57
60
|
if (!definitionId || !req.ctx)
|
|
58
61
|
return { definitionId };
|
|
59
62
|
const record = await req.deps.definitionMeta.get(req.ctx, definitionId);
|
|
60
|
-
|
|
63
|
+
const project = record ? await req.deps.projects.getProject(req.ctx, record.projectId) : null;
|
|
64
|
+
if (!project || outsideTokenOrg(req.ctx, project.orgId))
|
|
65
|
+
return { definitionId };
|
|
66
|
+
return { definitionId, projectId: project.id };
|
|
61
67
|
};
|
|
62
68
|
}
|
|
63
69
|
//# sourceMappingURL=scope.js.map
|
package/dist/api/scope.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/api/scope.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/api/scope.ts"],"names":[],"mappings":"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"}
|
package/dist/compute/index.d.ts
CHANGED
|
@@ -7,5 +7,4 @@ export { resolveServerForOrg } from './resolve-server.js';
|
|
|
7
7
|
export { ComputeServerUnconfiguredError } from './errors.js';
|
|
8
8
|
export { evictChangedServers, type ServerConnection } from './evict-changed-servers.js';
|
|
9
9
|
export { validateIncomingServers, resolveApiKey, storedKeysById, type IncomingServerBase } from './server-config-write.js';
|
|
10
|
-
export { idempotencyKey, toStoredResponse, fromStoredResponse, IDEMPOTENCY_REPLAYED_HEADER, type StoredResponse } from './idempotency-http.js';
|
|
11
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/compute/index.ts"],"names":[],"mappings":"AAWA,OAAO,EACN,oBAAoB,EACpB,eAAe,EACf,kBAAkB,EAClB,QAAQ,EACR,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,MAAM,aAAa,CAAC;AAErB,OAAO,EACN,wBAAwB,EACxB,gBAAgB,EAChB,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,EACpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACN,sBAAsB,EACtB,4BAA4B,EAC5B,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACN,yBAAyB,EACzB,6BAA6B,EAC7B,cAAc,EACd,MAAM,eAAe,CAAC;AAEvB,OAAO,EACN,6BAA6B,EAC7B,eAAe,EACf,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACxF,OAAO,EACN,uBAAuB,EACvB,aAAa,EACb,cAAc,EACd,KAAK,kBAAkB,EACvB,MAAM,0BAA0B,CAAC
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/compute/index.ts"],"names":[],"mappings":"AAWA,OAAO,EACN,oBAAoB,EACpB,eAAe,EACf,kBAAkB,EAClB,QAAQ,EACR,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,MAAM,aAAa,CAAC;AAErB,OAAO,EACN,wBAAwB,EACxB,gBAAgB,EAChB,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,EACpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACN,sBAAsB,EACtB,4BAA4B,EAC5B,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACN,yBAAyB,EACzB,6BAA6B,EAC7B,cAAc,EACd,MAAM,eAAe,CAAC;AAEvB,OAAO,EACN,6BAA6B,EAC7B,eAAe,EACf,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACxF,OAAO,EACN,uBAAuB,EACvB,aAAa,EACb,cAAc,EACd,KAAK,kBAAkB,EACvB,MAAM,0BAA0B,CAAC"}
|
package/dist/compute/index.js
CHANGED
|
@@ -17,5 +17,4 @@ export { resolveServerForOrg } from './resolve-server.js';
|
|
|
17
17
|
export { ComputeServerUnconfiguredError } from './errors.js';
|
|
18
18
|
export { evictChangedServers } from './evict-changed-servers.js';
|
|
19
19
|
export { validateIncomingServers, resolveApiKey, storedKeysById } from './server-config-write.js';
|
|
20
|
-
export { idempotencyKey, toStoredResponse, fromStoredResponse, IDEMPOTENCY_REPLAYED_HEADER } from './idempotency-http.js';
|
|
21
20
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/compute/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,EAAE;AACF,kGAAkG;AAClG,mGAAmG;AACnG,oBAAoB;AACpB,EAAE;AACF,6FAA6F;AAC7F,6FAA6F;AAC7F,8FAA8F;AAC9F,qCAAqC;AAErC,OAAO,EACN,oBAAoB,EACpB,eAAe,EACf,kBAAkB,EAClB,QAAQ,EAGR,MAAM,aAAa,CAAC;AAErB,OAAO,EACN,wBAAwB,EACxB,gBAAgB,EAIhB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACN,sBAAsB,EACtB,4BAA4B,EAI5B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACN,yBAAyB,EACzB,6BAA6B,EAC7B,cAAc,EACd,MAAM,eAAe,CAAC;AAEvB,OAAO,EACN,6BAA6B,EAC7B,eAAe,EAGf,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAyB,MAAM,4BAA4B,CAAC;AACxF,OAAO,EACN,uBAAuB,EACvB,aAAa,EACb,cAAc,EAEd,MAAM,0BAA0B,CAAC
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/compute/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,EAAE;AACF,kGAAkG;AAClG,mGAAmG;AACnG,oBAAoB;AACpB,EAAE;AACF,6FAA6F;AAC7F,6FAA6F;AAC7F,8FAA8F;AAC9F,qCAAqC;AAErC,OAAO,EACN,oBAAoB,EACpB,eAAe,EACf,kBAAkB,EAClB,QAAQ,EAGR,MAAM,aAAa,CAAC;AAErB,OAAO,EACN,wBAAwB,EACxB,gBAAgB,EAIhB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACN,sBAAsB,EACtB,4BAA4B,EAI5B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACN,yBAAyB,EACzB,6BAA6B,EAC7B,cAAc,EACd,MAAM,eAAe,CAAC;AAEvB,OAAO,EACN,6BAA6B,EAC7B,eAAe,EAGf,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAyB,MAAM,4BAA4B,CAAC;AACxF,OAAO,EACN,uBAAuB,EACvB,aAAa,EACb,cAAc,EAEd,MAAM,0BAA0B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definition-service.d.ts","sourceRoot":"","sources":["../../src/definitions/definition-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,QAAQ,EACR,MAAM,mBAAmB,CAAC;AAG3B;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;GAQG;AACH,qBAAa,iBAAiB;IAE5B,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,OAAO;gBADP,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,gBAAgB;IAG5B,MAAM,CACX,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,sBAAsB,EAC7B,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,QAAQ,GACd,OAAO,CAAC;QAAE,MAAM,EAAE,gBAAgB,CAAC;QAAC,OAAO,EAAE,iBAAiB,CAAA;KAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"definition-service.d.ts","sourceRoot":"","sources":["../../src/definitions/definition-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,QAAQ,EACR,MAAM,mBAAmB,CAAC;AAG3B;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;GAQG;AACH,qBAAa,iBAAiB;IAE5B,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,OAAO;gBADP,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,gBAAgB;IAG5B,MAAM,CACX,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,sBAAsB,EAC7B,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,QAAQ,GACd,OAAO,CAAC;QAAE,MAAM,EAAE,gBAAgB,CAAC;QAAC,OAAO,EAAE,iBAAiB,CAAA;KAAE,CAAC;IA6DpE;;;OAGG;IACG,aAAa,CAClB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,iBAAiB,EACtB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,QAAQ,EAChB,UAAU,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,iBAAiB,CAAC;IAuC7B;;;OAGG;IACG,OAAO,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAoB1F,aAAa,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUlF,UAAU,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxF,cAAc,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAQzF,MAAM,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAW9D"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { ProviderError, definitionPaths } from '@selvajs/platform';
|
|
2
|
+
import { ProviderError, definitionPaths, toSourceDocumentId } from '@selvajs/platform';
|
|
3
3
|
/**
|
|
4
4
|
* Orchestrates writes spanning IDataProvider + IStorageProvider. Application
|
|
5
5
|
* orchestration, not platform contract — hence not in @selvajs/platform.
|
|
@@ -37,6 +37,7 @@ export class DefinitionService {
|
|
|
37
37
|
nextVersionNumber: 2,
|
|
38
38
|
liveVersionId: null,
|
|
39
39
|
draftVersionId: null,
|
|
40
|
+
sourceDocumentId: toSourceDocumentId(schema.documentId) ?? undefined,
|
|
40
41
|
createdAt: now,
|
|
41
42
|
updatedAt: now,
|
|
42
43
|
deletedAt: null
|
|
@@ -102,6 +103,11 @@ export class DefinitionService {
|
|
|
102
103
|
};
|
|
103
104
|
await this.data.definitions.createVersion(ctx, version);
|
|
104
105
|
await this.data.definitions.setDraftVersion(ctx, guid, versionId);
|
|
106
|
+
// A schema without a GUID leaves the old one: it says nothing about which file this is.
|
|
107
|
+
const sourceDocumentId = toSourceDocumentId(schema.documentId);
|
|
108
|
+
if (sourceDocumentId && sourceDocumentId !== existing.sourceDocumentId) {
|
|
109
|
+
await this.data.definitions.update(ctx, guid, { sourceDocumentId });
|
|
110
|
+
}
|
|
105
111
|
return version;
|
|
106
112
|
}
|
|
107
113
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definition-service.js","sourceRoot":"","sources":["../../src/definitions/definition-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAWzC,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"definition-service.js","sourceRoot":"","sources":["../../src/definitions/definition-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,5 +2,5 @@ export { DefinitionService, type CreateDefinitionRecord } from './definition-ser
|
|
|
2
2
|
export { fetchSchemaFromCompute, postSchemaFormData, assertSupportedSchemaVersion, assertCamelCaseSchema, readSchemaResults, SchemaExtractionError } from './schema-extraction.js';
|
|
3
3
|
export type { SchemaExtractionResult } from './schema-extraction.js';
|
|
4
4
|
export { createDefinitionLoader, DefinitionLoadError, type DefinitionChannel, type DefinitionLoader, type DefinitionLoaderDeps, type DefinitionLoadErrorKind, type DefinitionLoadOptions, type LoadedDefinition } from './load-for-render.js';
|
|
5
|
-
export { resolveAccessibleProjects, listVisibleDefinitions, getVisibleDefinition, loadVisibleVersion, type VisibilityDeps, type AccessibleProjectSet, type ListVisibleDefinitionsResult } from './visibility.js';
|
|
5
|
+
export { resolveAccessibleProjects, canCreateDefinitionInOrg, listVisibleDefinitions, listEditableDefinitionsByDocument, getVisibleDefinition, loadVisibleDefinition, mayUploadToDefinition, loadVisibleVersion, type VisibilityDeps, type VisibleDefinition, type AccessibleProjectSet, type ListVisibleDefinitionsResult } from './visibility.js';
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/definitions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEzF,OAAO,EACN,sBAAsB,EACtB,kBAAkB,EAClB,4BAA4B,EAC5B,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAErE,OAAO,EACN,sBAAsB,EACtB,mBAAmB,EACnB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACN,yBAAyB,EACzB,sBAAsB,EACtB,oBAAoB,EACpB,kBAAkB,EAClB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EACjC,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/definitions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEzF,OAAO,EACN,sBAAsB,EACtB,kBAAkB,EAClB,4BAA4B,EAC5B,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAErE,OAAO,EACN,sBAAsB,EACtB,mBAAmB,EACnB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACN,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,EACtB,iCAAiC,EACjC,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAClB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EACjC,MAAM,iBAAiB,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { DefinitionService } from './definition-service.js';
|
|
2
2
|
export { fetchSchemaFromCompute, postSchemaFormData, assertSupportedSchemaVersion, assertCamelCaseSchema, readSchemaResults, SchemaExtractionError } from './schema-extraction.js';
|
|
3
3
|
export { createDefinitionLoader, DefinitionLoadError } from './load-for-render.js';
|
|
4
|
-
export { resolveAccessibleProjects, listVisibleDefinitions, getVisibleDefinition, loadVisibleVersion } from './visibility.js';
|
|
4
|
+
export { resolveAccessibleProjects, canCreateDefinitionInOrg, listVisibleDefinitions, listEditableDefinitionsByDocument, getVisibleDefinition, loadVisibleDefinition, mayUploadToDefinition, loadVisibleVersion } from './visibility.js';
|
|
5
5
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/definitions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAA+B,MAAM,yBAAyB,CAAC;AAEzF,OAAO,EACN,sBAAsB,EACtB,kBAAkB,EAClB,4BAA4B,EAC5B,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACN,sBAAsB,EACtB,mBAAmB,EAOnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACN,yBAAyB,EACzB,sBAAsB,EACtB,oBAAoB,EACpB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/definitions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAA+B,MAAM,yBAAyB,CAAC;AAEzF,OAAO,EACN,sBAAsB,EACtB,kBAAkB,EAClB,4BAA4B,EAC5B,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACN,sBAAsB,EACtB,mBAAmB,EAOnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACN,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,EACtB,iCAAiC,EACjC,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAKlB,MAAM,iBAAiB,CAAC"}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* reads regardless of N. Anything added here must keep that property — a
|
|
14
14
|
* per-project `await` inside a loop reintroduces the N+1 this replaced.
|
|
15
15
|
*/
|
|
16
|
-
import type { DefinitionListOptions, DefinitionRecord, DefinitionVersion, OrgMember, Page, Project, ProjectMember, RequestContext } from '@selvajs/platform';
|
|
16
|
+
import type { DefinitionListOptions, DefinitionRecord, DefinitionVersion, OrgMember, Page, PlatformProjectGrant, Project, ProjectMember, RequestContext } from '@selvajs/platform';
|
|
17
17
|
import type { SelvaDeps } from '../api/deps.js';
|
|
18
18
|
/**
|
|
19
19
|
* The stores this module reads. Required at every call site.
|
|
@@ -38,6 +38,8 @@ export interface AccessibleProjectSet {
|
|
|
38
38
|
memberByProjectId: Map<string, ProjectMember | null>;
|
|
39
39
|
/** The caller's org-membership row per scanned org (`null` = not a member). */
|
|
40
40
|
orgMemberByOrgId: Map<string, OrgMember | null>;
|
|
41
|
+
/** Grants per scanned `platform` project; absent for every other visibility. */
|
|
42
|
+
grantsByProjectId: Map<string, PlatformProjectGrant[]>;
|
|
41
43
|
}
|
|
42
44
|
/**
|
|
43
45
|
* Resolve the caller's accessible project set in a constant number of queries.
|
|
@@ -45,6 +47,12 @@ export interface AccessibleProjectSet {
|
|
|
45
47
|
* `canView` short-circuits before reading them for every other visibility.
|
|
46
48
|
*/
|
|
47
49
|
export declare function resolveAccessibleProjects(ctx: RequestContext, deps: VisibilityDeps): Promise<AccessibleProjectSet>;
|
|
50
|
+
/**
|
|
51
|
+
* Whether the caller may create a definition in at least one project of
|
|
52
|
+
* `orgId`, by the same rule `requireCanCreateDefinition` applies. Reads the
|
|
53
|
+
* org's projects a page at a time and stops at the first that passes.
|
|
54
|
+
*/
|
|
55
|
+
export declare function canCreateDefinitionInOrg(ctx: RequestContext, orgId: string, deps: VisibilityDeps): Promise<boolean>;
|
|
48
56
|
export interface ListVisibleDefinitionsResult extends Page<DefinitionRecord> {
|
|
49
57
|
/** For resolving a definition's `projectId` to a name. */
|
|
50
58
|
projects: Project[];
|
|
@@ -56,6 +64,24 @@ export interface ListVisibleDefinitionsResult extends Page<DefinitionRecord> {
|
|
|
56
64
|
export declare function listVisibleDefinitions(ctx: RequestContext, opts: (DefinitionListOptions & {
|
|
57
65
|
projectId?: string;
|
|
58
66
|
}) | undefined, deps: VisibilityDeps): Promise<ListVisibleDefinitionsResult>;
|
|
67
|
+
/**
|
|
68
|
+
* Editable definitions whose `sourceDocumentId` is `documentId`: the ones the
|
|
69
|
+
* caller could upload a new version of, by {@link mayUploadToDefinition}.
|
|
70
|
+
*
|
|
71
|
+
* Commons projects are scanned too, since a caller owns their own uploads there
|
|
72
|
+
* without edit rights on the project; rows they can't edit are dropped after
|
|
73
|
+
* the query, so a page can come back short while `nextCursor` stays valid.
|
|
74
|
+
*/
|
|
75
|
+
export declare function listEditableDefinitionsByDocument(ctx: RequestContext, documentId: string, opts: DefinitionListOptions & {
|
|
76
|
+
projectId?: string;
|
|
77
|
+
}, deps: VisibilityDeps): Promise<Page<DefinitionRecord>>;
|
|
78
|
+
/** A visible definition and the caller's rows that decided it. */
|
|
79
|
+
export interface VisibleDefinition {
|
|
80
|
+
record: DefinitionRecord;
|
|
81
|
+
project: Project;
|
|
82
|
+
member: ProjectMember | null;
|
|
83
|
+
orgMember: OrgMember | null;
|
|
84
|
+
}
|
|
59
85
|
/**
|
|
60
86
|
* One definition, or `null` when the caller cannot view its project.
|
|
61
87
|
*
|
|
@@ -64,6 +90,14 @@ export declare function listVisibleDefinitions(ctx: RequestContext, opts: (Defin
|
|
|
64
90
|
* `/definitions/{guid}` into a cross-tenant existence oracle.
|
|
65
91
|
*/
|
|
66
92
|
export declare function getVisibleDefinition(ctx: RequestContext, guid: string, deps: VisibilityDeps): Promise<DefinitionRecord | null>;
|
|
93
|
+
/** {@link getVisibleDefinition} with the rows it read, for a second rule over the same caller. */
|
|
94
|
+
export declare function loadVisibleDefinition(ctx: RequestContext, guid: string, deps: VisibilityDeps): Promise<VisibleDefinition | null>;
|
|
95
|
+
/**
|
|
96
|
+
* May the caller upload a version of this definition and make one live? The
|
|
97
|
+
* rule `requireEditableDefinition` applies, and for an API token its `upload`
|
|
98
|
+
* scope on the definition, which is what those routes check.
|
|
99
|
+
*/
|
|
100
|
+
export declare function mayUploadToDefinition(ctx: RequestContext, { record, project, member, orgMember }: VisibleDefinition, deps: Pick<VisibilityDeps, 'flag'>): boolean;
|
|
67
101
|
/**
|
|
68
102
|
* One version of a definition the caller can view, including its cached
|
|
69
103
|
* `schema`. `null` when the definition is invisible, the version is missing, or
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visibility.d.ts","sourceRoot":"","sources":["../../src/definitions/visibility.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;
|
|
1
|
+
{"version":3,"file":"visibility.d.ts","sourceRoot":"","sources":["../../src/definitions/visibility.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* reads regardless of N. Anything added here must keep that property — a
|
|
14
14
|
* per-project `await` inside a loop reintroduces the N+1 this replaced.
|
|
15
15
|
*/
|
|
16
|
-
import { SYSTEM_CONTEXT, canView, outsideTokenOrg } from '@selvajs/platform';
|
|
16
|
+
import { SYSTEM_CONTEXT, canCreateDefinition, canEditDefinition, canView, outsideTokenOrg, scopeAllows } from '@selvajs/platform';
|
|
17
17
|
import { projectAccessInputFromRowsWith } from '../access/index.js';
|
|
18
18
|
/** Upper bound on the org/project scan. Visibility needs the whole set. */
|
|
19
19
|
const SCAN_LIMIT = 200;
|
|
@@ -51,9 +51,41 @@ export async function resolveAccessibleProjects(ctx, deps) {
|
|
|
51
51
|
projects,
|
|
52
52
|
allById: new Map(allProjects.map((p) => [p.id, p])),
|
|
53
53
|
memberByProjectId,
|
|
54
|
-
orgMemberByOrgId
|
|
54
|
+
orgMemberByOrgId,
|
|
55
|
+
grantsByProjectId
|
|
55
56
|
};
|
|
56
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Whether the caller may create a definition in at least one project of
|
|
60
|
+
* `orgId`, by the same rule `requireCanCreateDefinition` applies. Reads the
|
|
61
|
+
* org's projects a page at a time and stops at the first that passes.
|
|
62
|
+
*/
|
|
63
|
+
export async function canCreateDefinitionInOrg(ctx, orgId, deps) {
|
|
64
|
+
const orgMember = (await deps.orgs.getOrgMembersFor(SYSTEM_CONTEXT, [orgId], ctx.userId)).get(orgId) ?? null;
|
|
65
|
+
let cursor;
|
|
66
|
+
do {
|
|
67
|
+
const page = await deps.projects.listProjects(SYSTEM_CONTEXT, orgId, {
|
|
68
|
+
limit: SCAN_LIMIT,
|
|
69
|
+
cursor
|
|
70
|
+
});
|
|
71
|
+
const platformIds = page.items.filter((p) => p.visibility === 'platform').map((p) => p.id);
|
|
72
|
+
const [members, grants] = await Promise.all([
|
|
73
|
+
deps.projects.getProjectMembersFor(SYSTEM_CONTEXT, page.items.map((p) => p.id), ctx.userId),
|
|
74
|
+
platformIds.length
|
|
75
|
+
? deps.platformProjectGrants.listByProjects(SYSTEM_CONTEXT, platformIds)
|
|
76
|
+
: Promise.resolve(new Map())
|
|
77
|
+
]);
|
|
78
|
+
const allowed = page.items.some((project) => canCreateDefinition(projectAccessInputFromRowsWith({ deps }, ctx, project, {
|
|
79
|
+
member: members.get(project.id) ?? null,
|
|
80
|
+
orgMember,
|
|
81
|
+
platformGrants: grants.get(project.id) ?? []
|
|
82
|
+
})));
|
|
83
|
+
if (allowed)
|
|
84
|
+
return true;
|
|
85
|
+
cursor = page.nextCursor;
|
|
86
|
+
} while (cursor);
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
57
89
|
/**
|
|
58
90
|
* `opts.projectId` narrows to one project; a caller who cannot view it gets an
|
|
59
91
|
* empty page rather than a 403, so this never reveals that a project exists.
|
|
@@ -70,6 +102,37 @@ export async function listVisibleDefinitions(ctx, opts = {}, deps) {
|
|
|
70
102
|
});
|
|
71
103
|
return { items: page.items, nextCursor: page.nextCursor, projects: scoped };
|
|
72
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Editable definitions whose `sourceDocumentId` is `documentId`: the ones the
|
|
107
|
+
* caller could upload a new version of, by {@link mayUploadToDefinition}.
|
|
108
|
+
*
|
|
109
|
+
* Commons projects are scanned too, since a caller owns their own uploads there
|
|
110
|
+
* without edit rights on the project; rows they can't edit are dropped after
|
|
111
|
+
* the query, so a page can come back short while `nextCursor` stays valid.
|
|
112
|
+
*/
|
|
113
|
+
export async function listEditableDefinitionsByDocument(ctx, documentId, opts, deps) {
|
|
114
|
+
const { projectId, ...listOpts } = opts;
|
|
115
|
+
const set = await resolveAccessibleProjects(ctx, deps);
|
|
116
|
+
const rowsFor = (project) => ({
|
|
117
|
+
member: set.memberByProjectId.get(project.id) ?? null,
|
|
118
|
+
orgMember: set.orgMemberByOrgId.get(project.orgId) ?? null,
|
|
119
|
+
platformGrants: set.grantsByProjectId.get(project.id) ?? []
|
|
120
|
+
});
|
|
121
|
+
const candidates = set.projects.filter((p) => (!projectId || p.id === projectId) &&
|
|
122
|
+
canCreateDefinition(projectAccessInputFromRowsWith({ deps }, ctx, p, rowsFor(p))));
|
|
123
|
+
const page = await deps.definitionMeta.list(ctx, {
|
|
124
|
+
...listOpts,
|
|
125
|
+
sourceDocumentId: documentId,
|
|
126
|
+
projectIds: candidates.map((p) => p.id)
|
|
127
|
+
});
|
|
128
|
+
const items = page.items.filter((record) => {
|
|
129
|
+
const project = set.allById.get(record.projectId);
|
|
130
|
+
return project
|
|
131
|
+
? mayUploadToDefinition(ctx, { record, project, ...rowsFor(project) }, deps)
|
|
132
|
+
: false;
|
|
133
|
+
});
|
|
134
|
+
return { items, nextCursor: page.nextCursor };
|
|
135
|
+
}
|
|
73
136
|
/**
|
|
74
137
|
* One definition, or `null` when the caller cannot view its project.
|
|
75
138
|
*
|
|
@@ -78,6 +141,10 @@ export async function listVisibleDefinitions(ctx, opts = {}, deps) {
|
|
|
78
141
|
* `/definitions/{guid}` into a cross-tenant existence oracle.
|
|
79
142
|
*/
|
|
80
143
|
export async function getVisibleDefinition(ctx, guid, deps) {
|
|
144
|
+
return (await loadVisibleDefinition(ctx, guid, deps))?.record ?? null;
|
|
145
|
+
}
|
|
146
|
+
/** {@link getVisibleDefinition} with the rows it read, for a second rule over the same caller. */
|
|
147
|
+
export async function loadVisibleDefinition(ctx, guid, deps) {
|
|
81
148
|
const meta = deps.definitionMeta;
|
|
82
149
|
const projectStore = deps.projects;
|
|
83
150
|
const record = await meta.get(ctx, guid);
|
|
@@ -93,12 +160,31 @@ export async function getVisibleDefinition(ctx, guid, deps) {
|
|
|
93
160
|
? deps.platformProjectGrants.listByProject(SYSTEM_CONTEXT, project.id)
|
|
94
161
|
: Promise.resolve([])
|
|
95
162
|
]);
|
|
163
|
+
const member = projectMembers.get(project.id) ?? null;
|
|
164
|
+
const orgMember = orgMembers.get(project.orgId) ?? null;
|
|
96
165
|
const allowed = canView(projectAccessInputFromRowsWith({ deps }, ctx, project, {
|
|
97
|
-
member
|
|
98
|
-
orgMember
|
|
166
|
+
member,
|
|
167
|
+
orgMember,
|
|
99
168
|
platformGrants: grants
|
|
100
169
|
}));
|
|
101
|
-
return allowed ? record : null;
|
|
170
|
+
return allowed ? { record, project, member, orgMember } : null;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* May the caller upload a version of this definition and make one live? The
|
|
174
|
+
* rule `requireEditableDefinition` applies, and for an API token its `upload`
|
|
175
|
+
* scope on the definition, which is what those routes check.
|
|
176
|
+
*/
|
|
177
|
+
export function mayUploadToDefinition(ctx, { record, project, member, orgMember }, deps) {
|
|
178
|
+
return (scopeAllows(ctx, 'upload', { definitionId: record.guid, projectId: project.id }) &&
|
|
179
|
+
canEditDefinition({
|
|
180
|
+
project,
|
|
181
|
+
definition: record,
|
|
182
|
+
member,
|
|
183
|
+
orgMember,
|
|
184
|
+
userId: ctx.userId,
|
|
185
|
+
platformPermissions: ctx.platformPermissions,
|
|
186
|
+
enablePlatformProjects: deps.flag('ENABLE_PLATFORM_PROJECTS')
|
|
187
|
+
}));
|
|
102
188
|
}
|
|
103
189
|
/**
|
|
104
190
|
* One version of a definition the caller can view, including its cached
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visibility.js","sourceRoot":"","sources":["../../src/definitions/visibility.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"visibility.js","sourceRoot":"","sources":["../../src/definitions/visibility.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,18 +2,53 @@
|
|
|
2
2
|
* API tokens: mint, list, revoke.
|
|
3
3
|
*
|
|
4
4
|
* **Session-only.** A key can't manage keys, so a leaked one can't mint more or
|
|
5
|
-
* revoke the owner's others to cover its tracks.
|
|
5
|
+
* revoke the owner's others to cover its tracks. The one exception is a key
|
|
6
|
+
* revoking itself, which only ever takes access away.
|
|
6
7
|
*
|
|
7
8
|
* **The raw key exists only in the mint response.** The store holds its HMAC,
|
|
8
9
|
* and every response goes through a schema that has no `tokenHash`.
|
|
9
10
|
*/
|
|
10
|
-
import { type ApiTokenRevokeReason, type IApiTokenStore, type ILogger, type RequestContext } from '@selvajs/platform';
|
|
11
|
-
import type { ApiHandler } from '../api/index.js';
|
|
11
|
+
import { type ApiTokenLifetimeDays, type ApiTokenRevokeReason, type ApiTokenSummary, type IApiTokenStore, type ILogger, type ListOptions, type Page, type RequestContext } from '@selvajs/platform';
|
|
12
|
+
import type { ApiHandler, ApiRequest } from '../api/index.js';
|
|
12
13
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
14
|
+
* May `ctx` hold a key with `scopes`, by the host's policy or the default rule?
|
|
15
|
+
* The one call every mint path makes, so a host's token page and its consent
|
|
16
|
+
* screen can't disagree with the mint.
|
|
15
17
|
*/
|
|
18
|
+
export declare function mayHoldApiTokens(deps: ApiRequest['deps'], ctx: RequestContext, scopes: readonly string[]): Promise<boolean>;
|
|
19
|
+
export type ApiTokenRow = ApiTokenSummary & {
|
|
20
|
+
refusedToday: number;
|
|
21
|
+
};
|
|
22
|
+
/** Who sees every owner's keys in an org and may revoke any of them. */
|
|
23
|
+
export declare const canManageApiTokenRoster: (ctx: RequestContext) => boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Keys in `orgId`, newest first, including revoked and expired ones: the
|
|
26
|
+
* caller's own, or with `roster` everyone's. The list endpoint and a host's
|
|
27
|
+
* token page both read through here, so they can't disagree on who sees what.
|
|
28
|
+
*/
|
|
29
|
+
export declare function listOrgApiTokens(store: IApiTokenStore, ctx: RequestContext, orgId: string, { roster, ...opts }?: ListOptions & {
|
|
30
|
+
roster?: boolean;
|
|
31
|
+
}): Promise<Page<ApiTokenRow>>;
|
|
32
|
+
/** The caller's own keys in this org. `?all=true` returns everyone's and needs `manage_org_members`. */
|
|
16
33
|
export declare const listApiTokens: ApiHandler;
|
|
34
|
+
export interface MintApiTokenInput {
|
|
35
|
+
name: string;
|
|
36
|
+
scopes: readonly string[];
|
|
37
|
+
expiresInDays: ApiTokenLifetimeDays;
|
|
38
|
+
}
|
|
39
|
+
export interface MintedApiToken {
|
|
40
|
+
token: ApiTokenRow;
|
|
41
|
+
/** The raw key. Shown once; the store keeps only its HMAC. */
|
|
42
|
+
secret: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Mint a token acting as the caller, in the caller's acting org. Every mint
|
|
46
|
+
* goes through here, the token endpoint and an OAuth consent alike, so the
|
|
47
|
+
* holder rule, the scope checks, the audit event and the owner's email always
|
|
48
|
+
* apply. A consent screen passes a `req` whose `ctx` acts in the org the user
|
|
49
|
+
* picked.
|
|
50
|
+
*/
|
|
51
|
+
export declare function mintApiToken(req: ApiRequest, input: MintApiTokenInput): Promise<MintedApiToken>;
|
|
17
52
|
/** Mint a token acting as the caller. The raw key is in this response and nowhere else. */
|
|
18
53
|
export declare const createApiToken: ApiHandler;
|
|
19
54
|
/**
|
|
@@ -21,6 +56,12 @@ export declare const createApiToken: ApiHandler;
|
|
|
21
56
|
* `manage_org_members`. Someone else's token reads as missing, not forbidden.
|
|
22
57
|
*/
|
|
23
58
|
export declare const revokeApiToken: ApiHandler;
|
|
59
|
+
/**
|
|
60
|
+
* Revoke the key that sent this request, and nothing else. Any key may call it,
|
|
61
|
+
* whatever its scopes, so a client signing out never needs more than it has.
|
|
62
|
+
* A browser session gets 400: it has no key to revoke.
|
|
63
|
+
*/
|
|
64
|
+
export declare const revokeOwnApiToken: ApiHandler;
|
|
24
65
|
/**
|
|
25
66
|
* Revoke every live key `userId` holds, in one org or (no `orgId`) all of
|
|
26
67
|
* them. Call it when someone leaves an org or is disabled: the resolver already
|