@effect-auth/core 0.1.0-alpha.18 → 0.1.0-alpha.19
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 +4 -5
- package/dist/DevEmail.d.ts +44 -0
- package/dist/DevEmail.d.ts.map +1 -0
- package/dist/DevEmail.js +115 -0
- package/dist/DevEmail.js.map +1 -0
- package/dist/DevelopmentSeed.d.ts +47 -0
- package/dist/DevelopmentSeed.d.ts.map +1 -0
- package/dist/DevelopmentSeed.js +337 -0
- package/dist/DevelopmentSeed.js.map +1 -0
- package/dist/DrizzleBunSqliteStorage.d.ts +1 -1
- package/dist/DrizzleBunSqliteStorage.d.ts.map +1 -1
- package/dist/DrizzleD1SqliteStorage.d.ts +1 -1
- package/dist/DrizzleD1SqliteStorage.d.ts.map +1 -1
- package/dist/DrizzleEffectSqliteStorage.d.ts +1 -1
- package/dist/DrizzleEffectSqliteStorage.d.ts.map +1 -1
- package/dist/DrizzleNodeSqliteStorage.d.ts +1 -1
- package/dist/DrizzleNodeSqliteStorage.d.ts.map +1 -1
- package/dist/DrizzlePostgresStorage.d.ts +26 -0
- package/dist/DrizzlePostgresStorage.d.ts.map +1 -0
- package/dist/DrizzlePostgresStorage.js +14 -0
- package/dist/DrizzlePostgresStorage.js.map +1 -0
- package/dist/EffectQbPostgresStorage.d.ts +8 -1
- package/dist/EffectQbPostgresStorage.d.ts.map +1 -1
- package/dist/EffectQbPostgresStorage.js +359 -2
- package/dist/EffectQbPostgresStorage.js.map +1 -1
- package/dist/EffectQbSqliteStorage.d.ts +42 -2
- package/dist/EffectQbSqliteStorage.d.ts.map +1 -1
- package/dist/EffectQbSqliteStorage.js +337 -1
- package/dist/EffectQbSqliteStorage.js.map +1 -1
- package/dist/HttpApi/Api.d.ts +151 -98
- package/dist/HttpApi/Api.d.ts.map +1 -1
- package/dist/HttpApi/Api.js +122 -72
- package/dist/HttpApi/Api.js.map +1 -1
- package/dist/HttpApi/ClientApi.d.ts +136 -136
- package/dist/HttpApi/Endpoints.d.ts +33 -1
- package/dist/HttpApi/Endpoints.d.ts.map +1 -1
- package/dist/HttpApi/Endpoints.js +31 -2
- package/dist/HttpApi/Endpoints.js.map +1 -1
- package/dist/HttpApi/Errors.d.ts +11 -3
- package/dist/HttpApi/Errors.d.ts.map +1 -1
- package/dist/HttpApi/Errors.js +16 -0
- package/dist/HttpApi/Errors.js.map +1 -1
- package/dist/HttpApi/Middleware.d.ts +12 -0
- package/dist/HttpApi/Middleware.d.ts.map +1 -1
- package/dist/HttpApi/Middleware.js +8 -0
- package/dist/HttpApi/Middleware.js.map +1 -1
- package/dist/HttpApi/OAuthDeviceAuthorization.d.ts +106 -0
- package/dist/HttpApi/OAuthDeviceAuthorization.d.ts.map +1 -0
- package/dist/HttpApi/OAuthDeviceAuthorization.js +415 -0
- package/dist/HttpApi/OAuthDeviceAuthorization.js.map +1 -0
- package/dist/HttpApi/OAuthToken.d.ts +1 -1
- package/dist/HttpApi/OAuthToken.d.ts.map +1 -1
- package/dist/HttpApi/OAuthToken.js +1 -1
- package/dist/HttpApi/OAuthToken.js.map +1 -1
- package/dist/HttpApi/Operations/OAuthDeviceAuthorization.d.ts +23 -0
- package/dist/HttpApi/Operations/OAuthDeviceAuthorization.d.ts.map +1 -0
- package/dist/HttpApi/Operations/OAuthDeviceAuthorization.js +7 -0
- package/dist/HttpApi/Operations/OAuthDeviceAuthorization.js.map +1 -0
- package/dist/HttpApi/Operations/OAuthToken.d.ts +10 -0
- package/dist/HttpApi/Operations/OAuthToken.d.ts.map +1 -1
- package/dist/HttpApi/Operations/OAuthToken.js +4 -0
- package/dist/HttpApi/Operations/OAuthToken.js.map +1 -1
- package/dist/HttpApi/Operations/index.d.ts +1 -0
- package/dist/HttpApi/Operations/index.d.ts.map +1 -1
- package/dist/HttpApi/Operations/index.js +1 -0
- package/dist/HttpApi/Operations/index.js.map +1 -1
- package/dist/HttpApi/PasswordContract.d.ts +9 -9
- package/dist/HttpApi/Schemas.d.ts +38 -0
- package/dist/HttpApi/Schemas.d.ts.map +1 -1
- package/dist/HttpApi/Schemas.js +36 -1
- package/dist/HttpApi/Schemas.js.map +1 -1
- package/dist/HttpApi/index.d.ts +3 -1
- package/dist/HttpApi/index.d.ts.map +1 -1
- package/dist/HttpApi/index.js +3 -1
- package/dist/HttpApi/index.js.map +1 -1
- package/dist/OAuth.d.ts +46 -1
- package/dist/OAuth.d.ts.map +1 -1
- package/dist/OAuth.js +118 -4
- package/dist/OAuth.js.map +1 -1
- package/dist/OAuthDeviceAuthorization.d.ts +378 -0
- package/dist/OAuthDeviceAuthorization.d.ts.map +1 -0
- package/dist/OAuthDeviceAuthorization.js +860 -0
- package/dist/OAuthDeviceAuthorization.js.map +1 -0
- package/dist/OAuthDeviceClient.d.ts +76 -0
- package/dist/OAuthDeviceClient.d.ts.map +1 -0
- package/dist/OAuthDeviceClient.js +362 -0
- package/dist/OAuthDeviceClient.js.map +1 -0
- package/dist/PostgresStorageMigrations.d.ts +2 -1
- package/dist/PostgresStorageMigrations.d.ts.map +1 -1
- package/dist/PostgresStorageMigrations.js +54 -0
- package/dist/PostgresStorageMigrations.js.map +1 -1
- package/dist/Retention.d.ts +6 -1
- package/dist/Retention.d.ts.map +1 -1
- package/dist/Retention.js +49 -12
- package/dist/Retention.js.map +1 -1
- package/dist/SqliteStorageSchemaData.d.ts +2 -0
- package/dist/SqliteStorageSchemaData.d.ts.map +1 -0
- package/dist/SqliteStorageSchemaData.js +508 -0
- package/dist/SqliteStorageSchemaData.js.map +1 -0
- package/dist/StorageMigrations.d.ts +2 -1
- package/dist/StorageMigrations.d.ts.map +1 -1
- package/dist/StorageMigrations.js +32 -0
- package/dist/StorageMigrations.js.map +1 -1
- package/dist/StorageSchemaGenerator.d.ts +70 -12
- package/dist/StorageSchemaGenerator.d.ts.map +1 -1
- package/dist/StorageSchemaGenerator.js +478 -82
- package/dist/StorageSchemaGenerator.js.map +1 -1
- package/migrations/0029_auth_oauth_device_authorization.sql +28 -0
- package/migrations/postgres/0010_auth_oauth_device_authorization.sql +50 -0
- package/package.json +24 -16
- package/dist/DrizzleDurableObjectSqliteStorage.d.ts +0 -19
- package/dist/DrizzleDurableObjectSqliteStorage.d.ts.map +0 -1
- package/dist/DrizzleDurableObjectSqliteStorage.js +0 -14
- package/dist/DrizzleDurableObjectSqliteStorage.js.map +0 -1
- package/dist/DrizzleWasmSqliteStorage.d.ts +0 -23
- package/dist/DrizzleWasmSqliteStorage.d.ts.map +0 -1
- package/dist/DrizzleWasmSqliteStorage.js +0 -15
- package/dist/DrizzleWasmSqliteStorage.js.map +0 -1
package/README.md
CHANGED
|
@@ -44,8 +44,6 @@ Storage and runtime adapter subpaths are public alpha adapters. Their names may
|
|
|
44
44
|
@effect-auth/core/DrizzleD1SqliteStorage
|
|
45
45
|
@effect-auth/core/DrizzleBunSqliteStorage
|
|
46
46
|
@effect-auth/core/DrizzleNodeSqliteStorage
|
|
47
|
-
@effect-auth/core/DrizzleDurableObjectSqliteStorage
|
|
48
|
-
@effect-auth/core/DrizzleWasmSqliteStorage
|
|
49
47
|
@effect-auth/core/CloudflareEmail
|
|
50
48
|
@effect-auth/core/CloudflareRequestMetadata
|
|
51
49
|
@effect-auth/core/CloudflareRateLimitDurableObject
|
|
@@ -53,13 +51,14 @@ Storage and runtime adapter subpaths are public alpha adapters. Their names may
|
|
|
53
51
|
@effect-auth/core/AlchemyCloudflareRateLimitDurableObject
|
|
54
52
|
@effect-auth/core/PasskeySimpleWebAuthn
|
|
55
53
|
@effect-auth/core/StorageSchemaGenerator
|
|
54
|
+
@effect-auth/core/DevelopmentSeed
|
|
56
55
|
```
|
|
57
56
|
|
|
58
57
|
`@effect-auth/core/Testing` is test/dev-only API. Do not wire it into production applications.
|
|
59
58
|
|
|
60
59
|
SQL migrations are packaged as files for copy/read workflows, but the supported TypeScript APIs are `authStorageMigrations` from `@effect-auth/core/StorageMigrations` and `postgresAuthStorageMigrations` from `@effect-auth/core/PostgresStorageMigrations`. Raw SQL files are not importable package subpaths.
|
|
61
60
|
|
|
62
|
-
For fresh PostgreSQL
|
|
61
|
+
For fresh PostgreSQL or SQLite/D1 schema planning, `@effect-auth/core/StorageSchemaGenerator` exposes the same deterministic feature resolver used by the public API at `https://effect-auth.itsbroly.com/api/generator/v1`. Tools and AI agents should call `/catalog`, choose the database and adapter, then request `migration-sql`, `development-seed`, and, for Drizzle, `drizzle-schema`; they should not infer physical tables from store service types. `@effect-auth/core/DevelopmentSeed` provides the fixed 100-user, development-only runtime program used by generated seed launchers. Maintained runtime bridges are available for Drizzle PostgreSQL, D1, Bun SQLite, Node SQLite, and application-provided Effect SQLite databases.
|
|
63
62
|
|
|
64
63
|
Before beta, breaking changes are still allowed when they simplify this API surface. Keep the root metadata-only and add public APIs through explicit subpaths.
|
|
65
64
|
|
|
@@ -1018,7 +1017,7 @@ import { DrizzleD1SqliteAuthStorageLive } from "@effect-auth/core/DrizzleD1Sqlit
|
|
|
1018
1017
|
const StorageLive = DrizzleD1SqliteAuthStorageLive(env.DB);
|
|
1019
1018
|
```
|
|
1020
1019
|
|
|
1021
|
-
Runtime-specific Drizzle SQLite helpers are available for Node
|
|
1020
|
+
Runtime-specific Drizzle SQLite helpers are available for Node and Bun. They construct the matching Drizzle Effect SQLite database from the Effect SQL client layer, then reuse the same auth storage bridge:
|
|
1022
1021
|
|
|
1023
1022
|
```ts
|
|
1024
1023
|
import { DrizzleBunSqliteAuthStorageLive } from "@effect-auth/core/DrizzleBunSqliteStorage";
|
|
@@ -1028,7 +1027,7 @@ const StorageLive = DrizzleBunSqliteAuthStorageLive({
|
|
|
1028
1027
|
});
|
|
1029
1028
|
```
|
|
1030
1029
|
|
|
1031
|
-
Install the matching runtime package when using a runtime-specific subpath, such as `@effect/sql-sqlite-bun
|
|
1030
|
+
Install the matching runtime package when using a runtime-specific subpath, such as `@effect/sql-sqlite-bun` or `@effect/sql-sqlite-node`.
|
|
1032
1031
|
|
|
1033
1032
|
Database and ORM packages used only by storage subpaths are optional peers. The metadata-only root does not load them; install the matching optional peers for the adapter subpath your application imports.
|
|
1034
1033
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import type { Email, UnixMillis } from "./Identifiers.js";
|
|
3
|
+
import { AuthEmailTemplates, AuthMailer, type AuthEmail, type AuthMailerOptions, type EmailAddress } from "./Mailer.js";
|
|
4
|
+
export type DevEmailKind = AuthEmail["_tag"];
|
|
5
|
+
export interface DevEmailMessage {
|
|
6
|
+
readonly id: string;
|
|
7
|
+
readonly kind: DevEmailKind;
|
|
8
|
+
readonly recipient: Email;
|
|
9
|
+
readonly sender?: EmailAddress;
|
|
10
|
+
readonly subject: string;
|
|
11
|
+
readonly text?: string;
|
|
12
|
+
readonly html?: string;
|
|
13
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
14
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
15
|
+
readonly createdAt: UnixMillis;
|
|
16
|
+
readonly expiresAt: UnixMillis;
|
|
17
|
+
}
|
|
18
|
+
export interface DevEmailListOptions {
|
|
19
|
+
readonly recipient?: Email;
|
|
20
|
+
readonly kind?: DevEmailKind;
|
|
21
|
+
readonly limit?: number;
|
|
22
|
+
}
|
|
23
|
+
export type DevEmailStoreOperation = "save" | "list" | "clear";
|
|
24
|
+
declare const DevEmailStoreError_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 & {
|
|
25
|
+
readonly _tag: "DevEmailStoreError";
|
|
26
|
+
} & Readonly<A>;
|
|
27
|
+
export declare class DevEmailStoreError extends DevEmailStoreError_base<{
|
|
28
|
+
readonly operation: DevEmailStoreOperation;
|
|
29
|
+
readonly message: string;
|
|
30
|
+
readonly cause?: unknown;
|
|
31
|
+
}> {
|
|
32
|
+
}
|
|
33
|
+
export interface DevEmailStoreService {
|
|
34
|
+
readonly save: (message: DevEmailMessage) => Effect.Effect<void, DevEmailStoreError>;
|
|
35
|
+
readonly list: (options?: DevEmailListOptions) => Effect.Effect<readonly DevEmailMessage[], DevEmailStoreError>;
|
|
36
|
+
readonly clear: () => Effect.Effect<void, DevEmailStoreError>;
|
|
37
|
+
}
|
|
38
|
+
declare const DevEmailStore_base: Context.ServiceClass<DevEmailStore, "auth/DevEmailStore", DevEmailStoreService>;
|
|
39
|
+
export declare class DevEmailStore extends DevEmailStore_base {
|
|
40
|
+
}
|
|
41
|
+
export declare const DevEmailStoreMemoryLive: Layer.Layer<DevEmailStore>;
|
|
42
|
+
export declare const AuthMailerFromDevEmailStoreLive: (options?: AuthMailerOptions) => Layer.Layer<AuthMailer, never, AuthEmailTemplates | DevEmailStore>;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=DevEmail.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DevEmail.d.ts","sourceRoot":"","sources":["../src/DevEmail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,OAAO,EAAQ,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAE7D,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,EACL,kBAAkB,EAClB,UAAU,EAEV,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AAE7C,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;CAChC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;;;;AAE/D,qBAAa,kBAAmB,SAAQ,wBAAuC;IAC7E,QAAQ,CAAC,SAAS,EAAE,sBAAsB,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;CAAG;AAEL,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,CACb,OAAO,EAAE,eAAe,KACrB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;IAC7C,QAAQ,CAAC,IAAI,EAAE,CACb,OAAO,CAAC,EAAE,mBAAmB,KAC1B,MAAM,CAAC,MAAM,CAAC,SAAS,eAAe,EAAE,EAAE,kBAAkB,CAAC,CAAC;IACnE,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;CAC/D;;AAED,qBAAa,aAAc,SAAQ,kBAGV;CAAG;AAQ5B,eAAO,MAAM,uBAAuB,EAAE,KAAK,CAAC,KAAK,CAAC,aAAa,CAgD7D,CAAC;AA8CH,eAAO,MAAM,+BAA+B,aACjC,iBAAiB,KACzB,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,EAAE,kBAAkB,GAAG,aAAa,CAoDjE,CAAC"}
|
package/dist/DevEmail.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Clock, Context, Data, Effect, Layer } from "effect";
|
|
2
|
+
import { UnixMillis as makeUnixMillis } from "./Identifiers.js";
|
|
3
|
+
import { AuthEmailTemplates, AuthMailer, AuthMailerError, } from "./Mailer.js";
|
|
4
|
+
export class DevEmailStoreError extends Data.TaggedError("DevEmailStoreError") {
|
|
5
|
+
}
|
|
6
|
+
export class DevEmailStore extends Context.Service()("auth/DevEmailStore") {
|
|
7
|
+
}
|
|
8
|
+
const memoryCapacity = 100;
|
|
9
|
+
const defaultListLimit = 50;
|
|
10
|
+
const cloneMessage = (message) => structuredClone(message);
|
|
11
|
+
export const DevEmailStoreMemoryLive = Layer.sync(DevEmailStore)(() => {
|
|
12
|
+
const messages = new Map();
|
|
13
|
+
return DevEmailStore.of({
|
|
14
|
+
save: (message) => Effect.sync(() => {
|
|
15
|
+
messages.delete(message.id);
|
|
16
|
+
messages.set(message.id, cloneMessage(message));
|
|
17
|
+
while (messages.size > memoryCapacity) {
|
|
18
|
+
const oldestId = messages.keys().next().value;
|
|
19
|
+
if (oldestId === undefined) {
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
messages.delete(oldestId);
|
|
23
|
+
}
|
|
24
|
+
}),
|
|
25
|
+
list: (options = {}) => Effect.sync(() => {
|
|
26
|
+
const limit = Math.max(0, Math.floor(options.limit ?? defaultListLimit));
|
|
27
|
+
const newestFirst = [];
|
|
28
|
+
for (const message of messages.values()) {
|
|
29
|
+
newestFirst.unshift(message);
|
|
30
|
+
}
|
|
31
|
+
return newestFirst
|
|
32
|
+
.filter((message) => (options.recipient === undefined ||
|
|
33
|
+
message.recipient === options.recipient) &&
|
|
34
|
+
(options.kind === undefined || message.kind === options.kind))
|
|
35
|
+
.slice(0, limit)
|
|
36
|
+
.map(cloneMessage);
|
|
37
|
+
}),
|
|
38
|
+
clear: () => Effect.sync(() => {
|
|
39
|
+
messages.clear();
|
|
40
|
+
}),
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
const messageId = (input) => {
|
|
44
|
+
switch (input._tag) {
|
|
45
|
+
case "EmailAuth": {
|
|
46
|
+
return input.emailOtp.challengeId;
|
|
47
|
+
}
|
|
48
|
+
case "EmailOtp":
|
|
49
|
+
case "MagicLink":
|
|
50
|
+
case "PasswordReset":
|
|
51
|
+
case "EmailVerification":
|
|
52
|
+
case "LoginApproval": {
|
|
53
|
+
return input.challengeId;
|
|
54
|
+
}
|
|
55
|
+
case "LoginNotification": {
|
|
56
|
+
return (input.reportChallengeId ??
|
|
57
|
+
`${input.sessionId}:${input.occurredAt}:${input.reason}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const messageExpiresAt = (input) => {
|
|
62
|
+
switch (input._tag) {
|
|
63
|
+
case "EmailAuth": {
|
|
64
|
+
return makeUnixMillis(Math.max(Number(input.emailOtp.expiresAt), Number(input.magicLink.expiresAt)));
|
|
65
|
+
}
|
|
66
|
+
case "EmailOtp":
|
|
67
|
+
case "MagicLink":
|
|
68
|
+
case "PasswordReset":
|
|
69
|
+
case "EmailVerification":
|
|
70
|
+
case "LoginApproval": {
|
|
71
|
+
return input.expiresAt;
|
|
72
|
+
}
|
|
73
|
+
case "LoginNotification": {
|
|
74
|
+
return input.reportExpiresAt ?? input.occurredAt;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
export const AuthMailerFromDevEmailStoreLive = (options = {}) => Layer.effect(AuthMailer)(Effect.gen(function* () {
|
|
79
|
+
const store = yield* DevEmailStore;
|
|
80
|
+
const templates = yield* AuthEmailTemplates;
|
|
81
|
+
return AuthMailer.of({
|
|
82
|
+
send: Effect.fn("auth.dev_email.send")(function* (input) {
|
|
83
|
+
yield* Effect.annotateCurrentSpan("auth.email.kind", input._tag);
|
|
84
|
+
const rendered = yield* templates.render(input).pipe(Effect.mapError((cause) => new AuthMailerError({
|
|
85
|
+
message: "Failed to render dev auth email",
|
|
86
|
+
cause,
|
|
87
|
+
})));
|
|
88
|
+
const createdAt = makeUnixMillis(yield* Clock.currentTimeMillis);
|
|
89
|
+
const sender = rendered.from ?? options.from;
|
|
90
|
+
yield* store
|
|
91
|
+
.save({
|
|
92
|
+
id: messageId(input),
|
|
93
|
+
kind: input._tag,
|
|
94
|
+
recipient: input.to,
|
|
95
|
+
...(sender === undefined ? {} : { sender }),
|
|
96
|
+
subject: rendered.subject,
|
|
97
|
+
...(rendered.text === undefined ? {} : { text: rendered.text }),
|
|
98
|
+
...(rendered.html === undefined ? {} : { html: rendered.html }),
|
|
99
|
+
...(rendered.headers === undefined
|
|
100
|
+
? {}
|
|
101
|
+
: { headers: rendered.headers }),
|
|
102
|
+
...(input.metadata === undefined
|
|
103
|
+
? {}
|
|
104
|
+
: { metadata: input.metadata }),
|
|
105
|
+
createdAt,
|
|
106
|
+
expiresAt: messageExpiresAt(input),
|
|
107
|
+
})
|
|
108
|
+
.pipe(Effect.mapError((cause) => new AuthMailerError({
|
|
109
|
+
message: "Failed to store dev auth email",
|
|
110
|
+
cause,
|
|
111
|
+
})));
|
|
112
|
+
}),
|
|
113
|
+
});
|
|
114
|
+
}));
|
|
115
|
+
//# sourceMappingURL=DevEmail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DevEmail.js","sourceRoot":"","sources":["../src/DevEmail.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { UserId } from "./Identifiers.js";
|
|
3
|
+
import { IdentityKindRegistry } from "./Identity.js";
|
|
4
|
+
import { PasswordHasher } from "./Password.js";
|
|
5
|
+
import { CredentialStore, IdentityStore, RegistrationStore, UserStore } from "./Storage.js";
|
|
6
|
+
export declare const developmentSeedUserCount: 100;
|
|
7
|
+
export declare const developmentSeedPassword: "password";
|
|
8
|
+
export declare const developmentSeedVersion: 1;
|
|
9
|
+
export type DevelopmentSeedUserState = "active-verified" | "unverified" | "disabled" | "revoked-identity" | "revoked-password";
|
|
10
|
+
export interface DevelopmentSeedUserDefinition {
|
|
11
|
+
readonly userNumber: number;
|
|
12
|
+
readonly email: string;
|
|
13
|
+
readonly state: DevelopmentSeedUserState;
|
|
14
|
+
}
|
|
15
|
+
export interface SeedDevelopmentUserResult extends DevelopmentSeedUserDefinition {
|
|
16
|
+
readonly userId: UserId;
|
|
17
|
+
readonly outcome: "created" | "existing";
|
|
18
|
+
}
|
|
19
|
+
export interface SeedDevelopmentUsersResult {
|
|
20
|
+
readonly created: number;
|
|
21
|
+
readonly existing: number;
|
|
22
|
+
readonly users: readonly SeedDevelopmentUserResult[];
|
|
23
|
+
}
|
|
24
|
+
export interface DevelopmentSeedService {
|
|
25
|
+
readonly seedUsers: Effect.Effect<SeedDevelopmentUsersResult, DevelopmentSeedError>;
|
|
26
|
+
readonly seedPasswordUsers: Effect.Effect<SeedDevelopmentUsersResult, DevelopmentSeedError, CredentialStore | PasswordHasher>;
|
|
27
|
+
}
|
|
28
|
+
export type DevelopmentSeedErrorReason = "normalization" | "password-hash" | "storage" | "registration" | "ownership" | "state";
|
|
29
|
+
declare const DevelopmentSeedError_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: "DevelopmentSeedError";
|
|
31
|
+
} & Readonly<A>;
|
|
32
|
+
export declare class DevelopmentSeedError extends DevelopmentSeedError_base<{
|
|
33
|
+
readonly reason: DevelopmentSeedErrorReason;
|
|
34
|
+
readonly message: string;
|
|
35
|
+
readonly userNumber?: number;
|
|
36
|
+
readonly cause?: unknown;
|
|
37
|
+
}> {
|
|
38
|
+
}
|
|
39
|
+
export declare const developmentSeedUsers: readonly DevelopmentSeedUserDefinition[];
|
|
40
|
+
declare const DevelopmentSeed_base: Context.ServiceClass<DevelopmentSeed, "auth/DevelopmentSeed", DevelopmentSeedService> & {
|
|
41
|
+
readonly make: Effect.Effect<DevelopmentSeedService, never, IdentityKindRegistry | IdentityStore | RegistrationStore | UserStore>;
|
|
42
|
+
};
|
|
43
|
+
export declare class DevelopmentSeed extends DevelopmentSeed_base {
|
|
44
|
+
}
|
|
45
|
+
export declare const DevelopmentSeedLive: Layer.Layer<DevelopmentSeed, never, IdentityKindRegistry | IdentityStore | RegistrationStore | UserStore>;
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=DevelopmentSeed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DevelopmentSeed.d.ts","sourceRoot":"","sources":["../src/DevelopmentSeed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,OAAO,EAAQ,MAAM,EAAE,KAAK,EAAoB,MAAM,QAAQ,CAAC;AAE/E,OAAO,EAAwC,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAChF,OAAO,EAAsB,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAEzE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EACL,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,SAAS,EACV,MAAM,cAAc,CAAC;AAOtB,eAAO,MAAM,wBAAwB,EAAG,GAAY,CAAC;AACrD,eAAO,MAAM,uBAAuB,EAAG,UAAmB,CAAC;AAC3D,eAAO,MAAM,sBAAsB,EAAG,CAAU,CAAC;AAKjD,MAAM,MAAM,wBAAwB,GAChC,iBAAiB,GACjB,YAAY,GACZ,UAAU,GACV,kBAAkB,GAClB,kBAAkB,CAAC;AAEvB,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,wBAAwB,CAAC;CAC1C;AAED,MAAM,WAAW,yBAA0B,SAAQ,6BAA6B;IAC9E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,SAAS,GAAG,UAAU,CAAC;CAC1C;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,yBAAyB,EAAE,CAAC;CACtD;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAC/B,0BAA0B,EAC1B,oBAAoB,CACrB,CAAC;IACF,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC,MAAM,CACvC,0BAA0B,EAC1B,oBAAoB,EACpB,eAAe,GAAG,cAAc,CACjC,CAAC;CACH;AAED,MAAM,MAAM,0BAA0B,GAClC,eAAe,GACf,eAAe,GACf,SAAS,GACT,cAAc,GACd,WAAW,GACX,OAAO,CAAC;;;;AAEZ,qBAAa,oBAAqB,SAAQ,0BAExC;IACA,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;CAAG;AAiCL,eAAO,MAAM,oBAAoB,EAAE,SAAS,6BAA6B,EAUtE,CAAC;;;;AA4NJ,qBAAa,eAAgB,SAAQ,oBAsWnC;CAAG;AAEL,eAAO,MAAM,mBAAmB,2GAE/B,CAAC"}
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import { Clock, Context, Data, Effect, Layer, Option, Redacted } from "effect";
|
|
2
|
+
import { CredentialId, IdentityId, UnixMillis, UserId } from "./Identifiers.js";
|
|
3
|
+
import { emailLoginIdentity, IdentityKindRegistry } from "./Identity.js";
|
|
4
|
+
import { PasswordHasher } from "./Password.js";
|
|
5
|
+
import { CredentialStore, IdentityStore, RegistrationStore, UserStore, } from "./Storage.js";
|
|
6
|
+
export const developmentSeedUserCount = 100;
|
|
7
|
+
export const developmentSeedPassword = "password";
|
|
8
|
+
export const developmentSeedVersion = 1;
|
|
9
|
+
const developmentSeedOwner = "@effect-auth/core/DevelopmentSeed";
|
|
10
|
+
const developmentSeedMetadataKey = "effectAuthDevelopmentSeed";
|
|
11
|
+
export class DevelopmentSeedError extends Data.TaggedError("DevelopmentSeedError") {
|
|
12
|
+
}
|
|
13
|
+
const knownStates = [
|
|
14
|
+
"active-verified",
|
|
15
|
+
"unverified",
|
|
16
|
+
"disabled",
|
|
17
|
+
"revoked-identity",
|
|
18
|
+
"revoked-password",
|
|
19
|
+
];
|
|
20
|
+
const shuffledRemainingStates = () => {
|
|
21
|
+
const states = [
|
|
22
|
+
...Array.from({ length: 84 }).fill("active-verified"),
|
|
23
|
+
...Array.from({ length: 7 }).fill("unverified"),
|
|
24
|
+
...Array.from({ length: 3 }).fill("disabled"),
|
|
25
|
+
"revoked-identity",
|
|
26
|
+
];
|
|
27
|
+
let randomState = 0x45_ff_ec_7a;
|
|
28
|
+
for (let index = states.length - 1; index > 0; index -= 1) {
|
|
29
|
+
randomState = Math.imul(randomState, 1_664_525) + 1_013_904_223;
|
|
30
|
+
if (randomState < 0) {
|
|
31
|
+
randomState += 4_294_967_296;
|
|
32
|
+
}
|
|
33
|
+
const swapIndex = randomState % (index + 1);
|
|
34
|
+
[states[index], states[swapIndex]] = [states[swapIndex], states[index]];
|
|
35
|
+
}
|
|
36
|
+
return states;
|
|
37
|
+
};
|
|
38
|
+
export const developmentSeedUsers = Object.freeze([...knownStates, ...shuffledRemainingStates()].map((state, index) => {
|
|
39
|
+
const userNumber = index + 1;
|
|
40
|
+
return Object.freeze({
|
|
41
|
+
userNumber,
|
|
42
|
+
email: `user${userNumber}@example.test`,
|
|
43
|
+
state,
|
|
44
|
+
});
|
|
45
|
+
}));
|
|
46
|
+
const userIdFor = (userNumber) => UserId(`effect-auth-development-user-${userNumber}`);
|
|
47
|
+
const identityIdFor = (userNumber) => IdentityId(`effect-auth-development-email-${userNumber}`);
|
|
48
|
+
const credentialIdFor = (userNumber) => CredentialId(`effect-auth-development-password-${userNumber}`);
|
|
49
|
+
const metadataFor = (definition) => ({
|
|
50
|
+
[developmentSeedMetadataKey]: {
|
|
51
|
+
owner: developmentSeedOwner,
|
|
52
|
+
version: developmentSeedVersion,
|
|
53
|
+
userNumber: definition.userNumber,
|
|
54
|
+
state: definition.state,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
58
|
+
const hasSeedOwnership = (metadata, definition) => {
|
|
59
|
+
const marker = metadata?.[developmentSeedMetadataKey];
|
|
60
|
+
return (isRecord(marker) &&
|
|
61
|
+
marker.owner === developmentSeedOwner &&
|
|
62
|
+
marker.version === developmentSeedVersion &&
|
|
63
|
+
marker.userNumber === definition.userNumber &&
|
|
64
|
+
marker.state === definition.state);
|
|
65
|
+
};
|
|
66
|
+
const failure = (definition, reason, message, cause) => new DevelopmentSeedError({
|
|
67
|
+
reason,
|
|
68
|
+
message,
|
|
69
|
+
userNumber: definition.userNumber,
|
|
70
|
+
...(cause === undefined ? {} : { cause }),
|
|
71
|
+
});
|
|
72
|
+
const readExistingRows = (definition, users, identities, credentials) => {
|
|
73
|
+
const userId = userIdFor(definition.userNumber);
|
|
74
|
+
return Effect.all({
|
|
75
|
+
user: users.findById(userId),
|
|
76
|
+
identity: identities.findById(identityIdFor(definition.userNumber)),
|
|
77
|
+
credential: credentials === undefined
|
|
78
|
+
? Effect.succeed(Option.none())
|
|
79
|
+
: credentials.findPasswordByUserId(userId),
|
|
80
|
+
}).pipe(Effect.mapError((cause) => failure(definition, "storage", `Failed to read development seed user ${definition.userNumber}.`, cause)));
|
|
81
|
+
};
|
|
82
|
+
const effectiveState = (definition, includePassword) => definition.state === "revoked-password" && !includePassword
|
|
83
|
+
? "active-verified"
|
|
84
|
+
: definition.state;
|
|
85
|
+
const validateExistingRows = (definition, rows, includePassword, normalizedValue, allowPendingIdentityRevocation = false) =>
|
|
86
|
+
// oxlint-disable-next-line eslint/complexity -- validation compares the owned aggregate's identity and lifecycle state before accepting a rerun
|
|
87
|
+
Effect.gen(function* () {
|
|
88
|
+
if (Option.isNone(rows.user) ||
|
|
89
|
+
Option.isNone(rows.identity) ||
|
|
90
|
+
(includePassword && Option.isNone(rows.credential)) ||
|
|
91
|
+
(!includePassword && Option.isSome(rows.credential))) {
|
|
92
|
+
return yield* failure(definition, "state", `Development seed user ${definition.userNumber} is only partially present.`);
|
|
93
|
+
}
|
|
94
|
+
const user = rows.user.value;
|
|
95
|
+
const identity = rows.identity.value;
|
|
96
|
+
const credential = Option.getOrUndefined(rows.credential);
|
|
97
|
+
if (!hasSeedOwnership(user.metadata, definition) ||
|
|
98
|
+
!hasSeedOwnership(identity.metadata, definition) ||
|
|
99
|
+
(credential !== undefined &&
|
|
100
|
+
!hasSeedOwnership(credential.metadata, definition))) {
|
|
101
|
+
return yield* failure(definition, "ownership", `Development seed user ${definition.userNumber} conflicts with data not owned by this seed version.`);
|
|
102
|
+
}
|
|
103
|
+
const state = effectiveState(definition, includePassword);
|
|
104
|
+
const expectsDisabled = state === "disabled";
|
|
105
|
+
const expectsVerified = state !== "unverified" && state !== "revoked-identity";
|
|
106
|
+
const expectsRevokedIdentity = state === "revoked-identity";
|
|
107
|
+
const expectsRevokedPassword = state === "revoked-password";
|
|
108
|
+
const identityRevoked = identity.revokedAt !== undefined;
|
|
109
|
+
const revocationMatches = identityRevoked === expectsRevokedIdentity ||
|
|
110
|
+
(allowPendingIdentityRevocation &&
|
|
111
|
+
expectsRevokedIdentity &&
|
|
112
|
+
!identityRevoked);
|
|
113
|
+
if (user.id !== userIdFor(definition.userNumber) ||
|
|
114
|
+
(user.disabledAt !== undefined) !== expectsDisabled ||
|
|
115
|
+
identity.id !== identityIdFor(definition.userNumber) ||
|
|
116
|
+
identity.userId !== user.id ||
|
|
117
|
+
identity.scope.type !== "global" ||
|
|
118
|
+
identity.kind !== "email" ||
|
|
119
|
+
identity.value !== definition.email ||
|
|
120
|
+
identity.normalizedValue !== normalizedValue ||
|
|
121
|
+
(identity.verifiedAt !== undefined) !== expectsVerified ||
|
|
122
|
+
!revocationMatches ||
|
|
123
|
+
identity.isPrimaryLogin === expectsRevokedIdentity ||
|
|
124
|
+
(credential !== undefined &&
|
|
125
|
+
(credential.id !== credentialIdFor(definition.userNumber) ||
|
|
126
|
+
credential.userId !== user.id ||
|
|
127
|
+
(credential.revokedAt !== undefined) !== expectsRevokedPassword))) {
|
|
128
|
+
return yield* failure(definition, "state", `Development seed user ${definition.userNumber} does not match its expected state.`);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
const registrationInputFor = (definition, includePassword, normalized, now, passwordHash) => {
|
|
132
|
+
const state = effectiveState(definition, includePassword);
|
|
133
|
+
const userId = userIdFor(definition.userNumber);
|
|
134
|
+
const metadata = metadataFor(definition);
|
|
135
|
+
return {
|
|
136
|
+
user: {
|
|
137
|
+
id: userId,
|
|
138
|
+
createdAt: now,
|
|
139
|
+
updatedAt: now,
|
|
140
|
+
...(state === "disabled" ? { disabledAt: now } : {}),
|
|
141
|
+
metadata,
|
|
142
|
+
},
|
|
143
|
+
identity: {
|
|
144
|
+
id: identityIdFor(definition.userNumber),
|
|
145
|
+
userId,
|
|
146
|
+
scope: normalized.scope,
|
|
147
|
+
kind: normalized.kind,
|
|
148
|
+
value: normalized.value,
|
|
149
|
+
normalizedValue: normalized.normalizedValue,
|
|
150
|
+
...(state === "unverified" || state === "revoked-identity"
|
|
151
|
+
? {}
|
|
152
|
+
: { verifiedAt: now }),
|
|
153
|
+
isPrimaryLogin: state !== "revoked-identity",
|
|
154
|
+
createdAt: now,
|
|
155
|
+
metadata,
|
|
156
|
+
},
|
|
157
|
+
...(includePassword && passwordHash !== undefined
|
|
158
|
+
? {
|
|
159
|
+
passwordCredential: {
|
|
160
|
+
id: credentialIdFor(definition.userNumber),
|
|
161
|
+
userId,
|
|
162
|
+
passwordHash,
|
|
163
|
+
createdAt: now,
|
|
164
|
+
updatedAt: now,
|
|
165
|
+
...(state === "revoked-password" ? { revokedAt: now } : {}),
|
|
166
|
+
metadata,
|
|
167
|
+
},
|
|
168
|
+
}
|
|
169
|
+
: {}),
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
export class DevelopmentSeed extends Context.Service()("auth/DevelopmentSeed", {
|
|
173
|
+
make: Effect.gen(function* () {
|
|
174
|
+
const users = yield* UserStore;
|
|
175
|
+
const identities = yield* IdentityStore;
|
|
176
|
+
const registration = yield* RegistrationStore;
|
|
177
|
+
const identityKinds = yield* IdentityKindRegistry;
|
|
178
|
+
const runSeed = (password) => Effect.gen(function* () {
|
|
179
|
+
const includePassword = password !== undefined;
|
|
180
|
+
const now = UnixMillis(yield* Clock.currentTimeMillis);
|
|
181
|
+
let passwordHash;
|
|
182
|
+
const verifiedPasswordHashes = new Set();
|
|
183
|
+
const getPasswordHash = () => {
|
|
184
|
+
if (passwordHash !== undefined) {
|
|
185
|
+
return Effect.succeed(passwordHash);
|
|
186
|
+
}
|
|
187
|
+
if (password === undefined) {
|
|
188
|
+
return Effect.fail(new DevelopmentSeedError({
|
|
189
|
+
reason: "password-hash",
|
|
190
|
+
message: "Password seed dependencies are unavailable.",
|
|
191
|
+
}));
|
|
192
|
+
}
|
|
193
|
+
return password.hasher
|
|
194
|
+
.hash({ password: Redacted.make(developmentSeedPassword) })
|
|
195
|
+
.pipe(Effect.map((hash) => {
|
|
196
|
+
passwordHash = hash;
|
|
197
|
+
return hash;
|
|
198
|
+
}), Effect.mapError((cause) => new DevelopmentSeedError({
|
|
199
|
+
reason: "password-hash",
|
|
200
|
+
message: "Failed to hash the development seed password.",
|
|
201
|
+
cause,
|
|
202
|
+
})));
|
|
203
|
+
};
|
|
204
|
+
const validatePasswordHash = (definition, credential) => {
|
|
205
|
+
const { passwordHash: storedHash } = credential;
|
|
206
|
+
if (verifiedPasswordHashes.has(storedHash)) {
|
|
207
|
+
return Effect.void;
|
|
208
|
+
}
|
|
209
|
+
if (password === undefined) {
|
|
210
|
+
return Effect.fail(failure(definition, "password-hash", "Password seed dependencies are unavailable."));
|
|
211
|
+
}
|
|
212
|
+
return password.hasher
|
|
213
|
+
.verify({
|
|
214
|
+
hash: storedHash,
|
|
215
|
+
password: Redacted.make(developmentSeedPassword),
|
|
216
|
+
})
|
|
217
|
+
.pipe(Effect.mapError((cause) => failure(definition, "password-hash", `Failed to verify the password for development seed user ${definition.userNumber}.`, cause)), Effect.flatMap((valid) => valid
|
|
218
|
+
? Effect.sync(() => {
|
|
219
|
+
verifiedPasswordHashes.add(storedHash);
|
|
220
|
+
passwordHash ??= storedHash;
|
|
221
|
+
})
|
|
222
|
+
: Effect.fail(failure(definition, "state", `Development seed user ${definition.userNumber} no longer uses the documented password.`))));
|
|
223
|
+
};
|
|
224
|
+
const acceptExistingRows = (definition, normalizedValue, rows) => Effect.gen(function* () {
|
|
225
|
+
let validatedRows = rows;
|
|
226
|
+
if (effectiveState(definition, includePassword) ===
|
|
227
|
+
"revoked-identity" &&
|
|
228
|
+
Option.isSome(rows.identity) &&
|
|
229
|
+
rows.identity.value.revokedAt === undefined) {
|
|
230
|
+
yield* validateExistingRows(definition, rows, includePassword, normalizedValue, true);
|
|
231
|
+
yield* identities
|
|
232
|
+
.revoke({
|
|
233
|
+
id: rows.identity.value.id,
|
|
234
|
+
userId: userIdFor(definition.userNumber),
|
|
235
|
+
expectedUpdatedAt: rows.identity.value.updatedAt,
|
|
236
|
+
revokedAt: now,
|
|
237
|
+
reason: "development-seed",
|
|
238
|
+
})
|
|
239
|
+
.pipe(Effect.mapError((cause) => failure(definition, "storage", `Failed to finish revoking ${definition.email}.`, cause)));
|
|
240
|
+
validatedRows = yield* readExistingRows(definition, users, identities, password?.credentials);
|
|
241
|
+
}
|
|
242
|
+
yield* validateExistingRows(definition, validatedRows, includePassword, normalizedValue);
|
|
243
|
+
if (includePassword && Option.isSome(validatedRows.credential)) {
|
|
244
|
+
yield* validatePasswordHash(definition, validatedRows.credential.value);
|
|
245
|
+
}
|
|
246
|
+
return {
|
|
247
|
+
...definition,
|
|
248
|
+
state: effectiveState(definition, includePassword),
|
|
249
|
+
userId: userIdFor(definition.userNumber),
|
|
250
|
+
outcome: "existing",
|
|
251
|
+
};
|
|
252
|
+
});
|
|
253
|
+
const hasCompleteRows = (rows) => Option.isSome(rows.user) &&
|
|
254
|
+
Option.isSome(rows.identity) &&
|
|
255
|
+
(includePassword
|
|
256
|
+
? Option.isSome(rows.credential)
|
|
257
|
+
: Option.isNone(rows.credential));
|
|
258
|
+
const results = [];
|
|
259
|
+
for (const definition of developmentSeedUsers) {
|
|
260
|
+
const normalized = yield* identityKinds
|
|
261
|
+
.normalize(emailLoginIdentity(definition.email))
|
|
262
|
+
.pipe(Effect.mapError((cause) => failure(definition, "normalization", `Failed to normalize ${definition.email}.`, cause)));
|
|
263
|
+
const existingRows = yield* readExistingRows(definition, users, identities, password?.credentials);
|
|
264
|
+
const allAbsent = Option.isNone(existingRows.user) &&
|
|
265
|
+
Option.isNone(existingRows.identity) &&
|
|
266
|
+
Option.isNone(existingRows.credential);
|
|
267
|
+
if (!allAbsent) {
|
|
268
|
+
const existingResult = yield* acceptExistingRows(definition, normalized.normalizedValue, existingRows);
|
|
269
|
+
results.push(existingResult);
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
const activeIdentity = yield* identities
|
|
273
|
+
.findByKindAndNormalizedValue(normalized)
|
|
274
|
+
.pipe(Effect.mapError((cause) => failure(definition, "storage", `Failed to check ${definition.email} for conflicts.`, cause)));
|
|
275
|
+
if (Option.isSome(activeIdentity)) {
|
|
276
|
+
const racedRows = yield* readExistingRows(definition, users, identities, password?.credentials);
|
|
277
|
+
if (hasCompleteRows(racedRows)) {
|
|
278
|
+
const racedResult = yield* acceptExistingRows(definition, normalized.normalizedValue, racedRows);
|
|
279
|
+
results.push(racedResult);
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
return yield* failure(definition, "ownership", `${definition.email} is already owned by another user.`);
|
|
283
|
+
}
|
|
284
|
+
const hash = includePassword ? yield* getPasswordHash() : undefined;
|
|
285
|
+
const registrationResult = yield* registration
|
|
286
|
+
.create(registrationInputFor(definition, includePassword, normalized, now, hash))
|
|
287
|
+
.pipe(Effect.map((registered) => ({ _tag: "Created", registered })), Effect.catch((error) => readExistingRows(definition, users, identities, password?.credentials).pipe(Effect.flatMap((rows) => hasCompleteRows(rows)
|
|
288
|
+
? acceptExistingRows(definition, normalized.normalizedValue, rows).pipe(Effect.map((result) => ({ _tag: "Existing", result })))
|
|
289
|
+
: Effect.fail(failure(definition, "registration", `Failed to create development seed user ${definition.userNumber}.`, error))))));
|
|
290
|
+
if (registrationResult._tag === "Existing") {
|
|
291
|
+
results.push(registrationResult.result);
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
const { registered } = registrationResult;
|
|
295
|
+
if (effectiveState(definition, includePassword) === "revoked-identity") {
|
|
296
|
+
const revoked = yield* identities
|
|
297
|
+
.revoke({
|
|
298
|
+
id: registered.identity.id,
|
|
299
|
+
userId: registered.user.id,
|
|
300
|
+
expectedUpdatedAt: registered.identity.updatedAt,
|
|
301
|
+
revokedAt: now,
|
|
302
|
+
reason: "development-seed",
|
|
303
|
+
})
|
|
304
|
+
.pipe(Effect.mapError((cause) => failure(definition, "storage", `Failed to revoke ${definition.email}.`, cause)));
|
|
305
|
+
if (Option.isNone(revoked)) {
|
|
306
|
+
const rows = yield* readExistingRows(definition, users, identities, password?.credentials);
|
|
307
|
+
yield* validateExistingRows(definition, rows, includePassword, normalized.normalizedValue);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
results.push({
|
|
311
|
+
...definition,
|
|
312
|
+
state: effectiveState(definition, includePassword),
|
|
313
|
+
userId: registered.user.id,
|
|
314
|
+
outcome: "created",
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
return {
|
|
318
|
+
created: results.filter(({ outcome }) => outcome === "created")
|
|
319
|
+
.length,
|
|
320
|
+
existing: results.filter(({ outcome }) => outcome === "existing")
|
|
321
|
+
.length,
|
|
322
|
+
users: results,
|
|
323
|
+
};
|
|
324
|
+
});
|
|
325
|
+
return {
|
|
326
|
+
seedUsers: runSeed().pipe(Effect.withSpan("auth.development_seed.seed_users")),
|
|
327
|
+
seedPasswordUsers: Effect.gen(function* () {
|
|
328
|
+
const credentials = yield* CredentialStore;
|
|
329
|
+
const hasher = yield* PasswordHasher;
|
|
330
|
+
return yield* runSeed({ credentials, hasher });
|
|
331
|
+
}).pipe(Effect.withSpan("auth.development_seed.seed_password_users")),
|
|
332
|
+
};
|
|
333
|
+
}),
|
|
334
|
+
}) {
|
|
335
|
+
}
|
|
336
|
+
export const DevelopmentSeedLive = Layer.effect(DevelopmentSeed)(DevelopmentSeed.make);
|
|
337
|
+
//# sourceMappingURL=DevelopmentSeed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DevelopmentSeed.js","sourceRoot":"","sources":["../src/DevelopmentSeed.ts"],"names":[],"mappings":"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"}
|