@arcblock/did-connect-service 4.1.10 → 4.1.12
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/_generated/asset-bytes.js +1 -1
- package/dist/_generated/asset-manifest.js +2 -2
- package/dist/assets/admin-core.cbbdbe6d.js +1465 -0
- package/dist/assets/admin-extra.35b91f98.js +2543 -0
- package/dist/blocklet-service-rpc.js +5 -5
- package/dist/blocklet-service-rpc.js.map +1 -1
- package/dist/blocklet-service.js +5 -5
- package/dist/blocklet-service.js.map +1 -1
- package/dist/env-config.d.ts +6 -3
- package/dist/env-config.d.ts.map +1 -1
- package/dist/env-config.js +21 -4
- package/dist/env-config.js.map +1 -1
- package/dist/handlers/avatar-handler.d.ts +9 -1
- package/dist/handlers/avatar-handler.d.ts.map +1 -1
- package/dist/handlers/avatar-handler.js +22 -6
- package/dist/handlers/avatar-handler.js.map +1 -1
- package/dist/handlers/did-connect-handler.d.ts.map +1 -1
- package/dist/handlers/did-connect-handler.js +9 -0
- package/dist/handlers/did-connect-handler.js.map +1 -1
- package/dist/handlers/email-login-handler.d.ts.map +1 -1
- package/dist/handlers/email-login-handler.js +9 -0
- package/dist/handlers/email-login-handler.js.map +1 -1
- package/dist/handlers/team-handler.d.ts.map +1 -1
- package/dist/handlers/team-handler.js +6 -3
- package/dist/handlers/team-handler.js.map +1 -1
- package/dist/og/ssrf-guard.d.ts.map +1 -1
- package/dist/og/ssrf-guard.js +21 -3
- package/dist/og/ssrf-guard.js.map +1 -1
- package/dist/pages/admin/scripts/utils.d.ts +1 -1
- package/dist/pages/admin/scripts/utils.d.ts.map +1 -1
- package/dist/pages/admin/scripts/utils.js +5 -1
- package/dist/pages/admin/scripts/utils.js.map +1 -1
- package/dist/pages/admin/tab-appearance.js +1 -1
- package/dist/pages/admin/tab-members.d.ts +1 -1
- package/dist/pages/admin/tab-members.d.ts.map +1 -1
- package/dist/pages/admin/tab-members.js +16 -6
- package/dist/pages/admin/tab-members.js.map +1 -1
- package/dist/pages/admin/tab-settings.d.ts.map +1 -1
- package/dist/pages/admin/tab-settings.js +4 -1
- package/dist/pages/admin/tab-settings.js.map +1 -1
- package/dist/pages/admin-instances-page.d.ts.map +1 -1
- package/dist/pages/admin-instances-page.js +13 -3
- package/dist/pages/admin-instances-page.js.map +1 -1
- package/dist/store/d1-store.d.ts.map +1 -1
- package/dist/store/d1-store.js +252 -214
- package/dist/store/d1-store.js.map +1 -1
- package/dist/store/d1-token-storage.js +7 -7
- package/dist/store/d1-token-storage.js.map +1 -1
- package/migrations/0010_rename_tables.sql +31 -0
- package/package.json +3 -3
package/dist/store/d1-store.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { dbToAccessType, invalidateRegexCache } from "../access/access-policy.js";
|
|
8
8
|
const SCHEMA_SQL = `
|
|
9
|
-
CREATE TABLE IF NOT EXISTS
|
|
9
|
+
CREATE TABLE IF NOT EXISTS cs_users (
|
|
10
10
|
did TEXT PRIMARY KEY,
|
|
11
11
|
pk TEXT NOT NULL DEFAULT '',
|
|
12
12
|
fullName TEXT,
|
|
@@ -40,10 +40,10 @@ CREATE TABLE IF NOT EXISTS users (
|
|
|
40
40
|
updatedBy TEXT
|
|
41
41
|
);
|
|
42
42
|
|
|
43
|
-
CREATE TABLE IF NOT EXISTS
|
|
43
|
+
CREATE TABLE IF NOT EXISTS cs_connected_accounts (
|
|
44
44
|
did TEXT PRIMARY KEY,
|
|
45
45
|
pk TEXT,
|
|
46
|
-
userDid TEXT REFERENCES
|
|
46
|
+
userDid TEXT REFERENCES cs_users(did),
|
|
47
47
|
provider TEXT NOT NULL,
|
|
48
48
|
id TEXT,
|
|
49
49
|
firstLoginAt TEXT,
|
|
@@ -58,14 +58,14 @@ CREATE TABLE IF NOT EXISTS connected_accounts (
|
|
|
58
58
|
updatedBy TEXT
|
|
59
59
|
);
|
|
60
60
|
|
|
61
|
-
CREATE TABLE IF NOT EXISTS
|
|
61
|
+
CREATE TABLE IF NOT EXISTS cs_challenges (
|
|
62
62
|
id TEXT PRIMARY KEY,
|
|
63
63
|
challenge TEXT NOT NULL,
|
|
64
64
|
invitationId TEXT,
|
|
65
65
|
createdAt TEXT DEFAULT (datetime('now'))
|
|
66
66
|
);
|
|
67
67
|
|
|
68
|
-
CREATE TABLE IF NOT EXISTS
|
|
68
|
+
CREATE TABLE IF NOT EXISTS cs_invitations (
|
|
69
69
|
id TEXT PRIMARY KEY,
|
|
70
70
|
teamDid TEXT NOT NULL,
|
|
71
71
|
role TEXT NOT NULL,
|
|
@@ -81,7 +81,7 @@ CREATE TABLE IF NOT EXISTS invitations (
|
|
|
81
81
|
updatedBy TEXT
|
|
82
82
|
);
|
|
83
83
|
|
|
84
|
-
CREATE TABLE IF NOT EXISTS
|
|
84
|
+
CREATE TABLE IF NOT EXISTS cs_audit_logs (
|
|
85
85
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
86
86
|
action TEXT NOT NULL,
|
|
87
87
|
operatorDid TEXT NOT NULL,
|
|
@@ -91,20 +91,20 @@ CREATE TABLE IF NOT EXISTS audit_logs (
|
|
|
91
91
|
createdAt TEXT DEFAULT (datetime('now'))
|
|
92
92
|
);
|
|
93
93
|
|
|
94
|
-
CREATE INDEX IF NOT EXISTS idx_users_email ON
|
|
95
|
-
CREATE INDEX IF NOT EXISTS idx_users_pk ON
|
|
96
|
-
CREATE INDEX IF NOT EXISTS idx_users_createdAt ON
|
|
97
|
-
CREATE INDEX IF NOT EXISTS idx_connected_accounts_userDid ON
|
|
98
|
-
CREATE INDEX IF NOT EXISTS idx_connected_accounts_pk ON
|
|
99
|
-
CREATE INDEX IF NOT EXISTS idx_invitations_status ON
|
|
100
|
-
CREATE INDEX IF NOT EXISTS idx_invitations_expireAt ON
|
|
101
|
-
CREATE INDEX IF NOT EXISTS idx_audit_logs_action ON
|
|
102
|
-
CREATE INDEX IF NOT EXISTS idx_audit_logs_operatorDid ON
|
|
103
|
-
CREATE INDEX IF NOT EXISTS idx_audit_logs_createdAt ON
|
|
104
|
-
CREATE INDEX IF NOT EXISTS idx_audit_logs_targetDid ON
|
|
105
|
-
CREATE INDEX IF NOT EXISTS idx_audit_logs_ip ON
|
|
94
|
+
CREATE INDEX IF NOT EXISTS idx_users_email ON cs_users(email);
|
|
95
|
+
CREATE INDEX IF NOT EXISTS idx_users_pk ON cs_users(pk);
|
|
96
|
+
CREATE INDEX IF NOT EXISTS idx_users_createdAt ON cs_users(createdAt);
|
|
97
|
+
CREATE INDEX IF NOT EXISTS idx_connected_accounts_userDid ON cs_connected_accounts(userDid);
|
|
98
|
+
CREATE INDEX IF NOT EXISTS idx_connected_accounts_pk ON cs_connected_accounts(pk);
|
|
99
|
+
CREATE INDEX IF NOT EXISTS idx_invitations_status ON cs_invitations(status);
|
|
100
|
+
CREATE INDEX IF NOT EXISTS idx_invitations_expireAt ON cs_invitations(expireAt);
|
|
101
|
+
CREATE INDEX IF NOT EXISTS idx_audit_logs_action ON cs_audit_logs(action);
|
|
102
|
+
CREATE INDEX IF NOT EXISTS idx_audit_logs_operatorDid ON cs_audit_logs(operatorDid);
|
|
103
|
+
CREATE INDEX IF NOT EXISTS idx_audit_logs_createdAt ON cs_audit_logs(createdAt);
|
|
104
|
+
CREATE INDEX IF NOT EXISTS idx_audit_logs_targetDid ON cs_audit_logs(targetDid);
|
|
105
|
+
CREATE INDEX IF NOT EXISTS idx_audit_logs_ip ON cs_audit_logs(ip);
|
|
106
106
|
|
|
107
|
-
CREATE TABLE IF NOT EXISTS
|
|
107
|
+
CREATE TABLE IF NOT EXISTS cs_access_policies (
|
|
108
108
|
id TEXT PRIMARY KEY,
|
|
109
109
|
name TEXT NOT NULL,
|
|
110
110
|
description TEXT DEFAULT '',
|
|
@@ -117,11 +117,11 @@ CREATE TABLE IF NOT EXISTS access_policies (
|
|
|
117
117
|
updatedBy TEXT
|
|
118
118
|
);
|
|
119
119
|
|
|
120
|
-
CREATE TABLE IF NOT EXISTS
|
|
120
|
+
CREATE TABLE IF NOT EXISTS cs_security_rules (
|
|
121
121
|
id TEXT PRIMARY KEY,
|
|
122
122
|
pathPattern TEXT NOT NULL,
|
|
123
123
|
priority INTEGER DEFAULT 0,
|
|
124
|
-
accessPolicyId TEXT NOT NULL REFERENCES
|
|
124
|
+
accessPolicyId TEXT NOT NULL REFERENCES cs_access_policies(id),
|
|
125
125
|
enabled INTEGER DEFAULT 1,
|
|
126
126
|
remark TEXT DEFAULT '',
|
|
127
127
|
createdAt TEXT DEFAULT (datetime('now')),
|
|
@@ -130,10 +130,10 @@ CREATE TABLE IF NOT EXISTS security_rules (
|
|
|
130
130
|
updatedBy TEXT
|
|
131
131
|
);
|
|
132
132
|
|
|
133
|
-
CREATE INDEX IF NOT EXISTS idx_security_rules_priority ON
|
|
134
|
-
CREATE INDEX IF NOT EXISTS idx_security_rules_accessPolicyId ON
|
|
133
|
+
CREATE INDEX IF NOT EXISTS idx_security_rules_priority ON cs_security_rules(priority);
|
|
134
|
+
CREATE INDEX IF NOT EXISTS idx_security_rules_accessPolicyId ON cs_security_rules(accessPolicyId);
|
|
135
135
|
|
|
136
|
-
CREATE TABLE IF NOT EXISTS
|
|
136
|
+
CREATE TABLE IF NOT EXISTS cs_access_keys (
|
|
137
137
|
accessKeyId TEXT PRIMARY KEY,
|
|
138
138
|
accessKeyPublic TEXT NOT NULL,
|
|
139
139
|
role TEXT NOT NULL,
|
|
@@ -146,22 +146,43 @@ CREATE TABLE IF NOT EXISTS access_keys (
|
|
|
146
146
|
updatedBy TEXT
|
|
147
147
|
);
|
|
148
148
|
|
|
149
|
-
CREATE INDEX IF NOT EXISTS idx_access_keys_createdBy ON
|
|
150
|
-
CREATE INDEX IF NOT EXISTS idx_access_keys_expireAt ON
|
|
151
|
-
CREATE INDEX IF NOT EXISTS idx_access_keys_lastUsedAt ON
|
|
149
|
+
CREATE INDEX IF NOT EXISTS idx_access_keys_createdBy ON cs_access_keys(createdBy);
|
|
150
|
+
CREATE INDEX IF NOT EXISTS idx_access_keys_expireAt ON cs_access_keys(expireAt);
|
|
151
|
+
CREATE INDEX IF NOT EXISTS idx_access_keys_lastUsedAt ON cs_access_keys(lastUsedAt);
|
|
152
152
|
|
|
153
|
-
CREATE TABLE IF NOT EXISTS
|
|
153
|
+
CREATE TABLE IF NOT EXISTS cs_connect_tokens (
|
|
154
154
|
token TEXT PRIMARY KEY,
|
|
155
155
|
data TEXT NOT NULL,
|
|
156
156
|
expiresAt INTEGER NOT NULL
|
|
157
157
|
);
|
|
158
158
|
|
|
159
|
-
CREATE TABLE IF NOT EXISTS
|
|
159
|
+
CREATE TABLE IF NOT EXISTS cs_kv_cache (
|
|
160
160
|
key TEXT PRIMARY KEY,
|
|
161
161
|
value TEXT NOT NULL,
|
|
162
162
|
expires_at INTEGER NOT NULL
|
|
163
163
|
);
|
|
164
164
|
`;
|
|
165
|
+
// Upgrade map (cs_ table prefix): pre-cs_ unprefixed name → cs_ name.
|
|
166
|
+
// Consumed by the runtime rename guard in migrate() (the non-assumeMigrated
|
|
167
|
+
// path), mirroring migrations/0010_rename_tables.sql for deploy-time DBs.
|
|
168
|
+
const TABLE_RENAMES = [
|
|
169
|
+
["users", "cs_users"],
|
|
170
|
+
["connected_accounts", "cs_connected_accounts"],
|
|
171
|
+
["challenges", "cs_challenges"],
|
|
172
|
+
["invitations", "cs_invitations"],
|
|
173
|
+
["audit_logs", "cs_audit_logs"],
|
|
174
|
+
["access_policies", "cs_access_policies"],
|
|
175
|
+
["security_rules", "cs_security_rules"],
|
|
176
|
+
["access_keys", "cs_access_keys"],
|
|
177
|
+
["access_key_sessions", "cs_access_key_sessions"],
|
|
178
|
+
["connect_tokens", "cs_connect_tokens"],
|
|
179
|
+
["kv_cache", "cs_kv_cache"],
|
|
180
|
+
["memberships", "cs_memberships"],
|
|
181
|
+
["settings", "cs_settings"],
|
|
182
|
+
["instance_hosts", "cs_instance_hosts"],
|
|
183
|
+
["login_tickets", "cs_login_tickets"],
|
|
184
|
+
["verify_codes", "cs_verify_codes"],
|
|
185
|
+
];
|
|
165
186
|
// Module-level flag: schema migration runs once per isolate lifetime.
|
|
166
187
|
// Safe because CREATE TABLE IF NOT EXISTS is idempotent — if the isolate
|
|
167
188
|
// is recycled the flag resets and the migration re-runs harmlessly.
|
|
@@ -247,6 +268,23 @@ export class D1Store {
|
|
|
247
268
|
schemaMigrated = true;
|
|
248
269
|
return;
|
|
249
270
|
}
|
|
271
|
+
// Upgrade guard (cs_ table prefix): rename any pre-cs_ unprefixed tables
|
|
272
|
+
// to their cs_* names BEFORE the CREATE TABLE IF NOT EXISTS batch below.
|
|
273
|
+
// Without this, CREATE IF NOT EXISTS would create a new empty cs_* table
|
|
274
|
+
// alongside the old one, silently losing all existing rows. Runtime analogue
|
|
275
|
+
// of migrations/0010_rename_tables.sql for the non-assumeMigrated path.
|
|
276
|
+
// "no such table" = fresh install / already migrated; "already … table named"
|
|
277
|
+
// = concurrent-open race — both are safe to ignore.
|
|
278
|
+
for (const [oldName, newName] of TABLE_RENAMES) {
|
|
279
|
+
try {
|
|
280
|
+
await this.db.prepare(`ALTER TABLE ${oldName} RENAME TO ${newName}`).run();
|
|
281
|
+
}
|
|
282
|
+
catch (err) {
|
|
283
|
+
const msg = String(err?.message ?? err);
|
|
284
|
+
if (!/no such table|already .*table|already exists/i.test(msg))
|
|
285
|
+
throw err;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
250
288
|
// Batch 1: core tables + indexes from SCHEMA_SQL
|
|
251
289
|
const statements = SCHEMA_SQL.split(";")
|
|
252
290
|
.map((s) => s.trim())
|
|
@@ -254,43 +292,43 @@ export class D1Store {
|
|
|
254
292
|
await this.db.batch(statements.map((sql) => this.db.prepare(sql)));
|
|
255
293
|
// ALTER TABLE — run in parallel (each is independent; failure = column already exists)
|
|
256
294
|
await Promise.allSettled([
|
|
257
|
-
this.db.prepare("ALTER TABLE
|
|
258
|
-
this.db.prepare("ALTER TABLE
|
|
259
|
-
this.db.prepare("ALTER TABLE
|
|
260
|
-
this.db.prepare("ALTER TABLE
|
|
261
|
-
this.db.prepare("ALTER TABLE
|
|
262
|
-
this.db.prepare("ALTER TABLE
|
|
263
|
-
this.db.prepare("ALTER TABLE
|
|
264
|
-
this.db.prepare("ALTER TABLE
|
|
265
|
-
this.db.prepare("ALTER TABLE
|
|
266
|
-
this.db.prepare("ALTER TABLE
|
|
267
|
-
this.db.prepare("ALTER TABLE
|
|
268
|
-
this.db.prepare("ALTER TABLE
|
|
269
|
-
this.db.prepare("ALTER TABLE
|
|
270
|
-
this.db.prepare("ALTER TABLE
|
|
295
|
+
this.db.prepare("ALTER TABLE cs_challenges ADD COLUMN invitationId TEXT").run(),
|
|
296
|
+
this.db.prepare("ALTER TABLE cs_users ADD COLUMN sourceDomain TEXT").run(),
|
|
297
|
+
this.db.prepare("ALTER TABLE cs_users ADD COLUMN lastLoginDomain TEXT").run(),
|
|
298
|
+
this.db.prepare("ALTER TABLE cs_security_rules ADD COLUMN instance_did TEXT DEFAULT NULL").run(),
|
|
299
|
+
this.db.prepare("ALTER TABLE cs_access_keys ADD COLUMN instance_did TEXT DEFAULT NULL").run(),
|
|
300
|
+
this.db.prepare("ALTER TABLE cs_audit_logs ADD COLUMN instance_did TEXT DEFAULT NULL").run(),
|
|
301
|
+
this.db.prepare("ALTER TABLE cs_access_policies ADD COLUMN instance_did TEXT DEFAULT NULL").run(),
|
|
302
|
+
this.db.prepare("ALTER TABLE cs_invitations ADD COLUMN instance_did TEXT DEFAULT NULL").run(),
|
|
303
|
+
this.db.prepare("ALTER TABLE cs_connected_accounts ADD COLUMN createdAt TEXT").run(),
|
|
304
|
+
this.db.prepare("ALTER TABLE cs_connected_accounts ADD COLUMN updatedAt TEXT").run(),
|
|
305
|
+
this.db.prepare("ALTER TABLE cs_memberships ADD COLUMN created_at TEXT").run(),
|
|
306
|
+
this.db.prepare("ALTER TABLE cs_memberships ADD COLUMN updated_at TEXT").run(),
|
|
307
|
+
this.db.prepare("ALTER TABLE cs_settings ADD COLUMN created_at TEXT").run(),
|
|
308
|
+
this.db.prepare("ALTER TABLE cs_instance_hosts ADD COLUMN updated_at TEXT").run(),
|
|
271
309
|
// Phase 3: createdBy/updatedBy audit columns
|
|
272
|
-
this.db.prepare("ALTER TABLE
|
|
273
|
-
this.db.prepare("ALTER TABLE
|
|
274
|
-
this.db.prepare("ALTER TABLE
|
|
275
|
-
this.db.prepare("ALTER TABLE
|
|
276
|
-
this.db.prepare("ALTER TABLE
|
|
277
|
-
this.db.prepare("ALTER TABLE
|
|
278
|
-
this.db.prepare("ALTER TABLE
|
|
279
|
-
this.db.prepare("ALTER TABLE
|
|
280
|
-
this.db.prepare("ALTER TABLE
|
|
281
|
-
this.db.prepare("ALTER TABLE
|
|
282
|
-
this.db.prepare("ALTER TABLE
|
|
283
|
-
this.db.prepare("ALTER TABLE
|
|
284
|
-
this.db.prepare("ALTER TABLE
|
|
285
|
-
this.db.prepare("ALTER TABLE
|
|
286
|
-
this.db.prepare("ALTER TABLE
|
|
287
|
-
this.db.prepare("ALTER TABLE
|
|
288
|
-
this.db.prepare("ALTER TABLE
|
|
310
|
+
this.db.prepare("ALTER TABLE cs_users ADD COLUMN createdBy TEXT").run(),
|
|
311
|
+
this.db.prepare("ALTER TABLE cs_users ADD COLUMN updatedBy TEXT").run(),
|
|
312
|
+
this.db.prepare("ALTER TABLE cs_connected_accounts ADD COLUMN createdBy TEXT").run(),
|
|
313
|
+
this.db.prepare("ALTER TABLE cs_connected_accounts ADD COLUMN updatedBy TEXT").run(),
|
|
314
|
+
this.db.prepare("ALTER TABLE cs_invitations ADD COLUMN createdBy TEXT").run(),
|
|
315
|
+
this.db.prepare("ALTER TABLE cs_invitations ADD COLUMN updatedBy TEXT").run(),
|
|
316
|
+
this.db.prepare("ALTER TABLE cs_access_policies ADD COLUMN createdBy TEXT").run(),
|
|
317
|
+
this.db.prepare("ALTER TABLE cs_access_policies ADD COLUMN updatedBy TEXT").run(),
|
|
318
|
+
this.db.prepare("ALTER TABLE cs_security_rules ADD COLUMN createdBy TEXT").run(),
|
|
319
|
+
this.db.prepare("ALTER TABLE cs_security_rules ADD COLUMN updatedBy TEXT").run(),
|
|
320
|
+
this.db.prepare("ALTER TABLE cs_access_keys ADD COLUMN updatedBy TEXT").run(),
|
|
321
|
+
this.db.prepare("ALTER TABLE cs_memberships ADD COLUMN created_by TEXT").run(),
|
|
322
|
+
this.db.prepare("ALTER TABLE cs_memberships ADD COLUMN updated_by TEXT").run(),
|
|
323
|
+
this.db.prepare("ALTER TABLE cs_settings ADD COLUMN created_by TEXT").run(),
|
|
324
|
+
this.db.prepare("ALTER TABLE cs_settings ADD COLUMN updated_by TEXT").run(),
|
|
325
|
+
this.db.prepare("ALTER TABLE cs_instance_hosts ADD COLUMN created_by TEXT").run(),
|
|
326
|
+
this.db.prepare("ALTER TABLE cs_instance_hosts ADD COLUMN updated_by TEXT").run(),
|
|
289
327
|
]);
|
|
290
328
|
// Batch 2: additional tables + indexes (all CREATE IF NOT EXISTS, safe in one batch)
|
|
291
329
|
await this.db.batch([
|
|
292
330
|
this.db.prepare(`
|
|
293
|
-
CREATE TABLE IF NOT EXISTS
|
|
331
|
+
CREATE TABLE IF NOT EXISTS cs_memberships (
|
|
294
332
|
user_did TEXT NOT NULL,
|
|
295
333
|
instance_did TEXT NOT NULL,
|
|
296
334
|
role TEXT NOT NULL DEFAULT 'guest',
|
|
@@ -303,8 +341,8 @@ export class D1Store {
|
|
|
303
341
|
PRIMARY KEY (user_did, instance_did)
|
|
304
342
|
)
|
|
305
343
|
`),
|
|
306
|
-
this.db.prepare(`CREATE INDEX IF NOT EXISTS idx_memberships_instance ON
|
|
307
|
-
this.db.prepare(`CREATE TABLE IF NOT EXISTS
|
|
344
|
+
this.db.prepare(`CREATE INDEX IF NOT EXISTS idx_memberships_instance ON cs_memberships(instance_did)`),
|
|
345
|
+
this.db.prepare(`CREATE TABLE IF NOT EXISTS cs_settings (
|
|
308
346
|
instance_did TEXT NOT NULL,
|
|
309
347
|
key TEXT NOT NULL,
|
|
310
348
|
value TEXT,
|
|
@@ -314,7 +352,7 @@ export class D1Store {
|
|
|
314
352
|
updated_by TEXT,
|
|
315
353
|
PRIMARY KEY (instance_did, key)
|
|
316
354
|
)`),
|
|
317
|
-
this.db.prepare(`CREATE TABLE IF NOT EXISTS
|
|
355
|
+
this.db.prepare(`CREATE TABLE IF NOT EXISTS cs_verify_codes (
|
|
318
356
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
319
357
|
code TEXT NOT NULL UNIQUE,
|
|
320
358
|
subject TEXT NOT NULL,
|
|
@@ -325,15 +363,15 @@ export class D1Store {
|
|
|
325
363
|
sent_at TEXT,
|
|
326
364
|
created_at TEXT DEFAULT (datetime('now'))
|
|
327
365
|
)`),
|
|
328
|
-
this.db.prepare("CREATE INDEX IF NOT EXISTS idx_vc_subject ON
|
|
329
|
-
this.db.prepare(`CREATE TABLE IF NOT EXISTS
|
|
366
|
+
this.db.prepare("CREATE INDEX IF NOT EXISTS idx_vc_subject ON cs_verify_codes(subject)"),
|
|
367
|
+
this.db.prepare(`CREATE TABLE IF NOT EXISTS cs_login_tickets (
|
|
330
368
|
ticket TEXT PRIMARY KEY,
|
|
331
369
|
did TEXT NOT NULL,
|
|
332
370
|
target_origin TEXT,
|
|
333
371
|
created_at TEXT DEFAULT (datetime('now')),
|
|
334
372
|
expires_at TEXT NOT NULL
|
|
335
373
|
)`),
|
|
336
|
-
this.db.prepare(`CREATE TABLE IF NOT EXISTS
|
|
374
|
+
this.db.prepare(`CREATE TABLE IF NOT EXISTS cs_access_key_sessions (
|
|
337
375
|
id TEXT PRIMARY KEY,
|
|
338
376
|
challenge TEXT NOT NULL,
|
|
339
377
|
status TEXT DEFAULT 'pending',
|
|
@@ -343,7 +381,7 @@ export class D1Store {
|
|
|
343
381
|
created_at TEXT DEFAULT (datetime('now')),
|
|
344
382
|
expires_at TEXT NOT NULL
|
|
345
383
|
)`),
|
|
346
|
-
this.db.prepare(`CREATE TABLE IF NOT EXISTS
|
|
384
|
+
this.db.prepare(`CREATE TABLE IF NOT EXISTS cs_instance_hosts (
|
|
347
385
|
host TEXT PRIMARY KEY,
|
|
348
386
|
instance_did TEXT NOT NULL,
|
|
349
387
|
created_at TEXT DEFAULT (datetime('now')),
|
|
@@ -351,7 +389,7 @@ export class D1Store {
|
|
|
351
389
|
created_by TEXT,
|
|
352
390
|
updated_by TEXT
|
|
353
391
|
)`),
|
|
354
|
-
this.db.prepare("CREATE INDEX IF NOT EXISTS idx_instance_hosts_instance ON
|
|
392
|
+
this.db.prepare("CREATE INDEX IF NOT EXISTS idx_instance_hosts_instance ON cs_instance_hosts(instance_did)"),
|
|
355
393
|
]);
|
|
356
394
|
// Seed built-in access policies + default rule (idempotent via INSERT OR IGNORE)
|
|
357
395
|
await this.ensureBuiltinPolicies();
|
|
@@ -365,13 +403,13 @@ export class D1Store {
|
|
|
365
403
|
// ─── Challenge operations ──────────────────────────────────────────────
|
|
366
404
|
async saveChallenge(id, challenge, invitationId) {
|
|
367
405
|
await this.db
|
|
368
|
-
.prepare("INSERT OR REPLACE INTO
|
|
406
|
+
.prepare("INSERT OR REPLACE INTO cs_challenges (id, challenge, invitationId) VALUES (?, ?, ?)")
|
|
369
407
|
.bind(id, challenge, invitationId ?? null)
|
|
370
408
|
.run();
|
|
371
409
|
}
|
|
372
410
|
async getChallenge(id) {
|
|
373
411
|
const row = await this.db
|
|
374
|
-
.prepare("SELECT challenge, invitationId FROM
|
|
412
|
+
.prepare("SELECT challenge, invitationId FROM cs_challenges WHERE id = ?")
|
|
375
413
|
.bind(id)
|
|
376
414
|
.first();
|
|
377
415
|
return row ?? null;
|
|
@@ -379,25 +417,25 @@ export class D1Store {
|
|
|
379
417
|
/** Find challenge by its value (not by ID). Returns id + challenge + invitationId. */
|
|
380
418
|
async getChallengeByValue(challenge) {
|
|
381
419
|
const row = await this.db
|
|
382
|
-
.prepare("SELECT id, challenge, invitationId FROM
|
|
420
|
+
.prepare("SELECT id, challenge, invitationId FROM cs_challenges WHERE challenge = ?")
|
|
383
421
|
.bind(challenge)
|
|
384
422
|
.first();
|
|
385
423
|
return row ?? null;
|
|
386
424
|
}
|
|
387
425
|
async deleteChallenge(id) {
|
|
388
|
-
await this.db.prepare("DELETE FROM
|
|
426
|
+
await this.db.prepare("DELETE FROM cs_challenges WHERE id = ?").bind(id).run();
|
|
389
427
|
}
|
|
390
428
|
async purgeExpiredChallenges() {
|
|
391
429
|
// Purge challenges older than 5 minutes
|
|
392
430
|
await this.db
|
|
393
|
-
.prepare("DELETE FROM
|
|
431
|
+
.prepare("DELETE FROM cs_challenges WHERE createdAt < datetime('now', '-5 minutes')")
|
|
394
432
|
.run();
|
|
395
433
|
}
|
|
396
434
|
async isRegistrationOpen(instanceDid) {
|
|
397
435
|
// Check instance-specific default rule first, fall back to global
|
|
398
436
|
if (instanceDid) {
|
|
399
437
|
const instanceRule = await this.db
|
|
400
|
-
.prepare("SELECT accessPolicyId FROM
|
|
438
|
+
.prepare("SELECT accessPolicyId FROM cs_security_rules WHERE id = ?")
|
|
401
439
|
.bind(`default-${instanceDid}`)
|
|
402
440
|
.first();
|
|
403
441
|
if (instanceRule) {
|
|
@@ -408,7 +446,7 @@ export class D1Store {
|
|
|
408
446
|
}
|
|
409
447
|
// Global fallback
|
|
410
448
|
const row = await this.db
|
|
411
|
-
.prepare("SELECT accessPolicyId FROM
|
|
449
|
+
.prepare("SELECT accessPolicyId FROM cs_security_rules WHERE id = 'default'")
|
|
412
450
|
.first();
|
|
413
451
|
return row?.accessPolicyId === "public";
|
|
414
452
|
}
|
|
@@ -419,34 +457,34 @@ export class D1Store {
|
|
|
419
457
|
// admin代建 passes createdBy = caller.did explicitly.
|
|
420
458
|
const actor = params.createdBy ?? params.did;
|
|
421
459
|
await this.db
|
|
422
|
-
.prepare(`INSERT INTO
|
|
460
|
+
.prepare(`INSERT INTO cs_users (did, pk, fullName, email, avatar, sourceProvider, emailVerified, firstLoginAt, lastLoginAt, lastLoginIp, sourceDomain, lastLoginDomain, createdAt, updatedAt, createdBy, updatedBy)
|
|
423
461
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
424
462
|
.bind(params.did, params.pk, params.fullName ?? null, params.email ?? null, params.avatar ?? null, params.sourceProvider, params.emailVerified ?? 0, now, now, params.ip ?? null, params.domain ?? null, params.domain ?? null, now, now, actor, actor)
|
|
425
463
|
.run();
|
|
426
464
|
}
|
|
427
465
|
async getUserByDid(did) {
|
|
428
|
-
return this.db.prepare("SELECT * FROM
|
|
466
|
+
return this.db.prepare("SELECT * FROM cs_users WHERE did = ?").bind(did).first();
|
|
429
467
|
}
|
|
430
468
|
async getUserByEmail(email) {
|
|
431
|
-
return this.db.prepare("SELECT * FROM
|
|
469
|
+
return this.db.prepare("SELECT * FROM cs_users WHERE email = ? LIMIT 1").bind(email).first();
|
|
432
470
|
}
|
|
433
471
|
async updateLastLogin(did, ip, domain) {
|
|
434
472
|
const now = new Date().toISOString();
|
|
435
473
|
await this.db
|
|
436
|
-
.prepare("UPDATE
|
|
474
|
+
.prepare("UPDATE cs_users SET lastLoginAt = ?, lastLoginIp = ?, lastLoginDomain = ?, updatedAt = ? WHERE did = ?")
|
|
437
475
|
.bind(now, ip ?? null, domain ?? null, now, did)
|
|
438
476
|
.run();
|
|
439
477
|
}
|
|
440
478
|
async incrementPasskeyCount(did) {
|
|
441
479
|
await this.db
|
|
442
|
-
.prepare("UPDATE
|
|
480
|
+
.prepare("UPDATE cs_users SET passkeyCount = passkeyCount + 1, updatedAt = ? WHERE did = ?")
|
|
443
481
|
.bind(new Date().toISOString(), did)
|
|
444
482
|
.run();
|
|
445
483
|
}
|
|
446
484
|
// ─── Team: User queries ────────────────────────────────────────────────
|
|
447
485
|
async getUserCount() {
|
|
448
486
|
const row = await this.db
|
|
449
|
-
.prepare("SELECT COUNT(*) as count FROM
|
|
487
|
+
.prepare("SELECT COUNT(*) as count FROM cs_users")
|
|
450
488
|
.first();
|
|
451
489
|
return Number(row?.count ?? 0);
|
|
452
490
|
}
|
|
@@ -487,14 +525,14 @@ export class D1Store {
|
|
|
487
525
|
const orderBy = `ORDER BY ${sortExpr} ${direction}, u.did ASC`;
|
|
488
526
|
// Batch COUNT + SELECT into one D1 roundtrip
|
|
489
527
|
const [countResult, dataResult] = await this.db.batch([
|
|
490
|
-
this.db.prepare(`SELECT COUNT(*) as count FROM
|
|
528
|
+
this.db.prepare(`SELECT COUNT(*) as count FROM cs_users u ${where}`).bind(...params),
|
|
491
529
|
this.db
|
|
492
530
|
.prepare(`SELECT u.did, u.fullName, u.email, u.avatar, u.role, u.approved,
|
|
493
531
|
COALESCE(u.createdAt, u.firstLoginAt) as createdAt,
|
|
494
532
|
u.lastLoginAt, u.passkeyCount, u.sourceDomain, u.lastLoginDomain, u.sourceProvider, u.inviter,
|
|
495
533
|
inv.fullName as inviterName
|
|
496
|
-
FROM
|
|
497
|
-
LEFT JOIN
|
|
534
|
+
FROM cs_users u
|
|
535
|
+
LEFT JOIN cs_users inv ON u.inviter = inv.did
|
|
498
536
|
${where}
|
|
499
537
|
${orderBy}
|
|
500
538
|
LIMIT ? OFFSET ?`)
|
|
@@ -508,8 +546,8 @@ export class D1Store {
|
|
|
508
546
|
const row = await this.db
|
|
509
547
|
.prepare(`SELECT u.did, u.fullName, u.email, u.avatar, u.role, u.approved, u.createdAt, u.lastLoginAt, u.passkeyCount, u.sourceDomain, u.lastLoginDomain, u.sourceProvider, u.inviter, u.emailVerified,
|
|
510
548
|
inv.fullName as inviterName
|
|
511
|
-
FROM
|
|
512
|
-
LEFT JOIN
|
|
549
|
+
FROM cs_users u
|
|
550
|
+
LEFT JOIN cs_users inv ON u.inviter = inv.did
|
|
513
551
|
WHERE u.did = ?`)
|
|
514
552
|
.bind(did)
|
|
515
553
|
.first();
|
|
@@ -517,13 +555,13 @@ export class D1Store {
|
|
|
517
555
|
}
|
|
518
556
|
async updateUserRole(did, role, actor) {
|
|
519
557
|
await this.db
|
|
520
|
-
.prepare("UPDATE
|
|
558
|
+
.prepare("UPDATE cs_users SET role = ?, updatedAt = ?, updatedBy = ? WHERE did = ?")
|
|
521
559
|
.bind(role, new Date().toISOString(), actor, did)
|
|
522
560
|
.run();
|
|
523
561
|
}
|
|
524
562
|
async updateUserApproval(did, approved, actor) {
|
|
525
563
|
await this.db
|
|
526
|
-
.prepare("UPDATE
|
|
564
|
+
.prepare("UPDATE cs_users SET approved = ?, updatedAt = ?, updatedBy = ? WHERE did = ?")
|
|
527
565
|
.bind(approved ? 1 : 0, new Date().toISOString(), actor, did)
|
|
528
566
|
.run();
|
|
529
567
|
}
|
|
@@ -554,20 +592,20 @@ export class D1Store {
|
|
|
554
592
|
params.push(actor);
|
|
555
593
|
params.push(did);
|
|
556
594
|
await this.db
|
|
557
|
-
.prepare(`UPDATE
|
|
595
|
+
.prepare(`UPDATE cs_users SET ${sets.join(", ")} WHERE did = ?`)
|
|
558
596
|
.bind(...params)
|
|
559
597
|
.run();
|
|
560
598
|
}
|
|
561
599
|
async removeUser(did) {
|
|
562
600
|
// Delete connected accounts first, then user
|
|
563
601
|
await this.db.batch([
|
|
564
|
-
this.db.prepare("DELETE FROM
|
|
565
|
-
this.db.prepare("DELETE FROM
|
|
602
|
+
this.db.prepare("DELETE FROM cs_connected_accounts WHERE userDid = ?").bind(did),
|
|
603
|
+
this.db.prepare("DELETE FROM cs_users WHERE did = ?").bind(did),
|
|
566
604
|
]);
|
|
567
605
|
}
|
|
568
606
|
async setUserInviter(did, inviterDid, actor) {
|
|
569
607
|
await this.db
|
|
570
|
-
.prepare("UPDATE
|
|
608
|
+
.prepare("UPDATE cs_users SET inviter = ?, updatedAt = ?, updatedBy = ? WHERE did = ? AND inviter IS NULL")
|
|
571
609
|
.bind(inviterDid, new Date().toISOString(), actor, did)
|
|
572
610
|
.run();
|
|
573
611
|
}
|
|
@@ -579,10 +617,10 @@ export class D1Store {
|
|
|
579
617
|
const now = new Date().toISOString();
|
|
580
618
|
await this.db.batch([
|
|
581
619
|
this.db
|
|
582
|
-
.prepare("UPDATE
|
|
620
|
+
.prepare("UPDATE cs_users SET role = 'owner', updatedAt = ?, updatedBy = ? WHERE did = ?")
|
|
583
621
|
.bind(now, actor, newOwnerDid),
|
|
584
622
|
this.db
|
|
585
|
-
.prepare("UPDATE
|
|
623
|
+
.prepare("UPDATE cs_users SET role = 'admin', updatedAt = ?, updatedBy = ? WHERE did = ?")
|
|
586
624
|
.bind(now, actor, currentOwnerDid),
|
|
587
625
|
]);
|
|
588
626
|
}
|
|
@@ -596,7 +634,7 @@ export class D1Store {
|
|
|
596
634
|
// Default actor = inviter (the invitation's creator) per plan §五A.
|
|
597
635
|
const actor = input.actor ?? input.inviterDid;
|
|
598
636
|
await this.db
|
|
599
|
-
.prepare(`INSERT INTO
|
|
637
|
+
.prepare(`INSERT INTO cs_invitations (id, teamDid, role, remark, inviterDid, expireAt, maxUses, useCount, status, instance_did, createdAt, updatedAt, createdBy, updatedBy)
|
|
600
638
|
VALUES (?, ?, ?, ?, ?, ?, ?, 0, 'active', ?, ?, ?, ?, ?)`)
|
|
601
639
|
.bind(id, input.teamDid, input.role, input.remark ?? "", input.inviterDid, expireAt, maxUses, input.instanceDid ?? null, now, now, actor, actor)
|
|
602
640
|
.run();
|
|
@@ -619,7 +657,7 @@ export class D1Store {
|
|
|
619
657
|
}
|
|
620
658
|
async getInvitation(id) {
|
|
621
659
|
return this.db
|
|
622
|
-
.prepare("SELECT * FROM
|
|
660
|
+
.prepare("SELECT * FROM cs_invitations WHERE id = ?")
|
|
623
661
|
.bind(id)
|
|
624
662
|
.first();
|
|
625
663
|
}
|
|
@@ -637,11 +675,11 @@ export class D1Store {
|
|
|
637
675
|
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
638
676
|
// Batch COUNT + SELECT into one D1 roundtrip
|
|
639
677
|
const [countResult, dataResult] = await this.db.batch([
|
|
640
|
-
this.db.prepare(`SELECT COUNT(*) as count FROM
|
|
678
|
+
this.db.prepare(`SELECT COUNT(*) as count FROM cs_invitations i ${where}`).bind(...params),
|
|
641
679
|
this.db
|
|
642
680
|
.prepare(`SELECT i.*, u.fullName as inviterName
|
|
643
|
-
FROM
|
|
644
|
-
LEFT JOIN
|
|
681
|
+
FROM cs_invitations i
|
|
682
|
+
LEFT JOIN cs_users u ON i.inviterDid = u.did
|
|
645
683
|
${where}
|
|
646
684
|
ORDER BY i.createdAt DESC
|
|
647
685
|
LIMIT ? OFFSET ?`)
|
|
@@ -656,7 +694,7 @@ export class D1Store {
|
|
|
656
694
|
*/
|
|
657
695
|
async incrementInvitationUseCount(id) {
|
|
658
696
|
const result = await this.db
|
|
659
|
-
.prepare(`UPDATE
|
|
697
|
+
.prepare(`UPDATE cs_invitations SET useCount = useCount + 1, updatedAt = ?
|
|
660
698
|
WHERE id = ? AND useCount < maxUses AND status = 'active'`)
|
|
661
699
|
.bind(new Date().toISOString(), id)
|
|
662
700
|
.run();
|
|
@@ -664,23 +702,23 @@ export class D1Store {
|
|
|
664
702
|
}
|
|
665
703
|
async updateInvitationStatus(id, status, actor) {
|
|
666
704
|
await this.db
|
|
667
|
-
.prepare("UPDATE
|
|
705
|
+
.prepare("UPDATE cs_invitations SET status = ?, updatedAt = ?, updatedBy = ? WHERE id = ?")
|
|
668
706
|
.bind(status, new Date().toISOString(), actor, id)
|
|
669
707
|
.run();
|
|
670
708
|
}
|
|
671
709
|
async deleteInvitation(id) {
|
|
672
|
-
await this.db.prepare("DELETE FROM
|
|
710
|
+
await this.db.prepare("DELETE FROM cs_invitations WHERE id = ?").bind(id).run();
|
|
673
711
|
}
|
|
674
712
|
async purgeExpiredInvitations() {
|
|
675
713
|
await this.db
|
|
676
|
-
.prepare("UPDATE
|
|
714
|
+
.prepare("UPDATE cs_invitations SET status = 'expired', updatedAt = ? WHERE status = 'active' AND expireAt < datetime('now')")
|
|
677
715
|
.bind(new Date().toISOString())
|
|
678
716
|
.run();
|
|
679
717
|
}
|
|
680
718
|
// ─── Team: Audit logs ─────────────────────────────────────────────────
|
|
681
719
|
async createAuditLog(input) {
|
|
682
720
|
await this.db
|
|
683
|
-
.prepare(`INSERT INTO
|
|
721
|
+
.prepare(`INSERT INTO cs_audit_logs (action, operatorDid, targetDid, metadata, ip, instance_did, createdAt)
|
|
684
722
|
VALUES (?, ?, ?, ?, ?, ?, ?)`)
|
|
685
723
|
.bind(input.action, input.operatorDid, input.targetDid ?? null, JSON.stringify(input.metadata ?? {}), input.ip ?? null, input.instanceDid ?? null, new Date().toISOString())
|
|
686
724
|
.run();
|
|
@@ -731,12 +769,12 @@ export class D1Store {
|
|
|
731
769
|
const offset = (opts.page - 1) * opts.pageSize;
|
|
732
770
|
// Batch COUNT + SELECT into one D1 roundtrip
|
|
733
771
|
const [countResult, dataResult] = await this.db.batch([
|
|
734
|
-
this.db.prepare(`SELECT COUNT(*) as count FROM
|
|
772
|
+
this.db.prepare(`SELECT COUNT(*) as count FROM cs_audit_logs a ${where}`).bind(...params),
|
|
735
773
|
this.db
|
|
736
774
|
.prepare(`SELECT a.*, op.fullName as operatorName, op.role as operatorRole, tgt.fullName as targetName
|
|
737
|
-
FROM
|
|
738
|
-
LEFT JOIN
|
|
739
|
-
LEFT JOIN
|
|
775
|
+
FROM cs_audit_logs a
|
|
776
|
+
LEFT JOIN cs_users op ON a.operatorDid = op.did
|
|
777
|
+
LEFT JOIN cs_users tgt ON a.targetDid = tgt.did
|
|
740
778
|
${where}
|
|
741
779
|
ORDER BY a.createdAt DESC
|
|
742
780
|
LIMIT ? OFFSET ?`)
|
|
@@ -749,9 +787,9 @@ export class D1Store {
|
|
|
749
787
|
async getAuditLogById(id, instanceDid) {
|
|
750
788
|
return this.db
|
|
751
789
|
.prepare(`SELECT a.*, op.fullName as operatorName, op.role as operatorRole, tgt.fullName as targetName
|
|
752
|
-
FROM
|
|
753
|
-
LEFT JOIN
|
|
754
|
-
LEFT JOIN
|
|
790
|
+
FROM cs_audit_logs a
|
|
791
|
+
LEFT JOIN cs_users op ON a.operatorDid = op.did
|
|
792
|
+
LEFT JOIN cs_users tgt ON a.targetDid = tgt.did
|
|
755
793
|
WHERE a.id = ? AND a.instance_did = ?`)
|
|
756
794
|
.bind(id, instanceDid)
|
|
757
795
|
.first();
|
|
@@ -762,7 +800,7 @@ export class D1Store {
|
|
|
762
800
|
// Self-serve account link: default actor = the user's own DID (plan §二).
|
|
763
801
|
const actor = params.actor ?? params.userDid;
|
|
764
802
|
await this.db
|
|
765
|
-
.prepare(`INSERT INTO
|
|
803
|
+
.prepare(`INSERT INTO cs_connected_accounts (did, pk, userDid, provider, id, extra, userInfo, firstLoginAt, lastLoginAt, lastLoginIp, createdAt, updatedAt, createdBy, updatedBy)
|
|
766
804
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
767
805
|
.bind(params.did, params.pk, params.userDid, params.provider, params.id, params.extra, params.userInfo, now, now, params.ip ?? null, now, now, actor, actor)
|
|
768
806
|
.run();
|
|
@@ -775,49 +813,49 @@ export class D1Store {
|
|
|
775
813
|
.prepare(
|
|
776
814
|
// Bind all timestamps as ISO `?` params (consistent with createConnectedAccount;
|
|
777
815
|
// avoids mixing `datetime('now')` literals with `?` placeholders).
|
|
778
|
-
`INSERT INTO
|
|
816
|
+
`INSERT INTO cs_connected_accounts (did, pk, userDid, provider, id, userInfo, firstLoginAt, lastLoginAt, createdAt, updatedAt, createdBy, updatedBy)
|
|
779
817
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
780
818
|
ON CONFLICT (did) DO UPDATE SET
|
|
781
819
|
pk = excluded.pk, lastLoginAt = excluded.lastLoginAt, updatedAt = excluded.updatedAt,
|
|
782
|
-
userInfo = COALESCE(excluded.userInfo,
|
|
820
|
+
userInfo = COALESCE(excluded.userInfo, cs_connected_accounts.userInfo)`)
|
|
783
821
|
.bind(account.did, account.pk, account.userDid, account.provider, account.id, account.userInfo || null, now, now, now, now, actor, actor)
|
|
784
822
|
.run();
|
|
785
823
|
}
|
|
786
824
|
async getConnectedAccountById(credentialId) {
|
|
787
825
|
return this.db
|
|
788
|
-
.prepare("SELECT * FROM
|
|
826
|
+
.prepare("SELECT * FROM cs_connected_accounts WHERE id = ?")
|
|
789
827
|
.bind(credentialId)
|
|
790
828
|
.first();
|
|
791
829
|
}
|
|
792
830
|
async getConnectedAccountByDid(did) {
|
|
793
831
|
return this.db
|
|
794
|
-
.prepare("SELECT * FROM
|
|
832
|
+
.prepare("SELECT * FROM cs_connected_accounts WHERE did = ?")
|
|
795
833
|
.bind(did)
|
|
796
834
|
.first();
|
|
797
835
|
}
|
|
798
836
|
async updateCounter(did, counter) {
|
|
799
837
|
const now = new Date().toISOString();
|
|
800
838
|
await this.db
|
|
801
|
-
.prepare("UPDATE
|
|
839
|
+
.prepare("UPDATE cs_connected_accounts SET counter = ?, lastLoginAt = ?, updatedAt = ? WHERE did = ?")
|
|
802
840
|
.bind(counter, now, now, did)
|
|
803
841
|
.run();
|
|
804
842
|
}
|
|
805
843
|
async getConnectedAccountsByUserDid(userDid) {
|
|
806
844
|
const rows = await this.db
|
|
807
|
-
.prepare("SELECT * FROM
|
|
845
|
+
.prepare("SELECT * FROM cs_connected_accounts WHERE userDid = ?")
|
|
808
846
|
.bind(userDid)
|
|
809
847
|
.all();
|
|
810
848
|
return rows.results ?? [];
|
|
811
849
|
}
|
|
812
850
|
async getConnectedAccountByProviderAndUser(provider, userDid) {
|
|
813
851
|
return this.db
|
|
814
|
-
.prepare("SELECT * FROM
|
|
852
|
+
.prepare("SELECT * FROM cs_connected_accounts WHERE provider = ? AND userDid = ?")
|
|
815
853
|
.bind(provider, userDid)
|
|
816
854
|
.first();
|
|
817
855
|
}
|
|
818
856
|
async getConnectedAccountsByProviderAndUser(provider, userDid) {
|
|
819
857
|
const rows = await this.db
|
|
820
|
-
.prepare("SELECT * FROM
|
|
858
|
+
.prepare("SELECT * FROM cs_connected_accounts WHERE provider = ? AND userDid = ?")
|
|
821
859
|
.bind(provider, userDid)
|
|
822
860
|
.all();
|
|
823
861
|
return rows.results ?? [];
|
|
@@ -826,33 +864,33 @@ export class D1Store {
|
|
|
826
864
|
// Single query: direct DID match OR indirect via connected_accounts.
|
|
827
865
|
// UNION ALL + LIMIT 1 ensures direct match is preferred.
|
|
828
866
|
return this.db
|
|
829
|
-
.prepare(`SELECT u.* FROM
|
|
867
|
+
.prepare(`SELECT u.* FROM cs_users u WHERE u.did = ?
|
|
830
868
|
UNION ALL
|
|
831
|
-
SELECT u.* FROM
|
|
869
|
+
SELECT u.* FROM cs_connected_accounts ca JOIN cs_users u ON ca.userDid = u.did WHERE ca.did = ?
|
|
832
870
|
LIMIT 1`)
|
|
833
871
|
.bind(did, did)
|
|
834
872
|
.first();
|
|
835
873
|
}
|
|
836
874
|
async decrementPasskeyCount(did) {
|
|
837
875
|
await this.db
|
|
838
|
-
.prepare("UPDATE
|
|
876
|
+
.prepare("UPDATE cs_users SET passkeyCount = MAX(passkeyCount - 1, 0), updatedAt = ? WHERE did = ?")
|
|
839
877
|
.bind(new Date().toISOString(), did)
|
|
840
878
|
.run();
|
|
841
879
|
}
|
|
842
880
|
async updateConnectedAccountName(did, name, actor) {
|
|
843
881
|
await this.db
|
|
844
|
-
.prepare("UPDATE
|
|
882
|
+
.prepare("UPDATE cs_connected_accounts SET userInfo = ?, updatedAt = ?, updatedBy = ? WHERE did = ?")
|
|
845
883
|
.bind(JSON.stringify({ name }), new Date().toISOString(), actor, did)
|
|
846
884
|
.run();
|
|
847
885
|
}
|
|
848
886
|
async deleteConnectedAccount(did) {
|
|
849
|
-
await this.db.prepare("DELETE FROM
|
|
887
|
+
await this.db.prepare("DELETE FROM cs_connected_accounts WHERE did = ?").bind(did).run();
|
|
850
888
|
}
|
|
851
889
|
// ─── Access keys ────────────────────────────────────────────────────────
|
|
852
890
|
async createAccessKey(input) {
|
|
853
891
|
const now = new Date().toISOString();
|
|
854
892
|
await this.db
|
|
855
|
-
.prepare(`INSERT INTO
|
|
893
|
+
.prepare(`INSERT INTO cs_access_keys (accessKeyId, accessKeyPublic, role, remark, createdBy, expireAt, instance_did, createdAt, updatedAt, updatedBy)
|
|
856
894
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
857
895
|
.bind(input.accessKeyId, input.accessKeyPublic, input.role, input.remark ?? "", input.createdBy, input.expireAt ?? null, input.instanceDid ?? null, now, now, input.createdBy)
|
|
858
896
|
.run();
|
|
@@ -873,8 +911,8 @@ export class D1Store {
|
|
|
873
911
|
async getAccessKeyById(accessKeyId) {
|
|
874
912
|
const row = await this.db
|
|
875
913
|
.prepare(`SELECT k.*, u.fullName as createdByName
|
|
876
|
-
FROM
|
|
877
|
-
LEFT JOIN
|
|
914
|
+
FROM cs_access_keys k
|
|
915
|
+
LEFT JOIN cs_users u ON k.createdBy = u.did
|
|
878
916
|
WHERE k.accessKeyId = ?`)
|
|
879
917
|
.bind(accessKeyId)
|
|
880
918
|
.first();
|
|
@@ -906,11 +944,11 @@ export class D1Store {
|
|
|
906
944
|
const offset = (opts.page - 1) * opts.pageSize;
|
|
907
945
|
// Batch COUNT + SELECT into one D1 roundtrip
|
|
908
946
|
const [countResult, dataResult] = await this.db.batch([
|
|
909
|
-
this.db.prepare(`SELECT COUNT(*) as count FROM
|
|
947
|
+
this.db.prepare(`SELECT COUNT(*) as count FROM cs_access_keys k ${where}`).bind(...params),
|
|
910
948
|
this.db
|
|
911
949
|
.prepare(`SELECT k.*, u.fullName as createdByName
|
|
912
|
-
FROM
|
|
913
|
-
LEFT JOIN
|
|
950
|
+
FROM cs_access_keys k
|
|
951
|
+
LEFT JOIN cs_users u ON k.createdBy = u.did
|
|
914
952
|
${where}
|
|
915
953
|
ORDER BY k.createdAt DESC
|
|
916
954
|
LIMIT ? OFFSET ?`)
|
|
@@ -948,18 +986,18 @@ export class D1Store {
|
|
|
948
986
|
params.push(actor);
|
|
949
987
|
params.push(accessKeyId);
|
|
950
988
|
await this.db
|
|
951
|
-
.prepare(`UPDATE
|
|
989
|
+
.prepare(`UPDATE cs_access_keys SET ${sets.join(", ")} WHERE accessKeyId = ?`)
|
|
952
990
|
.bind(...params)
|
|
953
991
|
.run();
|
|
954
992
|
}
|
|
955
993
|
return this.getAccessKeyById(accessKeyId);
|
|
956
994
|
}
|
|
957
995
|
async deleteAccessKey(accessKeyId) {
|
|
958
|
-
await this.db.prepare("DELETE FROM
|
|
996
|
+
await this.db.prepare("DELETE FROM cs_access_keys WHERE accessKeyId = ?").bind(accessKeyId).run();
|
|
959
997
|
}
|
|
960
998
|
async refreshAccessKeyLastUsed(accessKeyId) {
|
|
961
999
|
await this.db
|
|
962
|
-
.prepare("UPDATE
|
|
1000
|
+
.prepare("UPDATE cs_access_keys SET lastUsedAt = ? WHERE accessKeyId = ?")
|
|
963
1001
|
.bind(new Date().toISOString(), accessKeyId)
|
|
964
1002
|
.run();
|
|
965
1003
|
}
|
|
@@ -997,7 +1035,7 @@ export class D1Store {
|
|
|
997
1035
|
];
|
|
998
1036
|
const now = new Date().toISOString();
|
|
999
1037
|
await this.db.batch(policies.map((p) => this.db
|
|
1000
|
-
.prepare(`INSERT OR IGNORE INTO
|
|
1038
|
+
.prepare(`INSERT OR IGNORE INTO cs_access_policies (id, name, description, roles, reverse, isProtected, createdAt, updatedAt, createdBy, updatedBy)
|
|
1001
1039
|
VALUES (?, ?, ?, ?, ?, 1, ?, ?, 'system', 'system')`)
|
|
1002
1040
|
.bind(p.id, p.name, p.description, p.roles, p.reverse, now, now)));
|
|
1003
1041
|
invalidateRulesCache();
|
|
@@ -1005,7 +1043,7 @@ export class D1Store {
|
|
|
1005
1043
|
async ensureDefaultRule() {
|
|
1006
1044
|
const now = new Date().toISOString();
|
|
1007
1045
|
await this.db
|
|
1008
|
-
.prepare(`INSERT OR IGNORE INTO
|
|
1046
|
+
.prepare(`INSERT OR IGNORE INTO cs_security_rules (id, pathPattern, priority, accessPolicyId, enabled, remark, createdAt, updatedAt, createdBy, updatedBy)
|
|
1009
1047
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'system', 'system')`)
|
|
1010
1048
|
.bind("default", "*", -1, "public", 1, "Default fallback rule", now, now)
|
|
1011
1049
|
.run();
|
|
@@ -1013,7 +1051,7 @@ export class D1Store {
|
|
|
1013
1051
|
}
|
|
1014
1052
|
// ─── Access policies: CRUD ─────────────────────────────────────────────
|
|
1015
1053
|
async getAccessPolicies(instanceDid) {
|
|
1016
|
-
let sql = "SELECT * FROM
|
|
1054
|
+
let sql = "SELECT * FROM cs_access_policies";
|
|
1017
1055
|
const params = [];
|
|
1018
1056
|
if (instanceDid !== undefined) {
|
|
1019
1057
|
sql += " WHERE instance_did = ?";
|
|
@@ -1032,7 +1070,7 @@ export class D1Store {
|
|
|
1032
1070
|
return [];
|
|
1033
1071
|
// Batch-fetch all rule counts in one D1 roundtrip (instead of N+1 individual queries)
|
|
1034
1072
|
const countResults = await this.db.batch(policies.map((p) => this.db
|
|
1035
|
-
.prepare("SELECT COUNT(*) as count FROM
|
|
1073
|
+
.prepare("SELECT COUNT(*) as count FROM cs_security_rules WHERE accessPolicyId = ?")
|
|
1036
1074
|
.bind(p.id)));
|
|
1037
1075
|
return policies.map((p, i) => {
|
|
1038
1076
|
const ruleCount = countResults[i]?.results?.[0]?.count ?? 0;
|
|
@@ -1055,9 +1093,9 @@ export class D1Store {
|
|
|
1055
1093
|
async getAccessPolicy(id) {
|
|
1056
1094
|
// Batch policy + rule count into one D1 roundtrip
|
|
1057
1095
|
const [policyResult, countResult] = await this.db.batch([
|
|
1058
|
-
this.db.prepare("SELECT * FROM
|
|
1096
|
+
this.db.prepare("SELECT * FROM cs_access_policies WHERE id = ?").bind(id),
|
|
1059
1097
|
this.db
|
|
1060
|
-
.prepare("SELECT COUNT(*) as count FROM
|
|
1098
|
+
.prepare("SELECT COUNT(*) as count FROM cs_security_rules WHERE accessPolicyId = ?")
|
|
1061
1099
|
.bind(id),
|
|
1062
1100
|
]);
|
|
1063
1101
|
const p = policyResult.results?.[0];
|
|
@@ -1084,7 +1122,7 @@ export class D1Store {
|
|
|
1084
1122
|
const now = new Date().toISOString();
|
|
1085
1123
|
const { roles: dbRoles, reverse } = await import("../access/access-policy.js").then((m) => m.accessTypeToDb(input.accessType, input.roles));
|
|
1086
1124
|
await this.db
|
|
1087
|
-
.prepare(`INSERT INTO
|
|
1125
|
+
.prepare(`INSERT INTO cs_access_policies (id, name, description, roles, reverse, isProtected, instance_did, createdAt, updatedAt, createdBy, updatedBy)
|
|
1088
1126
|
VALUES (?, ?, ?, ?, ?, 0, ?, ?, ?, ?, ?)`)
|
|
1089
1127
|
.bind(id, input.name, input.description ?? "", dbRoles, reverse, input.instanceDid ?? null, now, now, actor, actor)
|
|
1090
1128
|
.run();
|
|
@@ -1117,7 +1155,7 @@ export class D1Store {
|
|
|
1117
1155
|
params.push(actor);
|
|
1118
1156
|
params.push(id);
|
|
1119
1157
|
await this.db
|
|
1120
|
-
.prepare(`UPDATE
|
|
1158
|
+
.prepare(`UPDATE cs_access_policies SET ${sets.join(", ")} WHERE id = ?`)
|
|
1121
1159
|
.bind(...params)
|
|
1122
1160
|
.run();
|
|
1123
1161
|
}
|
|
@@ -1125,12 +1163,12 @@ export class D1Store {
|
|
|
1125
1163
|
return (await this.getAccessPolicy(id));
|
|
1126
1164
|
}
|
|
1127
1165
|
async deleteAccessPolicy(id) {
|
|
1128
|
-
await this.db.prepare("DELETE FROM
|
|
1166
|
+
await this.db.prepare("DELETE FROM cs_access_policies WHERE id = ?").bind(id).run();
|
|
1129
1167
|
invalidateRulesCache();
|
|
1130
1168
|
}
|
|
1131
1169
|
async getAccessPolicyRuleCount(id) {
|
|
1132
1170
|
const row = await this.db
|
|
1133
|
-
.prepare("SELECT COUNT(*) as count FROM
|
|
1171
|
+
.prepare("SELECT COUNT(*) as count FROM cs_security_rules WHERE accessPolicyId = ?")
|
|
1134
1172
|
.bind(id)
|
|
1135
1173
|
.first();
|
|
1136
1174
|
return Number(row?.count ?? 0);
|
|
@@ -1138,8 +1176,8 @@ export class D1Store {
|
|
|
1138
1176
|
// ─── Security rules: CRUD ─────────────────────────────────────────────
|
|
1139
1177
|
async getSecurityRules(instanceDid) {
|
|
1140
1178
|
let sql = `SELECT r.*, p.name as accessPolicyName
|
|
1141
|
-
FROM
|
|
1142
|
-
LEFT JOIN
|
|
1179
|
+
FROM cs_security_rules r
|
|
1180
|
+
LEFT JOIN cs_access_policies p ON r.accessPolicyId = p.id`;
|
|
1143
1181
|
const params = [];
|
|
1144
1182
|
if (instanceDid !== undefined) {
|
|
1145
1183
|
sql += ` WHERE r.instance_did = ?`;
|
|
@@ -1169,8 +1207,8 @@ export class D1Store {
|
|
|
1169
1207
|
async getSecurityRule(id) {
|
|
1170
1208
|
const r = await this.db
|
|
1171
1209
|
.prepare(`SELECT r.*, p.name as accessPolicyName
|
|
1172
|
-
FROM
|
|
1173
|
-
LEFT JOIN
|
|
1210
|
+
FROM cs_security_rules r
|
|
1211
|
+
LEFT JOIN cs_access_policies p ON r.accessPolicyId = p.id
|
|
1174
1212
|
WHERE r.id = ?`)
|
|
1175
1213
|
.bind(id)
|
|
1176
1214
|
.first();
|
|
@@ -1193,7 +1231,7 @@ export class D1Store {
|
|
|
1193
1231
|
const id = crypto.randomUUID();
|
|
1194
1232
|
const now = new Date().toISOString();
|
|
1195
1233
|
await this.db
|
|
1196
|
-
.prepare(`INSERT INTO
|
|
1234
|
+
.prepare(`INSERT INTO cs_security_rules (id, pathPattern, priority, accessPolicyId, enabled, remark, instance_did, createdAt, updatedAt, createdBy, updatedBy)
|
|
1197
1235
|
VALUES (?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?)`)
|
|
1198
1236
|
.bind(id, input.pathPattern, input.priority ?? 0, input.accessPolicyId, input.remark ?? "", input.instanceDid ?? null, now, now, actor, actor)
|
|
1199
1237
|
.run();
|
|
@@ -1231,7 +1269,7 @@ export class D1Store {
|
|
|
1231
1269
|
params.push(actor);
|
|
1232
1270
|
params.push(id);
|
|
1233
1271
|
await this.db
|
|
1234
|
-
.prepare(`UPDATE
|
|
1272
|
+
.prepare(`UPDATE cs_security_rules SET ${sets.join(", ")} WHERE id = ?`)
|
|
1235
1273
|
.bind(...params)
|
|
1236
1274
|
.run();
|
|
1237
1275
|
}
|
|
@@ -1239,14 +1277,14 @@ export class D1Store {
|
|
|
1239
1277
|
return (await this.getSecurityRule(id));
|
|
1240
1278
|
}
|
|
1241
1279
|
async deleteSecurityRule(id) {
|
|
1242
|
-
await this.db.prepare("DELETE FROM
|
|
1280
|
+
await this.db.prepare("DELETE FROM cs_security_rules WHERE id = ?").bind(id).run();
|
|
1243
1281
|
invalidateRulesCache();
|
|
1244
1282
|
}
|
|
1245
1283
|
// ─── Membership operations ──────────────────────────────────────────────
|
|
1246
1284
|
async createMembership(userDid, instanceDid, role, invitedBy, actor) {
|
|
1247
1285
|
const now = new Date().toISOString();
|
|
1248
1286
|
await this.db
|
|
1249
|
-
.prepare(`INSERT OR IGNORE INTO
|
|
1287
|
+
.prepare(`INSERT OR IGNORE INTO cs_memberships (user_did, instance_did, role, invited_by, created_at, updated_at, created_by, updated_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
1250
1288
|
.bind(userDid, instanceDid, role, invitedBy ?? null, now, now, actor, actor)
|
|
1251
1289
|
.run();
|
|
1252
1290
|
invalidateMembership(userDid, instanceDid);
|
|
@@ -1258,7 +1296,7 @@ export class D1Store {
|
|
|
1258
1296
|
return cached.result;
|
|
1259
1297
|
}
|
|
1260
1298
|
const result = await this.db
|
|
1261
|
-
.prepare("SELECT * FROM
|
|
1299
|
+
.prepare("SELECT * FROM cs_memberships WHERE user_did = ? AND instance_did = ?")
|
|
1262
1300
|
.bind(userDid, instanceDid)
|
|
1263
1301
|
.first();
|
|
1264
1302
|
_membershipCache.set(cacheKey, { result: result ?? null, at: Date.now() });
|
|
@@ -1267,14 +1305,14 @@ export class D1Store {
|
|
|
1267
1305
|
/** Get all instance DIDs where user has owner role (single query). */
|
|
1268
1306
|
async getOwnerInstanceDids(userDid) {
|
|
1269
1307
|
const { results } = await this.db
|
|
1270
|
-
.prepare("SELECT instance_did FROM
|
|
1308
|
+
.prepare("SELECT instance_did FROM cs_memberships WHERE user_did = ? AND role = 'owner'")
|
|
1271
1309
|
.bind(userDid)
|
|
1272
1310
|
.all();
|
|
1273
1311
|
return new Set((results ?? []).map((r) => r.instance_did));
|
|
1274
1312
|
}
|
|
1275
1313
|
async listMemberships(instanceDid) {
|
|
1276
1314
|
const rows = await this.db
|
|
1277
|
-
.prepare("SELECT * FROM
|
|
1315
|
+
.prepare("SELECT * FROM cs_memberships WHERE instance_did = ? ORDER BY joined_at ASC")
|
|
1278
1316
|
.bind(instanceDid)
|
|
1279
1317
|
.all();
|
|
1280
1318
|
return rows.results ?? [];
|
|
@@ -1284,8 +1322,8 @@ export class D1Store {
|
|
|
1284
1322
|
.prepare(`SELECT m.user_did, m.instance_did, m.role, m.invited_by, m.joined_at,
|
|
1285
1323
|
u.fullName, u.email, u.avatar, COALESCE(u.approved, 1) as approved,
|
|
1286
1324
|
u.sourceProvider, u.sourceDomain, u.lastLoginDomain, u.createdAt
|
|
1287
|
-
FROM
|
|
1288
|
-
LEFT JOIN
|
|
1325
|
+
FROM cs_memberships m
|
|
1326
|
+
LEFT JOIN cs_users u ON m.user_did = u.did
|
|
1289
1327
|
WHERE m.instance_did = ?
|
|
1290
1328
|
ORDER BY
|
|
1291
1329
|
CASE m.role WHEN 'owner' THEN 0 WHEN 'admin' THEN 1 WHEN 'member' THEN 2 ELSE 3 END,
|
|
@@ -1298,8 +1336,8 @@ export class D1Store {
|
|
|
1298
1336
|
const rows = await this.db
|
|
1299
1337
|
.prepare(`SELECT m.user_did, m.instance_did, m.role, m.joined_at,
|
|
1300
1338
|
u.fullName, u.email, u.sourceProvider, COALESCE(u.approved, 1) as approved
|
|
1301
|
-
FROM
|
|
1302
|
-
LEFT JOIN
|
|
1339
|
+
FROM cs_memberships m
|
|
1340
|
+
LEFT JOIN cs_users u ON m.user_did = u.did
|
|
1303
1341
|
ORDER BY m.instance_did, m.role, m.joined_at ASC`)
|
|
1304
1342
|
.all();
|
|
1305
1343
|
return rows.results ?? [];
|
|
@@ -1314,8 +1352,8 @@ export class D1Store {
|
|
|
1314
1352
|
CASE MIN(CASE m.role WHEN 'owner' THEN 0 WHEN 'admin' THEN 1 WHEN 'member' THEN 2 ELSE 3 END)
|
|
1315
1353
|
WHEN 0 THEN 'owner' WHEN 1 THEN 'admin' WHEN 2 THEN 'member' ELSE 'guest' END as role,
|
|
1316
1354
|
json_group_array(json_object('instance_did', m.instance_did, 'role', m.role, 'joined_at', m.joined_at)) as instances_json
|
|
1317
|
-
FROM
|
|
1318
|
-
LEFT JOIN
|
|
1355
|
+
FROM cs_memberships m
|
|
1356
|
+
LEFT JOIN cs_users u ON m.user_did = u.did
|
|
1319
1357
|
GROUP BY m.user_did
|
|
1320
1358
|
ORDER BY MIN(CASE m.role WHEN 'owner' THEN 0 WHEN 'admin' THEN 1 WHEN 'member' THEN 2 ELSE 3 END) ASC,
|
|
1321
1359
|
MIN(m.joined_at) ASC`)
|
|
@@ -1324,26 +1362,26 @@ export class D1Store {
|
|
|
1324
1362
|
}
|
|
1325
1363
|
async updateMembershipRole(userDid, instanceDid, role, actor) {
|
|
1326
1364
|
await this.db
|
|
1327
|
-
.prepare("UPDATE
|
|
1365
|
+
.prepare("UPDATE cs_memberships SET role = ?, updated_at = ?, updated_by = ? WHERE user_did = ? AND instance_did = ?")
|
|
1328
1366
|
.bind(role, new Date().toISOString(), actor, userDid, instanceDid)
|
|
1329
1367
|
.run();
|
|
1330
1368
|
invalidateMembership(userDid, instanceDid);
|
|
1331
1369
|
}
|
|
1332
1370
|
async deleteMembership(userDid, instanceDid) {
|
|
1333
1371
|
await this.db
|
|
1334
|
-
.prepare("DELETE FROM
|
|
1372
|
+
.prepare("DELETE FROM cs_memberships WHERE user_did = ? AND instance_did = ?")
|
|
1335
1373
|
.bind(userDid, instanceDid)
|
|
1336
1374
|
.run();
|
|
1337
1375
|
invalidateMembership(userDid, instanceDid);
|
|
1338
1376
|
}
|
|
1339
1377
|
async deleteMembershipsByInstance(instanceDid) {
|
|
1340
|
-
await this.db.prepare("DELETE FROM
|
|
1378
|
+
await this.db.prepare("DELETE FROM cs_memberships WHERE instance_did = ?").bind(instanceDid).run();
|
|
1341
1379
|
invalidateMembershipsByInstance(instanceDid);
|
|
1342
1380
|
}
|
|
1343
1381
|
// ─── Settings CRUD ─────────────────────────────────────────────────────
|
|
1344
1382
|
async getSetting(instanceDid, key) {
|
|
1345
1383
|
const row = await this.db
|
|
1346
|
-
.prepare("SELECT value FROM
|
|
1384
|
+
.prepare("SELECT value FROM cs_settings WHERE instance_did = ? AND key = ?")
|
|
1347
1385
|
.bind(instanceDid, key)
|
|
1348
1386
|
.first();
|
|
1349
1387
|
return row?.value ?? null;
|
|
@@ -1351,7 +1389,7 @@ export class D1Store {
|
|
|
1351
1389
|
async setSetting(instanceDid, key, value, actor) {
|
|
1352
1390
|
try {
|
|
1353
1391
|
await this.db
|
|
1354
|
-
.prepare(`INSERT INTO
|
|
1392
|
+
.prepare(`INSERT INTO cs_settings (instance_did, key, value, updated_at, created_at, created_by, updated_by)
|
|
1355
1393
|
VALUES (?, ?, ?, datetime('now'), datetime('now'), ?, ?)
|
|
1356
1394
|
ON CONFLICT(instance_did, key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at, updated_by = excluded.updated_by`)
|
|
1357
1395
|
.bind(instanceDid, key, value, actor, actor)
|
|
@@ -1362,7 +1400,7 @@ export class D1Store {
|
|
|
1362
1400
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1363
1401
|
if (msg.includes("UNIQUE constraint")) {
|
|
1364
1402
|
await this.db
|
|
1365
|
-
.prepare(`UPDATE
|
|
1403
|
+
.prepare(`UPDATE cs_settings SET value = ?, updated_at = datetime('now'), updated_by = ? WHERE instance_did = ? AND key = ?`)
|
|
1366
1404
|
.bind(value, actor, instanceDid, key)
|
|
1367
1405
|
.run();
|
|
1368
1406
|
}
|
|
@@ -1373,14 +1411,14 @@ export class D1Store {
|
|
|
1373
1411
|
}
|
|
1374
1412
|
async listSettings(instanceDid) {
|
|
1375
1413
|
const rows = await this.db
|
|
1376
|
-
.prepare("SELECT key, value, updated_at FROM
|
|
1414
|
+
.prepare("SELECT key, value, updated_at FROM cs_settings WHERE instance_did = ? ORDER BY key")
|
|
1377
1415
|
.bind(instanceDid)
|
|
1378
1416
|
.all();
|
|
1379
1417
|
return rows.results ?? [];
|
|
1380
1418
|
}
|
|
1381
1419
|
async deleteSetting(instanceDid, key) {
|
|
1382
1420
|
await this.db
|
|
1383
|
-
.prepare("DELETE FROM
|
|
1421
|
+
.prepare("DELETE FROM cs_settings WHERE instance_did = ? AND key = ?")
|
|
1384
1422
|
.bind(instanceDid, key)
|
|
1385
1423
|
.run();
|
|
1386
1424
|
}
|
|
@@ -1388,13 +1426,13 @@ export class D1Store {
|
|
|
1388
1426
|
async batchDeleteSettings(entries) {
|
|
1389
1427
|
if (entries.length === 0)
|
|
1390
1428
|
return;
|
|
1391
|
-
const stmts = entries.map(({ instanceDid, key }) => this.db.prepare("DELETE FROM
|
|
1429
|
+
const stmts = entries.map(({ instanceDid, key }) => this.db.prepare("DELETE FROM cs_settings WHERE instance_did = ? AND key = ?").bind(instanceDid, key));
|
|
1392
1430
|
await this.db.batch(stmts);
|
|
1393
1431
|
}
|
|
1394
1432
|
async listSettingsByPrefix(instanceDid, keyPrefix) {
|
|
1395
1433
|
await this.ensureSchema();
|
|
1396
1434
|
const rows = await this.db
|
|
1397
|
-
.prepare("SELECT key, value, updated_at FROM
|
|
1435
|
+
.prepare("SELECT key, value, updated_at FROM cs_settings WHERE instance_did = ? AND key LIKE ? ORDER BY key")
|
|
1398
1436
|
.bind(instanceDid, `${keyPrefix}%`)
|
|
1399
1437
|
.all();
|
|
1400
1438
|
return rows.results ?? [];
|
|
@@ -1403,7 +1441,7 @@ export class D1Store {
|
|
|
1403
1441
|
async findSettingByKey(key) {
|
|
1404
1442
|
await this.ensureSchema();
|
|
1405
1443
|
const rows = await this.db
|
|
1406
|
-
.prepare("SELECT instance_did, value FROM
|
|
1444
|
+
.prepare("SELECT instance_did, value FROM cs_settings WHERE key = ? ORDER BY instance_did")
|
|
1407
1445
|
.bind(key)
|
|
1408
1446
|
.all();
|
|
1409
1447
|
return (rows.results ?? []).map((r) => ({ instanceDid: r.instance_did, value: r.value }));
|
|
@@ -1434,7 +1472,7 @@ export class D1Store {
|
|
|
1434
1472
|
if (cached && Date.now() - cached.at < HOST_CACHE_TTL)
|
|
1435
1473
|
return cached.instanceDid;
|
|
1436
1474
|
const row = await this.db
|
|
1437
|
-
.prepare("SELECT instance_did FROM
|
|
1475
|
+
.prepare("SELECT instance_did FROM cs_instance_hosts WHERE host = ?")
|
|
1438
1476
|
.bind(h)
|
|
1439
1477
|
.first();
|
|
1440
1478
|
if (row)
|
|
@@ -1449,7 +1487,7 @@ export class D1Store {
|
|
|
1449
1487
|
if (!h)
|
|
1450
1488
|
return { ok: false, reason: "invalid" };
|
|
1451
1489
|
const res = await this.db
|
|
1452
|
-
.prepare("INSERT INTO
|
|
1490
|
+
.prepare("INSERT INTO cs_instance_hosts (host, instance_did, updated_at, created_by, updated_by) VALUES (?, ?, datetime('now'), ?, ?) ON CONFLICT(host) DO NOTHING")
|
|
1453
1491
|
.bind(h, instanceDid, actor, actor)
|
|
1454
1492
|
.run();
|
|
1455
1493
|
if ((res.meta?.changes ?? 0) > 0) {
|
|
@@ -1458,7 +1496,7 @@ export class D1Store {
|
|
|
1458
1496
|
}
|
|
1459
1497
|
// Row already existed — read committed value from D1 (not cache) to decide.
|
|
1460
1498
|
const owner = await this.db
|
|
1461
|
-
.prepare("SELECT instance_did FROM
|
|
1499
|
+
.prepare("SELECT instance_did FROM cs_instance_hosts WHERE host = ?")
|
|
1462
1500
|
.bind(h)
|
|
1463
1501
|
.first();
|
|
1464
1502
|
if (owner?.instance_did === instanceDid)
|
|
@@ -1470,26 +1508,26 @@ export class D1Store {
|
|
|
1470
1508
|
const h = this.normalizeHost(host);
|
|
1471
1509
|
if (!h)
|
|
1472
1510
|
return;
|
|
1473
|
-
await this.db.prepare("DELETE FROM
|
|
1511
|
+
await this.db.prepare("DELETE FROM cs_instance_hosts WHERE host = ?").bind(h).run();
|
|
1474
1512
|
invalidateHostCache();
|
|
1475
1513
|
}
|
|
1476
1514
|
/** List all hosts bound to an instance (normalized form). */
|
|
1477
1515
|
async listInstanceHosts(instanceDid) {
|
|
1478
1516
|
const rows = await this.db
|
|
1479
|
-
.prepare("SELECT host FROM
|
|
1517
|
+
.prepare("SELECT host FROM cs_instance_hosts WHERE instance_did = ? ORDER BY host")
|
|
1480
1518
|
.bind(instanceDid)
|
|
1481
1519
|
.all();
|
|
1482
1520
|
return (rows.results ?? []).map((r) => r.host);
|
|
1483
1521
|
}
|
|
1484
1522
|
/** Delete all host bindings for an instance (used during instance removal). */
|
|
1485
1523
|
async deleteInstanceHosts(instanceDid) {
|
|
1486
|
-
await this.db.prepare("DELETE FROM
|
|
1524
|
+
await this.db.prepare("DELETE FROM cs_instance_hosts WHERE instance_did = ?").bind(instanceDid).run();
|
|
1487
1525
|
invalidateHostCache();
|
|
1488
1526
|
}
|
|
1489
1527
|
// ─── Verify codes (Email Login) ────────────────────────────────────────
|
|
1490
1528
|
async createVerifyCode(code, subject, purpose) {
|
|
1491
1529
|
const result = await this.db
|
|
1492
|
-
.prepare("INSERT INTO
|
|
1530
|
+
.prepare("INSERT INTO cs_verify_codes (code, subject, purpose) VALUES (?, ?, ?)")
|
|
1493
1531
|
.bind(code, subject, purpose)
|
|
1494
1532
|
.run();
|
|
1495
1533
|
// D1 returns last_row_id in meta
|
|
@@ -1500,11 +1538,11 @@ export class D1Store {
|
|
|
1500
1538
|
// then SELECT to retrieve data. batch() is transactional in D1.
|
|
1501
1539
|
const [updateResult, selectResult] = await this.db.batch([
|
|
1502
1540
|
this.db
|
|
1503
|
-
.prepare(`UPDATE
|
|
1541
|
+
.prepare(`UPDATE cs_verify_codes SET verified = 1, verified_at = datetime('now')
|
|
1504
1542
|
WHERE code = ? AND verified = 0
|
|
1505
1543
|
AND created_at > datetime('now', '-30 minutes')`)
|
|
1506
1544
|
.bind(code),
|
|
1507
|
-
this.db.prepare("SELECT id, subject FROM
|
|
1545
|
+
this.db.prepare("SELECT id, subject FROM cs_verify_codes WHERE code = ?").bind(code),
|
|
1508
1546
|
]);
|
|
1509
1547
|
if (!updateResult.meta?.changes)
|
|
1510
1548
|
return null;
|
|
@@ -1512,7 +1550,7 @@ export class D1Store {
|
|
|
1512
1550
|
}
|
|
1513
1551
|
async isVerifyCodeSent(subject) {
|
|
1514
1552
|
const row = await this.db
|
|
1515
|
-
.prepare(`SELECT 1 FROM
|
|
1553
|
+
.prepare(`SELECT 1 FROM cs_verify_codes
|
|
1516
1554
|
WHERE subject = ? AND sent = 1
|
|
1517
1555
|
AND sent_at > datetime('now', '-1 minute')`)
|
|
1518
1556
|
.bind(subject)
|
|
@@ -1521,46 +1559,46 @@ export class D1Store {
|
|
|
1521
1559
|
}
|
|
1522
1560
|
async markVerifyCodeSent(code) {
|
|
1523
1561
|
await this.db
|
|
1524
|
-
.prepare("UPDATE
|
|
1562
|
+
.prepare("UPDATE cs_verify_codes SET sent = 1, sent_at = datetime('now') WHERE code = ?")
|
|
1525
1563
|
.bind(code)
|
|
1526
1564
|
.run();
|
|
1527
1565
|
}
|
|
1528
1566
|
async purgeExpiredVerifyCodes() {
|
|
1529
1567
|
await this.db
|
|
1530
|
-
.prepare("DELETE FROM
|
|
1568
|
+
.prepare("DELETE FROM cs_verify_codes WHERE created_at < datetime('now', '-1 hour')")
|
|
1531
1569
|
.run();
|
|
1532
1570
|
}
|
|
1533
1571
|
// ─── Login tickets (Federation) ────────────────────────────────────────
|
|
1534
1572
|
async createLoginTicket(ticket, did, targetOrigin, ttlSeconds = 300) {
|
|
1535
1573
|
await this.db
|
|
1536
|
-
.prepare(`INSERT INTO
|
|
1574
|
+
.prepare(`INSERT INTO cs_login_tickets (ticket, did, target_origin, expires_at)
|
|
1537
1575
|
VALUES (?, ?, ?, datetime('now', '+' || ? || ' seconds'))`)
|
|
1538
1576
|
.bind(ticket, did, targetOrigin || null, ttlSeconds)
|
|
1539
1577
|
.run();
|
|
1540
1578
|
}
|
|
1541
1579
|
async getLoginTicket(ticket) {
|
|
1542
1580
|
return this.db
|
|
1543
|
-
.prepare(`SELECT ticket, did, target_origin FROM
|
|
1581
|
+
.prepare(`SELECT ticket, did, target_origin FROM cs_login_tickets
|
|
1544
1582
|
WHERE ticket = ? AND expires_at > datetime('now')`)
|
|
1545
1583
|
.bind(ticket)
|
|
1546
1584
|
.first();
|
|
1547
1585
|
}
|
|
1548
1586
|
async deleteLoginTicket(ticket) {
|
|
1549
|
-
await this.db.prepare("DELETE FROM
|
|
1587
|
+
await this.db.prepare("DELETE FROM cs_login_tickets WHERE ticket = ?").bind(ticket).run();
|
|
1550
1588
|
}
|
|
1551
1589
|
async purgeExpiredLoginTickets() {
|
|
1552
|
-
await this.db.prepare("DELETE FROM
|
|
1590
|
+
await this.db.prepare("DELETE FROM cs_login_tickets WHERE expires_at < datetime('now')").run();
|
|
1553
1591
|
}
|
|
1554
1592
|
async deleteLoginTicketsByOrigin(origin) {
|
|
1555
1593
|
await this.ensureSchema();
|
|
1556
1594
|
await this.db
|
|
1557
|
-
.prepare("DELETE FROM
|
|
1595
|
+
.prepare("DELETE FROM cs_login_tickets WHERE target_origin = ?")
|
|
1558
1596
|
.bind(origin)
|
|
1559
1597
|
.run();
|
|
1560
1598
|
}
|
|
1561
1599
|
async deleteAllLoginTickets() {
|
|
1562
1600
|
await this.ensureSchema();
|
|
1563
|
-
await this.db.prepare("DELETE FROM
|
|
1601
|
+
await this.db.prepare("DELETE FROM cs_login_tickets").run();
|
|
1564
1602
|
}
|
|
1565
1603
|
// ─── Instance default rule seeding ──────────────────────────────────────
|
|
1566
1604
|
async seedInstanceDefaults(instanceDid) {
|
|
@@ -1597,13 +1635,13 @@ export class D1Store {
|
|
|
1597
1635
|
},
|
|
1598
1636
|
];
|
|
1599
1637
|
await this.db.batch(policies.map((p) => this.db
|
|
1600
|
-
.prepare(`INSERT OR IGNORE INTO
|
|
1638
|
+
.prepare(`INSERT OR IGNORE INTO cs_access_policies (id, name, description, roles, reverse, isProtected, instance_did, createdAt, updatedAt, createdBy, updatedBy)
|
|
1601
1639
|
VALUES (?, ?, ?, ?, ?, 1, ?, ?, ?, 'system', 'system')`)
|
|
1602
1640
|
.bind(p.id, p.name, p.description, p.roles, p.reverse, instanceDid, now, now)));
|
|
1603
1641
|
// Seed instance default rule referencing the instance-scoped public policy
|
|
1604
1642
|
const ruleId = `default-${instanceDid}`;
|
|
1605
1643
|
await this.db
|
|
1606
|
-
.prepare(`INSERT OR IGNORE INTO
|
|
1644
|
+
.prepare(`INSERT OR IGNORE INTO cs_security_rules
|
|
1607
1645
|
(id, pathPattern, priority, accessPolicyId, enabled, remark, instance_did, createdAt, updatedAt, createdBy, updatedBy)
|
|
1608
1646
|
VALUES (?, '*', 0, ?, 1, 'Instance default: public access', ?, ?, ?, 'system', 'system')`)
|
|
1609
1647
|
.bind(ruleId, `public-${instanceDid}`, instanceDid, now, now)
|
|
@@ -1618,8 +1656,8 @@ export class D1Store {
|
|
|
1618
1656
|
}
|
|
1619
1657
|
const rows = await this.db
|
|
1620
1658
|
.prepare(`SELECT r.id, r.pathPattern, r.priority, p.roles, p.reverse, r.enabled
|
|
1621
|
-
FROM
|
|
1622
|
-
JOIN
|
|
1659
|
+
FROM cs_security_rules r
|
|
1660
|
+
JOIN cs_access_policies p ON r.accessPolicyId = p.id
|
|
1623
1661
|
WHERE r.enabled = 1
|
|
1624
1662
|
AND (r.instance_did = ?1 OR r.instance_did IS NULL)
|
|
1625
1663
|
AND (p.instance_did = ?1 OR p.instance_did IS NULL)
|
|
@@ -1642,8 +1680,8 @@ export class D1Store {
|
|
|
1642
1680
|
}
|
|
1643
1681
|
const rows = await this.db
|
|
1644
1682
|
.prepare(`SELECT r.id, r.pathPattern, r.priority, p.roles, p.reverse, r.enabled
|
|
1645
|
-
FROM
|
|
1646
|
-
JOIN
|
|
1683
|
+
FROM cs_security_rules r
|
|
1684
|
+
JOIN cs_access_policies p ON r.accessPolicyId = p.id
|
|
1647
1685
|
WHERE r.enabled = 1
|
|
1648
1686
|
ORDER BY CASE WHEN r.id = 'default' THEN 1 ELSE 0 END, r.priority ASC`)
|
|
1649
1687
|
.all();
|
|
@@ -1655,46 +1693,46 @@ export class D1Store {
|
|
|
1655
1693
|
async createAccessKeySession(params) {
|
|
1656
1694
|
const now = new Date().toISOString();
|
|
1657
1695
|
await this.db
|
|
1658
|
-
.prepare(`INSERT INTO
|
|
1696
|
+
.prepare(`INSERT INTO cs_access_key_sessions (id, challenge, status, access_key_id, access_key_secret_encrypted, source, created_at, expires_at)
|
|
1659
1697
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
1660
1698
|
.bind(params.id, params.challenge, "pending", null, null, params.source, now, params.expiresAt)
|
|
1661
1699
|
.run();
|
|
1662
1700
|
}
|
|
1663
1701
|
async getAccessKeySession(id) {
|
|
1664
1702
|
const row = await this.db
|
|
1665
|
-
.prepare(`SELECT * FROM
|
|
1703
|
+
.prepare(`SELECT * FROM cs_access_key_sessions WHERE id = ? AND expires_at > datetime('now')`)
|
|
1666
1704
|
.bind(id)
|
|
1667
1705
|
.first();
|
|
1668
1706
|
return row ?? null;
|
|
1669
1707
|
}
|
|
1670
1708
|
async updateAccessKeySession(id, updates) {
|
|
1671
1709
|
await this.db
|
|
1672
|
-
.prepare(`UPDATE
|
|
1710
|
+
.prepare(`UPDATE cs_access_key_sessions SET status = ?, access_key_id = ?, access_key_secret_encrypted = ? WHERE id = ?`)
|
|
1673
1711
|
.bind(updates.status, updates.accessKeyId, updates.accessKeySecretEncrypted, id)
|
|
1674
1712
|
.run();
|
|
1675
1713
|
}
|
|
1676
1714
|
async deleteAccessKeySession(id) {
|
|
1677
1715
|
await this.db
|
|
1678
|
-
.prepare(`DELETE FROM
|
|
1716
|
+
.prepare(`DELETE FROM cs_access_key_sessions WHERE id = ?`)
|
|
1679
1717
|
.bind(id)
|
|
1680
1718
|
.run();
|
|
1681
1719
|
}
|
|
1682
1720
|
async purgeExpiredAccessKeySessions() {
|
|
1683
1721
|
await this.db
|
|
1684
|
-
.prepare(`DELETE FROM
|
|
1722
|
+
.prepare(`DELETE FROM cs_access_key_sessions WHERE expires_at <= datetime('now')`)
|
|
1685
1723
|
.run();
|
|
1686
1724
|
}
|
|
1687
1725
|
// ── Generic KV cache (kv_cache table) ─────────────────────────────────
|
|
1688
1726
|
/** Read a cached value. Returns null if missing or expired (lazy-deletes expired rows). */
|
|
1689
1727
|
async cacheGet(key) {
|
|
1690
1728
|
const row = await this.db
|
|
1691
|
-
.prepare("SELECT value, expires_at FROM
|
|
1729
|
+
.prepare("SELECT value, expires_at FROM cs_kv_cache WHERE key = ?")
|
|
1692
1730
|
.bind(key)
|
|
1693
1731
|
.first();
|
|
1694
1732
|
if (!row)
|
|
1695
1733
|
return null;
|
|
1696
1734
|
if (row.expires_at < Math.floor(Date.now() / 1000)) {
|
|
1697
|
-
this.db.prepare("DELETE FROM
|
|
1735
|
+
this.db.prepare("DELETE FROM cs_kv_cache WHERE key = ?").bind(key).run().catch(() => { });
|
|
1698
1736
|
return null;
|
|
1699
1737
|
}
|
|
1700
1738
|
return row.value;
|
|
@@ -1703,7 +1741,7 @@ export class D1Store {
|
|
|
1703
1741
|
async cachePut(key, value, ttlSeconds) {
|
|
1704
1742
|
const expiresAt = Math.floor(Date.now() / 1000) + ttlSeconds;
|
|
1705
1743
|
await this.db
|
|
1706
|
-
.prepare("INSERT OR REPLACE INTO
|
|
1744
|
+
.prepare("INSERT OR REPLACE INTO cs_kv_cache (key, value, expires_at) VALUES (?, ?, ?)")
|
|
1707
1745
|
.bind(key, value, expiresAt)
|
|
1708
1746
|
.run();
|
|
1709
1747
|
if (Math.random() < 0.05) {
|
|
@@ -1712,12 +1750,12 @@ export class D1Store {
|
|
|
1712
1750
|
}
|
|
1713
1751
|
/** Delete a cached value. */
|
|
1714
1752
|
async cacheDelete(key) {
|
|
1715
|
-
await this.db.prepare("DELETE FROM
|
|
1753
|
+
await this.db.prepare("DELETE FROM cs_kv_cache WHERE key = ?").bind(key).run();
|
|
1716
1754
|
}
|
|
1717
1755
|
/** Purge all expired cache rows. */
|
|
1718
1756
|
async purgeExpiredCache() {
|
|
1719
1757
|
const now = Math.floor(Date.now() / 1000);
|
|
1720
|
-
await this.db.prepare("DELETE FROM
|
|
1758
|
+
await this.db.prepare("DELETE FROM cs_kv_cache WHERE expires_at < ?").bind(now).run();
|
|
1721
1759
|
}
|
|
1722
1760
|
// ─── Instance registration queries ──────────────────────────────────────
|
|
1723
1761
|
/** List all registered instances (those with an app:sk setting). */
|
|
@@ -1727,10 +1765,10 @@ export class D1Store {
|
|
|
1727
1765
|
COALESCE(s2.value, json_extract(s4.value, '$.name')) as app_name,
|
|
1728
1766
|
CASE WHEN s3.value IS NOT NULL THEN 1 ELSE 0 END as has_psk,
|
|
1729
1767
|
s1.updated_at as registered_at
|
|
1730
|
-
FROM
|
|
1731
|
-
LEFT JOIN
|
|
1732
|
-
LEFT JOIN
|
|
1733
|
-
LEFT JOIN
|
|
1768
|
+
FROM cs_settings s1
|
|
1769
|
+
LEFT JOIN cs_settings s2 ON s1.instance_did = s2.instance_did AND s2.key = 'app:name'
|
|
1770
|
+
LEFT JOIN cs_settings s3 ON s1.instance_did = s3.instance_did AND s3.key = 'app:psk'
|
|
1771
|
+
LEFT JOIN cs_settings s4 ON s1.instance_did = s4.instance_did AND s4.key = 'app:branding'
|
|
1734
1772
|
WHERE s1.key = 'app:sk'
|
|
1735
1773
|
ORDER BY s1.updated_at DESC`)
|
|
1736
1774
|
.all();
|
|
@@ -1749,7 +1787,7 @@ export class D1Store {
|
|
|
1749
1787
|
const withPrefix = appSk.startsWith("0x") ? appSk : `0x${appSk}`;
|
|
1750
1788
|
const withoutPrefix = appSk.startsWith("0x") ? appSk.slice(2) : appSk;
|
|
1751
1789
|
const { results } = await this.db
|
|
1752
|
-
.prepare(`SELECT DISTINCT instance_did FROM
|
|
1790
|
+
.prepare(`SELECT DISTINCT instance_did FROM cs_settings
|
|
1753
1791
|
WHERE key = 'app:sk' AND value IN (?, ?)`)
|
|
1754
1792
|
.bind(withPrefix, withoutPrefix)
|
|
1755
1793
|
.all();
|
|
@@ -1758,7 +1796,7 @@ export class D1Store {
|
|
|
1758
1796
|
/** Delete all security rules for a specific instance. */
|
|
1759
1797
|
async deleteSecurityRulesByInstance(instanceDid) {
|
|
1760
1798
|
await this.db
|
|
1761
|
-
.prepare("DELETE FROM
|
|
1799
|
+
.prepare("DELETE FROM cs_security_rules WHERE instance_did = ?")
|
|
1762
1800
|
.bind(instanceDid)
|
|
1763
1801
|
.run();
|
|
1764
1802
|
invalidateRulesCache();
|
|
@@ -1766,7 +1804,7 @@ export class D1Store {
|
|
|
1766
1804
|
/** Delete all access policies for a specific instance. */
|
|
1767
1805
|
async deleteAccessPoliciesByInstance(instanceDid) {
|
|
1768
1806
|
await this.db
|
|
1769
|
-
.prepare("DELETE FROM
|
|
1807
|
+
.prepare("DELETE FROM cs_access_policies WHERE instance_did = ?")
|
|
1770
1808
|
.bind(instanceDid)
|
|
1771
1809
|
.run();
|
|
1772
1810
|
invalidateRulesCache();
|