wabe 0.6.12 → 0.6.14

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.
Files changed (156) hide show
  1. package/dist/database/DatabaseController.d.ts +2 -0
  2. package/dist/file/FileDevAdapter.d.ts +1 -0
  3. package/dist/graphql/pointerAndRelationFunction.d.ts +6 -0
  4. package/dist/index.js +3827 -3541
  5. package/dist/schema/Schema.d.ts +2 -2
  6. package/dist/server/generateCodegen.d.ts +10 -0
  7. package/dist/server/index.d.ts +2 -1
  8. package/dist/utils/objectKeys.d.ts +1 -0
  9. package/package.json +7 -4
  10. package/dev/index.ts +0 -215
  11. package/dist/schema/resolvers/sendEmail.d.ts +0 -1
  12. package/generated/schema.graphql +0 -1945
  13. package/generated/wabe.ts +0 -448
  14. package/src/authentication/OTP.test.ts +0 -69
  15. package/src/authentication/OTP.ts +0 -64
  16. package/src/authentication/Session.test.ts +0 -629
  17. package/src/authentication/Session.ts +0 -517
  18. package/src/authentication/cookies.ts +0 -10
  19. package/src/authentication/defaultAuthentication.ts +0 -209
  20. package/src/authentication/index.ts +0 -4
  21. package/src/authentication/interface.ts +0 -177
  22. package/src/authentication/oauth/GitHub.test.ts +0 -91
  23. package/src/authentication/oauth/GitHub.ts +0 -121
  24. package/src/authentication/oauth/Google.test.ts +0 -91
  25. package/src/authentication/oauth/Google.ts +0 -101
  26. package/src/authentication/oauth/Oauth2Client.test.ts +0 -219
  27. package/src/authentication/oauth/Oauth2Client.ts +0 -135
  28. package/src/authentication/oauth/index.ts +0 -2
  29. package/src/authentication/oauth/utils.test.ts +0 -33
  30. package/src/authentication/oauth/utils.ts +0 -27
  31. package/src/authentication/providers/EmailOTP.test.ts +0 -127
  32. package/src/authentication/providers/EmailOTP.ts +0 -95
  33. package/src/authentication/providers/EmailPassword.test.ts +0 -263
  34. package/src/authentication/providers/EmailPassword.ts +0 -138
  35. package/src/authentication/providers/EmailPasswordSRP.test.ts +0 -208
  36. package/src/authentication/providers/EmailPasswordSRP.ts +0 -191
  37. package/src/authentication/providers/GitHub.ts +0 -24
  38. package/src/authentication/providers/Google.ts +0 -24
  39. package/src/authentication/providers/OAuth.test.ts +0 -185
  40. package/src/authentication/providers/OAuth.ts +0 -106
  41. package/src/authentication/providers/PhonePassword.test.ts +0 -221
  42. package/src/authentication/providers/PhonePassword.ts +0 -136
  43. package/src/authentication/providers/QRCodeOTP.test.ts +0 -77
  44. package/src/authentication/providers/QRCodeOTP.ts +0 -69
  45. package/src/authentication/providers/index.ts +0 -6
  46. package/src/authentication/resolvers/refreshResolver.test.ts +0 -30
  47. package/src/authentication/resolvers/refreshResolver.ts +0 -19
  48. package/src/authentication/resolvers/signInWithResolver.inte.test.ts +0 -59
  49. package/src/authentication/resolvers/signInWithResolver.test.ts +0 -306
  50. package/src/authentication/resolvers/signInWithResolver.ts +0 -106
  51. package/src/authentication/resolvers/signOutResolver.test.ts +0 -38
  52. package/src/authentication/resolvers/signOutResolver.ts +0 -18
  53. package/src/authentication/resolvers/signUpWithResolver.test.ts +0 -180
  54. package/src/authentication/resolvers/signUpWithResolver.ts +0 -68
  55. package/src/authentication/resolvers/verifyChallenge.test.ts +0 -230
  56. package/src/authentication/resolvers/verifyChallenge.ts +0 -78
  57. package/src/authentication/roles.test.ts +0 -49
  58. package/src/authentication/roles.ts +0 -40
  59. package/src/authentication/security.ts +0 -278
  60. package/src/authentication/utils.test.ts +0 -97
  61. package/src/authentication/utils.ts +0 -39
  62. package/src/cache/InMemoryCache.test.ts +0 -62
  63. package/src/cache/InMemoryCache.ts +0 -45
  64. package/src/cron/index.test.ts +0 -17
  65. package/src/cron/index.ts +0 -43
  66. package/src/database/DatabaseController.test.ts +0 -613
  67. package/src/database/DatabaseController.ts +0 -1415
  68. package/src/database/index.test.ts +0 -1551
  69. package/src/database/index.ts +0 -9
  70. package/src/database/interface.ts +0 -308
  71. package/src/email/DevAdapter.ts +0 -7
  72. package/src/email/EmailController.test.ts +0 -29
  73. package/src/email/EmailController.ts +0 -13
  74. package/src/email/index.ts +0 -2
  75. package/src/email/interface.ts +0 -36
  76. package/src/email/templates/sendOtpCode.ts +0 -120
  77. package/src/file/FileController.ts +0 -28
  78. package/src/file/FileDevAdapter.ts +0 -51
  79. package/src/file/hookDeleteFile.ts +0 -25
  80. package/src/file/hookReadFile.ts +0 -66
  81. package/src/file/hookUploadFile.ts +0 -52
  82. package/src/file/index.test.ts +0 -1031
  83. package/src/file/index.ts +0 -2
  84. package/src/file/interface.ts +0 -63
  85. package/src/file/security.ts +0 -156
  86. package/src/graphql/GraphQLSchema.test.ts +0 -5099
  87. package/src/graphql/GraphQLSchema.ts +0 -886
  88. package/src/graphql/index.ts +0 -2
  89. package/src/graphql/parseGraphqlSchema.ts +0 -85
  90. package/src/graphql/parser.test.ts +0 -203
  91. package/src/graphql/parser.ts +0 -707
  92. package/src/graphql/pointerAndRelationFunction.ts +0 -191
  93. package/src/graphql/resolvers.ts +0 -464
  94. package/src/graphql/tests/aggregation.test.ts +0 -1115
  95. package/src/graphql/tests/e2e.test.ts +0 -590
  96. package/src/graphql/tests/scalars.test.ts +0 -250
  97. package/src/graphql/types.ts +0 -227
  98. package/src/hooks/HookObject.test.ts +0 -122
  99. package/src/hooks/HookObject.ts +0 -165
  100. package/src/hooks/authentication.ts +0 -67
  101. package/src/hooks/createUser.test.ts +0 -77
  102. package/src/hooks/createUser.ts +0 -10
  103. package/src/hooks/defaultFields.test.ts +0 -176
  104. package/src/hooks/defaultFields.ts +0 -32
  105. package/src/hooks/deleteSession.test.ts +0 -181
  106. package/src/hooks/deleteSession.ts +0 -20
  107. package/src/hooks/hashFieldHook.test.ts +0 -152
  108. package/src/hooks/hashFieldHook.ts +0 -89
  109. package/src/hooks/index.test.ts +0 -258
  110. package/src/hooks/index.ts +0 -420
  111. package/src/hooks/permissions.test.ts +0 -412
  112. package/src/hooks/permissions.ts +0 -93
  113. package/src/hooks/protected.test.ts +0 -551
  114. package/src/hooks/protected.ts +0 -74
  115. package/src/hooks/searchableFields.test.ts +0 -147
  116. package/src/hooks/searchableFields.ts +0 -86
  117. package/src/hooks/session.test.ts +0 -134
  118. package/src/hooks/session.ts +0 -76
  119. package/src/hooks/setEmail.test.ts +0 -216
  120. package/src/hooks/setEmail.ts +0 -33
  121. package/src/hooks/setupAcl.test.ts +0 -618
  122. package/src/hooks/setupAcl.ts +0 -25
  123. package/src/hooks/virtualFields.test.ts +0 -228
  124. package/src/hooks/virtualFields.ts +0 -48
  125. package/src/index.ts +0 -9
  126. package/src/schema/Schema.test.ts +0 -482
  127. package/src/schema/Schema.ts +0 -839
  128. package/src/schema/defaultResolvers.ts +0 -93
  129. package/src/schema/index.ts +0 -1
  130. package/src/schema/resolvers/meResolver.test.ts +0 -62
  131. package/src/schema/resolvers/meResolver.ts +0 -10
  132. package/src/schema/resolvers/resetPassword.test.ts +0 -341
  133. package/src/schema/resolvers/resetPassword.ts +0 -63
  134. package/src/schema/resolvers/sendEmail.test.ts +0 -118
  135. package/src/schema/resolvers/sendEmail.ts +0 -21
  136. package/src/schema/resolvers/sendOtpCode.test.ts +0 -141
  137. package/src/schema/resolvers/sendOtpCode.ts +0 -52
  138. package/src/security.test.ts +0 -4136
  139. package/src/server/defaultSessionHandler.test.ts +0 -62
  140. package/src/server/defaultSessionHandler.ts +0 -104
  141. package/src/server/generateCodegen.ts +0 -433
  142. package/src/server/index.test.ts +0 -843
  143. package/src/server/index.ts +0 -336
  144. package/src/server/interface.ts +0 -11
  145. package/src/server/routes/authHandler.ts +0 -171
  146. package/src/server/routes/index.ts +0 -48
  147. package/src/utils/crypto.test.ts +0 -41
  148. package/src/utils/crypto.ts +0 -105
  149. package/src/utils/database.ts +0 -8
  150. package/src/utils/export.ts +0 -12
  151. package/src/utils/helper.ts +0 -204
  152. package/src/utils/index.test.ts +0 -11
  153. package/src/utils/index.ts +0 -196
  154. package/src/utils/preload.ts +0 -8
  155. package/src/utils/testHelper.ts +0 -124
  156. package/tsconfig.json +0 -32
