@boopkit/cap-users 0.6.0 → 0.8.0
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/README.md +14 -0
- package/capability.json +19 -0
- package/dist/auth-middleware.d.ts +96 -2
- package/dist/auth-middleware.d.ts.map +1 -1
- package/dist/auth-middleware.js +131 -63
- package/dist/auth-middleware.js.map +1 -1
- package/dist/auth-service.d.ts +8 -0
- package/dist/auth-service.d.ts.map +1 -1
- package/dist/auth-service.js +93 -46
- package/dist/auth-service.js.map +1 -1
- package/dist/credential-migration.d.ts +76 -0
- package/dist/credential-migration.d.ts.map +1 -0
- package/dist/credential-migration.js +126 -0
- package/dist/credential-migration.js.map +1 -0
- package/dist/identity-service.d.ts +49 -0
- package/dist/identity-service.d.ts.map +1 -1
- package/dist/identity-service.js +34 -0
- package/dist/identity-service.js.map +1 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/dist/info-schema-tags.d.ts +21 -0
- package/dist/info-schema-tags.d.ts.map +1 -0
- package/dist/info-schema-tags.js +24 -0
- package/dist/info-schema-tags.js.map +1 -0
- package/dist/team-invitation-service.d.ts.map +1 -1
- package/dist/team-invitation-service.js +42 -8
- package/dist/team-invitation-service.js.map +1 -1
- package/package.json +1 -1
- package/scaffold/reference/user-auth.ref.md +48 -4
- package/scaffold/src/scripts/migrate-credentials.ts +69 -0
- package/scaffold/src/types/express.ts +11 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// @boopkit/cap-users template — Rehash cleartext credentials stored in property
|
|
2
|
+
// tables (boop-j8xc credential-hashing epic).
|
|
3
|
+
//
|
|
4
|
+
// Some property payloads once stored a raw, redeemable bearer credential beside
|
|
5
|
+
// its correctly-hashed twin: session tokens and API keys in the `authorization`
|
|
6
|
+
// user-property (and, once cap-users ships it, invitation tokens in the
|
|
7
|
+
// `team_invitations` account-property). The upgraded services store the hash and
|
|
8
|
+
// read tolerantly, but existing rows keep the raw value until they are rewritten.
|
|
9
|
+
// This script rehashes them IN PLACE, so no user is logged out and no pending
|
|
10
|
+
// invitation is voided.
|
|
11
|
+
//
|
|
12
|
+
// Usage:
|
|
13
|
+
// npm run credentials:migrate # REPORT ONLY — counts what would change, writes nothing
|
|
14
|
+
// npm run credentials:migrate -- --run # apply the rehash
|
|
15
|
+
//
|
|
16
|
+
// ⚠️ ONE-WAY, NO ROLLBACK. Hashing is irreversible — once a row is rewritten the
|
|
17
|
+
// raw value is gone for good. TAKE A DATABASE BACKUP before running --run.
|
|
18
|
+
//
|
|
19
|
+
// Safe to re-run: idempotency is decided by value shape (a SHA-256 digest is left
|
|
20
|
+
// untouched), so a value is never double-hashed. Provider access/refresh tokens
|
|
21
|
+
// in the `authentication` property are never touched — they are replayed to
|
|
22
|
+
// Google/Microsoft and must stay raw.
|
|
23
|
+
|
|
24
|
+
import { migrateCredentialStore, authorizationStore, teamInvitationsStore, type CredentialStore, type MigrationDelegate } from '@boopkit/cap-users';
|
|
25
|
+
import db from '../db';
|
|
26
|
+
|
|
27
|
+
const run = process.argv.includes('--run');
|
|
28
|
+
|
|
29
|
+
// The stores this deployment migrates — the same runner drives every one:
|
|
30
|
+
// - `authorization` user-property: raw session tokens and API keys (boop-j8xc.2)
|
|
31
|
+
// - `team_invitations` account-property: raw invitation tokens (boop-j8xc.3)
|
|
32
|
+
const targets: { model: MigrationDelegate; store: CredentialStore }[] = [
|
|
33
|
+
{ model: db.userProperty as unknown as MigrationDelegate, store: authorizationStore },
|
|
34
|
+
{ model: db.accountProperty as unknown as MigrationDelegate, store: teamInvitationsStore },
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
async function main() {
|
|
38
|
+
if (!run) {
|
|
39
|
+
console.log('=== REPORT ONLY (no writes) — pass --run to apply ===\n');
|
|
40
|
+
} else {
|
|
41
|
+
console.log('=== APPLYING migration (--run) ===\n');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let totalPending = 0;
|
|
45
|
+
for (const { model, store } of targets) {
|
|
46
|
+
const report = await migrateCredentialStore(model, store, { run });
|
|
47
|
+
totalPending += report.needsMigration;
|
|
48
|
+
const action = run ? `rehashed ${report.migrated}` : `${report.needsMigration} would be rehashed`;
|
|
49
|
+
console.log(
|
|
50
|
+
`${store.label}: scanned ${report.scanned}, ${action} ` +
|
|
51
|
+
`(${report.scanned - report.needsMigration} already migrated)`,
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!run && totalPending > 0) {
|
|
56
|
+
console.log(`\n${totalPending} row(s) hold a raw credential. Back up your database, then re-run with --run.`);
|
|
57
|
+
} else if (run) {
|
|
58
|
+
console.log('\nDone. All targeted rows are hashed and tagged.');
|
|
59
|
+
} else {
|
|
60
|
+
console.log('\nNothing to migrate — every targeted row is already hashed.');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
main()
|
|
65
|
+
.catch((err) => {
|
|
66
|
+
console.error('Migration failed:', err);
|
|
67
|
+
process.exitCode = 1;
|
|
68
|
+
})
|
|
69
|
+
.finally(() => db.$disconnect());
|
|
@@ -60,8 +60,18 @@ declare global {
|
|
|
60
60
|
* the session cookie via resolveVisitor. A gate that must accept only one
|
|
61
61
|
* kind of credential (requireApiKey) reads this — req.user alone cannot
|
|
62
62
|
* tell a key principal from a cookie one.
|
|
63
|
+
*
|
|
64
|
+
* `string`, not the `'api-key'` literal, because the label is chosen by
|
|
65
|
+
* whoever built the bearer middleware: `createBearerMiddleware` writes
|
|
66
|
+
* whatever `options.strategy` it was given, so a capability that issues
|
|
67
|
+
* its own tokens labels them its own way (oauth-server uses `'oauth'`).
|
|
68
|
+
* cap-users' own `resolveBearer` still writes `'api-key'`, and
|
|
69
|
+
* `requireApiKey` still compares against that literal — which is what
|
|
70
|
+
* makes another capability's token fail a key-only gate rather than pass
|
|
71
|
+
* it. Widening the label and widening the gate are NOT the same change;
|
|
72
|
+
* only the label widens.
|
|
63
73
|
*/
|
|
64
|
-
authStrategy?:
|
|
74
|
+
authStrategy?: string;
|
|
65
75
|
}
|
|
66
76
|
}
|
|
67
77
|
}
|