@flowerforce/flowerbase 1.0.1-beta.8 → 1.0.2

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 (178) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/LICENSE +1 -1
  3. package/README.md +466 -7
  4. package/dist/auth/controller.d.ts.map +1 -1
  5. package/dist/auth/controller.js +11 -1
  6. package/dist/auth/providers/local-userpass/controller.d.ts.map +1 -1
  7. package/dist/auth/providers/local-userpass/controller.js +15 -15
  8. package/dist/auth/utils.d.ts +2 -1
  9. package/dist/auth/utils.d.ts.map +1 -1
  10. package/dist/auth/utils.js +14 -10
  11. package/dist/constants.d.ts.map +1 -1
  12. package/dist/constants.js +3 -3
  13. package/dist/features/endpoints/utils.d.ts +1 -1
  14. package/dist/features/endpoints/utils.d.ts.map +1 -1
  15. package/dist/features/endpoints/utils.js +5 -2
  16. package/dist/features/functions/controller.d.ts.map +1 -1
  17. package/dist/features/functions/controller.js +12 -8
  18. package/dist/features/functions/dtos.d.ts +2 -1
  19. package/dist/features/functions/dtos.d.ts.map +1 -1
  20. package/dist/features/functions/interface.d.ts +2 -1
  21. package/dist/features/functions/interface.d.ts.map +1 -1
  22. package/dist/features/functions/utils.d.ts +1 -1
  23. package/dist/features/functions/utils.d.ts.map +1 -1
  24. package/dist/features/functions/utils.js +4 -4
  25. package/dist/features/triggers/index.d.ts.map +1 -1
  26. package/dist/features/triggers/index.js +9 -3
  27. package/dist/features/triggers/interface.d.ts +4 -4
  28. package/dist/features/triggers/interface.d.ts.map +1 -1
  29. package/dist/features/triggers/utils.d.ts.map +1 -1
  30. package/dist/features/triggers/utils.js +25 -14
  31. package/dist/global.d.ts +9 -0
  32. package/dist/global.d.ts.map +1 -0
  33. package/dist/global.js +2 -0
  34. package/dist/index.d.ts +1 -1
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +13 -9
  37. package/dist/model.d.ts +1 -0
  38. package/dist/model.d.ts.map +1 -1
  39. package/dist/model.js +15 -0
  40. package/dist/services/api/index.d.ts.map +1 -1
  41. package/dist/services/api/index.js +6 -1
  42. package/dist/services/aws/index.d.ts.map +1 -1
  43. package/dist/services/aws/index.js +5 -5
  44. package/dist/services/index.d.ts.map +1 -1
  45. package/dist/services/mongodb-atlas/index.d.ts.map +1 -1
  46. package/dist/services/mongodb-atlas/index.js +76 -71
  47. package/dist/services/mongodb-atlas/model.d.ts +3 -3
  48. package/dist/services/mongodb-atlas/model.d.ts.map +1 -1
  49. package/dist/services/mongodb-atlas/utils.d.ts.map +1 -1
  50. package/dist/state.d.ts +2 -2
  51. package/dist/state.d.ts.map +1 -1
  52. package/dist/utils/context/helpers.d.ts +4 -4
  53. package/dist/utils/context/helpers.d.ts.map +1 -1
  54. package/dist/utils/context/helpers.js +1 -1
  55. package/dist/utils/context/index.d.ts.map +1 -1
  56. package/dist/utils/context/index.js +6 -5
  57. package/dist/utils/helpers/someAsync.d.ts.map +1 -1
  58. package/dist/utils/initializer/exposeRoutes.d.ts.map +1 -1
  59. package/dist/utils/initializer/exposeRoutes.js +44 -1
  60. package/dist/utils/initializer/registerPlugins.d.ts.map +1 -1
  61. package/dist/utils/initializer/registerPlugins.js +9 -9
  62. package/dist/utils/roles/helpers.d.ts.map +1 -1
  63. package/dist/utils/roles/helpers.js +9 -7
  64. package/dist/utils/roles/interface.d.ts.map +1 -1
  65. package/dist/utils/roles/machines/commonValidators.d.ts +2 -2
  66. package/dist/utils/roles/machines/commonValidators.d.ts.map +1 -1
  67. package/dist/utils/roles/machines/commonValidators.js +5 -6
  68. package/dist/utils/roles/machines/index.d.ts.map +1 -1
  69. package/dist/utils/roles/machines/interface.d.ts.map +1 -1
  70. package/dist/utils/roles/machines/machine.d.ts +3 -3
  71. package/dist/utils/roles/machines/machine.d.ts.map +1 -1
  72. package/dist/utils/roles/machines/machine.js +12 -4
  73. package/dist/utils/roles/machines/read/A/index.d.ts.map +1 -1
  74. package/dist/utils/roles/machines/read/A/index.js +12 -2
  75. package/dist/utils/roles/machines/read/B/index.d.ts.map +1 -1
  76. package/dist/utils/roles/machines/read/B/index.js +20 -5
  77. package/dist/utils/roles/machines/read/C/index.d.ts.map +1 -1
  78. package/dist/utils/roles/machines/read/C/index.js +20 -5
  79. package/dist/utils/roles/machines/read/D/index.d.ts.map +1 -1
  80. package/dist/utils/roles/machines/read/D/index.js +13 -3
  81. package/dist/utils/roles/machines/read/D/validators.d.ts +1 -1
  82. package/dist/utils/roles/machines/read/D/validators.d.ts.map +1 -1
  83. package/dist/utils/roles/machines/read/D/validators.js +8 -4
  84. package/dist/utils/roles/machines/utils.d.ts +4 -4
  85. package/dist/utils/roles/machines/utils.d.ts.map +1 -1
  86. package/dist/utils/roles/machines/utils.js +5 -1
  87. package/dist/utils/roles/machines/write/A/index.d.ts.map +1 -1
  88. package/dist/utils/roles/machines/write/A/index.js +13 -3
  89. package/dist/utils/roles/machines/write/B/index.d.ts.map +1 -1
  90. package/dist/utils/roles/machines/write/B/index.js +37 -10
  91. package/dist/utils/roles/machines/write/C/index.d.ts.map +1 -1
  92. package/dist/utils/roles/machines/write/C/index.js +13 -3
  93. package/dist/utils/roles/machines/write/C/validators.d.ts +1 -1
  94. package/dist/utils/roles/machines/write/C/validators.d.ts.map +1 -1
  95. package/dist/utils/roles/machines/write/C/validators.js +8 -4
  96. package/dist/utils/rules-matcher/interface.d.ts.map +1 -1
  97. package/dist/utils/rules-matcher/utils.d.ts.map +1 -1
  98. package/dist/utils/rules.d.ts.map +1 -1
  99. package/package.json +9 -2
  100. package/src/auth/controller.ts +12 -1
  101. package/src/auth/providers/local-userpass/controller.ts +47 -39
  102. package/src/auth/providers/local-userpass/dtos.ts +1 -1
  103. package/src/auth/utils.ts +24 -18
  104. package/src/constants.ts +7 -3
  105. package/src/features/endpoints/utils.ts +6 -4
  106. package/src/features/functions/controller.ts +23 -22
  107. package/src/features/functions/dtos.ts +9 -9
  108. package/src/features/functions/interface.ts +2 -1
  109. package/src/features/functions/utils.ts +12 -12
  110. package/src/features/triggers/index.ts +9 -6
  111. package/src/features/triggers/interface.ts +9 -10
  112. package/src/features/triggers/utils.ts +57 -29
  113. package/src/global.ts +9 -0
  114. package/src/index.ts +16 -11
  115. package/src/model.ts +3 -1
  116. package/src/services/api/index.ts +6 -1
  117. package/src/services/aws/index.ts +19 -17
  118. package/src/services/mongodb-atlas/index.ts +204 -163
  119. package/src/services/mongodb-atlas/model.ts +13 -13
  120. package/src/services/mongodb-atlas/utils.ts +6 -4
  121. package/src/state.ts +32 -20
  122. package/src/utils/__tests__/STEP_A_STATES.test.ts +78 -47
  123. package/src/utils/__tests__/STEP_B_STATES.test.ts +168 -105
  124. package/src/utils/__tests__/STEP_C_STATES.test.ts +150 -78
  125. package/src/utils/__tests__/STEP_D_STATES.test.ts +129 -86
  126. package/src/utils/__tests__/checkAdditionalFieldsFn.test.ts +35 -35
  127. package/src/utils/__tests__/checkApplyWhen.test.ts +40 -41
  128. package/src/utils/__tests__/checkFieldsPropertyExists.test.ts +40 -40
  129. package/src/utils/__tests__/checkIsValidFieldNameFn.test.ts +185 -184
  130. package/src/utils/__tests__/comparePassword.test.ts +27 -30
  131. package/src/utils/__tests__/evaluateDocumentsFiltersReadFn.test.ts +55 -47
  132. package/src/utils/__tests__/evaluateDocumentsFiltersWriteFn.test.ts +61 -47
  133. package/src/utils/__tests__/evaluateTopLevelReadFn.test.ts +48 -48
  134. package/src/utils/__tests__/evaluateTopLevelWriteFn.test.ts +56 -56
  135. package/src/utils/__tests__/exposeRoutes.test.ts +46 -44
  136. package/src/utils/__tests__/generateContextData.test.ts +57 -51
  137. package/src/utils/__tests__/getDefaultRule.test.ts +32 -27
  138. package/src/utils/__tests__/getKey.test.ts +10 -10
  139. package/src/utils/__tests__/getKeys.test.ts +10 -9
  140. package/src/utils/__tests__/getWinningRole.test.ts +57 -50
  141. package/src/utils/__tests__/hashPassword.test.ts +24 -25
  142. package/src/utils/__tests__/isEmpty.test.ts +14 -15
  143. package/src/utils/__tests__/logMachineInfo.test.ts +12 -12
  144. package/src/utils/__tests__/operators.test.ts +94 -96
  145. package/src/utils/__tests__/readFileContent.test.ts +28 -28
  146. package/src/utils/__tests__/registerPlugins.test.ts +44 -32
  147. package/src/utils/__tests__/rule.test.ts +47 -49
  148. package/src/utils/__tests__/rulesMatcherInterfaces.test.ts +57 -52
  149. package/src/utils/__tests__/rulesMatcherUtils.test.ts +64 -53
  150. package/src/utils/__tests__/someAsync.test.ts +46 -49
  151. package/src/utils/context/helpers.ts +1 -1
  152. package/src/utils/context/index.ts +9 -10
  153. package/src/utils/crypto/index.ts +2 -2
  154. package/src/utils/helpers/someAsync.ts +11 -11
  155. package/src/utils/initializer/exposeRoutes.ts +56 -2
  156. package/src/utils/initializer/registerPlugins.ts +11 -13
  157. package/src/utils/roles/helpers.ts +22 -15
  158. package/src/utils/roles/interface.ts +2 -3
  159. package/src/utils/roles/machines/commonValidators.ts +23 -14
  160. package/src/utils/roles/machines/index.ts +7 -4
  161. package/src/utils/roles/machines/interface.ts +17 -5
  162. package/src/utils/roles/machines/machine.ts +97 -72
  163. package/src/utils/roles/machines/read/A/index.ts +12 -4
  164. package/src/utils/roles/machines/read/B/index.ts +20 -7
  165. package/src/utils/roles/machines/read/C/index.ts +24 -8
  166. package/src/utils/roles/machines/read/D/index.ts +14 -8
  167. package/src/utils/roles/machines/read/D/validators.ts +21 -13
  168. package/src/utils/roles/machines/read/index.ts +5 -5
  169. package/src/utils/roles/machines/utils.ts +30 -13
  170. package/src/utils/roles/machines/write/A/index.ts +13 -5
  171. package/src/utils/roles/machines/write/B/index.ts +42 -16
  172. package/src/utils/roles/machines/write/C/index.ts +14 -8
  173. package/src/utils/roles/machines/write/C/validators.ts +21 -13
  174. package/src/utils/roles/machines/write/index.ts +4 -4
  175. package/src/utils/rules-matcher/interface.ts +4 -4
  176. package/src/utils/rules-matcher/utils.ts +10 -6
  177. package/src/utils/rules.ts +12 -5
  178. package/src/global.d.ts +0 -0
