jazz-tools 0.20.11 → 0.20.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.svelte-kit/__package__/server.d.ts.map +1 -1
- package/.svelte-kit/__package__/server.js +2 -1
- package/.svelte-kit/__package__/tests/server.test.js +34 -0
- package/.turbo/turbo-build.log +43 -43
- package/CHANGELOG.md +9 -0
- package/dist/better-auth/auth/server.d.ts.map +1 -1
- package/dist/better-auth/auth/server.js +1 -1
- package/dist/better-auth/auth/server.js.map +1 -1
- package/package.json +4 -4
- package/src/better-auth/auth/server.ts +2 -1
- package/src/better-auth/auth/tests/server.test.ts +45 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/better-auth/auth/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,gBAAgB,EAGtB,MAAM,aAAa,CAAC;AASrB,KAAK,UAAU,GAAG,gBAAgB,GAAG;IACnC,MAAM,EAAE;QACN,IAAI,EAAE;YACJ,MAAM,EAAE;gBACN,SAAS,EAAE;oBACT,IAAI,EAAE,QAAQ,CAAC;oBACf,QAAQ,EAAE,KAAK,CAAC;oBAChB,KAAK,EAAE,KAAK,CAAC;iBACd,CAAC;gBACF,oBAAoB,EAAE;oBACpB,IAAI,EAAE,QAAQ,CAAC;oBACf,QAAQ,EAAE,KAAK,CAAC;oBAChB,KAAK,EAAE,KAAK,CAAC;oBACb,QAAQ,EAAE,KAAK,CAAC;iBACjB,CAAC;aACH,CAAC;SACH,CAAC;KACH,CAAC;CACH,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/better-auth/auth/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,gBAAgB,EAGtB,MAAM,aAAa,CAAC;AASrB,KAAK,UAAU,GAAG,gBAAgB,GAAG;IACnC,MAAM,EAAE;QACN,IAAI,EAAE;YACJ,MAAM,EAAE;gBACN,SAAS,EAAE;oBACT,IAAI,EAAE,QAAQ,CAAC;oBACf,QAAQ,EAAE,KAAK,CAAC;oBAChB,KAAK,EAAE,KAAK,CAAC;iBACd,CAAC;gBACF,oBAAoB,EAAE;oBACpB,IAAI,EAAE,QAAQ,CAAC;oBACf,QAAQ,EAAE,KAAK,CAAC;oBAChB,KAAK,EAAE,KAAK,CAAC;oBACb,QAAQ,EAAE,KAAK,CAAC;iBACjB,CAAC;aACH,CAAC;SACH,CAAC;KACH,CAAC;CACH,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,UA6Q9B,CAAC"}
|
|
@@ -163,7 +163,8 @@ export const jazzPlugin = () => {
|
|
|
163
163
|
return context.path?.startsWith("/sign-in/email-otp") || false;
|
|
164
164
|
},
|
|
165
165
|
handler: createAuthMiddleware(async (ctx) => {
|
|
166
|
-
|
|
166
|
+
// lowercase the email as done in https://github.com/better-auth/better-auth/blob/40a80b070bbabf2d6886e8a3ad1bc068c8d570cb/packages/better-auth/src/plugins/email-otp/routes.ts#L641
|
|
167
|
+
const email = ctx.body.email.toLowerCase();
|
|
167
168
|
const identifier = `jazz-auth-sign-in-otp-${email}`;
|
|
168
169
|
const data = await ctx.context.internalAdapter.findVerificationValue(identifier);
|
|
169
170
|
// if not found, it isn't a sign-up
|
|
@@ -365,6 +365,40 @@ describe("Better-Auth server plugin", async () => {
|
|
|
365
365
|
expect(accountCreationSpy).toHaveBeenCalledTimes(1);
|
|
366
366
|
expect(accountCreationSpy).toHaveBeenCalledWith(expect.objectContaining({ accountID: "123" }), expect.any(Object));
|
|
367
367
|
});
|
|
368
|
+
it("should be case-insensitive for email", async () => {
|
|
369
|
+
let OTP = "";
|
|
370
|
+
sendVerificationOTPSpy.mockImplementationOnce(({ otp }) => {
|
|
371
|
+
OTP = otp;
|
|
372
|
+
});
|
|
373
|
+
await auth.api.sendVerificationOTP({
|
|
374
|
+
headers: {
|
|
375
|
+
"x-jazz-auth": JSON.stringify({
|
|
376
|
+
accountID: "123",
|
|
377
|
+
secretSeed: [1, 2, 3],
|
|
378
|
+
accountSecret: "123",
|
|
379
|
+
}),
|
|
380
|
+
},
|
|
381
|
+
body: {
|
|
382
|
+
email: "EMAIL@email.it",
|
|
383
|
+
type: "sign-in",
|
|
384
|
+
},
|
|
385
|
+
});
|
|
386
|
+
expect(accountCreationSpy).toHaveBeenCalledTimes(0);
|
|
387
|
+
expect(sendVerificationOTPSpy).toHaveBeenCalledTimes(1);
|
|
388
|
+
expect(verificationCreationSpy).toHaveBeenCalledTimes(2);
|
|
389
|
+
expect(verificationCreationSpy.mock.calls[0]?.[0]).toMatchObject(expect.objectContaining({
|
|
390
|
+
identifier: "jazz-auth-sign-in-otp-email@email.it",
|
|
391
|
+
value: expect.stringContaining('"accountID":"123"'),
|
|
392
|
+
}));
|
|
393
|
+
await auth.api.signInEmailOTP({
|
|
394
|
+
body: {
|
|
395
|
+
email: "EMAIL@email.it",
|
|
396
|
+
otp: OTP,
|
|
397
|
+
},
|
|
398
|
+
});
|
|
399
|
+
expect(accountCreationSpy).toHaveBeenCalledTimes(1);
|
|
400
|
+
expect(accountCreationSpy).toHaveBeenCalledWith(expect.objectContaining({ accountID: "123" }), expect.any(Object));
|
|
401
|
+
});
|
|
368
402
|
it("should not expect Jazz's credentials using Email OTP for sign-in an already registered user", async () => {
|
|
369
403
|
// 1. User registration
|
|
370
404
|
const userData = {
|
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> jazz-tools@0.20.
|
|
2
|
+
> jazz-tools@0.20.12 build /home/runner/_work/jazz/jazz/packages/jazz-tools
|
|
3
3
|
> tsup && pnpm types && pnpm build:svelte && pnpm build:better-auth-svelte
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: {"index":"src/index.ts","testing":"src/testing.ts","tools/ssr":"src/tools/ssr/index.ts"}
|
|
@@ -109,81 +109,81 @@
|
|
|
109
109
|
[34mESM[39m Build start
|
|
110
110
|
[32mESM[39m [1mdist/tiptap/index.js [22m[32m564.00 B[39m
|
|
111
111
|
[32mESM[39m [1mdist/tiptap/index.js.map [22m[32m1.21 KB[39m
|
|
112
|
-
[32mESM[39m ⚡️ Build success in
|
|
112
|
+
[32mESM[39m ⚡️ Build success in 38ms
|
|
113
113
|
[32mESM[39m [1mdist/worker/index.js [22m[32m3.45 KB[39m
|
|
114
114
|
[32mESM[39m [1mdist/worker/edge-wasm.js [22m[32m259.00 B[39m
|
|
115
115
|
[32mESM[39m [1mdist/worker/napi-crypto.js [22m[32m110.00 B[39m
|
|
116
116
|
[32mESM[39m [1mdist/worker/index.js.map [22m[32m6.97 KB[39m
|
|
117
117
|
[32mESM[39m [1mdist/worker/edge-wasm.js.map [22m[32m505.00 B[39m
|
|
118
118
|
[32mESM[39m [1mdist/worker/napi-crypto.js.map [22m[32m162.00 B[39m
|
|
119
|
-
[32mESM[39m ⚡️ Build success in
|
|
119
|
+
[32mESM[39m ⚡️ Build success in 36ms
|
|
120
120
|
[32mESM[39m [1mdist/better-auth/auth/client.js [22m[32m4.54 KB[39m
|
|
121
|
-
[32mESM[39m [1mdist/better-auth/auth/server.js [22m[32m8.
|
|
121
|
+
[32mESM[39m [1mdist/better-auth/auth/server.js [22m[32m8.42 KB[39m
|
|
122
122
|
[32mESM[39m [1mdist/better-auth/auth/react.js [22m[32m813.00 B[39m
|
|
123
123
|
[32mESM[39m [1mdist/better-auth/auth/client.js.map [22m[32m8.44 KB[39m
|
|
124
|
-
[32mESM[39m [1mdist/better-auth/auth/server.js.map [22m[32m15.
|
|
124
|
+
[32mESM[39m [1mdist/better-auth/auth/server.js.map [22m[32m15.61 KB[39m
|
|
125
125
|
[32mESM[39m [1mdist/better-auth/auth/react.js.map [22m[32m2.07 KB[39m
|
|
126
|
-
[32mESM[39m ⚡️ Build success in
|
|
126
|
+
[32mESM[39m ⚡️ Build success in 34ms
|
|
127
127
|
[32mESM[39m [1mdist/media/index.js [22m[32m236.00 B[39m
|
|
128
128
|
[32mESM[39m [1mdist/media/index.browser.js [22m[32m2.79 KB[39m
|
|
129
|
-
[32mESM[39m [1mdist/media/index.server.js [22m[32m2.95 KB[39m
|
|
130
129
|
[32mESM[39m [1mdist/media/index.native.js [22m[32m4.02 KB[39m
|
|
130
|
+
[32mESM[39m [1mdist/media/index.server.js [22m[32m2.95 KB[39m
|
|
131
131
|
[32mESM[39m [1mdist/media/chunk-IRL3KNPO.js [22m[32m6.70 KB[39m
|
|
132
132
|
[32mESM[39m [1mdist/media/index.js.map [22m[32m71.00 B[39m
|
|
133
133
|
[32mESM[39m [1mdist/media/index.browser.js.map [22m[32m6.15 KB[39m
|
|
134
|
-
[32mESM[39m [1mdist/media/index.server.js.map [22m[32m6.37 KB[39m
|
|
135
134
|
[32mESM[39m [1mdist/media/index.native.js.map [22m[32m8.13 KB[39m
|
|
135
|
+
[32mESM[39m [1mdist/media/index.server.js.map [22m[32m6.37 KB[39m
|
|
136
136
|
[32mESM[39m [1mdist/media/chunk-IRL3KNPO.js.map [22m[32m17.00 KB[39m
|
|
137
|
-
[32mESM[39m ⚡️ Build success in
|
|
138
|
-
[32mESM[39m [1mdist/browser/index.js [22m[32m15.96 KB[39m
|
|
139
|
-
[32mESM[39m [1mdist/browser/index.js.map [22m[32m34.06 KB[39m
|
|
140
|
-
[32mESM[39m ⚡️ Build success in 62ms
|
|
141
|
-
[32mESM[39m [1mdist/react-core/index.js [22m[32m17.87 KB[39m
|
|
137
|
+
[32mESM[39m ⚡️ Build success in 43ms
|
|
142
138
|
[32mESM[39m [1mdist/react-core/testing.js [22m[32m904.00 B[39m
|
|
143
139
|
[32mESM[39m [1mdist/react-core/chunk-UOYH6JFJ.js [22m[32m189.00 B[39m
|
|
144
|
-
[32mESM[39m [1mdist/react-core/index.js
|
|
140
|
+
[32mESM[39m [1mdist/react-core/index.js [22m[32m17.87 KB[39m
|
|
145
141
|
[32mESM[39m [1mdist/react-core/testing.js.map [22m[32m1.34 KB[39m
|
|
146
142
|
[32mESM[39m [1mdist/react-core/chunk-UOYH6JFJ.js.map [22m[32m363.00 B[39m
|
|
147
|
-
[32mESM[39m
|
|
148
|
-
[32mESM[39m
|
|
149
|
-
[32mESM[39m [1mdist/better-auth/database-adapter/index.js.map [22m[32m58.67 KB[39m
|
|
150
|
-
[32mESM[39m ⚡️ Build success in 52ms
|
|
143
|
+
[32mESM[39m [1mdist/react-core/index.js.map [22m[32m58.59 KB[39m
|
|
144
|
+
[32mESM[39m ⚡️ Build success in 56ms
|
|
151
145
|
[32mESM[39m [1mdist/expo/index.js [22m[32m5.65 KB[39m
|
|
152
146
|
[32mESM[39m [1mdist/expo/testing.js [22m[32m112.00 B[39m
|
|
153
147
|
[32mESM[39m [1mdist/expo/polyfills.js [22m[32m858.00 B[39m
|
|
154
148
|
[32mESM[39m [1mdist/expo/index.js.map [22m[32m11.85 KB[39m
|
|
155
149
|
[32mESM[39m [1mdist/expo/testing.js.map [22m[32m168.00 B[39m
|
|
156
150
|
[32mESM[39m [1mdist/expo/polyfills.js.map [22m[32m1.61 KB[39m
|
|
157
|
-
[32mESM[39m ⚡️ Build success in
|
|
158
|
-
[32mESM[39m [1mdist/
|
|
159
|
-
[32mESM[39m [1mdist/
|
|
160
|
-
[32mESM[39m ⚡️ Build success in
|
|
151
|
+
[32mESM[39m ⚡️ Build success in 53ms
|
|
152
|
+
[32mESM[39m [1mdist/browser/index.js [22m[32m15.96 KB[39m
|
|
153
|
+
[32mESM[39m [1mdist/browser/index.js.map [22m[32m34.06 KB[39m
|
|
154
|
+
[32mESM[39m ⚡️ Build success in 71ms
|
|
155
|
+
[32mESM[39m [1mdist/react/testing.js [22m[32m122.00 B[39m
|
|
161
156
|
[32mESM[39m [1mdist/react/index.js [22m[32m26.02 KB[39m
|
|
162
157
|
[32mESM[39m [1mdist/react/ssr.js [22m[32m693.00 B[39m
|
|
163
|
-
[32mESM[39m [1mdist/react/testing.js [22m[32m122.00 B[39m
|
|
164
|
-
[32mESM[39m [1mdist/react/ssr.js.map [22m[32m1.10 KB[39m
|
|
165
|
-
[32mESM[39m [1mdist/react/index.js.map [22m[32m55.45 KB[39m
|
|
166
158
|
[32mESM[39m [1mdist/react/testing.js.map [22m[32m165.00 B[39m
|
|
167
|
-
[32mESM[39m
|
|
159
|
+
[32mESM[39m [1mdist/react/index.js.map [22m[32m55.45 KB[39m
|
|
160
|
+
[32mESM[39m [1mdist/react/ssr.js.map [22m[32m1.10 KB[39m
|
|
161
|
+
[32mESM[39m ⚡️ Build success in 63ms
|
|
162
|
+
[32mESM[39m [1mdist/better-auth/database-adapter/index.js [22m[32m26.86 KB[39m
|
|
163
|
+
[32mESM[39m [1mdist/better-auth/database-adapter/index.js.map [22m[32m58.67 KB[39m
|
|
164
|
+
[32mESM[39m ⚡️ Build success in 61ms
|
|
165
|
+
[32mESM[39m [1mdist/prosemirror/index.js [22m[32m78.48 KB[39m
|
|
166
|
+
[32mESM[39m [1mdist/prosemirror/index.js.map [22m[32m309.11 KB[39m
|
|
167
|
+
[32mESM[39m ⚡️ Build success in 84ms
|
|
168
|
+
[32mESM[39m [1mdist/react-native-core/index.js [22m[32m34.47 KB[39m
|
|
169
|
+
[32mESM[39m [1mdist/react-native-core/testing.js [22m[32m119.00 B[39m
|
|
170
|
+
[32mESM[39m [1mdist/react-native-core/index.js.map [22m[32m69.10 KB[39m
|
|
171
|
+
[32mESM[39m [1mdist/react-native-core/testing.js.map [22m[32m175.00 B[39m
|
|
172
|
+
[32mESM[39m ⚡️ Build success in 83ms
|
|
168
173
|
[32mESM[39m [1mdist/react-native/index.js [22m[32m38.21 KB[39m
|
|
169
|
-
[32mESM[39m [1mdist/react-native/polyfills.js [22m[32m858.00 B[39m
|
|
170
174
|
[32mESM[39m [1mdist/react-native/testing.js [22m[32m120.00 B[39m
|
|
171
|
-
[32mESM[39m [1mdist/react-native/polyfills.js
|
|
175
|
+
[32mESM[39m [1mdist/react-native/polyfills.js [22m[32m858.00 B[39m
|
|
172
176
|
[32mESM[39m [1mdist/react-native/testing.js.map [22m[32m176.00 B[39m
|
|
177
|
+
[32mESM[39m [1mdist/react-native/polyfills.js.map [22m[32m1.61 KB[39m
|
|
173
178
|
[32mESM[39m [1mdist/react-native/index.js.map [22m[32m76.75 KB[39m
|
|
174
|
-
[32mESM[39m ⚡️ Build success in
|
|
175
|
-
[32mESM[39m [1mdist/react-native-core/testing.js [22m[32m119.00 B[39m
|
|
176
|
-
[32mESM[39m [1mdist/react-native-core/index.js [22m[32m34.47 KB[39m
|
|
177
|
-
[32mESM[39m [1mdist/react-native-core/testing.js.map [22m[32m175.00 B[39m
|
|
178
|
-
[32mESM[39m [1mdist/react-native-core/index.js.map [22m[32m69.10 KB[39m
|
|
179
|
-
[32mESM[39m ⚡️ Build success in 79ms
|
|
179
|
+
[32mESM[39m ⚡️ Build success in 88ms
|
|
180
180
|
[32mESM[39m [1mdist/inspector/index.js [22m[32m37.49 KB[39m
|
|
181
181
|
[32mESM[39m [1mdist/inspector/standalone.js [22m[32m12.61 KB[39m
|
|
182
182
|
[32mESM[39m [1mdist/inspector/chunk-ORKZSKZF.js [22m[32m128.83 KB[39m
|
|
183
|
-
[32mESM[39m [1mdist/inspector/index.js.map [22m[32m63.80 KB[39m
|
|
184
183
|
[32mESM[39m [1mdist/inspector/standalone.js.map [22m[32m20.11 KB[39m
|
|
184
|
+
[32mESM[39m [1mdist/inspector/index.js.map [22m[32m63.80 KB[39m
|
|
185
185
|
[32mESM[39m [1mdist/inspector/chunk-ORKZSKZF.js.map [22m[32m222.34 KB[39m
|
|
186
|
-
[32mESM[39m ⚡️ Build success in
|
|
186
|
+
[32mESM[39m ⚡️ Build success in 122ms
|
|
187
187
|
[32mESM[39m [1mdist/testing.js [22m[32m8.56 KB[39m
|
|
188
188
|
[32mESM[39m [1mdist/index.js [22m[32m32.18 KB[39m
|
|
189
189
|
[32mESM[39m [1mdist/tools/ssr.js [22m[32m156.00 B[39m
|
|
@@ -191,28 +191,28 @@
|
|
|
191
191
|
[32mESM[39m [1mdist/chunk-ZQWSQH6L.js [22m[32m945.00 B[39m
|
|
192
192
|
[32mESM[39m [1mdist/chunk-KGV2CJMG.js [22m[32m262.16 KB[39m
|
|
193
193
|
[32mESM[39m [1mdist/testing.js.map [22m[32m16.22 KB[39m
|
|
194
|
-
[32mESM[39m [1mdist/index.js.map [22m[32m65.34 KB[39m
|
|
195
|
-
[32mESM[39m [1mdist/tools/ssr.js.map [22m[32m71.00 B[39m
|
|
196
194
|
[32mESM[39m [1mdist/chunk-K4D7IMFM.js.map [22m[32m1.10 KB[39m
|
|
195
|
+
[32mESM[39m [1mdist/tools/ssr.js.map [22m[32m71.00 B[39m
|
|
196
|
+
[32mESM[39m [1mdist/index.js.map [22m[32m65.34 KB[39m
|
|
197
197
|
[32mESM[39m [1mdist/chunk-ZQWSQH6L.js.map [22m[32m71.00 B[39m
|
|
198
198
|
[32mESM[39m [1mdist/chunk-KGV2CJMG.js.map [22m[32m604.30 KB[39m
|
|
199
|
-
[32mESM[39m ⚡️ Build success in
|
|
199
|
+
[32mESM[39m ⚡️ Build success in 139ms
|
|
200
200
|
[32mESM[39m [1mdist/inspector/register-custom-element.js [22m[32m305.00 B[39m
|
|
201
201
|
[32mESM[39m [1mdist/inspector/register-custom-element.js.map [22m[32m445.00 B[39m
|
|
202
202
|
[32mESM[39m [1mdist/inspector/custom-element-7G7IZVLL.js [22m[32m1.64 MB[39m
|
|
203
203
|
[32mESM[39m [1mdist/inspector/custom-element-7G7IZVLL.js.map [22m[32m2.52 MB[39m
|
|
204
|
-
[32mESM[39m ⚡️ Build success in
|
|
204
|
+
[32mESM[39m ⚡️ Build success in 171ms
|
|
205
205
|
|
|
206
|
-
> jazz-tools@0.20.
|
|
206
|
+
> jazz-tools@0.20.12 types /home/runner/_work/jazz/jazz/packages/jazz-tools
|
|
207
207
|
> tsc --outDir dist
|
|
208
208
|
|
|
209
209
|
|
|
210
|
-
> jazz-tools@0.20.
|
|
210
|
+
> jazz-tools@0.20.12 build:svelte /home/runner/_work/jazz/jazz/packages/jazz-tools
|
|
211
211
|
> rm -rf dist/svelte && svelte-package -i src/svelte -o dist/svelte --tsconfig tsconfig.svelte.json
|
|
212
212
|
|
|
213
213
|
src/svelte -> dist/svelte
|
|
214
214
|
|
|
215
|
-
> jazz-tools@0.20.
|
|
215
|
+
> jazz-tools@0.20.12 build:better-auth-svelte /home/runner/_work/jazz/jazz/packages/jazz-tools
|
|
216
216
|
> mkdir -p dist/better-auth/auth && svelte-package -i src/better-auth/auth -o dist/better-auth/auth-temp --tsconfig tsconfig.svelte.json && cp dist/better-auth/auth-temp/svelte.svelte dist/better-auth/auth/svelte.svelte && cp dist/better-auth/auth-temp/svelte.svelte.d.ts dist/better-auth/auth/svelte.d.ts && rm -rf dist/better-auth/auth-temp
|
|
217
217
|
|
|
218
218
|
src/better-auth/auth -> dist/better-auth/auth-temp
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# jazz-tools
|
|
2
2
|
|
|
3
|
+
## 0.20.12
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 9a43096: Fixed Better Auth email OTP sign-in to handle email addresses case-insensitively.
|
|
8
|
+
- cojson@0.20.12
|
|
9
|
+
- cojson-storage-indexeddb@0.20.12
|
|
10
|
+
- cojson-transport-ws@0.20.12
|
|
11
|
+
|
|
3
12
|
## 0.20.11
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/better-auth/auth/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,gBAAgB,EAGtB,MAAM,aAAa,CAAC;AASrB,KAAK,UAAU,GAAG,gBAAgB,GAAG;IACnC,MAAM,EAAE;QACN,IAAI,EAAE;YACJ,MAAM,EAAE;gBACN,SAAS,EAAE;oBACT,IAAI,EAAE,QAAQ,CAAC;oBACf,QAAQ,EAAE,KAAK,CAAC;oBAChB,KAAK,EAAE,KAAK,CAAC;iBACd,CAAC;gBACF,oBAAoB,EAAE;oBACpB,IAAI,EAAE,QAAQ,CAAC;oBACf,QAAQ,EAAE,KAAK,CAAC;oBAChB,KAAK,EAAE,KAAK,CAAC;oBACb,QAAQ,EAAE,KAAK,CAAC;iBACjB,CAAC;aACH,CAAC;SACH,CAAC;KACH,CAAC;CACH,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/better-auth/auth/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,gBAAgB,EAGtB,MAAM,aAAa,CAAC;AASrB,KAAK,UAAU,GAAG,gBAAgB,GAAG;IACnC,MAAM,EAAE;QACN,IAAI,EAAE;YACJ,MAAM,EAAE;gBACN,SAAS,EAAE;oBACT,IAAI,EAAE,QAAQ,CAAC;oBACf,QAAQ,EAAE,KAAK,CAAC;oBAChB,KAAK,EAAE,KAAK,CAAC;iBACd,CAAC;gBACF,oBAAoB,EAAE;oBACpB,IAAI,EAAE,QAAQ,CAAC;oBACf,QAAQ,EAAE,KAAK,CAAC;oBAChB,KAAK,EAAE,KAAK,CAAC;oBACb,QAAQ,EAAE,KAAK,CAAC;iBACjB,CAAC;aACH,CAAC;SACH,CAAC;KACH,CAAC;CACH,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,UA6Q9B,CAAC"}
|
|
@@ -147,7 +147,7 @@ var jazzPlugin = () => {
|
|
|
147
147
|
return context.path?.startsWith("/sign-in/email-otp") || false;
|
|
148
148
|
},
|
|
149
149
|
handler: createAuthMiddleware(async (ctx) => {
|
|
150
|
-
const email = ctx.body.email;
|
|
150
|
+
const email = ctx.body.email.toLowerCase();
|
|
151
151
|
const identifier = `jazz-auth-sign-in-otp-${email}`;
|
|
152
152
|
const data = await ctx.context.internalAdapter.findVerificationValue(
|
|
153
153
|
identifier
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/better-auth/auth/server.ts"],"sourcesContent":["import {\n AuthContext,\n type BetterAuthPlugin,\n MiddlewareContext,\n MiddlewareOptions,\n} from \"better-auth\";\nimport { APIError } from \"better-auth/api\";\nimport { symmetricDecrypt, symmetricEncrypt } from \"better-auth/crypto\";\nimport { createAuthMiddleware } from \"better-auth/plugins\";\nimport type { Account, AuthCredentials, ID } from \"jazz-tools\";\n\n// Define a type to have user fields mapped in the better-auth instance\n// It should be automatic, but it needs an hard reference to BetterAuthPlugin type\n// in order to be exported as library.\ntype JazzPlugin = BetterAuthPlugin & {\n schema: {\n user: {\n fields: {\n accountID: {\n type: \"string\";\n required: false;\n input: false;\n };\n encryptedCredentials: {\n type: \"string\";\n required: false;\n input: false;\n returned: false;\n };\n };\n };\n };\n};\n\n/**\n * @returns The BetterAuth server plugin.\n *\n * @example\n * ```ts\n * const auth = betterAuth({\n * plugins: [jazzPlugin()],\n * // ... other BetterAuth options\n * });\n * ```\n */\nexport const jazzPlugin: () => JazzPlugin = () => {\n return {\n id: \"jazz-plugin\",\n schema: {\n user: {\n fields: {\n accountID: {\n type: \"string\",\n required: false,\n input: false,\n },\n encryptedCredentials: {\n type: \"string\",\n required: false,\n input: false,\n returned: false,\n },\n },\n },\n },\n\n init() {\n return {\n options: {\n databaseHooks: {\n user: {\n create: {\n before: async (user, context) => {\n // If the user is created without a jazzAuth, it will throw an error.\n if (!contextContainsJazzAuth(context)) {\n throw new APIError(422, {\n message: \"JazzAuth is required on user creation\",\n });\n }\n // Decorate the user with the jazz's credentials.\n return {\n data: {\n accountID: context.jazzAuth.accountID,\n encryptedCredentials:\n context.jazzAuth.encryptedCredentials,\n },\n };\n },\n },\n },\n verification: {\n create: {\n after: async (verification, context) => {\n /**\n * For: Email OTP plugin\n * After a verification is created, if it is from the EmailOTP plugin,\n * create a new verification value with the jazzAuth with the same expiration.\n */\n if (\n contextContainsJazzAuth(context) &&\n verification.identifier.startsWith(\"sign-in-otp-\")\n ) {\n const identifier = `jazz-auth-${verification.identifier}`;\n await context.context.internalAdapter.deleteVerificationByIdentifier(\n identifier,\n );\n await context.context.internalAdapter.createVerificationValue(\n {\n value: JSON.stringify({ jazzAuth: context.jazzAuth }),\n identifier: identifier,\n expiresAt: verification.expiresAt,\n },\n );\n }\n },\n },\n },\n },\n },\n };\n },\n\n hooks: {\n before: [\n /**\n * If the client sends a x-jazz-auth header,\n * we encrypt the credentials and inject them into the context.\n */\n {\n matcher: (context) => {\n return !!context.headers?.get(\"x-jazz-auth\");\n },\n handler: createAuthMiddleware(async (ctx) => {\n const jazzAuth = JSON.parse(ctx.headers?.get(\"x-jazz-auth\")!);\n\n const credentials: AuthCredentials = {\n accountID: jazzAuth.accountID as ID<Account>,\n secretSeed: jazzAuth.secretSeed,\n accountSecret: jazzAuth.accountSecret as any,\n // If the provider remains 'anonymous', Jazz will not consider us authenticated later.\n provider: \"better-auth\",\n };\n\n const encryptedCredentials = await symmetricEncrypt({\n key: ctx.context.secret,\n data: JSON.stringify(credentials),\n });\n\n return {\n context: {\n ...ctx,\n jazzAuth: {\n accountID: jazzAuth.accountID,\n encryptedCredentials: encryptedCredentials,\n },\n },\n };\n }),\n },\n\n /**\n * For: Social / OAuth2 plugin\n * /callback is the endpoint that BetterAuth uses to authenticate the user coming from a social provider.\n * 1. Catch the state\n * 2. Find the verification value\n * 3. If the verification value contains a jazzAuth, inject into the context to have it in case of registration.\n */\n {\n matcher: (context) => {\n return (\n context.path?.startsWith(\"/callback\") ||\n context.path?.startsWith(\"/oauth2/callback\") ||\n false\n );\n },\n handler: createAuthMiddleware(async (ctx) => {\n const state = ctx.query?.state || ctx.body?.state;\n\n const identifier = `jazz-auth-${state}`;\n\n const data =\n await ctx.context.internalAdapter.findVerificationValue(\n identifier,\n );\n\n // if not found, the social plugin will throw later anyway\n if (!data) {\n throw new APIError(404, {\n message: \"Verification not found\",\n });\n }\n\n const parsed = JSON.parse(data.value);\n\n if (parsed && \"jazzAuth\" in parsed) {\n return {\n context: {\n ...ctx,\n jazzAuth: parsed.jazzAuth,\n },\n };\n } else {\n throw new APIError(404, {\n message: \"JazzAuth not found in verification value\",\n });\n }\n }),\n },\n /**\n * For: Email OTP plugin\n * When the user sends an OTP, we try to find the jazzAuth.\n * If it isn't a sign-up, we expect to not find a verification value.\n */\n {\n matcher: (context) => {\n return context.path?.startsWith(\"/sign-in/email-otp\") || false;\n },\n handler: createAuthMiddleware(async (ctx) => {\n const email = ctx.body.email;\n const identifier = `jazz-auth-sign-in-otp-${email}`;\n\n const data =\n await ctx.context.internalAdapter.findVerificationValue(\n identifier,\n );\n\n // if not found, it isn't a sign-up\n if (!data || data.expiresAt < new Date()) {\n return;\n }\n\n const parsed = JSON.parse(data.value);\n\n if (parsed && \"jazzAuth\" in parsed) {\n return {\n context: {\n ...ctx,\n jazzAuth: parsed.jazzAuth,\n },\n };\n } else {\n throw new APIError(500, {\n message: \"JazzAuth not found in verification value\",\n });\n }\n }),\n },\n ],\n after: [\n /**\n * This middleware is used to extract the jazzAuth from the user and return it in the response.\n * It is used in the following endpoints that return the user:\n * - /sign-up/email\n * - /sign-in/email\n * - /get-session\n */\n {\n matcher: (context) => {\n return (\n context.path?.startsWith(\"/sign-up\") ||\n context.path?.startsWith(\"/sign-in\") ||\n context.path?.startsWith(\"/get-session\") ||\n false\n );\n },\n handler: createAuthMiddleware({}, async (ctx) => {\n const returned = ctx.context.returned as any;\n if (!returned?.user?.id) {\n return;\n }\n const jazzAuth = await extractJazzAuth(returned.user.id, ctx);\n\n return ctx.json({\n ...returned,\n jazzAuth: jazzAuth,\n });\n }),\n },\n\n /**\n * For: Social / OAuth2 plugin\n * When the user sign-in via social, we create a verification value with the jazzAuth.\n */\n {\n matcher: (context) => {\n return context.path?.startsWith(\"/sign-in/social\") || false;\n },\n handler: createAuthMiddleware(async (ctx) => {\n if (!contextContainsJazzAuth(ctx)) {\n throw new APIError(500, {\n message: \"JazzAuth not found in context\",\n });\n }\n\n const returned = ctx.context.returned as { url: string };\n\n const url = new URL(returned.url);\n const state = url.searchParams.get(\"state\");\n\n const value = JSON.stringify({ jazzAuth: ctx.jazzAuth });\n const expiresAt = new Date();\n expiresAt.setMinutes(expiresAt.getMinutes() + 10);\n\n await ctx.context.internalAdapter.createVerificationValue({\n value,\n identifier: `jazz-auth-${state}`,\n expiresAt,\n });\n }),\n },\n ],\n },\n } satisfies JazzPlugin;\n};\n\nfunction contextContainsJazzAuth(ctx: unknown): ctx is {\n jazzAuth: {\n accountID: string;\n encryptedCredentials: string;\n };\n} {\n return !!ctx && typeof ctx === \"object\" && \"jazzAuth\" in ctx;\n}\n\nasync function extractJazzAuth(\n userId: string,\n ctx: MiddlewareContext<\n MiddlewareOptions,\n AuthContext & {\n returned?: unknown;\n responseHeaders?: Headers;\n }\n >,\n) {\n const user = await ctx.context.adapter.findOne<{\n accountID: string;\n encryptedCredentials: string;\n }>({\n model: ctx.context.tables.user!.modelName,\n where: [\n {\n field: \"id\",\n operator: \"eq\",\n value: userId,\n },\n ],\n select: [\"accountID\", \"encryptedCredentials\"],\n });\n\n if (!user) {\n return;\n }\n\n const jazzAuth = JSON.parse(\n await symmetricDecrypt({\n key: ctx.context.secret,\n data: user.encryptedCredentials,\n }),\n );\n\n return jazzAuth;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/better-auth/auth/server.ts"],"sourcesContent":["import {\n AuthContext,\n type BetterAuthPlugin,\n MiddlewareContext,\n MiddlewareOptions,\n} from \"better-auth\";\nimport { APIError } from \"better-auth/api\";\nimport { symmetricDecrypt, symmetricEncrypt } from \"better-auth/crypto\";\nimport { createAuthMiddleware } from \"better-auth/plugins\";\nimport type { Account, AuthCredentials, ID } from \"jazz-tools\";\n\n// Define a type to have user fields mapped in the better-auth instance\n// It should be automatic, but it needs an hard reference to BetterAuthPlugin type\n// in order to be exported as library.\ntype JazzPlugin = BetterAuthPlugin & {\n schema: {\n user: {\n fields: {\n accountID: {\n type: \"string\";\n required: false;\n input: false;\n };\n encryptedCredentials: {\n type: \"string\";\n required: false;\n input: false;\n returned: false;\n };\n };\n };\n };\n};\n\n/**\n * @returns The BetterAuth server plugin.\n *\n * @example\n * ```ts\n * const auth = betterAuth({\n * plugins: [jazzPlugin()],\n * // ... other BetterAuth options\n * });\n * ```\n */\nexport const jazzPlugin: () => JazzPlugin = () => {\n return {\n id: \"jazz-plugin\",\n schema: {\n user: {\n fields: {\n accountID: {\n type: \"string\",\n required: false,\n input: false,\n },\n encryptedCredentials: {\n type: \"string\",\n required: false,\n input: false,\n returned: false,\n },\n },\n },\n },\n\n init() {\n return {\n options: {\n databaseHooks: {\n user: {\n create: {\n before: async (user, context) => {\n // If the user is created without a jazzAuth, it will throw an error.\n if (!contextContainsJazzAuth(context)) {\n throw new APIError(422, {\n message: \"JazzAuth is required on user creation\",\n });\n }\n // Decorate the user with the jazz's credentials.\n return {\n data: {\n accountID: context.jazzAuth.accountID,\n encryptedCredentials:\n context.jazzAuth.encryptedCredentials,\n },\n };\n },\n },\n },\n verification: {\n create: {\n after: async (verification, context) => {\n /**\n * For: Email OTP plugin\n * After a verification is created, if it is from the EmailOTP plugin,\n * create a new verification value with the jazzAuth with the same expiration.\n */\n if (\n contextContainsJazzAuth(context) &&\n verification.identifier.startsWith(\"sign-in-otp-\")\n ) {\n const identifier = `jazz-auth-${verification.identifier}`;\n await context.context.internalAdapter.deleteVerificationByIdentifier(\n identifier,\n );\n await context.context.internalAdapter.createVerificationValue(\n {\n value: JSON.stringify({ jazzAuth: context.jazzAuth }),\n identifier: identifier,\n expiresAt: verification.expiresAt,\n },\n );\n }\n },\n },\n },\n },\n },\n };\n },\n\n hooks: {\n before: [\n /**\n * If the client sends a x-jazz-auth header,\n * we encrypt the credentials and inject them into the context.\n */\n {\n matcher: (context) => {\n return !!context.headers?.get(\"x-jazz-auth\");\n },\n handler: createAuthMiddleware(async (ctx) => {\n const jazzAuth = JSON.parse(ctx.headers?.get(\"x-jazz-auth\")!);\n\n const credentials: AuthCredentials = {\n accountID: jazzAuth.accountID as ID<Account>,\n secretSeed: jazzAuth.secretSeed,\n accountSecret: jazzAuth.accountSecret as any,\n // If the provider remains 'anonymous', Jazz will not consider us authenticated later.\n provider: \"better-auth\",\n };\n\n const encryptedCredentials = await symmetricEncrypt({\n key: ctx.context.secret,\n data: JSON.stringify(credentials),\n });\n\n return {\n context: {\n ...ctx,\n jazzAuth: {\n accountID: jazzAuth.accountID,\n encryptedCredentials: encryptedCredentials,\n },\n },\n };\n }),\n },\n\n /**\n * For: Social / OAuth2 plugin\n * /callback is the endpoint that BetterAuth uses to authenticate the user coming from a social provider.\n * 1. Catch the state\n * 2. Find the verification value\n * 3. If the verification value contains a jazzAuth, inject into the context to have it in case of registration.\n */\n {\n matcher: (context) => {\n return (\n context.path?.startsWith(\"/callback\") ||\n context.path?.startsWith(\"/oauth2/callback\") ||\n false\n );\n },\n handler: createAuthMiddleware(async (ctx) => {\n const state = ctx.query?.state || ctx.body?.state;\n\n const identifier = `jazz-auth-${state}`;\n\n const data =\n await ctx.context.internalAdapter.findVerificationValue(\n identifier,\n );\n\n // if not found, the social plugin will throw later anyway\n if (!data) {\n throw new APIError(404, {\n message: \"Verification not found\",\n });\n }\n\n const parsed = JSON.parse(data.value);\n\n if (parsed && \"jazzAuth\" in parsed) {\n return {\n context: {\n ...ctx,\n jazzAuth: parsed.jazzAuth,\n },\n };\n } else {\n throw new APIError(404, {\n message: \"JazzAuth not found in verification value\",\n });\n }\n }),\n },\n /**\n * For: Email OTP plugin\n * When the user sends an OTP, we try to find the jazzAuth.\n * If it isn't a sign-up, we expect to not find a verification value.\n */\n {\n matcher: (context) => {\n return context.path?.startsWith(\"/sign-in/email-otp\") || false;\n },\n handler: createAuthMiddleware(async (ctx) => {\n // lowercase the email as done in https://github.com/better-auth/better-auth/blob/40a80b070bbabf2d6886e8a3ad1bc068c8d570cb/packages/better-auth/src/plugins/email-otp/routes.ts#L641\n const email = ctx.body.email.toLowerCase();\n const identifier = `jazz-auth-sign-in-otp-${email}`;\n\n const data =\n await ctx.context.internalAdapter.findVerificationValue(\n identifier,\n );\n\n // if not found, it isn't a sign-up\n if (!data || data.expiresAt < new Date()) {\n return;\n }\n\n const parsed = JSON.parse(data.value);\n\n if (parsed && \"jazzAuth\" in parsed) {\n return {\n context: {\n ...ctx,\n jazzAuth: parsed.jazzAuth,\n },\n };\n } else {\n throw new APIError(500, {\n message: \"JazzAuth not found in verification value\",\n });\n }\n }),\n },\n ],\n after: [\n /**\n * This middleware is used to extract the jazzAuth from the user and return it in the response.\n * It is used in the following endpoints that return the user:\n * - /sign-up/email\n * - /sign-in/email\n * - /get-session\n */\n {\n matcher: (context) => {\n return (\n context.path?.startsWith(\"/sign-up\") ||\n context.path?.startsWith(\"/sign-in\") ||\n context.path?.startsWith(\"/get-session\") ||\n false\n );\n },\n handler: createAuthMiddleware({}, async (ctx) => {\n const returned = ctx.context.returned as any;\n if (!returned?.user?.id) {\n return;\n }\n const jazzAuth = await extractJazzAuth(returned.user.id, ctx);\n\n return ctx.json({\n ...returned,\n jazzAuth: jazzAuth,\n });\n }),\n },\n\n /**\n * For: Social / OAuth2 plugin\n * When the user sign-in via social, we create a verification value with the jazzAuth.\n */\n {\n matcher: (context) => {\n return context.path?.startsWith(\"/sign-in/social\") || false;\n },\n handler: createAuthMiddleware(async (ctx) => {\n if (!contextContainsJazzAuth(ctx)) {\n throw new APIError(500, {\n message: \"JazzAuth not found in context\",\n });\n }\n\n const returned = ctx.context.returned as { url: string };\n\n const url = new URL(returned.url);\n const state = url.searchParams.get(\"state\");\n\n const value = JSON.stringify({ jazzAuth: ctx.jazzAuth });\n const expiresAt = new Date();\n expiresAt.setMinutes(expiresAt.getMinutes() + 10);\n\n await ctx.context.internalAdapter.createVerificationValue({\n value,\n identifier: `jazz-auth-${state}`,\n expiresAt,\n });\n }),\n },\n ],\n },\n } satisfies JazzPlugin;\n};\n\nfunction contextContainsJazzAuth(ctx: unknown): ctx is {\n jazzAuth: {\n accountID: string;\n encryptedCredentials: string;\n };\n} {\n return !!ctx && typeof ctx === \"object\" && \"jazzAuth\" in ctx;\n}\n\nasync function extractJazzAuth(\n userId: string,\n ctx: MiddlewareContext<\n MiddlewareOptions,\n AuthContext & {\n returned?: unknown;\n responseHeaders?: Headers;\n }\n >,\n) {\n const user = await ctx.context.adapter.findOne<{\n accountID: string;\n encryptedCredentials: string;\n }>({\n model: ctx.context.tables.user!.modelName,\n where: [\n {\n field: \"id\",\n operator: \"eq\",\n value: userId,\n },\n ],\n select: [\"accountID\", \"encryptedCredentials\"],\n });\n\n if (!user) {\n return;\n }\n\n const jazzAuth = JSON.parse(\n await symmetricDecrypt({\n key: ctx.context.secret,\n data: user.encryptedCredentials,\n }),\n );\n\n return jazzAuth;\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -196,7 +196,7 @@
|
|
|
196
196
|
},
|
|
197
197
|
"type": "module",
|
|
198
198
|
"license": "MIT",
|
|
199
|
-
"version": "0.20.
|
|
199
|
+
"version": "0.20.12",
|
|
200
200
|
"dependencies": {
|
|
201
201
|
"@scure/base": "1.2.1",
|
|
202
202
|
"@scure/bip39": "^1.3.0",
|
|
@@ -212,9 +212,9 @@
|
|
|
212
212
|
"prosemirror-transform": "^1.9.0",
|
|
213
213
|
"use-sync-external-store": "^1.5.0",
|
|
214
214
|
"zod": "4.1.11",
|
|
215
|
-
"cojson": "0.20.
|
|
216
|
-
"cojson-storage-indexeddb": "0.20.
|
|
217
|
-
"cojson-transport-ws": "0.20.
|
|
215
|
+
"cojson": "0.20.12",
|
|
216
|
+
"cojson-storage-indexeddb": "0.20.12",
|
|
217
|
+
"cojson-transport-ws": "0.20.12"
|
|
218
218
|
},
|
|
219
219
|
"devDependencies": {
|
|
220
220
|
"@scure/bip39": "^1.3.0",
|
|
@@ -216,7 +216,8 @@ export const jazzPlugin: () => JazzPlugin = () => {
|
|
|
216
216
|
return context.path?.startsWith("/sign-in/email-otp") || false;
|
|
217
217
|
},
|
|
218
218
|
handler: createAuthMiddleware(async (ctx) => {
|
|
219
|
-
|
|
219
|
+
// lowercase the email as done in https://github.com/better-auth/better-auth/blob/40a80b070bbabf2d6886e8a3ad1bc068c8d570cb/packages/better-auth/src/plugins/email-otp/routes.ts#L641
|
|
220
|
+
const email = ctx.body.email.toLowerCase();
|
|
220
221
|
const identifier = `jazz-auth-sign-in-otp-${email}`;
|
|
221
222
|
|
|
222
223
|
const data =
|
|
@@ -453,6 +453,51 @@ describe("Better-Auth server plugin", async () => {
|
|
|
453
453
|
);
|
|
454
454
|
});
|
|
455
455
|
|
|
456
|
+
it("should be case-insensitive for email", async () => {
|
|
457
|
+
let OTP: string = "";
|
|
458
|
+
|
|
459
|
+
sendVerificationOTPSpy.mockImplementationOnce(({ otp }) => {
|
|
460
|
+
OTP = otp;
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
await auth.api.sendVerificationOTP({
|
|
464
|
+
headers: {
|
|
465
|
+
"x-jazz-auth": JSON.stringify({
|
|
466
|
+
accountID: "123",
|
|
467
|
+
secretSeed: [1, 2, 3],
|
|
468
|
+
accountSecret: "123",
|
|
469
|
+
}),
|
|
470
|
+
},
|
|
471
|
+
body: {
|
|
472
|
+
email: "EMAIL@email.it",
|
|
473
|
+
type: "sign-in",
|
|
474
|
+
},
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
expect(accountCreationSpy).toHaveBeenCalledTimes(0);
|
|
478
|
+
expect(sendVerificationOTPSpy).toHaveBeenCalledTimes(1);
|
|
479
|
+
expect(verificationCreationSpy).toHaveBeenCalledTimes(2);
|
|
480
|
+
expect(verificationCreationSpy.mock.calls[0]?.[0]).toMatchObject(
|
|
481
|
+
expect.objectContaining({
|
|
482
|
+
identifier: "jazz-auth-sign-in-otp-email@email.it",
|
|
483
|
+
value: expect.stringContaining('"accountID":"123"'),
|
|
484
|
+
}),
|
|
485
|
+
);
|
|
486
|
+
|
|
487
|
+
await auth.api.signInEmailOTP({
|
|
488
|
+
body: {
|
|
489
|
+
email: "EMAIL@email.it",
|
|
490
|
+
otp: OTP,
|
|
491
|
+
},
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
expect(accountCreationSpy).toHaveBeenCalledTimes(1);
|
|
495
|
+
expect(accountCreationSpy).toHaveBeenCalledWith(
|
|
496
|
+
expect.objectContaining({ accountID: "123" }),
|
|
497
|
+
expect.any(Object),
|
|
498
|
+
);
|
|
499
|
+
});
|
|
500
|
+
|
|
456
501
|
it("should not expect Jazz's credentials using Email OTP for sign-in an already registered user", async () => {
|
|
457
502
|
// 1. User registration
|
|
458
503
|
const userData = {
|