@flowerforce/flowerbase 1.2.1-beta.9 → 1.3.0

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 (82) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/README.md +9 -3
  3. package/dist/auth/controller.d.ts.map +1 -1
  4. package/dist/auth/controller.js +2 -2
  5. package/dist/auth/plugins/jwt.js +3 -3
  6. package/dist/auth/providers/anon-user/controller.d.ts +8 -0
  7. package/dist/auth/providers/anon-user/controller.d.ts.map +1 -0
  8. package/dist/auth/providers/anon-user/controller.js +90 -0
  9. package/dist/auth/providers/anon-user/dtos.d.ts +10 -0
  10. package/dist/auth/providers/anon-user/dtos.d.ts.map +1 -0
  11. package/dist/auth/providers/anon-user/dtos.js +2 -0
  12. package/dist/auth/providers/custom-function/controller.d.ts.map +1 -1
  13. package/dist/auth/providers/custom-function/controller.js +32 -35
  14. package/dist/auth/providers/custom-function/dtos.d.ts +4 -1
  15. package/dist/auth/providers/custom-function/dtos.d.ts.map +1 -1
  16. package/dist/auth/providers/local-userpass/controller.d.ts.map +1 -1
  17. package/dist/auth/providers/local-userpass/controller.js +41 -33
  18. package/dist/auth/providers/local-userpass/dtos.d.ts +6 -0
  19. package/dist/auth/providers/local-userpass/dtos.d.ts.map +1 -1
  20. package/dist/auth/utils.d.ts +24 -1
  21. package/dist/auth/utils.d.ts.map +1 -1
  22. package/dist/auth/utils.js +13 -1
  23. package/dist/constants.d.ts +4 -0
  24. package/dist/constants.d.ts.map +1 -1
  25. package/dist/constants.js +7 -3
  26. package/dist/features/functions/controller.d.ts.map +1 -1
  27. package/dist/features/functions/controller.js +27 -11
  28. package/dist/features/functions/utils.d.ts +1 -1
  29. package/dist/features/triggers/index.d.ts.map +1 -1
  30. package/dist/features/triggers/index.js +49 -7
  31. package/dist/features/triggers/interface.d.ts +1 -0
  32. package/dist/features/triggers/interface.d.ts.map +1 -1
  33. package/dist/features/triggers/utils.d.ts.map +1 -1
  34. package/dist/features/triggers/utils.js +67 -26
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +18 -12
  37. package/dist/services/mongodb-atlas/index.d.ts.map +1 -1
  38. package/dist/services/mongodb-atlas/index.js +2 -2
  39. package/dist/services/mongodb-atlas/model.d.ts +2 -2
  40. package/dist/services/mongodb-atlas/model.d.ts.map +1 -1
  41. package/dist/services/mongodb-atlas/utils.d.ts.map +1 -1
  42. package/dist/services/mongodb-atlas/utils.js +3 -1
  43. package/dist/shared/handleUserRegistration.d.ts.map +1 -1
  44. package/dist/shared/handleUserRegistration.js +66 -1
  45. package/dist/shared/models/handleUserRegistration.model.d.ts +2 -1
  46. package/dist/shared/models/handleUserRegistration.model.d.ts.map +1 -1
  47. package/dist/shared/models/handleUserRegistration.model.js +1 -0
  48. package/dist/utils/context/helpers.d.ts +5 -5
  49. package/dist/utils/context/helpers.d.ts.map +1 -1
  50. package/dist/utils/context/index.d.ts.map +1 -1
  51. package/dist/utils/context/index.js +12 -14
  52. package/dist/utils/initializer/exposeRoutes.js +1 -1
  53. package/dist/utils/initializer/registerPlugins.d.ts.map +1 -1
  54. package/dist/utils/initializer/registerPlugins.js +12 -4
  55. package/dist/utils/rules-matcher/utils.d.ts.map +1 -1
  56. package/dist/utils/rules-matcher/utils.js +3 -0
  57. package/package.json +1 -1
  58. package/src/auth/controller.ts +5 -2
  59. package/src/auth/plugins/jwt.ts +5 -5
  60. package/src/auth/providers/anon-user/controller.ts +91 -0
  61. package/src/auth/providers/anon-user/dtos.ts +10 -0
  62. package/src/auth/providers/custom-function/controller.ts +34 -39
  63. package/src/auth/providers/custom-function/dtos.ts +5 -1
  64. package/src/auth/providers/local-userpass/controller.ts +56 -43
  65. package/src/auth/providers/local-userpass/dtos.ts +7 -0
  66. package/src/auth/utils.ts +22 -1
  67. package/src/constants.ts +5 -1
  68. package/src/features/functions/controller.ts +27 -11
  69. package/src/features/triggers/index.ts +44 -1
  70. package/src/features/triggers/interface.ts +1 -0
  71. package/src/features/triggers/utils.ts +89 -37
  72. package/src/index.ts +18 -12
  73. package/src/services/mongodb-atlas/index.ts +654 -654
  74. package/src/services/mongodb-atlas/model.ts +2 -2
  75. package/src/services/mongodb-atlas/utils.ts +3 -0
  76. package/src/shared/handleUserRegistration.ts +83 -2
  77. package/src/shared/models/handleUserRegistration.model.ts +2 -1
  78. package/src/utils/__tests__/registerPlugins.test.ts +5 -1
  79. package/src/utils/context/index.ts +32 -36
  80. package/src/utils/initializer/exposeRoutes.ts +1 -1
  81. package/src/utils/initializer/registerPlugins.ts +8 -0
  82. package/src/utils/rules-matcher/utils.ts +3 -0
