@effect-auth/core 0.1.0-alpha.1 → 0.1.0-alpha.10
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 +728 -72
- package/dist/ApiKey.d.ts +207 -0
- package/dist/ApiKey.d.ts.map +1 -0
- package/dist/ApiKey.js +275 -0
- package/dist/ApiKey.js.map +1 -0
- package/dist/AuditLog.d.ts +275 -1
- package/dist/AuditLog.d.ts.map +1 -1
- package/dist/AuditLog.js +213 -1
- package/dist/AuditLog.js.map +1 -1
- package/dist/AuthConfig.d.ts +42 -0
- package/dist/AuthConfig.d.ts.map +1 -0
- package/dist/AuthConfig.js +43 -0
- package/dist/AuthConfig.js.map +1 -0
- package/dist/AuthFlow.d.ts +462 -36
- package/dist/AuthFlow.d.ts.map +1 -1
- package/dist/AuthFlow.js +657 -5
- package/dist/AuthFlow.js.map +1 -1
- package/dist/AuthKernel.d.ts +3 -0
- package/dist/AuthKernel.d.ts.map +1 -0
- package/dist/AuthKernel.js +9 -0
- package/dist/AuthKernel.js.map +1 -0
- package/dist/Challenge.d.ts +24 -4
- package/dist/Challenge.d.ts.map +1 -1
- package/dist/Challenge.js +167 -1
- package/dist/Challenge.js.map +1 -1
- package/dist/Client.d.ts +378 -0
- package/dist/Client.d.ts.map +1 -0
- package/dist/Client.js +768 -0
- package/dist/Client.js.map +1 -0
- package/dist/Crypto.d.ts +6 -1
- package/dist/Crypto.d.ts.map +1 -1
- package/dist/Crypto.js +62 -1
- package/dist/Crypto.js.map +1 -1
- package/dist/EffectQbSqliteStorage.d.ts +600 -0
- package/dist/EffectQbSqliteStorage.d.ts.map +1 -0
- package/dist/EffectQbSqliteStorage.js +1637 -0
- package/dist/EffectQbSqliteStorage.js.map +1 -0
- package/dist/EmailOtp.d.ts +120 -0
- package/dist/EmailOtp.d.ts.map +1 -0
- package/dist/EmailOtp.js +286 -0
- package/dist/EmailOtp.js.map +1 -0
- package/dist/EmailVerification.d.ts +121 -0
- package/dist/EmailVerification.d.ts.map +1 -0
- package/dist/EmailVerification.js +200 -0
- package/dist/EmailVerification.js.map +1 -0
- package/dist/HttpApi/Api.d.ts +1956 -0
- package/dist/HttpApi/Api.d.ts.map +1 -0
- package/dist/HttpApi/Api.js +2325 -0
- package/dist/HttpApi/Api.js.map +1 -0
- package/dist/HttpApi/Endpoints.d.ts +945 -0
- package/dist/HttpApi/Endpoints.d.ts.map +1 -0
- package/dist/HttpApi/Endpoints.js +373 -0
- package/dist/HttpApi/Endpoints.js.map +1 -0
- package/dist/HttpApi/Errors.d.ts +82 -0
- package/dist/HttpApi/Errors.d.ts.map +1 -0
- package/dist/HttpApi/Errors.js +184 -0
- package/dist/HttpApi/Errors.js.map +1 -0
- package/dist/HttpApi/Schemas.d.ts +1113 -0
- package/dist/HttpApi/Schemas.d.ts.map +1 -0
- package/dist/HttpApi/Schemas.js +734 -0
- package/dist/HttpApi/Schemas.js.map +1 -0
- package/dist/HttpApi/Security.d.ts +159 -0
- package/dist/HttpApi/Security.d.ts.map +1 -0
- package/dist/HttpApi/Security.js +530 -0
- package/dist/HttpApi/Security.js.map +1 -0
- package/dist/HttpApi/Transport.d.ts +65 -0
- package/dist/HttpApi/Transport.d.ts.map +1 -0
- package/dist/HttpApi/Transport.js +311 -0
- package/dist/HttpApi/Transport.js.map +1 -0
- package/dist/HttpApi/index.d.ts +8 -0
- package/dist/HttpApi/index.d.ts.map +1 -0
- package/dist/HttpApi/index.js +7 -0
- package/dist/HttpApi/index.js.map +1 -0
- package/dist/HttpApi.d.ts +2 -0
- package/dist/HttpApi.d.ts.map +1 -0
- package/dist/HttpApi.js +2 -0
- package/dist/HttpApi.js.map +1 -0
- package/dist/Identifiers.d.ts.map +1 -1
- package/dist/Identifiers.js.map +1 -1
- package/dist/Internal.d.ts +7 -0
- package/dist/Internal.d.ts.map +1 -0
- package/dist/Internal.js +12 -0
- package/dist/Internal.js.map +1 -0
- package/dist/Jwt.d.ts +271 -0
- package/dist/Jwt.d.ts.map +1 -0
- package/dist/Jwt.js +512 -0
- package/dist/Jwt.js.map +1 -0
- package/dist/LoginApproval.d.ts +314 -0
- package/dist/LoginApproval.d.ts.map +1 -0
- package/dist/LoginApproval.js +551 -0
- package/dist/LoginApproval.js.map +1 -0
- package/dist/LoginNotification.d.ts +183 -0
- package/dist/LoginNotification.d.ts.map +1 -0
- package/dist/LoginNotification.js +329 -0
- package/dist/LoginNotification.js.map +1 -0
- package/dist/LoginRisk.d.ts +73 -0
- package/dist/LoginRisk.d.ts.map +1 -0
- package/dist/LoginRisk.js +57 -0
- package/dist/LoginRisk.js.map +1 -0
- package/dist/MagicLink.d.ts +85 -0
- package/dist/MagicLink.d.ts.map +1 -0
- package/dist/MagicLink.js +206 -0
- package/dist/MagicLink.js.map +1 -0
- package/dist/Mailer.d.ts +147 -0
- package/dist/Mailer.d.ts.map +1 -0
- package/dist/Mailer.js +208 -0
- package/dist/Mailer.js.map +1 -0
- package/dist/OAuth.d.ts +934 -0
- package/dist/OAuth.d.ts.map +1 -0
- package/dist/OAuth.js +1661 -0
- package/dist/OAuth.js.map +1 -0
- package/dist/Passkey.d.ts +334 -0
- package/dist/Passkey.d.ts.map +1 -0
- package/dist/Passkey.js +422 -0
- package/dist/Passkey.js.map +1 -0
- package/dist/PasskeySimpleWebAuthn.d.ts +11 -0
- package/dist/PasskeySimpleWebAuthn.d.ts.map +1 -0
- package/dist/PasskeySimpleWebAuthn.js +181 -0
- package/dist/PasskeySimpleWebAuthn.js.map +1 -0
- package/dist/Password.d.ts +237 -0
- package/dist/Password.d.ts.map +1 -0
- package/dist/Password.js +641 -0
- package/dist/Password.js.map +1 -0
- package/dist/Policy.d.ts +7 -4
- package/dist/Policy.d.ts.map +1 -1
- package/dist/Policy.js +28 -5
- package/dist/Policy.js.map +1 -1
- package/dist/Privacy.d.ts +15 -0
- package/dist/Privacy.d.ts.map +1 -1
- package/dist/Privacy.js +58 -1
- package/dist/Privacy.js.map +1 -1
- package/dist/RateLimiter.d.ts +104 -0
- package/dist/RateLimiter.d.ts.map +1 -0
- package/dist/RateLimiter.js +118 -0
- package/dist/RateLimiter.js.map +1 -0
- package/dist/RecoveryCode.d.ts +169 -0
- package/dist/RecoveryCode.d.ts.map +1 -0
- package/dist/RecoveryCode.js +299 -0
- package/dist/RecoveryCode.js.map +1 -0
- package/dist/RefreshToken.d.ts +222 -0
- package/dist/RefreshToken.d.ts.map +1 -0
- package/dist/RefreshToken.js +342 -0
- package/dist/RefreshToken.js.map +1 -0
- package/dist/SecurityTimeline.d.ts +72 -0
- package/dist/SecurityTimeline.d.ts.map +1 -0
- package/dist/SecurityTimeline.js +386 -0
- package/dist/SecurityTimeline.js.map +1 -0
- package/dist/Sessions.d.ts +123 -11
- package/dist/Sessions.d.ts.map +1 -1
- package/dist/Sessions.js +534 -1
- package/dist/Sessions.js.map +1 -1
- package/dist/StepUp.d.ts +44 -0
- package/dist/StepUp.d.ts.map +1 -0
- package/dist/StepUp.js +82 -0
- package/dist/StepUp.js.map +1 -0
- package/dist/Storage.d.ts +73 -5
- package/dist/Storage.d.ts.map +1 -1
- package/dist/Storage.js +11 -1
- package/dist/Storage.js.map +1 -1
- package/dist/StorageMigrations.d.ts +13 -1
- package/dist/StorageMigrations.d.ts.map +1 -1
- package/dist/StorageMigrations.js +256 -2
- package/dist/StorageMigrations.js.map +1 -1
- package/dist/Testing.d.ts +9 -1
- package/dist/Testing.d.ts.map +1 -1
- package/dist/Testing.js +30 -2
- package/dist/Testing.js.map +1 -1
- package/dist/Totp.d.ts +220 -0
- package/dist/Totp.d.ts.map +1 -0
- package/dist/Totp.js +477 -0
- package/dist/Totp.js.map +1 -0
- package/dist/TrustedDevice.d.ts +127 -0
- package/dist/TrustedDevice.d.ts.map +1 -0
- package/dist/TrustedDevice.js +252 -0
- package/dist/TrustedDevice.js.map +1 -0
- package/dist/WaitUntil.d.ts.map +1 -1
- package/dist/WaitUntil.js +1 -1
- package/dist/WaitUntil.js.map +1 -1
- package/dist/Webhook.d.ts +72 -0
- package/dist/Webhook.d.ts.map +1 -0
- package/dist/Webhook.js +82 -0
- package/dist/Webhook.js.map +1 -0
- package/dist/alchemy/cloudflare/Email.d.ts +25 -0
- package/dist/alchemy/cloudflare/Email.d.ts.map +1 -0
- package/dist/alchemy/cloudflare/Email.js +117 -0
- package/dist/alchemy/cloudflare/Email.js.map +1 -0
- package/dist/alchemy/cloudflare/RateLimitDurableObject.d.ts +34 -0
- package/dist/alchemy/cloudflare/RateLimitDurableObject.d.ts.map +1 -0
- package/dist/alchemy/cloudflare/RateLimitDurableObject.js +30 -0
- package/dist/alchemy/cloudflare/RateLimitDurableObject.js.map +1 -0
- package/dist/cloudflare/Email.d.ts +25 -0
- package/dist/cloudflare/Email.d.ts.map +1 -0
- package/dist/cloudflare/Email.js +153 -0
- package/dist/cloudflare/Email.js.map +1 -0
- package/dist/cloudflare/RateLimitDurableObject.d.ts +50 -0
- package/dist/cloudflare/RateLimitDurableObject.d.ts.map +1 -0
- package/dist/cloudflare/RateLimitDurableObject.js +51 -0
- package/dist/cloudflare/RateLimitDurableObject.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/RateLimitDurableObject.d.ts +32 -0
- package/dist/internal/RateLimitDurableObject.d.ts.map +1 -0
- package/dist/internal/RateLimitDurableObject.js +80 -0
- package/dist/internal/RateLimitDurableObject.js.map +1 -0
- package/migrations/0002_auth_password.sql +25 -0
- package/migrations/0003_auth_login_approval_review.sql +22 -0
- package/migrations/0004_auth_trusted_device.sql +12 -0
- package/migrations/0005_auth_passkey.sql +17 -0
- package/migrations/0006_auth_totp_factor.sql +17 -0
- package/migrations/0007_auth_recovery_code.sql +13 -0
- package/migrations/0008_auth_api_key.sql +17 -0
- package/migrations/0009_auth_refresh_token.sql +21 -0
- package/migrations/0010_auth_jwt_revocation.sql +8 -0
- package/migrations/0011_auth_oauth_account.sql +16 -0
- package/migrations/0012_auth_oauth_provider_token_vault.sql +20 -0
- package/migrations/0013_auth_security_timeline.sql +16 -0
- package/package.json +146 -26
- package/dist/D1Kysely.d.ts +0 -40
- package/dist/D1Kysely.d.ts.map +0 -1
- package/dist/D1Kysely.js +0 -75
- package/dist/D1Kysely.js.map +0 -1
- package/dist/KyselyStorage.d.ts +0 -41
- package/dist/KyselyStorage.d.ts.map +0 -1
- package/dist/KyselyStorage.js +0 -176
- package/dist/KyselyStorage.js.map +0 -1
package/dist/EmailOtp.js
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import { Context, Data, Duration, Effect, Layer, Option, Redacted, } from "effect";
|
|
2
|
+
import { AuthFlow, AuthResult } from "./AuthFlow.js";
|
|
3
|
+
import { Challenge } from "./Challenge.js";
|
|
4
|
+
import { Crypto } from "./Crypto.js";
|
|
5
|
+
import { Email, UserId } from "./Identifiers.js";
|
|
6
|
+
import { currentUnixMillis } from "./Internal.js";
|
|
7
|
+
import { AuthMailer } from "./Mailer.js";
|
|
8
|
+
import { UserStore } from "./Storage.js";
|
|
9
|
+
export class EmailOtpStartError extends Data.TaggedError("EmailOtpStartError") {
|
|
10
|
+
}
|
|
11
|
+
export class EmailOtpVerifyError extends Data.TaggedError("EmailOtpVerifyError") {
|
|
12
|
+
}
|
|
13
|
+
export class EmailOtpSecretGeneratorError extends Data.TaggedError("EmailOtpSecretGeneratorError") {
|
|
14
|
+
}
|
|
15
|
+
export class EmailOtpLogin extends Context.Service()("auth/login/EmailOtp") {
|
|
16
|
+
}
|
|
17
|
+
(function (EmailOtpLogin) {
|
|
18
|
+
EmailOtpLogin.make = (service) => EmailOtpLogin.of(service);
|
|
19
|
+
})(EmailOtpLogin || (EmailOtpLogin = {}));
|
|
20
|
+
export class EmailOtpSecretGenerator extends Context.Service()("auth/email-otp/SecretGenerator") {
|
|
21
|
+
}
|
|
22
|
+
(function (EmailOtpSecretGenerator) {
|
|
23
|
+
EmailOtpSecretGenerator.make = (service) => EmailOtpSecretGenerator.of(service);
|
|
24
|
+
})(EmailOtpSecretGenerator || (EmailOtpSecretGenerator = {}));
|
|
25
|
+
export const defaultEmailOtpTtl = Duration.minutes(10);
|
|
26
|
+
export const defaultEmailOtpAlphabet = "0123456789";
|
|
27
|
+
export const defaultEmailOtpLength = 6;
|
|
28
|
+
const validateSecretLength = (length) => Number.isInteger(length) && length >= 4 && length <= 128
|
|
29
|
+
? Effect.succeed(length)
|
|
30
|
+
: Effect.fail(new EmailOtpSecretGeneratorError({
|
|
31
|
+
operation: "generate",
|
|
32
|
+
message: "Email OTP secret length must be an integer between 4 and 128",
|
|
33
|
+
}));
|
|
34
|
+
const validateSecretAlphabet = (alphabet) => {
|
|
35
|
+
const characters = [...alphabet];
|
|
36
|
+
if (characters.length < 2 || characters.length > 256) {
|
|
37
|
+
return Effect.fail(new EmailOtpSecretGeneratorError({
|
|
38
|
+
operation: "generate",
|
|
39
|
+
message: "Email OTP secret alphabet must contain between 2 and 256 characters",
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
if (new Set(characters).size !== characters.length) {
|
|
43
|
+
return Effect.fail(new EmailOtpSecretGeneratorError({
|
|
44
|
+
operation: "generate",
|
|
45
|
+
message: "Email OTP secret alphabet must not contain duplicate characters",
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
return Effect.succeed(characters);
|
|
49
|
+
};
|
|
50
|
+
const randomAlphabetSecret = (crypto, alphabet, length) => Effect.gen(function* () {
|
|
51
|
+
const unbiasedLimit = Math.floor(256 / alphabet.length) * alphabet.length;
|
|
52
|
+
const secret = [];
|
|
53
|
+
while (secret.length < length) {
|
|
54
|
+
const bytes = yield* crypto.randomBytes(length).pipe(Effect.mapError((cause) => new EmailOtpSecretGeneratorError({
|
|
55
|
+
operation: "generate",
|
|
56
|
+
message: "Failed to generate email OTP secret",
|
|
57
|
+
cause,
|
|
58
|
+
})));
|
|
59
|
+
for (const byte of bytes) {
|
|
60
|
+
if (byte >= unbiasedLimit) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
secret.push(alphabet[byte % alphabet.length]);
|
|
64
|
+
if (secret.length === length) {
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return Redacted.make(secret.join(""));
|
|
70
|
+
});
|
|
71
|
+
export const makeAlphabetEmailOtpSecretGenerator = (dependencies) => {
|
|
72
|
+
const alphabet = dependencies.alphabet ?? defaultEmailOtpAlphabet;
|
|
73
|
+
const length = dependencies.length ?? defaultEmailOtpLength;
|
|
74
|
+
return EmailOtpSecretGenerator.make({
|
|
75
|
+
generate: Effect.fn("auth.email_otp.secret_generator.alphabet.generate")(function* () {
|
|
76
|
+
const characters = yield* validateSecretAlphabet(alphabet);
|
|
77
|
+
const secretLength = yield* validateSecretLength(length);
|
|
78
|
+
const secret = yield* randomAlphabetSecret(dependencies.crypto, characters, secretLength);
|
|
79
|
+
return { secret };
|
|
80
|
+
}),
|
|
81
|
+
normalize: Effect.fn("auth.email_otp.secret_generator.alphabet.normalize")(function* (input) {
|
|
82
|
+
return Redacted.make(Redacted.value(input.secret).trim());
|
|
83
|
+
}),
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
export const EmailOtpSecretGeneratorLive = (options) => Layer.effect(EmailOtpSecretGenerator)(Effect.gen(function* () {
|
|
87
|
+
const crypto = yield* Crypto;
|
|
88
|
+
const config = options ?? {};
|
|
89
|
+
return makeAlphabetEmailOtpSecretGenerator({
|
|
90
|
+
crypto,
|
|
91
|
+
alphabet: config.alphabet,
|
|
92
|
+
length: config.length,
|
|
93
|
+
});
|
|
94
|
+
}));
|
|
95
|
+
const verifiedExistingUser = (users, user) => Effect.gen(function* () {
|
|
96
|
+
if (user.disabledAt !== undefined) {
|
|
97
|
+
return AuthResult.AccountDisabled();
|
|
98
|
+
}
|
|
99
|
+
if (user.emailVerified) {
|
|
100
|
+
return { _tag: "User", user };
|
|
101
|
+
}
|
|
102
|
+
const updatedAt = yield* currentUnixMillis;
|
|
103
|
+
const updated = yield* users
|
|
104
|
+
.markEmailVerified({ userId: user.id, updatedAt })
|
|
105
|
+
.pipe(Effect.mapError((cause) => new EmailOtpVerifyError({
|
|
106
|
+
message: "Failed to mark email verified",
|
|
107
|
+
cause,
|
|
108
|
+
})));
|
|
109
|
+
if (Option.isNone(updated)) {
|
|
110
|
+
return yield* new EmailOtpVerifyError({
|
|
111
|
+
message: "User not found",
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return { _tag: "User", user: updated.value };
|
|
115
|
+
});
|
|
116
|
+
const findByEmail = (users, email) => users.findByEmail(email).pipe(Effect.mapError((cause) => new EmailOtpVerifyError({
|
|
117
|
+
message: "Failed to load user by email",
|
|
118
|
+
cause,
|
|
119
|
+
})));
|
|
120
|
+
const createVerifiedUser = (dependencies, email) => Effect.gen(function* () {
|
|
121
|
+
const now = yield* currentUnixMillis;
|
|
122
|
+
const userId = UserId(yield* dependencies.crypto
|
|
123
|
+
.randomToken(dependencies.userIdBytes ?? 16)
|
|
124
|
+
.pipe(Effect.mapError((cause) => new EmailOtpVerifyError({
|
|
125
|
+
message: "Failed to generate user id",
|
|
126
|
+
cause,
|
|
127
|
+
}))));
|
|
128
|
+
const user = {
|
|
129
|
+
id: userId,
|
|
130
|
+
email,
|
|
131
|
+
emailVerified: true,
|
|
132
|
+
createdAt: now,
|
|
133
|
+
updatedAt: now,
|
|
134
|
+
};
|
|
135
|
+
return yield* dependencies.users.insert(user).pipe(Effect.as({ _tag: "User", user }), Effect.catchTag("StorageError", (cause) => findByEmail(dependencies.users, email).pipe(Effect.flatMap((existing) => Option.isSome(existing)
|
|
136
|
+
? verifiedExistingUser(dependencies.users, existing.value)
|
|
137
|
+
: Effect.fail(new EmailOtpVerifyError({
|
|
138
|
+
message: "Failed to create user",
|
|
139
|
+
cause,
|
|
140
|
+
}))))));
|
|
141
|
+
});
|
|
142
|
+
const findOrCreateVerifiedUser = (dependencies, email) => Effect.gen(function* () {
|
|
143
|
+
const existing = yield* findByEmail(dependencies.users, email);
|
|
144
|
+
if (Option.isSome(existing)) {
|
|
145
|
+
return yield* verifiedExistingUser(dependencies.users, existing.value);
|
|
146
|
+
}
|
|
147
|
+
return yield* createVerifiedUser(dependencies, email);
|
|
148
|
+
});
|
|
149
|
+
const invalidateChallenge = (challenge, id) => challenge
|
|
150
|
+
.consume(id)
|
|
151
|
+
.pipe(Effect.catchTag("ChallengeConsumeError", () => Effect.void));
|
|
152
|
+
const startSecret = (secretGenerator, input) => Effect.gen(function* () {
|
|
153
|
+
const rawSecret = input.secret;
|
|
154
|
+
if (rawSecret !== undefined) {
|
|
155
|
+
return yield* secretGenerator.normalize({ secret: rawSecret }).pipe(Effect.mapError((cause) => new EmailOtpStartError({
|
|
156
|
+
message: "Failed to normalize email OTP secret",
|
|
157
|
+
cause,
|
|
158
|
+
})));
|
|
159
|
+
}
|
|
160
|
+
const generated = yield* secretGenerator
|
|
161
|
+
.generate({
|
|
162
|
+
email: input.email,
|
|
163
|
+
locale: input.locale,
|
|
164
|
+
metadata: input.metadata,
|
|
165
|
+
})
|
|
166
|
+
.pipe(Effect.mapError((cause) => new EmailOtpStartError({
|
|
167
|
+
message: "Failed to generate email OTP secret",
|
|
168
|
+
cause,
|
|
169
|
+
})));
|
|
170
|
+
return yield* secretGenerator.normalize({ secret: generated.secret }).pipe(Effect.mapError((cause) => new EmailOtpStartError({
|
|
171
|
+
message: "Failed to normalize email OTP secret",
|
|
172
|
+
cause,
|
|
173
|
+
})));
|
|
174
|
+
});
|
|
175
|
+
const verifySecret = (secretGenerator, secret) => secretGenerator.normalize({ secret }).pipe(Effect.mapError((cause) => new EmailOtpVerifyError({
|
|
176
|
+
message: "Failed to normalize email OTP secret",
|
|
177
|
+
cause,
|
|
178
|
+
})));
|
|
179
|
+
export const makeEmailOtpLogin = (dependencies) => {
|
|
180
|
+
const ttl = dependencies.ttl ?? defaultEmailOtpTtl;
|
|
181
|
+
return EmailOtpLogin.make({
|
|
182
|
+
start: Effect.fn("auth.email_otp.start")(function* (input) {
|
|
183
|
+
yield* Effect.annotateCurrentSpan("auth.method", "email-otp");
|
|
184
|
+
const secret = yield* startSecret(dependencies.secretGenerator, input);
|
|
185
|
+
const issued = yield* dependencies.challenge
|
|
186
|
+
.issue({
|
|
187
|
+
type: "email-otp",
|
|
188
|
+
subject: input.email,
|
|
189
|
+
ttl: input.ttl ?? ttl,
|
|
190
|
+
secret,
|
|
191
|
+
metadata: input.metadata,
|
|
192
|
+
})
|
|
193
|
+
.pipe(Effect.mapError((cause) => new EmailOtpStartError({
|
|
194
|
+
message: "Failed to issue email OTP challenge",
|
|
195
|
+
cause,
|
|
196
|
+
})));
|
|
197
|
+
yield* dependencies.authMailer
|
|
198
|
+
.send({
|
|
199
|
+
_tag: "EmailOtp",
|
|
200
|
+
to: input.email,
|
|
201
|
+
challengeId: issued.id,
|
|
202
|
+
secret,
|
|
203
|
+
expiresAt: issued.expiresAt,
|
|
204
|
+
locale: input.locale,
|
|
205
|
+
metadata: input.metadata,
|
|
206
|
+
})
|
|
207
|
+
.pipe(Effect.matchEffect({
|
|
208
|
+
onSuccess: () => Effect.void,
|
|
209
|
+
onFailure: (cause) => invalidateChallenge(dependencies.challenge, issued.id).pipe(Effect.flatMap(() => Effect.fail(new EmailOtpStartError({
|
|
210
|
+
message: "Failed to send email OTP",
|
|
211
|
+
cause,
|
|
212
|
+
})))),
|
|
213
|
+
}));
|
|
214
|
+
return {
|
|
215
|
+
challengeId: issued.id,
|
|
216
|
+
email: input.email,
|
|
217
|
+
expiresAt: issued.expiresAt,
|
|
218
|
+
};
|
|
219
|
+
}),
|
|
220
|
+
verify: Effect.fn("auth.email_otp.verify")(function* (input) {
|
|
221
|
+
yield* Effect.annotateCurrentSpan("auth.method", "email-otp");
|
|
222
|
+
const secret = yield* verifySecret(dependencies.secretGenerator, input.secret);
|
|
223
|
+
const verifiedOption = yield* dependencies.challenge
|
|
224
|
+
.verify({
|
|
225
|
+
challengeId: input.challengeId,
|
|
226
|
+
type: "email-otp",
|
|
227
|
+
secret,
|
|
228
|
+
})
|
|
229
|
+
.pipe(Effect.match({
|
|
230
|
+
onSuccess: Option.some,
|
|
231
|
+
onFailure: () => Option.none(),
|
|
232
|
+
}));
|
|
233
|
+
if (Option.isNone(verifiedOption)) {
|
|
234
|
+
yield* Effect.annotateCurrentSpan("auth.result", "InvalidCredentials");
|
|
235
|
+
return AuthResult.InvalidCredentials();
|
|
236
|
+
}
|
|
237
|
+
const email = Email(verifiedOption.value.subject);
|
|
238
|
+
const userResult = yield* findOrCreateVerifiedUser(dependencies, email);
|
|
239
|
+
if (userResult._tag === "AccountDisabled") {
|
|
240
|
+
yield* Effect.annotateCurrentSpan("auth.result", "AccountDisabled");
|
|
241
|
+
return userResult;
|
|
242
|
+
}
|
|
243
|
+
return yield* dependencies.authFlow
|
|
244
|
+
.completePrimaryFactor({
|
|
245
|
+
userId: userResult.user.id,
|
|
246
|
+
email: userResult.user.email,
|
|
247
|
+
intent: "sign-in",
|
|
248
|
+
method: "email-otp",
|
|
249
|
+
amr: ["email", "otp"],
|
|
250
|
+
aal: "aal1",
|
|
251
|
+
claims: { emailVerified: true },
|
|
252
|
+
...(input.trustedDeviceToken === undefined
|
|
253
|
+
? {}
|
|
254
|
+
: { trustedDeviceToken: input.trustedDeviceToken }),
|
|
255
|
+
...(input.request === undefined ? {} : { request: input.request }),
|
|
256
|
+
...(verifiedOption.value.metadata === undefined
|
|
257
|
+
? {}
|
|
258
|
+
: { metadata: verifiedOption.value.metadata }),
|
|
259
|
+
})
|
|
260
|
+
.pipe(Effect.mapError((cause) => new EmailOtpVerifyError({
|
|
261
|
+
message: "Failed to complete email OTP authentication",
|
|
262
|
+
cause,
|
|
263
|
+
})));
|
|
264
|
+
}),
|
|
265
|
+
});
|
|
266
|
+
};
|
|
267
|
+
export const EmailOtpLoginLive = (options) => Layer.effect(EmailOtpLogin)(Effect.gen(function* () {
|
|
268
|
+
const challenge = yield* Challenge;
|
|
269
|
+
const users = yield* UserStore;
|
|
270
|
+
const crypto = yield* Crypto;
|
|
271
|
+
const authFlow = yield* AuthFlow;
|
|
272
|
+
const authMailer = yield* AuthMailer;
|
|
273
|
+
const secretGenerator = yield* EmailOtpSecretGenerator;
|
|
274
|
+
const resolvedOptions = options ?? {};
|
|
275
|
+
return makeEmailOtpLogin({
|
|
276
|
+
...resolvedOptions,
|
|
277
|
+
challenge,
|
|
278
|
+
users,
|
|
279
|
+
crypto,
|
|
280
|
+
authFlow,
|
|
281
|
+
authMailer,
|
|
282
|
+
secretGenerator,
|
|
283
|
+
});
|
|
284
|
+
}));
|
|
285
|
+
export const EmailOtpFeatureLive = (options) => EmailOtpLoginLive(options).pipe(Layer.provideMerge(EmailOtpSecretGeneratorLive(options)));
|
|
286
|
+
//# sourceMappingURL=EmailOtp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmailOtp.js","sourceRoot":"","sources":["../src/EmailOtp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { Redacted } from "effect";
|
|
2
|
+
import { Context, Duration, Effect, Layer } from "effect";
|
|
3
|
+
import { Challenge, type ChallengeService } from "./Challenge.js";
|
|
4
|
+
import { type ChallengeId, Email, type UnixMillis, UserId } from "./Identifiers.js";
|
|
5
|
+
import { AuthMailer, type AuthMailerService } from "./Mailer.js";
|
|
6
|
+
import { UserStore, type UserRow, type UserStoreService } from "./Storage.js";
|
|
7
|
+
export interface EmailVerificationIssueInput {
|
|
8
|
+
readonly userId: UserId;
|
|
9
|
+
readonly email: Email;
|
|
10
|
+
readonly ttl?: Duration.Duration;
|
|
11
|
+
readonly secret?: Redacted.Redacted<string>;
|
|
12
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
13
|
+
}
|
|
14
|
+
export interface IssuedEmailVerification {
|
|
15
|
+
readonly challengeId: ChallengeId;
|
|
16
|
+
readonly userId: UserId;
|
|
17
|
+
readonly email: Email;
|
|
18
|
+
readonly secret?: Redacted.Redacted<string>;
|
|
19
|
+
readonly expiresAt: UnixMillis;
|
|
20
|
+
}
|
|
21
|
+
export interface EmailVerificationVerifyInput {
|
|
22
|
+
readonly challengeId: ChallengeId;
|
|
23
|
+
readonly secret?: Redacted.Redacted<string>;
|
|
24
|
+
}
|
|
25
|
+
export interface VerifiedEmail {
|
|
26
|
+
readonly challengeId: ChallengeId;
|
|
27
|
+
readonly user: UserRow;
|
|
28
|
+
}
|
|
29
|
+
declare const EmailVerificationIssueError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
30
|
+
readonly _tag: "EmailVerificationIssueError";
|
|
31
|
+
} & Readonly<A>;
|
|
32
|
+
export declare class EmailVerificationIssueError extends EmailVerificationIssueError_base<{
|
|
33
|
+
readonly message: string;
|
|
34
|
+
readonly cause?: unknown;
|
|
35
|
+
}> {
|
|
36
|
+
}
|
|
37
|
+
declare const EmailVerificationVerifyError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
38
|
+
readonly _tag: "EmailVerificationVerifyError";
|
|
39
|
+
} & Readonly<A>;
|
|
40
|
+
export declare class EmailVerificationVerifyError extends EmailVerificationVerifyError_base<{
|
|
41
|
+
readonly message: string;
|
|
42
|
+
readonly cause?: unknown;
|
|
43
|
+
}> {
|
|
44
|
+
}
|
|
45
|
+
export type EmailVerificationError = EmailVerificationIssueError | EmailVerificationVerifyError;
|
|
46
|
+
export interface EmailVerificationDeliveryInput {
|
|
47
|
+
readonly userId: UserId;
|
|
48
|
+
readonly email: Email;
|
|
49
|
+
readonly challengeId: ChallengeId;
|
|
50
|
+
readonly secret?: Redacted.Redacted<string>;
|
|
51
|
+
readonly expiresAt: UnixMillis;
|
|
52
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
53
|
+
}
|
|
54
|
+
declare const EmailDeliveryError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
55
|
+
readonly _tag: "EmailDeliveryError";
|
|
56
|
+
} & Readonly<A>;
|
|
57
|
+
export declare class EmailDeliveryError extends EmailDeliveryError_base<{
|
|
58
|
+
readonly message: string;
|
|
59
|
+
readonly cause?: unknown;
|
|
60
|
+
}> {
|
|
61
|
+
}
|
|
62
|
+
export interface EmailDeliveryService {
|
|
63
|
+
readonly sendEmailVerification: (input: EmailVerificationDeliveryInput) => Effect.Effect<void, EmailDeliveryError>;
|
|
64
|
+
}
|
|
65
|
+
declare const EmailDelivery_base: Context.ServiceClass<EmailDelivery, "auth/EmailDelivery", EmailDeliveryService>;
|
|
66
|
+
export declare class EmailDelivery extends EmailDelivery_base {
|
|
67
|
+
}
|
|
68
|
+
export declare namespace EmailDelivery {
|
|
69
|
+
const make: (service: EmailDeliveryService) => EmailDeliveryService;
|
|
70
|
+
}
|
|
71
|
+
declare const EmailVerificationFlowStartError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
72
|
+
readonly _tag: "EmailVerificationFlowStartError";
|
|
73
|
+
} & Readonly<A>;
|
|
74
|
+
export declare class EmailVerificationFlowStartError extends EmailVerificationFlowStartError_base<{
|
|
75
|
+
readonly message: string;
|
|
76
|
+
readonly cause?: unknown;
|
|
77
|
+
}> {
|
|
78
|
+
}
|
|
79
|
+
export interface EmailVerificationFlowService {
|
|
80
|
+
readonly start: (input: EmailVerificationIssueInput) => Effect.Effect<IssuedEmailVerification, EmailVerificationFlowStartError>;
|
|
81
|
+
}
|
|
82
|
+
declare const EmailVerificationFlow_base: Context.ServiceClass<EmailVerificationFlow, "auth/EmailVerificationFlow", EmailVerificationFlowService>;
|
|
83
|
+
export declare class EmailVerificationFlow extends EmailVerificationFlow_base {
|
|
84
|
+
}
|
|
85
|
+
export declare namespace EmailVerificationFlow {
|
|
86
|
+
const make: (service: EmailVerificationFlowService) => EmailVerificationFlowService;
|
|
87
|
+
}
|
|
88
|
+
export interface EmailVerificationService {
|
|
89
|
+
readonly issue: (input: EmailVerificationIssueInput) => Effect.Effect<IssuedEmailVerification, EmailVerificationIssueError>;
|
|
90
|
+
readonly verify: (input: EmailVerificationVerifyInput) => Effect.Effect<VerifiedEmail, EmailVerificationVerifyError>;
|
|
91
|
+
}
|
|
92
|
+
declare const EmailVerification_base: Context.ServiceClass<EmailVerification, "auth/EmailVerification", EmailVerificationService>;
|
|
93
|
+
export declare class EmailVerification extends EmailVerification_base {
|
|
94
|
+
}
|
|
95
|
+
export declare namespace EmailVerification {
|
|
96
|
+
const make: (service: EmailVerificationService) => EmailVerificationService;
|
|
97
|
+
}
|
|
98
|
+
export interface EmailVerificationOptions {
|
|
99
|
+
readonly ttl?: Duration.Duration;
|
|
100
|
+
}
|
|
101
|
+
export interface EmailVerificationDependencies extends EmailVerificationOptions {
|
|
102
|
+
readonly challenge: ChallengeService;
|
|
103
|
+
readonly users: UserStoreService;
|
|
104
|
+
}
|
|
105
|
+
export interface EmailVerificationFlowDependencies {
|
|
106
|
+
readonly emailVerification: EmailVerificationService;
|
|
107
|
+
readonly emailDelivery: EmailDeliveryService;
|
|
108
|
+
}
|
|
109
|
+
export interface EmailDeliveryFromAuthMailerDependencies {
|
|
110
|
+
readonly authMailer: AuthMailerService;
|
|
111
|
+
}
|
|
112
|
+
export declare const defaultEmailVerificationTtl: Duration.Duration;
|
|
113
|
+
export declare const makeEmailVerification: (dependencies: EmailVerificationDependencies) => EmailVerificationService;
|
|
114
|
+
export declare const EmailVerificationLive: (options?: EmailVerificationOptions) => Layer.Layer<EmailVerification, never, UserStore | Challenge>;
|
|
115
|
+
export declare const makeEmailDeliveryFromAuthMailer: (dependencies: EmailDeliveryFromAuthMailerDependencies) => EmailDeliveryService;
|
|
116
|
+
export declare const EmailDeliveryFromAuthMailerLive: Layer.Layer<EmailDelivery, never, AuthMailer>;
|
|
117
|
+
export declare const makeEmailVerificationFlow: (dependencies: EmailVerificationFlowDependencies) => EmailVerificationFlowService;
|
|
118
|
+
export declare const EmailVerificationFlowLive: Layer.Layer<EmailVerificationFlow, never, EmailDelivery | EmailVerification>;
|
|
119
|
+
export declare const EmailVerificationFeatureLive: (options?: EmailVerificationOptions) => Layer.Layer<EmailVerificationFlow | EmailVerification, never, UserStore | Challenge | EmailDelivery>;
|
|
120
|
+
export {};
|
|
121
|
+
//# sourceMappingURL=EmailVerification.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmailVerification.d.ts","sourceRoot":"","sources":["../src/EmailVerification.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { Context, Data, Duration, Effect, Layer, Option } from "effect";
|
|
2
|
+
import { Challenge } from "./Challenge.js";
|
|
3
|
+
import { Email, UserId, } from "./Identifiers.js";
|
|
4
|
+
import { currentUnixMillis } from "./Internal.js";
|
|
5
|
+
import { AuthMailer } from "./Mailer.js";
|
|
6
|
+
import { UserStore } from "./Storage.js";
|
|
7
|
+
export class EmailVerificationIssueError extends Data.TaggedError("EmailVerificationIssueError") {
|
|
8
|
+
}
|
|
9
|
+
export class EmailVerificationVerifyError extends Data.TaggedError("EmailVerificationVerifyError") {
|
|
10
|
+
}
|
|
11
|
+
export class EmailDeliveryError extends Data.TaggedError("EmailDeliveryError") {
|
|
12
|
+
}
|
|
13
|
+
export class EmailDelivery extends Context.Service()("auth/EmailDelivery") {
|
|
14
|
+
}
|
|
15
|
+
(function (EmailDelivery) {
|
|
16
|
+
EmailDelivery.make = (service) => EmailDelivery.of(service);
|
|
17
|
+
})(EmailDelivery || (EmailDelivery = {}));
|
|
18
|
+
export class EmailVerificationFlowStartError extends Data.TaggedError("EmailVerificationFlowStartError") {
|
|
19
|
+
}
|
|
20
|
+
export class EmailVerificationFlow extends Context.Service()("auth/EmailVerificationFlow") {
|
|
21
|
+
}
|
|
22
|
+
(function (EmailVerificationFlow) {
|
|
23
|
+
EmailVerificationFlow.make = (service) => EmailVerificationFlow.of(service);
|
|
24
|
+
})(EmailVerificationFlow || (EmailVerificationFlow = {}));
|
|
25
|
+
export class EmailVerification extends Context.Service()("auth/EmailVerification") {
|
|
26
|
+
}
|
|
27
|
+
(function (EmailVerification) {
|
|
28
|
+
EmailVerification.make = (service) => EmailVerification.of(service);
|
|
29
|
+
})(EmailVerification || (EmailVerification = {}));
|
|
30
|
+
export const defaultEmailVerificationTtl = Duration.minutes(30);
|
|
31
|
+
const userIdFromMetadata = (metadata) => {
|
|
32
|
+
const userId = metadata?.userId;
|
|
33
|
+
return typeof userId === "string" && userId.length > 0
|
|
34
|
+
? UserId(userId)
|
|
35
|
+
: undefined;
|
|
36
|
+
};
|
|
37
|
+
export const makeEmailVerification = (dependencies) => {
|
|
38
|
+
const ttl = dependencies.ttl ?? defaultEmailVerificationTtl;
|
|
39
|
+
return EmailVerification.make({
|
|
40
|
+
issue: Effect.fn("auth.email_verification.issue")(function* (input) {
|
|
41
|
+
yield* Effect.annotateCurrentSpan("auth.email_verification.operation", "issue");
|
|
42
|
+
const userOption = yield* dependencies.users.findById(input.userId).pipe(Effect.mapError((cause) => new EmailVerificationIssueError({
|
|
43
|
+
message: "Failed to load user for email verification",
|
|
44
|
+
cause,
|
|
45
|
+
})));
|
|
46
|
+
if (Option.isNone(userOption)) {
|
|
47
|
+
return yield* new EmailVerificationIssueError({
|
|
48
|
+
message: "User not found",
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
const user = userOption.value;
|
|
52
|
+
if (user.email !== input.email) {
|
|
53
|
+
return yield* new EmailVerificationIssueError({
|
|
54
|
+
message: "Email does not match user",
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
if (user.emailVerified) {
|
|
58
|
+
return yield* new EmailVerificationIssueError({
|
|
59
|
+
message: "Email is already verified",
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
const issued = yield* dependencies.challenge
|
|
63
|
+
.issue({
|
|
64
|
+
type: "email-verification",
|
|
65
|
+
subject: input.email,
|
|
66
|
+
ttl: input.ttl ?? ttl,
|
|
67
|
+
secret: input.secret,
|
|
68
|
+
metadata: {
|
|
69
|
+
...input.metadata,
|
|
70
|
+
userId: input.userId,
|
|
71
|
+
},
|
|
72
|
+
})
|
|
73
|
+
.pipe(Effect.mapError((cause) => new EmailVerificationIssueError({
|
|
74
|
+
message: "Failed to issue email verification challenge",
|
|
75
|
+
cause,
|
|
76
|
+
})));
|
|
77
|
+
return {
|
|
78
|
+
challengeId: issued.id,
|
|
79
|
+
userId: input.userId,
|
|
80
|
+
email: input.email,
|
|
81
|
+
secret: issued.secret,
|
|
82
|
+
expiresAt: issued.expiresAt,
|
|
83
|
+
};
|
|
84
|
+
}),
|
|
85
|
+
verify: Effect.fn("auth.email_verification.verify")(function* (input) {
|
|
86
|
+
yield* Effect.annotateCurrentSpan("auth.email_verification.operation", "verify");
|
|
87
|
+
const verified = yield* dependencies.challenge
|
|
88
|
+
.verify({
|
|
89
|
+
challengeId: input.challengeId,
|
|
90
|
+
type: "email-verification",
|
|
91
|
+
secret: input.secret,
|
|
92
|
+
})
|
|
93
|
+
.pipe(Effect.mapError((cause) => new EmailVerificationVerifyError({
|
|
94
|
+
message: "Invalid email verification challenge",
|
|
95
|
+
cause,
|
|
96
|
+
})));
|
|
97
|
+
const userId = userIdFromMetadata(verified.metadata);
|
|
98
|
+
if (userId === undefined) {
|
|
99
|
+
return yield* new EmailVerificationVerifyError({
|
|
100
|
+
message: "Email verification challenge is missing user metadata",
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
const userOption = yield* dependencies.users.findById(userId).pipe(Effect.mapError((cause) => new EmailVerificationVerifyError({
|
|
104
|
+
message: "Failed to load user for email verification",
|
|
105
|
+
cause,
|
|
106
|
+
})));
|
|
107
|
+
if (Option.isNone(userOption)) {
|
|
108
|
+
return yield* new EmailVerificationVerifyError({
|
|
109
|
+
message: "User not found",
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
if (userOption.value.email !== Email(verified.subject)) {
|
|
113
|
+
return yield* new EmailVerificationVerifyError({
|
|
114
|
+
message: "Email verification challenge does not match user email",
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
const updatedAt = yield* currentUnixMillis;
|
|
118
|
+
const updatedUser = yield* dependencies.users
|
|
119
|
+
.markEmailVerified({ userId, updatedAt })
|
|
120
|
+
.pipe(Effect.mapError((cause) => new EmailVerificationVerifyError({
|
|
121
|
+
message: "Failed to mark email verified",
|
|
122
|
+
cause,
|
|
123
|
+
})));
|
|
124
|
+
if (Option.isNone(updatedUser)) {
|
|
125
|
+
return yield* new EmailVerificationVerifyError({
|
|
126
|
+
message: "User not found",
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
challengeId: verified.id,
|
|
131
|
+
user: updatedUser.value,
|
|
132
|
+
};
|
|
133
|
+
}),
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
export const EmailVerificationLive = (options) => Layer.effect(EmailVerification)(Effect.gen(function* () {
|
|
137
|
+
const challenge = yield* Challenge;
|
|
138
|
+
const users = yield* UserStore;
|
|
139
|
+
const resolvedOptions = options ?? {};
|
|
140
|
+
return makeEmailVerification({
|
|
141
|
+
...resolvedOptions,
|
|
142
|
+
challenge,
|
|
143
|
+
users,
|
|
144
|
+
});
|
|
145
|
+
}));
|
|
146
|
+
export const makeEmailDeliveryFromAuthMailer = (dependencies) => EmailDelivery.make({
|
|
147
|
+
sendEmailVerification: Effect.fn("auth.email_verification.delivery.auth_mailer")(function* (input) {
|
|
148
|
+
yield* dependencies.authMailer
|
|
149
|
+
.send({
|
|
150
|
+
_tag: "EmailVerification",
|
|
151
|
+
to: input.email,
|
|
152
|
+
userId: input.userId,
|
|
153
|
+
challengeId: input.challengeId,
|
|
154
|
+
secret: input.secret,
|
|
155
|
+
expiresAt: input.expiresAt,
|
|
156
|
+
metadata: input.metadata,
|
|
157
|
+
})
|
|
158
|
+
.pipe(Effect.mapError((cause) => new EmailDeliveryError({
|
|
159
|
+
message: "Failed to send email verification",
|
|
160
|
+
cause,
|
|
161
|
+
})));
|
|
162
|
+
}),
|
|
163
|
+
});
|
|
164
|
+
export const EmailDeliveryFromAuthMailerLive = Layer.effect(EmailDelivery)(Effect.gen(function* () {
|
|
165
|
+
const authMailer = yield* AuthMailer;
|
|
166
|
+
return makeEmailDeliveryFromAuthMailer({ authMailer });
|
|
167
|
+
}));
|
|
168
|
+
export const makeEmailVerificationFlow = (dependencies) => EmailVerificationFlow.make({
|
|
169
|
+
start: Effect.fn("auth.email_verification_flow.start")(function* (input) {
|
|
170
|
+
yield* Effect.annotateCurrentSpan("auth.email_verification_flow.operation", "start");
|
|
171
|
+
const issued = yield* dependencies.emailVerification.issue(input).pipe(Effect.mapError((cause) => new EmailVerificationFlowStartError({
|
|
172
|
+
message: "Failed to issue email verification challenge",
|
|
173
|
+
cause,
|
|
174
|
+
})));
|
|
175
|
+
yield* dependencies.emailDelivery
|
|
176
|
+
.sendEmailVerification({
|
|
177
|
+
userId: issued.userId,
|
|
178
|
+
email: issued.email,
|
|
179
|
+
challengeId: issued.challengeId,
|
|
180
|
+
secret: issued.secret,
|
|
181
|
+
expiresAt: issued.expiresAt,
|
|
182
|
+
metadata: input.metadata,
|
|
183
|
+
})
|
|
184
|
+
.pipe(Effect.mapError((cause) => new EmailVerificationFlowStartError({
|
|
185
|
+
message: "Failed to send email verification",
|
|
186
|
+
cause,
|
|
187
|
+
})));
|
|
188
|
+
return issued;
|
|
189
|
+
}),
|
|
190
|
+
});
|
|
191
|
+
export const EmailVerificationFlowLive = Layer.effect(EmailVerificationFlow)(Effect.gen(function* () {
|
|
192
|
+
const emailVerification = yield* EmailVerification;
|
|
193
|
+
const emailDelivery = yield* EmailDelivery;
|
|
194
|
+
return makeEmailVerificationFlow({
|
|
195
|
+
emailVerification,
|
|
196
|
+
emailDelivery,
|
|
197
|
+
});
|
|
198
|
+
}));
|
|
199
|
+
export const EmailVerificationFeatureLive = (options) => EmailVerificationFlowLive.pipe(Layer.provideMerge(EmailVerificationLive(options)));
|
|
200
|
+
//# sourceMappingURL=EmailVerification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmailVerification.js","sourceRoot":"","sources":["../src/EmailVerification.ts"],"names":[],"mappings":"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"}
|