@@ -1,6 +1,9 @@
1
1
  import { uptime } from 'node:process'
2
2
  import { FastifyInstance } from 'fastify'
3
- import { API_VERSION, DEFAULT_CONFIG } from '../../constants'
3
+ import { RegistrationDto } from '../../auth/providers/local-userpass/dtos'
4
+ import { AUTH_ENDPOINTS, PROVIDER_TYPE, REGISTRATION_SCHEMA } from '../../auth/utils'
5
+ import { API_VERSION, AUTH_CONFIG, DB_NAME, DEFAULT_CONFIG } from '../../constants'
6
+ import { hashPassword } from '../crypto'
4
7
 
5
8
  /**
6
9
  * > Used to expose all app routes
@@ -13,14 +16,65 @@ export const exposeRoutes = async (fastify: FastifyInstance) => {
13
16
  deployment_model: 'LOCAL',
14
17
  location: 'IE',
15
18
  hostname: `${DEFAULT_CONFIG.HTTPS_SCHEMA}://${req.headers.host}`,
16
- ws_hostname: `${DEFAULT_CONFIG.HTTPS_SCHEMA === "https" ? "wss" : "ws"}://${req.headers.host}`
19
+ ws_hostname: `${DEFAULT_CONFIG.HTTPS_SCHEMA === 'https' ? 'wss' : 'ws'}://${req.headers.host}`
17
20
  }))
18
21
 
19
22
  fastify.get('/health', async () => ({
20
23
  status: 'ok',
21
24
  uptime: uptime()
22
25
  }))
26
+
27
+ fastify.post<RegistrationDto>(AUTH_ENDPOINTS.FIRST_USER, {
28
+ schema: REGISTRATION_SCHEMA
29
+ }, async function (req, res) {
30
+ const { authCollection } = AUTH_CONFIG
31
+ const db = fastify.mongo.client.db(DB_NAME)
32
+ const { email, password } = req.body
33
+ const hashedPassword = await hashPassword(password)
34
+
35
+ const users = db.collection(authCollection!).find()
36
+
37
+ const list = await users?.toArray()
38
+
39
+ if (list?.length) {
40
+ res.status(409)
41
+ return {
42
+ error: `The ${authCollection} collection is not empty`
43
+ }
44
+ }
45
+
46
+ const result = await db.collection(authCollection!).insertOne({
47
+ email: email,
48
+ password: hashedPassword,
49
+ custom_data: {}
50
+ })
51
+
52
+ await db?.collection(authCollection!).updateOne(
53
+ {
54
+ email: email
55
+ },
56
+ {
57
+ $set: {
58
+ identities: [
59
+ {
60
+ id: result?.insertedId.toString(),
61
+ provider_id: result?.insertedId.toString(),
62
+ provider_type: PROVIDER_TYPE,
63
+ provider_data: { email }
64
+ }
65
+ ]
66
+ }
67
+ }
68
+ )
69
+
70
+ res.status(201)
71
+ return {
72
+ userId: result?.insertedId
73
+ }
74
+ })
23
75
  } catch (e) {
24
76
  console.error('Error while exposing routes', (e as Error).message)
25
77
  }
26
78
  }
79
+
80
+
@@ -46,13 +46,11 @@ export const registerPlugins = async ({
46
46
  registersConfig.forEach(({ plugin, options, pluginName }) => {
47
47
  try {
48
48
  register(plugin, options)
49
- console.log("registration COMPLETED --->", pluginName)
49
+ console.log('registration COMPLETED --->', pluginName)
50
+ } catch (e) {
51
+ console.log('Registration FAILED --->', pluginName)
52
+ console.log('Error --->', e)
50
53
  }
51
- catch (e) {
52
- console.log("Registration FAILED --->", pluginName)
53
- console.log("Error --->", e)
54
- }
55
-
56
54
  })
57
55
  } catch (e) {
58
56
  console.error('Error while registering plugins', (e as Error).message)
@@ -63,7 +61,7 @@ export const registerPlugins = async ({
63
61
  * > Used to generate the register congig
64
62
  * @param mongodbUrl -> the database connection string
65
63
  * @param jwtSecret -> connection jwt
66
- * @testable
64
+ * @testable
67
65
  */
