@camstack/core 0.1.21 → 0.1.22
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/auth/scoped-token-manager.d.ts +16 -0
- package/dist/auth/scoped-token-manager.d.ts.map +1 -1
- package/dist/builtins/local-auth/local-auth.addon.d.ts.map +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +37 -0
- package/dist/builtins/local-auth/local-auth.addon.js.map +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +37 -0
- package/dist/builtins/local-auth/local-auth.addon.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -14,5 +14,21 @@ export declare class ScopedTokenManager {
|
|
|
14
14
|
revoke(tokenId: string): Promise<void>;
|
|
15
15
|
listForUser(userId: string): Promise<ScopedToken[]>;
|
|
16
16
|
updateLastUsed(tokenId: string): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* One-shot migration: drop tokens whose owner can't be resolved.
|
|
19
|
+
*
|
|
20
|
+
* Two ways a token can end up orphan:
|
|
21
|
+
* • Pre-fix tokens minted via the CLI were owned by the literal
|
|
22
|
+
* string `"system"` (provider hardcode, fixed 2026-05-11).
|
|
23
|
+
* • A user gets deleted but their tokens were not cascade-revoked.
|
|
24
|
+
*
|
|
25
|
+
* Either way the UI's `listScopedTokens({ userId: u.id })` never
|
|
26
|
+
* returns them, so the operator can't revoke through the normal flow.
|
|
27
|
+
* We sweep both classes by passing the live user-id set in.
|
|
28
|
+
*
|
|
29
|
+
* Idempotent: if no orphans exist the method is a no-op.
|
|
30
|
+
* Returns the number of tokens removed.
|
|
31
|
+
*/
|
|
32
|
+
cleanupOrphans(validUserIds: ReadonlySet<string>): Promise<number>;
|
|
17
33
|
}
|
|
18
34
|
//# sourceMappingURL=scoped-token-manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scoped-token-manager.d.ts","sourceRoot":"","sources":["../../src/auth/scoped-token-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAUnF;;GAEG;AACH,qBAAa,kBAAkB;IACjB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,mBAAmB;IAEjD,MAAM,CACV,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,UAAU,EAAE,EACpB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,WAAW,CAAA;KAAE,CAAC;IAsB5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAY7D,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO;IAW9F,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAItC,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAKnD,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"scoped-token-manager.d.ts","sourceRoot":"","sources":["../../src/auth/scoped-token-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAUnF;;GAEG;AACH,qBAAa,kBAAkB;IACjB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,mBAAmB;IAEjD,MAAM,CACV,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,UAAU,EAAE,EACpB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,WAAW,CAAA;KAAE,CAAC;IAsB5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAY7D,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO;IAW9F,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAItC,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAKnD,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOpD;;;;;;;;;;;;;;OAcG;IACG,cAAc,CAAC,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;CAYzE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-auth.addon.d.ts","sourceRoot":"","sources":["../../../src/builtins/local-auth/local-auth.addon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAA2B,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AACpF,OAAO,EAAE,SAAS,EAAoD,MAAM,iBAAiB,CAAA;AA4B7F,UAAU,eAAe;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,qBAAa,cAAe,SAAQ,SAAS,CAAC,eAAe,CAAC;IAC5D,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,kBAAkB,CAAkC;;cAI5C,YAAY,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"local-auth.addon.d.ts","sourceRoot":"","sources":["../../../src/builtins/local-auth/local-auth.addon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAA2B,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AACpF,OAAO,EAAE,SAAS,EAAoD,MAAM,iBAAiB,CAAA;AA4B7F,UAAU,eAAe;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,qBAAa,cAAe,SAAQ,SAAS,CAAC,eAAe,CAAC;IAC5D,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,kBAAkB,CAAkC;;cAI5C,YAAY,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC;cAwM/C,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAM5C;AAED,eAAe,cAAc,CAAA"}
|
|
@@ -6523,6 +6523,39 @@ var ScopedTokenManager = class {
|
|
|
6523
6523
|
}
|
|
6524
6524
|
});
|
|
6525
6525
|
}
|
|
6526
|
+
/**
|
|
6527
|
+
* One-shot migration: drop tokens whose owner can't be resolved.
|
|
6528
|
+
*
|
|
6529
|
+
* Two ways a token can end up orphan:
|
|
6530
|
+
* • Pre-fix tokens minted via the CLI were owned by the literal
|
|
6531
|
+
* string `"system"` (provider hardcode, fixed 2026-05-11).
|
|
6532
|
+
* • A user gets deleted but their tokens were not cascade-revoked.
|
|
6533
|
+
*
|
|
6534
|
+
* Either way the UI's `listScopedTokens({ userId: u.id })` never
|
|
6535
|
+
* returns them, so the operator can't revoke through the normal flow.
|
|
6536
|
+
* We sweep both classes by passing the live user-id set in.
|
|
6537
|
+
*
|
|
6538
|
+
* Idempotent: if no orphans exist the method is a no-op.
|
|
6539
|
+
* Returns the number of tokens removed.
|
|
6540
|
+
*/
|
|
6541
|
+
async cleanupOrphans(validUserIds) {
|
|
6542
|
+
const all = await this.store.query.query({
|
|
6543
|
+
collection: TOKENS_COLLECTION,
|
|
6544
|
+
filter: {}
|
|
6545
|
+
});
|
|
6546
|
+
let removed = 0;
|
|
6547
|
+
for (const entry of all) {
|
|
6548
|
+
const record = parseToken(entry.data);
|
|
6549
|
+
if (record.userId === "system" || !validUserIds.has(record.userId)) {
|
|
6550
|
+
await this.store.delete.mutate({
|
|
6551
|
+
collection: TOKENS_COLLECTION,
|
|
6552
|
+
key: record.id
|
|
6553
|
+
});
|
|
6554
|
+
removed++;
|
|
6555
|
+
}
|
|
6556
|
+
}
|
|
6557
|
+
return removed;
|
|
6558
|
+
}
|
|
6526
6559
|
};
|
|
6527
6560
|
//#endregion
|
|
6528
6561
|
//#region src/builtins/local-auth/auth-schema.ts
|
|
@@ -6740,6 +6773,10 @@ var LocalAuthAddon = class extends _camstack_types.BaseAddon {
|
|
|
6740
6773
|
this.scopedTokenManager = new ScopedTokenManager(store);
|
|
6741
6774
|
try {
|
|
6742
6775
|
await this.userManager.ensureAdminExists();
|
|
6776
|
+
const liveUsers = await this.userManager.listAll();
|
|
6777
|
+
const liveIds = new Set(liveUsers.map((u) => u.id));
|
|
6778
|
+
const removed = await this.scopedTokenManager.cleanupOrphans(liveIds);
|
|
6779
|
+
if (removed > 0) this.ctx.logger.warn(`cleaned up ${removed} orphan scoped-token(s) on boot`);
|
|
6743
6780
|
} catch (err) {
|
|
6744
6781
|
const detail = err instanceof Error ? err.message : String(err);
|
|
6745
6782
|
throw new Error(`local-auth bootstrap failed: ensureAdminExists threw before \`user-management\` could be registered. Most likely a \`users\` collection schema mismatch in the settings-store. Underlying: ${detail}`, { cause: err });
|