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