@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.
- package/CHANGELOG.md +74 -0
- package/README.md +9 -3
- package/dist/auth/controller.d.ts.map +1 -1
- package/dist/auth/controller.js +2 -2
- package/dist/auth/plugins/jwt.js +3 -3
- package/dist/auth/providers/anon-user/controller.d.ts +8 -0
- package/dist/auth/providers/anon-user/controller.d.ts.map +1 -0
- package/dist/auth/providers/anon-user/controller.js +90 -0
- package/dist/auth/providers/anon-user/dtos.d.ts +10 -0
- package/dist/auth/providers/anon-user/dtos.d.ts.map +1 -0
- package/dist/auth/providers/anon-user/dtos.js +2 -0
- package/dist/auth/providers/custom-function/controller.d.ts.map +1 -1
- package/dist/auth/providers/custom-function/controller.js +32 -35
- package/dist/auth/providers/custom-function/dtos.d.ts +4 -1
- package/dist/auth/providers/custom-function/dtos.d.ts.map +1 -1
- package/dist/auth/providers/local-userpass/controller.d.ts.map +1 -1
- package/dist/auth/providers/local-userpass/controller.js +41 -33
- package/dist/auth/providers/local-userpass/dtos.d.ts +6 -0
- package/dist/auth/providers/local-userpass/dtos.d.ts.map +1 -1
- package/dist/auth/utils.d.ts +24 -1
- package/dist/auth/utils.d.ts.map +1 -1
- package/dist/auth/utils.js +13 -1
- package/dist/constants.d.ts +4 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +7 -3
- package/dist/features/functions/controller.d.ts.map +1 -1
- package/dist/features/functions/controller.js +27 -11
- package/dist/features/functions/utils.d.ts +1 -1
- package/dist/features/triggers/index.d.ts.map +1 -1
- package/dist/features/triggers/index.js +49 -7
- package/dist/features/triggers/interface.d.ts +1 -0
- package/dist/features/triggers/interface.d.ts.map +1 -1
- package/dist/features/triggers/utils.d.ts.map +1 -1
- package/dist/features/triggers/utils.js +67 -26
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -12
- package/dist/services/mongodb-atlas/index.d.ts.map +1 -1
- package/dist/services/mongodb-atlas/index.js +2 -2
- package/dist/services/mongodb-atlas/model.d.ts +2 -2
- package/dist/services/mongodb-atlas/model.d.ts.map +1 -1
- package/dist/services/mongodb-atlas/utils.d.ts.map +1 -1
- package/dist/services/mongodb-atlas/utils.js +3 -1
- package/dist/shared/handleUserRegistration.d.ts.map +1 -1
- package/dist/shared/handleUserRegistration.js +66 -1
- package/dist/shared/models/handleUserRegistration.model.d.ts +2 -1
- package/dist/shared/models/handleUserRegistration.model.d.ts.map +1 -1
- package/dist/shared/models/handleUserRegistration.model.js +1 -0
- package/dist/utils/context/helpers.d.ts +5 -5
- package/dist/utils/context/helpers.d.ts.map +1 -1
- package/dist/utils/context/index.d.ts.map +1 -1
- package/dist/utils/context/index.js +12 -14
- package/dist/utils/initializer/exposeRoutes.js +1 -1
- package/dist/utils/initializer/registerPlugins.d.ts.map +1 -1
- package/dist/utils/initializer/registerPlugins.js +12 -4
- package/dist/utils/rules-matcher/utils.d.ts.map +1 -1
- package/dist/utils/rules-matcher/utils.js +3 -0
- package/package.json +1 -1
- package/src/auth/controller.ts +5 -2
- package/src/auth/plugins/jwt.ts +5 -5
- package/src/auth/providers/anon-user/controller.ts +91 -0
- package/src/auth/providers/anon-user/dtos.ts +10 -0
- package/src/auth/providers/custom-function/controller.ts +34 -39
- package/src/auth/providers/custom-function/dtos.ts +5 -1
- package/src/auth/providers/local-userpass/controller.ts +56 -43
- package/src/auth/providers/local-userpass/dtos.ts +7 -0
- package/src/auth/utils.ts +22 -1
- package/src/constants.ts +5 -1
- package/src/features/functions/controller.ts +27 -11
- package/src/features/triggers/index.ts +44 -1
- package/src/features/triggers/interface.ts +1 -0
- package/src/features/triggers/utils.ts +89 -37
- package/src/index.ts +18 -12
- package/src/services/mongodb-atlas/index.ts +654 -654
- package/src/services/mongodb-atlas/model.ts +2 -2
- package/src/services/mongodb-atlas/utils.ts +3 -0
- package/src/shared/handleUserRegistration.ts +83 -2
- package/src/shared/models/handleUserRegistration.model.ts +2 -1
- package/src/utils/__tests__/registerPlugins.test.ts +5 -1
- package/src/utils/context/index.ts +32 -36
- package/src/utils/initializer/exposeRoutes.ts +1 -1
- package/src/utils/initializer/registerPlugins.ts +8 -0
- package/src/utils/rules-matcher/utils.ts +3 -0
|
@@ -2,9 +2,9 @@ import { FastifyInstance } from 'fastify'
|
|
|
2
2
|
import {
|
|
3
3
|
Collection,
|
|
4
4
|
Document,
|
|
5
|
-
Filter as MongoFilter,
|
|
6
5
|
FindCursor,
|
|
7
6
|
FindOneAndUpdateOptions,
|
|
7
|
+
Filter as MongoFilter,
|
|
8
8
|
UpdateFilter,
|
|
9
9
|
WithId
|
|
10
10
|
} from 'mongodb'
|
|
@@ -67,7 +67,7 @@ export type GetOperatorsFunction = (
|
|
|
67
67
|
watch: (...params: Parameters<Method<'watch'>>) => ReturnType<Method<'watch'>>
|
|
68
68
|
aggregate: (
|
|
69
69
|
...params: [...Parameters<Method<'aggregate'>>, isClient: boolean]
|
|
70
|
-
) =>
|
|
70
|
+
) => ReturnType<Method<'aggregate'>>
|
|
71
71
|
insertMany: (
|
|
72
72
|
...params: Parameters<Method<'insertMany'>>
|
|
73
73
|
) => ReturnType<Method<'insertMany'>>
|
|
@@ -23,12 +23,14 @@ export const getValidRule = <T extends Role | Filter>({
|
|
|
23
23
|
record = null
|
|
24
24
|
}: GetValidRuleParams<T>) => {
|
|
25
25
|
if (!filters.length) return []
|
|
26
|
+
const rootRecord = record ?? null
|
|
26
27
|
|
|
27
28
|
return filters.filter((f) => {
|
|
28
29
|
if (Object.keys(f.apply_when).length === 0) return true
|
|
29
30
|
|
|
30
31
|
// expandQuery traduce i placeholder (%%user, %%true)
|
|
31
32
|
const conditions = expandQuery(f.apply_when, {
|
|
33
|
+
'%%root': rootRecord,
|
|
32
34
|
'%%user': user,
|
|
33
35
|
'%%true': true
|
|
34
36
|
/** values */
|
|
@@ -40,6 +42,7 @@ export const getValidRule = <T extends Role | Filter>({
|
|
|
40
42
|
conditions as Parameters<typeof rulesMatcherUtils.checkRule>[0],
|
|
41
43
|
{
|
|
42
44
|
...(record ?? {}),
|
|
45
|
+
'%%root': rootRecord,
|
|
43
46
|
'%%user': user,
|
|
44
47
|
'%%true': true
|
|
45
48
|
},
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { AUTH_CONFIG, DB_NAME } from "../constants"
|
|
2
|
-
import {
|
|
2
|
+
import { StateManager } from "../state"
|
|
3
|
+
import { GenerateContext } from "../utils/context"
|
|
4
|
+
import { generateToken, hashPassword } from "../utils/crypto"
|
|
3
5
|
import { HandleUserRegistration } from "./models/handleUserRegistration.model"
|
|
4
6
|
|
|
5
7
|
/**
|
|
@@ -17,6 +19,10 @@ const handleUserRegistration: HandleUserRegistration = (app, opt) => async ({ em
|
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
const { authCollection } = AUTH_CONFIG
|
|
22
|
+
const localUserpassConfig = AUTH_CONFIG.localUserpassConfig
|
|
23
|
+
const autoConfirm = localUserpassConfig?.autoConfirm === true
|
|
24
|
+
const runConfirmationFunction = localUserpassConfig?.runConfirmationFunction === true
|
|
25
|
+
const confirmationFunctionName = localUserpassConfig?.confirmationFunctionName
|
|
20
26
|
const mongo = app?.mongo
|
|
21
27
|
const db = mongo.client.db(DB_NAME)
|
|
22
28
|
const hashedPassword = await hashPassword(password)
|
|
@@ -29,7 +35,7 @@ const handleUserRegistration: HandleUserRegistration = (app, opt) => async ({ em
|
|
|
29
35
|
const result = await db?.collection(authCollection!).insertOne({
|
|
30
36
|
email,
|
|
31
37
|
password: hashedPassword,
|
|
32
|
-
status: skipUserCheck ? 'confirmed' : 'pending',
|
|
38
|
+
status: skipUserCheck || autoConfirm ? 'confirmed' : 'pending',
|
|
33
39
|
createdAt: new Date(),
|
|
34
40
|
custom_data: {
|
|
35
41
|
// TODO: aggiungere dati personalizzati alla registrazione
|
|
@@ -58,6 +64,81 @@ const handleUserRegistration: HandleUserRegistration = (app, opt) => async ({ em
|
|
|
58
64
|
}
|
|
59
65
|
)
|
|
60
66
|
|
|
67
|
+
if (!result?.insertedId || skipUserCheck || autoConfirm) {
|
|
68
|
+
return result
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!runConfirmationFunction) {
|
|
72
|
+
throw new Error('Missing confirmation function')
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!confirmationFunctionName) {
|
|
76
|
+
throw new Error('Missing confirmation function name')
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const functionsList = StateManager.select('functions')
|
|
80
|
+
const services = StateManager.select('services')
|
|
81
|
+
const confirmationFunction = functionsList[confirmationFunctionName]
|
|
82
|
+
if (!confirmationFunction) {
|
|
83
|
+
throw new Error(`Confirmation function not found: ${confirmationFunctionName}`)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const token = generateToken()
|
|
87
|
+
const tokenId = generateToken()
|
|
88
|
+
await db?.collection(authCollection!).updateOne(
|
|
89
|
+
{ _id: result.insertedId },
|
|
90
|
+
{
|
|
91
|
+
$set: {
|
|
92
|
+
confirmationToken: token,
|
|
93
|
+
confirmationTokenId: tokenId
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
type ConfirmationResult = { status?: 'success' | 'pending' | 'fail' }
|
|
99
|
+
let confirmationStatus: ConfirmationResult['status'] = 'fail'
|
|
100
|
+
try {
|
|
101
|
+
const response = await GenerateContext({
|
|
102
|
+
args: [{
|
|
103
|
+
token,
|
|
104
|
+
tokenId,
|
|
105
|
+
username: email
|
|
106
|
+
}],
|
|
107
|
+
app,
|
|
108
|
+
rules: {},
|
|
109
|
+
user: {},
|
|
110
|
+
currentFunction: confirmationFunction,
|
|
111
|
+
functionsList,
|
|
112
|
+
services,
|
|
113
|
+
runAsSystem: true
|
|
114
|
+
}) as ConfirmationResult
|
|
115
|
+
confirmationStatus = response?.status ?? 'fail'
|
|
116
|
+
} catch {
|
|
117
|
+
confirmationStatus = 'fail'
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (confirmationStatus === 'success') {
|
|
121
|
+
await db?.collection(authCollection!).updateOne(
|
|
122
|
+
{ _id: result.insertedId },
|
|
123
|
+
{
|
|
124
|
+
$set: { status: 'confirmed' },
|
|
125
|
+
$unset: { confirmationToken: '', confirmationTokenId: '' }
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
return result
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (confirmationStatus === 'pending') {
|
|
132
|
+
return result
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
await db?.collection(authCollection!).updateOne(
|
|
136
|
+
{ _id: result.insertedId },
|
|
137
|
+
{
|
|
138
|
+
$set: { status: 'failed' },
|
|
139
|
+
$unset: { confirmationToken: '', confirmationTokenId: '' }
|
|
140
|
+
}
|
|
141
|
+
)
|
|
61
142
|
return result
|
|
62
143
|
|
|
63
144
|
}
|
|
@@ -3,6 +3,7 @@ import fastifyMongodb from '@fastify/mongodb'
|
|
|
3
3
|
import { authController } from '../../auth/controller'
|
|
4
4
|
import jwtAuthPlugin from '../../auth/plugins/jwt'
|
|
5
5
|
import fastifyRawBody from 'fastify-raw-body'
|
|
6
|
+
import { anonUserController } from '../../auth/providers/anon-user/controller'
|
|
6
7
|
import { customFunctionController } from '../../auth/providers/custom-function/controller'
|
|
7
8
|
import { localUserPassController } from '../../auth/providers/local-userpass/controller'
|
|
8
9
|
import { Functions } from '../../features/functions/interface'
|
|
@@ -36,7 +37,7 @@ describe('registerPlugins', () => {
|
|
|
36
37
|
})
|
|
37
38
|
|
|
38
39
|
// Check Plugins Registration
|
|
39
|
-
expect(registerMock).toHaveBeenCalledTimes(
|
|
40
|
+
expect(registerMock).toHaveBeenCalledTimes(8)
|
|
40
41
|
expect(registerMock).toHaveBeenCalledWith(cors, {
|
|
41
42
|
origin: '*',
|
|
42
43
|
methods: ['POST', 'GET']
|
|
@@ -63,6 +64,9 @@ describe('registerPlugins', () => {
|
|
|
63
64
|
expect(registerMock).toHaveBeenCalledWith(customFunctionController, {
|
|
64
65
|
prefix: `${MOCKED_API_VERSION}/app/:appId/auth/providers/custom-function`
|
|
65
66
|
})
|
|
67
|
+
expect(registerMock).toHaveBeenCalledWith(anonUserController, {
|
|
68
|
+
prefix: `${MOCKED_API_VERSION}/app/:appId/auth/providers/anon-user`
|
|
69
|
+
})
|
|
66
70
|
})
|
|
67
71
|
|
|
68
72
|
it('should handle errors in the catch block', async () => {
|
|
@@ -214,11 +214,11 @@ export async function GenerateContext({
|
|
|
214
214
|
const moduleCache = new Map<string, vm.Module>()
|
|
215
215
|
|
|
216
216
|
const loadModule = async (specifier: string): Promise<vm.Module> => {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
217
|
+
const importTarget = resolveImportTarget(specifier, customRequire)
|
|
218
|
+
const cached = moduleCache.get(importTarget)
|
|
219
|
+
if (cached) return cached
|
|
220
220
|
|
|
221
|
-
|
|
221
|
+
const namespace = await dynamicImport(importTarget)
|
|
222
222
|
const exportNames = Object.keys(namespace)
|
|
223
223
|
if ('default' in namespace && !exportNames.includes('default')) {
|
|
224
224
|
exportNames.push('default')
|
|
@@ -234,34 +234,25 @@ export async function GenerateContext({
|
|
|
234
234
|
{ context: vmContext, identifier: importTarget }
|
|
235
235
|
)
|
|
236
236
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
const importModuleDynamically = (async (
|
|
242
|
-
specifier: string
|
|
243
|
-
): Promise<vm.Module> => {
|
|
244
|
-
const module = await loadModule(specifier)
|
|
245
|
-
if (module.status === 'unlinked') {
|
|
246
|
-
await module.link(loadModule)
|
|
247
|
-
}
|
|
248
|
-
if (module.status === 'linked') {
|
|
249
|
-
await module.evaluate()
|
|
237
|
+
moduleCache.set(importTarget, syntheticModule)
|
|
238
|
+
return syntheticModule
|
|
250
239
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
240
|
+
|
|
241
|
+
const importModuleDynamically =
|
|
242
|
+
((specifier: string) => loadModule(specifier) as unknown as vm.Module) as unknown as
|
|
243
|
+
vm.SourceTextModuleOptions['importModuleDynamically']
|
|
244
|
+
|
|
245
|
+
const sourceModule = new vmModules.SourceTextModule(
|
|
246
|
+
wrapEsmModule(functionToRun.code),
|
|
247
|
+
{
|
|
248
|
+
context: vmContext,
|
|
249
|
+
identifier: entryFile,
|
|
250
|
+
initializeImportMeta: (meta) => {
|
|
251
|
+
meta.url = pathToFileURL(entryFile).href
|
|
252
|
+
},
|
|
253
|
+
importModuleDynamically
|
|
254
|
+
}
|
|
255
|
+
)
|
|
265
256
|
|
|
266
257
|
await sourceModule.link(loadModule)
|
|
267
258
|
await sourceModule.evaluate()
|
|
@@ -281,9 +272,9 @@ export async function GenerateContext({
|
|
|
281
272
|
}
|
|
282
273
|
|
|
283
274
|
sandboxModule.exports = resolveExport(vmContext) ?? sandboxModule.exports
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
|
|
275
|
+
} catch (error) {
|
|
276
|
+
console.error(error)
|
|
277
|
+
throw error
|
|
287
278
|
}
|
|
288
279
|
|
|
289
280
|
if (deserializeArgs) {
|
|
@@ -294,6 +285,11 @@ export async function GenerateContext({
|
|
|
294
285
|
|
|
295
286
|
return await (sandboxModule.exports as ExportedFunction)(...args)
|
|
296
287
|
}
|
|
297
|
-
|
|
298
|
-
|
|
288
|
+
try {
|
|
289
|
+
const res = await functionsQueue.add(run, enqueue)
|
|
290
|
+
return res
|
|
291
|
+
} catch (error) {
|
|
292
|
+
console.error(error)
|
|
293
|
+
throw error
|
|
294
|
+
}
|
|
299
295
|
}
|
|
@@ -18,7 +18,7 @@ export const exposeRoutes = async (fastify: FastifyInstance) => {
|
|
|
18
18
|
const headerHost = req.headers.host ?? 'localhost:3000'
|
|
19
19
|
const hostname = headerHost.split(':')[0]
|
|
20
20
|
const port = DEFAULT_CONFIG?.PORT ?? 3000
|
|
21
|
-
const host = `${hostname}:${port}`
|
|
21
|
+
const host = port === 8080 ? hostname : `${hostname}:${port}`
|
|
22
22
|
const wsSchema = 'wss'
|
|
23
23
|
|
|
24
24
|
return {
|
|
@@ -5,6 +5,7 @@ import fastifyRawBody from 'fastify-raw-body'
|
|
|
5
5
|
import { CorsConfig } from '../../'
|
|
6
6
|
import { authController } from '../../auth/controller'
|
|
7
7
|
import jwtAuthPlugin from '../../auth/plugins/jwt'
|
|
8
|
+
import { anonUserController } from '../../auth/providers/anon-user/controller'
|
|
8
9
|
import { customFunctionController } from '../../auth/providers/custom-function/controller'
|
|
9
10
|
import { localUserPassController } from '../../auth/providers/local-userpass/controller'
|
|
10
11
|
import { API_VERSION } from '../../constants'
|
|
@@ -133,6 +134,13 @@ const getRegisterConfig = async ({
|
|
|
133
134
|
options: {
|
|
134
135
|
prefix: `${API_VERSION}/app/:appId/auth/providers/custom-function`
|
|
135
136
|
}
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
pluginName: 'anonUserController',
|
|
140
|
+
plugin: anonUserController,
|
|
141
|
+
options: {
|
|
142
|
+
prefix: `${API_VERSION}/app/:appId/auth/providers/anon-user`
|
|
143
|
+
}
|
|
136
144
|
}
|
|
137
145
|
] as RegisterConfig[]
|
|
138
146
|
}
|
|
@@ -154,6 +154,9 @@ const rulesMatcherUtils: RulesMatcherUtils = {
|
|
|
154
154
|
},
|
|
155
155
|
forceArray: (a) => (Array.isArray(a) ? a : [a]),
|
|
156
156
|
getPath: (path, prefix) => {
|
|
157
|
+
if (typeof path !== 'string' || path.length === 0) {
|
|
158
|
+
return ''
|
|
159
|
+
}
|
|
157
160
|
if (path.indexOf('^') === 0) {
|
|
158
161
|
return _trimStart(path, '^')
|
|
159
162
|
}
|