@@ -1,6 +1,6 @@
1
1
  import { FastifyInstance } from 'fastify'
2
+ import { ObjectId } from 'mongodb'
2
3
  import { AUTH_CONFIG, DB_NAME, DEFAULT_CONFIG } from '../../../constants'
3
- import { services } from '../../../services'
4
4
  import handleUserRegistration from '../../../shared/handleUserRegistration'
5
5
  import { PROVIDER } from '../../../shared/models/handleUserRegistration.model'
6
6
  import { StateManager } from '../../../state'
@@ -10,6 +10,7 @@ import {
10
10
  AUTH_ENDPOINTS,
11
11
  AUTH_ERRORS,
12
12
  CONFIRM_RESET_SCHEMA,
13
+ CONFIRM_USER_SCHEMA,
13
14
  LOGIN_SCHEMA,
14
15
  REGISTRATION_SCHEMA,
15
16
  RESET_CALL_SCHEMA,
@@ -17,6 +18,7 @@ import {
17
18
  } from '../../utils'
18
19
  import {
19
20
  ConfirmResetPasswordDto,
21
+ ConfirmUserDto,
20
22
  LoginDto,
21
23
  RegistrationDto,
22
24
  ResetPasswordCallDto,
@@ -39,20 +41,14 @@ const isRateLimited = (key: string, maxAttempts: number, windowMs: number) => {
39
41
  * @param {FastifyInstance} app - The Fastify instance.
40
42
  */
41
43
  export async function localUserPassController(app: FastifyInstance) {
42
- const functionsList = StateManager.select('functions')
43
-
44
- const {
45
- authCollection,
46
- userCollection,
47
- user_id_field,
48
- on_user_creation_function_name
49
- } = AUTH_CONFIG
44
+ const { authCollection, userCollection, user_id_field } = AUTH_CONFIG
50
45
  const { resetPasswordCollection } = AUTH_CONFIG
51
46
  const { refreshTokensCollection } = AUTH_CONFIG
52
47
  const db = app.mongo.client.db(DB_NAME)
53
48
  const resetPasswordTtlSeconds = DEFAULT_CONFIG.RESET_PASSWORD_TTL_SECONDS
54
49
  const rateLimitWindowMs = DEFAULT_CONFIG.AUTH_RATE_LIMIT_WINDOW_MS
55
50
  const loginMaxAttempts = DEFAULT_CONFIG.AUTH_LOGIN_MAX_ATTEMPTS
51
+ const registerMaxAttempts = DEFAULT_CONFIG.AUTH_REGISTER_MAX_ATTEMPTS
56
52
  const resetMaxAttempts = DEFAULT_CONFIG.AUTH_RESET_MAX_ATTEMPTS
57
53
  const refreshTokenTtlMs = DEFAULT_CONFIG.REFRESH_TOKEN_TTL_DAYS * 24 * 60 * 60 * 1000
58
54
 
@@ -136,6 +132,11 @@ export async function localUserPassController(app: FastifyInstance) {
136
132
  schema: REGISTRATION_SCHEMA
137
133
  },
138
134
  async (req, res) => {
135
+ const key = `register:${req.ip}`
136
+ if (isRateLimited(key, registerMaxAttempts, rateLimitWindowMs)) {
137
+ res.status(429).send({ message: 'Too many requests' })
138
+ return
139
+ }
139
140
 
140
141
  const result = await handleUserRegistration(app, { run_as_system: true, provider: PROVIDER.LOCAL_USERPASS })({ email: req.body.email.toLowerCase(), password: req.body.password })
141
142
 
@@ -149,6 +150,50 @@ export async function localUserPassController(app: FastifyInstance) {
149
150
  }
150
151
  )
151
152
 
153
+ /**
154
+ * Endpoint for confirming a user registration.
155
+ *
156
+ * @route {POST} /confirm
157
+ * @param {ConfirmUserDto} req - The request object with confirmation data.
158
+ * @returns {Promise<Object>} A promise resolving with confirmation status.
159
+ */
160
+ app.post<ConfirmUserDto>(
161
+ AUTH_ENDPOINTS.CONFIRM,
162
+ {
163
+ schema: CONFIRM_USER_SCHEMA
164
+ },
165
+ async (req, res) => {
166
+ const key = `confirm:${req.ip}`
167
+ if (isRateLimited(key, resetMaxAttempts, rateLimitWindowMs)) {
168
+ res.status(429).send({ message: 'Too many requests' })
169
+ return
170
+ }
171
+
172
+ const existing = await db.collection(authCollection!).findOne({
173
+ confirmationToken: req.body.token,
174
+ confirmationTokenId: req.body.tokenId
175
+ }) as { _id: ObjectId; status?: string } | null
176
+
177
+ if (!existing) {
178
+ res.status(500)
179
+ throw new Error(AUTH_ERRORS.INVALID_TOKEN)
180
+ }
181
+
182
+ if (existing.status !== 'confirmed') {
183
+ await db.collection(authCollection!).updateOne(
184
+ { _id: existing._id },
185
+ {
186
+ $set: { status: 'confirmed' },
187
+ $unset: { confirmationToken: '', confirmationTokenId: '' }
188
+ }
189
+ )
190
+ }
191
+
192
+ res.status(200)
193
+ return { status: 'confirmed' }
194
+ }
195
+ )
196
+
152
197
  /**
153
198
  * Endpoint for user login.
154
199
  *
@@ -199,40 +244,8 @@ export async function localUserPassController(app: FastifyInstance) {
199
244
  id: authUser._id.toString()
200
245
  }
201
246
 
202
- if (authUser && authUser.status === 'pending') {
203
- try {
204
- await db?.collection(authCollection!).updateOne(
205
- { _id: authUser._id },
206
- {
207
- $set: {
208
- status: 'confirmed'
209
- }
210
- }
211
- )
212
- } catch (error) {
213
- console.log('>>> 🚀 ~ localUserPassController ~ error:', error)
214
- }
215
- }
216
-
217
- if (
218
- authUser &&
219
- authUser.status === 'pending' &&
220
- on_user_creation_function_name &&
221
- functionsList[on_user_creation_function_name]
222
- ) {
223
- try {
224
- await GenerateContext({
225
- args: [userWithCustomData],
226
- app,
227
- rules: {},
228
- user: userWithCustomData,
229
- currentFunction: functionsList[on_user_creation_function_name],
230
- functionsList,
231
- services
232
- })
233
- } catch (error) {
234
- console.log('localUserPassController - /login - GenerateContext - CATCH:', error)
235
- }
247
+ if (authUser && authUser.status !== 'confirmed') {
248
+ throw new Error(AUTH_ERRORS.USER_NOT_CONFIRMED)
236
249
  }
237
250
 
238
251
  const refreshToken = this.createRefreshToken(userWithCustomData)
@@ -49,3 +49,10 @@ export interface ConfirmResetPasswordDto {
49
49
  password: string
50
50
  }
51
51
  }
52
+
53
+ export interface ConfirmUserDto {
54
+ Body: {
55
+ token: string
56
+ tokenId: string
57
+ }
58
+ }
package/src/auth/utils.ts CHANGED
@@ -64,6 +64,17 @@ export const CONFIRM_RESET_SCHEMA = {
64
64
  }
65
65
  }
66
66
 
67
+ export const CONFIRM_USER_SCHEMA = {
68
+ body: {
69
+ type: 'object',
70
+ properties: {
71
+ token: { type: 'string' },
72
+ tokenId: { type: 'string' }
73
+ },
74
+ required: ['token', 'tokenId']
75
+ }
76
+ }
77
+
67
78
  export const RESET_SCHEMA = RESET_SEND_SCHEMA
68
79
 
69
80
  export const REGISTRATION_SCHEMA = {
@@ -85,6 +96,7 @@ export const REGISTRATION_SCHEMA = {
85
96
  export enum AUTH_ENDPOINTS {
86
97
  LOGIN = '/login',
87
98
  REGISTRATION = '/register',
99
+ CONFIRM = '/confirm',
88
100
  PROFILE = '/profile',
89
101
  SESSION = '/session',
90
102
  RESET = '/reset/send',
@@ -97,7 +109,8 @@ export enum AUTH_ERRORS {
97
109
  INVALID_CREDENTIALS = 'Invalid credentials',
98
110
  INVALID_TOKEN = 'Invalid refresh token provided',
99
111
  INVALID_RESET_PARAMS = 'Invalid token or tokenId provided',
100
- MISSING_RESET_FUNCTION = 'Missing reset function'
112
+ MISSING_RESET_FUNCTION = 'Missing reset function',
113
+ USER_NOT_CONFIRMED = 'User not confirmed'
101
114
  }
102
115
 
103
116
  export interface AuthConfig {
@@ -105,6 +118,7 @@ export interface AuthConfig {
105
118
  'api-key': ApiKey
106
119
  'local-userpass': LocalUserpass
107
120
  'custom-function': CustomFunction
121
+ 'anon-user'?: AnonUser
108
122
  }
109
123
 
110
124
  interface ApiKey {
@@ -128,8 +142,15 @@ interface CustomFunction {
128
142
  }
129
143
  }
130
144
 
145
+ export interface AnonUser {
146
+ name: "anon-user"
147
+ type: "anon-user"
148
+ disabled: boolean
149
+ }
150
+
131
151
  export interface Config {
132
152
  autoConfirm: boolean
153
+ confirmationFunctionName?: string
133
154
  resetFunctionName: string
134
155
  resetPasswordUrl: string
135
156
  runConfirmationFunction: boolean
package/src/constants.ts CHANGED
@@ -20,8 +20,10 @@ export const DEFAULT_CONFIG = {
20
20
  RESET_PASSWORD_TTL_SECONDS: Number(process.env.RESET_PASSWORD_TTL_SECONDS) || 3600,
21
21
  AUTH_RATE_LIMIT_WINDOW_MS: Number(process.env.AUTH_RATE_LIMIT_WINDOW_MS) || 15 * 60 * 1000,
22
22
  AUTH_LOGIN_MAX_ATTEMPTS: Number(process.env.AUTH_LOGIN_MAX_ATTEMPTS) || 10,
23
+ AUTH_REGISTER_MAX_ATTEMPTS: Number(process.env.AUTH_REGISTER_MAX_ATTEMPTS) || 5,
23
24
  AUTH_RESET_MAX_ATTEMPTS: Number(process.env.AUTH_RESET_MAX_ATTEMPTS) || 5,
24
25
  REFRESH_TOKEN_TTL_DAYS: Number(process.env.REFRESH_TOKEN_TTL_DAYS) || 60,
26
+ ANON_USER_TTL_SECONDS: Number(process.env.ANON_USER_TTL_SECONDS) || 3 * 60 * 60,
25
27
  SWAGGER_UI_USER: process.env.SWAGGER_UI_USER || '',
26
28
  SWAGGER_UI_PASSWORD: process.env.SWAGGER_UI_PASSWORD || '',
27
29
  CORS_OPTIONS: {
@@ -40,10 +42,12 @@ export const AUTH_CONFIG = {
40
42
  resetPasswordCollection: 'reset_password_requests',
41
43
  refreshTokensCollection: 'auth_refresh_tokens',
42
44
  resetPasswordConfig: configuration['local-userpass']?.config,
45
+ localUserpassConfig: configuration['local-userpass']?.config,
43
46
  user_id_field,
44
47
  on_user_creation_function_name,
45
48
  providers: {
46
- "custom-function": configuration['custom-function']?.config
49
+ "custom-function": configuration['custom-function']?.config,
50
+ "anon-user": configuration['anon-user']
47
51
  }
48
52
  }
49
53
 
@@ -34,6 +34,13 @@ const logFunctionCall = (method: string, user: Record<string, any> | undefined,
34
34
  console.log('[functions-debug]', method, user ? { id: user.id, role: user.role, email: user.email } : 'no-user', args)
35
35
  }
36
36
 
37
+ const formatFunctionExecutionError = (error: unknown) => {
38
+ const err = error as { message?: string; name?: string }
39
+ const message = typeof err?.message === 'string' ? err.message : String(error)
40
+ const name = typeof err?.name === 'string' ? err.name : 'Error'
41
+ return JSON.stringify({ message, name })
42
+ }
43
+
37
44
  /**
38
45
  * > Creates a pre handler for every query
39
46
  * @param app -> the fastify instance
@@ -105,17 +112,26 @@ export const functionsController: FunctionController = async (
105
112
  }
106
113
 
107
114
  logFunctionCall(`function:${method}`, user, args)
108
- const result = await GenerateContext({
109
- args: req.body.arguments,
110
- app,
111
- rules,
112
- user: { ...user, _id: new ObjectId(user.id) },
113
- currentFunction,
114
- functionsList,
115
- services
116
- })
117
- res.type('application/json')
118
- return JSON.stringify(result)
115
+ try {
116
+ const result = await GenerateContext({
117
+ args: req.body.arguments,
118
+ app,
119
+ rules,
120
+ user: { ...user, _id: new ObjectId(user.id) },
121
+ currentFunction,
122
+ functionsList,
123
+ services
124
+ })
125
+ res.type('application/json')
126
+ return JSON.stringify(result)
127
+ } catch (error) {
128
+ res.status(500)
129
+ res.type('application/json')
130
+ return JSON.stringify({
131
+ error: formatFunctionExecutionError(error),
132
+ error_code: 'FunctionExecutionError'
133
+ })
134
+ }
119
135
  })
120
136
  app.get<{
121
137
  Querystring: FunctionCallBase64Dto
@@ -1,3 +1,4 @@
1
+ import { AUTH_CONFIG, DB_NAME } from '../../constants'
1
2
  import { services } from '../../services'
2
3
  import { Function, Functions } from '../functions/interface'
3
4
  import { ActivateTriggersParams } from './dtos'
@@ -17,7 +18,49 @@ export const activateTriggers = async ({
17
18
  }: ActivateTriggersParams) => {
18
19
  console.log('START ACTIVATION TRIGGERS')
19
20
  try {
20
- for await (const trigger of triggersList) {
21
+ const triggersToActivate = [...triggersList]
22
+ if (AUTH_CONFIG.on_user_creation_function_name) {
23
+ const alreadyDeclared = triggersToActivate.some(
24
+ (trigger) =>
25
+ trigger.content.type === 'AUTHENTICATION' &&
26
+ trigger.content.event_processors?.FUNCTION?.config?.function_name ===
27
+ AUTH_CONFIG.on_user_creation_function_name
28
+ )
29
+ if (!alreadyDeclared) {
30
+ triggersToActivate.push({
31
+ fileName: '__auto_on_user_creation_trigger__.json',
32
+ content: {
33
+ name: 'onUserCreation',
34
+ type: 'AUTHENTICATION',
35
+ disabled: false,
36
+ config: {
37
+ isAutoTrigger: true,
38
+ collection: AUTH_CONFIG.authCollection ?? 'auth_users',
39
+ database: DB_NAME,
40
+ full_document: true,
41
+ full_document_before_change: false,
42
+ match: {},
43
+ operation_types: ['insert', 'update', 'replace'],
44
+ project: {},
45
+ service_name: 'mongodb-atlas',
46
+ skip_catchup_events: false,
47
+ tolerate_resume_errors: false,
48
+ unordered: false,
49
+ schedule: ''
50
+ },
51
+ event_processors: {
52
+ FUNCTION: {
53
+ config: {
54
+ function_name: AUTH_CONFIG.on_user_creation_function_name
55
+ }
56
+ }
57
+ }
58
+ }
59
+ })
60
+ }
61
+ }
62
+
63
+ for await (const trigger of triggersToActivate) {
21
64
  const { content } = trigger
22
65
  const { type, config, event_processors } = content
23
66
 
@@ -21,6 +21,7 @@ type Config = {
21
21
  database: string
22
22
  full_document: boolean
23
23
  full_document_before_change: boolean
24
+ isAutoTrigger?: boolean
24
25
  match: Record<string, unknown>
25
26
  operation_types: string[]
26
27
  project: Record<string, unknown>
@@ -110,55 +110,107 @@ const handleAuthenticationTrigger = async ({
110
110
  services,
111
111
  app
112
112
  }: HandlerParams) => {
113
- const { database } = config
113
+ const { database, isAutoTrigger } = config
114
+ const authCollection = AUTH_CONFIG.authCollection ?? 'auth_users'
115
+ const collection = app.mongo.client.db(database || DB_NAME).collection(authCollection)
114
116
  const pipeline = [
115
117
  {
116
118
  $match: {
117
- operationType: { $in: ['insert'] }
119
+ operationType: { $in: ['insert', 'update', 'replace'] }
118
120
  }
119
121
  }
120
122
  ]
121
- const changeStream = app.mongo.client
122
- .db(database || DB_NAME)
123
- .collection(AUTH_CONFIG.authCollection)
124
- .watch(pipeline, {
125
- fullDocument: 'whenAvailable'
126
- })
123
+ const changeStream = collection.watch(pipeline, {
124
+ fullDocument: 'whenAvailable'
125
+ })
127
126
  changeStream.on('error', (error) => {
128
127
  if (shouldIgnoreStreamError(error)) return
129
128
  console.error('Authentication trigger change stream error', error)
130
129
  })
131
130
  changeStream.on('change', async function (change) {
132
- const document = change['fullDocument' as keyof typeof change] as Record<
133
- string,
134
- string
135
- > //TODO -> define user type
136
-
137
- if (document) {
138
- delete document.password
139
-
140
- const currentUser = { ...document }
141
- delete currentUser.password
142
- await GenerateContext({
143
- args: [{
144
- user: {
145
- ...currentUser,
146
- id: currentUser._id.toString(),
147
- data: {
148
- _id: currentUser._id.toString(),
149
- email: currentUser.email
150
- }
151
- }
152
- }],
153
- app,
154
- rules: StateManager.select("rules"),
155
- user: {}, // TODO from currentUser ??
156
- currentFunction: triggerHandler,
157
- functionsList,
158
- services,
159
- runAsSystem: true
160
- })
131
+ const operationType = change['operationType' as keyof typeof change] as string | undefined
132
+ const documentKey = change['documentKey' as keyof typeof change] as
133
+ | { _id?: unknown }
134
+ | undefined
135
+ const fullDocument = change['fullDocument' as keyof typeof change] as
136
+ | Record<string, unknown>
137
+ | null
138
+ if (!documentKey?._id) {
139
+ return
161
140
  }
141
+
142
+ const updateDescription = change[
143
+ 'updateDescription' as keyof typeof change
144
+ ] as { updatedFields?: Record<string, unknown> } | undefined
145
+ const updatedStatus = updateDescription?.updatedFields?.status
146
+ let confirmedCandidate = false
147
+ let confirmedDocument =
148
+ fullDocument as Record<string, unknown> | null
149
+
150
+ if (operationType === 'update') {
151
+ if (updatedStatus === 'confirmed') {
152
+ confirmedCandidate = true
153
+ } else if (updatedStatus === undefined) {
154
+ const fetched = await collection.findOne({
155
+ _id: documentKey._id
156
+ }) as Record<string, unknown> | null
157
+ confirmedDocument = fetched ?? confirmedDocument
158
+ confirmedCandidate = (confirmedDocument as { status?: string } | null)?.status === 'confirmed'
159
+ }
160
+ } else {
161
+ confirmedCandidate = (confirmedDocument as { status?: string } | null)?.status === 'confirmed'
162
+ }
163
+
164
+ if (!confirmedCandidate) {
165
+ return
166
+ }
167
+
168
+ const updateResult = await collection.findOneAndUpdate(
169
+ {
170
+ _id: documentKey._id,
171
+ status: 'confirmed',
172
+ on_user_creation_triggered_at: { $exists: false }
173
+ },
174
+ {
175
+ $set: {
176
+ on_user_creation_triggered_at: new Date()
177
+ }
178
+ },
179
+ {
180
+ returnDocument: 'after'
181
+ }
182
+ )
183
+
184
+ const document =
185
+ (updateResult?.value as Record<string, unknown> | null) ?? confirmedDocument
186
+ if (!document) {
187
+ return
188
+ }
189
+
190
+ delete (document as { password?: unknown }).password
191
+
192
+ const currentUser = { ...document }
193
+ delete (currentUser as { password?: unknown }).password
194
+
195
+ const userData = {
196
+ ...currentUser,
197
+ id: (currentUser as { _id: { toString: () => string } })._id.toString(),
198
+ data: {
199
+ _id: (currentUser as { _id: { toString: () => string } })._id.toString(),
200
+ email: (currentUser as { email?: string }).email
201
+ }
202
+ }
203
+ // TODO change va ripulito
204
+ await GenerateContext({
205
+ args: isAutoTrigger ? [userData] : [{ user: userData /*, ...change */ }],
206
+ app,
207
+ rules: StateManager.select("rules"),
208
+ user: {}, // TODO from currentUser ??
209
+ currentFunction: triggerHandler,
210
+ functionsList,
211
+ services,
212
+ runAsSystem: true
213
+ })
162
214
  })
