@enbox/dwn-server 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/src/admin/admin-api.d.ts +5 -1
- package/dist/esm/src/admin/admin-api.d.ts.map +1 -1
- package/dist/esm/src/admin/admin-api.js +327 -7
- package/dist/esm/src/admin/admin-api.js.map +1 -1
- package/dist/esm/src/admin/admin-auth.d.ts +21 -3
- package/dist/esm/src/admin/admin-auth.d.ts.map +1 -1
- package/dist/esm/src/admin/admin-auth.js +17 -9
- package/dist/esm/src/admin/admin-auth.js.map +1 -1
- package/dist/esm/src/admin/admin-passkey-store.d.ts +68 -0
- package/dist/esm/src/admin/admin-passkey-store.d.ts.map +1 -0
- package/dist/esm/src/admin/admin-passkey-store.js +132 -0
- package/dist/esm/src/admin/admin-passkey-store.js.map +1 -0
- package/dist/esm/src/admin/admin-session.d.ts +35 -0
- package/dist/esm/src/admin/admin-session.d.ts.map +1 -0
- package/dist/esm/src/admin/admin-session.js +91 -0
- package/dist/esm/src/admin/admin-session.js.map +1 -0
- package/dist/esm/src/admin/admin-store.d.ts +4 -0
- package/dist/esm/src/admin/admin-store.d.ts.map +1 -1
- package/dist/esm/src/admin/admin-store.js +6 -2
- package/dist/esm/src/admin/admin-store.js.map +1 -1
- package/dist/esm/src/admin/audit-log.d.ts.map +1 -1
- package/dist/esm/src/admin/audit-log.js +5 -43
- package/dist/esm/src/admin/audit-log.js.map +1 -1
- package/dist/esm/src/admin/index.d.ts +5 -1
- package/dist/esm/src/admin/index.d.ts.map +1 -1
- package/dist/esm/src/admin/index.js +2 -0
- package/dist/esm/src/admin/index.js.map +1 -1
- package/dist/esm/src/admin/types.d.ts +22 -0
- package/dist/esm/src/admin/types.d.ts.map +1 -1
- package/dist/esm/src/admin/webhook-manager.d.ts.map +1 -1
- package/dist/esm/src/admin/webhook-manager.js +11 -10
- package/dist/esm/src/admin/webhook-manager.js.map +1 -1
- package/dist/esm/src/config.d.ts +18 -0
- package/dist/esm/src/config.d.ts.map +1 -1
- package/dist/esm/src/config.js +18 -0
- package/dist/esm/src/config.js.map +1 -1
- package/dist/esm/src/connect/connect-server.d.ts +75 -0
- package/dist/esm/src/connect/connect-server.d.ts.map +1 -0
- package/dist/esm/src/{web5-connect/web5-connect-server.js → connect/connect-server.js} +32 -24
- package/dist/esm/src/connect/connect-server.js.map +1 -0
- package/dist/esm/src/{web5-connect → connect}/sql-ttl-cache.d.ts +11 -1
- package/dist/esm/src/connect/sql-ttl-cache.d.ts.map +1 -0
- package/dist/esm/src/{web5-connect → connect}/sql-ttl-cache.js +19 -20
- package/dist/esm/src/connect/sql-ttl-cache.js.map +1 -0
- package/dist/esm/src/dwn-server.d.ts.map +1 -1
- package/dist/esm/src/dwn-server.js +46 -11
- package/dist/esm/src/dwn-server.js.map +1 -1
- package/dist/esm/src/http-api.d.ts +6 -2
- package/dist/esm/src/http-api.d.ts.map +1 -1
- package/dist/esm/src/http-api.js +31 -17
- package/dist/esm/src/http-api.js.map +1 -1
- package/dist/esm/src/migrations/001-initial-server-schema.d.ts +21 -0
- package/dist/esm/src/migrations/001-initial-server-schema.d.ts.map +1 -0
- package/dist/esm/src/migrations/001-initial-server-schema.js +97 -0
- package/dist/esm/src/migrations/001-initial-server-schema.js.map +1 -0
- package/dist/esm/src/migrations/index.d.ts +13 -0
- package/dist/esm/src/migrations/index.d.ts.map +1 -0
- package/dist/esm/src/migrations/index.js +5 -0
- package/dist/esm/src/migrations/index.js.map +1 -0
- package/dist/esm/src/registration/registration-store.d.ts +4 -0
- package/dist/esm/src/registration/registration-store.d.ts.map +1 -1
- package/dist/esm/src/registration/registration-store.js +11 -34
- package/dist/esm/src/registration/registration-store.js.map +1 -1
- package/dist/esm/src/server-migration-runner.d.ts +23 -0
- package/dist/esm/src/server-migration-runner.d.ts.map +1 -0
- package/dist/esm/src/server-migration-runner.js +57 -0
- package/dist/esm/src/server-migration-runner.js.map +1 -0
- package/dist/esm/src/storage.d.ts +15 -0
- package/dist/esm/src/storage.d.ts.map +1 -1
- package/dist/esm/src/storage.js +135 -17
- package/dist/esm/src/storage.js.map +1 -1
- package/package.json +8 -27
- package/src/admin/admin-api.ts +403 -10
- package/src/admin/admin-auth.ts +38 -9
- package/src/admin/admin-passkey-store.ts +190 -0
- package/src/admin/admin-session.ts +116 -0
- package/src/admin/admin-store.ts +6 -2
- package/src/admin/audit-log.ts +7 -44
- package/src/admin/index.ts +5 -0
- package/src/admin/types.ts +28 -0
- package/src/admin/webhook-manager.ts +12 -10
- package/src/config.ts +21 -0
- package/src/connect/connect-server.ts +150 -0
- package/src/{web5-connect → connect}/sql-ttl-cache.ts +21 -22
- package/src/dwn-server.ts +49 -11
- package/src/http-api.ts +37 -18
- package/src/migrations/001-initial-server-schema.ts +114 -0
- package/src/migrations/index.ts +18 -0
- package/src/registration/registration-store.ts +13 -36
- package/src/server-migration-runner.ts +74 -0
- package/src/storage.ts +145 -17
- package/dist/esm/src/web5-connect/sql-ttl-cache.d.ts.map +0 -1
- package/dist/esm/src/web5-connect/sql-ttl-cache.js.map +0 -1
- package/dist/esm/src/web5-connect/web5-connect-server.d.ts +0 -58
- package/dist/esm/src/web5-connect/web5-connect-server.d.ts.map +0 -1
- package/dist/esm/src/web5-connect/web5-connect-server.js.map +0 -1
- package/src/web5-connect/web5-connect-server.ts +0 -123
package/src/storage.ts
CHANGED
|
@@ -20,6 +20,7 @@ import { Kysely } from 'kysely';
|
|
|
20
20
|
|
|
21
21
|
import { createBunSqliteDatabase } from '@enbox/dwn-sql-store';
|
|
22
22
|
import { PluginLoader } from './plugin-loader.js';
|
|
23
|
+
import { runServerMigrations } from './server-migration-runner.js';
|
|
23
24
|
|
|
24
25
|
import {
|
|
25
26
|
DataStoreLevel,
|
|
@@ -55,26 +56,27 @@ export enum BackendTypes {
|
|
|
55
56
|
export type DwnStore = DataStore | StateIndex | MessageStore | ResumableTaskStore;
|
|
56
57
|
|
|
57
58
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
59
|
+
* Returns a (potentially cached) dialect for the given connection URL. For
|
|
60
|
+
* Postgres, creates a pool with configurable sizing from the server config.
|
|
61
|
+
* For other backends, delegates to `getDialectFromUrl()` which handles its
|
|
62
|
+
* own caching (critical for in-memory SQLite).
|
|
63
|
+
*
|
|
64
|
+
* All Postgres dialects are cached in a separate map keyed by URL so that
|
|
65
|
+
* multiple DWN stores sharing the same Postgres URL reuse a single
|
|
66
|
+
* `pg.Pool`, reducing connection count from 4 × pool_max to 1 × pool_max.
|
|
62
67
|
*/
|
|
63
|
-
const
|
|
68
|
+
const postgresDialectCache: Map<string, Dialect> = new Map();
|
|
64
69
|
|
|
65
|
-
/**
|
|
66
|
-
* Returns a (potentially cached) dialect for the given Postgres connection URL.
|
|
67
|
-
* Non-Postgres URLs always return a fresh dialect (no caching).
|
|
68
|
-
*/
|
|
69
70
|
function getOrCreateDialect(connectionUrl: URL, config: DwnServerConfig): Dialect {
|
|
70
71
|
const protocol = connectionUrl.protocol.slice(0, -1);
|
|
71
72
|
|
|
72
73
|
if (protocol !== BackendTypes.POSTGRES) {
|
|
74
|
+
// getDialectFromUrl handles its own caching for SQLite/MySQL.
|
|
73
75
|
return getDialectFromUrl(connectionUrl);
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
const key = connectionUrl.toString();
|
|
77
|
-
const cached =
|
|
79
|
+
const cached = postgresDialectCache.get(key);
|
|
78
80
|
if (cached !== undefined) {
|
|
79
81
|
return cached;
|
|
80
82
|
}
|
|
@@ -92,7 +94,7 @@ function getOrCreateDialect(connectionUrl: URL, config: DwnServerConfig): Dialec
|
|
|
92
94
|
cursor : Cursor,
|
|
93
95
|
});
|
|
94
96
|
|
|
95
|
-
|
|
97
|
+
postgresDialectCache.set(key, dialect);
|
|
96
98
|
return dialect;
|
|
97
99
|
}
|
|
98
100
|
|
|
@@ -152,13 +154,99 @@ async function runSqlMigrationsIfNeeded(config: DwnServerConfig): Promise<void>
|
|
|
152
154
|
console.log(`DWN migrations applied: ${applied.join(', ')}`);
|
|
153
155
|
}
|
|
154
156
|
} finally {
|
|
155
|
-
//
|
|
156
|
-
//
|
|
157
|
-
//
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
// Do NOT destroy the Kysely instance — the dialect is cached and will be
|
|
158
|
+
// reused by stores. For in-memory SQLite, destroying would close the
|
|
159
|
+
// database and lose all migrated schema. For Postgres, the pool is shared.
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Runs DWN server schema migrations (admin stores, registration, TTL cache)
|
|
165
|
+
* if the given URL points to a SQL backend. Uses the `registrationStoreUrl`
|
|
166
|
+
* (or the TTL cache URL) as the target database.
|
|
167
|
+
*
|
|
168
|
+
* Server migrations use a separate tracking table (`dwn_server_migration`)
|
|
169
|
+
* so they do not conflict with the DWN store migrations.
|
|
170
|
+
*
|
|
171
|
+
* Call this once during server startup, before creating admin stores.
|
|
172
|
+
*
|
|
173
|
+
* @returns The dialect used for the target database (so the caller can reuse
|
|
174
|
+
* it for the TTL cache and admin stores), or `undefined` if no SQL
|
|
175
|
+
* backend was configured or needed.
|
|
176
|
+
*/
|
|
177
|
+
export async function runServerMigrationsIfNeeded(config: DwnServerConfig): Promise<Dialect | undefined> {
|
|
178
|
+
const sqlBackends: string[] = [BackendTypes.SQLITE, BackendTypes.MYSQL, BackendTypes.POSTGRES];
|
|
179
|
+
|
|
180
|
+
// Determine the target URL for server migrations. Prefer registrationStoreUrl
|
|
181
|
+
// since admin stores and the TTL cache share that database. Fall back to
|
|
182
|
+
// ttlCacheUrl when no registration store is configured (the cacheEntries
|
|
183
|
+
// table still needs a schema).
|
|
184
|
+
const targetUrl = config.registrationStoreUrl ?? config.ttlCacheUrl;
|
|
185
|
+
if (!targetUrl) {
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (isFilePath(targetUrl)) {
|
|
190
|
+
return undefined;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
let parsedUrl: URL;
|
|
194
|
+
try {
|
|
195
|
+
parsedUrl = new URL(targetUrl);
|
|
196
|
+
} catch {
|
|
197
|
+
return undefined;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const protocol = parsedUrl.protocol.slice(0, -1);
|
|
201
|
+
if (!sqlBackends.includes(protocol)) {
|
|
202
|
+
return undefined;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// When both registrationStoreUrl and ttlCacheUrl are set and differ,
|
|
206
|
+
// validate they point at the same database — the cacheEntries table is
|
|
207
|
+
// included in the server migration so it must live alongside the other
|
|
208
|
+
// server tables.
|
|
209
|
+
if (config.registrationStoreUrl && config.ttlCacheUrl
|
|
210
|
+
&& config.ttlCacheUrl !== config.registrationStoreUrl) {
|
|
211
|
+
let ttlUrl: URL | undefined;
|
|
212
|
+
try {
|
|
213
|
+
ttlUrl = new URL(config.ttlCacheUrl);
|
|
214
|
+
} catch { /* not a URL */ }
|
|
215
|
+
|
|
216
|
+
if (ttlUrl) {
|
|
217
|
+
const ttlProtocol = ttlUrl.protocol.slice(0, -1);
|
|
218
|
+
if (sqlBackends.includes(ttlProtocol)) {
|
|
219
|
+
throw new Error(
|
|
220
|
+
'DWN server misconfiguration: DWN_TTL_CACHE_URL must point to the same database as ' +
|
|
221
|
+
'DWN_REGISTRATION_STORE_URL (or DWN_STORAGE) because the cacheEntries table is managed ' +
|
|
222
|
+
'by the server migration system. ' +
|
|
223
|
+
`Got registrationStoreUrl="${config.registrationStoreUrl}", ttlCacheUrl="${config.ttlCacheUrl}".`
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const dialect = getOrCreateDialect(parsedUrl, config);
|
|
230
|
+
const db = new Kysely<Record<string, unknown>>({ dialect });
|
|
231
|
+
try {
|
|
232
|
+
const applied = await runServerMigrations(db, dialect);
|
|
233
|
+
if (applied.length > 0) {
|
|
234
|
+
console.log(`Server migrations applied: ${applied.join(', ')}`);
|
|
235
|
+
}
|
|
236
|
+
} finally {
|
|
237
|
+
// For Postgres, don't destroy — the pool is cached in sharedDialectCache.
|
|
238
|
+
// For SQLite/MySQL, we also keep the Kysely instance alive so the caller
|
|
239
|
+
// can reuse the same dialect (critical for in-memory SQLite).
|
|
240
|
+
if (protocol === BackendTypes.POSTGRES) {
|
|
241
|
+
// Pool stays alive via sharedDialectCache.
|
|
160
242
|
}
|
|
243
|
+
// NOTE: We intentionally do NOT destroy the Kysely instance for any
|
|
244
|
+
// backend. The dialect is returned to the caller for reuse (e.g. by the
|
|
245
|
+
// TTL cache and admin stores). For in-memory SQLite, destroying would
|
|
246
|
+
// lose the database.
|
|
161
247
|
}
|
|
248
|
+
|
|
249
|
+
return dialect;
|
|
162
250
|
}
|
|
163
251
|
|
|
164
252
|
function getLevelStore(
|
|
@@ -264,6 +352,21 @@ async function loadStoreFromFilePath(
|
|
|
264
352
|
}
|
|
265
353
|
}
|
|
266
354
|
|
|
355
|
+
/**
|
|
356
|
+
* Cache for the in-memory SQLite dialect. Since every call to
|
|
357
|
+
* `createBunSqliteDatabase(':memory:')` creates a separate, empty database,
|
|
358
|
+
* we must ensure that `getDialectFromUrl(new URL('sqlite://'))` always
|
|
359
|
+
* returns the same dialect (and thus the same underlying database) within a
|
|
360
|
+
* process. This is critical for the DWN server startup flow where migrations,
|
|
361
|
+
* the registration store, and the TTL cache all need to share the same
|
|
362
|
+
* in-memory database.
|
|
363
|
+
*
|
|
364
|
+
* File-based SQLite and other backends are NOT cached here — file-based SQLite
|
|
365
|
+
* connections naturally share state through the filesystem, and caching would
|
|
366
|
+
* break test isolation when multiple test files run in the same process.
|
|
367
|
+
*/
|
|
368
|
+
let inMemorySqliteDialect: Dialect | undefined;
|
|
369
|
+
|
|
267
370
|
export function getDialectFromUrl(connectionUrl: URL): Dialect {
|
|
268
371
|
switch (connectionUrl.protocol.slice(0, -1)) {
|
|
269
372
|
case BackendTypes.SQLITE: {
|
|
@@ -275,9 +378,32 @@ export function getDialectFromUrl(connectionUrl: URL): Dialect {
|
|
|
275
378
|
fs.mkdirSync(connectionUrl.host, { recursive: true });
|
|
276
379
|
}
|
|
277
380
|
|
|
278
|
-
// Use in-memory database if no path is provided (for tests)
|
|
381
|
+
// Use in-memory database if no path is provided (for tests).
|
|
279
382
|
const dbPath = path || ':memory:';
|
|
280
383
|
|
|
384
|
+
// For in-memory SQLite, return a cached dialect so that all callers
|
|
385
|
+
// (migrations, registration store, TTL cache) share the same database.
|
|
386
|
+
// The wrapper makes close() a no-op so that individual consumers (e.g.
|
|
387
|
+
// DwnServer.stop() → Dwn.close() → store.close()) cannot destroy the
|
|
388
|
+
// shared database out from under other consumers.
|
|
389
|
+
if (dbPath === ':memory:') {
|
|
390
|
+
if (inMemorySqliteDialect === undefined) {
|
|
391
|
+
const sharedDb = createBunSqliteDatabase(':memory:');
|
|
392
|
+
const nonCloseableDb = {
|
|
393
|
+
close(): void {
|
|
394
|
+
// no-op — shared instance must survive the process
|
|
395
|
+
},
|
|
396
|
+
prepare(sql: string): ReturnType<typeof sharedDb.prepare> {
|
|
397
|
+
return sharedDb.prepare(sql);
|
|
398
|
+
},
|
|
399
|
+
};
|
|
400
|
+
inMemorySqliteDialect = new SqliteDialect({
|
|
401
|
+
database: async (): Promise<typeof nonCloseableDb> => nonCloseableDb,
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
return inMemorySqliteDialect;
|
|
405
|
+
}
|
|
406
|
+
|
|
281
407
|
return new SqliteDialect({
|
|
282
408
|
database: async () => createBunSqliteDatabase(dbPath),
|
|
283
409
|
});
|
|
@@ -291,6 +417,8 @@ export function getDialectFromUrl(connectionUrl: URL): Dialect {
|
|
|
291
417
|
pool : async () => new pg.Pool({ connectionString: connectionUrl.toString() }),
|
|
292
418
|
cursor : Cursor,
|
|
293
419
|
});
|
|
420
|
+
default:
|
|
421
|
+
throw new Error(`Unsupported database protocol: ${connectionUrl.protocol}`);
|
|
294
422
|
}
|
|
295
423
|
}
|
|
296
424
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sql-ttl-cache.d.ts","sourceRoot":"","sources":["../../../../src/web5-connect/sql-ttl-cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAGpD;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAkB;IACxD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAAM;IAEtD,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,EAAE,CAAwB;IAClC,OAAO,CAAC,YAAY,CAAiB;IAErC,OAAO;IAKP;;OAEG;WACiB,MAAM,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;YAQvD,UAAU;IA0BxB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAMzB;;;OAGG;IACU,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW3E;;OAEG;IACU,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IA+B1D;;OAEG;IACU,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/C;;OAEG;IACU,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;CAMpD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sql-ttl-cache.js","sourceRoot":"","sources":["../../../../src/web5-connect/sql-ttl-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The Web5 Connect Request object.
|
|
3
|
-
*/
|
|
4
|
-
export type Web5ConnectRequest = any;
|
|
5
|
-
/**
|
|
6
|
-
* The Web5 Connect Response object, which is also an OIDC ID token
|
|
7
|
-
*/
|
|
8
|
-
export type Web5ConnectResponse = any;
|
|
9
|
-
/**
|
|
10
|
-
* The result of the setWeb5ConnectRequest() method.
|
|
11
|
-
*/
|
|
12
|
-
export type SetWeb5ConnectRequestResult = {
|
|
13
|
-
/**
|
|
14
|
-
* The Request URI that the wallet should use to retrieve the request object.
|
|
15
|
-
*/
|
|
16
|
-
request_uri: string;
|
|
17
|
-
/**
|
|
18
|
-
* The time in seconds that the Request URI is valid for.
|
|
19
|
-
*/
|
|
20
|
-
expires_in: number;
|
|
21
|
-
};
|
|
22
|
-
/**
|
|
23
|
-
* The Web5 Connect Server is responsible for handling the Web5 Connect flow.
|
|
24
|
-
*/
|
|
25
|
-
export declare class Web5ConnectServer {
|
|
26
|
-
static readonly ttlInSeconds = 600;
|
|
27
|
-
private baseUrl;
|
|
28
|
-
private cache;
|
|
29
|
-
/**
|
|
30
|
-
* Creates a new instance of the Web5 Connect Server.
|
|
31
|
-
* @param params.baseUrl The the base URL of the connect server including the port.
|
|
32
|
-
* This is given to the Identity Provider (wallet) to fetch the Web5 Connect Request object.
|
|
33
|
-
* @param params.sqlTtlCacheUrl The URL of the SQL database to use as the TTL cache.
|
|
34
|
-
*/
|
|
35
|
-
static create({ baseUrl, sqlTtlCacheUrl }: {
|
|
36
|
-
baseUrl: string;
|
|
37
|
-
sqlTtlCacheUrl: string;
|
|
38
|
-
}): Promise<Web5ConnectServer>;
|
|
39
|
-
private constructor();
|
|
40
|
-
/**
|
|
41
|
-
* Stores the given Web5 Connect Request object, which is also an OAuth 2 Pushed Authorization Request (PAR) object.
|
|
42
|
-
* This is the initial call to the connect server to start the Web5 Connect flow.
|
|
43
|
-
*/
|
|
44
|
-
setWeb5ConnectRequest(request: Web5ConnectRequest): Promise<SetWeb5ConnectRequestResult>;
|
|
45
|
-
/**
|
|
46
|
-
* Returns the Web5 Connect Request object. The request ID can only be used once.
|
|
47
|
-
*/
|
|
48
|
-
getWeb5ConnectRequest(requestId: string): Promise<Web5ConnectRequest | undefined>;
|
|
49
|
-
/**
|
|
50
|
-
* Sets the Web5 Connect Response object, which is also an OIDC ID token.
|
|
51
|
-
*/
|
|
52
|
-
setWeb5ConnectResponse(state: string, response: Web5ConnectResponse): Promise<any>;
|
|
53
|
-
/**
|
|
54
|
-
* Gets the Web5 Connect Response object. The `state` string can only be used once.
|
|
55
|
-
*/
|
|
56
|
-
getWeb5ConnectResponse(state: string): Promise<Web5ConnectResponse | undefined>;
|
|
57
|
-
}
|
|
58
|
-
//# sourceMappingURL=web5-connect-server.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"web5-connect-server.d.ts","sourceRoot":"","sources":["../../../../src/web5-connect/web5-connect-server.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAErC;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEtC;;GAEG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,gBAAuB,YAAY,OAAO;IAE1C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAAc;IAE3B;;;;;OAKG;WACiB,MAAM,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE;QACtD,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,MAAM,CAAC;KACxB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAU9B,OAAO;IAMP;;;OAGG;IACU,qBAAqB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,2BAA2B,CAAC;IAcrG;;OAEG;IACU,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC;IAc9F;;OAEG;IACU,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAAC,GAAG,CAAC;IAI/F;;OAEG;IACU,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC;CAa7F"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"web5-connect-server.js","sourceRoot":"","sources":["../../../../src/web5-connect/web5-connect-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AA2BjD;;GAEG;AACH,MAAM,OAAO,iBAAiB;IACrB,MAAM,CAAU,YAAY,GAAG,GAAG,CAAC;IAElC,OAAO,CAAS;IAChB,KAAK,CAAc;IAE3B;;;;;OAKG;IACI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,cAAc,EAGnD;QACC,MAAM,iBAAiB,GAAG,IAAI,iBAAiB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QAE7D,wBAAwB;QACxB,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;QAC9D,iBAAiB,CAAC,KAAK,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAE/D,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,YAAoB,EAAE,OAAO,EAE5B;QACC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,qBAAqB,CAAC,OAA2B;QAC5D,yBAAyB;QACzB,MAAM,SAAS,GAAG,WAAW,CAAC,UAAU,EAAE,CAAC;QAC3C,MAAM,WAAW,GAAG,GAAG,IAAI,CAAC,OAAO,sBAAsB,SAAS,MAAM,CAAC;QAEzE,4BAA4B;QAC5B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,SAAS,EAAE,EAAE,OAAO,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC;QAEnF,OAAO;YACL,WAAW;YACX,UAAU,EAAE,iBAAiB,CAAC,YAAY;SAC3C,CAAC;IACJ,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,qBAAqB,CAAC,SAAiB;QAClD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,SAAS,EAAE,CAAC,CAAC;QAE7D,mEAAmE;QACnE,yFAAyF;QACzF,wFAAwF;QACxF,mEAAmE;QACnE,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,SAAS,EAAE,CAAC,CAAC;QAC5C,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,sBAAsB,CAAC,KAAa,EAAE,QAA6B;QAC9E,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,KAAK,EAAE,EAAE,QAAQ,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC;IACnF,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,sBAAsB,CAAC,KAAa;QAC/C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC;QAE3D,wEAAwE;QACxE,yFAAyF;QACzF,wFAAwF;QACxF,mEAAmE;QACnE,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC;QACzC,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC"}
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import { CryptoUtils } from '@enbox/crypto';
|
|
2
|
-
|
|
3
|
-
import { getDialectFromUrl } from '../storage.js';
|
|
4
|
-
import { SqlTtlCache } from './sql-ttl-cache.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* The Web5 Connect Request object.
|
|
8
|
-
*/
|
|
9
|
-
export type Web5ConnectRequest = any; // TODO: define type in common repo for reuse (https://github.com/enboxorg/enbox/issues/138)
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* The Web5 Connect Response object, which is also an OIDC ID token
|
|
13
|
-
*/
|
|
14
|
-
export type Web5ConnectResponse = any; // TODO: define type in common repo for reuse (https://github.com/enboxorg/enbox/issues/138)
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* The result of the setWeb5ConnectRequest() method.
|
|
18
|
-
*/
|
|
19
|
-
export type SetWeb5ConnectRequestResult = {
|
|
20
|
-
/**
|
|
21
|
-
* The Request URI that the wallet should use to retrieve the request object.
|
|
22
|
-
*/
|
|
23
|
-
request_uri: string;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* The time in seconds that the Request URI is valid for.
|
|
27
|
-
*/
|
|
28
|
-
expires_in: number;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* The Web5 Connect Server is responsible for handling the Web5 Connect flow.
|
|
33
|
-
*/
|
|
34
|
-
export class Web5ConnectServer {
|
|
35
|
-
public static readonly ttlInSeconds = 600;
|
|
36
|
-
|
|
37
|
-
private baseUrl: string;
|
|
38
|
-
private cache: SqlTtlCache;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Creates a new instance of the Web5 Connect Server.
|
|
42
|
-
* @param params.baseUrl The the base URL of the connect server including the port.
|
|
43
|
-
* This is given to the Identity Provider (wallet) to fetch the Web5 Connect Request object.
|
|
44
|
-
* @param params.sqlTtlCacheUrl The URL of the SQL database to use as the TTL cache.
|
|
45
|
-
*/
|
|
46
|
-
public static async create({ baseUrl, sqlTtlCacheUrl }: {
|
|
47
|
-
baseUrl: string;
|
|
48
|
-
sqlTtlCacheUrl: string;
|
|
49
|
-
}): Promise<Web5ConnectServer> {
|
|
50
|
-
const web5ConnectServer = new Web5ConnectServer({ baseUrl });
|
|
51
|
-
|
|
52
|
-
// Initialize TTL cache.
|
|
53
|
-
const sqlDialect = getDialectFromUrl(new URL(sqlTtlCacheUrl));
|
|
54
|
-
web5ConnectServer.cache = await SqlTtlCache.create(sqlDialect);
|
|
55
|
-
|
|
56
|
-
return web5ConnectServer;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
private constructor({ baseUrl }: {
|
|
60
|
-
baseUrl: string;
|
|
61
|
-
}) {
|
|
62
|
-
this.baseUrl = baseUrl;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Stores the given Web5 Connect Request object, which is also an OAuth 2 Pushed Authorization Request (PAR) object.
|
|
67
|
-
* This is the initial call to the connect server to start the Web5 Connect flow.
|
|
68
|
-
*/
|
|
69
|
-
public async setWeb5ConnectRequest(request: Web5ConnectRequest): Promise<SetWeb5ConnectRequestResult> {
|
|
70
|
-
// Generate a request URI
|
|
71
|
-
const requestId = CryptoUtils.randomUuid();
|
|
72
|
-
const request_uri = `${this.baseUrl}/connect/authorize/${requestId}.jwt`;
|
|
73
|
-
|
|
74
|
-
// Store the Request Object.
|
|
75
|
-
this.cache.insert(`request:${requestId}`, request, Web5ConnectServer.ttlInSeconds);
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
request_uri,
|
|
79
|
-
expires_in: Web5ConnectServer.ttlInSeconds,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Returns the Web5 Connect Request object. The request ID can only be used once.
|
|
85
|
-
*/
|
|
86
|
-
public async getWeb5ConnectRequest(requestId: string): Promise<Web5ConnectRequest | undefined> {
|
|
87
|
-
const request = await this.cache.get(`request:${requestId}`);
|
|
88
|
-
|
|
89
|
-
// Delete the Request Object from cache once it has been retrieved.
|
|
90
|
-
// IMPORTANT: only delete if the object exists, otherwise there could be a race condition
|
|
91
|
-
// where the object does not exist in this call but becomes available immediately after,
|
|
92
|
-
// we would end up deleting it before it is successfully retrieved.
|
|
93
|
-
if (request !== undefined) {
|
|
94
|
-
this.cache.delete(`request:${requestId}`);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return request;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Sets the Web5 Connect Response object, which is also an OIDC ID token.
|
|
102
|
-
*/
|
|
103
|
-
public async setWeb5ConnectResponse(state: string, response: Web5ConnectResponse): Promise<any> {
|
|
104
|
-
this.cache.insert(`response:${state}`, response, Web5ConnectServer.ttlInSeconds);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Gets the Web5 Connect Response object. The `state` string can only be used once.
|
|
109
|
-
*/
|
|
110
|
-
public async getWeb5ConnectResponse(state: string): Promise<Web5ConnectResponse | undefined> {
|
|
111
|
-
const response = await this.cache.get(`response:${state}`);
|
|
112
|
-
|
|
113
|
-
// Delete the Response object from the cache once it has been retrieved.
|
|
114
|
-
// IMPORTANT: only delete if the object exists, otherwise there could be a race condition
|
|
115
|
-
// where the object does not exist in this call but becomes available immediately after,
|
|
116
|
-
// we would end up deleting it before it is successfully retrieved.
|
|
117
|
-
if (response !== undefined) {
|
|
118
|
-
this.cache.delete(`response:${state}`);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return response;
|
|
122
|
-
}
|
|
123
|
-
}
|