@flowerforce/flowerbase 1.7.5 → 1.7.6-beta.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.
- package/dist/auth/controller.d.ts.map +1 -1
- package/dist/auth/controller.js +11 -10
- package/dist/auth/plugins/jwt.js +1 -1
- package/dist/auth/providers/anon-user/controller.js +1 -1
- package/dist/auth/providers/custom-function/controller.d.ts.map +1 -1
- package/dist/auth/providers/custom-function/controller.js +36 -10
- package/dist/auth/providers/local-userpass/controller.d.ts.map +1 -1
- package/dist/auth/providers/local-userpass/controller.js +15 -14
- package/dist/auth/utils.d.ts +1 -0
- package/dist/auth/utils.d.ts.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +4 -3
- package/dist/features/triggers/index.js +1 -1
- package/dist/features/triggers/utils.d.ts.map +1 -1
- package/dist/features/triggers/utils.js +38 -30
- package/dist/monitoring/routes/users.d.ts.map +1 -1
- package/dist/monitoring/routes/users.js +7 -6
- package/dist/monitoring/utils.d.ts.map +1 -1
- package/dist/monitoring/utils.js +5 -4
- package/dist/services/api/index.d.ts +4 -0
- package/dist/services/api/index.d.ts.map +1 -1
- package/dist/services/api/utils.d.ts +1 -0
- package/dist/services/api/utils.d.ts.map +1 -1
- package/dist/services/index.d.ts +4 -0
- package/dist/services/index.d.ts.map +1 -1
- package/dist/shared/handleUserDeletion.js +1 -1
- package/dist/shared/handleUserRegistration.js +2 -2
- package/dist/utils/context/helpers.d.ts +12 -0
- package/dist/utils/context/helpers.d.ts.map +1 -1
- package/dist/utils/initializer/exposeRoutes.js +1 -1
- package/dist/utils/rules-matcher/interface.d.ts +5 -1
- package/dist/utils/rules-matcher/interface.d.ts.map +1 -1
- package/dist/utils/rules-matcher/interface.js +2 -0
- package/dist/utils/rules-matcher/utils.d.ts.map +1 -1
- package/dist/utils/rules-matcher/utils.js +51 -16
- package/package.json +1 -1
- package/src/auth/__tests__/controller.test.ts +1 -0
- package/src/auth/controller.ts +12 -11
- package/src/auth/plugins/jwt.ts +2 -2
- package/src/auth/providers/anon-user/__tests__/controller.test.ts +1 -0
- package/src/auth/providers/anon-user/controller.ts +2 -2
- package/src/auth/providers/custom-function/controller.ts +39 -12
- package/src/auth/providers/local-userpass/controller.ts +16 -15
- package/src/auth/utils.ts +1 -0
- package/src/constants.ts +3 -2
- package/src/features/triggers/__tests__/index.test.ts +1 -0
- package/src/features/triggers/index.ts +2 -2
- package/src/features/triggers/utils.ts +42 -31
- package/src/monitoring/routes/users.ts +8 -7
- package/src/monitoring/ui.css +5 -1
- package/src/monitoring/ui.events.js +2 -2
- package/src/monitoring/ui.shared.js +2 -1
- package/src/monitoring/utils.ts +6 -5
- package/src/shared/handleUserDeletion.ts +2 -2
- package/src/shared/handleUserRegistration.ts +3 -3
- package/src/utils/__tests__/operators.test.ts +24 -0
- package/src/utils/__tests__/rule.test.ts +39 -0
- package/src/utils/__tests__/rulesMatcherInterfaces.test.ts +2 -0
- package/src/utils/initializer/exposeRoutes.ts +2 -2
- package/src/utils/rules-matcher/interface.ts +5 -1
- package/src/utils/rules-matcher/utils.ts +78 -32
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FastifyInstance } from 'fastify'
|
|
2
|
-
import {
|
|
2
|
+
import { ObjectId } from 'mongodb'
|
|
3
|
+
import { AUTH_CONFIG, AUTH_DB_NAME, DB_NAME, DEFAULT_CONFIG } from '../../../constants'
|
|
3
4
|
import { StateManager } from '../../../state'
|
|
4
5
|
import { GenerateContext } from '../../../utils/context'
|
|
5
6
|
import { hashToken } from '../../../utils/crypto'
|
|
@@ -16,7 +17,8 @@ export async function customFunctionController(app: FastifyInstance) {
|
|
|
16
17
|
|
|
17
18
|
const functionsList = StateManager.select('functions')
|
|
18
19
|
const services = StateManager.select('services')
|
|
19
|
-
const
|
|
20
|
+
const authDb = app.mongo.client.db(AUTH_DB_NAME)
|
|
21
|
+
const customUserDb = app.mongo.client.db(DB_NAME)
|
|
20
22
|
const { authCollection, refreshTokensCollection, userCollection, user_id_field } = AUTH_CONFIG
|
|
21
23
|
const refreshTokenTtlMs = DEFAULT_CONFIG.REFRESH_TOKEN_TTL_DAYS * 24 * 60 * 60 * 1000
|
|
22
24
|
|
|
@@ -30,7 +32,10 @@ export async function customFunctionController(app: FastifyInstance) {
|
|
|
30
32
|
app.post<LoginDto>(
|
|
31
33
|
AUTH_ENDPOINTS.LOGIN,
|
|
32
34
|
{
|
|
33
|
-
schema: LOGIN_SCHEMA
|
|
35
|
+
schema: LOGIN_SCHEMA,
|
|
36
|
+
errorHandler: (_error, _request, reply) => {
|
|
37
|
+
reply.code(500).send({ message: 'Internal Server Error' })
|
|
38
|
+
}
|
|
34
39
|
},
|
|
35
40
|
async function (req, reply) {
|
|
36
41
|
const customFunctionProvider = AUTH_CONFIG.authProviders?.['custom-function']
|
|
@@ -54,7 +59,7 @@ export async function customFunctionController(app: FastifyInstance) {
|
|
|
54
59
|
id
|
|
55
60
|
} = req
|
|
56
61
|
|
|
57
|
-
type CustomFunctionAuthResult = { id?: string }
|
|
62
|
+
type CustomFunctionAuthResult = { id?: string; email?: string }
|
|
58
63
|
const authResult = await GenerateContext({
|
|
59
64
|
args: [
|
|
60
65
|
req.body
|
|
@@ -77,21 +82,39 @@ export async function customFunctionController(app: FastifyInstance) {
|
|
|
77
82
|
}
|
|
78
83
|
}) as CustomFunctionAuthResult
|
|
79
84
|
|
|
80
|
-
|
|
81
85
|
if (!authResult.id) {
|
|
82
86
|
reply.code(401).send({ message: 'Unauthorized' })
|
|
83
87
|
return
|
|
84
88
|
}
|
|
85
89
|
|
|
86
|
-
const
|
|
90
|
+
const email = authResult.email ?? authResult.id
|
|
91
|
+
let authUser = await authDb.collection(authCollection!).findOne({ email })
|
|
87
92
|
if (!authUser) {
|
|
88
|
-
|
|
89
|
-
|
|
93
|
+
const authUserId = new ObjectId()
|
|
94
|
+
await authDb.collection(authCollection!).insertOne({
|
|
95
|
+
_id: authUserId,
|
|
96
|
+
email,
|
|
97
|
+
status: 'confirmed',
|
|
98
|
+
createdAt: new Date(),
|
|
99
|
+
custom_data: {},
|
|
100
|
+
identities: [
|
|
101
|
+
{
|
|
102
|
+
id: authResult.id.toString(),
|
|
103
|
+
provider_id: authResult.id.toString(),
|
|
104
|
+
provider_type: 'custom-function',
|
|
105
|
+
provider_data: { email }
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
})
|
|
109
|
+
authUser = {
|
|
110
|
+
_id: authUserId,
|
|
111
|
+
email
|
|
112
|
+
}
|
|
90
113
|
}
|
|
91
114
|
|
|
92
115
|
const user =
|
|
93
116
|
user_id_field && userCollection
|
|
94
|
-
? await
|
|
117
|
+
? await customUserDb
|
|
95
118
|
.collection(userCollection)
|
|
96
119
|
.findOne({ [user_id_field]: authUser._id.toString() })
|
|
97
120
|
: {}
|
|
@@ -107,21 +130,25 @@ export async function customFunctionController(app: FastifyInstance) {
|
|
|
107
130
|
...(user || {})
|
|
108
131
|
}
|
|
109
132
|
}
|
|
133
|
+
|
|
110
134
|
const refreshToken = this.createRefreshToken(currentUserData)
|
|
111
135
|
const refreshTokenHash = hashToken(refreshToken)
|
|
112
|
-
await
|
|
136
|
+
await authDb.collection(refreshTokensCollection).insertOne({
|
|
113
137
|
userId: authUser._id,
|
|
114
138
|
tokenHash: refreshTokenHash,
|
|
115
139
|
createdAt: new Date(),
|
|
116
140
|
expiresAt: new Date(Date.now() + refreshTokenTtlMs),
|
|
117
141
|
revokedAt: null
|
|
118
142
|
})
|
|
119
|
-
|
|
120
|
-
|
|
143
|
+
const accessToken = this.createAccessToken(currentUserData)
|
|
144
|
+
|
|
145
|
+
const responsePayload = {
|
|
146
|
+
access_token: accessToken,
|
|
121
147
|
refresh_token: refreshToken,
|
|
122
148
|
device_id: '',
|
|
123
149
|
user_id: authUser._id.toString()
|
|
124
150
|
}
|
|
151
|
+
reply.code(200).send(responsePayload)
|
|
125
152
|
}
|
|
126
153
|
)
|
|
127
154
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FastifyInstance } from 'fastify'
|
|
2
2
|
import { ObjectId } from 'mongodb'
|
|
3
|
-
import { AUTH_CONFIG, DB_NAME, DEFAULT_CONFIG } from '../../../constants'
|
|
3
|
+
import { AUTH_CONFIG, AUTH_DB_NAME, DB_NAME, DEFAULT_CONFIG } from '../../../constants'
|
|
4
4
|
import handleUserRegistration from '../../../shared/handleUserRegistration'
|
|
5
5
|
import { PROVIDER } from '../../../shared/models/handleUserRegistration.model'
|
|
6
6
|
import { StateManager } from '../../../state'
|
|
@@ -44,7 +44,8 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
44
44
|
const { authCollection, userCollection, user_id_field } = AUTH_CONFIG
|
|
45
45
|
const { resetPasswordCollection } = AUTH_CONFIG
|
|
46
46
|
const { refreshTokensCollection } = AUTH_CONFIG
|
|
47
|
-
const
|
|
47
|
+
const authDb = app.mongo.client.db(AUTH_DB_NAME)
|
|
48
|
+
const customUserDb = app.mongo.client.db(DB_NAME)
|
|
48
49
|
const resetPasswordTtlSeconds = DEFAULT_CONFIG.RESET_PASSWORD_TTL_SECONDS
|
|
49
50
|
const rateLimitWindowMs = DEFAULT_CONFIG.AUTH_RATE_LIMIT_WINDOW_MS
|
|
50
51
|
const loginMaxAttempts = DEFAULT_CONFIG.AUTH_LOGIN_MAX_ATTEMPTS
|
|
@@ -54,7 +55,7 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
54
55
|
const resolveLocalUserpassProvider = () => AUTH_CONFIG.authProviders?.['local-userpass']
|
|
55
56
|
|
|
56
57
|
try {
|
|
57
|
-
await
|
|
58
|
+
await authDb.collection(resetPasswordCollection).createIndex(
|
|
58
59
|
{ createdAt: 1 },
|
|
59
60
|
{ expireAfterSeconds: resetPasswordTtlSeconds }
|
|
60
61
|
)
|
|
@@ -63,7 +64,7 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
try {
|
|
66
|
-
await
|
|
67
|
+
await authDb.collection(refreshTokensCollection).createIndex(
|
|
67
68
|
{ expiresAt: 1 },
|
|
68
69
|
{ expireAfterSeconds: 0 }
|
|
69
70
|
)
|
|
@@ -76,7 +77,7 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
76
77
|
extraArguments?: unknown[]
|
|
77
78
|
) => {
|
|
78
79
|
const { resetPasswordConfig } = AUTH_CONFIG
|
|
79
|
-
const authUser = await
|
|
80
|
+
const authUser = await authDb.collection(authCollection!).findOne({
|
|
80
81
|
email
|
|
81
82
|
})
|
|
82
83
|
|
|
@@ -87,7 +88,7 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
87
88
|
const token = generateToken()
|
|
88
89
|
const tokenId = generateToken()
|
|
89
90
|
|
|
90
|
-
await
|
|
91
|
+
await authDb
|
|
91
92
|
?.collection(resetPasswordCollection)
|
|
92
93
|
.updateOne(
|
|
93
94
|
{ email },
|
|
@@ -194,7 +195,7 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
194
195
|
return
|
|
195
196
|
}
|
|
196
197
|
|
|
197
|
-
const existing = await
|
|
198
|
+
const existing = await authDb.collection(authCollection!).findOne({
|
|
198
199
|
confirmationToken: req.body.token,
|
|
199
200
|
confirmationTokenId: req.body.tokenId
|
|
200
201
|
}) as { _id: ObjectId; status?: string } | null
|
|
@@ -205,7 +206,7 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
205
206
|
}
|
|
206
207
|
|
|
207
208
|
if (existing.status !== 'confirmed') {
|
|
208
|
-
await
|
|
209
|
+
await authDb.collection(authCollection!).updateOne(
|
|
209
210
|
{ _id: existing._id },
|
|
210
211
|
{
|
|
211
212
|
$set: { status: 'confirmed' },
|
|
@@ -241,7 +242,7 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
241
242
|
res.status(429).send({ message: 'Too many requests' })
|
|
242
243
|
return
|
|
243
244
|
}
|
|
244
|
-
const authUser = await
|
|
245
|
+
const authUser = await authDb.collection(authCollection!).findOne({
|
|
245
246
|
email: req.body.username
|
|
246
247
|
})
|
|
247
248
|
|
|
@@ -260,7 +261,7 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
260
261
|
|
|
261
262
|
const user =
|
|
262
263
|
user_id_field && userCollection
|
|
263
|
-
? await
|
|
264
|
+
? await customUserDb
|
|
264
265
|
.collection(userCollection)
|
|
265
266
|
.findOne({ [user_id_field]: authUser._id.toString() })
|
|
266
267
|
: {}
|
|
@@ -284,7 +285,7 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
284
285
|
|
|
285
286
|
const refreshToken = this.createRefreshToken(userWithCustomData)
|
|
286
287
|
const refreshTokenHash = hashToken(refreshToken)
|
|
287
|
-
await
|
|
288
|
+
await authDb.collection(refreshTokensCollection).insertOne({
|
|
288
289
|
userId: authUser._id,
|
|
289
290
|
tokenHash: refreshTokenHash,
|
|
290
291
|
createdAt: new Date(),
|
|
@@ -382,7 +383,7 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
382
383
|
}
|
|
383
384
|
const { token, tokenId, password } = req.body
|
|
384
385
|
|
|
385
|
-
const resetRequest = await
|
|
386
|
+
const resetRequest = await authDb
|
|
386
387
|
?.collection(resetPasswordCollection)
|
|
387
388
|
.findOne({ token, tokenId })
|
|
388
389
|
|
|
@@ -396,11 +397,11 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
396
397
|
Date.now() - createdAt.getTime() > resetPasswordTtlSeconds * 1000
|
|
397
398
|
|
|
398
399
|
if (isExpired) {
|
|
399
|
-
await
|
|
400
|
+
await authDb?.collection(resetPasswordCollection).deleteOne({ _id: resetRequest._id })
|
|
400
401
|
throw new Error(AUTH_ERRORS.INVALID_RESET_PARAMS)
|
|
401
402
|
}
|
|
402
403
|
const hashedPassword = await hashPassword(password)
|
|
403
|
-
await
|
|
404
|
+
await authDb.collection(authCollection!).updateOne(
|
|
404
405
|
{ email: resetRequest.email },
|
|
405
406
|
{
|
|
406
407
|
$set: {
|
|
@@ -409,7 +410,7 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
409
410
|
}
|
|
410
411
|
)
|
|
411
412
|
|
|
412
|
-
await
|
|
413
|
+
await authDb?.collection(resetPasswordCollection).deleteOne({ _id: resetRequest._id })
|
|
413
414
|
}
|
|
414
415
|
)
|
|
415
416
|
}
|
package/src/auth/utils.ts
CHANGED
package/src/constants.ts
CHANGED
|
@@ -14,12 +14,12 @@ const monitEnabled = typeof monitEnabledEnv === 'string'
|
|
|
14
14
|
: false
|
|
15
15
|
|
|
16
16
|
const {
|
|
17
|
-
database_name,
|
|
17
|
+
database_name = 'main',
|
|
18
18
|
collection_name = 'users',
|
|
19
19
|
user_id_field = 'id',
|
|
20
20
|
on_user_creation_function_name
|
|
21
21
|
} = loadCustomUserData()
|
|
22
|
-
const { auth_collection = 'auth_users', ...configuration } = loadAuthConfig()
|
|
22
|
+
const { auth_collection = 'auth_users', auth_database, ...configuration } = loadAuthConfig()
|
|
23
23
|
|
|
24
24
|
export const DEFAULT_CONFIG = {
|
|
25
25
|
PORT: Number(process.env.PORT) || 3000,
|
|
@@ -62,6 +62,7 @@ export const DEFAULT_CONFIG = {
|
|
|
62
62
|
export const API_VERSION = `/api/client/${DEFAULT_CONFIG.API_VERSION}`
|
|
63
63
|
export const HTTPS_SCHEMA = DEFAULT_CONFIG.HTTPS_SCHEMA
|
|
64
64
|
export const DB_NAME = database_name
|
|
65
|
+
export const AUTH_DB_NAME = auth_database ?? database_name
|
|
65
66
|
|
|
66
67
|
type AuthProviders = Record<string, { disabled?: boolean; config?: unknown }>
|
|
67
68
|
// TODO spostare nell'oggetto providers anche le altre configurazioni
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AUTH_CONFIG,
|
|
1
|
+
import { AUTH_CONFIG, AUTH_DB_NAME } from '../../constants'
|
|
2
2
|
import { services } from '../../services'
|
|
3
3
|
import { Function, Functions } from '../functions/interface'
|
|
4
4
|
import { ActivateTriggersParams } from './dtos'
|
|
@@ -36,7 +36,7 @@ export const activateTriggers = async ({
|
|
|
36
36
|
config: {
|
|
37
37
|
isAutoTrigger: true,
|
|
38
38
|
collection: AUTH_CONFIG.authCollection ?? 'auth_users',
|
|
39
|
-
database:
|
|
39
|
+
database: AUTH_DB_NAME,
|
|
40
40
|
full_document: true,
|
|
41
41
|
full_document_before_change: false,
|
|
42
42
|
match: {},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import cron from 'node-cron'
|
|
4
|
-
import { AUTH_CONFIG, DB_NAME } from '../../constants'
|
|
4
|
+
import { AUTH_CONFIG, AUTH_DB_NAME, DB_NAME } from '../../constants'
|
|
5
5
|
import { createEventId, sanitize } from '../../monitoring/utils'
|
|
6
6
|
import { StateManager } from '../../state'
|
|
7
7
|
import { readJsonContent } from '../../utils'
|
|
@@ -246,11 +246,11 @@ const handleAuthenticationTrigger = async ({
|
|
|
246
246
|
const { database, isAutoTrigger, operation_types = [], operation_type } = config
|
|
247
247
|
const providerFilter = normalizeProviders(config.providers ?? [])
|
|
248
248
|
const authCollection = AUTH_CONFIG.authCollection ?? 'auth_users'
|
|
249
|
-
const collection = app.mongo.client.db(database ||
|
|
249
|
+
const collection = app.mongo.client.db(database || AUTH_DB_NAME).collection(authCollection)
|
|
250
250
|
const operationCandidates = operation_type ? mapOpInverse[operation_type] : operation_types
|
|
251
251
|
const normalizedOps = normalizeOperationTypes(operationCandidates)
|
|
252
252
|
const baseMeta = {
|
|
253
|
-
database: database ||
|
|
253
|
+
database: database || AUTH_DB_NAME,
|
|
254
254
|
collection: authCollection,
|
|
255
255
|
operationTypes: normalizedOps,
|
|
256
256
|
providers: providerFilter,
|
|
@@ -277,6 +277,17 @@ const handleAuthenticationTrigger = async ({
|
|
|
277
277
|
changeStream.on('error', (error) => {
|
|
278
278
|
if (shouldIgnoreStreamError(error)) return
|
|
279
279
|
console.error('Authentication trigger change stream error', error)
|
|
280
|
+
emitTriggerEvent({
|
|
281
|
+
status: 'error',
|
|
282
|
+
triggerName,
|
|
283
|
+
triggerType,
|
|
284
|
+
functionName,
|
|
285
|
+
meta: {
|
|
286
|
+
...baseMeta,
|
|
287
|
+
event: 'CHANGE_STREAM'
|
|
288
|
+
},
|
|
289
|
+
error
|
|
290
|
+
})
|
|
280
291
|
})
|
|
281
292
|
changeStream.on('change', async function (change) {
|
|
282
293
|
const operationType = change['operationType' as keyof typeof change] as
|
|
@@ -365,13 +376,6 @@ const handleAuthenticationTrigger = async ({
|
|
|
365
376
|
updateDescription
|
|
366
377
|
}
|
|
367
378
|
try {
|
|
368
|
-
emitTriggerEvent({
|
|
369
|
-
status: 'fired',
|
|
370
|
-
triggerName,
|
|
371
|
-
triggerType,
|
|
372
|
-
functionName,
|
|
373
|
-
meta: { ...baseMeta, event: 'LOGOUT' }
|
|
374
|
-
})
|
|
375
379
|
await GenerateContext({
|
|
376
380
|
args: [{ user: userData, ...op }],
|
|
377
381
|
app,
|
|
@@ -383,6 +387,13 @@ const handleAuthenticationTrigger = async ({
|
|
|
383
387
|
services,
|
|
384
388
|
runAsSystem: true
|
|
385
389
|
})
|
|
390
|
+
emitTriggerEvent({
|
|
391
|
+
status: 'fired',
|
|
392
|
+
triggerName,
|
|
393
|
+
triggerType,
|
|
394
|
+
functionName,
|
|
395
|
+
meta: { ...baseMeta, event: 'LOGOUT' }
|
|
396
|
+
})
|
|
386
397
|
} catch (error) {
|
|
387
398
|
emitTriggerEvent({
|
|
388
399
|
status: 'error',
|
|
@@ -417,13 +428,6 @@ const handleAuthenticationTrigger = async ({
|
|
|
417
428
|
updateDescription
|
|
418
429
|
}
|
|
419
430
|
try {
|
|
420
|
-
emitTriggerEvent({
|
|
421
|
-
status: 'fired',
|
|
422
|
-
triggerName,
|
|
423
|
-
triggerType,
|
|
424
|
-
functionName,
|
|
425
|
-
meta: { ...baseMeta, event: 'DELETE' }
|
|
426
|
-
})
|
|
427
431
|
await GenerateContext({
|
|
428
432
|
args: isAutoTrigger ? [userData] : [{ user: userData, ...op }],
|
|
429
433
|
app,
|
|
@@ -435,6 +439,13 @@ const handleAuthenticationTrigger = async ({
|
|
|
435
439
|
services,
|
|
436
440
|
runAsSystem: true
|
|
437
441
|
})
|
|
442
|
+
emitTriggerEvent({
|
|
443
|
+
status: 'fired',
|
|
444
|
+
triggerName,
|
|
445
|
+
triggerType,
|
|
446
|
+
functionName,
|
|
447
|
+
meta: { ...baseMeta, event: 'DELETE' }
|
|
448
|
+
})
|
|
438
449
|
} catch (error) {
|
|
439
450
|
emitTriggerEvent({
|
|
440
451
|
status: 'error',
|
|
@@ -471,13 +482,6 @@ const handleAuthenticationTrigger = async ({
|
|
|
471
482
|
updateDescription
|
|
472
483
|
}
|
|
473
484
|
try {
|
|
474
|
-
emitTriggerEvent({
|
|
475
|
-
status: 'fired',
|
|
476
|
-
triggerName,
|
|
477
|
-
triggerType,
|
|
478
|
-
functionName,
|
|
479
|
-
meta: { ...baseMeta, event: 'UPDATE' }
|
|
480
|
-
})
|
|
481
485
|
await GenerateContext({
|
|
482
486
|
args: isAutoTrigger ? [userData] : [{ user: userData, ...op }],
|
|
483
487
|
app,
|
|
@@ -489,6 +493,13 @@ const handleAuthenticationTrigger = async ({
|
|
|
489
493
|
services,
|
|
490
494
|
runAsSystem: true
|
|
491
495
|
})
|
|
496
|
+
emitTriggerEvent({
|
|
497
|
+
status: 'fired',
|
|
498
|
+
triggerName,
|
|
499
|
+
triggerType,
|
|
500
|
+
functionName,
|
|
501
|
+
meta: { ...baseMeta, event: 'UPDATE' }
|
|
502
|
+
})
|
|
492
503
|
} catch (error) {
|
|
493
504
|
emitTriggerEvent({
|
|
494
505
|
status: 'error',
|
|
@@ -575,13 +586,6 @@ const handleAuthenticationTrigger = async ({
|
|
|
575
586
|
}
|
|
576
587
|
|
|
577
588
|
try {
|
|
578
|
-
emitTriggerEvent({
|
|
579
|
-
status: 'fired',
|
|
580
|
-
triggerName,
|
|
581
|
-
triggerType,
|
|
582
|
-
functionName,
|
|
583
|
-
meta: { ...baseMeta, event: 'CREATE' }
|
|
584
|
-
})
|
|
585
589
|
await GenerateContext({
|
|
586
590
|
args: isAutoTrigger ? [userData] : [{ user: userData, ...op }],
|
|
587
591
|
app,
|
|
@@ -593,6 +597,13 @@ const handleAuthenticationTrigger = async ({
|
|
|
593
597
|
services,
|
|
594
598
|
runAsSystem: true
|
|
595
599
|
})
|
|
600
|
+
emitTriggerEvent({
|
|
601
|
+
status: 'fired',
|
|
602
|
+
triggerName,
|
|
603
|
+
triggerType,
|
|
604
|
+
functionName,
|
|
605
|
+
meta: { ...baseMeta, event: 'CREATE' }
|
|
606
|
+
})
|
|
596
607
|
} catch (error) {
|
|
597
608
|
emitTriggerEvent({
|
|
598
609
|
status: 'error',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { FastifyInstance } from 'fastify'
|
|
2
2
|
import { ObjectId } from 'mongodb'
|
|
3
3
|
import { loadAuthConfig, loadCustomUserData, PASSWORD_RULES } from '../../auth/utils'
|
|
4
|
-
import { AUTH_CONFIG, DB_NAME } from '../../constants'
|
|
4
|
+
import { AUTH_CONFIG, AUTH_DB_NAME, DB_NAME } from '../../constants'
|
|
5
5
|
import handleUserRegistration from '../../shared/handleUserRegistration'
|
|
6
6
|
import { PROVIDER } from '../../shared/models/handleUserRegistration.model'
|
|
7
7
|
import { hashPassword } from '../../utils/crypto'
|
|
@@ -47,7 +47,8 @@ export const registerUserRoutes = (app: FastifyInstance, deps: UserRoutesDeps) =
|
|
|
47
47
|
const resolvedAuthLimit = Math.min(Number.isFinite(parsedAuthLimit) && parsedAuthLimit > 0 ? parsedAuthLimit : 100, 500)
|
|
48
48
|
const resolvedCustomLimit = Math.min(Number.isFinite(parsedCustomLimit) && parsedCustomLimit > 0 ? parsedCustomLimit : 25, 500)
|
|
49
49
|
const resolvedCustomPage = Math.max(Number.isFinite(parsedPage) && parsedPage > 0 ? parsedPage : 1, 1)
|
|
50
|
-
const
|
|
50
|
+
const authDb = app.mongo.client.db(AUTH_DB_NAME)
|
|
51
|
+
const customDb = app.mongo.client.db(DB_NAME)
|
|
51
52
|
const authCollection = AUTH_CONFIG.authCollection ?? 'auth_users'
|
|
52
53
|
const userCollection = AUTH_CONFIG.userCollection
|
|
53
54
|
|
|
@@ -69,7 +70,7 @@ export const registerUserRoutes = (app: FastifyInstance, deps: UserRoutesDeps) =
|
|
|
69
70
|
]
|
|
70
71
|
}
|
|
71
72
|
: {}
|
|
72
|
-
const authItems = await
|
|
73
|
+
const authItems = await authDb
|
|
73
74
|
.collection(authCollection)
|
|
74
75
|
.find(authFilter)
|
|
75
76
|
.sort({ createdAt: -1, _id: -1 })
|
|
@@ -94,11 +95,11 @@ export const registerUserRoutes = (app: FastifyInstance, deps: UserRoutesDeps) =
|
|
|
94
95
|
]
|
|
95
96
|
}
|
|
96
97
|
: {}
|
|
97
|
-
const total = await
|
|
98
|
+
const total = await customDb.collection(userCollection).countDocuments(customFilter)
|
|
98
99
|
const totalPages = Math.max(1, Math.ceil(total / Math.max(resolvedCustomLimit, 1)))
|
|
99
100
|
const page = Math.min(resolvedCustomPage, totalPages)
|
|
100
101
|
const skip = Math.max(0, (page - 1) * resolvedCustomLimit)
|
|
101
|
-
const customItems = await
|
|
102
|
+
const customItems = await customDb
|
|
102
103
|
.collection(userCollection)
|
|
103
104
|
.find(customFilter)
|
|
104
105
|
.sort({ createdAt: -1, _id: -1 })
|
|
@@ -193,7 +194,7 @@ export const registerUserRoutes = (app: FastifyInstance, deps: UserRoutesDeps) =
|
|
|
193
194
|
return { error: passwordError }
|
|
194
195
|
}
|
|
195
196
|
|
|
196
|
-
const db = app.mongo.client.db(
|
|
197
|
+
const db = app.mongo.client.db(AUTH_DB_NAME)
|
|
197
198
|
const authCollection = AUTH_CONFIG.authCollection ?? 'auth_users'
|
|
198
199
|
const selector: Record<string, unknown> = {}
|
|
199
200
|
|
|
@@ -231,7 +232,7 @@ export const registerUserRoutes = (app: FastifyInstance, deps: UserRoutesDeps) =
|
|
|
231
232
|
app.patch(`${prefix}/api/users/:id/status`, async (req, reply) => {
|
|
232
233
|
const params = req.params as { id: string }
|
|
233
234
|
const body = req.body as { disabled?: boolean; status?: string; email?: string }
|
|
234
|
-
const db = app.mongo.client.db(
|
|
235
|
+
const db = app.mongo.client.db(AUTH_DB_NAME)
|
|
235
236
|
const authCollection = AUTH_CONFIG.authCollection ?? 'auth_users'
|
|
236
237
|
const selector: Record<string, unknown> = {}
|
|
237
238
|
|
package/src/monitoring/ui.css
CHANGED
|
@@ -365,13 +365,17 @@ button.danger {
|
|
|
365
365
|
|
|
366
366
|
.event-row {
|
|
367
367
|
display: grid;
|
|
368
|
-
grid-template-columns:
|
|
368
|
+
grid-template-columns: 170px 90px 70px 160px 160px 1fr;
|
|
369
369
|
gap: 8px;
|
|
370
370
|
padding: 4px 6px;
|
|
371
371
|
border-bottom: 1px dashed rgba(26, 47, 34, 0.6);
|
|
372
372
|
cursor: pointer;
|
|
373
373
|
}
|
|
374
374
|
|
|
375
|
+
.event-row > div:first-child {
|
|
376
|
+
white-space: nowrap;
|
|
377
|
+
}
|
|
378
|
+
|
|
375
379
|
.event-row.event-header {
|
|
376
380
|
position: sticky;
|
|
377
381
|
top: 0;
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
wsStatus,
|
|
27
27
|
clearEvents
|
|
28
28
|
} = dom;
|
|
29
|
-
const {
|
|
29
|
+
const { formatDateTime, highlightJson } = utils;
|
|
30
30
|
const { setActiveTab } = helpers;
|
|
31
31
|
|
|
32
32
|
const isOptionsEvent = (event) => {
|
|
@@ -141,7 +141,7 @@
|
|
|
141
141
|
row.className = 'event-row';
|
|
142
142
|
row.dataset.id = event.id;
|
|
143
143
|
const typeClass = event.type === 'error' ? 'error' : (event.type === 'warn' ? 'warn' : '');
|
|
144
|
-
row.innerHTML = '<div>' +
|
|
144
|
+
row.innerHTML = '<div>' + formatDateTime(event.ts) + '</div>' +
|
|
145
145
|
'<div class="event-type ' + typeClass + '">' + (event.type || '-') + '</div>' +
|
|
146
146
|
'<div class="event-run" title="' + (runMode || '-') + '">' + (runMode || '-') + '</div>' +
|
|
147
147
|
'<div class="event-invoked" title="' + (invokedFrom || '-') + '">' + (invokedFrom || '-') + '</div>' +
|
package/src/monitoring/utils.ts
CHANGED
|
@@ -2,7 +2,7 @@ import fs from 'node:fs'
|
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import type { FastifyInstance, FastifyRequest } from 'fastify'
|
|
4
4
|
import { ObjectId } from 'mongodb'
|
|
5
|
-
import { AUTH_CONFIG, DB_NAME, DEFAULT_CONFIG } from '../constants'
|
|
5
|
+
import { AUTH_CONFIG, AUTH_DB_NAME, DB_NAME, DEFAULT_CONFIG } from '../constants'
|
|
6
6
|
import type { Rules } from '../features/rules/interface'
|
|
7
7
|
import { getValidRule } from '../services/mongodb-atlas/utils'
|
|
8
8
|
import { checkApplyWhen } from '../utils/roles/machines/utils'
|
|
@@ -380,7 +380,8 @@ export const resolveUserContext = async (
|
|
|
380
380
|
if (!userId) return undefined
|
|
381
381
|
const normalizedUserId = userId.trim()
|
|
382
382
|
|
|
383
|
-
const
|
|
383
|
+
const authDb = app.mongo.client.db(AUTH_DB_NAME)
|
|
384
|
+
const customDb = app.mongo.client.db(DB_NAME)
|
|
384
385
|
const authCollection = AUTH_CONFIG.authCollection ?? 'auth_users'
|
|
385
386
|
const userCollection = AUTH_CONFIG.userCollection
|
|
386
387
|
const userIdField = AUTH_CONFIG.user_id_field ?? 'id'
|
|
@@ -388,14 +389,14 @@ export const resolveUserContext = async (
|
|
|
388
389
|
const authSelector = isObjectId
|
|
389
390
|
? { _id: new ObjectId(normalizedUserId) }
|
|
390
391
|
: { id: normalizedUserId }
|
|
391
|
-
const authUser = await
|
|
392
|
+
const authUser = await authDb.collection(authCollection).findOne(authSelector)
|
|
392
393
|
|
|
393
394
|
let customUser: Record<string, unknown> | null = null
|
|
394
395
|
if (userCollection) {
|
|
395
396
|
const customSelector = { [userIdField]: normalizedUserId }
|
|
396
|
-
customUser = await
|
|
397
|
+
customUser = await customDb.collection(userCollection).findOne(customSelector)
|
|
397
398
|
if (!customUser && isObjectId) {
|
|
398
|
-
customUser = await
|
|
399
|
+
customUser = await customDb.collection(userCollection).findOne({ _id: new ObjectId(normalizedUserId) })
|
|
399
400
|
}
|
|
400
401
|
}
|
|
401
402
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ObjectId } from "bson"
|
|
2
|
-
import { AUTH_CONFIG,
|
|
2
|
+
import { AUTH_CONFIG, AUTH_DB_NAME } from "../constants"
|
|
3
3
|
import { emitServiceEvent } from "../services/monitoring"
|
|
4
4
|
import { HandleUserDeletion } from "./models/handleUserDeletion.model"
|
|
5
5
|
|
|
@@ -33,7 +33,7 @@ const handleUserDeletion: HandleUserDeletion = (app, opt) => async ({ id, email
|
|
|
33
33
|
|
|
34
34
|
const { authCollection } = AUTH_CONFIG
|
|
35
35
|
const mongo = app?.mongo
|
|
36
|
-
const db = mongo.client.db(
|
|
36
|
+
const db = mongo.client.db(AUTH_DB_NAME)
|
|
37
37
|
const collection = db.collection<Record<string, unknown>>(authCollection!)
|
|
38
38
|
let query: Record<string, unknown>
|
|
39
39
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { AUTH_CONFIG,
|
|
1
|
+
import { AUTH_CONFIG, AUTH_DB_NAME } from "../constants"
|
|
2
|
+
import { emitServiceEvent } from "../services/monitoring"
|
|
2
3
|
import { StateManager } from "../state"
|
|
3
4
|
import { GenerateContext } from "../utils/context"
|
|
4
5
|
import { generateToken, hashPassword } from "../utils/crypto"
|
|
5
|
-
import { emitServiceEvent } from "../services/monitoring"
|
|
6
6
|
import { HandleUserRegistration } from "./models/handleUserRegistration.model"
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -35,7 +35,7 @@ const handleUserRegistration: HandleUserRegistration = (app, opt) => async ({ em
|
|
|
35
35
|
const runConfirmationFunction = localUserpassConfig?.runConfirmationFunction === true
|
|
36
36
|
const confirmationFunctionName = localUserpassConfig?.confirmationFunctionName
|
|
37
37
|
const mongo = app?.mongo
|
|
38
|
-
const db = mongo.client.db(
|
|
38
|
+
const db = mongo.client.db(AUTH_DB_NAME)
|
|
39
39
|
const hashedPassword = await hashPassword(password)
|
|
40
40
|
|
|
41
41
|
const existingUser = await db?.collection(authCollection!).findOne({ email })
|