68
66
  const getRegisterConfig = async ({
69
67
  mongodbUrl,
@@ -73,15 +71,15 @@ const getRegisterConfig = async ({
73
71
  > => {
74
72
  return [
75
73
  {
76
- pluginName: "cors",
74
+ pluginName: 'cors',
77
75
  plugin: cors,
78
76
  options: {
79
77
  origin: '*',
80
- methods: ['POST', 'GET']
78
+ methods: ['POST', 'GET', 'DELETE']
81
79
  }
82
80
  },
83
81
  {
84
- pluginName: "fastifyMongodb",
82
+ pluginName: 'fastifyMongodb',
85
83
  plugin: fastifyMongodb,
86
84
  options: {
87
85
  forceClose: true,
@@ -89,19 +87,19 @@ const getRegisterConfig = async ({
89
87
  }
90
88
  },
91
89
  {
92
- pluginName: "jwtAuthPlugin",
90
+ pluginName: 'jwtAuthPlugin',
93
91
  plugin: jwtAuthPlugin,
94
92
  options: {
95
93
  secret: jwtSecret
96
94
  }
97
95
  },
98
96
  {
99
- pluginName: "authController",
97
+ pluginName: 'authController',
100
98
  plugin: authController,
101
99
  options: { prefix: `${API_VERSION}/auth` }
102
100
  },
103
101
  {
104
- pluginName: "localUserPassController",
102
+ pluginName: 'localUserPassController',
105
103
  plugin: localUserPassController,
106
104
  options: {
107
105
  prefix: `${API_VERSION}/app/:appId/auth/providers/local-userpass`
@@ -6,29 +6,40 @@ import rulesMatcherUtils from '../rules-matcher/utils'
6
6
  import { PermissionExpression } from './interface'
7
7
  import { MachineContext } from './machines/interface'
8
8
 
9
- const functionsConditions = ["%%true", "%%false"]
9
+ const functionsConditions = ['%%true', '%%false']
10
10
 
11
- export const evaluateExpression = async (params: MachineContext["params"], expression?: PermissionExpression, user?: MachineContext["user"]): Promise<boolean> => {
11
+ export const evaluateExpression = async (
12
+ params: MachineContext['params'],
13
+ expression?: PermissionExpression,
14
+ user?: MachineContext['user']
15
+ ): Promise<boolean> => {
12
16
  if (!expression || typeof expression === 'boolean') return !!expression
13
17
 
14
18
  const value = {
15
19
  ...params.expansions,
16
20
  ...params.cursor,
17
- "%%user": user,
21
+ '%%user': user,
18
22
  '%%true': true
19
23
  }
20
24
  const conditions = expandQuery(expression, value)
21
- const complexCondition = Object.entries<Record<string, any>>(conditions).find(([key]) => functionsConditions.includes(key))
22
- return complexCondition ? await evaluateComplexExpression(complexCondition, params, user) : rulesMatcherUtils.checkRule(conditions, value, {})
23
-
25
+ const complexCondition = Object.entries<Record<string, any>>(conditions).find(([key]) =>
26
+ functionsConditions.includes(key)
27
+ )
28
+ return complexCondition
29
+ ? await evaluateComplexExpression(complexCondition, params, user)
30
+ : rulesMatcherUtils.checkRule(conditions, value, {})
24
31
  }
25
32
 
26
- const evaluateComplexExpression = async (condition: [string, Record<string, any>], params: MachineContext["params"], user: MachineContext["user"]) => {
33
+ const evaluateComplexExpression = async (
34
+ condition: [string, Record<string, any>],
35
+ params: MachineContext['params'],
36
+ user: MachineContext['user']
37
+ ) => {
27
38
  const [key, config] = condition
28
39
 
29
- const { name } = config["%function"]
30
- const functionsList = StateManager.select("functions")
31
- const app = StateManager.select("app")
40
+ const { name } = config['%function']
41
+ const functionsList = StateManager.select('functions')
42
+ const app = StateManager.select('app')
32
43
  const currentFunction = functionsList[name]
33
44
  const response = await GenerateContext({
34
45
  args: [params.cursor],
@@ -39,9 +50,5 @@ const evaluateComplexExpression = async (condition: [string, Record<string, any>
39
50
  functionsList,
40
51
  services
41
52
  })
42
- return key === "%%true" ? response : !response
43
-
53
+ return key === '%%true' ? response : !response
44
54
  }
45
-
46
-
47
-
@@ -1,7 +1,7 @@
1
1
  export type PermissionExpression = boolean // TODO: add complex condition (%%true: %function)
2
2
 
3
3
  export type FieldPermissionExpression = {
4
- read?: boolean,
4
+ read?: boolean
5
5
  write?: boolean
6
6
  }
7
7
 
@@ -37,6 +37,5 @@ export interface Params {
37
37
  type: 'insert' | 'read' | 'delete' | 'search' | 'write'
38
38
  }
39
39
 
40
-
41
40
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
- export type Condition = Record<string, any>
41
+ export type Condition = Record<string, any>
@@ -1,24 +1,33 @@
1
- import { someAsync } from "../../helpers/someAsync"
2
- import { evaluateExpression } from "../helpers"
3
- import { DocumentFiltersPermissions } from "../interface"
4
- import { MachineContext } from "./interface"
1
+ import { someAsync } from '../../helpers/someAsync'
2
+ import { evaluateExpression } from '../helpers'
3
+ import { DocumentFiltersPermissions } from '../interface'
4
+ import { MachineContext } from './interface'
5
5
 
6
6
  const readOnlyPermissions = ['read']
7
7
  const readWritePermissions = ['write', 'delete', 'insert', ...readOnlyPermissions]
8
8
 
9
- export const evaluateDocumentFiltersFn = async ({ params, role, user }: MachineContext, currentType: keyof DocumentFiltersPermissions) => {
10
- const permissions = currentType === "read" ? readOnlyPermissions : readWritePermissions
11
- return await someAsync([
12
- permissions.includes(params.type) && role.document_filters?.[currentType]
13
- ]
14
- .filter(Boolean), async (expr) => evaluateExpression(params, expr, user))
9
+ export const evaluateDocumentFiltersFn = async (
10
+ { params, role, user }: MachineContext,
11
+ currentType: keyof DocumentFiltersPermissions
12
+ ) => {
13
+ const permissions = currentType === 'read' ? readOnlyPermissions : readWritePermissions
14
+ return await someAsync(
15
+ [permissions.includes(params.type) && role.document_filters?.[currentType]].filter(
16
+ Boolean
17
+ ),
18
+ async (expr) => evaluateExpression(params, expr, user)
19
+ )
15
20
  }
16
21
 
17
-
18
- export const evaluateTopLevelPermissionsFn = async ({ params, role, user }: MachineContext, currentType: MachineContext["params"]["type"]) => {
19
- return role[currentType] ? await evaluateExpression(params, role[currentType], user) : undefined
22
+ export const evaluateTopLevelPermissionsFn = async (
23
+ { params, role, user }: MachineContext,
24
+ currentType: MachineContext['params']['type']
25
+ ) => {
26
+ return role[currentType]
27
+ ? await evaluateExpression(params, role[currentType], user)
28
+ : undefined
20
29
  }
21
30
 
22
31
  export const checkFieldsPropertyExists = ({ role }: MachineContext) => {
23
- return !!Object.keys(role.fields ?? {}).length
32
+ return !!Object.keys(role.fields ?? {}).length
24
33
  }
@@ -9,12 +9,15 @@ import { StateMachine } from './machine'
9
9
  * @param {Role} role - The role configuration for validation.
10
10
  * @param {Params} params - The parameters relevant to the validation process.
11
11
  * @param {User} user - The user for whom the validation is being performed.
12
- *
12
+ *
13
13
  * @returns {Promise<StepResult>} - The result of the state machine's validation process.
14
14
  */
15
- export const checkValidation = async (role: Role, params: Params, user: User, enableLog?: boolean): Promise<StepResult> => {
15
+ export const checkValidation = async (
16
+ role: Role,
17
+ params: Params,
18
+ user: User,
19
+ enableLog?: boolean
20
+ ): Promise<StepResult> => {
16
21
  const stateMachine = new StateMachine(role, params, user, enableLog)
17
22
  return await stateMachine.runValidation()
18
23
  }
19
-
20
-
@@ -17,7 +17,13 @@ type StateFunction = (
17
17
  context: MachineContext
18
18
  } & {
19
19
  next: (step: string, params?: Record<string, any>) => void
20
- endValidation: ({ success, document }: { success: boolean, document?: Document }) => void
20
+ endValidation: ({
21
+ success,
22
+ document
23
+ }: {
24
+ success: boolean
25
+ document?: Document
26
+ }) => void
21
27
  goToNextValidationStage: (initialStep?: string | null) => void
22
28
  }
23
29
  ) => Promise<void>
@@ -33,14 +39,20 @@ export interface ValidationStatus {
33
39
  document?: Document
34
40
  }
35
41
 
42
+ export interface StepResult {
43
+ status: boolean | null
44
+ nextInitialStep: string | null
45
+ document?: Document
46
+ }
36
47
 
37
- export interface StepResult { status: boolean | null; nextInitialStep: string | null; document?: Document }
38
-
39
- export interface EndValidationParams { success: boolean, document?: Document }
48
+ export interface EndValidationParams {
49
+ success: boolean
50
+ document?: Document
51
+ }
40
52
 
41
53
  export type LogMachineInfoParams = {
42
54
  enabled?: boolean
43
55
  machine: string
44
56
  step: number
45
57
  stepName: string
46
- }
58
+ }
@@ -1,85 +1,110 @@
1
- import { Document } from "mongodb"
2
- import { User } from "../../../auth/dtos";
3
- import { Params, Role } from "../interface";
4
- import { MachineContext, PrevParams, States, StepResult, ValidationStatus } from "./interface";
5
- import { READ_MACHINE } from "./read";
6
- import { WRITE_MACHINE } from "./write";
1
+ import { Document } from 'mongodb'
2
+ import { User } from '../../../auth/dtos'
3
+ import { Params, Role } from '../interface'
4
+ import {
5
+ MachineContext,
6
+ PrevParams,
7
+ States,
8
+ StepResult,
9
+ ValidationStatus
10
+ } from './interface'
11
+ import { READ_MACHINE } from './read'
12
+ import { WRITE_MACHINE } from './write'
7
13
 
8
14
  export class StateMachine {
9
- private _context: MachineContext
10
- private _validation: StepResult = {
11
- status: null,
12
- nextInitialStep: null
13
- }
14
- private _machines: States[]
15
- private _currentStep: {
16
- names: readonly string[]
17
- states: States
18
- validation: ValidationStatus,
19
- completed?: boolean,
20
- initialStep: string | null
21
- }
22
- constructor(role: Role, params: Params, user: User, enableLog?: boolean) {
23
- this._context = { role, params, user, enableLog }
24
- this._machines = params.type === "read" ? READ_MACHINE : WRITE_MACHINE
25
- this._currentStep = {
26
- names: [],
27
- states: {},
28
- validation: {
29
- status: null
30
- },
31
- initialStep: null
32
- }
15
+ private _context: MachineContext
16
+ private _validation: StepResult = {
17
+ status: null,
18
+ nextInitialStep: null
19
+ }
20
+ private _machines: States[]
21
+ private _currentStep: {
22
+ names: readonly string[]
23
+ states: States
24
+ validation: ValidationStatus
25
+ completed?: boolean
26
+ initialStep: string | null
27
+ }
28
+ constructor(role: Role, params: Params, user: User, enableLog?: boolean) {
29
+ this._context = { role, params, user, enableLog }
30
+ this._machines = params.type === 'read' ? READ_MACHINE : WRITE_MACHINE
31
+ this._currentStep = {
32
+ names: [],
33
+ states: {},
34
+ validation: {
35
+ status: null
36
+ },
37
+ initialStep: null
33
38
  }
39
+ }
34
40
 
35
- async runValidation() {
36
- for await (const machine of this._machines) {
37
- this._currentStep = { names: Object.freeze(Object.keys(machine)) as readonly (keyof typeof machine)[], states: machine, validation: { status: null }, initialStep: null }
38
- await this.runMachine(this._validation.nextInitialStep);
41
+ async runValidation() {
42
+ for await (const machine of this._machines) {
43
+ this._currentStep = {
44
+ names: Object.freeze(Object.keys(machine)) as readonly (keyof typeof machine)[],
45
+ states: machine,
46
+ validation: { status: null },
47
+ initialStep: null
48
+ }
49
+ await this.runMachine(this._validation.nextInitialStep)
39
50
 
40
- this._validation.nextInitialStep = this._currentStep.initialStep;
41
- if (this._currentStep.validation.status !== null) {
42
- this._validation.status = this._currentStep.validation.status;
43
- this._validation.document = this._currentStep.validation.document;
44
- break;
45
- }
46
- }
47
- return this._validation;
51
+ this._validation.nextInitialStep = this._currentStep.initialStep
52
+ if (this._currentStep.validation.status !== null) {
53
+ this._validation.status = this._currentStep.validation.status
54
+ this._validation.document = this._currentStep.validation.document
55
+ break
56
+ }
48
57
  }
58
+ return this._validation
59
+ }
49
60
 
50
- private async runMachine(initialStep: string | null) {
51
- const executeStep = async (step: keyof typeof this._currentStep.states, params?: PrevParams) => {
52
- const currentStep = this._currentStep.states[step]
53
- const next = (nextStep: keyof typeof this._currentStep.states, params?: PrevParams) =>
54
- executeStep(nextStep, params)
55
-
56
- await currentStep({
57
- context: { ...this._context, prevParams: params },
58
- next,
59
- endValidation: this.endValidation.bind(this),
60
- goToNextValidationStage: this.goToNextValidationStage.bind(this),
61
- initialStep
62
- })
61
+ private async runMachine(initialStep: string | null) {
62
+ const executeStep = async (
63
+ step: keyof typeof this._currentStep.states,
64
+ params?: PrevParams
65
+ ) => {
66
+ const currentStep = this._currentStep.states[step]
67
+ const next = (
68
+ nextStep: keyof typeof this._currentStep.states,
69
+ params?: PrevParams
70
+ ) => executeStep(nextStep, params)
63
71
 
64
- if (this._currentStep.validation.status !== null || this._currentStep.completed !== undefined)
65
- return { isValid: this._currentStep.validation.status, ...this._currentStep }
66
- }
67
- const nextStep = initialStep && this._currentStep.states[initialStep] ? initialStep : this._currentStep.names[0]
68
- await executeStep(nextStep)
69
- }
72
+ await currentStep({
73
+ context: { ...this._context, prevParams: params },
74
+ next,
75
+ endValidation: this.endValidation.bind(this),
76
+ goToNextValidationStage: this.goToNextValidationStage.bind(this),
77
+ initialStep
78
+ })
70
79
 
71
- private endValidation({ success, document }: { success: boolean, document?: Document }) {
72
- this._currentStep.validation.status = success
73
- if (success) {
74
- this._currentStep.validation.document = document || this._context.params.cursor
75
- }
80
+ if (
81
+ this._currentStep.validation.status !== null ||
82
+ this._currentStep.completed !== undefined
83
+ )
84
+ return { isValid: this._currentStep.validation.status, ...this._currentStep }
76
85
  }
86
+ const nextStep =
87
+ initialStep && this._currentStep.states[initialStep]
88
+ ? initialStep
89
+ : this._currentStep.names[0]
90
+ await executeStep(nextStep)
91
+ }
77
92
 
78
-
79
- private goToNextValidationStage(initialStep: string | null = null) {
80
- this._currentStep.completed = true
81
- this._currentStep.initialStep = initialStep
93
+ private endValidation({
94
+ success,
95
+ document
96
+ }: {
97
+ success: boolean
98
+ document?: Document
99
+ }) {
100
+ this._currentStep.validation.status = success
101
+ if (success) {
102
+ this._currentStep.validation.document = document || this._context.params.cursor
82
103
  }
104
+ }
83
105
 
84
-
85
- }
106
+ private goToNextValidationStage(initialStep: string | null = null) {
107
+ this._currentStep.completed = true
108
+ this._currentStep.initialStep = initialStep
109
+ }
110
+ }
@@ -3,17 +3,25 @@ import { logMachineInfo } from '../../utils'
3
3
 
4
4
  export const STEP_A_STATES: States = {
5
5
  checkSearchRequest: async ({ context, next, goToNextValidationStage }) => {
6
- logMachineInfo({ enabled: context.enableLog, machine: "A", step: 1, stepName: "checkSearchRequest" })
6
+ logMachineInfo({
7
+ enabled: context.enableLog,
8
+ machine: 'A',
9
+ step: 1,
10
+ stepName: 'checkSearchRequest'
11
+ })
7
12
  if (context.params.type === 'search') {
8
13
  return next('evaluateSearch')
9
14
  }
10
15
  return goToNextValidationStage()
11
16
  },
12
17
  evaluateSearch: async ({ context, endValidation }) => {
13
- logMachineInfo({ enabled: context.enableLog, machine: "A", step: 2, stepName: "evaluateSearch" })
18
+ logMachineInfo({
19
+ enabled: context.enableLog,
20
+ machine: 'A',
21
+ step: 2,
22
+ stepName: 'evaluateSearch'
23
+ })
14
24
  // NOTE -> we don't support search operations
15
25
  return endValidation({ success: false })
16
26
  }
17
27
  }
18
-
19
-
@@ -4,7 +4,12 @@ import { logMachineInfo } from '../../utils'
4
4
 
5
5
  export const STEP_B_STATES: States = {
6
6
  checkDocumentsFilters: async ({ context, next, goToNextValidationStage }) => {
7
- logMachineInfo({ enabled: context.enableLog, machine: "B", step: 1, stepName: "checkDocumentsFilters" })
7
+ logMachineInfo({
8
+ enabled: context.enableLog,
9
+ machine: 'B',
10
+ step: 1,
11
+ stepName: 'checkDocumentsFilters'
12
+ })
8
13
  const { role } = context
9
14
  if (role.document_filters) {
10
15
  return next('evaluateDocumentsFiltersRead')
@@ -12,8 +17,13 @@ export const STEP_B_STATES: States = {
12
17
  return goToNextValidationStage()
13
18
  },
14
19
  evaluateDocumentsFiltersRead: async ({ context, next, goToNextValidationStage }) => {
15
- logMachineInfo({ enabled: context.enableLog, machine: "B", step: 2, stepName: "evaluateDocumentsFiltersRead" })
16
- const hasDocumentFiltersRead = await evaluateDocumentFiltersFn(context, "read")
20
+ logMachineInfo({
21
+ enabled: context.enableLog,
22
+ machine: 'B',
23
+ step: 2,
24
+ stepName: 'evaluateDocumentsFiltersRead'
25
+ })
26
+ const hasDocumentFiltersRead = await evaluateDocumentFiltersFn(context, 'read')
17
27
  if (!hasDocumentFiltersRead) return next('evaluateDocumentsFiltersWrite')
18
28
  return goToNextValidationStage()
19
29
  },
@@ -22,10 +32,13 @@ export const STEP_B_STATES: States = {
22
32
  endValidation,
23
33
  goToNextValidationStage
24
34
  }) => {
25
- logMachineInfo({ enabled: context.enableLog, machine: "B", step: 3, stepName: "evaluateDocumentsFiltersWrite" })
26
- const check = await evaluateDocumentFiltersFn(context, "write")
35
+ logMachineInfo({
36
+ enabled: context.enableLog,
37
+ machine: 'B',
38
+ step: 3,
39
+ stepName: 'evaluateDocumentsFiltersWrite'
40
+ })
41
+ const check = await evaluateDocumentFiltersFn(context, 'write')
27
42
  return check ? goToNextValidationStage() : endValidation({ success: false })
28
43
  }
29
44
  }
30
-
31
-
@@ -1,30 +1,46 @@
1
- import { checkFieldsPropertyExists, evaluateTopLevelPermissionsFn } from '../../commonValidators'
1
+ import {
2
+ checkFieldsPropertyExists,
3
+ evaluateTopLevelPermissionsFn
4
+ } from '../../commonValidators'
2
5
  import { States } from '../../interface'
3
6
  import { logMachineInfo } from '../../utils'
4
7
 
5
-
6
8
  export const STEP_C_STATES: States = {
7
9
  evaluateTopLevelRead: async ({ context, next, endValidation }) => {
8
- logMachineInfo({ enabled: context.enableLog, machine: "C", step: 1, stepName: "evaluateTopLevelRead" })
9
- const check = await evaluateTopLevelPermissionsFn(context, "read")
10
+ logMachineInfo({
11
+ enabled: context.enableLog,
12
+ machine: 'C',
13
+ step: 1,
14
+ stepName: 'evaluateTopLevelRead'
15
+ })
16
+ const check = await evaluateTopLevelPermissionsFn(context, 'read')
10
17
  return check
11
18
  ? endValidation({ success: true })
12
19
  : next('evaluateTopLevelWrite', { check })
13
20
  },
14
21
  evaluateTopLevelWrite: async ({ context, next, endValidation }) => {
15
- logMachineInfo({ enabled: context.enableLog, machine: "C", step: 2, stepName: "evaluateTopLevelWrite" })
16
- const check = await evaluateTopLevelPermissionsFn(context, "write")
22
+ logMachineInfo({
23
+ enabled: context.enableLog,
24
+ machine: 'C',
25
+ step: 2,
26
+ stepName: 'evaluateTopLevelWrite'
27
+ })
28
+ const check = await evaluateTopLevelPermissionsFn(context, 'write')
17
29
  if (check) return endValidation({ success: true })
18
30
  return context?.prevParams?.check === false
19
31
  ? endValidation({ success: false })
20
32
  : next('checkFieldsProperty')
21
33
  },
22
34
  checkFieldsProperty: async ({ context, goToNextValidationStage }) => {
23
- logMachineInfo({ enabled: context.enableLog, machine: "C", step: 3, stepName: "checkFieldsProperty" })
35
+ logMachineInfo({
36
+ enabled: context.enableLog,
37
+ machine: 'C',
38
+ step: 3,
39
+ stepName: 'checkFieldsProperty'
40
+ })
24
41
  const check = checkFieldsPropertyExists(context)
25
42
  return goToNextValidationStage(
26
43
  check ? 'checkIsValidFieldName' : 'checkAdditionalFields'
27
44
  )
28
45
  }
29
46
  }
30
-