@camstack/core 0.1.20 → 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/auth-manager.d.ts +1 -16
- package/dist/auth/auth-manager.d.ts.map +1 -1
- 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 +38 -23
- package/dist/builtins/local-auth/local-auth.addon.js.map +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +38 -23
- package/dist/builtins/local-auth/local-auth.addon.mjs.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ScopedTokenManager } from './scoped-token-manager.js';
|
|
1
|
+
import { UserRole, TokenPayload, IScopedLogger } from '@camstack/types';
|
|
3
2
|
export type { UserRole, TokenPayload };
|
|
4
3
|
export type AuthConfigReader = {
|
|
5
4
|
get<T>(path: string): T;
|
|
@@ -8,7 +7,6 @@ export type AuthConfigReader = {
|
|
|
8
7
|
export declare class AuthManager {
|
|
9
8
|
private readonly config;
|
|
10
9
|
private readonly jwtSecret;
|
|
11
|
-
private scopedTokenManager;
|
|
12
10
|
private readonly logger;
|
|
13
11
|
constructor(config: AuthConfigReader, logger?: IScopedLogger);
|
|
14
12
|
signToken(payload: Omit<TokenPayload, 'iat' | 'exp'>): string;
|
|
@@ -30,18 +28,5 @@ export declare class AuthManager {
|
|
|
30
28
|
readonly role?: string;
|
|
31
29
|
readonly expiresIn?: string;
|
|
32
30
|
}): string;
|
|
33
|
-
/**
|
|
34
|
-
* Set the scoped token manager for the auth chain.
|
|
35
|
-
*/
|
|
36
|
-
setScopedTokenManager(manager: ScopedTokenManager): void;
|
|
37
|
-
/**
|
|
38
|
-
* Validate a scoped token string.
|
|
39
|
-
* Returns the token record if valid, null otherwise.
|
|
40
|
-
*/
|
|
41
|
-
validateScopedToken(rawToken: string): Promise<ScopedToken | null>;
|
|
42
|
-
/**
|
|
43
|
-
* Check whether a scoped token grants access to a given addon/route/capability.
|
|
44
|
-
*/
|
|
45
|
-
matchesScopedTokenScope(token: ScopedToken, addonId?: string, routePath?: string, capability?: string): boolean;
|
|
46
31
|
}
|
|
47
32
|
//# sourceMappingURL=auth-manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-manager.d.ts","sourceRoot":"","sources":["../../src/auth/auth-manager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"auth-manager.d.ts","sourceRoot":"","sources":["../../src/auth/auth-manager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAY5E,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAA;AAEtC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CAAA;IACvB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;CAC7D,CAAA;AAED,qBAAa,WAAW;IAIV,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;gBAET,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAE,aAA0B;IAczF,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,KAAK,GAAG,KAAK,CAAC,GAAG,MAAM;IAI7D,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY;IAIlC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI/C,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIvE,cAAc,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IAOjE,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO;IAK1D;;;OAGG;IACH,kBAAkB,CAAC,IAAI,EAAE;QACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;QACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAC5B,GAAG,MAAM;CAmBX"}
|
|
@@ -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"}
|
|
@@ -6166,7 +6166,6 @@ var noopLogger = {
|
|
|
6166
6166
|
};
|
|
6167
6167
|
var AuthManager = class {
|
|
6168
6168
|
jwtSecret;
|
|
6169
|
-
scopedTokenManager = null;
|
|
6170
6169
|
logger;
|
|
6171
6170
|
constructor(config, logger = noopLogger) {
|
|
6172
6171
|
this.config = config;
|
|
@@ -6220,27 +6219,6 @@ var AuthManager = class {
|
|
|
6220
6219
|
const expiresIn = opts.expiresIn ?? "24h";
|
|
6221
6220
|
return import_jsonwebtoken.sign(payload, this.jwtSecret, { expiresIn });
|
|
6222
6221
|
}
|
|
6223
|
-
/**
|
|
6224
|
-
* Set the scoped token manager for the auth chain.
|
|
6225
|
-
*/
|
|
6226
|
-
setScopedTokenManager(manager) {
|
|
6227
|
-
this.scopedTokenManager = manager;
|
|
6228
|
-
}
|
|
6229
|
-
/**
|
|
6230
|
-
* Validate a scoped token string.
|
|
6231
|
-
* Returns the token record if valid, null otherwise.
|
|
6232
|
-
*/
|
|
6233
|
-
async validateScopedToken(rawToken) {
|
|
6234
|
-
if (!this.scopedTokenManager) return null;
|
|
6235
|
-
return this.scopedTokenManager.validate(rawToken);
|
|
6236
|
-
}
|
|
6237
|
-
/**
|
|
6238
|
-
* Check whether a scoped token grants access to a given addon/route/capability.
|
|
6239
|
-
*/
|
|
6240
|
-
matchesScopedTokenScope(token, addonId, routePath, capability) {
|
|
6241
|
-
if (!this.scopedTokenManager) return false;
|
|
6242
|
-
return this.scopedTokenManager.matchesScope(token, addonId, routePath, capability);
|
|
6243
|
-
}
|
|
6244
6222
|
};
|
|
6245
6223
|
//#endregion
|
|
6246
6224
|
//#region src/auth/parse-record.ts
|
|
@@ -6545,6 +6523,39 @@ var ScopedTokenManager = class {
|
|
|
6545
6523
|
}
|
|
6546
6524
|
});
|
|
6547
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
|
+
}
|
|
6548
6559
|
};
|
|
6549
6560
|
//#endregion
|
|
6550
6561
|
//#region src/builtins/local-auth/auth-schema.ts
|
|
@@ -6762,6 +6773,10 @@ var LocalAuthAddon = class extends _camstack_types.BaseAddon {
|
|
|
6762
6773
|
this.scopedTokenManager = new ScopedTokenManager(store);
|
|
6763
6774
|
try {
|
|
6764
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`);
|
|
6765
6780
|
} catch (err) {
|
|
6766
6781
|
const detail = err instanceof Error ? err.message : String(err);
|
|
6767
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 });
|
|
@@ -6848,7 +6863,7 @@ var LocalAuthAddon = class extends _camstack_types.BaseAddon {
|
|
|
6848
6863
|
},
|
|
6849
6864
|
createScopedToken: async (input) => {
|
|
6850
6865
|
if (!this.scopedTokenManager) throw new Error("Scoped token management not available");
|
|
6851
|
-
const { token, record } = await this.scopedTokenManager.create(
|
|
6866
|
+
const { token, record } = await this.scopedTokenManager.create(input.userId, input.name, input.scopes, input.expiresAt);
|
|
6852
6867
|
return {
|
|
6853
6868
|
token,
|
|
6854
6869
|
record
|