@rebasepro/server-postgres 0.9.1-canary.ff338b5 → 0.10.1-canary.18115ba
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 +21 -0
- package/dist/PostgresBackendDriver.d.ts +18 -0
- package/dist/PostgresBootstrapper.d.ts +7 -1
- package/dist/auth/services.d.ts +93 -54
- package/dist/index.es.js +929 -224
- package/dist/index.es.js.map +1 -1
- package/dist/schema/auth-bootstrap-sql.d.ts +1 -1
- package/dist/schema/auth-schema.d.ts +194 -24
- package/dist/schema/introspect-db-logic.d.ts +0 -5
- package/dist/schema/introspect-db-naming.d.ts +10 -0
- package/dist/security/policy-drift.d.ts +24 -0
- package/dist/security/rls-enforcement.d.ts +2 -2
- package/dist/services/channel-history.d.ts +118 -0
- package/dist/services/realtimeService.d.ts +69 -2
- package/package.json +7 -31
- package/src/PostgresBackendDriver.ts +56 -5
- package/src/PostgresBootstrapper.ts +18 -1
- package/src/auth/ensure-tables.ts +187 -19
- package/src/auth/services.ts +309 -170
- package/src/schema/auth-bootstrap-sql.ts +7 -1
- package/src/schema/auth-schema.ts +53 -15
- package/src/schema/introspect-db-inference.ts +1 -1
- package/src/schema/introspect-db-logic.ts +1 -10
- package/src/schema/introspect-db-naming.ts +15 -0
- package/src/schema/introspect-runtime.ts +1 -1
- package/src/security/policy-drift.test.ts +46 -0
- package/src/security/policy-drift.ts +70 -4
- package/src/security/rls-enforcement.ts +11 -5
- package/src/services/channel-history.ts +343 -0
- package/src/services/realtimeService.ts +198 -10
- package/src/websocket.ts +30 -11
package/README.md
CHANGED
|
@@ -76,6 +76,27 @@ process.on("SIGTERM", async () => {
|
|
|
76
76
|
| `statementTimeout` | 30,000 |
|
|
77
77
|
| `keepAlive` | true |
|
|
78
78
|
|
|
79
|
+
## Testing
|
|
80
|
+
|
|
81
|
+
This package runs **two test runners**, split by directory. This is deliberate — check which half you are in before running anything.
|
|
82
|
+
|
|
83
|
+
| Tests | Runner | Config | Command |
|
|
84
|
+
|-------|--------|--------|---------|
|
|
85
|
+
| `test/*.ts` (unit) | jest | [`jest.config.cjs`](./jest.config.cjs) | `pnpm test` |
|
|
86
|
+
| `test/e2e/**` (integration) | vitest | [`vitest.e2e.config.ts`](./vitest.e2e.config.ts) | `pnpm test:e2e` |
|
|
87
|
+
|
|
88
|
+
The unit tests use jest's injected globals (`describe`/`it`/`expect`) and `jest.mock`. The e2e tests import explicitly from `vitest` and need Docker (testcontainers spins up a real Postgres).
|
|
89
|
+
|
|
90
|
+
**Running a single unit test:**
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
npx jest test/auth-services.test.ts
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Pointing `vitest` at a unit test is the easy mistake here — it produces a bare `ReferenceError: jest is not defined` and a "no tests" result, which looks exactly like a dead or broken test file rather than the wrong runner. [`vitest.config.ts`](./vitest.config.ts) exists solely to intercept that and print the command you actually wanted.
|
|
97
|
+
|
|
98
|
+
`pnpm test` runs jest **without** `--passWithNoTests`: if the unit suite ever stops being collected, CI fails instead of going quietly green.
|
|
99
|
+
|
|
79
100
|
## Related Packages
|
|
80
101
|
|
|
81
102
|
| Package | Role |
|
|
@@ -114,6 +114,24 @@ export declare class PostgresBackendDriver implements DataDriver {
|
|
|
114
114
|
}): Promise<Record<string, unknown>[]>;
|
|
115
115
|
fetchAvailableDatabases(): Promise<string[]>;
|
|
116
116
|
fetchAvailableRoles(): Promise<string[]>;
|
|
117
|
+
/**
|
|
118
|
+
* Application-level roles actually in use in this project.
|
|
119
|
+
*
|
|
120
|
+
* Distinct from {@link fetchAvailableRoles}, which returns native
|
|
121
|
+
* PostgreSQL roles from `pg_roles` (`postgres`, `rebase_user`, …). Those
|
|
122
|
+
* are the roles the SQL editor can `SET ROLE` to. *These* are the strings
|
|
123
|
+
* held in the users table's `roles` column, injected per-transaction as
|
|
124
|
+
* `auth.roles()` and matched by `SecurityRule.roles`. Feeding the pg roles
|
|
125
|
+
* into a `SecurityRule.roles` field produces a condition no user can ever
|
|
126
|
+
* satisfy, so the two must not be conflated.
|
|
127
|
+
*
|
|
128
|
+
* Roles have no registry table — they were migrated out of
|
|
129
|
+
* `rebase.user_roles` onto an inline `roles TEXT[]` column — so the live
|
|
130
|
+
* set is derived from what is assigned. A role that is declared in a policy
|
|
131
|
+
* but held by nobody yet cannot be discovered here; callers that need it
|
|
132
|
+
* should union in the roles they already know about.
|
|
133
|
+
*/
|
|
134
|
+
fetchApplicationRoles(): Promise<string[]>;
|
|
117
135
|
fetchCurrentDatabase(): Promise<string | undefined>;
|
|
118
136
|
/**
|
|
119
137
|
* Fetch public tables that are not yet mapped to a collection.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Implements the `BackendBootstrapper` interface for PostgreSQL.
|
|
5
5
|
*/
|
|
6
6
|
import { NodePgDatabase } from "drizzle-orm/node-postgres";
|
|
7
|
-
import { BackendBootstrapper } from "@rebasepro/types";
|
|
7
|
+
import { BackendBootstrapper, type RealtimeChannelsConfig } from "@rebasepro/types";
|
|
8
8
|
import { PostgresBackendDriver } from "./PostgresBackendDriver";
|
|
9
9
|
import { RealtimeService } from "./services/realtimeService";
|
|
10
10
|
import { DatabasePoolManager } from "./databasePoolManager";
|
|
@@ -25,6 +25,12 @@ export interface PostgresDriverConfig {
|
|
|
25
25
|
* (BaaS mode). Defaults to `public`.
|
|
26
26
|
*/
|
|
27
27
|
introspectionSchema?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Realtime options. Currently only channel retention, which is opt-in:
|
|
30
|
+
* without rules here no channel keeps any history and broadcast stays
|
|
31
|
+
* fire-and-forget. See {@link ChannelRetentionRule}.
|
|
32
|
+
*/
|
|
33
|
+
realtime?: RealtimeChannelsConfig;
|
|
28
34
|
}
|
|
29
35
|
/**
|
|
30
36
|
* Opaque internals bag that PostgresBootstrapper stores during `initializeDriver()`
|
package/dist/auth/services.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NodePgDatabase } from "drizzle-orm/node-postgres";
|
|
2
2
|
import type { RebasePgTable } from "../types";
|
|
3
|
-
import { UserRepository, TokenRepository, MfaRepository, AuthRepository, UserData, CreateUserData, RoleData, CreateRoleData, RefreshTokenInfo, PasswordResetTokenInfo, MagicLinkTokenInfo, UserIdentityData, ListUsersOptions, PaginatedUsersResult, MfaFactor, MfaChallengeInfo, RoleData as Role } from "@rebasepro/server";
|
|
3
|
+
import { UserRepository, TokenRepository, MfaRepository, AuthRepository, UserData, CreateUserData, RoleData, CreateRoleData, RefreshTokenInfo, RefreshTokenSession, PasswordResetTokenInfo, MagicLinkTokenInfo, UserIdentityData, ListUsersOptions, PaginatedUsersResult, MfaFactor, MfaChallengeInfo, RoleData as Role } from "@rebasepro/server";
|
|
4
4
|
export type { Role };
|
|
5
5
|
export interface AuthSchemaTables {
|
|
6
6
|
users: RebasePgTable;
|
|
@@ -23,7 +23,7 @@ export declare class UserService implements UserRepository {
|
|
|
23
23
|
* Run a privileged auth write with an explicitly cleared RLS context.
|
|
24
24
|
*
|
|
25
25
|
* The auth services run on the base/owner connection, which by design
|
|
26
|
-
* carries a NULL `app.
|
|
26
|
+
* carries a NULL `app.uid` so the `auth.uid() IS NULL` server-escape
|
|
27
27
|
* in the default policies applies. That NULL is normally guaranteed by
|
|
28
28
|
* `set_config(..., is_local = true)` resetting at transaction end — but a
|
|
29
29
|
* GUC that survives on a pooled connection (or a connection role that
|
|
@@ -41,8 +41,8 @@ export declare class UserService implements UserRepository {
|
|
|
41
41
|
getUserById(id: string): Promise<UserData | null>;
|
|
42
42
|
getUserByEmail(email: string): Promise<UserData | null>;
|
|
43
43
|
getUserByIdentity(provider: string, providerId: string): Promise<UserData | null>;
|
|
44
|
-
getUserIdentities(
|
|
45
|
-
linkUserIdentity(
|
|
44
|
+
getUserIdentities(uid: string): Promise<UserIdentityData[]>;
|
|
45
|
+
linkUserIdentity(uid: string, provider: string, providerId: string, profileData?: Record<string, unknown>): Promise<void>;
|
|
46
46
|
updateUser(id: string, data: Partial<Omit<CreateUserData, "id">>): Promise<UserData | null>;
|
|
47
47
|
deleteUser(id: string): Promise<void>;
|
|
48
48
|
listUsers(): Promise<UserData[]>;
|
|
@@ -66,23 +66,23 @@ export declare class UserService implements UserRepository {
|
|
|
66
66
|
/**
|
|
67
67
|
* Get roles for a user from database (inline TEXT[] column)
|
|
68
68
|
*/
|
|
69
|
-
getUserRoles(
|
|
69
|
+
getUserRoles(uid: string): Promise<Role[]>;
|
|
70
70
|
/**
|
|
71
71
|
* Get role IDs for a user
|
|
72
72
|
*/
|
|
73
|
-
getUserRoleIds(
|
|
73
|
+
getUserRoleIds(uid: string): Promise<string[]>;
|
|
74
74
|
/**
|
|
75
75
|
* Set roles for a user (replaces existing roles)
|
|
76
76
|
*/
|
|
77
|
-
setUserRoles(
|
|
77
|
+
setUserRoles(uid: string, roleIds: string[]): Promise<void>;
|
|
78
78
|
/**
|
|
79
79
|
* Assign a specific role to new user (appends if not present)
|
|
80
80
|
*/
|
|
81
|
-
assignDefaultRole(
|
|
81
|
+
assignDefaultRole(uid: string, roleId: string): Promise<void>;
|
|
82
82
|
/**
|
|
83
83
|
* Get user with their roles
|
|
84
84
|
*/
|
|
85
|
-
getUserWithRoles(
|
|
85
|
+
getUserWithRoles(uid: string): Promise<{
|
|
86
86
|
user: UserData;
|
|
87
87
|
roles: Role[];
|
|
88
88
|
} | null>;
|
|
@@ -90,13 +90,42 @@ export declare class UserService implements UserRepository {
|
|
|
90
90
|
export declare class RefreshTokenService {
|
|
91
91
|
private db;
|
|
92
92
|
private refreshTokensTable;
|
|
93
|
+
private usersTable;
|
|
93
94
|
constructor(db: NodePgDatabase, tableOrTables?: RebasePgTable | Partial<AuthSchemaTables>);
|
|
94
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Whether the table actually carries a column, so a host application that
|
|
97
|
+
* supplied its own `refresh_tokens` table — one that predates session
|
|
98
|
+
* grouping — degrades instead of throwing on every sign-in.
|
|
99
|
+
*/
|
|
100
|
+
private has;
|
|
101
|
+
private col;
|
|
102
|
+
/** The columns to read back, narrowed to the ones this table has. */
|
|
103
|
+
private selection;
|
|
104
|
+
createToken(uid: string, tokenHash: string, expiresAt: Date, userAgent?: string, ipAddress?: string, session?: RefreshTokenSession): Promise<void>;
|
|
95
105
|
findByHash(tokenHash: string): Promise<RefreshTokenInfo | null>;
|
|
106
|
+
/**
|
|
107
|
+
* Record that a token was rotated away, keeping the row.
|
|
108
|
+
*
|
|
109
|
+
* The row is what lets `/auth/refresh` distinguish "you already used this,
|
|
110
|
+
* here is a fresh one" from "no idea what this is". Deleting it — which is
|
|
111
|
+
* what this used to do — collapsed both into a 401 and signed the user out
|
|
112
|
+
* for the crime of losing a response.
|
|
113
|
+
*/
|
|
114
|
+
markRotated(tokenHash: string): Promise<void>;
|
|
115
|
+
/** Final kill of one sign-in: logout, or revoking a device remotely. */
|
|
116
|
+
revokeSession(sessionId: string): Promise<void>;
|
|
117
|
+
/**
|
|
118
|
+
* Housekeeping: rotation would otherwise leave a row per refresh forever.
|
|
119
|
+
* Superseded rows are only needed for as long as a straggler might still
|
|
120
|
+
* present them, and expired ones are dead weight everywhere.
|
|
121
|
+
*/
|
|
122
|
+
prune(uid: string, sessionId: string, supersededBefore: Date): Promise<void>;
|
|
123
|
+
getTokensValidAfter(uid: string): Promise<Date | null>;
|
|
124
|
+
setTokensValidAfter(uid: string, at: Date): Promise<void>;
|
|
96
125
|
deleteByHash(tokenHash: string): Promise<void>;
|
|
97
|
-
deleteAllForUser(
|
|
98
|
-
listForUser(
|
|
99
|
-
deleteById(id: string,
|
|
126
|
+
deleteAllForUser(uid: string): Promise<void>;
|
|
127
|
+
listForUser(uid: string): Promise<RefreshTokenInfo[]>;
|
|
128
|
+
deleteById(id: string, uid: string): Promise<void>;
|
|
100
129
|
}
|
|
101
130
|
/**
|
|
102
131
|
* Password reset token service
|
|
@@ -109,12 +138,12 @@ export declare class PasswordResetTokenService {
|
|
|
109
138
|
/**
|
|
110
139
|
* Create a password reset token
|
|
111
140
|
*/
|
|
112
|
-
createToken(
|
|
141
|
+
createToken(uid: string, tokenHash: string, expiresAt: Date): Promise<void>;
|
|
113
142
|
/**
|
|
114
143
|
* Find a valid (not expired, not used) token by hash
|
|
115
144
|
*/
|
|
116
145
|
findValidByHash(tokenHash: string): Promise<{
|
|
117
|
-
|
|
146
|
+
uid: string;
|
|
118
147
|
expiresAt: Date;
|
|
119
148
|
} | null>;
|
|
120
149
|
/**
|
|
@@ -124,7 +153,7 @@ export declare class PasswordResetTokenService {
|
|
|
124
153
|
/**
|
|
125
154
|
* Delete all tokens for a user
|
|
126
155
|
*/
|
|
127
|
-
deleteAllForUser(
|
|
156
|
+
deleteAllForUser(uid: string): Promise<void>;
|
|
128
157
|
/**
|
|
129
158
|
* Clean up expired tokens
|
|
130
159
|
*/
|
|
@@ -139,7 +168,7 @@ export declare class MagicLinkTokenService {
|
|
|
139
168
|
private magicLinkTokensTable;
|
|
140
169
|
constructor(db: NodePgDatabase, tableOrTables?: RebasePgTable | Partial<AuthSchemaTables>);
|
|
141
170
|
private getQualifiedTableName;
|
|
142
|
-
createToken(
|
|
171
|
+
createToken(uid: string, tokenHash: string, expiresAt: Date): Promise<void>;
|
|
143
172
|
findValidByHash(tokenHash: string): Promise<MagicLinkTokenInfo | null>;
|
|
144
173
|
markAsUsed(tokenHash: string): Promise<void>;
|
|
145
174
|
}
|
|
@@ -153,18 +182,23 @@ export declare class PostgresTokenRepository implements TokenRepository {
|
|
|
153
182
|
private passwordResetTokenService;
|
|
154
183
|
private magicLinkTokenService;
|
|
155
184
|
constructor(db: NodePgDatabase, tableOrTables?: RebasePgTable | Partial<AuthSchemaTables>);
|
|
156
|
-
createRefreshToken(
|
|
185
|
+
createRefreshToken(uid: string, tokenHash: string, expiresAt: Date, userAgent?: string, ipAddress?: string, session?: RefreshTokenSession): Promise<void>;
|
|
186
|
+
markRefreshTokenRotated(tokenHash: string): Promise<void>;
|
|
187
|
+
revokeRefreshTokenSession(sessionId: string): Promise<void>;
|
|
188
|
+
pruneRefreshTokens(uid: string, sessionId: string, supersededBefore: Date): Promise<void>;
|
|
189
|
+
getTokensValidAfter(uid: string): Promise<Date | null>;
|
|
190
|
+
setTokensValidAfter(uid: string, at: Date): Promise<void>;
|
|
157
191
|
findRefreshTokenByHash(tokenHash: string): Promise<RefreshTokenInfo | null>;
|
|
158
192
|
deleteRefreshToken(tokenHash: string): Promise<void>;
|
|
159
|
-
deleteAllRefreshTokensForUser(
|
|
160
|
-
listRefreshTokensForUser(
|
|
161
|
-
deleteRefreshTokenById(id: string,
|
|
162
|
-
createPasswordResetToken(
|
|
193
|
+
deleteAllRefreshTokensForUser(uid: string): Promise<void>;
|
|
194
|
+
listRefreshTokensForUser(uid: string): Promise<RefreshTokenInfo[]>;
|
|
195
|
+
deleteRefreshTokenById(id: string, uid: string): Promise<void>;
|
|
196
|
+
createPasswordResetToken(uid: string, tokenHash: string, expiresAt: Date): Promise<void>;
|
|
163
197
|
findValidPasswordResetToken(tokenHash: string): Promise<PasswordResetTokenInfo | null>;
|
|
164
198
|
markPasswordResetTokenUsed(tokenHash: string): Promise<void>;
|
|
165
|
-
deleteAllPasswordResetTokensForUser(
|
|
199
|
+
deleteAllPasswordResetTokensForUser(uid: string): Promise<void>;
|
|
166
200
|
deleteExpiredTokens(): Promise<void>;
|
|
167
|
-
createMagicLinkToken(
|
|
201
|
+
createMagicLinkToken(uid: string, tokenHash: string, expiresAt: Date): Promise<void>;
|
|
168
202
|
findValidMagicLinkToken(tokenHash: string): Promise<MagicLinkTokenInfo | null>;
|
|
169
203
|
markMagicLinkTokenUsed(tokenHash: string): Promise<void>;
|
|
170
204
|
}
|
|
@@ -182,8 +216,8 @@ export declare class PostgresAuthRepository implements AuthRepository {
|
|
|
182
216
|
getUserById(id: string): Promise<UserData | null>;
|
|
183
217
|
getUserByEmail(email: string): Promise<UserData | null>;
|
|
184
218
|
getUserByIdentity(provider: string, providerId: string): Promise<UserData | null>;
|
|
185
|
-
getUserIdentities(
|
|
186
|
-
linkUserIdentity(
|
|
219
|
+
getUserIdentities(uid: string): Promise<UserIdentityData[]>;
|
|
220
|
+
linkUserIdentity(uid: string, provider: string, providerId: string, profileData?: Record<string, unknown>): Promise<void>;
|
|
187
221
|
updateUser(id: string, data: Partial<Omit<CreateUserData, "id">>): Promise<UserData | null>;
|
|
188
222
|
deleteUser(id: string): Promise<void>;
|
|
189
223
|
listUsers(): Promise<UserData[]>;
|
|
@@ -192,11 +226,11 @@ export declare class PostgresAuthRepository implements AuthRepository {
|
|
|
192
226
|
setEmailVerified(id: string, verified: boolean): Promise<void>;
|
|
193
227
|
setVerificationToken(id: string, token: string | null): Promise<void>;
|
|
194
228
|
getUserByVerificationToken(token: string): Promise<UserData | null>;
|
|
195
|
-
getUserRoles(
|
|
196
|
-
getUserRoleIds(
|
|
197
|
-
setUserRoles(
|
|
198
|
-
assignDefaultRole(
|
|
199
|
-
getUserWithRoles(
|
|
229
|
+
getUserRoles(uid: string): Promise<RoleData[]>;
|
|
230
|
+
getUserRoleIds(uid: string): Promise<string[]>;
|
|
231
|
+
setUserRoles(uid: string, roleIds: string[]): Promise<void>;
|
|
232
|
+
assignDefaultRole(uid: string, roleId: string): Promise<void>;
|
|
233
|
+
getUserWithRoles(uid: string): Promise<{
|
|
200
234
|
user: UserData;
|
|
201
235
|
roles: RoleData[];
|
|
202
236
|
} | null>;
|
|
@@ -205,37 +239,42 @@ export declare class PostgresAuthRepository implements AuthRepository {
|
|
|
205
239
|
createRole(_data: CreateRoleData): Promise<RoleData>;
|
|
206
240
|
updateRole(id: string, data: Partial<Omit<RoleData, "id">>): Promise<RoleData | null>;
|
|
207
241
|
deleteRole(_id: string): Promise<void>;
|
|
208
|
-
createRefreshToken(
|
|
242
|
+
createRefreshToken(uid: string, tokenHash: string, expiresAt: Date, userAgent?: string, ipAddress?: string, session?: RefreshTokenSession): Promise<void>;
|
|
243
|
+
markRefreshTokenRotated(tokenHash: string): Promise<void>;
|
|
244
|
+
revokeRefreshTokenSession(sessionId: string): Promise<void>;
|
|
245
|
+
pruneRefreshTokens(uid: string, sessionId: string, supersededBefore: Date): Promise<void>;
|
|
246
|
+
getTokensValidAfter(uid: string): Promise<Date | null>;
|
|
247
|
+
setTokensValidAfter(uid: string, at: Date): Promise<void>;
|
|
209
248
|
findRefreshTokenByHash(tokenHash: string): Promise<RefreshTokenInfo | null>;
|
|
210
249
|
deleteRefreshToken(tokenHash: string): Promise<void>;
|
|
211
|
-
deleteAllRefreshTokensForUser(
|
|
212
|
-
listRefreshTokensForUser(
|
|
213
|
-
deleteRefreshTokenById(id: string,
|
|
214
|
-
createPasswordResetToken(
|
|
250
|
+
deleteAllRefreshTokensForUser(uid: string): Promise<void>;
|
|
251
|
+
listRefreshTokensForUser(uid: string): Promise<RefreshTokenInfo[]>;
|
|
252
|
+
deleteRefreshTokenById(id: string, uid: string): Promise<void>;
|
|
253
|
+
createPasswordResetToken(uid: string, tokenHash: string, expiresAt: Date): Promise<void>;
|
|
215
254
|
findValidPasswordResetToken(tokenHash: string): Promise<PasswordResetTokenInfo | null>;
|
|
216
255
|
markPasswordResetTokenUsed(tokenHash: string): Promise<void>;
|
|
217
|
-
deleteAllPasswordResetTokensForUser(
|
|
256
|
+
deleteAllPasswordResetTokensForUser(uid: string): Promise<void>;
|
|
218
257
|
deleteExpiredTokens(): Promise<void>;
|
|
219
|
-
createMagicLinkToken(
|
|
258
|
+
createMagicLinkToken(uid: string, tokenHash: string, expiresAt: Date): Promise<void>;
|
|
220
259
|
findValidMagicLinkToken(tokenHash: string): Promise<MagicLinkTokenInfo | null>;
|
|
221
260
|
markMagicLinkTokenUsed(tokenHash: string): Promise<void>;
|
|
222
261
|
private _mfaService;
|
|
223
262
|
private getMfaService;
|
|
224
|
-
createMfaFactor(
|
|
225
|
-
getMfaFactors(
|
|
263
|
+
createMfaFactor(uid: string, factorType: "totp", secretEncrypted: string, friendlyName?: string): Promise<MfaFactor>;
|
|
264
|
+
getMfaFactors(uid: string): Promise<MfaFactor[]>;
|
|
226
265
|
getMfaFactorById(factorId: string): Promise<(MfaFactor & {
|
|
227
266
|
secretEncrypted: string;
|
|
228
267
|
}) | null>;
|
|
229
268
|
verifyMfaFactor(factorId: string): Promise<void>;
|
|
230
|
-
deleteMfaFactor(factorId: string,
|
|
269
|
+
deleteMfaFactor(factorId: string, uid: string): Promise<void>;
|
|
231
270
|
createMfaChallenge(factorId: string, ipAddress?: string): Promise<MfaChallengeInfo>;
|
|
232
271
|
getMfaChallengeById(challengeId: string): Promise<MfaChallengeInfo | null>;
|
|
233
272
|
verifyMfaChallenge(challengeId: string): Promise<void>;
|
|
234
|
-
createRecoveryCodes(
|
|
235
|
-
useRecoveryCode(
|
|
236
|
-
getUnusedRecoveryCodeCount(
|
|
237
|
-
deleteAllRecoveryCodes(
|
|
238
|
-
hasVerifiedMfaFactors(
|
|
273
|
+
createRecoveryCodes(uid: string, codeHashes: string[]): Promise<void>;
|
|
274
|
+
useRecoveryCode(uid: string, codeHash: string): Promise<boolean>;
|
|
275
|
+
getUnusedRecoveryCodeCount(uid: string): Promise<number>;
|
|
276
|
+
deleteAllRecoveryCodes(uid: string): Promise<void>;
|
|
277
|
+
hasVerifiedMfaFactors(uid: string): Promise<boolean>;
|
|
239
278
|
}
|
|
240
279
|
/**
|
|
241
280
|
* PostgreSQL implementation of MfaRepository.
|
|
@@ -246,21 +285,21 @@ export declare class MfaService implements MfaRepository {
|
|
|
246
285
|
private schemaName;
|
|
247
286
|
constructor(db: NodePgDatabase, schemaName?: string);
|
|
248
287
|
private qualify;
|
|
249
|
-
createMfaFactor(
|
|
250
|
-
getMfaFactors(
|
|
288
|
+
createMfaFactor(uid: string, factorType: "totp", secretEncrypted: string, friendlyName?: string): Promise<MfaFactor>;
|
|
289
|
+
getMfaFactors(uid: string): Promise<MfaFactor[]>;
|
|
251
290
|
getMfaFactorById(factorId: string): Promise<(MfaFactor & {
|
|
252
291
|
secretEncrypted: string;
|
|
253
292
|
}) | null>;
|
|
254
293
|
verifyMfaFactor(factorId: string): Promise<void>;
|
|
255
|
-
deleteMfaFactor(factorId: string,
|
|
294
|
+
deleteMfaFactor(factorId: string, uid: string): Promise<void>;
|
|
256
295
|
createMfaChallenge(factorId: string, ipAddress?: string): Promise<MfaChallengeInfo>;
|
|
257
296
|
getMfaChallengeById(challengeId: string): Promise<MfaChallengeInfo | null>;
|
|
258
297
|
verifyMfaChallenge(challengeId: string): Promise<void>;
|
|
259
|
-
createRecoveryCodes(
|
|
260
|
-
useRecoveryCode(
|
|
261
|
-
getUnusedRecoveryCodeCount(
|
|
262
|
-
deleteAllRecoveryCodes(
|
|
263
|
-
hasVerifiedMfaFactors(
|
|
298
|
+
createRecoveryCodes(uid: string, codeHashes: string[]): Promise<void>;
|
|
299
|
+
useRecoveryCode(uid: string, codeHash: string): Promise<boolean>;
|
|
300
|
+
getUnusedRecoveryCodeCount(uid: string): Promise<number>;
|
|
301
|
+
deleteAllRecoveryCodes(uid: string): Promise<void>;
|
|
302
|
+
hasVerifiedMfaFactors(uid: string): Promise<boolean>;
|
|
264
303
|
}
|
|
265
304
|
/** PostgreSQL user repository implementation */
|
|
266
305
|
export type PostgresUserRepository = UserService;
|