@yielded/auth-persistence-drizzle 0.1.0-beta.0 → 0.1.0-beta.12
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 +6 -1
- package/dist/D1.d.mts +155 -40
- package/dist/D1.mjs +10 -6
- package/dist/D1.mjs.map +1 -1
- package/dist/Libsql.d.mts +251 -129
- package/dist/Libsql.mjs +20 -21
- package/dist/Libsql.mjs.map +1 -1
- package/dist/Mysql2.d.mts +208 -56
- package/dist/Mysql2.mjs +13 -8
- package/dist/Mysql2.mjs.map +1 -1
- package/dist/Pglite.d.mts +209 -57
- package/dist/Pglite.mjs +13 -9
- package/dist/Pglite.mjs.map +1 -1
- package/dist/Postgres.d.mts +207 -55
- package/dist/Postgres.mjs +13 -9
- package/dist/Postgres.mjs.map +1 -1
- package/dist/SqliteBun.d.mts +249 -126
- package/dist/SqliteBun.mjs +20 -18
- package/dist/SqliteBun.mjs.map +1 -1
- package/dist/SqliteDo.d.mts +248 -158
- package/dist/SqliteDo.mjs +26 -44
- package/dist/SqliteDo.mjs.map +1 -1
- package/dist/SqliteNode.d.mts +247 -124
- package/dist/SqliteNode.mjs +20 -18
- package/dist/SqliteNode.mjs.map +1 -1
- package/dist/SqliteWasm.d.mts +251 -128
- package/dist/SqliteWasm.mjs +20 -18
- package/dist/SqliteWasm.mjs.map +1 -1
- package/dist/drizzle/D1BatchStatements.d.mts +1 -1
- package/dist/drizzle/D1BatchStatements.mjs.map +1 -1
- package/dist/drizzle/d1-database.d.mts +11 -0
- package/dist/drizzle/d1-database.mjs +8 -0
- package/dist/drizzle/d1-database.mjs.map +1 -0
- package/dist/drizzle/d1-emails.d.mts +8 -7
- package/dist/drizzle/d1-emails.mjs +7 -4
- package/dist/drizzle/d1-emails.mjs.map +1 -1
- package/dist/drizzle/d1-generated-statement.mjs.map +1 -1
- package/dist/drizzle/d1-identity.mjs +12 -9
- package/dist/drizzle/d1-identity.mjs.map +1 -1
- package/dist/drizzle/d1-oauth.d.mts +41 -10
- package/dist/drizzle/d1-oauth.mjs +8 -5
- package/dist/drizzle/d1-oauth.mjs.map +1 -1
- package/dist/drizzle/d1-passkey.d.mts +3 -14
- package/dist/drizzle/d1-passkey.mjs +2 -1
- package/dist/drizzle/d1-passkey.mjs.map +1 -1
- package/dist/drizzle/d1-password-prepared.d.mts +4 -3
- package/dist/drizzle/d1-password-prepared.mjs +3 -1
- package/dist/drizzle/d1-password-prepared.mjs.map +1 -1
- package/dist/drizzle/d1-passwords.d.mts +7 -6
- package/dist/drizzle/d1-passwords.mjs +5 -2
- package/dist/drizzle/d1-passwords.mjs.map +1 -1
- package/dist/drizzle/d1-phone.d.mts +3 -4
- package/dist/drizzle/d1-phone.mjs +2 -1
- package/dist/drizzle/d1-phone.mjs.map +1 -1
- package/dist/drizzle/d1-planning.d.mts +1 -1
- package/dist/drizzle/d1-proofs.d.mts +5 -4
- package/dist/drizzle/d1-proofs.mjs +3 -1
- package/dist/drizzle/d1-proofs.mjs.map +1 -1
- package/dist/drizzle/d1-sessions.d.mts +14 -13
- package/dist/drizzle/d1-sessions.mjs +15 -9
- package/dist/drizzle/d1-sessions.mjs.map +1 -1
- package/dist/drizzle/d1-totp.d.mts +3 -4
- package/dist/drizzle/d1-totp.mjs +2 -1
- package/dist/drizzle/d1-totp.mjs.map +1 -1
- package/dist/drizzle/email-registration.d.mts +1 -1
- package/dist/drizzle/email-registration.mjs +2 -1
- package/dist/drizzle/email-registration.mjs.map +1 -1
- package/dist/drizzle/email-target.d.mts +8 -7
- package/dist/drizzle/email-target.mjs +10 -10
- package/dist/drizzle/email-target.mjs.map +1 -1
- package/dist/drizzle/model.d.mts +2 -126
- package/dist/drizzle/model.mjs +2 -21
- package/dist/drizzle/model.mjs.map +1 -1
- package/dist/drizzle/mysql-database.d.mts +8 -0
- package/dist/drizzle/mysql-database.mjs +8 -0
- package/dist/drizzle/mysql-database.mjs.map +1 -0
- package/dist/drizzle/mysql-emails.d.mts +8 -7
- package/dist/drizzle/mysql-emails.mjs +12 -8
- package/dist/drizzle/mysql-emails.mjs.map +1 -1
- package/dist/drizzle/mysql-identity.mjs +12 -9
- package/dist/drizzle/mysql-identity.mjs.map +1 -1
- package/dist/drizzle/mysql-password-prepared.d.mts +4 -3
- package/dist/drizzle/mysql-password-prepared.mjs +6 -2
- package/dist/drizzle/mysql-password-prepared.mjs.map +1 -1
- package/dist/drizzle/mysql-passwords.d.mts +7 -5
- package/dist/drizzle/mysql-passwords.mjs +11 -7
- package/dist/drizzle/mysql-passwords.mjs.map +1 -1
- package/dist/drizzle/mysql-proofs.d.mts +4 -3
- package/dist/drizzle/mysql-proofs.mjs +8 -4
- package/dist/drizzle/mysql-proofs.mjs.map +1 -1
- package/dist/drizzle/mysql-sessions.d.mts +12 -11
- package/dist/drizzle/mysql-sessions.mjs +16 -12
- package/dist/drizzle/mysql-sessions.mjs.map +1 -1
- package/dist/drizzle/native-database.mjs +10 -0
- package/dist/drizzle/native-database.mjs.map +1 -0
- package/dist/drizzle/oauth-accounts.mjs +1 -1
- package/dist/drizzle/oauth-connected-access.mjs +14 -12
- package/dist/drizzle/oauth-connected-access.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-custody.mjs +2 -2
- package/dist/drizzle/oauth-connected-drivers.mjs +11 -6
- package/dist/drizzle/oauth-connected-drivers.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-flow.mjs +2 -2
- package/dist/drizzle/oauth-connected-input.mjs +14 -1
- package/dist/drizzle/oauth-connected-input.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-maintenance.mjs +1 -1
- package/dist/drizzle/oauth-connected-management.mjs +2 -2
- package/dist/drizzle/oauth-connected-model.d.mts +17 -3
- package/dist/drizzle/oauth-connected-model.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-settlement.mjs +51 -41
- package/dist/drizzle/oauth-connected-settlement.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-sign-in.mjs +263 -0
- package/dist/drizzle/oauth-connected-sign-in.mjs.map +1 -0
- package/dist/drizzle/oauth-connected-state.d.mts +110 -2
- package/dist/drizzle/oauth-connected-state.mjs +9 -4
- package/dist/drizzle/oauth-connected-state.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-target.d.mts +142 -15
- package/dist/drizzle/oauth-connected-target.mjs +9 -6
- package/dist/drizzle/oauth-connected-target.mjs.map +1 -1
- package/dist/drizzle/oauth-drivers.mjs +9 -7
- package/dist/drizzle/oauth-drivers.mjs.map +1 -1
- package/dist/drizzle/oauth-flow.d.mts +1 -1
- package/dist/drizzle/oauth-flow.mjs +1 -1
- package/dist/drizzle/oauth-input.mjs +1 -1
- package/dist/drizzle/oauth-model.d.mts +1 -1
- package/dist/drizzle/oauth-owner.d.mts +1 -1
- package/dist/drizzle/oauth-registration.d.mts +2 -2
- package/dist/drizzle/oauth-registration.mjs +1 -1
- package/dist/drizzle/oauth-state.mjs +5 -4
- package/dist/drizzle/oauth-state.mjs.map +1 -1
- package/dist/drizzle/oauth-target.d.mts +14 -13
- package/dist/drizzle/oauth-target.mjs +14 -13
- package/dist/drizzle/oauth-target.mjs.map +1 -1
- package/dist/drizzle/passkey-drivers.mjs +8 -6
- package/dist/drizzle/passkey-drivers.mjs.map +1 -1
- package/dist/drizzle/passkey-write-drivers.mjs +5 -3
- package/dist/drizzle/passkey-write-drivers.mjs.map +1 -1
- package/dist/drizzle/passkey-write-target.d.mts +1 -1
- package/dist/drizzle/password-prepared-sql.mjs +2 -1
- package/dist/drizzle/password-prepared-sql.mjs.map +1 -1
- package/dist/drizzle/password-prepared-state.mjs +1 -1
- package/dist/drizzle/password-prepared-target.d.mts +4 -3
- package/dist/drizzle/password-prepared-target.mjs +4 -3
- package/dist/drizzle/password-prepared-target.mjs.map +1 -1
- package/dist/drizzle/password-registration.mjs +2 -1
- package/dist/drizzle/password-registration.mjs.map +1 -1
- package/dist/drizzle/password-target.d.mts +6 -5
- package/dist/drizzle/password-target.mjs +8 -8
- package/dist/drizzle/password-target.mjs.map +1 -1
- package/dist/drizzle/pg-database.d.mts +9 -0
- package/dist/drizzle/pg-database.mjs +8 -0
- package/dist/drizzle/pg-database.mjs.map +1 -0
- package/dist/drizzle/pg-emails.d.mts +8 -7
- package/dist/drizzle/pg-emails.mjs +12 -8
- package/dist/drizzle/pg-emails.mjs.map +1 -1
- package/dist/drizzle/pg-identity.mjs +92 -0
- package/dist/drizzle/pg-identity.mjs.map +1 -0
- package/dist/drizzle/pg-password-prepared.d.mts +4 -3
- package/dist/drizzle/pg-password-prepared.mjs +6 -2
- package/dist/drizzle/pg-password-prepared.mjs.map +1 -1
- package/dist/drizzle/pg-passwords.d.mts +7 -5
- package/dist/drizzle/pg-passwords.mjs +11 -7
- package/dist/drizzle/pg-passwords.mjs.map +1 -1
- package/dist/drizzle/pg-proofs.d.mts +4 -3
- package/dist/drizzle/pg-proofs.mjs +8 -4
- package/dist/drizzle/pg-proofs.mjs.map +1 -1
- package/dist/drizzle/pg-sessions.d.mts +12 -11
- package/dist/drizzle/pg-sessions.mjs +16 -12
- package/dist/drizzle/pg-sessions.mjs.map +1 -1
- package/dist/drizzle/phone-model.d.mts +1 -1
- package/dist/drizzle/phone-target.d.mts +5 -4
- package/dist/drizzle/phone-target.mjs +12 -11
- package/dist/drizzle/phone-target.mjs.map +1 -1
- package/dist/drizzle/proof-target.d.mts +4 -3
- package/dist/drizzle/proof-target.mjs +5 -5
- package/dist/drizzle/proof-target.mjs.map +1 -1
- package/dist/drizzle/session-sql.d.mts +1 -0
- package/dist/drizzle/session-target.d.mts +11 -9
- package/dist/drizzle/session-target.mjs +11 -11
- package/dist/drizzle/session-target.mjs.map +1 -1
- package/dist/drizzle/sqlite-emails.mjs +9 -5
- package/dist/drizzle/sqlite-emails.mjs.map +1 -1
- package/dist/drizzle/sqlite-identity.mjs +14 -11
- package/dist/drizzle/sqlite-identity.mjs.map +1 -1
- package/dist/drizzle/sqlite-password-prepared.mjs +7 -3
- package/dist/drizzle/sqlite-password-prepared.mjs.map +1 -1
- package/dist/drizzle/sqlite-passwords.mjs +10 -6
- package/dist/drizzle/sqlite-passwords.mjs.map +1 -1
- package/dist/drizzle/sqlite-proofs.mjs +7 -3
- package/dist/drizzle/sqlite-proofs.mjs.map +1 -1
- package/dist/drizzle/sqlite-sessions.mjs +16 -12
- package/dist/drizzle/sqlite-sessions.mjs.map +1 -1
- package/dist/drizzle/standalone-guard.d.mts +2 -0
- package/dist/drizzle/standalone-guard.mjs +8 -4
- package/dist/drizzle/standalone-guard.mjs.map +1 -1
- package/dist/drizzle/totp-model.d.mts +1 -1
- package/dist/drizzle/totp-target.d.mts +5 -4
- package/dist/drizzle/totp-target.mjs +31 -28
- package/dist/drizzle/totp-target.mjs.map +1 -1
- package/dist/drizzle/transaction-mysql.mjs +1 -1
- package/dist/drizzle/transaction-mysql.mjs.map +1 -1
- package/dist/index.d.mts +2 -4
- package/dist/index.mjs +2 -4
- package/dist/internal/drizzle-postgres.mjs.map +1 -1
- package/dist/internal/drizzle-sqlite.mjs.map +1 -1
- package/package.json +1 -1
- package/src/D1.ts +37 -26
- package/src/Libsql.ts +45 -61
- package/src/Mysql2.ts +39 -35
- package/src/Pglite.ts +48 -30
- package/src/Postgres.ts +48 -30
- package/src/SqliteBun.ts +59 -68
- package/src/SqliteDo.ts +61 -274
- package/src/SqliteNode.ts +56 -66
- package/src/SqliteWasm.ts +56 -66
- package/src/drizzle/D1BatchStatements.ts +1 -1
- package/src/drizzle/d1-database.ts +10 -0
- package/src/drizzle/d1-emails.ts +86 -88
- package/src/drizzle/d1-generated-statement.ts +1 -1
- package/src/drizzle/d1-identity.ts +17 -20
- package/src/drizzle/d1-oauth.ts +19 -8
- package/src/drizzle/d1-passkey.ts +5 -1
- package/src/drizzle/d1-password-prepared.ts +40 -42
- package/src/drizzle/d1-passwords.ts +76 -80
- package/src/drizzle/d1-phone.ts +5 -1
- package/src/drizzle/d1-proofs.ts +31 -34
- package/src/drizzle/d1-sessions.ts +53 -40
- package/src/drizzle/d1-totp.ts +5 -1
- package/src/drizzle/email-registration.ts +6 -2
- package/src/drizzle/email-target.ts +18 -20
- package/src/drizzle/model.ts +1 -208
- package/src/drizzle/mysql-database.ts +8 -0
- package/src/drizzle/mysql-emails.ts +29 -17
- package/src/drizzle/mysql-identity.ts +18 -21
- package/src/drizzle/mysql-password-prepared.ts +11 -9
- package/src/drizzle/mysql-passwords.ts +22 -10
- package/src/drizzle/mysql-proofs.ts +17 -6
- package/src/drizzle/mysql-sessions.ts +41 -18
- package/src/drizzle/native-database.ts +22 -0
- package/src/drizzle/oauth-connected-access.ts +8 -1
- package/src/drizzle/oauth-connected-drivers.ts +21 -6
- package/src/drizzle/oauth-connected-input.ts +13 -0
- package/src/drizzle/oauth-connected-model.ts +17 -0
- package/src/drizzle/oauth-connected-settlement.ts +65 -42
- package/src/drizzle/oauth-connected-sign-in.ts +438 -0
- package/src/drizzle/oauth-connected-state.ts +19 -7
- package/src/drizzle/oauth-connected-target.ts +26 -18
- package/src/drizzle/oauth-drivers.ts +26 -10
- package/src/drizzle/oauth-state.ts +5 -4
- package/src/drizzle/oauth-target.ts +31 -43
- package/src/drizzle/passkey-drivers.ts +21 -13
- package/src/drizzle/passkey-write-drivers.ts +11 -6
- package/src/drizzle/password-prepared-sql.ts +2 -4
- package/src/drizzle/password-prepared-target.ts +10 -7
- package/src/drizzle/password-registration.ts +7 -8
- package/src/drizzle/password-target.ts +20 -19
- package/src/drizzle/pg-database.ts +10 -0
- package/src/drizzle/pg-emails.ts +29 -17
- package/src/drizzle/pg-identity.ts +297 -0
- package/src/drizzle/pg-password-prepared.ts +11 -9
- package/src/drizzle/pg-passwords.ts +22 -10
- package/src/drizzle/pg-proofs.ts +17 -6
- package/src/drizzle/pg-sessions.ts +41 -18
- package/src/drizzle/phone-target.ts +23 -18
- package/src/drizzle/proof-target.ts +10 -13
- package/src/drizzle/session-target.ts +33 -51
- package/src/drizzle/sqlite-emails.ts +31 -14
- package/src/drizzle/sqlite-identity.ts +22 -42
- package/src/drizzle/sqlite-password-prepared.ts +24 -10
- package/src/drizzle/sqlite-passwords.ts +30 -16
- package/src/drizzle/sqlite-proofs.ts +29 -6
- package/src/drizzle/sqlite-sessions.ts +50 -24
- package/src/drizzle/standalone-guard.ts +19 -7
- package/src/drizzle/totp-target.ts +62 -61
- package/src/drizzle/transaction-mysql.ts +1 -1
- package/src/index.ts +0 -24
- package/src/internal/drizzle-postgres.ts +1 -1
- package/src/internal/drizzle-sqlite.ts +1 -1
- package/dist/drizzle/d1-identity.d.mts +0 -30
- package/dist/drizzle/mysql-identity.d.mts +0 -21
- package/dist/drizzle/mysql.d.mts +0 -69
- package/dist/drizzle/mysql.mjs +0 -218
- package/dist/drizzle/mysql.mjs.map +0 -1
- package/dist/drizzle/pg.d.mts +0 -80
- package/dist/drizzle/pg.mjs +0 -289
- package/dist/drizzle/pg.mjs.map +0 -1
- package/dist/drizzle/sqlite.d.mts +0 -77
- package/dist/drizzle/sqlite.mjs +0 -217
- package/dist/drizzle/sqlite.mjs.map +0 -1
- package/src/drizzle/mysql.ts +0 -687
- package/src/drizzle/pg.ts +0 -984
- package/src/drizzle/sqlite.ts +0 -705
|
@@ -5,10 +5,13 @@ import type { AnyRelations } from "drizzle-orm";
|
|
|
5
5
|
import type { EffectMysql2Database } from "drizzle-orm/effect-mysql2";
|
|
6
6
|
import type { AnyMySqlTable } from "drizzle-orm/mysql-core";
|
|
7
7
|
import { Effect, Context } from "effect";
|
|
8
|
-
import type { SqlError } from "effect/
|
|
8
|
+
import type { SqlError } from "effect/sql/SqlError";
|
|
9
9
|
|
|
10
|
+
import { Database as DatabaseService } from "./mysql-database";
|
|
11
|
+
import { nativeDatabase } from "./native-database";
|
|
10
12
|
import type { PasswordPersistenceMapping, PasswordRegistrationMapping } from "./password-model";
|
|
11
13
|
import type { PasswordRegistrationAuthority } from "./password-registration";
|
|
14
|
+
import { CurrentPasswordSql } from "./password-sql";
|
|
12
15
|
import type { PasswordSqlQuery } from "./password-sql";
|
|
13
16
|
import {
|
|
14
17
|
coordinateTargetPasswordPersistence,
|
|
@@ -20,22 +23,27 @@ import {
|
|
|
20
23
|
import type { ProofPersistenceMapping } from "./proof-model";
|
|
21
24
|
import type { ProofSqlQuery } from "./proof-sql";
|
|
22
25
|
import { sqlClientProofStandaloneGuard } from "./proof-target";
|
|
26
|
+
import {
|
|
27
|
+
type TransactionService,
|
|
28
|
+
acquireTransactionService,
|
|
29
|
+
transactionService,
|
|
30
|
+
} from "./standalone-guard";
|
|
23
31
|
import type { SuppliedService } from "./SuppliedService";
|
|
24
32
|
|
|
25
33
|
type Database = EffectMysql2Database<AnyRelations>;
|
|
26
34
|
type TransactionOf<D extends Database> = Parameters<Parameters<D["transaction"]>[0]>[0];
|
|
27
35
|
|
|
28
|
-
const configuration = (
|
|
36
|
+
const configuration = (service: TransactionService | undefined) => ({
|
|
29
37
|
mode: "interactive" as const,
|
|
30
38
|
locking: true,
|
|
31
|
-
standaloneGuard: sqlClientPasswordStandaloneGuard(
|
|
39
|
+
standaloneGuard: sqlClientPasswordStandaloneGuard(service),
|
|
32
40
|
insertIfAbsent: (query: PasswordSqlQuery, selfKey: string, selfValue: unknown) =>
|
|
33
41
|
query.onDuplicateKeyUpdate({ set: { [selfKey]: selfValue } }),
|
|
34
42
|
generatedSubjectRows: (query: PasswordSqlQuery) => query.$returningId(),
|
|
35
43
|
proof: {
|
|
36
44
|
mode: "interactive" as const,
|
|
37
45
|
locking: true,
|
|
38
|
-
standaloneGuard: sqlClientProofStandaloneGuard(
|
|
46
|
+
standaloneGuard: sqlClientProofStandaloneGuard(service),
|
|
39
47
|
insertIfAbsent: (query: ProofSqlQuery, selfKey: string, selfValue: unknown) =>
|
|
40
48
|
query.onDuplicateKeyUpdate({ set: { [selfKey]: selfValue } }),
|
|
41
49
|
},
|
|
@@ -64,7 +72,6 @@ export const makeMysqlPasswordPersistenceServices = <
|
|
|
64
72
|
M extends AnyMySqlTable,
|
|
65
73
|
NativeId,
|
|
66
74
|
>(
|
|
67
|
-
database: Database,
|
|
68
75
|
mapping: Mapping<S, I, C, AC, A, RS, CE, M, NativeId>,
|
|
69
76
|
proofMapping?: ProofPersistenceMapping<
|
|
70
77
|
any,
|
|
@@ -81,7 +88,10 @@ export const makeMysqlPasswordPersistenceServices = <
|
|
|
81
88
|
any
|
|
82
89
|
>,
|
|
83
90
|
) =>
|
|
84
|
-
|
|
91
|
+
Effect.flatMap(
|
|
92
|
+
Effect.map(acquireTransactionService(DatabaseService), configuration),
|
|
93
|
+
(configuration) => makeTargetPasswordPersistenceServices(mapping, configuration, proofMapping),
|
|
94
|
+
).pipe(Effect.provideServiceEffect(CurrentPasswordSql, nativeDatabase(DatabaseService)));
|
|
85
95
|
|
|
86
96
|
export function coordinateMysqlPasswordPersistence<
|
|
87
97
|
D extends Database,
|
|
@@ -189,7 +199,7 @@ export function coordinateMysqlPasswordPersistence<
|
|
|
189
199
|
coordinateTargetPasswordPersistence<TransactionOf<D>, Out, E, Exclude<R, PasswordPersistence>>(
|
|
190
200
|
database,
|
|
191
201
|
options.mapping,
|
|
192
|
-
configuration(database),
|
|
202
|
+
configuration(transactionService(database)),
|
|
193
203
|
options.proofMapping,
|
|
194
204
|
(
|
|
195
205
|
transaction: TransactionOf<D>,
|
|
@@ -215,10 +225,12 @@ export const makeMysqlPasswordRegistrationServices = <
|
|
|
215
225
|
Rq extends AnyMySqlTable,
|
|
216
226
|
NativeId,
|
|
217
227
|
>(
|
|
218
|
-
database: Database,
|
|
219
228
|
mapping: PasswordRegistrationMapping<Registration, S, I, C, AC, Rq, NativeId>,
|
|
220
229
|
) =>
|
|
221
|
-
|
|
230
|
+
Effect.flatMap(
|
|
231
|
+
Effect.map(acquireTransactionService(DatabaseService), configuration),
|
|
232
|
+
(configuration) => makeTargetPasswordRegistrationServices<Registration>(mapping, configuration),
|
|
233
|
+
).pipe(Effect.provideServiceEffect(CurrentPasswordSql, nativeDatabase(DatabaseService)));
|
|
222
234
|
|
|
223
235
|
export function coordinateMysqlPasswordRegistration<
|
|
224
236
|
TargetId,
|
|
@@ -320,7 +332,7 @@ export function coordinateMysqlPasswordRegistration<
|
|
|
320
332
|
>(
|
|
321
333
|
database,
|
|
322
334
|
options.mapping,
|
|
323
|
-
configuration(database),
|
|
335
|
+
configuration(transactionService(database)),
|
|
324
336
|
(
|
|
325
337
|
transaction: TransactionOf<D>,
|
|
326
338
|
services: { readonly registrationAuthority: PasswordRegistrationAuthority<Registration> },
|
|
@@ -4,16 +4,24 @@ import type { AnyRelations } from "drizzle-orm";
|
|
|
4
4
|
import type { EffectMysql2Database } from "drizzle-orm/effect-mysql2";
|
|
5
5
|
import type { AnyMySqlTable } from "drizzle-orm/mysql-core";
|
|
6
6
|
import { Effect, Context } from "effect";
|
|
7
|
-
import type { SqlError } from "effect/
|
|
7
|
+
import type { SqlError } from "effect/sql/SqlError";
|
|
8
8
|
|
|
9
9
|
import { updateValues } from "./model";
|
|
10
|
+
import { Database as DatabaseService } from "./mysql-database";
|
|
11
|
+
import { nativeDatabase } from "./native-database";
|
|
10
12
|
import type { ProofPersistenceMapping } from "./proof-model";
|
|
13
|
+
import { CurrentProofSql } from "./proof-sql";
|
|
11
14
|
import type { ProofSqlQuery } from "./proof-sql";
|
|
12
15
|
import {
|
|
13
16
|
coordinateTargetProofPersistence,
|
|
14
17
|
makeTargetProofPersistenceServices,
|
|
15
18
|
sqlClientProofStandaloneGuard,
|
|
16
19
|
} from "./proof-target";
|
|
20
|
+
import {
|
|
21
|
+
type TransactionService,
|
|
22
|
+
acquireTransactionService,
|
|
23
|
+
transactionService,
|
|
24
|
+
} from "./standalone-guard";
|
|
17
25
|
import type { SuppliedService } from "./SuppliedService";
|
|
18
26
|
|
|
19
27
|
type Database = EffectMysql2Database<AnyRelations>;
|
|
@@ -33,10 +41,10 @@ type Mapping<
|
|
|
33
41
|
NativeId,
|
|
34
42
|
> = ProofPersistenceMapping<Rq, S, G, Cn, Rs, A, F, C, Sub, I, Cr, NativeId>;
|
|
35
43
|
|
|
36
|
-
const configuration = (
|
|
44
|
+
const configuration = (service: TransactionService | undefined) => ({
|
|
37
45
|
mode: "interactive" as const,
|
|
38
46
|
locking: true,
|
|
39
|
-
standaloneGuard: sqlClientProofStandaloneGuard(
|
|
47
|
+
standaloneGuard: sqlClientProofStandaloneGuard(service),
|
|
40
48
|
insertIfAbsent: (query: ProofSqlQuery, selfKey: string, selfValue: unknown) =>
|
|
41
49
|
query.onDuplicateKeyUpdate({
|
|
42
50
|
set: updateValues([[selfKey, selfValue]]),
|
|
@@ -57,9 +65,12 @@ export const makeMysqlProofPersistenceServices = <
|
|
|
57
65
|
Cr extends AnyMySqlTable,
|
|
58
66
|
NativeId,
|
|
59
67
|
>(
|
|
60
|
-
database: Database,
|
|
61
68
|
mapping: Mapping<Rq, S, G, Cn, Rs, A, F, C, Sub, I, Cr, NativeId>,
|
|
62
|
-
) =>
|
|
69
|
+
) =>
|
|
70
|
+
Effect.flatMap(
|
|
71
|
+
Effect.map(acquireTransactionService(DatabaseService), configuration),
|
|
72
|
+
(configuration) => makeTargetProofPersistenceServices(mapping, configuration),
|
|
73
|
+
).pipe(Effect.provideServiceEffect(CurrentProofSql, nativeDatabase(DatabaseService)));
|
|
63
74
|
|
|
64
75
|
export function coordinateMysqlProofPersistence<
|
|
65
76
|
D extends Database,
|
|
@@ -164,7 +175,7 @@ export function coordinateMysqlProofPersistence<
|
|
|
164
175
|
coordinateTargetProofPersistence<Transaction, A, E, Exclude<R, ProofPersistence>>(
|
|
165
176
|
database,
|
|
166
177
|
options.mapping,
|
|
167
|
-
configuration(database),
|
|
178
|
+
configuration(transactionService(database)),
|
|
168
179
|
(
|
|
169
180
|
transaction: Transaction,
|
|
170
181
|
services: { readonly proofPersistence: ProofPersistence["Service"] },
|
|
@@ -12,14 +12,17 @@ import type { AnyRelations } from "drizzle-orm";
|
|
|
12
12
|
import type { EffectMysql2Database } from "drizzle-orm/effect-mysql2";
|
|
13
13
|
import type { AnyMySqlTable } from "drizzle-orm/mysql-core";
|
|
14
14
|
import { Effect, Context } from "effect";
|
|
15
|
-
import type { SqlError } from "effect/
|
|
15
|
+
import type { SqlError } from "effect/sql/SqlError";
|
|
16
16
|
|
|
17
|
+
import { Database as DatabaseService } from "./mysql-database";
|
|
18
|
+
import { nativeDatabase } from "./native-database";
|
|
17
19
|
import type {
|
|
18
20
|
AuthenticationAuthorityMapping,
|
|
19
21
|
PendingAuthenticationMapping,
|
|
20
22
|
SignedSessionValidityMapping,
|
|
21
23
|
StatefulSessionMapping,
|
|
22
24
|
} from "./session-model";
|
|
25
|
+
import { CurrentSessionSql } from "./session-sql";
|
|
23
26
|
import {
|
|
24
27
|
coordinateTargetAuthenticationAuthority,
|
|
25
28
|
coordinateTargetPendingAuthentication,
|
|
@@ -33,15 +36,20 @@ import {
|
|
|
33
36
|
makeTargetSessionStepUpServices,
|
|
34
37
|
coordinateTargetSessionStepUp,
|
|
35
38
|
} from "./session-target";
|
|
39
|
+
import {
|
|
40
|
+
type TransactionService,
|
|
41
|
+
acquireTransactionService,
|
|
42
|
+
transactionService,
|
|
43
|
+
} from "./standalone-guard";
|
|
36
44
|
import type { SuppliedService } from "./SuppliedService";
|
|
37
45
|
|
|
38
46
|
type Database = EffectMysql2Database<AnyRelations>;
|
|
39
47
|
type Transaction = Parameters<Parameters<Database["transaction"]>[0]>[0];
|
|
40
48
|
|
|
41
|
-
const configuration = (
|
|
49
|
+
const configuration = (service: TransactionService | undefined) => ({
|
|
42
50
|
mode: "interactive" as const,
|
|
43
51
|
locking: true,
|
|
44
|
-
standaloneGuard: sqlClientSessionStandaloneGuard(
|
|
52
|
+
standaloneGuard: sqlClientSessionStandaloneGuard(service),
|
|
45
53
|
});
|
|
46
54
|
|
|
47
55
|
export const makeMysqlAuthenticationAuthorityServices = <
|
|
@@ -52,9 +60,12 @@ export const makeMysqlAuthenticationAuthorityServices = <
|
|
|
52
60
|
P extends AnyMySqlTable,
|
|
53
61
|
NativeId,
|
|
54
62
|
>(
|
|
55
|
-
database: Database,
|
|
56
63
|
mapping: AuthenticationAuthorityMapping<Claims, S, C, F, P, NativeId>,
|
|
57
|
-
) =>
|
|
64
|
+
) =>
|
|
65
|
+
Effect.flatMap(
|
|
66
|
+
Effect.map(acquireTransactionService(DatabaseService), configuration),
|
|
67
|
+
(configuration) => makeTargetAuthenticationAuthorityServices<Claims>(mapping, configuration),
|
|
68
|
+
).pipe(Effect.provideServiceEffect(CurrentSessionSql, nativeDatabase(DatabaseService)));
|
|
58
69
|
|
|
59
70
|
export const makeMysqlPendingAuthenticationServices = <
|
|
60
71
|
Claims,
|
|
@@ -64,9 +75,12 @@ export const makeMysqlPendingAuthenticationServices = <
|
|
|
64
75
|
F extends AnyMySqlTable,
|
|
65
76
|
NativeId,
|
|
66
77
|
>(
|
|
67
|
-
database: Database,
|
|
68
78
|
mapping: PendingAuthenticationMapping<Claims, S, C, P, F, NativeId>,
|
|
69
|
-
) =>
|
|
79
|
+
) =>
|
|
80
|
+
Effect.flatMap(
|
|
81
|
+
Effect.map(acquireTransactionService(DatabaseService), configuration),
|
|
82
|
+
(configuration) => makeTargetPendingAuthenticationServices<Claims>(mapping, configuration),
|
|
83
|
+
).pipe(Effect.provideServiceEffect(CurrentSessionSql, nativeDatabase(DatabaseService)));
|
|
70
84
|
|
|
71
85
|
export const makeMysqlStatefulSessionServices = <
|
|
72
86
|
Claims,
|
|
@@ -78,9 +92,12 @@ export const makeMysqlStatefulSessionServices = <
|
|
|
78
92
|
NativeId,
|
|
79
93
|
NativeSessionId,
|
|
80
94
|
>(
|
|
81
|
-
database: Database,
|
|
82
95
|
mapping: StatefulSessionMapping<Claims, S, C, Session, F, P, NativeId, NativeSessionId>,
|
|
83
|
-
) =>
|
|
96
|
+
) =>
|
|
97
|
+
Effect.flatMap(
|
|
98
|
+
Effect.map(acquireTransactionService(DatabaseService), configuration),
|
|
99
|
+
(configuration) => makeTargetStatefulSessionServices<Claims>(mapping, configuration),
|
|
100
|
+
).pipe(Effect.provideServiceEffect(CurrentSessionSql, nativeDatabase(DatabaseService)));
|
|
84
101
|
|
|
85
102
|
export const makeMysqlSignedSessionValidityServices = <
|
|
86
103
|
S extends AnyMySqlTable,
|
|
@@ -88,9 +105,12 @@ export const makeMysqlSignedSessionValidityServices = <
|
|
|
88
105
|
NativeId,
|
|
89
106
|
NativeSessionId,
|
|
90
107
|
>(
|
|
91
|
-
database: Database,
|
|
92
108
|
mapping: SignedSessionValidityMapping<S, T, NativeId, NativeSessionId>,
|
|
93
|
-
) =>
|
|
109
|
+
) =>
|
|
110
|
+
Effect.flatMap(
|
|
111
|
+
Effect.map(acquireTransactionService(DatabaseService), configuration),
|
|
112
|
+
(configuration) => makeTargetSignedSessionValidityServices(mapping, configuration),
|
|
113
|
+
).pipe(Effect.provideServiceEffect(CurrentSessionSql, nativeDatabase(DatabaseService)));
|
|
94
114
|
|
|
95
115
|
export function coordinateMysqlAuthenticationAuthority<
|
|
96
116
|
D extends Database,
|
|
@@ -183,7 +203,7 @@ export function coordinateMysqlAuthenticationAuthority<
|
|
|
183
203
|
>(
|
|
184
204
|
database,
|
|
185
205
|
options.mapping,
|
|
186
|
-
configuration(database),
|
|
206
|
+
configuration(transactionService(database)),
|
|
187
207
|
(
|
|
188
208
|
transaction: Transaction,
|
|
189
209
|
services: { readonly authenticationAuthority: AuthenticationAuthority["Service"] },
|
|
@@ -290,7 +310,7 @@ export function coordinateMysqlPendingAuthentication<
|
|
|
290
310
|
coordinateTargetPendingAuthentication<Claims, Transaction, A, E, Exclude<R, TargetId>>(
|
|
291
311
|
database,
|
|
292
312
|
options.mapping,
|
|
293
|
-
configuration(database),
|
|
313
|
+
configuration(transactionService(database)),
|
|
294
314
|
(
|
|
295
315
|
transaction: Transaction,
|
|
296
316
|
services: { readonly pendingAuthentication: PendingAuthentication<Claims> },
|
|
@@ -442,7 +462,7 @@ export function coordinateMysqlStatefulSessions<
|
|
|
442
462
|
>(
|
|
443
463
|
database,
|
|
444
464
|
options.mapping,
|
|
445
|
-
configuration(database),
|
|
465
|
+
configuration(transactionService(database)),
|
|
446
466
|
(
|
|
447
467
|
transaction: Transaction,
|
|
448
468
|
services: {
|
|
@@ -550,7 +570,7 @@ export function coordinateMysqlSignedSessionValidity<
|
|
|
550
570
|
coordinateTargetSignedSessionValidity<Transaction, A, E, Exclude<R, TargetId>>(
|
|
551
571
|
database,
|
|
552
572
|
options.mapping,
|
|
553
|
-
configuration(database),
|
|
573
|
+
configuration(transactionService(database)),
|
|
554
574
|
(
|
|
555
575
|
transaction: Transaction,
|
|
556
576
|
services: { readonly signedSessionValidity: SignedSessionValidity },
|
|
@@ -579,10 +599,13 @@ export const makeMysqlSessionStepUpServices = <
|
|
|
579
599
|
NativeId,
|
|
580
600
|
NativeSessionId,
|
|
581
601
|
>(
|
|
582
|
-
database: Database,
|
|
583
602
|
mapping: SessionStepUpMapping<NoInfer<Claims>, S, C, I, Session, T, NativeId, NativeSessionId>,
|
|
584
603
|
target: Context.Service<Id, SessionStepUpPersistence<Claims>>,
|
|
585
|
-
) =>
|
|
604
|
+
) =>
|
|
605
|
+
Effect.flatMap(
|
|
606
|
+
Effect.map(acquireTransactionService(DatabaseService), configuration),
|
|
607
|
+
(configuration) => makeTargetSessionStepUpServices(mapping, target, configuration),
|
|
608
|
+
).pipe(Effect.provideServiceEffect(CurrentSessionSql, nativeDatabase(DatabaseService)));
|
|
586
609
|
|
|
587
610
|
export function coordinateMysqlSessionStepUp<
|
|
588
611
|
Claims,
|
|
@@ -724,7 +747,7 @@ export function coordinateMysqlSessionStepUp<
|
|
|
724
747
|
database,
|
|
725
748
|
options.mapping,
|
|
726
749
|
options.target,
|
|
727
|
-
configuration(database),
|
|
750
|
+
configuration(transactionService(database)),
|
|
728
751
|
(
|
|
729
752
|
transaction: Parameters<Parameters<D["transaction"]>[0]>[0],
|
|
730
753
|
services: { readonly sessionStepUpPersistence: SessionStepUpPersistence<Claims> },
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
TransactionNativeDatabase,
|
|
3
|
+
SessionSqlDatabase,
|
|
4
|
+
PasswordSqlDatabase,
|
|
5
|
+
EmailSqlDatabase,
|
|
6
|
+
ProofSqlDatabase,
|
|
7
|
+
} from "@yielded/auth-persistence/Adapter";
|
|
8
|
+
import { type Context, Effect } from "effect";
|
|
9
|
+
|
|
10
|
+
/** Drizzle omits its captured $client from database class types, and only D1
|
|
11
|
+
* exposes batch. Its generic query builders implement the SQL kernel contracts
|
|
12
|
+
* through drizzleQueryOperations. The selected driver mode controls native calls. */
|
|
13
|
+
export const nativeDatabase = <Id, Database>(databaseService: Context.Key<Id, Database>) =>
|
|
14
|
+
Effect.map(
|
|
15
|
+
Effect.service(databaseService),
|
|
16
|
+
(database) =>
|
|
17
|
+
database as unknown as TransactionNativeDatabase &
|
|
18
|
+
SessionSqlDatabase &
|
|
19
|
+
PasswordSqlDatabase &
|
|
20
|
+
EmailSqlDatabase &
|
|
21
|
+
ProofSqlDatabase,
|
|
22
|
+
);
|
|
@@ -132,6 +132,7 @@ export const claimRefresh = Effect.fn("oauthConnected.claimRefresh")(function* (
|
|
|
132
132
|
|
|
133
133
|
const claim = snapshotOAuthSync(M.OAuthConnectedRefreshClaim, {
|
|
134
134
|
grant: input.grant,
|
|
135
|
+
order: String(yield* S.nextOrder(mapping, read.client)),
|
|
135
136
|
claimId: input.claimId,
|
|
136
137
|
claimedAtMillis: read.now,
|
|
137
138
|
claimExpiresAtMillis: expires,
|
|
@@ -204,10 +205,16 @@ export const settleRefresh = Effect.fn("oauthConnected.settleRefresh")(function*
|
|
|
204
205
|
if (incoming !== undefined)
|
|
205
206
|
invariant(
|
|
206
207
|
C.sameContext(
|
|
207
|
-
{
|
|
208
|
+
{
|
|
209
|
+
...incoming.context,
|
|
210
|
+
tokenVersion: old.tokenVersion,
|
|
211
|
+
metadata: old.metadata,
|
|
212
|
+
exchangeOrder: old.exchangeOrder,
|
|
213
|
+
},
|
|
208
214
|
old,
|
|
209
215
|
) &&
|
|
210
216
|
incoming.context.tokenVersion === input.claim.nextTokenVersion &&
|
|
217
|
+
incoming.context.exchangeOrder === input.claim.order &&
|
|
211
218
|
validMetadata(incoming.context, now) &&
|
|
212
219
|
incoming.context.metadata.obtainedAtMillis >= input.claim.claimedAtMillis &&
|
|
213
220
|
(incoming.context.metadata.refreshUseUntilMillis === undefined ||
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NativeDatabase } from "@yielded/auth-persistence/Adapter";
|
|
1
2
|
import type { LifecycleHooks } from "@yielded/auth/Hooks";
|
|
2
3
|
import {
|
|
3
4
|
OAuthConnectedPersistence,
|
|
@@ -9,6 +10,7 @@ import { Effect, Context } from "effect";
|
|
|
9
10
|
|
|
10
11
|
import { makeD1Owner } from "./d1-planning";
|
|
11
12
|
import { D1BatchStatements } from "./D1BatchStatements";
|
|
13
|
+
import { nativeDatabase } from "./native-database";
|
|
12
14
|
import type {
|
|
13
15
|
OAuthConnectedMapping,
|
|
14
16
|
OAuthConnectedRevocationMapping,
|
|
@@ -28,11 +30,13 @@ type TransactionOf<D> = D extends { readonly transaction: (...args: any[]) => an
|
|
|
28
30
|
const unavailable = () => OAuthUnavailable.make({});
|
|
29
31
|
|
|
30
32
|
export const makeOAuthConnectedTarget = <
|
|
33
|
+
DatabaseId,
|
|
31
34
|
Database,
|
|
32
35
|
Family extends Table,
|
|
33
36
|
Extra = {},
|
|
34
37
|
Synchronous extends boolean = false,
|
|
35
38
|
>(
|
|
39
|
+
databaseService: Context.Service<DatabaseId, Database>,
|
|
36
40
|
configuration: OAuthTargetConfiguration,
|
|
37
41
|
) => {
|
|
38
42
|
function coordinateOAuthConnected<
|
|
@@ -300,9 +304,11 @@ export const makeOAuthConnectedTarget = <
|
|
|
300
304
|
N,
|
|
301
305
|
J extends Family = never,
|
|
302
306
|
>(
|
|
303
|
-
database: Database,
|
|
304
307
|
mapping: OAuthConnectedMapping<S, AC, T, O, F, G, C, H, UA, DC, N, J> & Extra,
|
|
305
|
-
) =>
|
|
308
|
+
) =>
|
|
309
|
+
makeTargetOAuthConnectedServices(mapping, configuration).pipe(
|
|
310
|
+
Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),
|
|
311
|
+
),
|
|
306
312
|
makeOAuthConnectedRevocationServices: <
|
|
307
313
|
T extends Family,
|
|
308
314
|
O extends Family,
|
|
@@ -313,15 +319,18 @@ export const makeOAuthConnectedTarget = <
|
|
|
313
319
|
J extends Family,
|
|
314
320
|
N,
|
|
315
321
|
>(
|
|
316
|
-
database: Database,
|
|
317
322
|
mapping: OAuthConnectedRevocationMapping<T, O, F, G, C, H, J, N> & Extra,
|
|
318
|
-
) =>
|
|
323
|
+
) =>
|
|
324
|
+
makeTargetOAuthConnectedRevocationServices(mapping, configuration).pipe(
|
|
325
|
+
Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),
|
|
326
|
+
),
|
|
319
327
|
coordinateOAuthConnected,
|
|
320
328
|
coordinateOAuthConnectedRevocations,
|
|
321
329
|
};
|
|
322
330
|
};
|
|
323
331
|
|
|
324
|
-
export const makeD1OAuthConnectedTarget = <Database, Family extends Table, Extra>(
|
|
332
|
+
export const makeD1OAuthConnectedTarget = <DatabaseId, Database, Family extends Table, Extra>(
|
|
333
|
+
databaseService: Context.Service<DatabaseId, Database>,
|
|
325
334
|
configuration: OAuthTargetConfiguration,
|
|
326
335
|
) => {
|
|
327
336
|
function coordinateOAuthConnected<
|
|
@@ -374,6 +383,9 @@ export const makeD1OAuthConnectedTarget = <Database, Family extends Table, Extra
|
|
|
374
383
|
);
|
|
375
384
|
|
|
376
385
|
const service: OAuthConnectedPersistence["Service"] = {
|
|
386
|
+
claimSignIn: (input, prepare) => owner.run(original.claimSignIn(input, prepare)),
|
|
387
|
+
inspectSignIn: (input) => owner.run(original.inspectSignIn(input)),
|
|
388
|
+
settleSignIn: (input, prepare) => owner.run(original.settleSignIn(input, prepare)),
|
|
377
389
|
capture: (input) => owner.run(original.capture(input)),
|
|
378
390
|
issue: (input, prepare) => owner.run(original.issue(input, prepare)),
|
|
379
391
|
preflight: (input) => owner.run(original.preflight(input)),
|
|
@@ -458,7 +470,10 @@ export const makeD1OAuthConnectedTarget = <Database, Family extends Table, Extra
|
|
|
458
470
|
}
|
|
459
471
|
|
|
460
472
|
return {
|
|
461
|
-
...makeOAuthConnectedTarget<Database, Family, Extra>(
|
|
473
|
+
...makeOAuthConnectedTarget<DatabaseId, Database, Family, Extra>(
|
|
474
|
+
databaseService,
|
|
475
|
+
configuration,
|
|
476
|
+
),
|
|
462
477
|
coordinateOAuthConnected,
|
|
463
478
|
coordinateOAuthConnectedRevocations,
|
|
464
479
|
};
|
|
@@ -105,6 +105,19 @@ const snapshot =
|
|
|
105
105
|
snapshotOAuthSync(schema, input);
|
|
106
106
|
|
|
107
107
|
export const connectedInputs = {
|
|
108
|
+
claimSignIn: snapshot(
|
|
109
|
+
Schema.Struct({ claim: M.OAuthClaim, configuration: M.OAuthConnectedConfiguration }),
|
|
110
|
+
),
|
|
111
|
+
inspectSignIn: snapshot(
|
|
112
|
+
Schema.Struct({
|
|
113
|
+
reservation: M.OAuthSignInAccessClaim,
|
|
114
|
+
credential: M.OAuthCredentialSnapshot,
|
|
115
|
+
grantId: M.OAuthGrantId,
|
|
116
|
+
}),
|
|
117
|
+
),
|
|
118
|
+
settleSignIn: snapshot(
|
|
119
|
+
Schema.Struct({ reservation: M.OAuthSignInAccessClaim, outcome: M.OAuthSignInAccessOutcome }),
|
|
120
|
+
),
|
|
108
121
|
capture: snapshot(capture),
|
|
109
122
|
issue: snapshot(issue),
|
|
110
123
|
preflight: snapshot(M.OAuthConnectedAccess),
|
|
@@ -7,6 +7,8 @@ import type { SubjectIdCodec } from "./model";
|
|
|
7
7
|
import type {
|
|
8
8
|
OAuthAuthorityReadTable,
|
|
9
9
|
OAuthClock,
|
|
10
|
+
OAuthCredentialReadTable,
|
|
11
|
+
OAuthFlowTable,
|
|
10
12
|
OAuthOwnershipMutation,
|
|
11
13
|
OAuthSubjectReadTable,
|
|
12
14
|
requiredOAuthTupleConstraints,
|
|
@@ -53,6 +55,9 @@ export interface OAuthConnectedFlowTable<F extends Table, N> {
|
|
|
53
55
|
readonly work: Column<F>;
|
|
54
56
|
/** Exact sealed quarantine when no correctly sealed revocation job is available. */
|
|
55
57
|
readonly custody: Column<F>;
|
|
58
|
+
/** Required when retaining grants during sign-in. subjectId is NULL until
|
|
59
|
+
* identity resolution; custom required columns are supplied by this encoder. */
|
|
60
|
+
readonly encodeSignIn?: (reservation: M.OAuthSignInAccessClaim) => InferInsertModel<F>;
|
|
56
61
|
readonly encodeInsert: (input: {
|
|
57
62
|
readonly flow: M.OAuthConnectedPendingFlow;
|
|
58
63
|
readonly subjectId: N;
|
|
@@ -192,6 +197,12 @@ export type OAuthConnectedPolicyInput<N> = {
|
|
|
192
197
|
readonly configuration: M.OAuthConnectedConfiguration;
|
|
193
198
|
readonly grant?: M.OAuthConnectedTokenContext;
|
|
194
199
|
}
|
|
200
|
+
| {
|
|
201
|
+
readonly kind: "sign-in";
|
|
202
|
+
readonly credential: M.OAuthCredentialSnapshot;
|
|
203
|
+
readonly configuration: M.OAuthConnectedConfiguration;
|
|
204
|
+
readonly grant?: M.OAuthConnectedTokenContext;
|
|
205
|
+
}
|
|
195
206
|
| {
|
|
196
207
|
readonly kind: "metadata" | "use";
|
|
197
208
|
readonly authorization: M.OAuthConnectedUseAuthorization;
|
|
@@ -307,6 +318,12 @@ export interface OAuthConnectedMapping<
|
|
|
307
318
|
readonly subject: OAuthConnectedSubjectTable<S>;
|
|
308
319
|
readonly authority: OAuthAuthorityReadTable<AC>;
|
|
309
320
|
readonly admission: OAuthConnectedAdmissionTable<A, N>;
|
|
321
|
+
/** Same shared sign-in tables used by OAuthSignInPersistence. Enable only
|
|
322
|
+
* alongside a nullable connected-flow subjectId and flow.encodeSignIn. */
|
|
323
|
+
readonly signIn?: {
|
|
324
|
+
readonly credential: OAuthCredentialReadTable<Table>;
|
|
325
|
+
readonly flow: OAuthFlowTable<Table>;
|
|
326
|
+
};
|
|
310
327
|
readonly command: OAuthConnectedCommandTable<D, N>;
|
|
311
328
|
readonly policy: OAuthConnectedSqlPolicy<N>;
|
|
312
329
|
readonly constraints: typeof requiredOAuthConnectedConstraints;
|
|
@@ -7,7 +7,7 @@ import * as C from "./oauth-connected-custody";
|
|
|
7
7
|
import * as F from "./oauth-connected-flow";
|
|
8
8
|
import * as S from "./oauth-connected-state";
|
|
9
9
|
import { both, col, equal, CurrentOAuthTransaction } from "./oauth-owner";
|
|
10
|
-
import { invariant, sameIdentity } from "./oauth-state";
|
|
10
|
+
import { invariant, sameIdentity, oauthIdentityKey } from "./oauth-state";
|
|
11
11
|
|
|
12
12
|
export const validMetadata = (context: M.OAuthConnectedTokenContext, now: number) => {
|
|
13
13
|
const m = context.metadata,
|
|
@@ -35,6 +35,67 @@ export const validMetadata = (context: M.OAuthConnectedTokenContext, now: number
|
|
|
35
35
|
);
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
+
/** The only writer that activates or replaces a confirmed connected grant. */
|
|
39
|
+
export const activateGrant = Effect.fn("oauthConnected.activateGrant")(function* (
|
|
40
|
+
mapping: S.Mapping,
|
|
41
|
+
grant: M.OAuthConnectedStoredGrant,
|
|
42
|
+
native: unknown,
|
|
43
|
+
now: number,
|
|
44
|
+
replacing: boolean,
|
|
45
|
+
) {
|
|
46
|
+
const owner = yield* CurrentOAuthTransaction;
|
|
47
|
+
const token = grant.context;
|
|
48
|
+
const g = mapping.grant;
|
|
49
|
+
const identityKey = oauthIdentityKey(token.identity);
|
|
50
|
+
const clientKey = S.clientKey(token.configuration);
|
|
51
|
+
const cohortKey = S.cohortKey(clientKey, identityKey);
|
|
52
|
+
|
|
53
|
+
const values = {
|
|
54
|
+
...g.encodeInsert({
|
|
55
|
+
grant: snapshotOAuthSync(M.OAuthConnectedStoredGrant, grant),
|
|
56
|
+
subjectId: S.nativeCopy(native),
|
|
57
|
+
}),
|
|
58
|
+
[g.moduleId]: token.moduleId,
|
|
59
|
+
[g.grantId]: token.grantId,
|
|
60
|
+
[g.subjectId]: native,
|
|
61
|
+
[g.identityKey]: identityKey,
|
|
62
|
+
[g.activeIdentityKey]: identityKey,
|
|
63
|
+
[g.clientKey]: clientKey,
|
|
64
|
+
[g.cohortKey]: cohortKey,
|
|
65
|
+
[g.profileKey]: token.configuration.profile.key,
|
|
66
|
+
[g.grantVersion]: token.grantVersion,
|
|
67
|
+
[g.tokenVersion]: token.tokenVersion,
|
|
68
|
+
[g.cohortGeneration]: token.cohortGeneration,
|
|
69
|
+
[g.state]: "Active",
|
|
70
|
+
[g.version]: owner.marker,
|
|
71
|
+
[g.context]: S.tokenContextStorage.encode(token),
|
|
72
|
+
[g.sealed]: S.sealedStorage.encode(grant.sealed),
|
|
73
|
+
[g.summary]: S.summaryStorage.encode(C.summary(token)),
|
|
74
|
+
[g.revocationJobId]: null,
|
|
75
|
+
[g.refreshWork]: "None",
|
|
76
|
+
[g.refreshClaim]: null,
|
|
77
|
+
[g.refreshClaimExpiresAt]: null,
|
|
78
|
+
[g.retentionUntil]: mapping.clock.encodeInstant(
|
|
79
|
+
S.retainedUntil(
|
|
80
|
+
mapping,
|
|
81
|
+
Math.max(now, token.metadata.useUntilMillis, token.metadata.refreshUseUntilMillis ?? 0),
|
|
82
|
+
),
|
|
83
|
+
),
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
if (!replacing) {
|
|
87
|
+
yield* owner.insert(g.table, values, {
|
|
88
|
+
[g.moduleId]: token.moduleId,
|
|
89
|
+
[g.grantId]: token.grantId,
|
|
90
|
+
});
|
|
91
|
+
} else
|
|
92
|
+
yield* owner.update(
|
|
93
|
+
g.table,
|
|
94
|
+
{ [g.moduleId]: token.moduleId, [g.grantId]: token.grantId },
|
|
95
|
+
values,
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
|
|
38
99
|
export const settle = Effect.fn("oauthConnected.settle")(function* (
|
|
39
100
|
mapping: S.Mapping,
|
|
40
101
|
input: F.Input<"settle">,
|
|
@@ -123,7 +184,8 @@ export const settle = Effect.fn("oauthConnected.settle")(function* (
|
|
|
123
184
|
|
|
124
185
|
if (claimed === undefined) return { _tag: "Rejected" } as const;
|
|
125
186
|
invariant(
|
|
126
|
-
|
|
187
|
+
token.exchangeOrder === input.claim.order &&
|
|
188
|
+
validMetadata(token, claimed.now) &&
|
|
127
189
|
token.metadata.obtainedAtMillis >= input.claim.claimedAtMillis,
|
|
128
190
|
);
|
|
129
191
|
const reconnect = c.reconnect;
|
|
@@ -177,46 +239,7 @@ export const settle = Effect.fn("oauthConnected.settle")(function* (
|
|
|
177
239
|
if (tuple.row[t.state] === "Unowned")
|
|
178
240
|
yield* F.acquireTuple(mapping.ownership, token.identity, tuple.key, S.nativeCopy(native));
|
|
179
241
|
|
|
180
|
-
|
|
181
|
-
...g.encodeInsert({
|
|
182
|
-
grant: snapshotOAuthSync(M.OAuthConnectedStoredGrant, grant),
|
|
183
|
-
subjectId: S.nativeCopy(native),
|
|
184
|
-
}),
|
|
185
|
-
[g.moduleId]: c.moduleId,
|
|
186
|
-
[g.grantId]: c.grantId,
|
|
187
|
-
[g.subjectId]: native,
|
|
188
|
-
[g.identityKey]: tuple.key,
|
|
189
|
-
[g.activeIdentityKey]: tuple.key,
|
|
190
|
-
[g.clientKey]: cl.id,
|
|
191
|
-
[g.cohortKey]: co.id,
|
|
192
|
-
[g.profileKey]: c.profile.key,
|
|
193
|
-
[g.grantVersion]: token.grantVersion,
|
|
194
|
-
[g.tokenVersion]: token.tokenVersion,
|
|
195
|
-
[g.cohortGeneration]: token.cohortGeneration,
|
|
196
|
-
[g.state]: "Active",
|
|
197
|
-
[g.version]: owner.marker,
|
|
198
|
-
[g.context]: S.tokenContextStorage.encode(token),
|
|
199
|
-
[g.sealed]: S.sealedStorage.encode(grant.sealed),
|
|
200
|
-
[g.summary]: S.summaryStorage.encode(C.summary(token)),
|
|
201
|
-
[g.revocationJobId]: null,
|
|
202
|
-
[g.refreshWork]: "None",
|
|
203
|
-
[g.refreshClaim]: null,
|
|
204
|
-
[g.refreshClaimExpiresAt]: null,
|
|
205
|
-
[g.retentionUntil]: mapping.clock.encodeInstant(
|
|
206
|
-
S.retainedUntil(
|
|
207
|
-
mapping,
|
|
208
|
-
Math.max(
|
|
209
|
-
claimed.now,
|
|
210
|
-
token.metadata.useUntilMillis,
|
|
211
|
-
token.metadata.refreshUseUntilMillis ?? 0,
|
|
212
|
-
),
|
|
213
|
-
),
|
|
214
|
-
),
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
if (original === undefined) {
|
|
218
|
-
yield* owner.insert(g.table, values, { [g.moduleId]: c.moduleId, [g.grantId]: c.grantId });
|
|
219
|
-
} else yield* owner.update(g.table, { [g.moduleId]: c.moduleId, [g.grantId]: c.grantId }, values);
|
|
242
|
+
yield* activateGrant(mapping, grant, native, claimed.now, original !== undefined);
|
|
220
243
|
yield* F.terminal(mapping, input.claim, "Connected", "Resolved", { cohort: co.id });
|
|
221
244
|
owner.postconditions.push(
|
|
222
245
|
sql`${mapping.clock.engineNowMillis} >= ${claimed.now} and ${mapping.clock.engineNowMillis} < ${Math.min(input.claim.claimExpiresAtMillis, token.metadata.useUntilMillis)}`,
|