@yielded/auth-persistence-drizzle 0.1.0-beta.22 → 0.1.0-beta.24
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 +3 -0
- package/dist/D1.d.mts +11 -11
- package/dist/D1.mjs +2 -1
- package/dist/D1.mjs.map +1 -1
- package/dist/Libsql.d.mts +40 -56
- package/dist/Libsql.mjs +2 -1
- package/dist/Libsql.mjs.map +1 -1
- package/dist/Mysql2.d.mts +16 -17
- package/dist/Pglite.d.mts +18 -18
- package/dist/Pglite.mjs +2 -1
- package/dist/Pglite.mjs.map +1 -1
- package/dist/Postgres.d.mts +24 -24
- package/dist/Postgres.mjs +2 -1
- package/dist/Postgres.mjs.map +1 -1
- package/dist/SqliteBun.d.mts +39 -55
- package/dist/SqliteBun.mjs +2 -1
- package/dist/SqliteBun.mjs.map +1 -1
- package/dist/SqliteDo.d.mts +48 -64
- package/dist/SqliteDo.mjs +2 -1
- package/dist/SqliteDo.mjs.map +1 -1
- package/dist/SqliteNode.d.mts +45 -61
- package/dist/SqliteNode.mjs +2 -1
- package/dist/SqliteNode.mjs.map +1 -1
- package/dist/SqliteWasm.d.mts +48 -64
- package/dist/SqliteWasm.mjs +2 -1
- package/dist/SqliteWasm.mjs.map +1 -1
- package/dist/drizzle/crypto.mjs +1 -1
- package/dist/drizzle/d1-emails.d.mts +1 -1
- package/dist/drizzle/d1-oauth.d.mts +14 -14
- package/dist/drizzle/d1-passkey.d.mts +1 -1
- package/dist/drizzle/d1-password-prepared.d.mts +4 -4
- package/dist/drizzle/d1-password-prepared.mjs.map +1 -1
- package/dist/drizzle/d1-passwords.d.mts +18 -35
- package/dist/drizzle/d1-passwords.mjs +78 -290
- package/dist/drizzle/d1-passwords.mjs.map +1 -1
- package/dist/drizzle/d1-phone.d.mts +1 -1
- package/dist/drizzle/d1-proofs.d.mts +2 -2
- package/dist/drizzle/d1-sessions.d.mts +3 -3
- package/dist/drizzle/d1-sessions.mjs +11 -6
- package/dist/drizzle/d1-sessions.mjs.map +1 -1
- package/dist/drizzle/d1-totp.d.mts +1 -1
- package/dist/drizzle/mysql-password-prepared.d.mts +5 -5
- package/dist/drizzle/mysql-password-prepared.mjs.map +1 -1
- package/dist/drizzle/mysql-passwords.d.mts +16 -32
- package/dist/drizzle/mysql-passwords.mjs.map +1 -1
- package/dist/drizzle/mysql-sessions.d.mts +1 -1
- package/dist/drizzle/native-sql-table.mjs +135 -0
- package/dist/drizzle/native-sql-table.mjs.map +1 -0
- package/dist/drizzle/oauth-connected-model.d.mts +20 -281
- package/dist/drizzle/oauth-connected-model.mjs +3 -17
- package/dist/drizzle/oauth-connected-model.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-reference.d.mts +1 -3
- package/dist/drizzle/oauth-connected-reference.mjs +4 -53
- package/dist/drizzle/oauth-connected-reference.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-target.d.mts +3 -990
- package/dist/drizzle/oauth-connected-target.mjs +8 -92
- package/dist/drizzle/oauth-connected-target.mjs.map +1 -1
- package/dist/drizzle/oauth-kernel.mjs +11 -0
- package/dist/drizzle/oauth-kernel.mjs.map +1 -0
- package/dist/drizzle/oauth-model.d.mts +35 -438
- package/dist/drizzle/oauth-model.mjs +6 -44
- package/dist/drizzle/oauth-model.mjs.map +1 -1
- package/dist/drizzle/oauth-mysql.mjs +2 -2
- package/dist/drizzle/oauth-mysql.mjs.map +1 -1
- package/dist/drizzle/oauth-proxy.d.mts +10 -0
- package/dist/drizzle/oauth-proxy.mjs +54 -0
- package/dist/drizzle/oauth-proxy.mjs.map +1 -0
- package/dist/drizzle/oauth-target.d.mts +6 -107
- package/dist/drizzle/oauth-target.mjs +15 -245
- package/dist/drizzle/oauth-target.mjs.map +1 -1
- package/dist/drizzle/password-model.d.mts +5 -8
- package/dist/drizzle/password-prepared-model.d.mts +5 -5
- package/dist/drizzle/password-prepared-model.mjs.map +1 -1
- package/dist/drizzle/password-prepared-state.mjs +1 -1
- package/dist/drizzle/password-sql.mjs +2 -1
- package/dist/drizzle/password-sql.mjs.map +1 -1
- package/dist/drizzle/password-target.mjs +13 -2
- package/dist/drizzle/password-target.mjs.map +1 -1
- package/dist/drizzle/pg-password-prepared.d.mts +5 -5
- package/dist/drizzle/pg-password-prepared.mjs.map +1 -1
- package/dist/drizzle/pg-passwords.d.mts +16 -32
- package/dist/drizzle/pg-passwords.mjs.map +1 -1
- package/dist/drizzle/pg-sessions.d.mts +1 -1
- package/dist/drizzle/phone-target.d.mts +2 -2
- package/dist/drizzle/phone-target.mjs +1 -1
- package/dist/drizzle/query-operations.mjs +3 -1
- package/dist/drizzle/query-operations.mjs.map +1 -1
- package/dist/drizzle/session-sql.mjs +2 -1
- package/dist/drizzle/session-sql.mjs.map +1 -1
- package/dist/drizzle/sqlite-password-prepared.mjs.map +1 -1
- package/dist/drizzle/sqlite-passwords.mjs.map +1 -1
- package/dist/drizzle/storage-validation.mjs +10 -198
- package/dist/drizzle/storage-validation.mjs.map +1 -1
- package/dist/drizzle/totp-target.d.mts +3 -3
- package/dist/drizzle/totp-target.mjs +2 -2
- package/dist/drizzle/transaction-execution.d.mts +2 -2
- package/dist/drizzle/transaction-owner.d.mts +1 -2
- package/dist/index.d.mts +3 -2
- package/dist/internal/drizzle-postgres-oauth-proxy.d.mts +138 -0
- package/dist/internal/drizzle-postgres-oauth-proxy.mjs +29 -0
- package/dist/internal/drizzle-postgres-oauth-proxy.mjs.map +1 -0
- package/dist/internal/drizzle-postgres.mjs +2 -0
- package/dist/internal/drizzle-postgres.mjs.map +1 -1
- package/dist/internal/drizzle-sqlite-oauth-proxy.d.mts +146 -0
- package/dist/internal/drizzle-sqlite-oauth-proxy.mjs +29 -0
- package/dist/internal/drizzle-sqlite-oauth-proxy.mjs.map +1 -0
- package/dist/internal/drizzle-sqlite.mjs +2 -0
- package/dist/internal/drizzle-sqlite.mjs.map +1 -1
- package/package.json +1 -1
- package/src/D1.ts +2 -0
- package/src/Libsql.ts +2 -0
- package/src/Pglite.ts +2 -0
- package/src/Postgres.ts +2 -0
- package/src/SqliteBun.ts +2 -0
- package/src/SqliteDo.ts +2 -0
- package/src/SqliteNode.ts +2 -0
- package/src/SqliteWasm.ts +2 -0
- package/src/drizzle/d1-password-prepared.ts +2 -23
- package/src/drizzle/d1-passwords.ts +158 -780
- package/src/drizzle/d1-sessions.ts +21 -6
- package/src/drizzle/mysql-password-prepared.ts +4 -16
- package/src/drizzle/mysql-passwords.ts +5 -20
- package/src/drizzle/native-sql-table.ts +259 -0
- package/src/drizzle/oauth-connected-model.ts +97 -315
- package/src/drizzle/oauth-connected-reference.ts +13 -93
- package/src/drizzle/oauth-connected-target.ts +14 -271
- package/src/drizzle/oauth-kernel.ts +10 -0
- package/src/drizzle/oauth-model.ts +188 -541
- package/src/drizzle/oauth-mysql.ts +2 -2
- package/src/drizzle/oauth-proxy.ts +101 -0
- package/src/drizzle/oauth-target.ts +33 -737
- package/src/drizzle/password-model.ts +0 -33
- package/src/drizzle/password-prepared-model.ts +0 -18
- package/src/drizzle/password-sql.ts +3 -0
- package/src/drizzle/password-target.ts +41 -4
- package/src/drizzle/pg-password-prepared.ts +4 -16
- package/src/drizzle/pg-passwords.ts +5 -20
- package/src/drizzle/query-operations.ts +4 -0
- package/src/drizzle/session-sql.ts +2 -1
- package/src/drizzle/sqlite-password-prepared.ts +4 -52
- package/src/drizzle/sqlite-passwords.ts +7 -28
- package/src/drizzle/storage-validation.ts +13 -222
- package/src/index.ts +2 -8
- package/src/internal/drizzle-postgres-oauth-proxy.ts +37 -0
- package/src/internal/drizzle-postgres.ts +2 -0
- package/src/internal/drizzle-sqlite-oauth-proxy.ts +44 -0
- package/src/internal/drizzle-sqlite.ts +2 -0
- package/dist/_virtual/_rolldown/runtime.mjs +0 -13
- package/dist/drizzle/oauth-accounts.mjs +0 -359
- package/dist/drizzle/oauth-accounts.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-access.mjs +0 -212
- package/dist/drizzle/oauth-connected-access.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-collection.mjs +0 -202
- package/dist/drizzle/oauth-connected-collection.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-custody.mjs +0 -147
- package/dist/drizzle/oauth-connected-custody.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-flow.mjs +0 -297
- package/dist/drizzle/oauth-connected-flow.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-input.mjs +0 -122
- package/dist/drizzle/oauth-connected-input.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-maintenance.mjs +0 -214
- package/dist/drizzle/oauth-connected-maintenance.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-management.mjs +0 -229
- package/dist/drizzle/oauth-connected-management.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-settlement.mjs +0 -128
- package/dist/drizzle/oauth-connected-settlement.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-sign-in.mjs +0 -265
- package/dist/drizzle/oauth-connected-sign-in.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-state.d.mts +0 -2062
- package/dist/drizzle/oauth-connected-state.mjs +0 -430
- package/dist/drizzle/oauth-connected-state.mjs.map +0 -1
- package/dist/drizzle/oauth-flow.d.mts +0 -22
- package/dist/drizzle/oauth-flow.mjs +0 -253
- package/dist/drizzle/oauth-flow.mjs.map +0 -1
- package/dist/drizzle/oauth-input.mjs +0 -127
- package/dist/drizzle/oauth-input.mjs.map +0 -1
- package/dist/drizzle/oauth-owner.d.mts +0 -10
- package/dist/drizzle/oauth-owner.mjs +0 -10
- package/dist/drizzle/oauth-owner.mjs.map +0 -1
- package/dist/drizzle/oauth-registration.d.mts +0 -5
- package/dist/drizzle/oauth-registration.mjs +0 -374
- package/dist/drizzle/oauth-registration.mjs.map +0 -1
- package/dist/drizzle/oauth-state.mjs +0 -107
- package/dist/drizzle/oauth-state.mjs.map +0 -1
- package/src/drizzle/oauth-accounts.ts +0 -805
- package/src/drizzle/oauth-connected-access.ts +0 -361
- package/src/drizzle/oauth-connected-collection.ts +0 -324
- package/src/drizzle/oauth-connected-custody.ts +0 -279
- package/src/drizzle/oauth-connected-flow.ts +0 -529
- package/src/drizzle/oauth-connected-input.ts +0 -147
- package/src/drizzle/oauth-connected-maintenance.ts +0 -346
- package/src/drizzle/oauth-connected-management.ts +0 -365
- package/src/drizzle/oauth-connected-settlement.ts +0 -251
- package/src/drizzle/oauth-connected-sign-in.ts +0 -443
- package/src/drizzle/oauth-connected-state.ts +0 -872
- package/src/drizzle/oauth-flow.ts +0 -462
- package/src/drizzle/oauth-input.ts +0 -201
- package/src/drizzle/oauth-owner.ts +0 -29
- package/src/drizzle/oauth-registration.ts +0 -640
- package/src/drizzle/oauth-state.ts +0 -218
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/* oxlint-disable no-explicit-any -- D1 plans bridge consumer-owned Drizzle rows and SQL statements. */
|
|
2
2
|
import type { D1Client } from "@effect/sql-d1/D1Client";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
NativeDatabase,
|
|
5
|
+
requireStandalone,
|
|
6
|
+
samePasswordCredentialSnapshot as sameSnapshot,
|
|
7
|
+
} from "@yielded/auth-persistence/Adapter";
|
|
4
8
|
import {
|
|
5
9
|
coordinateCommit,
|
|
6
10
|
CurrentCommitJournal,
|
|
@@ -12,6 +16,7 @@ import {
|
|
|
12
16
|
} from "@yielded/auth/Hooks";
|
|
13
17
|
import type { LoginIdentifier } from "@yielded/auth/Identity";
|
|
14
18
|
import {
|
|
19
|
+
EncodedPasswordHash,
|
|
15
20
|
PasswordUnavailable,
|
|
16
21
|
PasswordPersistence,
|
|
17
22
|
type PasswordMutationInput,
|
|
@@ -20,10 +25,7 @@ import {
|
|
|
20
25
|
snapshotPasswordRequirement,
|
|
21
26
|
snapshotPasswordRevision,
|
|
22
27
|
type PasswordAction,
|
|
23
|
-
type PasswordAttemptDecision,
|
|
24
|
-
type PasswordCredentialSnapshot,
|
|
25
28
|
type PasswordMutationDecision,
|
|
26
|
-
type PasswordAttemptPolicy,
|
|
27
29
|
} from "@yielded/auth/Password";
|
|
28
30
|
import { reportPersistenceFailure } from "@yielded/auth/Persistence";
|
|
29
31
|
import {
|
|
@@ -40,18 +42,14 @@ import {
|
|
|
40
42
|
} from "@yielded/auth/Sessions";
|
|
41
43
|
import {
|
|
42
44
|
and,
|
|
43
|
-
count,
|
|
44
45
|
eq,
|
|
45
|
-
|
|
46
|
+
getTableColumns,
|
|
46
47
|
inArray,
|
|
47
|
-
lte,
|
|
48
|
-
notExists,
|
|
49
48
|
sql,
|
|
50
49
|
type AnyRelations,
|
|
51
50
|
type SQL,
|
|
52
51
|
type Table,
|
|
53
52
|
} from "drizzle-orm";
|
|
54
|
-
import type { EffectDrizzleQueryError } from "drizzle-orm/effect-core";
|
|
55
53
|
import type { EffectSQLiteD1Database } from "drizzle-orm/effect-d1";
|
|
56
54
|
import type { AnySQLiteTable } from "drizzle-orm/sqlite-core";
|
|
57
55
|
import { Cause, DateTime, Effect, Option, Predicate, Redacted, Schema, Context } from "effect";
|
|
@@ -67,10 +65,7 @@ import { nativeDatabase } from "./native-database";
|
|
|
67
65
|
import {
|
|
68
66
|
type AnyPasswordRegistrationMapping,
|
|
69
67
|
type D1PasswordPersistenceMapping,
|
|
70
|
-
type PasswordAttemptRecord,
|
|
71
|
-
type PasswordRateScopeKind,
|
|
72
68
|
type PasswordRegistrationMapping,
|
|
73
|
-
type PasswordScopeKeys,
|
|
74
69
|
requiredPasswordConstraints,
|
|
75
70
|
requiredPasswordRegistrationConstraints,
|
|
76
71
|
} from "./password-model";
|
|
@@ -85,24 +80,14 @@ type PlanPrepare<Method extends (...args: any[]) => any, A> = (
|
|
|
85
80
|
) => PreparedCommit<A>;
|
|
86
81
|
|
|
87
82
|
type Database = EffectSQLiteD1Database<AnyRelations> & { readonly $client: D1Client };
|
|
88
|
-
type Mapping = D1PasswordPersistenceMapping<
|
|
89
|
-
Table,
|
|
90
|
-
Table,
|
|
91
|
-
Table,
|
|
92
|
-
Table,
|
|
93
|
-
Table,
|
|
94
|
-
Table,
|
|
95
|
-
Table,
|
|
96
|
-
Table,
|
|
97
|
-
unknown
|
|
98
|
-
>;
|
|
83
|
+
type Mapping = D1PasswordPersistenceMapping<Table, Table, Table, Table, Table, unknown>;
|
|
99
84
|
type RegistrationMapping<Registration> = AnyPasswordRegistrationMapping<Registration>;
|
|
100
|
-
type AdapterFailure = PersistenceMappingError | EffectDrizzleQueryError;
|
|
101
|
-
const mapAdapter = <A>(effect: Effect.Effect<A, AdapterFailure>) => effect;
|
|
102
85
|
|
|
103
86
|
interface Planned<A> {
|
|
104
87
|
readonly receipt: A;
|
|
105
88
|
readonly statements: ReadonlyArray<Statement<any>>;
|
|
89
|
+
/** Final-state guards without `changes()`, repeated after coordinated statements. */
|
|
90
|
+
readonly postconditions?: ReadonlyArray<Statement<any>>;
|
|
106
91
|
readonly retryable?: (cause: unknown) => boolean;
|
|
107
92
|
readonly journalGuard?: PreparedCommit<void>;
|
|
108
93
|
}
|
|
@@ -209,11 +194,6 @@ const readEngineNowMillis = Effect.fn("Drizzle.readEngineNowMillis")(function* (
|
|
|
209
194
|
);
|
|
210
195
|
});
|
|
211
196
|
|
|
212
|
-
const driverValues = (values: object, entries: ReadonlyArray<readonly [string, unknown]>) => ({
|
|
213
|
-
...values,
|
|
214
|
-
...Object.fromEntries(entries),
|
|
215
|
-
});
|
|
216
|
-
|
|
217
197
|
const allocate = <A>(
|
|
218
198
|
asyncValue: Effect.Effect<A, PersistenceMappingError> | undefined,
|
|
219
199
|
syncValue: (() => A) | undefined,
|
|
@@ -269,44 +249,6 @@ const authorityColumns = (mapping: Mapping) => ({
|
|
|
269
249
|
: column(mapping.authorityCredential.table, mapping.authorityCredential.status),
|
|
270
250
|
});
|
|
271
251
|
|
|
272
|
-
const attemptColumns = (mapping: Mapping) => ({
|
|
273
|
-
moduleId: column(mapping.attempt.table, mapping.attempt.moduleId),
|
|
274
|
-
action: column(mapping.attempt.table, mapping.attempt.action),
|
|
275
|
-
attemptId: column(mapping.attempt.table, mapping.attempt.attemptId),
|
|
276
|
-
identifierNamespace: column(mapping.attempt.table, mapping.attempt.identifierNamespace),
|
|
277
|
-
identifierValue: column(mapping.attempt.table, mapping.attempt.identifierValue),
|
|
278
|
-
subjectId: column(mapping.attempt.table, mapping.attempt.subjectId),
|
|
279
|
-
credentialId: column(mapping.attempt.table, mapping.attempt.credentialId),
|
|
280
|
-
securityRevision: column(mapping.attempt.table, mapping.attempt.securityRevision),
|
|
281
|
-
credentialRevision: column(mapping.attempt.table, mapping.attempt.credentialRevision),
|
|
282
|
-
verifierVersion: column(mapping.attempt.table, mapping.attempt.verifierVersion),
|
|
283
|
-
identifierBindingRevision: column(
|
|
284
|
-
mapping.attempt.table,
|
|
285
|
-
mapping.attempt.identifierBindingRevision,
|
|
286
|
-
),
|
|
287
|
-
admittedAt: column(mapping.attempt.table, mapping.attempt.admittedAt),
|
|
288
|
-
deadline: column(mapping.attempt.table, mapping.attempt.deadline),
|
|
289
|
-
retentionUntil: column(mapping.attempt.table, mapping.attempt.retentionUntil),
|
|
290
|
-
state: column(mapping.attempt.table, mapping.attempt.state),
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
const scopeColumns = (mapping: Mapping) => ({
|
|
294
|
-
moduleId: column(mapping.rateScope.table, mapping.rateScope.moduleId),
|
|
295
|
-
action: column(mapping.rateScope.table, mapping.rateScope.action),
|
|
296
|
-
scopeKind: column(mapping.rateScope.table, mapping.rateScope.scopeKind),
|
|
297
|
-
scopeKey: column(mapping.rateScope.table, mapping.rateScope.scopeKey),
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
const chargeColumns = (mapping: Mapping) => ({
|
|
301
|
-
moduleId: column(mapping.charge.table, mapping.charge.moduleId),
|
|
302
|
-
action: column(mapping.charge.table, mapping.charge.action),
|
|
303
|
-
scopeKind: column(mapping.charge.table, mapping.charge.scopeKind),
|
|
304
|
-
scopeKey: column(mapping.charge.table, mapping.charge.scopeKey),
|
|
305
|
-
attemptId: column(mapping.charge.table, mapping.charge.attemptId),
|
|
306
|
-
occurredAt: column(mapping.charge.table, mapping.charge.occurredAt),
|
|
307
|
-
retentionUntil: column(mapping.charge.table, mapping.charge.retentionUntil),
|
|
308
|
-
});
|
|
309
|
-
|
|
310
252
|
const commandColumns = (mapping: Mapping) => ({
|
|
311
253
|
moduleId: column(mapping.command.table, mapping.command.moduleId),
|
|
312
254
|
commandId: column(mapping.command.table, mapping.command.commandId),
|
|
@@ -360,14 +302,6 @@ const readCredentialNative = Effect.fn("Drizzle.readCredentialNative")(function*
|
|
|
360
302
|
.limit(1);
|
|
361
303
|
});
|
|
362
304
|
|
|
363
|
-
interface Resolved {
|
|
364
|
-
readonly nativeSubjectId: unknown;
|
|
365
|
-
readonly subject: any;
|
|
366
|
-
readonly identifier: any;
|
|
367
|
-
readonly credential?: any;
|
|
368
|
-
readonly snapshot?: PasswordCredentialSnapshot;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
305
|
const resolveCredential = Effect.fn("DrizzleD1Password.resolveCredential")(function* (
|
|
372
306
|
mapping: Mapping,
|
|
373
307
|
moduleId: string,
|
|
@@ -396,137 +330,6 @@ const resolveCredential = Effect.fn("DrizzleD1Password.resolveCredential")(funct
|
|
|
396
330
|
return { nativeSubjectId, subject, identifier: identifierRow, credential, snapshot };
|
|
397
331
|
});
|
|
398
332
|
|
|
399
|
-
interface ScopeEntry {
|
|
400
|
-
readonly kind: PasswordRateScopeKind;
|
|
401
|
-
readonly key: string;
|
|
402
|
-
readonly limit: number;
|
|
403
|
-
readonly windowMillis: number;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
const scopeEntries = (keys: PasswordScopeKeys, policy: PasswordAttemptPolicy) => {
|
|
407
|
-
const entries: ScopeEntry[] = [
|
|
408
|
-
{ kind: "action", key: keys.action, ...policy.action },
|
|
409
|
-
{ kind: "identifier", key: keys.identifier, ...policy.identifier },
|
|
410
|
-
];
|
|
411
|
-
|
|
412
|
-
if (keys.subject !== undefined)
|
|
413
|
-
entries.push({ kind: "subject", key: keys.subject, ...policy.subject });
|
|
414
|
-
|
|
415
|
-
return entries;
|
|
416
|
-
};
|
|
417
|
-
|
|
418
|
-
const livePendingAttempts = (
|
|
419
|
-
mapping: Mapping,
|
|
420
|
-
moduleId: string,
|
|
421
|
-
action: "sign-in" | "change",
|
|
422
|
-
entry: ScopeEntry,
|
|
423
|
-
identifier: LoginIdentifier,
|
|
424
|
-
nativeSubjectId: unknown | undefined,
|
|
425
|
-
activeAt: unknown,
|
|
426
|
-
) => {
|
|
427
|
-
const a = attemptColumns(mapping);
|
|
428
|
-
|
|
429
|
-
return and(
|
|
430
|
-
entry.kind === "action"
|
|
431
|
-
? and(eq(a.moduleId, moduleId), eq(a.action, action))
|
|
432
|
-
: entry.kind === "identifier"
|
|
433
|
-
? and(
|
|
434
|
-
eq(a.moduleId, moduleId),
|
|
435
|
-
eq(a.action, action),
|
|
436
|
-
eq(a.identifierNamespace, identifier.namespace),
|
|
437
|
-
eq(a.identifierValue, identifier.value),
|
|
438
|
-
)
|
|
439
|
-
: and(eq(a.moduleId, moduleId), eq(a.action, action), eq(a.subjectId, nativeSubjectId)),
|
|
440
|
-
eq(a.state, "pending"),
|
|
441
|
-
sql`${a.retentionUntil} > ${activeAt}`,
|
|
442
|
-
);
|
|
443
|
-
};
|
|
444
|
-
|
|
445
|
-
const scopeAdmissionCondition = (
|
|
446
|
-
mapping: Mapping,
|
|
447
|
-
moduleId: string,
|
|
448
|
-
action: "sign-in" | "change",
|
|
449
|
-
entry: ScopeEntry,
|
|
450
|
-
policy: PasswordAttemptPolicy,
|
|
451
|
-
identifier: LoginIdentifier,
|
|
452
|
-
nativeSubjectId: unknown | undefined,
|
|
453
|
-
) => {
|
|
454
|
-
const c = chargeColumns(mapping);
|
|
455
|
-
|
|
456
|
-
const pending = livePendingAttempts(
|
|
457
|
-
mapping,
|
|
458
|
-
moduleId,
|
|
459
|
-
action,
|
|
460
|
-
entry,
|
|
461
|
-
identifier,
|
|
462
|
-
nativeSubjectId,
|
|
463
|
-
mapping.d1.engineNow,
|
|
464
|
-
);
|
|
465
|
-
|
|
466
|
-
return sql`(select count(*) from ${mapping.charge.table} where ${c.moduleId} = ${sql.param(moduleId, c.moduleId)} and ${c.action} = ${sql.param(action, c.action)} and ${c.scopeKind} = ${sql.param(entry.kind, c.scopeKind)} and ${c.scopeKey} = ${sql.param(entry.key, c.scopeKey)} and ${c.occurredAt} >= ${mapping.d1.engineInstantMinus(entry.windowMillis)}) < ${entry.limit} and (select count(*) from ${mapping.attempt.table} where ${pending}) < ${policy.maximumPending}`;
|
|
467
|
-
};
|
|
468
|
-
|
|
469
|
-
const readScopeAdmission = Effect.fn("DrizzleD1Password.readScopeAdmission")(function* (
|
|
470
|
-
mapping: Mapping,
|
|
471
|
-
moduleId: string,
|
|
472
|
-
action: "sign-in" | "change",
|
|
473
|
-
entries: ReadonlyArray<ScopeEntry>,
|
|
474
|
-
policy: PasswordAttemptPolicy,
|
|
475
|
-
identifier: LoginIdentifier,
|
|
476
|
-
nativeSubjectId: unknown | undefined,
|
|
477
|
-
now: number,
|
|
478
|
-
) {
|
|
479
|
-
const database = yield* CurrentD1PlanningDatabase;
|
|
480
|
-
|
|
481
|
-
const c = chargeColumns(mapping);
|
|
482
|
-
const admitted: ScopeEntry[] = [];
|
|
483
|
-
|
|
484
|
-
for (let index = 0; index < entries.length; index++) {
|
|
485
|
-
const entry = entries[index]!;
|
|
486
|
-
|
|
487
|
-
const chargeRows = yield* mapAdapter(
|
|
488
|
-
database
|
|
489
|
-
.select({ total: count() })
|
|
490
|
-
.from(mapping.charge.table)
|
|
491
|
-
.where(
|
|
492
|
-
and(
|
|
493
|
-
eq(c.moduleId, moduleId),
|
|
494
|
-
eq(c.action, action),
|
|
495
|
-
eq(c.scopeKind, entry.kind),
|
|
496
|
-
eq(c.scopeKey, entry.key),
|
|
497
|
-
gte(c.occurredAt, mapping.encodeInstant(now - entry.windowMillis)),
|
|
498
|
-
),
|
|
499
|
-
),
|
|
500
|
-
);
|
|
501
|
-
|
|
502
|
-
const pendingRows = yield* mapAdapter(
|
|
503
|
-
database
|
|
504
|
-
.select({ total: count() })
|
|
505
|
-
.from(mapping.attempt.table)
|
|
506
|
-
.where(
|
|
507
|
-
livePendingAttempts(
|
|
508
|
-
mapping,
|
|
509
|
-
moduleId,
|
|
510
|
-
action,
|
|
511
|
-
entry,
|
|
512
|
-
identifier,
|
|
513
|
-
nativeSubjectId,
|
|
514
|
-
mapping.encodeInstant(now),
|
|
515
|
-
),
|
|
516
|
-
),
|
|
517
|
-
);
|
|
518
|
-
|
|
519
|
-
const admittedHere =
|
|
520
|
-
Number(chargeRows[0]?.total ?? 0) < entry.limit &&
|
|
521
|
-
Number(pendingRows[0]?.total ?? 0) < policy.maximumPending;
|
|
522
|
-
|
|
523
|
-
if (admittedHere) admitted.push(entry);
|
|
524
|
-
else if (index === 0) break;
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
return admitted;
|
|
528
|
-
});
|
|
529
|
-
|
|
530
333
|
const evidenceProofsJson = Schema.encodeSync(
|
|
531
334
|
Schema.fromJsonString(AuthenticationEvidence.fields.proofs),
|
|
532
335
|
);
|
|
@@ -555,25 +358,6 @@ const assuranceCondition = (
|
|
|
555
358
|
const sameIdentifier = (left: LoginIdentifier, right: LoginIdentifier) =>
|
|
556
359
|
left.namespace === right.namespace && left.value === right.value;
|
|
557
360
|
|
|
558
|
-
const sameSnapshot = (left: PasswordCredentialSnapshot, right: PasswordCredentialSnapshot) =>
|
|
559
|
-
left.moduleId === right.moduleId &&
|
|
560
|
-
left.revision.subjectId === right.revision.subjectId &&
|
|
561
|
-
left.revision.securityRevision === right.revision.securityRevision &&
|
|
562
|
-
left.credentialId === right.credentialId &&
|
|
563
|
-
left.credentialRevision === right.credentialRevision &&
|
|
564
|
-
left.verifierVersion === right.verifierVersion &&
|
|
565
|
-
left.normalization === right.normalization &&
|
|
566
|
-
left.identifierVerifiedAtMillis === right.identifierVerifiedAtMillis &&
|
|
567
|
-
left.revision.credentials.length === right.revision.credentials.length &&
|
|
568
|
-
left.revision.credentials.every((entry) =>
|
|
569
|
-
right.revision.credentials.some(
|
|
570
|
-
(other) => other.credentialId === entry.credentialId && other.revision === entry.revision,
|
|
571
|
-
),
|
|
572
|
-
) &&
|
|
573
|
-
left.identifierBindingRevision === right.identifierBindingRevision &&
|
|
574
|
-
sameIdentifier(left.identifier, right.identifier) &&
|
|
575
|
-
Redacted.value(left.verifier) === Redacted.value(right.verifier);
|
|
576
|
-
|
|
577
361
|
const evidenceSatisfiedAt = (
|
|
578
362
|
evidence: PasswordMutationInput["authorization"]["evidence"],
|
|
579
363
|
requirement: PasswordMutationInput["authorization"]["requirement"],
|
|
@@ -928,34 +712,6 @@ const credentialCurrentCondition = (
|
|
|
928
712
|
: sql`exists(select 1 from ${mapping.credential.table} where ${c.moduleId} = ${sql.param(input.moduleId, c.moduleId)} and ${c.subjectId} = ${sql.param(nativeSubjectId, c.subjectId)} and ${c.credentialId} = ${sql.param(input.credential.credentialId, c.credentialId)} and ${c.credentialRevision} = ${sql.param(input.credential.credentialRevision, c.credentialRevision)} and ${c.verifierVersion} = ${sql.param(input.credential.verifierVersion, c.verifierVersion)} and ${c.verifier} = ${sql.param(Redacted.value(input.credential.verifier), c.verifier)} and ${c.normalization} = ${sql.param(input.credential.normalization, c.normalization)})`;
|
|
929
713
|
};
|
|
930
714
|
|
|
931
|
-
const admittedSnapshotCondition = (
|
|
932
|
-
mapping: Mapping,
|
|
933
|
-
resolved: Resolved | undefined,
|
|
934
|
-
moduleId: string,
|
|
935
|
-
) => {
|
|
936
|
-
const snapshot = resolved?.snapshot;
|
|
937
|
-
|
|
938
|
-
if (snapshot === undefined || resolved === undefined) return sql`true`;
|
|
939
|
-
const s = subjectColumns(mapping);
|
|
940
|
-
const i = identifierColumns(mapping);
|
|
941
|
-
const c = credentialColumns(mapping);
|
|
942
|
-
const ac = authorityColumns(mapping);
|
|
943
|
-
|
|
944
|
-
return and(
|
|
945
|
-
sql`exists(select 1 from ${mapping.subject.table} where ${s.id} = ${sql.param(resolved.nativeSubjectId, s.id)} and ${s.status} = ${sql.param(mapping.subject.d1ActiveStatusValue, s.status)} and ${s.securityRevision} = ${sql.param(snapshot.revision.securityRevision, s.securityRevision)})`,
|
|
946
|
-
mapping.identifier.d1CurrentCondition({
|
|
947
|
-
identifier: snapshot.identifier,
|
|
948
|
-
nativeSubjectId: resolved.nativeSubjectId,
|
|
949
|
-
}),
|
|
950
|
-
sql`exists(select 1 from ${mapping.identifier.table} where ${i.namespace} = ${sql.param(snapshot.identifier.namespace, i.namespace)} and ${i.value} = ${sql.param(snapshot.identifier.value, i.value)} and ${i.subjectId} = ${sql.param(resolved.nativeSubjectId, i.subjectId)} and ${i.bindingRevision} = ${sql.param(snapshot.identifierBindingRevision, i.bindingRevision)})`,
|
|
951
|
-
sql`exists(select 1 from ${mapping.credential.table} where ${c.moduleId} = ${sql.param(moduleId, c.moduleId)} and ${c.subjectId} = ${sql.param(resolved.nativeSubjectId, c.subjectId)} and ${c.credentialId} = ${sql.param(snapshot.credentialId, c.credentialId)} and ${c.credentialRevision} = ${sql.param(snapshot.credentialRevision, c.credentialRevision)} and ${c.verifierVersion} = ${sql.param(snapshot.verifierVersion, c.verifierVersion)} and ${c.verifier} = ${sql.param(Redacted.value(snapshot.verifier), c.verifier)} and ${c.normalization} = ${sql.param(snapshot.normalization, c.normalization)})`,
|
|
952
|
-
...snapshot.revision.credentials.map(
|
|
953
|
-
(item) =>
|
|
954
|
-
sql`exists(select 1 from ${mapping.authorityCredential.table} where ${ac.subjectId} = ${sql.param(resolved.nativeSubjectId, ac.subjectId)} and ${ac.credentialId} = ${sql.param(item.credentialId, ac.credentialId)} and ${ac.revision} = ${sql.param(item.revision, ac.revision)}${ac.status === undefined ? sql`` : sql` and ${ac.status} = ${sql.param(mapping.authorityCredential.d1ActiveStatusValue, ac.status)}`})`,
|
|
955
|
-
),
|
|
956
|
-
)!;
|
|
957
|
-
};
|
|
958
|
-
|
|
959
715
|
const mutationStatements = Effect.fn(function* (
|
|
960
716
|
mapping: Mapping,
|
|
961
717
|
input: PasswordMutationInput,
|
|
@@ -1150,6 +906,7 @@ const compileAddMutation = Effect.fn("DrizzleD1Password.compileAddMutation")(fun
|
|
|
1150
906
|
return {
|
|
1151
907
|
statements,
|
|
1152
908
|
appliedCondition,
|
|
909
|
+
marker,
|
|
1153
910
|
retryable: (cause: unknown) => isGuardFailure(cause, marker),
|
|
1154
911
|
};
|
|
1155
912
|
});
|
|
@@ -1179,357 +936,121 @@ const makePasswordPlans = (
|
|
|
1179
936
|
});
|
|
1180
937
|
|
|
1181
938
|
return {
|
|
1182
|
-
|
|
1183
|
-
input: Parameters<PasswordPersistence["Service"]["admitAttempt"]>[0],
|
|
1184
|
-
prepare: PlanPrepare<PasswordPersistence["Service"]["admitAttempt"], A>,
|
|
1185
|
-
) =>
|
|
939
|
+
findCredential: (uncaptured: Parameters<PasswordPersistence["Service"]["findCredential"]>[0]) =>
|
|
1186
940
|
Effect.gen(function* () {
|
|
941
|
+
if (!validConstraints(mapping)) return yield* unavailable();
|
|
942
|
+
const input = { ...uncaptured, identifier: { ...uncaptured.identifier } };
|
|
1187
943
|
const database = yield* CurrentD1PlanningDatabase;
|
|
944
|
+
const identifierRow = (yield* readIdentifier(mapping, input.identifier))[0];
|
|
1188
945
|
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
)
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
input.action,
|
|
1219
|
-
scopes,
|
|
1220
|
-
input.policy,
|
|
1221
|
-
input.identifier,
|
|
1222
|
-
resolved?.nativeSubjectId,
|
|
1223
|
-
now,
|
|
1224
|
-
);
|
|
1225
|
-
|
|
1226
|
-
const allAdmitted = admitted.length === scopes.length;
|
|
1227
|
-
const considered = admitted.length === 0 ? scopes.slice(0, 1) : scopes;
|
|
1228
|
-
|
|
1229
|
-
const receipt = prepare(
|
|
1230
|
-
allAdmitted
|
|
1231
|
-
? {
|
|
1232
|
-
_tag: "Admitted" as const,
|
|
1233
|
-
attemptId,
|
|
1234
|
-
...(resolved?.snapshot === undefined ? {} : { credential: resolved.snapshot }),
|
|
1235
|
-
}
|
|
1236
|
-
: { _tag: "Denied" as const },
|
|
1237
|
-
journal,
|
|
1238
|
-
);
|
|
1239
|
-
|
|
1240
|
-
const marker = `effect-auth-password-guard:admit:${attemptId}`;
|
|
1241
|
-
const statements: Statement<any>[] = [];
|
|
946
|
+
if (identifierRow === undefined || !mapping.identifier.isCurrent(identifierRow))
|
|
947
|
+
return Option.none();
|
|
948
|
+
const nativeId = identifierRow[mapping.identifier.subjectId];
|
|
949
|
+
|
|
950
|
+
const sc = subjectColumns(mapping),
|
|
951
|
+
ic = identifierColumns(mapping),
|
|
952
|
+
cc = credentialColumns(mapping);
|
|
953
|
+
|
|
954
|
+
// Bind the same native ID through each column's codec, then inspect one coherent snapshot.
|
|
955
|
+
const rows = yield* database
|
|
956
|
+
.select({
|
|
957
|
+
subject: getTableColumns(mapping.subject.table),
|
|
958
|
+
identifier: getTableColumns(mapping.identifier.table),
|
|
959
|
+
credential: getTableColumns(mapping.credential.table),
|
|
960
|
+
})
|
|
961
|
+
.from(mapping.subject.table)
|
|
962
|
+
.innerJoin(
|
|
963
|
+
mapping.identifier.table,
|
|
964
|
+
and(
|
|
965
|
+
eq(ic.namespace, input.identifier.namespace),
|
|
966
|
+
eq(ic.value, input.identifier.value),
|
|
967
|
+
eq(ic.subjectId, nativeId),
|
|
968
|
+
),
|
|
969
|
+
)
|
|
970
|
+
.innerJoin(
|
|
971
|
+
mapping.credential.table,
|
|
972
|
+
and(eq(cc.moduleId, input.moduleId), eq(cc.subjectId, nativeId)),
|
|
973
|
+
)
|
|
974
|
+
.where(eq(sc.id, nativeId));
|
|
1242
975
|
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
yield* statement(
|
|
1246
|
-
database
|
|
1247
|
-
.insert(mapping.rateScope.table)
|
|
1248
|
-
.values(
|
|
1249
|
-
mapping.rateScope.encodeInsert({
|
|
1250
|
-
moduleId: input.moduleId,
|
|
1251
|
-
action: input.action,
|
|
1252
|
-
scopeKind: entry.kind,
|
|
1253
|
-
scopeKey: entry.key,
|
|
1254
|
-
}),
|
|
1255
|
-
)
|
|
1256
|
-
.onConflictDoNothing(),
|
|
1257
|
-
),
|
|
1258
|
-
);
|
|
1259
|
-
}
|
|
976
|
+
if (rows.length !== 1) return Option.none();
|
|
977
|
+
const row = rows[0]!;
|
|
1260
978
|
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
resolved?.nativeSubjectId,
|
|
1270
|
-
);
|
|
979
|
+
if (
|
|
980
|
+
!mapping.subject.isActiveStatus(row.subject[mapping.subject.status]) ||
|
|
981
|
+
!mapping.identifier.isCurrent(row.identifier) ||
|
|
982
|
+
!mapping.subjectId.equals(nativeId, row.subject[mapping.subject.id]) ||
|
|
983
|
+
!mapping.subjectId.equals(nativeId, row.identifier[mapping.identifier.subjectId]) ||
|
|
984
|
+
!mapping.subjectId.equals(nativeId, row.credential[mapping.credential.subjectId])
|
|
985
|
+
)
|
|
986
|
+
return Option.none();
|
|
1271
987
|
|
|
1272
|
-
|
|
1273
|
-
|
|
988
|
+
const credential = yield* mapping.credential
|
|
989
|
+
.decode({ moduleId: input.moduleId, ...row })
|
|
990
|
+
.pipe(Effect.flatMap(snapshotPasswordCredential));
|
|
1274
991
|
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
...conditions,
|
|
1279
|
-
...(allAdmitted
|
|
1280
|
-
? [admittedSnapshotCondition(mapping, resolved, input.moduleId)]
|
|
1281
|
-
: []),
|
|
1282
|
-
)!,
|
|
1283
|
-
marker,
|
|
1284
|
-
),
|
|
1285
|
-
);
|
|
1286
|
-
for (const entry of admitted)
|
|
1287
|
-
statements.push(
|
|
1288
|
-
yield* statement(
|
|
1289
|
-
database.insert(mapping.charge.table).values(
|
|
1290
|
-
driverValues(
|
|
1291
|
-
mapping.charge.encodeInsert({
|
|
1292
|
-
moduleId: input.moduleId,
|
|
1293
|
-
action: input.action,
|
|
1294
|
-
scopeKind: entry.kind,
|
|
1295
|
-
scopeKey: entry.key,
|
|
1296
|
-
attemptId,
|
|
1297
|
-
occurredAtMillis: now,
|
|
1298
|
-
retentionUntilMillis: now + entry.windowMillis,
|
|
1299
|
-
}),
|
|
1300
|
-
[
|
|
1301
|
-
[mapping.charge.occurredAt, mapping.d1.engineNow],
|
|
1302
|
-
[
|
|
1303
|
-
mapping.charge.retentionUntil,
|
|
1304
|
-
mapping.d1.engineInstantPlus(entry.windowMillis),
|
|
1305
|
-
],
|
|
1306
|
-
],
|
|
1307
|
-
),
|
|
1308
|
-
),
|
|
1309
|
-
),
|
|
1310
|
-
);
|
|
1311
|
-
if (allAdmitted) {
|
|
1312
|
-
const snapshot = resolved?.snapshot;
|
|
1313
|
-
|
|
1314
|
-
const record: PasswordAttemptRecord = {
|
|
1315
|
-
moduleId: input.moduleId,
|
|
1316
|
-
action: input.action,
|
|
1317
|
-
attemptId,
|
|
1318
|
-
identifier: input.identifier,
|
|
1319
|
-
...(snapshot === undefined
|
|
1320
|
-
? {}
|
|
1321
|
-
: {
|
|
1322
|
-
subjectId: snapshot.revision.subjectId,
|
|
1323
|
-
credentialId: snapshot.credentialId,
|
|
1324
|
-
securityRevision: snapshot.revision.securityRevision,
|
|
1325
|
-
credentialRevision: snapshot.credentialRevision,
|
|
1326
|
-
verifierVersion: snapshot.verifierVersion,
|
|
1327
|
-
identifierBindingRevision: snapshot.identifierBindingRevision,
|
|
1328
|
-
}),
|
|
1329
|
-
admittedAtMillis: now,
|
|
1330
|
-
deadlineMillis: now + input.policy.attemptLifetimeMillis,
|
|
1331
|
-
retentionUntilMillis: Math.max(
|
|
1332
|
-
now + input.policy.attemptLifetimeMillis,
|
|
1333
|
-
...scopes.map((entry) => now + entry.windowMillis),
|
|
1334
|
-
),
|
|
1335
|
-
};
|
|
1336
|
-
|
|
1337
|
-
statements.push(
|
|
1338
|
-
yield* statement(
|
|
1339
|
-
database.insert(mapping.attempt.table).values(
|
|
1340
|
-
driverValues(
|
|
1341
|
-
mapping.attempt.encodeInsert(record, {
|
|
1342
|
-
...(resolved?.nativeSubjectId === undefined
|
|
1343
|
-
? {}
|
|
1344
|
-
: { nativeSubjectId: resolved.nativeSubjectId }),
|
|
1345
|
-
state: "pending",
|
|
1346
|
-
}),
|
|
1347
|
-
[
|
|
1348
|
-
[mapping.attempt.admittedAt, mapping.d1.engineNow],
|
|
1349
|
-
[
|
|
1350
|
-
mapping.attempt.deadline,
|
|
1351
|
-
mapping.d1.engineInstantPlus(input.policy.attemptLifetimeMillis),
|
|
1352
|
-
],
|
|
1353
|
-
[
|
|
1354
|
-
mapping.attempt.retentionUntil,
|
|
1355
|
-
mapping.d1.engineInstantPlus(
|
|
1356
|
-
Math.max(
|
|
1357
|
-
input.policy.attemptLifetimeMillis,
|
|
1358
|
-
...scopes.map((entry) => entry.windowMillis),
|
|
1359
|
-
),
|
|
1360
|
-
),
|
|
1361
|
-
],
|
|
1362
|
-
],
|
|
1363
|
-
),
|
|
1364
|
-
),
|
|
1365
|
-
),
|
|
1366
|
-
);
|
|
1367
|
-
}
|
|
1368
|
-
|
|
1369
|
-
return {
|
|
1370
|
-
receipt,
|
|
1371
|
-
statements,
|
|
1372
|
-
retryable: (cause: unknown) => isGuardFailure(cause, marker),
|
|
1373
|
-
};
|
|
1374
|
-
}),
|
|
1375
|
-
);
|
|
992
|
+
return input.subjectId !== undefined && credential.revision.subjectId !== input.subjectId
|
|
993
|
+
? Option.none()
|
|
994
|
+
: Option.some(credential);
|
|
1376
995
|
}),
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
const captured =
|
|
1385
|
-
uncaptured.captured === undefined
|
|
1386
|
-
? undefined
|
|
1387
|
-
: yield* snapshotPasswordCredential(uncaptured.captured);
|
|
1388
|
-
|
|
1389
|
-
const input = { ...uncaptured, ...(captured === undefined ? {} : { captured }) };
|
|
1390
|
-
|
|
1391
|
-
return yield* run(
|
|
1392
|
-
Effect.gen(function* () {
|
|
1393
|
-
const journal = yield* CurrentCommitJournal;
|
|
1394
|
-
|
|
1395
|
-
const a = attemptColumns(mapping);
|
|
996
|
+
rehashIfCurrent: (input: Parameters<PasswordPersistence["Service"]["rehashIfCurrent"]>[0]) =>
|
|
997
|
+
run(
|
|
998
|
+
Effect.gen(function* () {
|
|
999
|
+
const nextVerifier = Redacted.make(
|
|
1000
|
+
yield* Schema.decodeEffect(EncodedPasswordHash)(Redacted.value(input.nextVerifier)),
|
|
1001
|
+
);
|
|
1396
1002
|
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
.limit(1);
|
|
1003
|
+
const credential = yield* snapshotPasswordCredential(input.credential);
|
|
1004
|
+
const database = yield* CurrentD1PlanningDatabase;
|
|
1005
|
+
const nativeId = yield* mapping.subjectId.toNative(credential.revision.subjectId);
|
|
1006
|
+
const version = yield* allocate(mapping.allocateRevision, mapping.allocateRevisionSync);
|
|
1402
1007
|
|
|
1403
|
-
|
|
1404
|
-
|
|
1008
|
+
if (version === credential.verifierVersion) return yield* unavailable();
|
|
1009
|
+
const encoded = mapping.credential.encodeVerifier(nextVerifier, version);
|
|
1405
1010
|
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1011
|
+
const values = {
|
|
1012
|
+
[mapping.credential.verifier]: encoded[mapping.credential.verifier],
|
|
1013
|
+
[mapping.credential.verifierVersion]: encoded[mapping.credential.verifierVersion],
|
|
1014
|
+
};
|
|
1410
1015
|
|
|
1411
|
-
|
|
1412
|
-
|
|
1016
|
+
if (Object.values(values).some((value) => value === undefined))
|
|
1017
|
+
return yield* unavailable();
|
|
1018
|
+
const c = credentialColumns(mapping);
|
|
1413
1019
|
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
input.outcome === "verified" &&
|
|
1418
|
-
input.captured !== undefined &&
|
|
1419
|
-
deadline !== undefined &&
|
|
1420
|
-
deadline > engineNow
|
|
1421
|
-
) {
|
|
1422
|
-
resolved = yield* resolveCredential(
|
|
1423
|
-
mapping,
|
|
1424
|
-
input.moduleId,
|
|
1425
|
-
input.captured.identifier,
|
|
1426
|
-
input.captured.revision.subjectId,
|
|
1427
|
-
);
|
|
1428
|
-
verified =
|
|
1429
|
-
input.captured.moduleId === input.moduleId &&
|
|
1430
|
-
resolved?.snapshot !== undefined &&
|
|
1431
|
-
sameSnapshot(resolved.snapshot, input.captured) &&
|
|
1432
|
-
mapping.subjectId.equals(
|
|
1433
|
-
row[mapping.attempt.subjectId],
|
|
1434
|
-
resolved.nativeSubjectId,
|
|
1435
|
-
) &&
|
|
1436
|
-
row[mapping.attempt.identifierNamespace] === input.captured.identifier.namespace &&
|
|
1437
|
-
row[mapping.attempt.identifierValue] === input.captured.identifier.value &&
|
|
1438
|
-
row[mapping.attempt.credentialId] === input.captured.credentialId &&
|
|
1439
|
-
row[mapping.attempt.securityRevision] ===
|
|
1440
|
-
input.captured.revision.securityRevision &&
|
|
1441
|
-
row[mapping.attempt.credentialRevision] === input.captured.credentialRevision &&
|
|
1442
|
-
row[mapping.attempt.verifierVersion] === input.captured.verifierVersion &&
|
|
1443
|
-
row[mapping.attempt.identifierBindingRevision] ===
|
|
1444
|
-
input.captured.identifierBindingRevision;
|
|
1445
|
-
}
|
|
1446
|
-
const decision: PasswordAttemptDecision = verified ? "verified" : "rejected";
|
|
1447
|
-
const receipt = prepare(decision, journal);
|
|
1448
|
-
|
|
1449
|
-
if (row === undefined || row[mapping.attempt.state] !== "pending")
|
|
1450
|
-
return { receipt, statements: [] };
|
|
1451
|
-
const marker = `effect-auth-password-guard:settle:${input.attemptId}`;
|
|
1452
|
-
|
|
1453
|
-
const base = and(
|
|
1454
|
-
eq(a.moduleId, input.moduleId),
|
|
1455
|
-
eq(a.attemptId, input.attemptId),
|
|
1456
|
-
eq(a.state, "pending"),
|
|
1457
|
-
)!;
|
|
1458
|
-
|
|
1459
|
-
const condition = verified
|
|
1460
|
-
? and(base, sql`${a.deadline} > ${mapping.d1.engineNow}`)!
|
|
1461
|
-
: base;
|
|
1462
|
-
|
|
1463
|
-
const statements: Statement<any>[] = [
|
|
1464
|
-
yield* assertion(
|
|
1465
|
-
sql`exists(select 1 from ${mapping.attempt.table} where ${condition})`,
|
|
1466
|
-
marker,
|
|
1467
|
-
),
|
|
1020
|
+
return {
|
|
1021
|
+
receipt: undefined,
|
|
1022
|
+
statements: [
|
|
1468
1023
|
yield* statement(
|
|
1469
1024
|
database
|
|
1470
|
-
.update(mapping.
|
|
1471
|
-
.set(
|
|
1472
|
-
.where(
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
statements.splice(1, 0, yield* assertion(authority, marker));
|
|
1493
|
-
if (
|
|
1494
|
-
input.rehash !== undefined &&
|
|
1495
|
-
input.rehash.expectedVersion === captured.verifierVersion &&
|
|
1496
|
-
Redacted.value(input.rehash.expectedVerifier) === Redacted.value(captured.verifier)
|
|
1497
|
-
) {
|
|
1498
|
-
const nextVersion = yield* allocate(
|
|
1499
|
-
mapping.allocateRevision,
|
|
1500
|
-
mapping.allocateRevisionSync,
|
|
1501
|
-
);
|
|
1502
|
-
|
|
1503
|
-
statements.push(
|
|
1504
|
-
yield* statement(
|
|
1505
|
-
database
|
|
1506
|
-
.update(mapping.credential.table)
|
|
1507
|
-
.set(
|
|
1508
|
-
mapping.credential.encodeVerifier(input.rehash.nextVerifier, nextVersion),
|
|
1509
|
-
)
|
|
1510
|
-
.where(
|
|
1511
|
-
and(
|
|
1512
|
-
eq(c.moduleId, input.moduleId),
|
|
1513
|
-
eq(c.subjectId, resolved.nativeSubjectId),
|
|
1514
|
-
eq(c.credentialId, captured.credentialId),
|
|
1515
|
-
eq(c.credentialRevision, captured.credentialRevision),
|
|
1516
|
-
eq(c.verifierVersion, input.rehash.expectedVersion),
|
|
1517
|
-
eq(c.verifier, Redacted.value(input.rehash.expectedVerifier)),
|
|
1518
|
-
),
|
|
1025
|
+
.update(mapping.credential.table)
|
|
1026
|
+
.set(values)
|
|
1027
|
+
.where(
|
|
1028
|
+
and(
|
|
1029
|
+
eq(c.moduleId, credential.moduleId),
|
|
1030
|
+
eq(c.subjectId, nativeId),
|
|
1031
|
+
eq(c.credentialId, credential.credentialId),
|
|
1032
|
+
...(
|
|
1033
|
+
[
|
|
1034
|
+
[c.moduleId, credential.moduleId],
|
|
1035
|
+
[c.subjectId, nativeId],
|
|
1036
|
+
[c.credentialId, credential.credentialId],
|
|
1037
|
+
[c.credentialRevision, credential.credentialRevision],
|
|
1038
|
+
[c.verifierVersion, credential.verifierVersion],
|
|
1039
|
+
[c.verifier, Redacted.value(credential.verifier)],
|
|
1040
|
+
[c.normalization, credential.normalization],
|
|
1041
|
+
] as const
|
|
1042
|
+
).map(([column, value]) =>
|
|
1043
|
+
typeof value === "string"
|
|
1044
|
+
? sql`cast(${column} as blob) = cast(${sql.param(value, column)} as blob)`
|
|
1045
|
+
: eq(column, value),
|
|
1519
1046
|
),
|
|
1047
|
+
),
|
|
1520
1048
|
),
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
receipt,
|
|
1527
|
-
statements,
|
|
1528
|
-
retryable: (cause: unknown) => isGuardFailure(cause, marker),
|
|
1529
|
-
};
|
|
1530
|
-
}),
|
|
1531
|
-
);
|
|
1532
|
-
}),
|
|
1049
|
+
),
|
|
1050
|
+
],
|
|
1051
|
+
};
|
|
1052
|
+
}),
|
|
1053
|
+
),
|
|
1533
1054
|
readForSubject: (input: Parameters<PasswordPersistence["Service"]["readForSubject"]>[0]) =>
|
|
1534
1055
|
Effect.gen(function* () {
|
|
1535
1056
|
const database = yield* CurrentD1PlanningDatabase;
|
|
@@ -1619,10 +1140,14 @@ const makePasswordPlans = (
|
|
|
1619
1140
|
nextSecurityRevision,
|
|
1620
1141
|
});
|
|
1621
1142
|
|
|
1143
|
+
if (compiled === undefined)
|
|
1144
|
+
return { receipt: prepare("rejected", journal), statements: [] };
|
|
1145
|
+
|
|
1622
1146
|
return {
|
|
1623
|
-
receipt: prepare(
|
|
1624
|
-
statements: compiled
|
|
1625
|
-
|
|
1147
|
+
receipt: prepare("changed", journal),
|
|
1148
|
+
statements: compiled.statements,
|
|
1149
|
+
postconditions: [yield* assertion(compiled.appliedCondition, compiled.marker)],
|
|
1150
|
+
retryable: compiled.retryable,
|
|
1626
1151
|
};
|
|
1627
1152
|
}),
|
|
1628
1153
|
);
|
|
@@ -1683,15 +1208,6 @@ const makePasswordPlans = (
|
|
|
1683
1208
|
"reset-password",
|
|
1684
1209
|
),
|
|
1685
1210
|
),
|
|
1686
|
-
cleanupAttempts: <A>(
|
|
1687
|
-
input: Parameters<PasswordPersistence["Service"]["cleanupAttempts"]>[0],
|
|
1688
|
-
prepare: PlanPrepare<PasswordPersistence["Service"]["cleanupAttempts"], A>,
|
|
1689
|
-
) =>
|
|
1690
|
-
run(
|
|
1691
|
-
Effect.gen(function* () {
|
|
1692
|
-
return yield* cleanupPlan(mapping, input, prepare);
|
|
1693
|
-
}),
|
|
1694
|
-
),
|
|
1695
1211
|
};
|
|
1696
1212
|
};
|
|
1697
1213
|
|
|
@@ -1826,6 +1342,7 @@ const replacementPlan = Effect.fn("Drizzle.replacementPlan")(function* <A>(
|
|
|
1826
1342
|
return {
|
|
1827
1343
|
receipt: passwordReceipt ?? prepare("rejected", journal),
|
|
1828
1344
|
statements: compiled.statements,
|
|
1345
|
+
...(compiled.postconditions === undefined ? {} : { postconditions: compiled.postconditions }),
|
|
1829
1346
|
retryable: (cause: unknown) =>
|
|
1830
1347
|
isGuardFailure(cause, marker) ||
|
|
1831
1348
|
isGuardFailure(
|
|
@@ -1839,159 +1356,12 @@ const replacementPlan = Effect.fn("Drizzle.replacementPlan")(function* <A>(
|
|
|
1839
1356
|
};
|
|
1840
1357
|
}
|
|
1841
1358
|
|
|
1842
|
-
|
|
1843
|
-
receipt: prepare("changed", journal),
|
|
1844
|
-
statements: [
|
|
1845
|
-
...protectedMutation.statements,
|
|
1846
|
-
yield* assertion(protectedMutation.appliedCondition, marker),
|
|
1847
|
-
],
|
|
1848
|
-
retryable: (cause: unknown) => isGuardFailure(cause, marker),
|
|
1849
|
-
};
|
|
1850
|
-
});
|
|
1851
|
-
|
|
1852
|
-
const cleanupPlan = Effect.fn("Drizzle.cleanupPlan")(function* <A>(
|
|
1853
|
-
mapping: Mapping,
|
|
1854
|
-
input: { readonly moduleId: string; readonly limit: number },
|
|
1855
|
-
prepare: PreparePasswordCommit<{ readonly removed: number; readonly hasMore: boolean }, A>,
|
|
1856
|
-
) {
|
|
1857
|
-
const database = yield* CurrentD1PlanningDatabase;
|
|
1858
|
-
const journal = yield* CurrentCommitJournal;
|
|
1859
|
-
|
|
1860
|
-
const now = yield* readEngineNowMillis(mapping);
|
|
1861
|
-
const nativeNow = mapping.encodeInstant(now);
|
|
1862
|
-
const a = attemptColumns(mapping);
|
|
1863
|
-
const c = chargeColumns(mapping);
|
|
1864
|
-
const sc = scopeColumns(mapping);
|
|
1865
|
-
let remaining = input.limit;
|
|
1866
|
-
let hasMore = false;
|
|
1867
|
-
|
|
1868
|
-
const attempts = yield* database
|
|
1869
|
-
.select({ attemptId: a.attemptId })
|
|
1870
|
-
.from(mapping.attempt.table)
|
|
1871
|
-
.where(and(eq(a.moduleId, input.moduleId), lte(a.retentionUntil, nativeNow)))
|
|
1872
|
-
.limit(remaining + 1);
|
|
1873
|
-
|
|
1874
|
-
if (attempts.length > remaining) hasMore = true;
|
|
1875
|
-
const selectedAttempts = attempts.slice(0, remaining);
|
|
1876
|
-
|
|
1877
|
-
remaining -= selectedAttempts.length;
|
|
1878
|
-
|
|
1879
|
-
const charges = yield* database
|
|
1880
|
-
.select({
|
|
1881
|
-
action: c.action,
|
|
1882
|
-
scopeKind: c.scopeKind,
|
|
1883
|
-
scopeKey: c.scopeKey,
|
|
1884
|
-
attemptId: c.attemptId,
|
|
1885
|
-
})
|
|
1886
|
-
.from(mapping.charge.table)
|
|
1887
|
-
.where(and(eq(c.moduleId, input.moduleId), lte(c.retentionUntil, nativeNow)))
|
|
1888
|
-
.limit(remaining + 1);
|
|
1889
|
-
|
|
1890
|
-
if (charges.length > remaining) hasMore = true;
|
|
1891
|
-
const selectedCharges = charges.slice(0, remaining);
|
|
1892
|
-
|
|
1893
|
-
remaining -= selectedCharges.length;
|
|
1894
|
-
|
|
1895
|
-
const scopes = yield* database
|
|
1896
|
-
.select({ action: sc.action, scopeKind: sc.scopeKind, scopeKey: sc.scopeKey })
|
|
1897
|
-
.from(mapping.rateScope.table)
|
|
1898
|
-
.where(
|
|
1899
|
-
and(
|
|
1900
|
-
eq(sc.moduleId, input.moduleId),
|
|
1901
|
-
notExists(
|
|
1902
|
-
database
|
|
1903
|
-
.select({ one: sql`1` })
|
|
1904
|
-
.from(mapping.charge.table)
|
|
1905
|
-
.where(
|
|
1906
|
-
and(
|
|
1907
|
-
eq(c.moduleId, sc.moduleId),
|
|
1908
|
-
eq(c.action, sc.action),
|
|
1909
|
-
eq(c.scopeKind, sc.scopeKind),
|
|
1910
|
-
eq(c.scopeKey, sc.scopeKey),
|
|
1911
|
-
),
|
|
1912
|
-
),
|
|
1913
|
-
),
|
|
1914
|
-
),
|
|
1915
|
-
)
|
|
1916
|
-
.limit(remaining + 1);
|
|
1917
|
-
|
|
1918
|
-
if (scopes.length > remaining) hasMore = true;
|
|
1919
|
-
const selectedScopes = scopes.slice(0, remaining);
|
|
1920
|
-
const marker = `effect-auth-password-guard:cleanup:${input.moduleId}:${now}`;
|
|
1921
|
-
const statements: Statement<any>[] = [];
|
|
1922
|
-
|
|
1923
|
-
for (const row of selectedAttempts) {
|
|
1924
|
-
const condition = and(
|
|
1925
|
-
eq(a.moduleId, input.moduleId),
|
|
1926
|
-
eq(a.attemptId, row.attemptId),
|
|
1927
|
-
lte(a.retentionUntil, mapping.d1.engineNow),
|
|
1928
|
-
)!;
|
|
1929
|
-
|
|
1930
|
-
statements.push(
|
|
1931
|
-
yield* assertion(
|
|
1932
|
-
sql`exists(select 1 from ${mapping.attempt.table} where ${condition})`,
|
|
1933
|
-
marker,
|
|
1934
|
-
),
|
|
1935
|
-
yield* statement(database.delete(mapping.attempt.table).where(condition)),
|
|
1936
|
-
);
|
|
1937
|
-
}
|
|
1938
|
-
for (const row of selectedCharges) {
|
|
1939
|
-
const condition = and(
|
|
1940
|
-
eq(c.moduleId, input.moduleId),
|
|
1941
|
-
eq(c.action, row.action),
|
|
1942
|
-
eq(c.scopeKind, row.scopeKind),
|
|
1943
|
-
eq(c.scopeKey, row.scopeKey),
|
|
1944
|
-
eq(c.attemptId, row.attemptId),
|
|
1945
|
-
lte(c.retentionUntil, mapping.d1.engineNow),
|
|
1946
|
-
)!;
|
|
1947
|
-
|
|
1948
|
-
statements.push(
|
|
1949
|
-
yield* assertion(
|
|
1950
|
-
sql`exists(select 1 from ${mapping.charge.table} where ${condition})`,
|
|
1951
|
-
marker,
|
|
1952
|
-
),
|
|
1953
|
-
yield* statement(database.delete(mapping.charge.table).where(condition)),
|
|
1954
|
-
);
|
|
1955
|
-
}
|
|
1956
|
-
for (const row of selectedScopes) {
|
|
1957
|
-
const condition = and(
|
|
1958
|
-
eq(sc.moduleId, input.moduleId),
|
|
1959
|
-
eq(sc.action, row.action),
|
|
1960
|
-
eq(sc.scopeKind, row.scopeKind),
|
|
1961
|
-
eq(sc.scopeKey, row.scopeKey),
|
|
1962
|
-
notExists(
|
|
1963
|
-
database
|
|
1964
|
-
.select({ one: sql`1` })
|
|
1965
|
-
.from(mapping.charge.table)
|
|
1966
|
-
.where(
|
|
1967
|
-
and(
|
|
1968
|
-
eq(c.moduleId, sc.moduleId),
|
|
1969
|
-
eq(c.action, sc.action),
|
|
1970
|
-
eq(c.scopeKind, sc.scopeKind),
|
|
1971
|
-
eq(c.scopeKey, sc.scopeKey),
|
|
1972
|
-
),
|
|
1973
|
-
),
|
|
1974
|
-
),
|
|
1975
|
-
)!;
|
|
1976
|
-
|
|
1977
|
-
statements.push(
|
|
1978
|
-
yield* assertion(
|
|
1979
|
-
sql`exists(select 1 from ${mapping.rateScope.table} where ${condition})`,
|
|
1980
|
-
marker,
|
|
1981
|
-
),
|
|
1982
|
-
yield* statement(database.delete(mapping.rateScope.table).where(condition)),
|
|
1983
|
-
);
|
|
1984
|
-
}
|
|
1359
|
+
const applied = yield* assertion(protectedMutation.appliedCondition, marker);
|
|
1985
1360
|
|
|
1986
1361
|
return {
|
|
1987
|
-
receipt: prepare(
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
hasMore,
|
|
1991
|
-
},
|
|
1992
|
-
journal,
|
|
1993
|
-
),
|
|
1994
|
-
statements,
|
|
1362
|
+
receipt: prepare("changed", journal),
|
|
1363
|
+
statements: [...protectedMutation.statements, applied],
|
|
1364
|
+
postconditions: [applied],
|
|
1995
1365
|
retryable: (cause: unknown) => isGuardFailure(cause, marker),
|
|
1996
1366
|
};
|
|
1997
1367
|
});
|
|
@@ -2001,13 +1371,10 @@ export const makeD1PasswordPersistenceServices = Effect.fnUntraced(function* <
|
|
|
2001
1371
|
I extends AnySQLiteTable,
|
|
2002
1372
|
C extends AnySQLiteTable,
|
|
2003
1373
|
AC extends AnySQLiteTable,
|
|
2004
|
-
A extends AnySQLiteTable,
|
|
2005
|
-
RS extends AnySQLiteTable,
|
|
2006
|
-
CE extends AnySQLiteTable,
|
|
2007
1374
|
M extends AnySQLiteTable,
|
|
2008
1375
|
NativeId,
|
|
2009
1376
|
>(
|
|
2010
|
-
mapping: D1PasswordPersistenceMapping<S, I, C, AC,
|
|
1377
|
+
mapping: D1PasswordPersistenceMapping<S, I, C, AC, M, NativeId>,
|
|
2011
1378
|
proofMapping?: D1ProofPersistenceMapping<
|
|
2012
1379
|
any,
|
|
2013
1380
|
any,
|
|
@@ -2033,9 +1400,14 @@ export const makeD1PasswordPersistenceServices = Effect.fnUntraced(function* <
|
|
|
2033
1400
|
const hooks = yield* LifecycleHooks;
|
|
2034
1401
|
const plans = makePasswordPlans(mapping as unknown as Mapping, proofMapping);
|
|
2035
1402
|
|
|
1403
|
+
const standalone = Effect.gen(function* () {
|
|
1404
|
+
if (yield* hasCommitScope) return yield* unavailable();
|
|
1405
|
+
yield* requireStandalone(unavailable, database.$client.transactionService);
|
|
1406
|
+
});
|
|
1407
|
+
|
|
2036
1408
|
const run = <Out, Err, Env>(plan: Effect.Effect<Planned<Out>, Err, Env>) =>
|
|
2037
1409
|
Effect.gen(function* () {
|
|
2038
|
-
|
|
1410
|
+
yield* standalone;
|
|
2039
1411
|
|
|
2040
1412
|
return yield* executeStandalone(plan, 2);
|
|
2041
1413
|
}).pipe(
|
|
@@ -2044,10 +1416,13 @@ export const makeD1PasswordPersistenceServices = Effect.fnUntraced(function* <
|
|
|
2044
1416
|
);
|
|
2045
1417
|
|
|
2046
1418
|
const service: PasswordPersistence["Service"] = {
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
1419
|
+
findCredential: (input) =>
|
|
1420
|
+
standalone.pipe(
|
|
1421
|
+
Effect.andThen(plans.findCredential(input)),
|
|
1422
|
+
Effect.provideService(CurrentD1PlanningDatabase, database),
|
|
1423
|
+
translateFailure,
|
|
1424
|
+
),
|
|
1425
|
+
rehashIfCurrent: (input) => run(plans.rehashIfCurrent(input)).pipe(translateFailure),
|
|
2051
1426
|
readForSubject: (input) =>
|
|
2052
1427
|
plans
|
|
2053
1428
|
.readForSubject(input)
|
|
@@ -2077,8 +1452,6 @@ export const makeD1PasswordPersistenceServices = Effect.fnUntraced(function* <
|
|
|
2077
1452
|
),
|
|
2078
1453
|
resetWithProof: (input, prepare) =>
|
|
2079
1454
|
run(plans.resetWithProof(input, prepare)).pipe(translateFailure),
|
|
2080
|
-
cleanupAttempts: (input, prepare) =>
|
|
2081
|
-
run(plans.cleanupAttempts(input, prepare)).pipe(translateFailure),
|
|
2082
1455
|
};
|
|
2083
1456
|
|
|
2084
1457
|
return { passwordPersistence: service };
|
|
@@ -2096,9 +1469,6 @@ export function coordinateD1PasswordPersistence<
|
|
|
2096
1469
|
I extends AnySQLiteTable,
|
|
2097
1470
|
C extends AnySQLiteTable,
|
|
2098
1471
|
AC extends AnySQLiteTable,
|
|
2099
|
-
At extends AnySQLiteTable,
|
|
2100
|
-
RS extends AnySQLiteTable,
|
|
2101
|
-
CE extends AnySQLiteTable,
|
|
2102
1472
|
M extends AnySQLiteTable,
|
|
2103
1473
|
NativeId,
|
|
2104
1474
|
A,
|
|
@@ -2109,7 +1479,7 @@ export function coordinateD1PasswordPersistence<
|
|
|
2109
1479
|
>(
|
|
2110
1480
|
acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,
|
|
2111
1481
|
options: {
|
|
2112
|
-
readonly mapping: D1PasswordPersistenceMapping<S, I, C, AC,
|
|
1482
|
+
readonly mapping: D1PasswordPersistenceMapping<S, I, C, AC, M, NativeId>;
|
|
2113
1483
|
readonly proofMapping?:
|
|
2114
1484
|
| D1ProofPersistenceMapping<any, any, any, any, any, any, any, any, any, any, any, any>
|
|
2115
1485
|
| undefined;
|
|
@@ -2173,10 +1543,17 @@ export function coordinateD1PasswordPersistence<
|
|
|
2173
1543
|
);
|
|
2174
1544
|
|
|
2175
1545
|
const service: PasswordPersistence["Service"] = {
|
|
2176
|
-
|
|
2177
|
-
owner.run(
|
|
2178
|
-
|
|
2179
|
-
|
|
1546
|
+
findCredential: (input) =>
|
|
1547
|
+
owner.run(
|
|
1548
|
+
plans
|
|
1549
|
+
.findCredential(input)
|
|
1550
|
+
.pipe(
|
|
1551
|
+
Effect.provideService(CurrentD1PlanningDatabase, database),
|
|
1552
|
+
translateFailure,
|
|
1553
|
+
),
|
|
1554
|
+
),
|
|
1555
|
+
rehashIfCurrent: (input) =>
|
|
1556
|
+
owner.run(run(plans.rehashIfCurrent(input)).pipe(translateFailure)),
|
|
2180
1557
|
readForSubject: (input) =>
|
|
2181
1558
|
owner.run(
|
|
2182
1559
|
plans
|
|
@@ -2213,8 +1590,6 @@ export function coordinateD1PasswordPersistence<
|
|
|
2213
1590
|
),
|
|
2214
1591
|
resetWithProof: (input, prepare) =>
|
|
2215
1592
|
owner.run(run(plans.resetWithProof(input, prepare)).pipe(translateFailure)),
|
|
2216
|
-
cleanupAttempts: (input, prepare) =>
|
|
2217
|
-
owner.run(run(plans.cleanupAttempts(input, prepare)).pipe(translateFailure)),
|
|
2218
1593
|
};
|
|
2219
1594
|
|
|
2220
1595
|
const provided = Context.make(PasswordPersistence, service).pipe(
|
|
@@ -2229,16 +1604,19 @@ export function coordinateD1PasswordPersistence<
|
|
|
2229
1604
|
if (status._tag === "Success" || status.failure._tag !== "CommitPending")
|
|
2230
1605
|
return yield* unavailable();
|
|
2231
1606
|
}
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
1607
|
+
// Re-assert the password's final state after application statements.
|
|
1608
|
+
yield* database.$client
|
|
1609
|
+
.batch([...statements, ...(mutation?.postconditions ?? [])])
|
|
1610
|
+
.pipe(
|
|
1611
|
+
Effect.catchCause((cause) =>
|
|
1612
|
+
Effect.failCause(
|
|
1613
|
+
Cause.map(cause, (error) =>
|
|
1614
|
+
everyFailureMatches(cause, mutation?.retryable) ? unavailable() : error,
|
|
1615
|
+
),
|
|
2237
1616
|
),
|
|
2238
1617
|
),
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
);
|
|
1618
|
+
translateFailure,
|
|
1619
|
+
);
|
|
2242
1620
|
|
|
2243
1621
|
return value;
|
|
2244
1622
|
}),
|