@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiTokens.d.ts","sourceRoot":"","sources":["../../src/handlers/apiTokens.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"apiTokens.d.ts","sourceRoot":"","sources":["../../src/handlers/apiTokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAKN,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,IAAI,EACT,KAAK,cAAc,EACnB,MAAM,mBAAmB,CAAC;AAiB3B,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAiB9D;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC/B,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,EACxB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,SAAS,MAAM,EAAE,GACvB,OAAO,CAAC,OAAO,CAAC,CAElB;AAkBD,MAAM,MAAM,WAAW,GAAG,eAAe,GAAG;IAAE,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC;AAMrE,wEAAwE;AACxE,eAAO,MAAM,uBAAuB,GAAI,KAAK,cAAc,KAAG,OACrB,CAAC;AAE1C;;;;GAIG;AACH,wBAAsB,gBAAgB,CACrC,KAAK,EAAE,cAAc,EACrB,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,MAAM,EACb,EAAE,MAAc,EAAE,GAAG,IAAI,EAAE,GAAE,WAAW,GAAG;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAClE,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAS5B;AAyED,wGAAwG;AACxG,eAAO,MAAM,aAAa,EAAE,UAO3B,CAAC;AAEF,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,aAAa,EAAE,oBAAoB,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,WAAW,CAAC;IACnB,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CACjC,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,iBAAiB,GACtB,OAAO,CAAC,cAAc,CAAC,CA6CzB;AAED,2FAA2F;AAC3F,eAAO,MAAM,cAAc,EAAE,UAQ5B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,UAY5B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,UAW/B,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACxC,KAAK,EAAE,cAAc,GAAG,SAAS,EACjC,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,oBAAoB,CAAA;CAAE,EACtD,GAAG,EAAE,OAAO,GACV,OAAO,CAAC,IAAI,CAAC,CAaf"}
|
|
@@ -2,7 +2,8 @@
|
|
|
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`.
|
|
@@ -11,7 +12,8 @@ import { randomUUID } from 'node:crypto';
|
|
|
11
12
|
import { describeApiScope, hasPermission, parseApiScope } from '@selvajs/platform';
|
|
12
13
|
import { renderApiTokenCreatedEmail } from '@selvajs/notifications';
|
|
13
14
|
import { apiError, ApiErrorCode, ApiTokenResponseSchema, CreateApiTokenBodySchema, CreatedApiTokenResponseSchema, isApiError, noContent, parseBody, parseListOptions, requireCaller, requireParams, scopeRefusalsToday, shapedCollection } from '../api/index.js';
|
|
14
|
-
import { requireActingOrg, requireCanViewProject
|
|
15
|
+
import { requireActingOrg, requireCanViewProject } from '../access/index.js';
|
|
16
|
+
import { canHoldApiTokens } from '../tokens/index.js';
|
|
15
17
|
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
16
18
|
function requireSessionInOrg(req) {
|
|
17
19
|
if (req.ctx?.apiScope) {
|
|
@@ -19,6 +21,14 @@ function requireSessionInOrg(req) {
|
|
|
19
21
|
}
|
|
20
22
|
return requireActingOrg(req, req.params.orgId);
|
|
21
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* May `ctx` hold a key with `scopes`, by the host's policy or the default rule?
|
|
26
|
+
* The one call every mint path makes, so a host's token page and its consent
|
|
27
|
+
* screen can't disagree with the mint.
|
|
28
|
+
*/
|
|
29
|
+
export function mayHoldApiTokens(deps, ctx, scopes) {
|
|
30
|
+
return canHoldApiTokens(ctx, scopes, { policy: deps.tokens.mayHoldApiTokens, deps });
|
|
31
|
+
}
|
|
22
32
|
function unavailable() {
|
|
23
33
|
apiError(503, ApiErrorCode.API_TOKENS_UNAVAILABLE, 'API tokens are not available on this server.');
|
|
24
34
|
}
|
|
@@ -31,6 +41,23 @@ function codecOf(req) {
|
|
|
31
41
|
function toResponse(token) {
|
|
32
42
|
return { ...token, refusedToday: scopeRefusalsToday(token.id) };
|
|
33
43
|
}
|
|
44
|
+
/** Who sees every owner's keys in an org and may revoke any of them. */
|
|
45
|
+
export const canManageApiTokenRoster = (ctx) => hasPermission(ctx, 'manage_org_members');
|
|
46
|
+
/**
|
|
47
|
+
* Keys in `orgId`, newest first, including revoked and expired ones: the
|
|
48
|
+
* caller's own, or with `roster` everyone's. The list endpoint and a host's
|
|
49
|
+
* token page both read through here, so they can't disagree on who sees what.
|
|
50
|
+
*/
|
|
51
|
+
export async function listOrgApiTokens(store, ctx, orgId, { roster = false, ...opts } = {}) {
|
|
52
|
+
if (roster && !canManageApiTokenRoster(ctx)) {
|
|
53
|
+
apiError(403, ApiErrorCode.FORBIDDEN, 'Only org admins can see everyone’s API tokens.');
|
|
54
|
+
}
|
|
55
|
+
const page = await store.listByOrg(ctx, orgId, {
|
|
56
|
+
...opts,
|
|
57
|
+
userId: roster ? undefined : ctx.userId
|
|
58
|
+
});
|
|
59
|
+
return { ...page, items: page.items.map(toResponse) };
|
|
60
|
+
}
|
|
34
61
|
/**
|
|
35
62
|
* Refuse scopes naming something outside this org or out of the creator's
|
|
36
63
|
* sight. Not the security boundary: a key never exceeds its owner's live rights
|
|
@@ -95,33 +122,37 @@ async function mailTokenCreated(req, token) {
|
|
|
95
122
|
});
|
|
96
123
|
}
|
|
97
124
|
}
|
|
98
|
-
/**
|
|
99
|
-
* The caller's own tokens in this org, newest first, including revoked and
|
|
100
|
-
* expired ones. `?all=true` returns everyone's and needs `manage_org_members`.
|
|
101
|
-
*/
|
|
125
|
+
/** The caller's own keys in this org. `?all=true` returns everyone's and needs `manage_org_members`. */
|
|
102
126
|
export const listApiTokens = async (req) => {
|
|
103
127
|
const { ctx, orgId } = requireSessionInOrg(req);
|
|
104
|
-
const
|
|
105
|
-
if (all)
|
|
106
|
-
requireManageOrgMembers(req);
|
|
107
|
-
const page = await storeOf(req).listByOrg(ctx, orgId, {
|
|
128
|
+
const page = await listOrgApiTokens(storeOf(req), ctx, orgId, {
|
|
108
129
|
...parseListOptions(req.url),
|
|
109
|
-
|
|
130
|
+
roster: req.url.searchParams.get('all') === 'true'
|
|
110
131
|
});
|
|
111
|
-
return shapedCollection(ApiTokenResponseSchema,
|
|
132
|
+
return shapedCollection(ApiTokenResponseSchema, page);
|
|
112
133
|
};
|
|
113
|
-
/**
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
134
|
+
/**
|
|
135
|
+
* Mint a token acting as the caller, in the caller's acting org. Every mint
|
|
136
|
+
* goes through here, the token endpoint and an OAuth consent alike, so the
|
|
137
|
+
* holder rule, the scope checks, the audit event and the owner's email always
|
|
138
|
+
* apply. A consent screen passes a `req` whose `ctx` acts in the org the user
|
|
139
|
+
* picked.
|
|
140
|
+
*/
|
|
141
|
+
export async function mintApiToken(req, input) {
|
|
142
|
+
const { ctx, user } = requireCaller(req);
|
|
143
|
+
const orgId = ctx.actingOrgId;
|
|
144
|
+
if (ctx.apiScope || !orgId) {
|
|
145
|
+
apiError(403, ApiErrorCode.FORBIDDEN, 'API tokens can only be created from a signed-in session.');
|
|
146
|
+
}
|
|
147
|
+
if (!(await mayHoldApiTokens(req.deps, ctx, input.scopes))) {
|
|
148
|
+
apiError(403, ApiErrorCode.FORBIDDEN, 'You can’t create API tokens with this access in this org.');
|
|
149
|
+
}
|
|
118
150
|
const store = storeOf(req);
|
|
119
151
|
const codec = codecOf(req);
|
|
120
152
|
// A key minted now would only ever get 503.
|
|
121
153
|
const delegated = req.deps.auth.delegatedSession;
|
|
122
154
|
if (delegated && !(await delegated.status()).ok)
|
|
123
155
|
unavailable();
|
|
124
|
-
const input = await parseBody(req.request, CreateApiTokenBodySchema);
|
|
125
156
|
await assertScopesReachable(req, orgId, input.scopes);
|
|
126
157
|
const raw = codec.mintRawToken();
|
|
127
158
|
const now = new Date();
|
|
@@ -141,10 +172,16 @@ export const createApiToken = async (req) => {
|
|
|
141
172
|
await store.create(ctx, token);
|
|
142
173
|
await mailTokenCreated(req, token);
|
|
143
174
|
const { tokenHash: _hash, ...summary } = token;
|
|
175
|
+
return { token: toResponse(summary), secret: raw };
|
|
176
|
+
}
|
|
177
|
+
/** Mint a token acting as the caller. The raw key is in this response and nowhere else. */
|
|
178
|
+
export const createApiToken = async (req) => {
|
|
179
|
+
requireSessionInOrg(req);
|
|
180
|
+
const input = await parseBody(req.request, CreateApiTokenBodySchema);
|
|
144
181
|
return {
|
|
145
182
|
status: 201,
|
|
146
183
|
headers: { 'Cache-Control': 'no-store' },
|
|
147
|
-
body: CreatedApiTokenResponseSchema.parse(
|
|
184
|
+
body: CreatedApiTokenResponseSchema.parse(await mintApiToken(req, input))
|
|
148
185
|
};
|
|
149
186
|
};
|
|
150
187
|
/**
|
|
@@ -157,12 +194,25 @@ export const revokeApiToken = async (req) => {
|
|
|
157
194
|
const store = storeOf(req);
|
|
158
195
|
const token = await store.get(ctx, tokenId);
|
|
159
196
|
const own = token?.userId === ctx.userId;
|
|
160
|
-
if (!token || token.orgId !== orgId || (!own && !
|
|
197
|
+
if (!token || token.orgId !== orgId || (!own && !canManageApiTokenRoster(ctx))) {
|
|
161
198
|
apiError(404, ApiErrorCode.NOT_FOUND, 'API token not found');
|
|
162
199
|
}
|
|
163
200
|
await store.revoke(ctx, tokenId, own ? 'owner' : 'admin');
|
|
164
201
|
return noContent();
|
|
165
202
|
};
|
|
203
|
+
/**
|
|
204
|
+
* Revoke the key that sent this request, and nothing else. Any key may call it,
|
|
205
|
+
* whatever its scopes, so a client signing out never needs more than it has.
|
|
206
|
+
* A browser session gets 400: it has no key to revoke.
|
|
207
|
+
*/
|
|
208
|
+
export const revokeOwnApiToken = async (req) => {
|
|
209
|
+
const { ctx } = requireCaller(req);
|
|
210
|
+
if (!ctx.apiScope) {
|
|
211
|
+
apiError(400, ApiErrorCode.VALIDATION_FAILED, 'Only an API token can revoke itself. Revoke tokens from the web app instead.');
|
|
212
|
+
}
|
|
213
|
+
await storeOf(req).revoke(ctx, ctx.apiScope.tokenId, 'owner');
|
|
214
|
+
return noContent();
|
|
215
|
+
};
|
|
166
216
|
/**
|
|
167
217
|
* Revoke every live key `userId` holds, in one org or (no `orgId`) all of
|
|
168
218
|
* them. Call it when someone leaves an org or is disabled: the resolver already
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiTokens.js","sourceRoot":"","sources":["../../src/handlers/apiTokens.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"apiTokens.js","sourceRoot":"","sources":["../../src/handlers/apiTokens.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,11 +9,17 @@ import type { ApiHandler } from '../api/index.js';
|
|
|
9
9
|
/**
|
|
10
10
|
* Definitions the caller can view. Visibility is resolved into the query via
|
|
11
11
|
* `projectIds`, so `limit`/`nextCursor` describe the filtered set.
|
|
12
|
+
*
|
|
13
|
+
* `?documentId=<guid>` narrows to definitions uploaded from that Grasshopper
|
|
14
|
+
* document which the caller can upload a new version of.
|
|
12
15
|
*/
|
|
13
16
|
export declare const listDefinitions: ApiHandler;
|
|
14
17
|
/** Create a definition — metadata and the Grasshopper file in one request. */
|
|
15
18
|
export declare const createDefinition: ApiHandler;
|
|
16
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* The record plus its live and draft version summaries. `canEdit` says whether
|
|
21
|
+
* the caller can upload a version and make one live, scope included for a key.
|
|
22
|
+
*/
|
|
17
23
|
export declare const getDefinition: ApiHandler;
|
|
18
24
|
/** Soft-delete the definition; versions and blobs are wiped with it. */
|
|
19
25
|
export declare const deleteDefinition: ApiHandler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/handlers/definitions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/handlers/definitions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAkBH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AA0BlD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,EAAE,UA2B7B,CAAC;AAWF,8EAA8E;AAC9E,eAAO,MAAM,gBAAgB,EAAE,UA0F9B,CAAC;AAaF;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,UAuB3B,CAAC;AAEF,wEAAwE;AACxE,eAAO,MAAM,gBAAgB,EAAE,UAM9B,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,gBAAgB,EAAE,UAa9B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,UAejC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,UAM/B,CAAC;AAEF,4BAA4B;AAC5B,eAAO,MAAM,qBAAqB,EAAE,UAanC,CAAC"}
|
|
@@ -6,30 +6,41 @@
|
|
|
6
6
|
* and mark their own metrics, which the `ApiResponse` envelope does not model.
|
|
7
7
|
*/
|
|
8
8
|
import { randomUUID } from 'node:crypto';
|
|
9
|
-
import { apiError, ApiErrorCode, collection, created, formText, noContent, parseBody, parseDefinitionListOptions, parseParam, requireCaller, requireUpload, throwZodError } from '../api/index.js';
|
|
10
|
-
import { toDefinitionListItem } from '@selvajs/platform';
|
|
9
|
+
import { apiError, ApiErrorCode, assertScope, collection, created, formText, noContent, parseBody, parseDefinitionListOptions, parseParam, requireCaller, requireUpload, throwZodError } from '../api/index.js';
|
|
10
|
+
import { toDefinitionListItem, toSourceDocumentId } from '@selvajs/platform';
|
|
11
11
|
import { CreateDefinitionInputSchema, GuidSchema, PublishVersionInputSchema, UpdateMetadataInputSchema } from '@selvajs/platform/definitions';
|
|
12
12
|
import { requireCanCreateDefinition, requireEditableDefinition } from '../access/index.js';
|
|
13
13
|
import { GH_EXTENSIONS } from '@selvajs/platform';
|
|
14
14
|
import { resolveServerForOrg } from '../compute/index.js';
|
|
15
|
-
import { fetchSchemaFromCompute, getVisibleDefinition, listVisibleDefinitions, loadVisibleVersion, resolveAccessibleProjects } from '../definitions/index.js';
|
|
15
|
+
import { fetchSchemaFromCompute, getVisibleDefinition, listEditableDefinitionsByDocument, listVisibleDefinitions, loadVisibleDefinition, loadVisibleVersion, mayUploadToDefinition, resolveAccessibleProjects } from '../definitions/index.js';
|
|
16
16
|
import { definitionService } from './services.js';
|
|
17
17
|
const LISTABLE_STATUSES = ['draft', 'published', 'archived'];
|
|
18
18
|
/**
|
|
19
19
|
* Definitions the caller can view. Visibility is resolved into the query via
|
|
20
20
|
* `projectIds`, so `limit`/`nextCursor` describe the filtered set.
|
|
21
|
+
*
|
|
22
|
+
* `?documentId=<guid>` narrows to definitions uploaded from that Grasshopper
|
|
23
|
+
* document which the caller can upload a new version of.
|
|
21
24
|
*/
|
|
22
25
|
export const listDefinitions = async (req) => {
|
|
23
26
|
const { ctx } = requireCaller(req);
|
|
27
|
+
const documentParam = req.url.searchParams.get('documentId');
|
|
28
|
+
const documentId = documentParam === null ? null : toSourceDocumentId(documentParam);
|
|
29
|
+
if (documentParam !== null && !documentId) {
|
|
30
|
+
apiError(400, ApiErrorCode.VALIDATION_FAILED, 'documentId must be a GUID');
|
|
31
|
+
}
|
|
24
32
|
const statusParam = req.url.searchParams.get('status');
|
|
25
33
|
if (statusParam && !LISTABLE_STATUSES.includes(statusParam)) {
|
|
26
34
|
apiError(400, ApiErrorCode.VALIDATION_FAILED, `status must be one of: ${LISTABLE_STATUSES.join(', ')}`);
|
|
27
35
|
}
|
|
28
|
-
const
|
|
36
|
+
const opts = {
|
|
29
37
|
...parseDefinitionListOptions(req.url),
|
|
30
38
|
projectId: req.url.searchParams.get('projectId') ?? undefined,
|
|
31
39
|
statuses: statusParam ? [statusParam] : undefined
|
|
32
|
-
}
|
|
40
|
+
};
|
|
41
|
+
const page = documentId
|
|
42
|
+
? await listEditableDefinitionsByDocument(ctx, documentId, opts, req.deps)
|
|
43
|
+
: await listVisibleDefinitions(ctx, opts, req.deps);
|
|
33
44
|
return collection({ items: page.items.map(toDefinitionListItem), nextCursor: page.nextCursor });
|
|
34
45
|
};
|
|
35
46
|
function parseTags(raw) {
|
|
@@ -126,13 +137,17 @@ function versionSummary(v) {
|
|
|
126
137
|
changeNote: v.changeNote
|
|
127
138
|
};
|
|
128
139
|
}
|
|
129
|
-
/**
|
|
140
|
+
/**
|
|
141
|
+
* The record plus its live and draft version summaries. `canEdit` says whether
|
|
142
|
+
* the caller can upload a version and make one live, scope included for a key.
|
|
143
|
+
*/
|
|
130
144
|
export const getDefinition = async (req) => {
|
|
131
145
|
const guid = parseParam(req.params.guid, GuidSchema, 'GUID');
|
|
132
146
|
const { ctx } = requireCaller(req);
|
|
133
|
-
const
|
|
134
|
-
if (!
|
|
147
|
+
const visible = await loadVisibleDefinition(ctx, guid, req.deps);
|
|
148
|
+
if (!visible)
|
|
135
149
|
apiError(404, ApiErrorCode.NOT_FOUND, 'Definition not found');
|
|
150
|
+
const { record } = visible;
|
|
136
151
|
const meta = req.deps.definitionMeta;
|
|
137
152
|
const [liveVersion, draftVersion] = await Promise.all([
|
|
138
153
|
record.liveVersionId ? meta.getVersion(ctx, record.liveVersionId) : null,
|
|
@@ -141,6 +156,8 @@ export const getDefinition = async (req) => {
|
|
|
141
156
|
return {
|
|
142
157
|
body: {
|
|
143
158
|
...record,
|
|
159
|
+
sourceDocumentId: record.sourceDocumentId ?? null,
|
|
160
|
+
canEdit: mayUploadToDefinition(ctx, visible, req.deps),
|
|
144
161
|
liveVersion: liveVersion ? versionSummary(liveVersion) : null,
|
|
145
162
|
draftVersion: draftVersion ? versionSummary(draftVersion) : null
|
|
146
163
|
}
|
|
@@ -158,8 +175,10 @@ export const updateDefinition = async (req) => {
|
|
|
158
175
|
const guid = parseParam(req.params.guid, GuidSchema, 'GUID');
|
|
159
176
|
const { ctx, record } = await requireEditableDefinition(req, guid);
|
|
160
177
|
const patch = await parseBody(req.request, UpdateMetadataInputSchema);
|
|
161
|
-
// Moving needs the same rights on the destination as uploading there
|
|
178
|
+
// Moving needs the same rights on the destination as uploading there, and a
|
|
179
|
+
// key scoped to the source project must not carry the definition out of it.
|
|
162
180
|
if (patch.projectId && patch.projectId !== record.projectId) {
|
|
181
|
+
assertScope(ctx, 'write', { projectId: patch.projectId });
|
|
163
182
|
await requireCanCreateDefinition(req, patch.projectId);
|
|
164
183
|
}
|
|
165
184
|
await definitionService(req.deps).updateMeta(ctx, guid, patch);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/handlers/definitions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACN,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,OAAO,EACP,QAAQ,EACR,SAAS,EACT,SAAS,EACT,0BAA0B,EAC1B,UAAU,EACV,aAAa,EACb,aAAa,EACb,aAAa,EACb,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,oBAAoB,EAAyB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/handlers/definitions.ts"],"names":[],"mappings":"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"}
|
package/dist/handlers/index.d.ts
CHANGED
|
@@ -24,5 +24,6 @@ export { listProjects, createProject, getProject, updateProject, deleteProject }
|
|
|
24
24
|
export { listProjectMembers, addProjectMember, updateProjectMemberRole, removeProjectMember } from './projectMembers.js';
|
|
25
25
|
export { getOrgCompute, updateOrgCompute } from './orgCompute.js';
|
|
26
26
|
export { listInvites, createInvite, revokeInvite, resendInvite } from './invites.js';
|
|
27
|
-
export { listApiTokens, createApiToken, revokeApiToken, revokeUserApiTokens } from './apiTokens.js';
|
|
27
|
+
export { listApiTokens, createApiToken, revokeApiToken, revokeOwnApiToken, revokeUserApiTokens, listOrgApiTokens, canManageApiTokenRoster, mintApiToken, mayHoldApiTokens, type ApiTokenRow, type MintApiTokenInput, type MintedApiToken } from './apiTokens.js';
|
|
28
|
+
export { consentOffer, consentOrgs, mintConsentToken, revokeUnredeemedConsentToken, type ConsentLevel, type ConsentOffer, type ConsentOrg } from './oauthConsent.js';
|
|
28
29
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE/E,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EACN,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,YAAY,EACZ,aAAa,EACb,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,YAAY,EACZ,aAAa,EACb,UAAU,EACV,aAAa,EACb,aAAa,EACb,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,EACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE/E,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EACN,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,YAAY,EACZ,aAAa,EACb,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,YAAY,EACZ,aAAa,EACb,UAAU,EACV,aAAa,EACb,aAAa,EACb,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,EACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,EACN,aAAa,EACb,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,uBAAuB,EACvB,YAAY,EACZ,gBAAgB,EAChB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACN,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,4BAA4B,EAC5B,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,MAAM,mBAAmB,CAAC"}
|
package/dist/handlers/index.js
CHANGED
|
@@ -26,5 +26,6 @@ export { listProjects, createProject, getProject, updateProject, deleteProject }
|
|
|
26
26
|
export { listProjectMembers, addProjectMember, updateProjectMemberRole, removeProjectMember } from './projectMembers.js';
|
|
27
27
|
export { getOrgCompute, updateOrgCompute } from './orgCompute.js';
|
|
28
28
|
export { listInvites, createInvite, revokeInvite, resendInvite } from './invites.js';
|
|
29
|
-
export { listApiTokens, createApiToken, revokeApiToken, revokeUserApiTokens } from './apiTokens.js';
|
|
29
|
+
export { listApiTokens, createApiToken, revokeApiToken, revokeOwnApiToken, revokeUserApiTokens, listOrgApiTokens, canManageApiTokenRoster, mintApiToken, mayHoldApiTokens } from './apiTokens.js';
|
|
30
|
+
export { consentOffer, consentOrgs, mintConsentToken, revokeUnredeemedConsentToken } from './oauthConsent.js';
|
|
30
31
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,8EAA8E;AAC9E,8EAA8E;AAC9E,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE/E,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EACN,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,YAAY,EACZ,aAAa,EACb,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,YAAY,EACZ,aAAa,EACb,UAAU,EACV,aAAa,EACb,aAAa,EACb,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,EACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,8EAA8E;AAC9E,8EAA8E;AAC9E,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE/E,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EACN,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,YAAY,EACZ,aAAa,EACb,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,YAAY,EACZ,aAAa,EACb,UAAU,EACV,aAAa,EACb,aAAa,EACb,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,EACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,EACN,aAAa,EACb,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,uBAAuB,EACvB,YAAY,EACZ,gBAAgB,EAIhB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACN,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,4BAA4B,EAI5B,MAAM,mBAAmB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"me.d.ts","sourceRoot":"","sources":["../../src/handlers/me.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"me.d.ts","sourceRoot":"","sources":["../../src/handlers/me.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEjE,eAAO,MAAM,KAAK,EAAE,UAqBnB,CAAC"}
|
package/dist/handlers/me.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* holder can see which org their credential resolved into — `actingOrgId` is
|
|
4
4
|
* derived per request from the caller's membership, not frozen at mint time.
|
|
5
5
|
*/
|
|
6
|
+
import { formatApiScope } from '@selvajs/platform';
|
|
6
7
|
import { requireCaller } from '../api/index.js';
|
|
7
8
|
export const getMe = async (req) => {
|
|
8
9
|
const { ctx, user } = requireCaller(req);
|
|
@@ -14,7 +15,14 @@ export const getMe = async (req) => {
|
|
|
14
15
|
actingOrgId: ctx.actingOrgId,
|
|
15
16
|
platformPermissions: ctx.platformPermissions,
|
|
16
17
|
orgPermissions: ctx.orgPermissions,
|
|
17
|
-
starredDefinitions: req.profile?.starredDefinitions ?? []
|
|
18
|
+
starredDefinitions: req.profile?.starredDefinitions ?? [],
|
|
19
|
+
...(ctx.apiScope && {
|
|
20
|
+
apiToken: {
|
|
21
|
+
id: ctx.apiScope.tokenId,
|
|
22
|
+
scopes: ctx.apiScope.scopes.map(formatApiScope),
|
|
23
|
+
expiresAt: ctx.apiScope.expiresAt
|
|
24
|
+
}
|
|
25
|
+
})
|
|
18
26
|
}
|
|
19
27
|
};
|
|
20
28
|
};
|
package/dist/handlers/me.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"me.js","sourceRoot":"","sources":["../../src/handlers/me.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAmB,MAAM,iBAAiB,CAAC;AAEjE,MAAM,CAAC,MAAM,KAAK,GAAe,KAAK,EAAE,GAAG,EAAE,EAAE;IAC9C,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAEzC,OAAO;QACN,IAAI,EAAE;YACL,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,WAAW,EAAE,GAAG,CAAC,OAAO,EAAE,WAAW;YACrC,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,mBAAmB,EAAE,GAAG,CAAC,mBAAmB;YAC5C,cAAc,EAAE,GAAG,CAAC,cAAc;YAClC,kBAAkB,EAAE,GAAG,CAAC,OAAO,EAAE,kBAAkB,IAAI,EAAE;
|
|
1
|
+
{"version":3,"file":"me.js","sourceRoot":"","sources":["../../src/handlers/me.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAmB,MAAM,iBAAiB,CAAC;AAEjE,MAAM,CAAC,MAAM,KAAK,GAAe,KAAK,EAAE,GAAG,EAAE,EAAE;IAC9C,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAEzC,OAAO;QACN,IAAI,EAAE;YACL,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,WAAW,EAAE,GAAG,CAAC,OAAO,EAAE,WAAW;YACrC,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,mBAAmB,EAAE,GAAG,CAAC,mBAAmB;YAC5C,cAAc,EAAE,GAAG,CAAC,cAAc;YAClC,kBAAkB,EAAE,GAAG,CAAC,OAAO,EAAE,kBAAkB,IAAI,EAAE;YACzD,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI;gBACnB,QAAQ,EAAE;oBACT,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,OAAO;oBACxB,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC;oBAC/C,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,SAAS;iBACjC;aACD,CAAC;SACF;KACD,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The server half of an OAuth consent screen: which access levels and orgs the
|
|
3
|
+
* user may grant, and minting the key in the org they picked.
|
|
4
|
+
*
|
|
5
|
+
* A key is bound to one org at mint. The user's session acts in one org too,
|
|
6
|
+
* but they may belong to several, so consent builds a context pinned to the
|
|
7
|
+
* picked org rather than trusting the session's.
|
|
8
|
+
*/
|
|
9
|
+
import { type ApiRequest } from '../api/index.js';
|
|
10
|
+
import { type ConsentChoice, type OAuthScope } from '../oauth/index.js';
|
|
11
|
+
import { type MintApiTokenInput, type MintedApiToken } from './apiTokens.js';
|
|
12
|
+
export interface ConsentOrg {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The orgs the signed-in user may grant a key with `scopes` in: those they
|
|
18
|
+
* belong to and may hold such a key in.
|
|
19
|
+
*/
|
|
20
|
+
export declare function consentOrgs(req: ApiRequest, scopes: readonly string[]): Promise<ConsentOrg[]>;
|
|
21
|
+
export interface ConsentLevel {
|
|
22
|
+
choice: ConsentChoice;
|
|
23
|
+
/** Where this level may be granted. Never empty. */
|
|
24
|
+
orgs: ConsentOrg[];
|
|
25
|
+
}
|
|
26
|
+
export interface ConsentOffer {
|
|
27
|
+
/**
|
|
28
|
+
* Narrowest first. Only levels the user may hold in at least one of their
|
|
29
|
+
* orgs; each carries its own orgs, since a narrower level can reach more.
|
|
30
|
+
*/
|
|
31
|
+
levels: ConsentLevel[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* What a consent page offers for a request's scopes, and what its approval
|
|
35
|
+
* accepts. Null when the user may grant none of it anywhere.
|
|
36
|
+
*/
|
|
37
|
+
export declare function consentOffer(req: ApiRequest, scopes: readonly OAuthScope[]): Promise<ConsentOffer | null>;
|
|
38
|
+
/**
|
|
39
|
+
* Mint the key a consent grants, acting in `orgId`. An org the user doesn't
|
|
40
|
+
* belong to is refused here, whatever the form said.
|
|
41
|
+
*/
|
|
42
|
+
export declare function mintConsentToken(req: ApiRequest, orgId: string, input: MintApiTokenInput): Promise<MintedApiToken>;
|
|
43
|
+
/**
|
|
44
|
+
* Revoke a consent key whose code was never redeemed, so an abandoned sign-in
|
|
45
|
+
* doesn't leave a live key nobody holds. A used key is kept: its code may have
|
|
46
|
+
* been redeemed on another replica.
|
|
47
|
+
*/
|
|
48
|
+
export declare function revokeUnredeemedConsentToken(req: ApiRequest, tokenId: string): Promise<void>;
|
|
49
|
+
//# sourceMappingURL=oauthConsent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauthConsent.d.ts","sourceRoot":"","sources":["../../src/handlers/oauthConsent.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAyC,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGzF,OAAO,EAGN,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAGN,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,MAAM,gBAAgB,CAAC;AAExB,MAAM,WAAW,UAAU;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACb;AAeD;;;GAGG;AACH,wBAAsB,WAAW,CAChC,GAAG,EAAE,UAAU,EACf,MAAM,EAAE,SAAS,MAAM,EAAE,GACvB,OAAO,CAAC,UAAU,EAAE,CAAC,CAWvB;AAED,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,aAAa,CAAC;IACtB,oDAAoD;IACpD,IAAI,EAAE,UAAU,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC5B;;;OAGG;IACH,MAAM,EAAE,YAAY,EAAE,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAsB,YAAY,CACjC,GAAG,EAAE,UAAU,EACf,MAAM,EAAE,SAAS,UAAU,EAAE,GAC3B,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAS9B;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,iBAAiB,GACtB,OAAO,CAAC,cAAc,CAAC,CASzB;AAED;;;;GAIG;AACH,wBAAsB,4BAA4B,CACjD,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAOf"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The server half of an OAuth consent screen: which access levels and orgs the
|
|
3
|
+
* user may grant, and minting the key in the org they picked.
|
|
4
|
+
*
|
|
5
|
+
* A key is bound to one org at mint. The user's session acts in one org too,
|
|
6
|
+
* but they may belong to several, so consent builds a context pinned to the
|
|
7
|
+
* picked org rather than trusting the session's.
|
|
8
|
+
*/
|
|
9
|
+
import { apiError, ApiErrorCode, requireCaller } from '../api/index.js';
|
|
10
|
+
import { buildRequestContext } from '../http/request-context.js';
|
|
11
|
+
import { listUserMemberships } from '../organizations/user-memberships.js';
|
|
12
|
+
import { apiScopesFor, consentChoices } from '../oauth/index.js';
|
|
13
|
+
import { mayHoldApiTokens, mintApiToken } from './apiTokens.js';
|
|
14
|
+
async function contextIn(req, member) {
|
|
15
|
+
const { ctx, user } = requireCaller(req);
|
|
16
|
+
if (ctx.apiScope) {
|
|
17
|
+
apiError(403, ApiErrorCode.FORBIDDEN, 'Sign in to the web app to connect an app.');
|
|
18
|
+
}
|
|
19
|
+
const pinned = await buildRequestContext({ user, platformPermissions: ctx.platformPermissions, membership: member, pinOrg: true }, { orgs: req.deps.orgs });
|
|
20
|
+
// The session's own adapter payload (Supabase's user JWT) still applies.
|
|
21
|
+
return { ...pinned, adapterContext: ctx.adapterContext };
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The orgs the signed-in user may grant a key with `scopes` in: those they
|
|
25
|
+
* belong to and may hold such a key in.
|
|
26
|
+
*/
|
|
27
|
+
export async function consentOrgs(req, scopes) {
|
|
28
|
+
const { ctx } = requireCaller(req);
|
|
29
|
+
const memberships = await listUserMemberships(req.deps.orgs, ctx.userId);
|
|
30
|
+
const allowed = await Promise.all(memberships.map(async ({ member }) => mayHoldApiTokens(req.deps, await contextIn(req, member), scopes)));
|
|
31
|
+
return memberships
|
|
32
|
+
.filter((_, i) => allowed[i])
|
|
33
|
+
.map(({ org }) => ({ id: org.id, name: org.name }));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* What a consent page offers for a request's scopes, and what its approval
|
|
37
|
+
* accepts. Null when the user may grant none of it anywhere.
|
|
38
|
+
*/
|
|
39
|
+
export async function consentOffer(req, scopes) {
|
|
40
|
+
const levels = await Promise.all(consentChoices(scopes).map(async (choice) => ({
|
|
41
|
+
choice,
|
|
42
|
+
orgs: await consentOrgs(req, apiScopesFor(choice.scopes))
|
|
43
|
+
})));
|
|
44
|
+
const offered = levels.filter((l) => l.orgs.length > 0);
|
|
45
|
+
return offered.length ? { levels: offered } : null;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Mint the key a consent grants, acting in `orgId`. An org the user doesn't
|
|
49
|
+
* belong to is refused here, whatever the form said.
|
|
50
|
+
*/
|
|
51
|
+
export async function mintConsentToken(req, orgId, input) {
|
|
52
|
+
const { ctx } = requireCaller(req);
|
|
53
|
+
// Matched against the user's own memberships, so the posted id never reaches a store query.
|
|
54
|
+
const memberships = await listUserMemberships(req.deps.orgs, ctx.userId);
|
|
55
|
+
const picked = memberships.find(({ org }) => org.id === orgId);
|
|
56
|
+
if (!picked) {
|
|
57
|
+
apiError(403, ApiErrorCode.FORBIDDEN, 'You aren’t a member of that organization.');
|
|
58
|
+
}
|
|
59
|
+
return mintApiToken({ ...req, ctx: await contextIn(req, picked.member) }, input);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Revoke a consent key whose code was never redeemed, so an abandoned sign-in
|
|
63
|
+
* doesn't leave a live key nobody holds. A used key is kept: its code may have
|
|
64
|
+
* been redeemed on another replica.
|
|
65
|
+
*/
|
|
66
|
+
export async function revokeUnredeemedConsentToken(req, tokenId) {
|
|
67
|
+
const store = req.deps.data.apiTokens;
|
|
68
|
+
if (!store)
|
|
69
|
+
return;
|
|
70
|
+
const { ctx } = requireCaller(req);
|
|
71
|
+
const token = await store.get(ctx, tokenId);
|
|
72
|
+
if (!token || token.revokedAt || token.lastUsedAt)
|
|
73
|
+
return;
|
|
74
|
+
await store.revoke(ctx, tokenId, 'owner');
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=oauthConsent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauthConsent.js","sourceRoot":"","sources":["../../src/handlers/oauthConsent.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
* correct. The rest are lifted, logic intact, with reads moved onto `req.deps`.
|
|
8
8
|
*/
|
|
9
9
|
import { type ApiHandler } from '../api/index.js';
|
|
10
|
+
/**
|
|
11
|
+
* Projects the caller can view. `canCreateDefinitions` says whether
|
|
12
|
+
* `POST /definitions` would take this project from this caller: the same rule
|
|
13
|
+
* as the route, and for an API token its `upload` scope there.
|
|
14
|
+
*/
|
|
10
15
|
export declare const listProjects: ApiHandler;
|
|
11
16
|
export declare const createProject: ApiHandler;
|
|
12
17
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/handlers/projects.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAYN,KAAK,UAAU,EACf,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/handlers/projects.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAYN,KAAK,UAAU,EACf,MAAM,iBAAiB,CAAC;AAyBzB;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,UAgC1B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,UAiD3B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,UAmCxB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,UAuE3B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,UAO3B,CAAC"}
|