@yielded/auth-persistence-drizzle 0.1.0-beta.23 → 0.1.0-beta.25
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 +9 -9
- package/dist/D1.mjs +2 -1
- package/dist/D1.mjs.map +1 -1
- package/dist/Libsql.d.mts +48 -64
- package/dist/Libsql.mjs +2 -1
- package/dist/Libsql.mjs.map +1 -1
- package/dist/Mysql2.d.mts +26 -27
- package/dist/Pglite.d.mts +28 -28
- package/dist/Pglite.mjs +2 -1
- package/dist/Pglite.mjs.map +1 -1
- package/dist/Postgres.d.mts +29 -29
- package/dist/Postgres.mjs +2 -1
- package/dist/Postgres.mjs.map +1 -1
- package/dist/SqliteBun.d.mts +49 -65
- package/dist/SqliteBun.mjs +2 -1
- package/dist/SqliteBun.mjs.map +1 -1
- package/dist/SqliteDo.d.mts +47 -63
- package/dist/SqliteDo.mjs +2 -1
- package/dist/SqliteDo.mjs.map +1 -1
- package/dist/SqliteNode.d.mts +51 -67
- package/dist/SqliteNode.mjs +2 -1
- package/dist/SqliteNode.mjs.map +1 -1
- package/dist/SqliteWasm.d.mts +47 -63
- 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 +15 -15
- 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 +1 -1
- package/dist/drizzle/d1-password-prepared.mjs.map +1 -1
- package/dist/drizzle/d1-passwords.d.mts +17 -33
- package/dist/drizzle/d1-passwords.mjs +57 -199
- 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 +1 -1
- package/dist/drizzle/d1-sessions.d.mts +2 -2
- 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 +26 -1
- package/dist/drizzle/native-sql-table.mjs.map +1 -1
- 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 -6
- 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-sql.mjs +1 -1
- package/dist/drizzle/password-prepared-sql.mjs.map +1 -1
- package/dist/drizzle/password-prepared-state.mjs +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 +1 -1
- 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/sqlite-password-prepared.mjs.map +1 -1
- package/dist/drizzle/sqlite-passwords.mjs.map +1 -1
- package/dist/drizzle/storage-validation.mjs +10 -185
- package/dist/drizzle/storage-validation.mjs.map +1 -1
- package/dist/drizzle/totp-target.d.mts +2 -2
- 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-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/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 +4 -6
- package/src/drizzle/d1-passwords.ts +125 -459
- package/src/drizzle/d1-sessions.ts +21 -6
- package/src/drizzle/mysql-password-prepared.ts +4 -8
- package/src/drizzle/mysql-passwords.ts +5 -10
- package/src/drizzle/native-sql-table.ts +30 -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 -13
- package/src/drizzle/password-prepared-model.ts +0 -6
- package/src/drizzle/password-prepared-sql.ts +2 -1
- package/src/drizzle/pg-password-prepared.ts +4 -8
- package/src/drizzle/pg-passwords.ts +5 -10
- package/src/drizzle/query-operations.ts +4 -0
- package/src/drizzle/sqlite-password-prepared.ts +4 -8
- package/src/drizzle/sqlite-passwords.ts +7 -14
- package/src/drizzle/storage-validation.ts +13 -214
- package/src/index.ts +2 -4
- package/src/internal/drizzle-postgres-oauth-proxy.ts +37 -0
- package/src/internal/drizzle-sqlite-oauth-proxy.ts +44 -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
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
} from "@yielded/auth/Hooks";
|
|
17
17
|
import type { LoginIdentifier } from "@yielded/auth/Identity";
|
|
18
18
|
import {
|
|
19
|
+
EncodedPasswordHash,
|
|
19
20
|
PasswordUnavailable,
|
|
20
21
|
PasswordPersistence,
|
|
21
22
|
type PasswordMutationInput,
|
|
@@ -24,11 +25,7 @@ import {
|
|
|
24
25
|
snapshotPasswordRequirement,
|
|
25
26
|
snapshotPasswordRevision,
|
|
26
27
|
type PasswordAction,
|
|
27
|
-
type PasswordAttemptDecision,
|
|
28
|
-
type PasswordCredentialSnapshot,
|
|
29
28
|
type PasswordMutationDecision,
|
|
30
|
-
type PasswordAttemptPreparation,
|
|
31
|
-
type PasswordAttemptAdmission,
|
|
32
29
|
} from "@yielded/auth/Password";
|
|
33
30
|
import { reportPersistenceFailure } from "@yielded/auth/Persistence";
|
|
34
31
|
import {
|
|
@@ -43,7 +40,16 @@ import {
|
|
|
43
40
|
AuthenticationRequirement,
|
|
44
41
|
type SecurityRevision,
|
|
45
42
|
} from "@yielded/auth/Sessions";
|
|
46
|
-
import {
|
|
43
|
+
import {
|
|
44
|
+
and,
|
|
45
|
+
eq,
|
|
46
|
+
getTableColumns,
|
|
47
|
+
inArray,
|
|
48
|
+
sql,
|
|
49
|
+
type AnyRelations,
|
|
50
|
+
type SQL,
|
|
51
|
+
type Table,
|
|
52
|
+
} from "drizzle-orm";
|
|
47
53
|
import type { EffectSQLiteD1Database } from "drizzle-orm/effect-d1";
|
|
48
54
|
import type { AnySQLiteTable } from "drizzle-orm/sqlite-core";
|
|
49
55
|
import { Cause, DateTime, Effect, Option, Predicate, Redacted, Schema, Context } from "effect";
|
|
@@ -59,7 +65,6 @@ import { nativeDatabase } from "./native-database";
|
|
|
59
65
|
import {
|
|
60
66
|
type AnyPasswordRegistrationMapping,
|
|
61
67
|
type D1PasswordPersistenceMapping,
|
|
62
|
-
type PasswordAttemptRecord,
|
|
63
68
|
type PasswordRegistrationMapping,
|
|
64
69
|
requiredPasswordConstraints,
|
|
65
70
|
requiredPasswordRegistrationConstraints,
|
|
@@ -75,7 +80,7 @@ type PlanPrepare<Method extends (...args: any[]) => any, A> = (
|
|
|
75
80
|
) => PreparedCommit<A>;
|
|
76
81
|
|
|
77
82
|
type Database = EffectSQLiteD1Database<AnyRelations> & { readonly $client: D1Client };
|
|
78
|
-
type Mapping = D1PasswordPersistenceMapping<Table, Table, Table, Table, Table,
|
|
83
|
+
type Mapping = D1PasswordPersistenceMapping<Table, Table, Table, Table, Table, unknown>;
|
|
79
84
|
type RegistrationMapping<Registration> = AnyPasswordRegistrationMapping<Registration>;
|
|
80
85
|
|
|
81
86
|
interface Planned<A> {
|
|
@@ -189,11 +194,6 @@ const readEngineNowMillis = Effect.fn("Drizzle.readEngineNowMillis")(function* (
|
|
|
189
194
|
);
|
|
190
195
|
});
|
|
191
196
|
|
|
192
|
-
const driverValues = (values: object, entries: ReadonlyArray<readonly [string, unknown]>) => ({
|
|
193
|
-
...values,
|
|
194
|
-
...Object.fromEntries(entries),
|
|
195
|
-
});
|
|
196
|
-
|
|
197
197
|
const allocate = <A>(
|
|
198
198
|
asyncValue: Effect.Effect<A, PersistenceMappingError> | undefined,
|
|
199
199
|
syncValue: (() => A) | undefined,
|
|
@@ -249,27 +249,6 @@ const authorityColumns = (mapping: Mapping) => ({
|
|
|
249
249
|
: column(mapping.authorityCredential.table, mapping.authorityCredential.status),
|
|
250
250
|
});
|
|
251
251
|
|
|
252
|
-
const attemptColumns = (mapping: Mapping) => ({
|
|
253
|
-
moduleId: column(mapping.attempt.table, mapping.attempt.moduleId),
|
|
254
|
-
action: column(mapping.attempt.table, mapping.attempt.action),
|
|
255
|
-
attemptId: column(mapping.attempt.table, mapping.attempt.attemptId),
|
|
256
|
-
identifierNamespace: column(mapping.attempt.table, mapping.attempt.identifierNamespace),
|
|
257
|
-
identifierValue: column(mapping.attempt.table, mapping.attempt.identifierValue),
|
|
258
|
-
subjectId: column(mapping.attempt.table, mapping.attempt.subjectId),
|
|
259
|
-
credentialId: column(mapping.attempt.table, mapping.attempt.credentialId),
|
|
260
|
-
securityRevision: column(mapping.attempt.table, mapping.attempt.securityRevision),
|
|
261
|
-
credentialRevision: column(mapping.attempt.table, mapping.attempt.credentialRevision),
|
|
262
|
-
verifierVersion: column(mapping.attempt.table, mapping.attempt.verifierVersion),
|
|
263
|
-
identifierBindingRevision: column(
|
|
264
|
-
mapping.attempt.table,
|
|
265
|
-
mapping.attempt.identifierBindingRevision,
|
|
266
|
-
),
|
|
267
|
-
admittedAt: column(mapping.attempt.table, mapping.attempt.admittedAt),
|
|
268
|
-
deadline: column(mapping.attempt.table, mapping.attempt.deadline),
|
|
269
|
-
retentionUntil: column(mapping.attempt.table, mapping.attempt.retentionUntil),
|
|
270
|
-
state: column(mapping.attempt.table, mapping.attempt.state),
|
|
271
|
-
});
|
|
272
|
-
|
|
273
252
|
const commandColumns = (mapping: Mapping) => ({
|
|
274
253
|
moduleId: column(mapping.command.table, mapping.command.moduleId),
|
|
275
254
|
commandId: column(mapping.command.table, mapping.command.commandId),
|
|
@@ -323,14 +302,6 @@ const readCredentialNative = Effect.fn("Drizzle.readCredentialNative")(function*
|
|
|
323
302
|
.limit(1);
|
|
324
303
|
});
|
|
325
304
|
|
|
326
|
-
interface Resolved {
|
|
327
|
-
readonly nativeSubjectId: unknown;
|
|
328
|
-
readonly subject: any;
|
|
329
|
-
readonly identifier: any;
|
|
330
|
-
readonly credential?: any;
|
|
331
|
-
readonly snapshot?: PasswordCredentialSnapshot;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
305
|
const resolveCredential = Effect.fn("DrizzleD1Password.resolveCredential")(function* (
|
|
335
306
|
mapping: Mapping,
|
|
336
307
|
moduleId: string,
|
|
@@ -697,7 +668,8 @@ const readAuthority = Effect.fn("DrizzleD1Password.readAuthority")(function* (
|
|
|
697
668
|
)
|
|
698
669
|
return undefined;
|
|
699
670
|
if (
|
|
700
|
-
input.invalidation.existingSessions === "immediate"
|
|
671
|
+
(input.invalidation.existingSessions === "immediate" ||
|
|
672
|
+
input.invalidation.existingSessions === "cache-expiry") &&
|
|
701
673
|
mapping.sessionInvalidation !== "same-authority-immediate"
|
|
702
674
|
)
|
|
703
675
|
return undefined;
|
|
@@ -741,34 +713,6 @@ const credentialCurrentCondition = (
|
|
|
741
713
|
: 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)})`;
|
|
742
714
|
};
|
|
743
715
|
|
|
744
|
-
const admittedSnapshotCondition = (
|
|
745
|
-
mapping: Mapping,
|
|
746
|
-
resolved: Resolved | undefined,
|
|
747
|
-
moduleId: string,
|
|
748
|
-
) => {
|
|
749
|
-
const snapshot = resolved?.snapshot;
|
|
750
|
-
|
|
751
|
-
if (snapshot === undefined || resolved === undefined) return sql`true`;
|
|
752
|
-
const s = subjectColumns(mapping);
|
|
753
|
-
const i = identifierColumns(mapping);
|
|
754
|
-
const c = credentialColumns(mapping);
|
|
755
|
-
const ac = authorityColumns(mapping);
|
|
756
|
-
|
|
757
|
-
return and(
|
|
758
|
-
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)})`,
|
|
759
|
-
mapping.identifier.d1CurrentCondition({
|
|
760
|
-
identifier: snapshot.identifier,
|
|
761
|
-
nativeSubjectId: resolved.nativeSubjectId,
|
|
762
|
-
}),
|
|
763
|
-
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)} and ${Predicate.isNullish(resolved.identifier[mapping.identifier.verifiedAt]) ? sql`${i.verifiedAt} is null` : sql`${i.verifiedAt} = ${sql.param(resolved.identifier[mapping.identifier.verifiedAt], i.verifiedAt)}`})`,
|
|
764
|
-
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)})`,
|
|
765
|
-
...snapshot.revision.credentials.map(
|
|
766
|
-
(item) =>
|
|
767
|
-
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)}`})`,
|
|
768
|
-
),
|
|
769
|
-
)!;
|
|
770
|
-
};
|
|
771
|
-
|
|
772
716
|
const mutationStatements = Effect.fn(function* (
|
|
773
717
|
mapping: Mapping,
|
|
774
718
|
input: PasswordMutationInput,
|
|
@@ -993,312 +937,121 @@ const makePasswordPlans = (
|
|
|
993
937
|
});
|
|
994
938
|
|
|
995
939
|
return {
|
|
996
|
-
|
|
940
|
+
findCredential: (uncaptured: Parameters<PasswordPersistence["Service"]["findCredential"]>[0]) =>
|
|
997
941
|
Effect.gen(function* () {
|
|
998
942
|
if (!validConstraints(mapping)) return yield* unavailable();
|
|
943
|
+
const input = { ...uncaptured, identifier: { ...uncaptured.identifier } };
|
|
944
|
+
const database = yield* CurrentD1PlanningDatabase;
|
|
945
|
+
const identifierRow = (yield* readIdentifier(mapping, input.identifier))[0];
|
|
999
946
|
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
mapping
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
used = true;
|
|
1023
|
-
|
|
1024
|
-
return Effect.void;
|
|
1025
|
-
}),
|
|
1026
|
-
admit: <A>(prepare: PreparePasswordCommit<PasswordAttemptAdmission, A>) =>
|
|
1027
|
-
run(
|
|
1028
|
-
Effect.gen(function* () {
|
|
1029
|
-
const database = yield* CurrentD1PlanningDatabase;
|
|
1030
|
-
const journal = yield* CurrentCommitJournal;
|
|
1031
|
-
const now = yield* readEngineNowMillis(mapping);
|
|
1032
|
-
const marker = `effect-auth-password-guard:admit:${attemptId}`;
|
|
1033
|
-
const a = attemptColumns(mapping);
|
|
1034
|
-
const key = and(eq(a.moduleId, input.moduleId), eq(a.attemptId, attemptId))!;
|
|
1035
|
-
const current = admittedSnapshotCondition(mapping, resolved, input.moduleId);
|
|
1036
|
-
|
|
1037
|
-
const record: PasswordAttemptRecord = {
|
|
1038
|
-
moduleId: input.moduleId,
|
|
1039
|
-
action: input.action,
|
|
1040
|
-
attemptId,
|
|
1041
|
-
identifier: input.identifier,
|
|
1042
|
-
...(snapshot === undefined
|
|
1043
|
-
? {}
|
|
1044
|
-
: {
|
|
1045
|
-
subjectId: snapshot.revision.subjectId,
|
|
1046
|
-
credentialId: snapshot.credentialId,
|
|
1047
|
-
securityRevision: snapshot.revision.securityRevision,
|
|
1048
|
-
credentialRevision: snapshot.credentialRevision,
|
|
1049
|
-
verifierVersion: snapshot.verifierVersion,
|
|
1050
|
-
identifierBindingRevision: snapshot.identifierBindingRevision,
|
|
1051
|
-
}),
|
|
1052
|
-
admittedAtMillis: now,
|
|
1053
|
-
deadlineMillis: now + input.attemptLifetimeMillis,
|
|
1054
|
-
retentionUntilMillis: now + input.attemptLifetimeMillis,
|
|
1055
|
-
};
|
|
1056
|
-
|
|
1057
|
-
const receipt = prepare(
|
|
1058
|
-
{
|
|
1059
|
-
_tag: "Admitted",
|
|
1060
|
-
attemptId,
|
|
1061
|
-
...(snapshot === undefined ? {} : { credential: snapshot }),
|
|
1062
|
-
},
|
|
1063
|
-
journal,
|
|
1064
|
-
);
|
|
1065
|
-
|
|
1066
|
-
const admitted = and(
|
|
1067
|
-
current,
|
|
1068
|
-
sql`exists(select 1 from ${mapping.attempt.table} where ${key} and ${a.state} = ${"pending"} and ${a.deadline} > ${mapping.d1.engineNow})`,
|
|
1069
|
-
)!;
|
|
1070
|
-
|
|
1071
|
-
const statements: Statement<any>[] = [
|
|
1072
|
-
yield* assertion(
|
|
1073
|
-
and(
|
|
1074
|
-
current,
|
|
1075
|
-
sql`not exists(select 1 from ${mapping.attempt.table} where ${key})`,
|
|
1076
|
-
)!,
|
|
1077
|
-
marker,
|
|
1078
|
-
),
|
|
1079
|
-
yield* statement(
|
|
1080
|
-
database.insert(mapping.attempt.table).values(
|
|
1081
|
-
driverValues(
|
|
1082
|
-
mapping.attempt.encodeInsert(record, {
|
|
1083
|
-
...(resolved?.nativeSubjectId === undefined
|
|
1084
|
-
? {}
|
|
1085
|
-
: { nativeSubjectId: resolved.nativeSubjectId }),
|
|
1086
|
-
state: "pending",
|
|
1087
|
-
}),
|
|
1088
|
-
[
|
|
1089
|
-
[mapping.attempt.admittedAt, mapping.d1.engineNow],
|
|
1090
|
-
[
|
|
1091
|
-
mapping.attempt.deadline,
|
|
1092
|
-
mapping.d1.engineInstantPlus(input.attemptLifetimeMillis),
|
|
1093
|
-
],
|
|
1094
|
-
[
|
|
1095
|
-
mapping.attempt.retentionUntil,
|
|
1096
|
-
mapping.d1.engineInstantPlus(input.attemptLifetimeMillis),
|
|
1097
|
-
],
|
|
1098
|
-
],
|
|
1099
|
-
),
|
|
1100
|
-
),
|
|
1101
|
-
),
|
|
1102
|
-
yield* assertion(and(sql`changes() = 1`, admitted)!, marker),
|
|
1103
|
-
];
|
|
1104
|
-
|
|
1105
|
-
// A failed captured-snapshot guard cannot authorize refreshing the
|
|
1106
|
-
// candidate after the strategy has consumed that subject's limit.
|
|
1107
|
-
return {
|
|
1108
|
-
receipt,
|
|
1109
|
-
statements,
|
|
1110
|
-
postconditions: [yield* assertion(admitted, marker)],
|
|
1111
|
-
};
|
|
1112
|
-
}),
|
|
947
|
+
if (identifierRow === undefined || !mapping.identifier.isCurrent(identifierRow))
|
|
948
|
+
return Option.none();
|
|
949
|
+
const nativeId = identifierRow[mapping.identifier.subjectId];
|
|
950
|
+
|
|
951
|
+
const sc = subjectColumns(mapping),
|
|
952
|
+
ic = identifierColumns(mapping),
|
|
953
|
+
cc = credentialColumns(mapping);
|
|
954
|
+
|
|
955
|
+
// Bind the same native ID through each column's codec, then inspect one coherent snapshot.
|
|
956
|
+
const rows = yield* database
|
|
957
|
+
.select({
|
|
958
|
+
subject: getTableColumns(mapping.subject.table),
|
|
959
|
+
identifier: getTableColumns(mapping.identifier.table),
|
|
960
|
+
credential: getTableColumns(mapping.credential.table),
|
|
961
|
+
})
|
|
962
|
+
.from(mapping.subject.table)
|
|
963
|
+
.innerJoin(
|
|
964
|
+
mapping.identifier.table,
|
|
965
|
+
and(
|
|
966
|
+
eq(ic.namespace, input.identifier.namespace),
|
|
967
|
+
eq(ic.value, input.identifier.value),
|
|
968
|
+
eq(ic.subjectId, nativeId),
|
|
1113
969
|
),
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
Effect.gen(function* () {
|
|
1121
|
-
const database = yield* CurrentD1PlanningDatabase;
|
|
970
|
+
)
|
|
971
|
+
.innerJoin(
|
|
972
|
+
mapping.credential.table,
|
|
973
|
+
and(eq(cc.moduleId, input.moduleId), eq(cc.subjectId, nativeId)),
|
|
974
|
+
)
|
|
975
|
+
.where(eq(sc.id, nativeId));
|
|
1122
976
|
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
? undefined
|
|
1126
|
-
: yield* snapshotPasswordCredential(uncaptured.captured);
|
|
977
|
+
if (rows.length !== 1) return Option.none();
|
|
978
|
+
const row = rows[0]!;
|
|
1127
979
|
|
|
1128
|
-
|
|
980
|
+
if (
|
|
981
|
+
!mapping.subject.isActiveStatus(row.subject[mapping.subject.status]) ||
|
|
982
|
+
!mapping.identifier.isCurrent(row.identifier) ||
|
|
983
|
+
!mapping.subjectId.equals(nativeId, row.subject[mapping.subject.id]) ||
|
|
984
|
+
!mapping.subjectId.equals(nativeId, row.identifier[mapping.identifier.subjectId]) ||
|
|
985
|
+
!mapping.subjectId.equals(nativeId, row.credential[mapping.credential.subjectId])
|
|
986
|
+
)
|
|
987
|
+
return Option.none();
|
|
1129
988
|
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
989
|
+
const credential = yield* mapping.credential
|
|
990
|
+
.decode({ moduleId: input.moduleId, ...row })
|
|
991
|
+
.pipe(Effect.flatMap(snapshotPasswordCredential));
|
|
1133
992
|
|
|
1134
|
-
|
|
993
|
+
return input.subjectId !== undefined && credential.revision.subjectId !== input.subjectId
|
|
994
|
+
? Option.none()
|
|
995
|
+
: Option.some(credential);
|
|
996
|
+
}),
|
|
997
|
+
rehashIfCurrent: (input: Parameters<PasswordPersistence["Service"]["rehashIfCurrent"]>[0]) =>
|
|
998
|
+
run(
|
|
999
|
+
Effect.gen(function* () {
|
|
1000
|
+
const nextVerifier = Redacted.make(
|
|
1001
|
+
yield* Schema.decodeEffect(EncodedPasswordHash)(Redacted.value(input.nextVerifier)),
|
|
1002
|
+
);
|
|
1135
1003
|
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
.limit(1);
|
|
1004
|
+
const credential = yield* snapshotPasswordCredential(input.credential);
|
|
1005
|
+
const database = yield* CurrentD1PlanningDatabase;
|
|
1006
|
+
const nativeId = yield* mapping.subjectId.toNative(credential.revision.subjectId);
|
|
1007
|
+
const version = yield* allocate(mapping.allocateRevision, mapping.allocateRevisionSync);
|
|
1141
1008
|
|
|
1142
|
-
|
|
1143
|
-
|
|
1009
|
+
if (version === credential.verifierVersion) return yield* unavailable();
|
|
1010
|
+
const encoded = mapping.credential.encodeVerifier(nextVerifier, version);
|
|
1144
1011
|
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1012
|
+
const values = {
|
|
1013
|
+
[mapping.credential.verifier]: encoded[mapping.credential.verifier],
|
|
1014
|
+
[mapping.credential.verifierVersion]: encoded[mapping.credential.verifierVersion],
|
|
1015
|
+
};
|
|
1149
1016
|
|
|
1150
|
-
|
|
1151
|
-
|
|
1017
|
+
if (Object.values(values).some((value) => value === undefined))
|
|
1018
|
+
return yield* unavailable();
|
|
1019
|
+
const c = credentialColumns(mapping);
|
|
1152
1020
|
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
input.outcome === "verified" &&
|
|
1157
|
-
input.captured !== undefined &&
|
|
1158
|
-
deadline !== undefined &&
|
|
1159
|
-
deadline > engineNow
|
|
1160
|
-
) {
|
|
1161
|
-
resolved = yield* resolveCredential(
|
|
1162
|
-
mapping,
|
|
1163
|
-
input.moduleId,
|
|
1164
|
-
input.captured.identifier,
|
|
1165
|
-
input.captured.revision.subjectId,
|
|
1166
|
-
);
|
|
1167
|
-
verified =
|
|
1168
|
-
input.captured.moduleId === input.moduleId &&
|
|
1169
|
-
resolved?.snapshot !== undefined &&
|
|
1170
|
-
sameSnapshot(resolved.snapshot, input.captured) &&
|
|
1171
|
-
mapping.subjectId.equals(
|
|
1172
|
-
row[mapping.attempt.subjectId],
|
|
1173
|
-
resolved.nativeSubjectId,
|
|
1174
|
-
) &&
|
|
1175
|
-
row[mapping.attempt.identifierNamespace] === input.captured.identifier.namespace &&
|
|
1176
|
-
row[mapping.attempt.identifierValue] === input.captured.identifier.value &&
|
|
1177
|
-
row[mapping.attempt.credentialId] === input.captured.credentialId &&
|
|
1178
|
-
row[mapping.attempt.securityRevision] ===
|
|
1179
|
-
input.captured.revision.securityRevision &&
|
|
1180
|
-
row[mapping.attempt.credentialRevision] === input.captured.credentialRevision &&
|
|
1181
|
-
row[mapping.attempt.verifierVersion] === input.captured.verifierVersion &&
|
|
1182
|
-
row[mapping.attempt.identifierBindingRevision] ===
|
|
1183
|
-
input.captured.identifierBindingRevision;
|
|
1184
|
-
}
|
|
1185
|
-
const decision: PasswordAttemptDecision = verified ? "verified" : "rejected";
|
|
1186
|
-
const receipt = prepare(decision, journal);
|
|
1187
|
-
|
|
1188
|
-
if (row === undefined || row[mapping.attempt.state] !== "pending")
|
|
1189
|
-
return { receipt, statements: [] };
|
|
1190
|
-
const marker = `effect-auth-password-guard:settle:${input.attemptId}`;
|
|
1191
|
-
|
|
1192
|
-
const base = and(
|
|
1193
|
-
eq(a.moduleId, input.moduleId),
|
|
1194
|
-
eq(a.attemptId, input.attemptId),
|
|
1195
|
-
eq(a.state, "pending"),
|
|
1196
|
-
)!;
|
|
1197
|
-
|
|
1198
|
-
const attemptSnapshot =
|
|
1199
|
-
verified && resolved?.snapshot !== undefined
|
|
1200
|
-
? and(
|
|
1201
|
-
eq(a.action, row[mapping.attempt.action]),
|
|
1202
|
-
eq(a.subjectId, resolved.nativeSubjectId),
|
|
1203
|
-
eq(a.identifierNamespace, input.captured!.identifier.namespace),
|
|
1204
|
-
eq(a.identifierValue, input.captured!.identifier.value),
|
|
1205
|
-
eq(a.credentialId, input.captured!.credentialId),
|
|
1206
|
-
eq(a.securityRevision, input.captured!.revision.securityRevision),
|
|
1207
|
-
eq(a.credentialRevision, input.captured!.credentialRevision),
|
|
1208
|
-
eq(a.verifierVersion, input.captured!.verifierVersion),
|
|
1209
|
-
eq(a.identifierBindingRevision, input.captured!.identifierBindingRevision),
|
|
1210
|
-
eq(a.deadline, row[mapping.attempt.deadline]),
|
|
1211
|
-
)!
|
|
1212
|
-
: sql`true`;
|
|
1213
|
-
|
|
1214
|
-
const condition = verified
|
|
1215
|
-
? and(base, attemptSnapshot, sql`${a.deadline} > ${mapping.d1.engineNow}`)!
|
|
1216
|
-
: base;
|
|
1217
|
-
|
|
1218
|
-
const statements: Statement<any>[] = [
|
|
1219
|
-
yield* assertion(
|
|
1220
|
-
sql`exists(select 1 from ${mapping.attempt.table} where ${condition})`,
|
|
1221
|
-
marker,
|
|
1222
|
-
),
|
|
1021
|
+
return {
|
|
1022
|
+
receipt: undefined,
|
|
1023
|
+
statements: [
|
|
1223
1024
|
yield* statement(
|
|
1224
1025
|
database
|
|
1225
|
-
.update(mapping.
|
|
1226
|
-
.set(
|
|
1227
|
-
.where(
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
mapping.allocateRevision,
|
|
1247
|
-
mapping.allocateRevisionSync,
|
|
1248
|
-
);
|
|
1249
|
-
|
|
1250
|
-
statements.push(
|
|
1251
|
-
yield* assertion(sql`changes() = 1`, marker),
|
|
1252
|
-
yield* statement(
|
|
1253
|
-
database
|
|
1254
|
-
.update(mapping.credential.table)
|
|
1255
|
-
.set(
|
|
1256
|
-
mapping.credential.encodeVerifier(input.rehash.nextVerifier, nextVersion),
|
|
1257
|
-
)
|
|
1258
|
-
.where(
|
|
1259
|
-
and(
|
|
1260
|
-
eq(c.moduleId, input.moduleId),
|
|
1261
|
-
eq(c.subjectId, resolved.nativeSubjectId),
|
|
1262
|
-
eq(c.credentialId, captured.credentialId),
|
|
1263
|
-
eq(c.credentialRevision, captured.credentialRevision),
|
|
1264
|
-
eq(c.verifierVersion, input.rehash.expectedVersion),
|
|
1265
|
-
eq(c.verifier, Redacted.value(input.rehash.expectedVerifier)),
|
|
1266
|
-
),
|
|
1026
|
+
.update(mapping.credential.table)
|
|
1027
|
+
.set(values)
|
|
1028
|
+
.where(
|
|
1029
|
+
and(
|
|
1030
|
+
eq(c.moduleId, credential.moduleId),
|
|
1031
|
+
eq(c.subjectId, nativeId),
|
|
1032
|
+
eq(c.credentialId, credential.credentialId),
|
|
1033
|
+
...(
|
|
1034
|
+
[
|
|
1035
|
+
[c.moduleId, credential.moduleId],
|
|
1036
|
+
[c.subjectId, nativeId],
|
|
1037
|
+
[c.credentialId, credential.credentialId],
|
|
1038
|
+
[c.credentialRevision, credential.credentialRevision],
|
|
1039
|
+
[c.verifierVersion, credential.verifierVersion],
|
|
1040
|
+
[c.verifier, Redacted.value(credential.verifier)],
|
|
1041
|
+
[c.normalization, credential.normalization],
|
|
1042
|
+
] as const
|
|
1043
|
+
).map(([column, value]) =>
|
|
1044
|
+
typeof value === "string"
|
|
1045
|
+
? sql`cast(${column} as blob) = cast(${sql.param(value, column)} as blob)`
|
|
1046
|
+
: eq(column, value),
|
|
1267
1047
|
),
|
|
1048
|
+
),
|
|
1268
1049
|
),
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
snapshot: {
|
|
1275
|
-
...resolved.snapshot,
|
|
1276
|
-
verifierVersion: nextVersion,
|
|
1277
|
-
verifier: input.rehash.nextVerifier,
|
|
1278
|
-
},
|
|
1279
|
-
},
|
|
1280
|
-
input.moduleId,
|
|
1281
|
-
);
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
|
|
1285
|
-
const settled = and(
|
|
1286
|
-
finalAuthority,
|
|
1287
|
-
sql`exists(select 1 from ${mapping.attempt.table} where ${a.moduleId} = ${sql.param(input.moduleId, a.moduleId)} and ${a.attemptId} = ${sql.param(input.attemptId, a.attemptId)} and ${a.state} = ${sql.param(decision, a.state)} and ${attemptSnapshot}${verified ? sql` and ${a.deadline} > ${mapping.d1.engineNow}` : sql``})`,
|
|
1288
|
-
)!;
|
|
1289
|
-
|
|
1290
|
-
// Run after attempt/rehash triggers, before the batch can publish its journal.
|
|
1291
|
-
statements.push(yield* assertion(and(sql`changes() = 1`, settled)!, marker));
|
|
1292
|
-
|
|
1293
|
-
return {
|
|
1294
|
-
receipt,
|
|
1295
|
-
statements,
|
|
1296
|
-
postconditions: [yield* assertion(settled, marker)],
|
|
1297
|
-
retryable: (cause: unknown) => isGuardFailure(cause, marker),
|
|
1298
|
-
};
|
|
1299
|
-
}),
|
|
1300
|
-
);
|
|
1301
|
-
}),
|
|
1050
|
+
),
|
|
1051
|
+
],
|
|
1052
|
+
};
|
|
1053
|
+
}),
|
|
1054
|
+
),
|
|
1302
1055
|
readForSubject: (input: Parameters<PasswordPersistence["Service"]["readForSubject"]>[0]) =>
|
|
1303
1056
|
Effect.gen(function* () {
|
|
1304
1057
|
const database = yield* CurrentD1PlanningDatabase;
|
|
@@ -1456,15 +1209,6 @@ const makePasswordPlans = (
|
|
|
1456
1209
|
"reset-password",
|
|
1457
1210
|
),
|
|
1458
1211
|
),
|
|
1459
|
-
cleanupAttempts: <A>(
|
|
1460
|
-
input: Parameters<PasswordPersistence["Service"]["cleanupAttempts"]>[0],
|
|
1461
|
-
prepare: PlanPrepare<PasswordPersistence["Service"]["cleanupAttempts"], A>,
|
|
1462
|
-
) =>
|
|
1463
|
-
run(
|
|
1464
|
-
Effect.gen(function* () {
|
|
1465
|
-
return yield* cleanupPlan(mapping, input, prepare);
|
|
1466
|
-
}),
|
|
1467
|
-
),
|
|
1468
1212
|
};
|
|
1469
1213
|
};
|
|
1470
1214
|
|
|
@@ -1623,68 +1367,15 @@ const replacementPlan = Effect.fn("Drizzle.replacementPlan")(function* <A>(
|
|
|
1623
1367
|
};
|
|
1624
1368
|
});
|
|
1625
1369
|
|
|
1626
|
-
const cleanupPlan = Effect.fn("Drizzle.cleanupPlan")(function* <A>(
|
|
1627
|
-
mapping: Mapping,
|
|
1628
|
-
input: { readonly moduleId: string; readonly limit: number },
|
|
1629
|
-
prepare: PreparePasswordCommit<{ readonly removed: number; readonly hasMore: boolean }, A>,
|
|
1630
|
-
) {
|
|
1631
|
-
const database = yield* CurrentD1PlanningDatabase;
|
|
1632
|
-
const journal = yield* CurrentCommitJournal;
|
|
1633
|
-
|
|
1634
|
-
const now = yield* readEngineNowMillis(mapping);
|
|
1635
|
-
const nativeNow = mapping.encodeInstant(now);
|
|
1636
|
-
const a = attemptColumns(mapping);
|
|
1637
|
-
|
|
1638
|
-
const attempts = yield* database
|
|
1639
|
-
.select({ attemptId: a.attemptId })
|
|
1640
|
-
.from(mapping.attempt.table)
|
|
1641
|
-
.where(and(eq(a.moduleId, input.moduleId), lte(a.retentionUntil, nativeNow)))
|
|
1642
|
-
.limit(input.limit + 1);
|
|
1643
|
-
|
|
1644
|
-
const selectedAttempts = attempts.slice(0, input.limit);
|
|
1645
|
-
const hasMore = attempts.length > selectedAttempts.length;
|
|
1646
|
-
const marker = `effect-auth-password-guard:cleanup:${input.moduleId}:${now}`;
|
|
1647
|
-
const statements: Statement<any>[] = [];
|
|
1648
|
-
|
|
1649
|
-
for (const row of selectedAttempts) {
|
|
1650
|
-
const condition = and(
|
|
1651
|
-
eq(a.moduleId, input.moduleId),
|
|
1652
|
-
eq(a.attemptId, row.attemptId),
|
|
1653
|
-
lte(a.retentionUntil, mapping.d1.engineNow),
|
|
1654
|
-
)!;
|
|
1655
|
-
|
|
1656
|
-
statements.push(
|
|
1657
|
-
yield* assertion(
|
|
1658
|
-
sql`exists(select 1 from ${mapping.attempt.table} where ${condition})`,
|
|
1659
|
-
marker,
|
|
1660
|
-
),
|
|
1661
|
-
yield* statement(database.delete(mapping.attempt.table).where(condition)),
|
|
1662
|
-
);
|
|
1663
|
-
}
|
|
1664
|
-
|
|
1665
|
-
return {
|
|
1666
|
-
receipt: prepare(
|
|
1667
|
-
{
|
|
1668
|
-
removed: selectedAttempts.length,
|
|
1669
|
-
hasMore,
|
|
1670
|
-
},
|
|
1671
|
-
journal,
|
|
1672
|
-
),
|
|
1673
|
-
statements,
|
|
1674
|
-
retryable: (cause: unknown) => isGuardFailure(cause, marker),
|
|
1675
|
-
};
|
|
1676
|
-
});
|
|
1677
|
-
|
|
1678
1370
|
export const makeD1PasswordPersistenceServices = Effect.fnUntraced(function* <
|
|
1679
1371
|
S extends AnySQLiteTable,
|
|
1680
1372
|
I extends AnySQLiteTable,
|
|
1681
1373
|
C extends AnySQLiteTable,
|
|
1682
1374
|
AC extends AnySQLiteTable,
|
|
1683
|
-
A extends AnySQLiteTable,
|
|
1684
1375
|
M extends AnySQLiteTable,
|
|
1685
1376
|
NativeId,
|
|
1686
1377
|
>(
|
|
1687
|
-
mapping: D1PasswordPersistenceMapping<S, I, C, AC,
|
|
1378
|
+
mapping: D1PasswordPersistenceMapping<S, I, C, AC, M, NativeId>,
|
|
1688
1379
|
proofMapping?: D1ProofPersistenceMapping<
|
|
1689
1380
|
any,
|
|
1690
1381
|
any,
|
|
@@ -1726,21 +1417,13 @@ export const makeD1PasswordPersistenceServices = Effect.fnUntraced(function* <
|
|
|
1726
1417
|
);
|
|
1727
1418
|
|
|
1728
1419
|
const service: PasswordPersistence["Service"] = {
|
|
1729
|
-
|
|
1420
|
+
findCredential: (input) =>
|
|
1730
1421
|
standalone.pipe(
|
|
1731
|
-
Effect.andThen(plans.
|
|
1732
|
-
Effect.map((planned): PasswordAttemptPreparation =>
|
|
1733
|
-
Object.freeze({
|
|
1734
|
-
...(planned.credential === undefined ? {} : { credential: planned.credential }),
|
|
1735
|
-
admit: <A>(prepare: PreparePasswordCommit<PasswordAttemptAdmission, A>) =>
|
|
1736
|
-
planned.claim.pipe(Effect.andThen(run(planned.admit(prepare))), translateFailure),
|
|
1737
|
-
}),
|
|
1738
|
-
),
|
|
1422
|
+
Effect.andThen(plans.findCredential(input)),
|
|
1739
1423
|
Effect.provideService(CurrentD1PlanningDatabase, database),
|
|
1740
1424
|
translateFailure,
|
|
1741
1425
|
),
|
|
1742
|
-
|
|
1743
|
-
run(plans.settleAttempt(input, prepare)).pipe(translateFailure),
|
|
1426
|
+
rehashIfCurrent: (input) => run(plans.rehashIfCurrent(input)).pipe(translateFailure),
|
|
1744
1427
|
readForSubject: (input) =>
|
|
1745
1428
|
plans
|
|
1746
1429
|
.readForSubject(input)
|
|
@@ -1770,8 +1453,6 @@ export const makeD1PasswordPersistenceServices = Effect.fnUntraced(function* <
|
|
|
1770
1453
|
),
|
|
1771
1454
|
resetWithProof: (input, prepare) =>
|
|
1772
1455
|
run(plans.resetWithProof(input, prepare)).pipe(translateFailure),
|
|
1773
|
-
cleanupAttempts: (input, prepare) =>
|
|
1774
|
-
run(plans.cleanupAttempts(input, prepare)).pipe(translateFailure),
|
|
1775
1456
|
};
|
|
1776
1457
|
|
|
1777
1458
|
return { passwordPersistence: service };
|
|
@@ -1789,7 +1470,6 @@ export function coordinateD1PasswordPersistence<
|
|
|
1789
1470
|
I extends AnySQLiteTable,
|
|
1790
1471
|
C extends AnySQLiteTable,
|
|
1791
1472
|
AC extends AnySQLiteTable,
|
|
1792
|
-
At extends AnySQLiteTable,
|
|
1793
1473
|
M extends AnySQLiteTable,
|
|
1794
1474
|
NativeId,
|
|
1795
1475
|
A,
|
|
@@ -1800,7 +1480,7 @@ export function coordinateD1PasswordPersistence<
|
|
|
1800
1480
|
>(
|
|
1801
1481
|
acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,
|
|
1802
1482
|
options: {
|
|
1803
|
-
readonly mapping: D1PasswordPersistenceMapping<S, I, C, AC,
|
|
1483
|
+
readonly mapping: D1PasswordPersistenceMapping<S, I, C, AC, M, NativeId>;
|
|
1804
1484
|
readonly proofMapping?:
|
|
1805
1485
|
| D1ProofPersistenceMapping<any, any, any, any, any, any, any, any, any, any, any, any>
|
|
1806
1486
|
| undefined;
|
|
@@ -1864,29 +1544,17 @@ export function coordinateD1PasswordPersistence<
|
|
|
1864
1544
|
);
|
|
1865
1545
|
|
|
1866
1546
|
const service: PasswordPersistence["Service"] = {
|
|
1867
|
-
|
|
1547
|
+
findCredential: (input) =>
|
|
1868
1548
|
owner.run(
|
|
1869
|
-
plans
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
: { credential: planned.credential }),
|
|
1875
|
-
admit: <A>(prepare: PreparePasswordCommit<PasswordAttemptAdmission, A>) =>
|
|
1876
|
-
owner.run(
|
|
1877
|
-
planned.claim.pipe(
|
|
1878
|
-
Effect.andThen(run(planned.admit(prepare))),
|
|
1879
|
-
translateFailure,
|
|
1880
|
-
),
|
|
1881
|
-
),
|
|
1882
|
-
}),
|
|
1549
|
+
plans
|
|
1550
|
+
.findCredential(input)
|
|
1551
|
+
.pipe(
|
|
1552
|
+
Effect.provideService(CurrentD1PlanningDatabase, database),
|
|
1553
|
+
translateFailure,
|
|
1883
1554
|
),
|
|
1884
|
-
Effect.provideService(CurrentD1PlanningDatabase, database),
|
|
1885
|
-
translateFailure,
|
|
1886
|
-
),
|
|
1887
1555
|
),
|
|
1888
|
-
|
|
1889
|
-
owner.run(run(plans.
|
|
1556
|
+
rehashIfCurrent: (input) =>
|
|
1557
|
+
owner.run(run(plans.rehashIfCurrent(input)).pipe(translateFailure)),
|
|
1890
1558
|
readForSubject: (input) =>
|
|
1891
1559
|
owner.run(
|
|
1892
1560
|
plans
|
|
@@ -1923,8 +1591,6 @@ export function coordinateD1PasswordPersistence<
|
|
|
1923
1591
|
),
|
|
1924
1592
|
resetWithProof: (input, prepare) =>
|
|
1925
1593
|
owner.run(run(plans.resetWithProof(input, prepare)).pipe(translateFailure)),
|
|
1926
|
-
cleanupAttempts: (input, prepare) =>
|
|
1927
|
-
owner.run(run(plans.cleanupAttempts(input, prepare)).pipe(translateFailure)),
|
|
1928
1594
|
};
|
|
1929
1595
|
|
|
1930
1596
|
const provided = Context.make(PasswordPersistence, service).pipe(
|