@vibes.diy/api-svc 13.1.11 → 13.1.13
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/asset-session.d.ts +2 -0
- package/asset-session.js +2 -1
- package/asset-session.js.map +1 -1
- package/create-handler.js +2 -0
- package/create-handler.js.map +1 -1
- package/evento-handler-manifest.js +2 -0
- package/evento-handler-manifest.js.map +1 -1
- package/index.d.ts +3 -0
- package/index.js +3 -0
- package/index.js.map +1 -1
- package/intern/apply-seed.js.map +1 -1
- package/intern/attempt-backend-fetch.js +1 -0
- package/intern/attempt-backend-fetch.js.map +1 -1
- package/intern/attempt-backend-onchange.js +1 -0
- package/intern/attempt-backend-onchange.js.map +1 -1
- package/intern/attempt-backend-scheduled.js +1 -0
- package/intern/attempt-backend-scheduled.js.map +1 -1
- package/intern/backend-connections-callback.d.ts +4 -0
- package/intern/backend-connections-callback.js +13 -2
- package/intern/backend-connections-callback.js.map +1 -1
- package/intern/backend-egress.d.ts +1 -0
- package/intern/backend-egress.js +24 -10
- package/intern/backend-egress.js.map +1 -1
- package/intern/components/vibe-page.js +29 -1
- package/intern/components/vibe-page.js.map +1 -1
- package/intern/connections-providers.d.ts +2 -1
- package/intern/connections-providers.js +7 -4
- package/intern/connections-providers.js.map +1 -1
- package/intern/egress-read-lane.js.map +1 -1
- package/intern/egress-request-log.d.ts +14 -0
- package/intern/egress-request-log.js +16 -0
- package/intern/egress-request-log.js.map +1 -0
- package/intern/get-vibe-route-hints.d.ts +2 -0
- package/intern/get-vibe-route-hints.js +4 -0
- package/intern/get-vibe-route-hints.js.map +1 -1
- package/intern/load-selected-backend.js.map +1 -1
- package/intern/notify-connection-expiring.d.ts +24 -0
- package/intern/notify-connection-expiring.js +78 -0
- package/intern/notify-connection-expiring.js.map +1 -0
- package/intern/prompt-assembly.d.ts +6 -2
- package/intern/prompt-assembly.js +32 -25
- package/intern/prompt-assembly.js.map +1 -1
- package/intern/render-vibe.js +2 -0
- package/intern/render-vibe.js.map +1 -1
- package/intern/ssr-theme-css.d.ts +1 -0
- package/intern/ssr-theme-css.js +12 -0
- package/intern/ssr-theme-css.js.map +1 -1
- package/intern/version-timeline.d.ts +0 -1
- package/intern/version-timeline.js +0 -12
- package/intern/version-timeline.js.map +1 -1
- package/package.json +12 -11
- package/public/asset-session.d.ts +1 -0
- package/public/asset-session.js +4 -3
- package/public/asset-session.js.map +1 -1
- package/public/connections-oauth.d.ts +44 -0
- package/public/connections-oauth.js +302 -0
- package/public/connections-oauth.js.map +1 -0
- package/public/connections-status.d.ts +18 -0
- package/public/connections-status.js +42 -0
- package/public/connections-status.js.map +1 -0
- package/public/connections-store.d.ts +73 -0
- package/public/connections-store.js +173 -0
- package/public/connections-store.js.map +1 -0
- package/public/ensure-app-slug-item.js +1 -17
- package/public/ensure-app-slug-item.js.map +1 -1
- package/public/files-asset.js +3 -1
- package/public/files-asset.js.map +1 -1
- package/public/fork-app.js +0 -15
- package/public/fork-app.js.map +1 -1
- package/public/get-app-by-fsid.js +26 -3
- package/public/get-app-by-fsid.js.map +1 -1
- package/public/github-setup.d.ts +18 -0
- package/public/github-setup.js +85 -61
- package/public/github-setup.js.map +1 -1
- package/public/prompt-chat-section.d.ts +2 -2
- package/public/prompt-chat-section.js +2 -2
- package/public/prompt-chat-section.js.map +1 -1
- package/public/publish-app.js +0 -10
- package/public/publish-app.js.map +1 -1
- package/public/report-egress.d.ts +19 -0
- package/public/report-egress.js +168 -0
- package/public/report-egress.js.map +1 -0
- package/usage-report/egress-abuse-alert-util.d.ts +100 -0
- package/usage-report/egress-abuse-alert-util.js +246 -0
- package/usage-report/egress-abuse-alert-util.js.map +1 -0
- package/usage-report/egress-abuse-alert.d.ts +1 -0
- package/usage-report/egress-abuse-alert.js +94 -0
- package/usage-report/egress-abuse-alert.js.map +1 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { BuildURI, exception2Result, TxtEnDecoderSingleton, URI } from "@adviser/cement";
|
|
2
|
+
import { and, eq } from "drizzle-orm/sql/expressions";
|
|
3
|
+
import { loadSelectedBackend } from "../intern/load-selected-backend.js";
|
|
4
|
+
import { CONNECTION_PROVIDERS } from "../intern/connections-providers.js";
|
|
5
|
+
import { timingSafeEqualString } from "./github-webhook.js";
|
|
6
|
+
import { disconnectAccount, revokeConsent } from "./connections-store.js";
|
|
7
|
+
import { appExists, b64urlDecode, b64urlEncode, GITHUB_OAUTH_AUTHORIZE_URL, GITHUB_SETUP_OAUTH_STATE_TTL_MS, GITHUB_SETUP_STATE_RE, hmacHex, htmlPage, sessionTokenFrom, stateSecret, } from "./github-setup.js";
|
|
8
|
+
export const CONNECT_STATE_PREFIX = "c1.";
|
|
9
|
+
export function isConnectState(state) {
|
|
10
|
+
return state.startsWith(CONNECT_STATE_PREFIX);
|
|
11
|
+
}
|
|
12
|
+
export async function signConnectState(secret, state) {
|
|
13
|
+
const blob = b64urlEncode(TxtEnDecoderSingleton().encode(JSON.stringify(state)));
|
|
14
|
+
const message = `${CONNECT_STATE_PREFIX}${blob}`;
|
|
15
|
+
return `${message}.${await hmacHex(secret, message)}`;
|
|
16
|
+
}
|
|
17
|
+
export async function verifyConnectState(secret, signed, nowMs) {
|
|
18
|
+
if (!isConnectState(signed))
|
|
19
|
+
return undefined;
|
|
20
|
+
const dot = signed.lastIndexOf(".");
|
|
21
|
+
if (dot <= CONNECT_STATE_PREFIX.length)
|
|
22
|
+
return undefined;
|
|
23
|
+
const message = signed.slice(0, dot);
|
|
24
|
+
const provided = signed.slice(dot + 1);
|
|
25
|
+
const expected = await hmacHex(secret, message);
|
|
26
|
+
if (!timingSafeEqualString(provided, expected))
|
|
27
|
+
return undefined;
|
|
28
|
+
const json = b64urlDecode(message.slice(CONNECT_STATE_PREFIX.length));
|
|
29
|
+
if (json === undefined)
|
|
30
|
+
return undefined;
|
|
31
|
+
const rParsed = exception2Result(() => JSON.parse(json));
|
|
32
|
+
if (rParsed.isErr())
|
|
33
|
+
return undefined;
|
|
34
|
+
const parsed = rParsed.Ok();
|
|
35
|
+
if (typeof parsed.owner !== "string" || typeof parsed.slug !== "string")
|
|
36
|
+
return undefined;
|
|
37
|
+
if (typeof parsed.provider !== "string" || parsed.provider === "")
|
|
38
|
+
return undefined;
|
|
39
|
+
if (typeof parsed.userId !== "string" || parsed.userId === "")
|
|
40
|
+
return undefined;
|
|
41
|
+
if (!Array.isArray(parsed.scopes) || parsed.scopes.some((s) => typeof s !== "string"))
|
|
42
|
+
return undefined;
|
|
43
|
+
if (typeof parsed.exp !== "number" || nowMs >= parsed.exp)
|
|
44
|
+
return undefined;
|
|
45
|
+
if (!GITHUB_SETUP_STATE_RE.test(`${parsed.owner}/${parsed.slug}`))
|
|
46
|
+
return undefined;
|
|
47
|
+
return {
|
|
48
|
+
userId: parsed.userId,
|
|
49
|
+
owner: parsed.owner,
|
|
50
|
+
slug: parsed.slug,
|
|
51
|
+
provider: parsed.provider,
|
|
52
|
+
scopes: parsed.scopes,
|
|
53
|
+
exp: parsed.exp,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export const CONNECT_APPROVAL_PREFIX = "f1.";
|
|
57
|
+
export const CONNECT_APPROVAL_TTL_MS = 2 * 60 * 1000;
|
|
58
|
+
export async function signConnectApproval(secret, approval) {
|
|
59
|
+
const blob = b64urlEncode(TxtEnDecoderSingleton().encode(JSON.stringify(approval)));
|
|
60
|
+
const message = `${CONNECT_APPROVAL_PREFIX}${blob}`;
|
|
61
|
+
return `${message}.${await hmacHex(secret, message)}`;
|
|
62
|
+
}
|
|
63
|
+
export async function verifyConnectApproval(secret, signed, nowMs) {
|
|
64
|
+
if (!signed.startsWith(CONNECT_APPROVAL_PREFIX))
|
|
65
|
+
return undefined;
|
|
66
|
+
const dot = signed.lastIndexOf(".");
|
|
67
|
+
if (dot <= CONNECT_APPROVAL_PREFIX.length)
|
|
68
|
+
return undefined;
|
|
69
|
+
const message = signed.slice(0, dot);
|
|
70
|
+
const provided = signed.slice(dot + 1);
|
|
71
|
+
const expected = await hmacHex(secret, message);
|
|
72
|
+
if (!timingSafeEqualString(provided, expected))
|
|
73
|
+
return undefined;
|
|
74
|
+
const json = b64urlDecode(message.slice(CONNECT_APPROVAL_PREFIX.length));
|
|
75
|
+
if (json === undefined)
|
|
76
|
+
return undefined;
|
|
77
|
+
const rParsed = exception2Result(() => JSON.parse(json));
|
|
78
|
+
if (rParsed.isErr())
|
|
79
|
+
return undefined;
|
|
80
|
+
const parsed = rParsed.Ok();
|
|
81
|
+
if (typeof parsed.id !== "string" || parsed.id === "")
|
|
82
|
+
return undefined;
|
|
83
|
+
if (typeof parsed.userId !== "string" || parsed.userId === "")
|
|
84
|
+
return undefined;
|
|
85
|
+
if (typeof parsed.provider !== "string" || parsed.provider === "")
|
|
86
|
+
return undefined;
|
|
87
|
+
if (typeof parsed.owner !== "string" || typeof parsed.slug !== "string")
|
|
88
|
+
return undefined;
|
|
89
|
+
if (typeof parsed.exp !== "number" || nowMs >= parsed.exp)
|
|
90
|
+
return undefined;
|
|
91
|
+
if (!GITHUB_SETUP_STATE_RE.test(`${parsed.owner}/${parsed.slug}`))
|
|
92
|
+
return undefined;
|
|
93
|
+
return {
|
|
94
|
+
id: parsed.id,
|
|
95
|
+
userId: parsed.userId,
|
|
96
|
+
provider: parsed.provider,
|
|
97
|
+
owner: parsed.owner,
|
|
98
|
+
slug: parsed.slug,
|
|
99
|
+
exp: parsed.exp,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function callbackUrl(env) {
|
|
103
|
+
const base = env.VIBES_DIY_PUBLIC_BASE_URL ?? "";
|
|
104
|
+
if (base.length === 0)
|
|
105
|
+
return undefined;
|
|
106
|
+
return BuildURI.from(base).pathname("/github/setup").cleanParams().hash("").toString();
|
|
107
|
+
}
|
|
108
|
+
async function connectGate(input) {
|
|
109
|
+
if (!Object.prototype.hasOwnProperty.call(CONNECTION_PROVIDERS, input.provider)) {
|
|
110
|
+
return { ok: false, reason: "unknown-provider" };
|
|
111
|
+
}
|
|
112
|
+
if (!GITHUB_SETUP_STATE_RE.test(`${input.owner}/${input.slug}`))
|
|
113
|
+
return { ok: false, reason: "malformed" };
|
|
114
|
+
const sql = { db: input.vctx.sql.db, tables: input.vctx.sql.tables };
|
|
115
|
+
if (!(await appExists(sql, input.owner, input.slug)))
|
|
116
|
+
return { ok: false, reason: "no-vibe" };
|
|
117
|
+
const loaded = await loadSelectedBackend(input.vctx, input.owner, input.slug);
|
|
118
|
+
const declared = loaded.ok ? (loaded.parsed.connections ?? []) : [];
|
|
119
|
+
const decl = declared.find((c) => c.provider === input.provider);
|
|
120
|
+
if (decl === undefined)
|
|
121
|
+
return { ok: false, reason: "undeclared" };
|
|
122
|
+
return { ok: true, scopes: decl.scopes };
|
|
123
|
+
}
|
|
124
|
+
function gateRefusalPage(reason) {
|
|
125
|
+
switch (reason) {
|
|
126
|
+
case "unknown-provider":
|
|
127
|
+
return htmlPage("Unknown connection", "That connection type is not one vibes.diy offers.", 400);
|
|
128
|
+
case "malformed":
|
|
129
|
+
return htmlPage("Invalid link", "That connection link is malformed. Open the app and try again.", 400);
|
|
130
|
+
case "no-vibe":
|
|
131
|
+
return htmlPage("Vibe not found", "That app does not exist, so there is nothing to connect it to.", 404);
|
|
132
|
+
case "undeclared":
|
|
133
|
+
return htmlPage("Not requested by this app", "This app has not asked for that connection, so there is nothing to approve. If you expected it, the app's " +
|
|
134
|
+
"author needs to publish a version that requests it.", 403);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function gateRefusalStatus(reason) {
|
|
138
|
+
switch (reason) {
|
|
139
|
+
case "unknown-provider":
|
|
140
|
+
return 400;
|
|
141
|
+
case "malformed":
|
|
142
|
+
return 400;
|
|
143
|
+
case "no-vibe":
|
|
144
|
+
return 404;
|
|
145
|
+
case "undeclared":
|
|
146
|
+
return 403;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
export async function handleConnectionsApprove(request, env, deps) {
|
|
150
|
+
const token = sessionTokenFrom(request);
|
|
151
|
+
const userId = token === undefined ? undefined : await deps.verifySessionToken(token);
|
|
152
|
+
if (userId === undefined)
|
|
153
|
+
return jsonResponse({ type: "error", message: "unauthorized" }, 401);
|
|
154
|
+
const body = await readJsonBody(request);
|
|
155
|
+
if (body === undefined)
|
|
156
|
+
return jsonResponse({ type: "error", message: "invalid body" }, 400);
|
|
157
|
+
const provider = typeof body.provider === "string" ? body.provider : "";
|
|
158
|
+
const owner = typeof body.owner === "string" ? body.owner : "";
|
|
159
|
+
const slug = typeof body.slug === "string" ? body.slug : "";
|
|
160
|
+
const gate = await connectGate({ vctx: deps.vctx, provider, owner, slug });
|
|
161
|
+
if (!gate.ok) {
|
|
162
|
+
return jsonResponse({ type: "error", message: "connection not available" }, gateRefusalStatus(gate.reason));
|
|
163
|
+
}
|
|
164
|
+
const signingKey = stateSecret(env);
|
|
165
|
+
if (signingKey === undefined) {
|
|
166
|
+
return jsonResponse({ type: "error", message: "connections are not configured" }, 503);
|
|
167
|
+
}
|
|
168
|
+
const nowMs = deps.nowMs ?? Date.now();
|
|
169
|
+
const id = crypto.randomUUID();
|
|
170
|
+
const t = deps.vctx.sql.tables.connectionApprovals;
|
|
171
|
+
await deps.vctx.sql.db.insert(t).values({
|
|
172
|
+
id,
|
|
173
|
+
userId,
|
|
174
|
+
provider,
|
|
175
|
+
ownerHandle: owner,
|
|
176
|
+
appSlug: slug,
|
|
177
|
+
created: new Date(nowMs).toISOString(),
|
|
178
|
+
consumedAt: "",
|
|
179
|
+
});
|
|
180
|
+
const approval = await signConnectApproval(signingKey, {
|
|
181
|
+
id,
|
|
182
|
+
userId,
|
|
183
|
+
provider,
|
|
184
|
+
owner,
|
|
185
|
+
slug,
|
|
186
|
+
exp: nowMs + CONNECT_APPROVAL_TTL_MS,
|
|
187
|
+
});
|
|
188
|
+
return new Response(JSON.stringify({ type: "ok", approval }), {
|
|
189
|
+
status: 200,
|
|
190
|
+
headers: { "Content-Type": "application/json" },
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
export async function handleConnectionsStart(request, env, deps) {
|
|
194
|
+
const token = sessionTokenFrom(request);
|
|
195
|
+
const userId = token === undefined ? undefined : await deps.verifySessionToken(token);
|
|
196
|
+
if (userId === undefined) {
|
|
197
|
+
return htmlPage("Sign in required", "Sign in to vibes.diy and start the connection again from the app.", 401);
|
|
198
|
+
}
|
|
199
|
+
const uri = URI.from(request.url);
|
|
200
|
+
const provider = uri.getParam("provider") ?? "";
|
|
201
|
+
const owner = uri.getParam("owner") ?? "";
|
|
202
|
+
const slug = uri.getParam("slug") ?? "";
|
|
203
|
+
const gate = await connectGate({ vctx: deps.vctx, provider, owner, slug });
|
|
204
|
+
if (!gate.ok)
|
|
205
|
+
return gateRefusalPage(gate.reason);
|
|
206
|
+
const signingKey = stateSecret(env);
|
|
207
|
+
const clientId = env.VIBES_GH_APP_CLIENT_ID ?? "";
|
|
208
|
+
const clientSecret = env.VIBES_GH_APP_CLIENT_SECRET ?? "";
|
|
209
|
+
const redirectUri = callbackUrl(env);
|
|
210
|
+
if (clientId.length === 0 || clientSecret.length === 0 || signingKey === undefined || redirectUri === undefined) {
|
|
211
|
+
return htmlPage("Not available", "Connections are not configured on this environment, so nothing has been connected.", 503);
|
|
212
|
+
}
|
|
213
|
+
const nowMs = deps.nowMs ?? Date.now();
|
|
214
|
+
const approval = await verifyConnectApproval(signingKey, uri.getParam("approval") ?? "", nowMs);
|
|
215
|
+
const bound = approval !== undefined &&
|
|
216
|
+
approval.userId === userId &&
|
|
217
|
+
approval.provider === provider &&
|
|
218
|
+
approval.owner === owner &&
|
|
219
|
+
approval.slug === slug;
|
|
220
|
+
if (!bound)
|
|
221
|
+
return approvalRefusalPage();
|
|
222
|
+
const t = deps.vctx.sql.tables.connectionApprovals;
|
|
223
|
+
const claimed = await deps.vctx.sql.db
|
|
224
|
+
.update(t)
|
|
225
|
+
.set({ consumedAt: new Date(nowMs).toISOString() })
|
|
226
|
+
.where(and(eq(t.id, approval.id), eq(t.consumedAt, ""), eq(t.userId, userId), eq(t.provider, provider), eq(t.ownerHandle, owner), eq(t.appSlug, slug)))
|
|
227
|
+
.returning({ id: t.id });
|
|
228
|
+
if (claimed.length === 0)
|
|
229
|
+
return approvalRefusalPage();
|
|
230
|
+
const signed = await signConnectState(signingKey, {
|
|
231
|
+
userId,
|
|
232
|
+
owner,
|
|
233
|
+
slug,
|
|
234
|
+
provider,
|
|
235
|
+
scopes: gate.scopes,
|
|
236
|
+
exp: nowMs + GITHUB_SETUP_OAUTH_STATE_TTL_MS,
|
|
237
|
+
});
|
|
238
|
+
const authorize = BuildURI.from(GITHUB_OAUTH_AUTHORIZE_URL)
|
|
239
|
+
.setParam("client_id", clientId)
|
|
240
|
+
.setParam("redirect_uri", redirectUri)
|
|
241
|
+
.setParam("state", signed);
|
|
242
|
+
if (gate.scopes.length > 0)
|
|
243
|
+
authorize.setParam("scope", gate.scopes.join(" "));
|
|
244
|
+
return new Response(null, { status: 302, headers: { Location: authorize.toString() } });
|
|
245
|
+
}
|
|
246
|
+
function approvalRefusalPage() {
|
|
247
|
+
return htmlPage("Approval required", "This connection was not approved, or the approval has already been used. Open the app and start the connection " +
|
|
248
|
+
"again from the button inside it.", 403);
|
|
249
|
+
}
|
|
250
|
+
function jsonResponse(body, status) {
|
|
251
|
+
return new Response(JSON.stringify(body), { status, headers: { "Content-Type": "application/json" } });
|
|
252
|
+
}
|
|
253
|
+
async function callerOf(request, deps) {
|
|
254
|
+
const token = sessionTokenFrom(request);
|
|
255
|
+
const userId = token === undefined ? undefined : await deps.verifySessionToken(token);
|
|
256
|
+
if (userId === undefined)
|
|
257
|
+
return { refusal: jsonResponse({ type: "error", message: "unauthorized" }, 401) };
|
|
258
|
+
return { userId };
|
|
259
|
+
}
|
|
260
|
+
async function readJsonBody(request) {
|
|
261
|
+
const r = await exception2Result(() => request.json());
|
|
262
|
+
if (r.isErr())
|
|
263
|
+
return undefined;
|
|
264
|
+
const body = r.Ok();
|
|
265
|
+
if (typeof body !== "object" || body === null || Array.isArray(body))
|
|
266
|
+
return undefined;
|
|
267
|
+
return body;
|
|
268
|
+
}
|
|
269
|
+
function providerOf(body) {
|
|
270
|
+
const provider = typeof body.provider === "string" ? body.provider : "";
|
|
271
|
+
return Object.prototype.hasOwnProperty.call(CONNECTION_PROVIDERS, provider) ? provider : undefined;
|
|
272
|
+
}
|
|
273
|
+
export async function handleConnectionsRevoke(request, deps) {
|
|
274
|
+
const caller = await callerOf(request, deps);
|
|
275
|
+
if ("refusal" in caller)
|
|
276
|
+
return caller.refusal;
|
|
277
|
+
const body = await readJsonBody(request);
|
|
278
|
+
if (body === undefined)
|
|
279
|
+
return jsonResponse({ type: "error", message: "invalid body" }, 400);
|
|
280
|
+
const provider = providerOf(body);
|
|
281
|
+
const ownerHandle = typeof body.owner === "string" ? body.owner : "";
|
|
282
|
+
const appSlug = typeof body.slug === "string" ? body.slug : "";
|
|
283
|
+
if (provider === undefined || !GITHUB_SETUP_STATE_RE.test(`${ownerHandle}/${appSlug}`)) {
|
|
284
|
+
return jsonResponse({ type: "error", message: "invalid request" }, 400);
|
|
285
|
+
}
|
|
286
|
+
await revokeConsent(deps.sql, { userId: caller.userId, provider, ownerHandle, appSlug }, deps.nowMs ?? Date.now());
|
|
287
|
+
return jsonResponse({ type: "ok" }, 200);
|
|
288
|
+
}
|
|
289
|
+
export async function handleConnectionsDisconnect(request, deps) {
|
|
290
|
+
const caller = await callerOf(request, deps);
|
|
291
|
+
if ("refusal" in caller)
|
|
292
|
+
return caller.refusal;
|
|
293
|
+
const body = await readJsonBody(request);
|
|
294
|
+
if (body === undefined)
|
|
295
|
+
return jsonResponse({ type: "error", message: "invalid body" }, 400);
|
|
296
|
+
const provider = providerOf(body);
|
|
297
|
+
if (provider === undefined)
|
|
298
|
+
return jsonResponse({ type: "error", message: "invalid request" }, 400);
|
|
299
|
+
await disconnectAccount(deps.sql, { userId: caller.userId, provider }, deps.nowMs ?? Date.now());
|
|
300
|
+
return jsonResponse({ type: "ok" }, 200);
|
|
301
|
+
}
|
|
302
|
+
//# sourceMappingURL=connections-oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connections-oauth.js","sourceRoot":"","sources":["../../jsr/public/connections-oauth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { VibesApiSQLCtx } from "../types.js";
|
|
2
|
+
import { type VerifySessionToken } from "./github-setup.js";
|
|
3
|
+
export interface ConnectionsStatusDeps {
|
|
4
|
+
readonly verifySessionToken: VerifySessionToken;
|
|
5
|
+
readonly vctx: VibesApiSQLCtx;
|
|
6
|
+
readonly nowMs?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface ConnectionsStatusBody {
|
|
9
|
+
readonly provider: string;
|
|
10
|
+
readonly declared?: boolean;
|
|
11
|
+
readonly scopes?: readonly string[];
|
|
12
|
+
readonly why?: string;
|
|
13
|
+
readonly state: "absent" | "live" | "expiring" | "dead";
|
|
14
|
+
readonly consented?: boolean;
|
|
15
|
+
readonly accountLabel?: string;
|
|
16
|
+
readonly expiresAt?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function handleConnectionsStatus(request: Request, deps: ConnectionsStatusDeps): Promise<Response>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { URI } from "@adviser/cement";
|
|
2
|
+
import { loadSelectedBackend } from "../intern/load-selected-backend.js";
|
|
3
|
+
import { CONNECTION_PROVIDERS } from "../intern/connections-providers.js";
|
|
4
|
+
import { readConnectionStatus } from "./connections-store.js";
|
|
5
|
+
import { GITHUB_SETUP_STATE_RE, sessionTokenFrom } from "./github-setup.js";
|
|
6
|
+
function jsonResponse(body, status) {
|
|
7
|
+
return new Response(JSON.stringify(body), {
|
|
8
|
+
status,
|
|
9
|
+
headers: { "Content-Type": "application/json", "Cache-Control": "no-store" },
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
export async function handleConnectionsStatus(request, deps) {
|
|
13
|
+
const uri = URI.from(request.url);
|
|
14
|
+
const provider = uri.getParam("provider") ?? "";
|
|
15
|
+
const owner = uri.getParam("owner") ?? "";
|
|
16
|
+
const slug = uri.getParam("slug") ?? "";
|
|
17
|
+
const accountScoped = owner === "" && slug === "";
|
|
18
|
+
if (!accountScoped && !GITHUB_SETUP_STATE_RE.test(`${owner}/${slug}`)) {
|
|
19
|
+
return jsonResponse({ type: "error", message: "invalid request" }, 400);
|
|
20
|
+
}
|
|
21
|
+
const known = Object.prototype.hasOwnProperty.call(CONNECTION_PROVIDERS, provider);
|
|
22
|
+
const loaded = known && !accountScoped ? await loadSelectedBackend(deps.vctx, owner, slug) : undefined;
|
|
23
|
+
const declared = loaded !== undefined && loaded.ok ? (loaded.parsed.connections ?? []) : [];
|
|
24
|
+
const decl = declared.find((c) => c.provider === provider);
|
|
25
|
+
const token = sessionTokenFrom(request);
|
|
26
|
+
const userId = token === undefined ? undefined : await deps.verifySessionToken(token);
|
|
27
|
+
const declarationHalf = accountScoped
|
|
28
|
+
? { provider }
|
|
29
|
+
: { provider, declared: decl !== undefined, scopes: decl?.scopes ?? [], why: decl?.why ?? "" };
|
|
30
|
+
if (userId === undefined) {
|
|
31
|
+
return jsonResponse({ ...declarationHalf, state: "absent", ...(accountScoped ? {} : { consented: false }) }, 200);
|
|
32
|
+
}
|
|
33
|
+
const status = await readConnectionStatus({ db: deps.vctx.sql.db, tables: deps.vctx.sql.tables }, { userId, provider, ownerHandle: owner, appSlug: slug }, deps.nowMs ?? Date.now());
|
|
34
|
+
return jsonResponse({
|
|
35
|
+
...declarationHalf,
|
|
36
|
+
state: status.state,
|
|
37
|
+
...(accountScoped ? {} : { consented: status.consented }),
|
|
38
|
+
...(status.accountLabel === undefined ? {} : { accountLabel: status.accountLabel }),
|
|
39
|
+
...(status.expiresAt === undefined ? {} : { expiresAt: status.expiresAt }),
|
|
40
|
+
}, 200);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=connections-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connections-status.js","sourceRoot":"","sources":["../../jsr/public/connections-status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { cfDrizzle, VibesApiTables } from "@vibes.diy/api-sql";
|
|
2
|
+
export interface ConnectionsSql {
|
|
3
|
+
db: ReturnType<typeof cfDrizzle>["db"];
|
|
4
|
+
tables: VibesApiTables;
|
|
5
|
+
}
|
|
6
|
+
export type ConnectionState = "absent" | "live" | "expiring" | "dead";
|
|
7
|
+
export declare const CONNECTION_EXPIRING_WINDOW_MS: number;
|
|
8
|
+
export interface ConnectionStatus {
|
|
9
|
+
readonly provider: string;
|
|
10
|
+
readonly state: ConnectionState;
|
|
11
|
+
readonly consented: boolean;
|
|
12
|
+
readonly accountLabel?: string;
|
|
13
|
+
readonly expiresAt?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ConnectionKey {
|
|
16
|
+
readonly userId: string;
|
|
17
|
+
readonly provider: string;
|
|
18
|
+
readonly ownerHandle: string;
|
|
19
|
+
readonly appSlug: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function packScopes(scopes: readonly string[]): string;
|
|
22
|
+
export declare function readConnectionStatus(sql: ConnectionsSql, key: ConnectionKey, nowMs?: number): Promise<ConnectionStatus>;
|
|
23
|
+
export interface ExpiringGrantRow {
|
|
24
|
+
readonly userId: string;
|
|
25
|
+
readonly provider: string;
|
|
26
|
+
readonly accountLabel: string;
|
|
27
|
+
readonly expiresAt: string;
|
|
28
|
+
}
|
|
29
|
+
export interface ExpiringGrantCursor {
|
|
30
|
+
readonly expiresAt: string;
|
|
31
|
+
readonly userId: string;
|
|
32
|
+
readonly provider: string;
|
|
33
|
+
}
|
|
34
|
+
export declare function listGrantsExpiringBefore(sql: ConnectionsSql, input: {
|
|
35
|
+
readonly nowIso: string;
|
|
36
|
+
readonly horizonIso: string;
|
|
37
|
+
readonly limit: number;
|
|
38
|
+
readonly after?: ExpiringGrantCursor;
|
|
39
|
+
}): Promise<ExpiringGrantRow[]>;
|
|
40
|
+
export declare function countGrantsExpiringBefore(sql: ConnectionsSql, input: {
|
|
41
|
+
readonly nowIso: string;
|
|
42
|
+
readonly horizonIso: string;
|
|
43
|
+
readonly after?: ExpiringGrantCursor;
|
|
44
|
+
}): Promise<number>;
|
|
45
|
+
export interface UpsertGrantInput {
|
|
46
|
+
readonly userId: string;
|
|
47
|
+
readonly provider: string;
|
|
48
|
+
readonly accessToken: string;
|
|
49
|
+
readonly accountLabel: string;
|
|
50
|
+
readonly accountId?: string;
|
|
51
|
+
readonly refreshToken?: string;
|
|
52
|
+
readonly expiresAt?: string;
|
|
53
|
+
readonly scopes: readonly string[];
|
|
54
|
+
readonly nowMs: number;
|
|
55
|
+
}
|
|
56
|
+
export interface UpsertGrantResult {
|
|
57
|
+
readonly consentsRevoked: boolean;
|
|
58
|
+
}
|
|
59
|
+
export declare function upsertGrant(sql: ConnectionsSql, input: UpsertGrantInput): Promise<UpsertGrantResult>;
|
|
60
|
+
export interface UpsertConsentInput {
|
|
61
|
+
readonly userId: string;
|
|
62
|
+
readonly provider: string;
|
|
63
|
+
readonly ownerHandle: string;
|
|
64
|
+
readonly appSlug: string;
|
|
65
|
+
readonly scopes: readonly string[];
|
|
66
|
+
readonly nowMs: number;
|
|
67
|
+
}
|
|
68
|
+
export declare function upsertConsent(sql: ConnectionsSql, input: UpsertConsentInput): Promise<void>;
|
|
69
|
+
export declare function revokeConsent(sql: ConnectionsSql, key: ConnectionKey, nowMs?: number): Promise<void>;
|
|
70
|
+
export declare function disconnectAccount(sql: ConnectionsSql, input: {
|
|
71
|
+
readonly userId: string;
|
|
72
|
+
readonly provider: string;
|
|
73
|
+
}, nowMs?: number): Promise<void>;
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { and, eq, gt, lte, ne, or } from "drizzle-orm/sql/expressions";
|
|
2
|
+
import { sql as drizzleSql } from "drizzle-orm";
|
|
3
|
+
export const CONNECTION_EXPIRING_WINDOW_MS = 14 * 24 * 60 * 60 * 1000;
|
|
4
|
+
export function packScopes(scopes) {
|
|
5
|
+
return scopes.filter((s) => s !== "").join(" ");
|
|
6
|
+
}
|
|
7
|
+
export async function readConnectionStatus(sql, key, nowMs = Date.now()) {
|
|
8
|
+
const t_g = sql.tables.thirdPartyGrants;
|
|
9
|
+
const grant = await sql.db
|
|
10
|
+
.select({
|
|
11
|
+
accountLabel: t_g.accountLabel,
|
|
12
|
+
expiresAt: t_g.expiresAt,
|
|
13
|
+
status: t_g.status,
|
|
14
|
+
revokedAt: t_g.revokedAt,
|
|
15
|
+
})
|
|
16
|
+
.from(t_g)
|
|
17
|
+
.where(and(eq(t_g.userId, key.userId), eq(t_g.provider, key.provider)))
|
|
18
|
+
.limit(1)
|
|
19
|
+
.then((rows) => rows[0]);
|
|
20
|
+
const t_c = sql.tables.thirdPartyConsents;
|
|
21
|
+
const consent = await sql.db
|
|
22
|
+
.select({ userId: t_c.userId })
|
|
23
|
+
.from(t_c)
|
|
24
|
+
.where(and(eq(t_c.userId, key.userId), eq(t_c.provider, key.provider), eq(t_c.ownerHandle, key.ownerHandle), eq(t_c.appSlug, key.appSlug), eq(t_c.revokedAt, "")))
|
|
25
|
+
.limit(1)
|
|
26
|
+
.then((rows) => rows[0]);
|
|
27
|
+
const consented = consent !== undefined;
|
|
28
|
+
if (grant === undefined)
|
|
29
|
+
return { provider: key.provider, state: "absent", consented };
|
|
30
|
+
const expiresAt = grant.expiresAt === "" ? undefined : grant.expiresAt;
|
|
31
|
+
const base = {
|
|
32
|
+
provider: key.provider,
|
|
33
|
+
consented,
|
|
34
|
+
...(grant.accountLabel === "" ? {} : { accountLabel: grant.accountLabel }),
|
|
35
|
+
...(expiresAt === undefined ? {} : { expiresAt }),
|
|
36
|
+
};
|
|
37
|
+
if (grant.revokedAt !== "" || grant.status === "dead")
|
|
38
|
+
return { ...base, state: "dead" };
|
|
39
|
+
if (expiresAt !== undefined) {
|
|
40
|
+
const at = Date.parse(expiresAt);
|
|
41
|
+
if (Number.isNaN(at) || at <= nowMs)
|
|
42
|
+
return { ...base, state: "dead" };
|
|
43
|
+
if (at - nowMs <= CONNECTION_EXPIRING_WINDOW_MS)
|
|
44
|
+
return { ...base, state: "expiring" };
|
|
45
|
+
}
|
|
46
|
+
return { ...base, state: "live" };
|
|
47
|
+
}
|
|
48
|
+
function expiringWindowWhere(t, input) {
|
|
49
|
+
const window = and(eq(t.revokedAt, ""), eq(t.status, "live"), ne(t.expiresAt, ""), gt(t.expiresAt, input.nowIso), lte(t.expiresAt, input.horizonIso));
|
|
50
|
+
const after = input.after;
|
|
51
|
+
if (after === undefined)
|
|
52
|
+
return window;
|
|
53
|
+
return and(window, or(gt(t.expiresAt, after.expiresAt), and(eq(t.expiresAt, after.expiresAt), gt(t.userId, after.userId)), and(eq(t.expiresAt, after.expiresAt), eq(t.userId, after.userId), gt(t.provider, after.provider))));
|
|
54
|
+
}
|
|
55
|
+
export async function listGrantsExpiringBefore(sql, input) {
|
|
56
|
+
const t = sql.tables.thirdPartyGrants;
|
|
57
|
+
return sql.db
|
|
58
|
+
.select({
|
|
59
|
+
userId: t.userId,
|
|
60
|
+
provider: t.provider,
|
|
61
|
+
accountLabel: t.accountLabel,
|
|
62
|
+
expiresAt: t.expiresAt,
|
|
63
|
+
})
|
|
64
|
+
.from(t)
|
|
65
|
+
.where(expiringWindowWhere(t, input))
|
|
66
|
+
.orderBy(t.expiresAt, t.userId, t.provider)
|
|
67
|
+
.limit(input.limit);
|
|
68
|
+
}
|
|
69
|
+
export async function countGrantsExpiringBefore(sql, input) {
|
|
70
|
+
const t = sql.tables.thirdPartyGrants;
|
|
71
|
+
const row = await sql.db
|
|
72
|
+
.select({ n: drizzleSql `cast(count(*) as int)` })
|
|
73
|
+
.from(t)
|
|
74
|
+
.where(expiringWindowWhere(t, input))
|
|
75
|
+
.then((rows) => rows[0]);
|
|
76
|
+
return row === undefined ? 0 : Number(row.n);
|
|
77
|
+
}
|
|
78
|
+
export async function upsertGrant(sql, input) {
|
|
79
|
+
const now = new Date(input.nowMs).toISOString();
|
|
80
|
+
const t_g = sql.tables.thirdPartyGrants;
|
|
81
|
+
const scopes = packScopes(input.scopes);
|
|
82
|
+
const expiresAt = input.expiresAt ?? "";
|
|
83
|
+
const accountId = input.accountId ?? "";
|
|
84
|
+
const existing = await sql.db
|
|
85
|
+
.select({ accountId: t_g.accountId })
|
|
86
|
+
.from(t_g)
|
|
87
|
+
.where(and(eq(t_g.userId, input.userId), eq(t_g.provider, input.provider)))
|
|
88
|
+
.limit(1)
|
|
89
|
+
.then((rows) => rows[0]);
|
|
90
|
+
const sameAccountProven = existing !== undefined && existing.accountId !== "" && accountId !== "" && existing.accountId === accountId;
|
|
91
|
+
const consentsRevoked = existing !== undefined && sameAccountProven === false;
|
|
92
|
+
if (consentsRevoked === true) {
|
|
93
|
+
const t_c = sql.tables.thirdPartyConsents;
|
|
94
|
+
await sql.db
|
|
95
|
+
.update(t_c)
|
|
96
|
+
.set({ revokedAt: now, updated: now })
|
|
97
|
+
.where(and(eq(t_c.userId, input.userId), eq(t_c.provider, input.provider), eq(t_c.revokedAt, "")));
|
|
98
|
+
}
|
|
99
|
+
await sql.db
|
|
100
|
+
.insert(t_g)
|
|
101
|
+
.values({
|
|
102
|
+
userId: input.userId,
|
|
103
|
+
provider: input.provider,
|
|
104
|
+
accountLabel: input.accountLabel,
|
|
105
|
+
accountId,
|
|
106
|
+
accessToken: input.accessToken,
|
|
107
|
+
refreshToken: input.refreshToken ?? "",
|
|
108
|
+
expiresAt,
|
|
109
|
+
scopes,
|
|
110
|
+
status: "live",
|
|
111
|
+
created: now,
|
|
112
|
+
updated: now,
|
|
113
|
+
revokedAt: "",
|
|
114
|
+
})
|
|
115
|
+
.onConflictDoUpdate({
|
|
116
|
+
target: [t_g.userId, t_g.provider],
|
|
117
|
+
set: {
|
|
118
|
+
accountLabel: input.accountLabel,
|
|
119
|
+
accountId,
|
|
120
|
+
accessToken: input.accessToken,
|
|
121
|
+
refreshToken: input.refreshToken ?? "",
|
|
122
|
+
expiresAt,
|
|
123
|
+
scopes,
|
|
124
|
+
status: "live",
|
|
125
|
+
updated: now,
|
|
126
|
+
revokedAt: "",
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
return { consentsRevoked };
|
|
130
|
+
}
|
|
131
|
+
export async function upsertConsent(sql, input) {
|
|
132
|
+
const now = new Date(input.nowMs).toISOString();
|
|
133
|
+
const t_c = sql.tables.thirdPartyConsents;
|
|
134
|
+
const scopes = packScopes(input.scopes);
|
|
135
|
+
await sql.db
|
|
136
|
+
.insert(t_c)
|
|
137
|
+
.values({
|
|
138
|
+
userId: input.userId,
|
|
139
|
+
provider: input.provider,
|
|
140
|
+
ownerHandle: input.ownerHandle,
|
|
141
|
+
appSlug: input.appSlug,
|
|
142
|
+
scopes,
|
|
143
|
+
created: now,
|
|
144
|
+
updated: now,
|
|
145
|
+
revokedAt: "",
|
|
146
|
+
})
|
|
147
|
+
.onConflictDoUpdate({
|
|
148
|
+
target: [t_c.userId, t_c.provider, t_c.ownerHandle, t_c.appSlug],
|
|
149
|
+
set: { scopes, updated: now, revokedAt: "" },
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
export async function revokeConsent(sql, key, nowMs = Date.now()) {
|
|
153
|
+
const now = new Date(nowMs).toISOString();
|
|
154
|
+
const t_c = sql.tables.thirdPartyConsents;
|
|
155
|
+
await sql.db
|
|
156
|
+
.update(t_c)
|
|
157
|
+
.set({ revokedAt: now, updated: now })
|
|
158
|
+
.where(and(eq(t_c.userId, key.userId), eq(t_c.provider, key.provider), eq(t_c.ownerHandle, key.ownerHandle), eq(t_c.appSlug, key.appSlug), eq(t_c.revokedAt, "")));
|
|
159
|
+
}
|
|
160
|
+
export async function disconnectAccount(sql, input, nowMs = Date.now()) {
|
|
161
|
+
const now = new Date(nowMs).toISOString();
|
|
162
|
+
const t_g = sql.tables.thirdPartyGrants;
|
|
163
|
+
await sql.db
|
|
164
|
+
.update(t_g)
|
|
165
|
+
.set({ revokedAt: now, status: "dead", updated: now })
|
|
166
|
+
.where(and(eq(t_g.userId, input.userId), eq(t_g.provider, input.provider), eq(t_g.revokedAt, "")));
|
|
167
|
+
const t_c = sql.tables.thirdPartyConsents;
|
|
168
|
+
await sql.db
|
|
169
|
+
.update(t_c)
|
|
170
|
+
.set({ revokedAt: now, updated: now })
|
|
171
|
+
.where(and(eq(t_c.userId, input.userId), eq(t_c.provider, input.provider), eq(t_c.revokedAt, "")));
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=connections-store.js.map
|