@camstack/core 0.1.29 → 0.1.30
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 +8 -1
- package/dist/auth/scoped-token-manager.d.ts.map +1 -1
- package/dist/auth/user-manager.d.ts +3 -2
- package/dist/auth/user-manager.d.ts.map +1 -1
- package/dist/builtins/local-auth/local-auth.addon.d.ts +6 -0
- package/dist/builtins/local-auth/local-auth.addon.d.ts.map +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +46 -5
- package/dist/builtins/local-auth/local-auth.addon.js.map +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +46 -5
- package/dist/builtins/local-auth/local-auth.addon.mjs.map +1 -1
- package/dist/index.js +116 -114
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +116 -114
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -10,7 +10,14 @@ export declare class ScopedTokenManager {
|
|
|
10
10
|
record: ScopedToken;
|
|
11
11
|
}>;
|
|
12
12
|
validate(rawToken: string): Promise<ScopedToken | null>;
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Coarse scope match — checks only `addonId` / `capability` (no
|
|
15
|
+
* `route-prefix` after the caps-only migration). Used by addon-route
|
|
16
|
+
* HTTP handlers that need a quick allow/deny before the per-method
|
|
17
|
+
* `access` check kicks in via `METHOD_ACCESS_MAP` in
|
|
18
|
+
* `protectedProcedure`.
|
|
19
|
+
*/
|
|
20
|
+
matchesScope(token: ScopedToken, addonId?: string, capability?: string): boolean;
|
|
14
21
|
revoke(tokenId: string): Promise<void>;
|
|
15
22
|
listForUser(userId: string): Promise<ScopedToken[]>;
|
|
16
23
|
updateLastUsed(tokenId: string): Promise<void>;
|
|
@@ -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,
|
|
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;;;;;;OAMG;IACH,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO;IAU1E,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,5 +1,5 @@
|
|
|
1
1
|
import { AuthManager } from './auth-manager.js';
|
|
2
|
-
import { UserRecord, UserRole, SettingsStoreClient } from '@camstack/types';
|
|
2
|
+
import { UserRecord, UserRole, TokenScope, SettingsStoreClient } from '@camstack/types';
|
|
3
3
|
export type { UserRecord };
|
|
4
4
|
interface CreateUserInput {
|
|
5
5
|
username: string;
|
|
@@ -7,8 +7,9 @@ interface CreateUserInput {
|
|
|
7
7
|
role: UserRole;
|
|
8
8
|
allowedProviders?: string[] | '*';
|
|
9
9
|
allowedDevices?: Record<string, string[] | '*'>;
|
|
10
|
+
scopes?: TokenScope[];
|
|
10
11
|
}
|
|
11
|
-
type UpdatableUserFields = Partial<Pick<UserRecord, 'role' | 'allowedProviders' | 'allowedDevices'>>;
|
|
12
|
+
type UpdatableUserFields = Partial<Pick<UserRecord, 'role' | 'allowedProviders' | 'allowedDevices' | 'scopes'>>;
|
|
12
13
|
export interface UserStorageAccess {
|
|
13
14
|
getStore(): SettingsStoreClient;
|
|
14
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-manager.d.ts","sourceRoot":"","sources":["../../src/auth/user-manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpD,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"user-manager.d.ts","sourceRoot":"","sources":["../../src/auth/user-manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpD,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAG5F,YAAY,EAAE,UAAU,EAAE,CAAA;AAE1B,UAAU,eAAe;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,QAAQ,CAAA;IACd,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,GAAG,CAAA;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,CAAA;IAC/C,MAAM,CAAC,EAAE,UAAU,EAAE,CAAA;CACtB;AAED,KAAK,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,GAAG,gBAAgB,GAAG,QAAQ,CAAC,CAAC,CAAA;AAI/G,MAAM,WAAW,iBAAiB;IAChC,QAAQ,IAAI,mBAAmB,CAAA;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CAAA;CACxB;AAMD,qBAAa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAFN,aAAa,EAAE,iBAAiB,EAChC,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,gBAAgB;IAG3C,OAAO,KAAK,KAAK,GAEhB;IAEK,MAAM,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC;IAsBnD,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAM5D,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAMhD,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAOnF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,EAAE,CAAC;IAStD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAM5D,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjC,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO7D,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;CAqBzC"}
|
|
@@ -12,6 +12,12 @@ export declare class LocalAuthAddon extends BaseAddon<LocalAuthConfig> {
|
|
|
12
12
|
constructor();
|
|
13
13
|
protected onInitialize(): Promise<ProviderRegistration[]>;
|
|
14
14
|
protected onShutdown(): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Caps-only auth migration — rewrites legacy `super_admin` rows to
|
|
17
|
+
* `admin` and backfills the missing `scopes` field with `[]`. Idempotent;
|
|
18
|
+
* a re-run sees no rows needing changes.
|
|
19
|
+
*/
|
|
20
|
+
private migrateLegacyUserRecords;
|
|
15
21
|
}
|
|
16
22
|
export default LocalAuthAddon;
|
|
17
23
|
//# sourceMappingURL=local-auth.addon.d.ts.map
|
|
@@ -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,
|
|
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,EAAuB,MAAM,iBAAiB,CAAA;AACzG,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;cAmO/C,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3C;;;;OAIG;YACW,wBAAwB;CAwBvC;AAED,eAAe,cAAc,CAAA"}
|
|
@@ -6258,6 +6258,7 @@ var UserManager = class {
|
|
|
6258
6258
|
role: input.role,
|
|
6259
6259
|
allowedProviders: input.allowedProviders ?? "*",
|
|
6260
6260
|
allowedDevices: input.allowedDevices ?? {},
|
|
6261
|
+
scopes: input.scopes ?? [],
|
|
6261
6262
|
createdAt: now,
|
|
6262
6263
|
updatedAt: now
|
|
6263
6264
|
};
|
|
@@ -6342,7 +6343,7 @@ var UserManager = class {
|
|
|
6342
6343
|
await this.create({
|
|
6343
6344
|
username: adminUsername,
|
|
6344
6345
|
password: adminPassword,
|
|
6345
|
-
role: "
|
|
6346
|
+
role: "admin",
|
|
6346
6347
|
allowedProviders: "*",
|
|
6347
6348
|
allowedDevices: {}
|
|
6348
6349
|
});
|
|
@@ -6481,14 +6482,18 @@ var ScopedTokenManager = class {
|
|
|
6481
6482
|
this.updateLastUsed(record.id).catch(() => {});
|
|
6482
6483
|
return record;
|
|
6483
6484
|
}
|
|
6484
|
-
|
|
6485
|
+
/**
|
|
6486
|
+
* Coarse scope match — checks only `addonId` / `capability` (no
|
|
6487
|
+
* `route-prefix` after the caps-only migration). Used by addon-route
|
|
6488
|
+
* HTTP handlers that need a quick allow/deny before the per-method
|
|
6489
|
+
* `access` check kicks in via `METHOD_ACCESS_MAP` in
|
|
6490
|
+
* `protectedProcedure`.
|
|
6491
|
+
*/
|
|
6492
|
+
matchesScope(token, addonId, capability) {
|
|
6485
6493
|
for (const scope of token.scopes) switch (scope.type) {
|
|
6486
6494
|
case "addon":
|
|
6487
6495
|
if (addonId && scope.target === addonId) return true;
|
|
6488
6496
|
break;
|
|
6489
|
-
case "route-prefix":
|
|
6490
|
-
if (routePath && routePath.startsWith(scope.target)) return true;
|
|
6491
|
-
break;
|
|
6492
6497
|
case "capability":
|
|
6493
6498
|
if (capability && scope.target === capability) return true;
|
|
6494
6499
|
break;
|
|
@@ -6772,6 +6777,11 @@ var LocalAuthAddon = class extends _camstack_types.BaseAddon {
|
|
|
6772
6777
|
this.apiKeyManager = new ApiKeyManager(storageAccess, this.authManager);
|
|
6773
6778
|
this.scopedTokenManager = new ScopedTokenManager(store);
|
|
6774
6779
|
try {
|
|
6780
|
+
try {
|
|
6781
|
+
await this.migrateLegacyUserRecords(store);
|
|
6782
|
+
} catch (err) {
|
|
6783
|
+
this.ctx.logger.warn("caps-only migration pass failed; legacy super_admin rows may still exist", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
6784
|
+
}
|
|
6775
6785
|
await this.userManager.ensureAdminExists();
|
|
6776
6786
|
const liveUsers = await this.userManager.listAll();
|
|
6777
6787
|
const liveIds = new Set(liveUsers.map((u) => u.id));
|
|
@@ -6832,6 +6842,11 @@ var LocalAuthAddon = class extends _camstack_types.BaseAddon {
|
|
|
6832
6842
|
await this.userManager.resetPassword(input.id, input.newPassword);
|
|
6833
6843
|
return { success: true };
|
|
6834
6844
|
},
|
|
6845
|
+
setUserScopes: async (input) => {
|
|
6846
|
+
if (!this.userManager) throw new Error("User management not available");
|
|
6847
|
+
await this.userManager.update(input.userId, { scopes: input.scopes });
|
|
6848
|
+
return { success: true };
|
|
6849
|
+
},
|
|
6835
6850
|
validateCredentials: async (input) => {
|
|
6836
6851
|
if (!this.userManager) return null;
|
|
6837
6852
|
return await this.userManager.validateCredentials(input.username, input.password) ?? null;
|
|
@@ -6898,6 +6913,32 @@ var LocalAuthAddon = class extends _camstack_types.BaseAddon {
|
|
|
6898
6913
|
this.apiKeyManager = null;
|
|
6899
6914
|
this.scopedTokenManager = null;
|
|
6900
6915
|
}
|
|
6916
|
+
/**
|
|
6917
|
+
* Caps-only auth migration — rewrites legacy `super_admin` rows to
|
|
6918
|
+
* `admin` and backfills the missing `scopes` field with `[]`. Idempotent;
|
|
6919
|
+
* a re-run sees no rows needing changes.
|
|
6920
|
+
*/
|
|
6921
|
+
async migrateLegacyUserRecords(store) {
|
|
6922
|
+
const results = await store.query.query({ collection: "users" });
|
|
6923
|
+
let migrated = 0;
|
|
6924
|
+
for (const row of results) {
|
|
6925
|
+
const data = row.data;
|
|
6926
|
+
const needsRoleRewrite = (typeof data["role"] === "string" ? data["role"] : null) === "super_admin";
|
|
6927
|
+
const needsScopesBackfill = !("scopes" in data);
|
|
6928
|
+
if (!needsRoleRewrite && !needsScopesBackfill) continue;
|
|
6929
|
+
const next = { ...data };
|
|
6930
|
+
if (needsRoleRewrite) next["role"] = "admin";
|
|
6931
|
+
if (needsScopesBackfill) next["scopes"] = [];
|
|
6932
|
+
next["updatedAt"] = Date.now();
|
|
6933
|
+
await store.update.mutate({
|
|
6934
|
+
collection: "users",
|
|
6935
|
+
id: row.id,
|
|
6936
|
+
data: next
|
|
6937
|
+
});
|
|
6938
|
+
migrated++;
|
|
6939
|
+
}
|
|
6940
|
+
if (migrated > 0) this.ctx.logger.info("caps-only auth migration: rewrote legacy user records", { meta: { count: migrated } });
|
|
6941
|
+
}
|
|
6901
6942
|
};
|
|
6902
6943
|
//#endregion
|
|
6903
6944
|
exports.ApiKeyManager = ApiKeyManager;
|