163
215
  registerOnClose(
164
216
  app,
package/src/index.ts CHANGED
@@ -58,19 +58,25 @@ export async function initialize({
58
58
  logger: !!DEFAULT_CONFIG.ENABLE_LOGGER
59
59
  })
60
60
 
61
- console.log("BASE PATH", resolvedBasePath)
61
+ const isTest = process.env.NODE_ENV === 'test' || process.env.JEST_WORKER_ID !== undefined
62
+ const logInfo = (...args: unknown[]) => {
63
+ if (!isTest) {
64
+ console.log(...args)
65
+ }
66
+ }
62
67
 
63
- console.log("CURRENT PORT", port)
64
- console.log("CURRENT HOST", host)
68
+ logInfo("BASE PATH", resolvedBasePath)
69
+ logInfo("CURRENT PORT", port)
70
+ logInfo("CURRENT HOST", host)
65
71
 
66
72
  const functionsList = await loadFunctions(resolvedBasePath)
67
- console.log("Functions LOADED")
73
+ logInfo("Functions LOADED")
68
74
  const triggersList = await loadTriggers(resolvedBasePath)
69
- console.log("Triggers LOADED")
75
+ logInfo("Triggers LOADED")
70
76
  const endpointsList = await loadEndpoints(resolvedBasePath)
71
- console.log("Endpoints LOADED")
77
+ logInfo("Endpoints LOADED")
72
78
  const rulesList = await loadRules(resolvedBasePath)
73
- console.log("Rules LOADED")
79
+ logInfo("Rules LOADED")
74
80
 
75
81
  const stateConfig = {
76
82
  functions: functionsList,
@@ -137,15 +143,15 @@ export async function initialize({
137
143
  corsConfig
138
144
  })
139
145
 
140
- console.log('Plugins registration COMPLETED')
146
+ logInfo('Plugins registration COMPLETED')
141
147
  await exposeRoutes(fastify)
142
- console.log('APP Routes registration COMPLETED')
148
+ logInfo('APP Routes registration COMPLETED')
143
149
  await registerFunctions({ app: fastify, functionsList, rulesList })
144
- console.log('Functions registration COMPLETED')
150
+ logInfo('Functions registration COMPLETED')
145
151
  await generateEndpoints({ app: fastify, functionsList, endpointsList, rulesList })
146
- console.log('HTTP Endpoints registration COMPLETED')
152
+ logInfo('HTTP Endpoints registration COMPLETED')
147
153
  fastify.ready(() => {
148
- console.log("FASTIFY IS READY")
154
+ logInfo("FASTIFY IS READY")
149
155
  if (triggersList?.length > 0) activateTriggers({ fastify, triggersList, functionsList })
150
156
  })
151
157
  await fastify.listen({ port, host })