@@ -1,306 +0,0 @@
1
- import { describe, expect, it, mock, spyOn, afterEach } from 'bun:test'
2
- import { signInWithResolver } from './signInWithResolver'
3
- import { Session } from '../Session'
4
- import { SecondaryFactor } from '../interface'
5
-
6
- describe('SignInWith', () => {
7
- const mockOnLogin = mock(() =>
8
- Promise.resolve({
9
- user: {
10
- id: 'id',
11
- },
12
- }),
13
- )
14
- const mockOnSignUp = mock(() =>
15
- Promise.resolve({
16
- authenticationDataToSave: {
17
- id: 'id',
18
- },
19
- }),
20
- )
21
-
22
- const mockCreateObject = mock(() => Promise.resolve({}))
23
- const mockGetObject = mock(() => Promise.resolve({ pendingChallenges: [] }))
24
- const mockUpdateObject = mock(() => Promise.resolve({}))
25
-
26
- const mockOnSendChallenge = mock(() => Promise.resolve())
27
- const mockOnVerifyChallenge = mock(() => Promise.resolve(true))
28
-
29
- const context = {
30
- wabe: {
31
- controllers: {
32
- database: {
33
- getObject: mockGetObject,
34
- updateObject: mockUpdateObject,
35
- },
36
- },
37
- config: {
38
- authentication: {
39
- session: {
40
- cookieSession: true,
41
- },
42
- customAuthenticationMethods: [
43
- {
44
- name: 'emailPassword',
45
- input: {
46
- email: { type: 'Email', required: true },
47
- password: { type: 'String', required: true },
48
- },
49
- provider: {
50
- onSignUp: mockOnSignUp,
51
- onSignIn: mockOnLogin,
52
- },
53
- },
54
- {
55
- name: 'emailOTP',
56
- input: {
57
- email: {
58
- type: 'Email',
59
- required: true,
60
- },
61
- code: {
62
- type: 'String',
63
- required: true,
64
- },
65
- },
66
- provider: {
67
- onSendChallenge: mockOnSendChallenge,
68
- onVerifyChallenge: mockOnVerifyChallenge,
69
- },
70
- },
71
- ],
72
- },
73
- },
74
- },
75
- }
76
-
77
- afterEach(() => {
78
- mockCreateObject.mockClear()
79
- mockGetObject.mockClear()
80
- mockUpdateObject.mockClear()
81
- mockOnLogin.mockClear()
82
- mockOnSignUp.mockClear()
83
- })
84
-
85
- it('should call the secondary factor authentication on signIn', async () => {
86
- mockOnLogin.mockResolvedValueOnce({
87
- user: {
88
- id: 'id',
89
- // @ts-expect-error
90
- email: 'email@test.fr',
91
- secondFA: {
92
- enabled: true,
93
- provider: SecondaryFactor.EmailOTP,
94
- },
95
- },
96
- })
97
-
98
- const res = await signInWithResolver(
99
- {},
100
- {
101
- input: {
102
- authentication: {
103
- emailPassword: {
104
- email: 'email@test.fr',
105
- password: 'password',
106
- },
107
- },
108
- },
109
- },
110
- // @ts-expect-error
111
- context,
112
- )
113
-
114
- expect(mockOnLogin).toHaveBeenCalledTimes(1)
115
- expect(mockOnLogin).toHaveBeenCalledWith({
116
- input: {
117
- email: 'email@test.fr',
118
- password: 'password',
119
- },
120
- context: expect.any(Object),
121
- })
122
-
123
- expect(mockOnSendChallenge).toHaveBeenCalledTimes(1)
124
- expect(mockOnSendChallenge).toHaveBeenCalledWith({
125
- context: expect.any(Object),
126
- user: expect.objectContaining({
127
- email: 'email@test.fr',
128
- }),
129
- })
130
-
131
- expect(res).toEqual({
132
- accessToken: null,
133
- refreshToken: null,
134
- srp: null,
135
- challengeToken: expect.any(String),
136
- user: {
137
- id: 'id',
138
- email: 'email@test.fr',
139
- secondFA: {
140
- enabled: true,
141
- // @ts-expect-error
142
- provider: SecondaryFactor.EmailOTP,
143
- },
144
- },
145
- })
146
- })
147
-
148
- it('should throw an error if no custom authentication configuration is provided', () => {
149
- expect(
150
- signInWithResolver(
151
- {},
152
- {
153
- input: {
154
- authentication: {
155
- emailPassword: {
156
- email: 'email@test.fr',
157
- password: 'password',
158
- },
159
- },
160
- },
161
- },
162
- { wabe: { config: { authentication: undefined } } } as any,
163
- ),
164
- ).rejects.toThrow('No custom authentication methods found')
165
- })
166
-
167
- it('should throw an error if a custom authentication is provided but not in the custom authentication config', () => {
168
- expect(
169
- signInWithResolver(
170
- {},
171
- {
172
- input: {
173
- authentication: {
174
- emailPassword: {
175
- email: 'email@test.fr',
176
- password: 'password',
177
- },
178
- },
179
- },
180
- },
181
- {
182
- wabe: {
183
- config: {
184
- authentication: {
185
- customAuthenticationMethods: [
186
- {
187
- name: 'phonePassword',
188
- input: {
189
- email: {
190
- type: 'Email',
191
- required: true,
192
- },
193
- password: {
194
- type: 'String',
195
- required: true,
196
- },
197
- },
198
- provider: {
199
- onSignUp: mockOnSignUp,
200
- onSignIn: mockOnLogin,
201
- },
202
- },
203
- ],
204
- },
205
- },
206
- },
207
- } as any,
208
- ),
209
- ).rejects.toThrow('No available custom authentication methods found')
210
- })
211
-
212
- it('should signInWith email and password when the user already exist (on cookieSession)', async () => {
213
- const mockCreateSession = spyOn(Session.prototype, 'create').mockResolvedValue({
214
- refreshToken: 'refreshToken',
215
- accessToken: 'accessToken',
216
- csrfToken: 'csrfToken',
217
- } as any)
218
-
219
- const mockSetCookie = mock(() => {})
220
-
221
- const mockResponse = {
222
- setCookie: mockSetCookie,
223
- }
224
-
225
- const res = await signInWithResolver(
226
- {},
227
- {
228
- input: {
229
- authentication: {
230
- emailPassword: {
231
- email: 'email@test.fr',
232
- password: 'password',
233
- },
234
- },
235
- },
236
- },
237
- {
238
- ...context,
239
- response: mockResponse,
240
- } as any,
241
- )
242
-
243
- expect(res).toEqual({
244
- accessToken: 'accessToken',
245
- refreshToken: 'refreshToken',
246
- challengeToken: null,
247
- user: {
248
- id: 'id',
249
- },
250
- srp: undefined,
251
- })
252
- expect(mockOnLogin).toHaveBeenCalledTimes(1)
253
- expect(mockOnLogin).toHaveBeenCalledWith({
254
- input: {
255
- email: 'email@test.fr',
256
- password: 'password',
257
- },
258
- context: expect.any(Object),
259
- })
260
-
261
- expect(mockSetCookie).toHaveBeenCalledTimes(3)
262
- expect(mockSetCookie).toHaveBeenNthCalledWith(1, 'refreshToken', 'refreshToken', {
263
- httpOnly: true,
264
- path: '/',
265
- secure: true,
266
- sameSite: 'Strict',
267
- expires: expect.any(Date),
268
- })
269
-
270
- expect(mockSetCookie).toHaveBeenNthCalledWith(2, 'accessToken', 'accessToken', {
271
- httpOnly: true,
272
- path: '/',
273
- secure: true,
274
- sameSite: 'Strict',
275
- expires: expect.any(Date),
276
- })
277
-
278
- expect(mockSetCookie).toHaveBeenNthCalledWith(3, 'csrfToken', 'csrfToken', {
279
- httpOnly: false,
280
- path: '/',
281
- secure: true,
282
- sameSite: 'Strict',
283
- expires: expect.any(Date),
284
- })
285
-
286
- // @ts-expect-error
287
- const refreshTokenExpiresIn = mockSetCookie.mock.calls[0][2].expires
288
- // @ts-expect-error
289
- const accessTokenExpiresIn = mockSetCookie.mock.calls[1][2].expires
290
-
291
- // - 1000 to avoid flaky
292
- expect(refreshTokenExpiresIn.getTime() - Date.now()).toBeGreaterThanOrEqual(
293
- 1000 * 7 * 24 * 60 * 60 - 1000,
294
- )
295
- expect(accessTokenExpiresIn.getTime() - Date.now()).toBeGreaterThanOrEqual(
296
- 1000 * 15 * 60 - 1000,
297
- )
298
-
299
- expect(mockCreateSession).toHaveBeenCalledTimes(1)
300
- expect(mockCreateSession).toHaveBeenCalledWith('id', expect.anything())
301
-
302
- expect(mockOnSignUp).toHaveBeenCalledTimes(0)
303
-
304
- mockCreateSession.mockRestore()
305
- })
306
- })
@@ -1,106 +0,0 @@
1
- import type { SignInWithInput } from '../../../generated/wabe'
2
- import type { WabeContext } from '../../server/interface'
3
- import type { DevWabeTypes } from '../../utils/helper'
4
- import { getSessionCookieSameSite } from '../cookies'
5
- import { createMfaChallenge } from '../security'
6
- import { Session } from '../Session'
7
- import type { ProviderInterface, SecondaryProviderInterface } from '../interface'
8
- import { getAuthenticationMethod } from '../utils'
9
-
10
- // 0 - Get the authentication method
11
- // 1 - We check if the signIn is possible (call onSign)
12
- // 2 - If secondaryFactor is present, we call the onSendChallenge method of the provider
13
- // 3 - We create session
14
- export const signInWithResolver = async (
15
- _: any,
16
- {
17
- input,
18
- }: {
19
- input: SignInWithInput
20
- },
21
- context: WabeContext<DevWabeTypes>,
22
- ) => {
23
- const { provider, name } = getAuthenticationMethod<DevWabeTypes, ProviderInterface<DevWabeTypes>>(
24
- Object.keys(input.authentication || {}),
25
- context,
26
- )
27
-
28
- const inputOfTheGoodAuthenticationMethod =
29
- // @ts-expect-error
30
- input.authentication[name]
31
-
32
- // 1 - We call the onSignIn method of the provider
33
- const { user, srp } = await provider.onSignIn({
34
- input: inputOfTheGoodAuthenticationMethod,
35
- context,
36
- })
37
-
38
- const userId = user.id
39
-
40
- if (!userId) throw new Error('Authentication failed')
41
-
42
- const secondFAObject = user.secondFA
43
-
44
- // 2 - We call the onSendChallenge method of the provider
45
- if (secondFAObject?.enabled) {
46
- const secondaryProvider = getAuthenticationMethod<
47
- DevWabeTypes,
48
- SecondaryProviderInterface<DevWabeTypes>
49
- >([secondFAObject.provider], context)
50
-
51
- await secondaryProvider.provider.onSendChallenge?.({
52
- context,
53
- // @ts-expect-error
54
- user,
55
- })
56
-
57
- const challengeToken = await createMfaChallenge(context, {
58
- userId,
59
- provider: secondFAObject.provider,
60
- })
61
-
62
- return {
63
- accessToken: null,
64
- refreshToken: null,
65
- user,
66
- challengeToken,
67
- srp: null,
68
- }
69
- }
70
-
71
- const session = new Session<DevWabeTypes>()
72
-
73
- const { refreshToken, accessToken, csrfToken } = await session.create(userId, context)
74
-
75
- if (context.wabe.config.authentication?.session?.cookieSession) {
76
- const accessTokenExpiresAt = session.getAccessTokenExpireAt(context.wabe.config)
77
- const refreshTokenExpiresAt = session.getRefreshTokenExpireAt(context.wabe.config)
78
- const sameSite = getSessionCookieSameSite(context.wabe.config)
79
-
80
- context.response?.setCookie('refreshToken', refreshToken, {
81
- httpOnly: true,
82
- path: '/',
83
- sameSite,
84
- secure: true,
85
- expires: refreshTokenExpiresAt,
86
- })
87
-
88
- context.response?.setCookie('accessToken', accessToken, {
89
- httpOnly: true,
90
- path: '/',
91
- sameSite,
92
- secure: true,
93
- expires: accessTokenExpiresAt,
94
- })
95
-
96
- context.response?.setCookie('csrfToken', csrfToken, {
97
- httpOnly: false, // OWASP specification specify that the csrfToken should not be httpOnly
98
- path: '/',
99
- sameSite,
100
- secure: true,
101
- expires: accessTokenExpiresAt,
102
- })
103
- }
104
-
105
- return { accessToken, refreshToken, user, srp, challengeToken: null }
106
- }
@@ -1,38 +0,0 @@
1
- import { describe, expect, it, mock, spyOn } from 'bun:test'
2
- import { signOutResolver } from './signOutResolver'
3
- import { Session } from '../Session'
4
-
5
- describe('signOut', () => {
6
- const mockDeleteCookie = mock(() => {})
7
-
8
- const context = {
9
- sessionId: 'sessionId',
10
- wabe: {
11
- config: {
12
- authentication: {
13
- session: {
14
- cookieSession: true,
15
- },
16
- },
17
- },
18
- },
19
- response: {
20
- deleteCookie: mockDeleteCookie,
21
- },
22
- } as any
23
-
24
- it('should sign out the current user', async () => {
25
- const spyDeleteSession = spyOn(Session.prototype, 'delete').mockResolvedValue(undefined)
26
-
27
- const res = await signOutResolver(undefined, {}, context)
28
-
29
- expect(res).toBe(true)
30
-
31
- expect(spyDeleteSession).toHaveBeenCalledTimes(1)
32
- expect(spyDeleteSession).toHaveBeenCalledWith(context)
33
-
34
- expect(mockDeleteCookie).toHaveBeenCalledTimes(2)
35
- expect(mockDeleteCookie).toHaveBeenNthCalledWith(1, 'accessToken')
36
- expect(mockDeleteCookie).toHaveBeenNthCalledWith(2, 'refreshToken')
37
- })
38
- })
@@ -1,18 +0,0 @@
1
- import type { WabeContext } from '../../server/interface'
2
- import type { DevWabeTypes } from '../../utils/helper'
3
- import { Session } from '../Session'
4
-
5
- export const signOutResolver = async (_: any, __: any, context: WabeContext<DevWabeTypes>) => {
6
- const session = new Session<DevWabeTypes>()
7
-
8
- // For the moment we only delete the session because we suppose the token
9
- // are used with headers. We will need to delete the cookies in the future.
10
- await session.delete(context)
11
-
12
- if (context.wabe.config.authentication?.session?.cookieSession) {
13
- context.response?.deleteCookie('accessToken')
14
- context.response?.deleteCookie('refreshToken')
15
- }
16
-
17
- return true
18
- }
@@ -1,180 +0,0 @@
1
- import { beforeAll, afterAll, describe, expect, it, beforeEach } from 'bun:test'
2
- import { type DevWabeTypes, getAnonymousClient } from '../../utils/helper'
3
- import type { Wabe } from '../../server'
4
- import { gql } from 'graphql-request'
5
- import { setupTests, closeTests } from '../../utils/testHelper'
6
-
7
- describe('SignUpWith', () => {
8
- let wabe: Wabe<DevWabeTypes>
9
-
10
- beforeAll(async () => {
11
- const setup = await setupTests()
12
- wabe = setup.wabe
13
- })
14
-
15
- beforeEach(async () => {
16
- await wabe.controllers.database.clearDatabase()
17
- })
18
-
19
- afterAll(async () => {
20
- await closeTests(wabe)
21
- })
22
-
23
- it('should throw an error if user already exist with emailPassword', async () => {
24
- const anonymousClient = getAnonymousClient(wabe.config.port)
25
-
26
- await anonymousClient.request<any>(
27
- gql`
28
- mutation signUpWith($input: SignUpWithInput!) {
29
- signUpWith(input: $input) {
30
- id
31
- }
32
- }
33
- `,
34
- {
35
- input: {
36
- authentication: {
37
- emailPassword: {
38
- email: 'test@gmail.com',
39
- password: 'password',
40
- },
41
- },
42
- },
43
- },
44
- )
45
-
46
- expect(
47
- anonymousClient.request<any>(
48
- gql`
49
- mutation signUpWith($input: SignUpWithInput!) {
50
- signUpWith(input: $input) {
51
- id
52
- }
53
- }
54
- `,
55
- {
56
- input: {
57
- authentication: {
58
- emailPassword: {
59
- email: 'test@gmail.com',
60
- password: 'password',
61
- },
62
- },
63
- },
64
- },
65
- ),
66
- ).rejects.toThrow('Not authorized to create user')
67
- })
68
-
69
- it('should throw an error if the signUp is disabled', () => {
70
- if (wabe.config) {
71
- wabe.config.authentication = {
72
- ...wabe.config.authentication,
73
- disableSignUp: true,
74
- }
75
- }
76
- const anonymousClient = getAnonymousClient(wabe.config.port)
77
-
78
- const userSchema = wabe.config.schema?.classes?.find((classItem) => classItem.name === 'User')
79
-
80
- if (!userSchema) throw new Error('Failed to find user schema')
81
-
82
- // @ts-expect-error
83
- userSchema.permissions.create.requireAuthentication = true
84
-
85
- expect(
86
- anonymousClient.request<any>(
87
- gql`
88
- mutation signUpWith($input: SignUpWithInput!) {
89
- signUpWith(input: $input) {
90
- id
91
- }
92
- }
93
- `,
94
- {
95
- input: {
96
- authentication: {
97
- emailPassword: {
98
- email: 'email@test.fr',
99
- password: 'password',
100
- },
101
- },
102
- },
103
- },
104
- ),
105
- ).rejects.toThrow('SignUp is disabled')
106
-
107
- if (wabe.config) {
108
- wabe.config.authentication = {
109
- ...wabe.config.authentication,
110
- disableSignUp: false,
111
- }
112
- }
113
- })
114
-
115
- it('should block the signUpWith if the user creation is blocked for anonymous (the creation is done with root to avoid ACL issues)', () => {
116
- const anonymousClient = getAnonymousClient(wabe.config.port)
117
-
118
- const userSchema = wabe.config.schema?.classes?.find((classItem) => classItem.name === 'User')
119
-
120
- if (!userSchema) throw new Error('Failed to find user schema')
121
-
122
- // @ts-expect-error
123
- userSchema.permissions.create.requireAuthentication = true
124
-
125
- expect(
126
- anonymousClient.request<any>(
127
- gql`
128
- mutation signUpWith($input: SignUpWithInput!) {
129
- signUpWith(input: $input) {
130
- id
131
- }
132
- }
133
- `,
134
- {
135
- input: {
136
- authentication: {
137
- emailPassword: {
138
- email: 'email@test.fr',
139
- password: 'password',
140
- },
141
- },
142
- },
143
- },
144
- ),
145
- ).rejects.toThrow('Permission denied to create class User')
146
-
147
- // @ts-expect-error
148
- userSchema.permissions.create.requireAuthentication = false
149
- })
150
-
151
- it('should signUpWith email and password when the user not exist', async () => {
152
- const anonymousClient = getAnonymousClient(wabe.config.port)
153
-
154
- const res = await anonymousClient.request<any>(
155
- gql`
156
- mutation signUpWith($input: SignUpWithInput!) {
157
- signUpWith(input: $input) {
158
- id
159
- accessToken
160
- refreshToken
161
- }
162
- }
163
- `,
164
- {
165
- input: {
166
- authentication: {
167
- emailPassword: {
168
- email: 'test@gmail.com',
169
- password: 'password',
170
- },
171
- },
172
- },
173
- },
174
- )
175
-
176
- expect(res.signUpWith.id).toEqual(expect.any(String))
177
- expect(res.signUpWith.accessToken).toEqual(expect.any(String))
178
- expect(res.signUpWith.refreshToken).toEqual(expect.any(String))
179
- })
180
- })
@@ -1,68 +0,0 @@
1
- import type { SignUpWithInput } from '../../../generated/wabe'
2
- import type { WabeContext } from '../../server/interface'
3
- import { getSessionCookieSameSite } from '../cookies'
4
- import { Session } from '../Session'
5
-
6
- // 0 - Get the authentication method
7
- // 1 - We check if the signUp is possible (call onSign)
8
- // 2 - We create the user
9
- // 3 - We create session
10
- export const signUpWithResolver = async (
11
- _: any,
12
- {
13
- input,
14
- }: {
15
- input: SignUpWithInput
16
- },
17
- context: WabeContext<any>,
18
- ) => {
19
- if (context.wabe.config.authentication?.disableSignUp) throw new Error('SignUp is disabled')
20
-
21
- // Create object call the provider signUp
22
- const res = await context.wabe.controllers.database.createObject({
23
- className: 'User',
24
- data: {
25
- authentication: input.authentication,
26
- },
27
- context,
28
- select: { id: true },
29
- })
30
-
31
- const createdUserId = res?.id
32
-
33
- const session = new Session<any>()
34
-
35
- if (!createdUserId) throw new Error('User not created')
36
-
37
- const { accessToken, refreshToken, csrfToken } = await session.create(createdUserId, context)
38
-
39
- if (context.wabe.config.authentication?.session?.cookieSession) {
40
- const sameSite = getSessionCookieSameSite(context.wabe.config)
41
-
42
- context.response?.setCookie('refreshToken', refreshToken, {
43
- httpOnly: true,
44
- path: '/',
45
- sameSite,
46
- secure: true,
47
- expires: session.getRefreshTokenExpireAt(context.wabe.config),
48
- })
49
-
50
- context.response?.setCookie('accessToken', accessToken, {
51
- httpOnly: true,
52
- path: '/',
53
- sameSite,
54
- secure: true,
55
- expires: session.getAccessTokenExpireAt(context.wabe.config),
56
- })
57
-
58
- context.response?.setCookie('csrfToken', csrfToken, {
59
- httpOnly: false, // OWASP specification specify that the csrfToken should not be httpOnly
60
- path: '/',
61
- sameSite,
62
- secure: true,
63
- expires: session.getAccessTokenExpireAt(context.wabe.config),
64
- })
65
- }
66
-
67
- return { accessToken, refreshToken, id: createdUserId }
68
- }