@passlock/client 0.9.22 → 0.9.23
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/dist/authentication/authenticate.d.ts +15 -15
- package/dist/authentication/authenticate.fixture.d.ts +20 -6
- package/dist/authentication/authenticate.fixture.js +7 -5
- package/dist/authentication/authenticate.fixture.js.map +1 -1
- package/dist/authentication/authenticate.js +19 -8
- package/dist/authentication/authenticate.js.map +1 -1
- package/dist/capabilities/capabilities.d.ts +8 -4
- package/dist/capabilities/capabilities.js +10 -1
- package/dist/capabilities/capabilities.js.map +1 -1
- package/dist/connection/connection.d.ts +11 -7
- package/dist/connection/connection.fixture.d.ts +2 -2
- package/dist/connection/connection.fixture.js +2 -1
- package/dist/connection/connection.fixture.js.map +1 -1
- package/dist/connection/connection.js +12 -3
- package/dist/connection/connection.js.map +1 -1
- package/dist/effect.d.ts +22 -45
- package/dist/effect.js +55 -51
- package/dist/effect.js.map +1 -1
- package/dist/email/email.d.ts +38 -11
- package/dist/email/email.fixture.d.ts +19 -5
- package/dist/email/email.fixture.js +4 -3
- package/dist/email/email.fixture.js.map +1 -1
- package/dist/email/email.js +43 -7
- package/dist/email/email.js.map +1 -1
- package/dist/event/event.d.ts +3 -1
- package/dist/event/event.js +3 -0
- package/dist/event/event.js.map +1 -1
- package/dist/index.d.ts +105 -27
- package/dist/index.js +101 -50
- package/dist/index.js.map +1 -1
- package/dist/logging/eventLogger.d.ts +13 -1
- package/dist/logging/eventLogger.js +13 -0
- package/dist/logging/eventLogger.js.map +1 -1
- package/dist/registration/register.d.ts +18 -21
- package/dist/registration/register.fixture.d.ts +19 -5
- package/dist/registration/register.fixture.js +14 -7
- package/dist/registration/register.fixture.js.map +1 -1
- package/dist/registration/register.js +18 -9
- package/dist/registration/register.js.map +1 -1
- package/dist/rpc/authentication.d.ts +0 -1
- package/dist/rpc/authentication.js +1 -0
- package/dist/rpc/authentication.js.map +1 -1
- package/dist/rpc/client.d.ts +4 -1
- package/dist/rpc/client.js +12 -2
- package/dist/rpc/client.js.map +1 -1
- package/dist/rpc/config.d.ts +0 -1
- package/dist/rpc/connection.d.ts +0 -1
- package/dist/rpc/connection.js +1 -0
- package/dist/rpc/connection.js.map +1 -1
- package/dist/rpc/registration.d.ts +0 -1
- package/dist/rpc/registration.js +1 -0
- package/dist/rpc/registration.js.map +1 -1
- package/dist/rpc/social.d.ts +0 -1
- package/dist/rpc/social.js +1 -0
- package/dist/rpc/social.js.map +1 -1
- package/dist/rpc/user.d.ts +0 -1
- package/dist/rpc/user.js +1 -0
- package/dist/rpc/user.js.map +1 -1
- package/dist/social/social.d.ts +16 -23
- package/dist/social/social.fixture.d.ts +21 -9
- package/dist/social/social.fixture.js +8 -14
- package/dist/social/social.fixture.js.map +1 -1
- package/dist/social/social.js +14 -10
- package/dist/social/social.js.map +1 -1
- package/dist/storage/storage.d.ts +40 -12
- package/dist/storage/storage.fixture.d.ts +2 -2
- package/dist/storage/storage.fixture.js +2 -2
- package/dist/storage/storage.fixture.js.map +1 -1
- package/dist/storage/storage.js +48 -15
- package/dist/storage/storage.js.map +1 -1
- package/dist/test/fixtures.d.ts +1 -2
- package/dist/test/fixtures.js +20 -5
- package/dist/test/fixtures.js.map +1 -1
- package/dist/user/user.d.ts +8 -5
- package/dist/user/user.fixture.d.ts +2 -2
- package/dist/user/user.fixture.js +9 -5
- package/dist/user/user.fixture.js.map +1 -1
- package/dist/user/user.js +9 -3
- package/dist/user/user.js.map +1 -1
- package/dist/version.d.ts +1 -2
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +30 -26
- package/src/authentication/authenticate.fixture.ts +8 -7
- package/src/authentication/authenticate.test.ts +59 -17
- package/src/authentication/authenticate.ts +34 -32
- package/src/capabilities/capabilities.ts +9 -8
- package/src/connection/connection.fixture.ts +2 -1
- package/src/connection/connection.test.ts +3 -3
- package/src/connection/connection.ts +9 -8
- package/src/effect.ts +129 -128
- package/src/email/email.fixture.ts +4 -3
- package/src/email/email.test.ts +4 -4
- package/src/email/email.ts +24 -16
- package/src/index.ts +225 -169
- package/src/logging/eventLogger.test.ts +1 -1
- package/src/logging/eventLogger.ts +2 -2
- package/src/registration/register.fixture.ts +14 -8
- package/src/registration/register.test.ts +13 -9
- package/src/registration/register.ts +37 -34
- package/src/rpc/authentication.ts +31 -0
- package/src/rpc/client.ts +173 -0
- package/src/rpc/config.ts +18 -0
- package/src/rpc/connection.ts +24 -0
- package/src/rpc/registration.ts +31 -0
- package/src/rpc/social.ts +36 -0
- package/src/rpc/user.ts +42 -0
- package/src/social/social.fixture.ts +10 -18
- package/src/social/social.test.ts +13 -29
- package/src/social/social.ts +20 -47
- package/src/storage/storage.fixture.ts +3 -4
- package/src/storage/storage.test.ts +28 -19
- package/src/storage/storage.ts +36 -36
- package/src/test/fixtures.ts +21 -6
- package/src/user/user.fixture.ts +17 -7
- package/src/user/user.test.ts +2 -5
- package/src/user/user.ts +13 -9
- package/src/version.ts +1 -0
- package/dist/authentication/authenticate.d.ts.map +0 -1
- package/dist/authentication/authenticate.fixture.d.ts.map +0 -1
- package/dist/capabilities/capabilities.d.ts.map +0 -1
- package/dist/config.d.ts +0 -18
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -20
- package/dist/config.js.map +0 -1
- package/dist/connection/connection.d.ts.map +0 -1
- package/dist/connection/connection.fixture.d.ts.map +0 -1
- package/dist/effect.d.ts.map +0 -1
- package/dist/email/email.d.ts.map +0 -1
- package/dist/email/email.fixture.d.ts.map +0 -1
- package/dist/event/event.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/logging/eventLogger.d.ts.map +0 -1
- package/dist/registration/register.d.ts.map +0 -1
- package/dist/registration/register.fixture.d.ts.map +0 -1
- package/dist/rpc/authentication.d.ts.map +0 -1
- package/dist/rpc/client.d.ts.map +0 -1
- package/dist/rpc/config.d.ts.map +0 -1
- package/dist/rpc/connection.d.ts.map +0 -1
- package/dist/rpc/registration.d.ts.map +0 -1
- package/dist/rpc/social.d.ts.map +0 -1
- package/dist/rpc/user.d.ts.map +0 -1
- package/dist/social/social.d.ts.map +0 -1
- package/dist/social/social.fixture.d.ts.map +0 -1
- package/dist/storage/storage.d.ts.map +0 -1
- package/dist/storage/storage.fixture.d.ts.map +0 -1
- package/dist/test/fixtures.d.ts.map +0 -1
- package/dist/user/user.d.ts.map +0 -1
- package/dist/user/user.fixture.d.ts.map +0 -1
- package/dist/version.d.ts.map +0 -1
- package/src/config.ts +0 -42
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { RpcConfig } from '@passlock/shared/dist/rpc/config.js'
|
|
2
|
-
import { ConnectionClient } from '@passlock/shared/dist/rpc/connection.js'
|
|
3
|
-
import { Dispatcher } from '@passlock/shared/dist/rpc/dispatcher.js'
|
|
4
1
|
import { Effect as E, Layer as L, Layer, LogLevel, Logger, pipe } from 'effect'
|
|
5
2
|
import { describe, expect, test } from 'vitest'
|
|
6
3
|
import { mock } from 'vitest-mock-extended'
|
|
4
|
+
import { Dispatcher } from '../rpc/client.js'
|
|
5
|
+
import { RpcConfig } from '../rpc/config.js'
|
|
6
|
+
import { ConnectionClient } from '../rpc/connection.js'
|
|
7
7
|
import * as Fixture from './connection.fixture.js'
|
|
8
8
|
import { ConnectionService, ConnectionServiceLive } from './connection.js'
|
|
9
9
|
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Hits the rpc endpoint to warm up a lambda
|
|
3
3
|
*/
|
|
4
|
-
import type { RpcConfig } from '@passlock/shared/dist/rpc/config.js'
|
|
5
|
-
import { ConnectionClient } from '@passlock/shared/dist/rpc/connection.js'
|
|
6
|
-
import { Dispatcher } from '@passlock/shared/dist/rpc/dispatcher.js'
|
|
7
4
|
import { Context, Effect as E, Layer, flow, pipe } from 'effect'
|
|
5
|
+
import { Dispatcher } from '../rpc/client.js'
|
|
6
|
+
import type { RpcConfig } from '../rpc/config.js'
|
|
7
|
+
import { ConnectionClient } from '../rpc/connection.js'
|
|
8
8
|
|
|
9
9
|
/* Service */
|
|
10
10
|
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
export class ConnectionService extends Context.Tag('@services/ConnectionService')<
|
|
12
|
+
ConnectionService,
|
|
13
|
+
{
|
|
14
|
+
preConnect: () => E.Effect<void>
|
|
15
|
+
}
|
|
16
|
+
>() {}
|
|
16
17
|
|
|
17
18
|
/* Effects */
|
|
18
19
|
|
package/src/effect.ts
CHANGED
|
@@ -1,115 +1,132 @@
|
|
|
1
1
|
import { create, get as getCredential } from '@github/webauthn-json/browser-ponyfill'
|
|
2
2
|
|
|
3
|
-
import { AuthenticationClientLive } from '@passlock/shared/dist/rpc/authentication.js'
|
|
4
|
-
import { ConnectionClientLive } from '@passlock/shared/dist/rpc/connection.js'
|
|
5
|
-
import { RegistrationClientLive } from '@passlock/shared/dist/rpc/registration.js'
|
|
6
|
-
import { SocialClientLive } from '@passlock/shared/dist/rpc/social.js'
|
|
7
|
-
import { UserClientLive } from '@passlock/shared/dist/rpc/user.js'
|
|
8
|
-
|
|
9
3
|
import {
|
|
4
|
+
type BadRequest,
|
|
10
5
|
Duplicate,
|
|
11
6
|
InternalBrowserError,
|
|
12
|
-
type BadRequest,
|
|
13
|
-
type Disabled,
|
|
14
|
-
type Forbidden,
|
|
15
|
-
type NotFound,
|
|
16
|
-
type NotSupported,
|
|
17
|
-
type Unauthorized,
|
|
18
7
|
} from '@passlock/shared/dist/error/error.js'
|
|
19
8
|
|
|
9
|
+
import { AuthenticationClientLive } from './rpc/authentication.js'
|
|
10
|
+
import { DispatcherLive } from './rpc/client.js'
|
|
11
|
+
import type { RpcConfig } from './rpc/config.js'
|
|
12
|
+
import { RetrySchedule } from './rpc/config.js'
|
|
13
|
+
import { ConnectionClientLive } from './rpc/connection.js'
|
|
14
|
+
import { RegistrationClientLive } from './rpc/registration.js'
|
|
15
|
+
import { SocialClientLive } from './rpc/social.js'
|
|
16
|
+
import { UserClientLive } from './rpc/user.js'
|
|
17
|
+
|
|
20
18
|
import type { Principal } from '@passlock/shared/dist/schema/principal.js'
|
|
21
19
|
|
|
22
|
-
import {
|
|
20
|
+
import { Effect as E, Layer as L, Layer, Schedule, pipe } from 'effect'
|
|
23
21
|
import type { NoSuchElementException } from 'effect/Cause'
|
|
24
22
|
|
|
25
23
|
import {
|
|
26
24
|
AuthenticateServiceLive,
|
|
25
|
+
type AuthenticationErrors,
|
|
26
|
+
type AuthenticationRequest,
|
|
27
27
|
AuthenticationService,
|
|
28
28
|
GetCredential,
|
|
29
|
-
type AuthenticationRequest,
|
|
30
29
|
} from './authentication/authenticate.js'
|
|
31
30
|
|
|
32
|
-
import { capabilitiesLive } from './capabilities/capabilities.js'
|
|
31
|
+
import { Capabilities, capabilitiesLive } from './capabilities/capabilities.js'
|
|
33
32
|
import { ConnectionService, ConnectionServiceLive } from './connection/connection.js'
|
|
34
|
-
import {
|
|
33
|
+
import {
|
|
34
|
+
EmailService,
|
|
35
|
+
EmailServiceLive,
|
|
36
|
+
URLQueryString,
|
|
37
|
+
type VerifyEmailErrors,
|
|
38
|
+
type VerifyRequest,
|
|
39
|
+
} from './email/email.js'
|
|
35
40
|
|
|
36
41
|
import {
|
|
37
42
|
CreateCredential,
|
|
43
|
+
type RegistrationErrors,
|
|
44
|
+
type RegistrationRequest,
|
|
38
45
|
RegistrationService,
|
|
39
46
|
RegistrationServiceLive,
|
|
40
|
-
type RegistrationRequest,
|
|
41
47
|
} from './registration/register.js'
|
|
42
48
|
|
|
43
49
|
import {
|
|
44
|
-
|
|
50
|
+
type AuthenticateOidcReq,
|
|
51
|
+
type AuthenticationErrors as OidcAuthenticationErrors,
|
|
52
|
+
type RegistrationErrors as OidcRegistrationErrors,
|
|
53
|
+
type RegisterOidcReq,
|
|
54
|
+
SocialService,
|
|
55
|
+
SocialServiceLive,
|
|
56
|
+
} from './social/social.js'
|
|
57
|
+
import {
|
|
58
|
+
type AuthType,
|
|
59
|
+
BrowserStorage,
|
|
45
60
|
StorageService,
|
|
46
61
|
StorageServiceLive,
|
|
47
|
-
type AuthType,
|
|
48
62
|
type StoredToken,
|
|
49
63
|
} from './storage/storage.js'
|
|
50
64
|
|
|
51
|
-
import {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
import {
|
|
66
|
+
type Email,
|
|
67
|
+
type ResendEmail,
|
|
68
|
+
type ResendEmailErrors,
|
|
69
|
+
UserService,
|
|
70
|
+
UserServiceLive,
|
|
71
|
+
} from './user/user.js'
|
|
55
72
|
|
|
56
73
|
/* Layers */
|
|
57
74
|
|
|
58
75
|
const createCredentialLive = L.succeed(
|
|
59
76
|
CreateCredential,
|
|
60
|
-
CreateCredential.of(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
CreateCredential.of({
|
|
78
|
+
createCredential: options =>
|
|
79
|
+
pipe(
|
|
80
|
+
E.tryPromise({
|
|
81
|
+
try: () => create(options),
|
|
82
|
+
catch: e => {
|
|
83
|
+
if (e instanceof Error && e.message.includes('excludeCredentials')) {
|
|
84
|
+
return new Duplicate({
|
|
85
|
+
message: 'Passkey already registered to this device or cloud account',
|
|
86
|
+
})
|
|
87
|
+
} else {
|
|
88
|
+
return new InternalBrowserError({
|
|
89
|
+
message: 'Unable to create credential',
|
|
90
|
+
detail: String(e),
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
}),
|
|
95
|
+
E.map(credential => credential.toJSON()),
|
|
96
|
+
),
|
|
97
|
+
}),
|
|
80
98
|
)
|
|
81
99
|
|
|
82
100
|
const getCredentialLive = L.succeed(
|
|
83
101
|
GetCredential,
|
|
84
|
-
GetCredential.of(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
102
|
+
GetCredential.of({
|
|
103
|
+
getCredential: (options: CredentialRequestOptions) =>
|
|
104
|
+
pipe(
|
|
105
|
+
E.tryPromise({
|
|
106
|
+
try: () => getCredential(options),
|
|
107
|
+
catch: e =>
|
|
108
|
+
new InternalBrowserError({
|
|
109
|
+
message: 'Unable to get authentication credential',
|
|
110
|
+
detail: String(e),
|
|
111
|
+
}),
|
|
112
|
+
}),
|
|
113
|
+
E.map(credential => credential.toJSON()),
|
|
114
|
+
),
|
|
115
|
+
}),
|
|
97
116
|
)
|
|
98
117
|
|
|
99
118
|
const schedule = Schedule.intersect(Schedule.recurs(3), Schedule.exponential('100 millis'))
|
|
100
119
|
|
|
101
120
|
const retryScheduleLive = L.succeed(RetrySchedule, RetrySchedule.of({ schedule }))
|
|
102
121
|
|
|
103
|
-
/*
|
|
122
|
+
/* Services */
|
|
104
123
|
const dispatcherLive = pipe(DispatcherLive, L.provide(retryScheduleLive))
|
|
105
124
|
const connectClientLive = pipe(ConnectionClientLive, L.provide(dispatcherLive))
|
|
106
125
|
const registerClientLive = pipe(RegistrationClientLive, L.provide(dispatcherLive))
|
|
107
126
|
const authenticateClientLive = pipe(AuthenticationClientLive, L.provide(dispatcherLive))
|
|
108
127
|
const socialClientLive = pipe(SocialClientLive, L.provide(dispatcherLive))
|
|
109
128
|
const userClientLive = pipe(UserClientLive, L.provide(dispatcherLive))
|
|
110
|
-
|
|
111
129
|
const storageServiceLive = StorageServiceLive
|
|
112
|
-
|
|
113
130
|
const userServiceLive = pipe(UserServiceLive, L.provide(userClientLive))
|
|
114
131
|
|
|
115
132
|
const registrationServiceLive = pipe(
|
|
@@ -149,10 +166,7 @@ const emailServiceLive = pipe(
|
|
|
149
166
|
L.provide(storageServiceLive),
|
|
150
167
|
)
|
|
151
168
|
|
|
152
|
-
const socialServiceLive = pipe(
|
|
153
|
-
SocialServiceLive,
|
|
154
|
-
L.provide(socialClientLive),
|
|
155
|
-
)
|
|
169
|
+
const socialServiceLive = pipe(SocialServiceLive, L.provide(socialClientLive))
|
|
156
170
|
|
|
157
171
|
export const allRequirements = Layer.mergeAll(
|
|
158
172
|
capabilitiesLive,
|
|
@@ -165,98 +179,75 @@ export const allRequirements = Layer.mergeAll(
|
|
|
165
179
|
socialServiceLive,
|
|
166
180
|
)
|
|
167
181
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
tenancyId: string
|
|
172
|
-
clientId: string
|
|
173
|
-
endpoint?: string
|
|
174
|
-
}
|
|
175
|
-
>() {}
|
|
176
|
-
|
|
177
|
-
const storageLive = Layer.effect(
|
|
178
|
-
Storage,
|
|
179
|
-
E.sync(() => Storage.of(globalThis.localStorage)),
|
|
182
|
+
const browserStorageLive = Layer.effect(
|
|
183
|
+
BrowserStorage,
|
|
184
|
+
E.sync(() => BrowserStorage.of(globalThis.localStorage)),
|
|
180
185
|
)
|
|
181
186
|
|
|
182
|
-
const
|
|
183
|
-
return pipe(
|
|
184
|
-
Config,
|
|
185
|
-
E.flatMap(config => E.provideService(effect, RpcConfig, RpcConfig.of(config))),
|
|
186
|
-
effect => E.provide(effect, storageLive),
|
|
187
|
-
)
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export const preConnect = (): E.Effect<void, never, Config> =>
|
|
187
|
+
export const preConnect = (): E.Effect<void, never, RpcConfig> =>
|
|
191
188
|
pipe(
|
|
192
189
|
ConnectionService,
|
|
193
190
|
E.flatMap(service => service.preConnect()),
|
|
194
191
|
E.provide(connectionServiceLive),
|
|
195
|
-
exchangeConfig,
|
|
196
192
|
)
|
|
197
193
|
|
|
198
|
-
export const
|
|
194
|
+
export const isPasskeySupport: E.Effect<boolean> = pipe(
|
|
195
|
+
Capabilities,
|
|
196
|
+
E.flatMap(service => service.isPasskeySupport),
|
|
197
|
+
E.provide(capabilitiesLive),
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
export const isExistingUser = (request: Email): E.Effect<boolean, BadRequest, RpcConfig> =>
|
|
199
201
|
pipe(
|
|
200
202
|
UserService,
|
|
201
|
-
E.flatMap(service => service.isExistingUser(
|
|
203
|
+
E.flatMap(service => service.isExistingUser(request)),
|
|
202
204
|
E.provide(userServiceLive),
|
|
203
|
-
exchangeConfig,
|
|
204
205
|
)
|
|
205
206
|
|
|
206
|
-
export type RegistrationErrors = NotSupported | BadRequest | Duplicate | Unauthorized | Forbidden
|
|
207
|
-
|
|
208
207
|
export const registerPasskey = (
|
|
209
208
|
request: RegistrationRequest,
|
|
210
|
-
): E.Effect<Principal, RegistrationErrors,
|
|
209
|
+
): E.Effect<Principal, RegistrationErrors, RpcConfig> =>
|
|
211
210
|
pipe(
|
|
212
211
|
RegistrationService,
|
|
213
212
|
E.flatMap(service => service.registerPasskey(request)),
|
|
214
213
|
E.provide(registrationServiceLive),
|
|
215
|
-
|
|
214
|
+
E.provide(browserStorageLive),
|
|
216
215
|
)
|
|
217
216
|
|
|
218
|
-
export type AuthenticationErrors =
|
|
219
|
-
| NotSupported
|
|
220
|
-
| BadRequest
|
|
221
|
-
| NotFound
|
|
222
|
-
| Disabled
|
|
223
|
-
| Unauthorized
|
|
224
|
-
| Forbidden
|
|
225
|
-
|
|
226
217
|
export const authenticatePasskey = (
|
|
227
218
|
request: AuthenticationRequest,
|
|
228
|
-
): E.Effect<Principal, AuthenticationErrors,
|
|
229
|
-
pipe(
|
|
219
|
+
): E.Effect<Principal, AuthenticationErrors, RpcConfig> => pipe(
|
|
230
220
|
AuthenticationService,
|
|
231
221
|
E.flatMap(service => service.authenticatePasskey(request)),
|
|
232
222
|
E.provide(authenticationServiceLive),
|
|
233
|
-
|
|
223
|
+
E.provide(browserStorageLive),
|
|
234
224
|
)
|
|
235
225
|
|
|
236
|
-
export type VerifyEmailErrors =
|
|
237
|
-
| NotSupported
|
|
238
|
-
| BadRequest
|
|
239
|
-
| NotFound
|
|
240
|
-
| Disabled
|
|
241
|
-
| Unauthorized
|
|
242
|
-
| Forbidden
|
|
243
|
-
|
|
244
226
|
export const verifyEmailCode = (
|
|
245
227
|
request: VerifyRequest,
|
|
246
|
-
): E.Effect<Principal, VerifyEmailErrors,
|
|
228
|
+
): E.Effect<Principal, VerifyEmailErrors, RpcConfig> =>
|
|
247
229
|
pipe(
|
|
248
230
|
EmailService,
|
|
249
231
|
E.flatMap(service => service.verifyEmailCode(request)),
|
|
250
232
|
E.provide(emailServiceLive),
|
|
251
|
-
|
|
233
|
+
E.provide(browserStorageLive),
|
|
252
234
|
)
|
|
253
235
|
|
|
254
|
-
export const verifyEmailLink
|
|
236
|
+
export const verifyEmailLink: E.Effect<Principal, VerifyEmailErrors, RpcConfig> = pipe(
|
|
237
|
+
EmailService,
|
|
238
|
+
E.flatMap(service => service.verifyEmailLink()),
|
|
239
|
+
E.provide(emailServiceLive),
|
|
240
|
+
E.provide(browserStorageLive),
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
export const resendVerificationEmail = (
|
|
244
|
+
request: ResendEmail,
|
|
245
|
+
): E.Effect<void, ResendEmailErrors, RpcConfig> =>
|
|
255
246
|
pipe(
|
|
256
|
-
|
|
257
|
-
E.flatMap(service => service.
|
|
258
|
-
E.provide(
|
|
259
|
-
|
|
247
|
+
UserService,
|
|
248
|
+
E.flatMap(service => service.resendVerificationEmail(request)),
|
|
249
|
+
E.provide(userServiceLive),
|
|
250
|
+
E.provide(browserStorageLive),
|
|
260
251
|
)
|
|
261
252
|
|
|
262
253
|
export const getSessionToken = (
|
|
@@ -266,20 +257,30 @@ export const getSessionToken = (
|
|
|
266
257
|
StorageService,
|
|
267
258
|
E.flatMap(service => service.getToken(authType)),
|
|
268
259
|
E.provide(storageServiceLive),
|
|
269
|
-
E.provide(
|
|
260
|
+
E.provide(browserStorageLive),
|
|
270
261
|
)
|
|
271
262
|
|
|
272
|
-
export const clearExpiredTokens
|
|
263
|
+
export const clearExpiredTokens: E.Effect<void> = pipe(
|
|
264
|
+
StorageService,
|
|
265
|
+
E.flatMap(service => service.clearExpiredTokens),
|
|
266
|
+
E.provide(storageServiceLive),
|
|
267
|
+
E.provide(browserStorageLive),
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
export const registerOidc = (
|
|
271
|
+
request: RegisterOidcReq,
|
|
272
|
+
): E.Effect<Principal, OidcRegistrationErrors, RpcConfig> =>
|
|
273
273
|
pipe(
|
|
274
|
-
|
|
275
|
-
E.flatMap(service => service.
|
|
276
|
-
E.provide(
|
|
277
|
-
E.provide(storageLive),
|
|
274
|
+
SocialService,
|
|
275
|
+
E.flatMap(service => service.registerOidc(request)),
|
|
276
|
+
E.provide(socialServiceLive),
|
|
278
277
|
)
|
|
279
278
|
|
|
280
|
-
export const
|
|
279
|
+
export const authenticateOidc = (
|
|
280
|
+
request: AuthenticateOidcReq,
|
|
281
|
+
): E.Effect<Principal, OidcAuthenticationErrors, RpcConfig> =>
|
|
281
282
|
pipe(
|
|
282
283
|
SocialService,
|
|
283
|
-
E.flatMap(service => service.
|
|
284
|
-
E.provide(socialServiceLive)
|
|
285
|
-
)
|
|
284
|
+
E.flatMap(service => service.authenticateOidc(request)),
|
|
285
|
+
E.provide(socialServiceLive),
|
|
286
|
+
)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Effect as E, Layer as L } from 'effect'
|
|
1
|
+
import { VerifyEmailReq, VerifyEmailRes } from '@passlock/shared/dist/rpc/user.js'
|
|
2
|
+
import { Effect as E, Layer as L, Option as O } from 'effect'
|
|
3
3
|
import { AuthenticationService } from '../authentication/authenticate.js'
|
|
4
|
+
import { UserClient } from '../rpc/user.js'
|
|
4
5
|
import * as Fixtures from '../test/fixtures.js'
|
|
5
6
|
import { URLQueryString } from './email.js'
|
|
6
7
|
|
|
@@ -28,7 +29,7 @@ export const rpcVerifyEmailRes = new VerifyEmailRes({ principal: Fixtures.princi
|
|
|
28
29
|
export const rpcClientTest = L.succeed(
|
|
29
30
|
UserClient,
|
|
30
31
|
UserClient.of({
|
|
31
|
-
isExistingUser: () => E.succeed({ existingUser: true }),
|
|
32
|
+
isExistingUser: () => E.succeed({ existingUser: true, detail: O.none() }),
|
|
32
33
|
verifyEmail: () => E.succeed(rpcVerifyEmailRes),
|
|
33
34
|
resendVerificationEmail: () => E.fail(Fixtures.notImplemented),
|
|
34
35
|
}),
|
package/src/email/email.test.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { UserClient } from '@passlock/shared/dist/rpc/user.js'
|
|
2
1
|
import { Effect as E, Layer as L, LogLevel, Logger, pipe } from 'effect'
|
|
3
2
|
import { NoSuchElementException } from 'effect/Cause'
|
|
4
3
|
import { describe, expect, test } from 'vitest'
|
|
5
4
|
import { mock } from 'vitest-mock-extended'
|
|
6
5
|
import { AuthenticationService } from '../authentication/authenticate.js'
|
|
6
|
+
import { UserClient } from '../rpc/user.js'
|
|
7
7
|
import { StorageService } from '../storage/storage.js'
|
|
8
8
|
import * as Fixture from './email.fixture.js'
|
|
9
9
|
import { EmailService, EmailServiceLive } from './email.js'
|
|
@@ -42,7 +42,7 @@ describe('verifyEmailCode should', () => {
|
|
|
42
42
|
const storageServiceTest = L.effect(
|
|
43
43
|
StorageService,
|
|
44
44
|
E.sync(() => {
|
|
45
|
-
const storageServiceMock = mock<StorageService>()
|
|
45
|
+
const storageServiceMock = mock<StorageService['Type']>()
|
|
46
46
|
|
|
47
47
|
storageServiceMock.getToken.mockReturnValue(E.succeed(Fixture.storedToken))
|
|
48
48
|
storageServiceMock.clearToken.mockReturnValue(E.void)
|
|
@@ -77,7 +77,7 @@ describe('verifyEmailCode should', () => {
|
|
|
77
77
|
const storageServiceTest = L.effect(
|
|
78
78
|
StorageService,
|
|
79
79
|
E.sync(() => {
|
|
80
|
-
const storageServiceMock = mock<StorageService>()
|
|
80
|
+
const storageServiceMock = mock<StorageService['Type']>()
|
|
81
81
|
|
|
82
82
|
storageServiceMock.getToken.mockReturnValue(E.fail(new NoSuchElementException()))
|
|
83
83
|
storageServiceMock.clearToken.mockReturnValue(E.void)
|
|
@@ -89,7 +89,7 @@ describe('verifyEmailCode should', () => {
|
|
|
89
89
|
const authServiceTest = L.effect(
|
|
90
90
|
AuthenticationService,
|
|
91
91
|
E.sync(() => {
|
|
92
|
-
const authServiceMock = mock<AuthenticationService>()
|
|
92
|
+
const authServiceMock = mock<AuthenticationService['Type']>()
|
|
93
93
|
|
|
94
94
|
authServiceMock.authenticatePasskey.mockReturnValue(E.succeed(Fixture.principal))
|
|
95
95
|
|
package/src/email/email.ts
CHANGED
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { BadRequest } from '@passlock/shared/dist/error/error.js'
|
|
5
5
|
import type { VerifyEmailErrors as RpcErrors } from '@passlock/shared/dist/rpc/user.js'
|
|
6
|
-
import {
|
|
6
|
+
import { VerifyEmailReq } from '@passlock/shared/dist/rpc/user.js'
|
|
7
7
|
import type { Principal } from '@passlock/shared/dist/schema/principal.js'
|
|
8
8
|
import { Context, Effect as E, Layer, Option as O, flow, identity, pipe } from 'effect'
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { type AuthenticationErrors, AuthenticationService } from '../authentication/authenticate.js'
|
|
10
|
+
import { UserClient } from '../rpc/user.js'
|
|
11
|
+
import { StorageService, type StoredToken } from '../storage/storage.js'
|
|
11
12
|
|
|
12
13
|
/* Requests */
|
|
13
14
|
|
|
@@ -21,19 +22,20 @@ export type VerifyEmailErrors = RpcErrors | AuthenticationErrors
|
|
|
21
22
|
|
|
22
23
|
/* Dependencies */
|
|
23
24
|
|
|
24
|
-
export class URLQueryString extends Context.Tag('URLQueryString')<
|
|
25
|
+
export class URLQueryString extends Context.Tag('@utils/URLQueryString')<
|
|
25
26
|
URLQueryString,
|
|
26
27
|
E.Effect<string>
|
|
27
28
|
>() {}
|
|
28
29
|
|
|
29
30
|
/* Service */
|
|
30
31
|
|
|
31
|
-
export
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
export class EmailService extends Context.Tag('@services/EmailService')<
|
|
33
|
+
EmailService,
|
|
34
|
+
{
|
|
35
|
+
verifyEmailCode: (request: VerifyRequest) => E.Effect<Principal, VerifyEmailErrors>
|
|
36
|
+
verifyEmailLink: () => E.Effect<Principal, VerifyEmailErrors>
|
|
37
|
+
}
|
|
38
|
+
>() {}
|
|
37
39
|
|
|
38
40
|
/* Utils */
|
|
39
41
|
|
|
@@ -56,12 +58,18 @@ const getToken = () => {
|
|
|
56
58
|
onFailure: () =>
|
|
57
59
|
// No token, need to authenticate the user
|
|
58
60
|
pipe(
|
|
59
|
-
authenticationService.authenticatePasskey({
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
authenticationService.authenticatePasskey({
|
|
62
|
+
userVerification: O.some('preferred'),
|
|
63
|
+
email: O.none(),
|
|
64
|
+
}),
|
|
65
|
+
E.map(
|
|
66
|
+
principal =>
|
|
67
|
+
({
|
|
68
|
+
token: principal.jti,
|
|
69
|
+
authType: principal.authType,
|
|
70
|
+
expiry: principal.exp.getTime(),
|
|
71
|
+
}) as StoredToken,
|
|
72
|
+
),
|
|
65
73
|
),
|
|
66
74
|
})
|
|
67
75
|
|