@blazedpath/commons 0.0.4

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 (224) hide show
  1. package/README.md +3 -0
  2. package/blz-base/health/index.js +215 -0
  3. package/blz-base/index.js +1466 -0
  4. package/blz-cache/LruCache.js +44 -0
  5. package/blz-cache/index.js +29 -0
  6. package/blz-config/index.js +434 -0
  7. package/blz-core/index.js +364 -0
  8. package/blz-cryptography/index.js +54 -0
  9. package/blz-datetimes/index.js +356 -0
  10. package/blz-file/example.dat +2545 -0
  11. package/blz-file/fileService.js +205 -0
  12. package/blz-file/index.js +94 -0
  13. package/blz-file/index.test.js +31 -0
  14. package/blz-file/lab.js +33 -0
  15. package/blz-hazelcast/index.js +189 -0
  16. package/blz-hazelcast/lib/credentials.js +25 -0
  17. package/blz-hazelcast/lib/credentialsFactory.js +12 -0
  18. package/blz-hazelcast/lib/hazelcastCache.js +234 -0
  19. package/blz-iterable/index.js +446 -0
  20. package/blz-json-schema/index.js +11 -0
  21. package/blz-jwt/index.js +121 -0
  22. package/blz-kafka/index.js +522 -0
  23. package/blz-math/index.js +131 -0
  24. package/blz-mongodb/index.js +326 -0
  25. package/blz-rds/__test__/scape.test.js +58 -0
  26. package/blz-rds/blz-rds-executor.js +578 -0
  27. package/blz-rds/blz-rds-helper.js +310 -0
  28. package/blz-rds/commands/core/add.js +13 -0
  29. package/blz-rds/commands/core/and.js +18 -0
  30. package/blz-rds/commands/core/asc.js +10 -0
  31. package/blz-rds/commands/core/avg.js +10 -0
  32. package/blz-rds/commands/core/column-ref.js +8 -0
  33. package/blz-rds/commands/core/count-distinct.js +10 -0
  34. package/blz-rds/commands/core/count.js +10 -0
  35. package/blz-rds/commands/core/decimal.js +8 -0
  36. package/blz-rds/commands/core/desc.js +10 -0
  37. package/blz-rds/commands/core/distinct.js +10 -0
  38. package/blz-rds/commands/core/divide.js +11 -0
  39. package/blz-rds/commands/core/embedded-exists.js +17 -0
  40. package/blz-rds/commands/core/embedded-select.js +17 -0
  41. package/blz-rds/commands/core/equals.js +9 -0
  42. package/blz-rds/commands/core/false.js +8 -0
  43. package/blz-rds/commands/core/greater-or-equal.js +9 -0
  44. package/blz-rds/commands/core/greater.js +9 -0
  45. package/blz-rds/commands/core/in.js +9 -0
  46. package/blz-rds/commands/core/integer.js +8 -0
  47. package/blz-rds/commands/core/is-not-null.js +11 -0
  48. package/blz-rds/commands/core/is-null-or-value.js +10 -0
  49. package/blz-rds/commands/core/is-null.js +11 -0
  50. package/blz-rds/commands/core/less-or-equal.js +9 -0
  51. package/blz-rds/commands/core/less-unary.js +12 -0
  52. package/blz-rds/commands/core/less.js +9 -0
  53. package/blz-rds/commands/core/like.js +12 -0
  54. package/blz-rds/commands/core/max.js +10 -0
  55. package/blz-rds/commands/core/min.js +10 -0
  56. package/blz-rds/commands/core/multiply.js +13 -0
  57. package/blz-rds/commands/core/not-equals.js +9 -0
  58. package/blz-rds/commands/core/not-in.js +9 -0
  59. package/blz-rds/commands/core/not.js +13 -0
  60. package/blz-rds/commands/core/null.js +8 -0
  61. package/blz-rds/commands/core/nvl.js +11 -0
  62. package/blz-rds/commands/core/or.js +13 -0
  63. package/blz-rds/commands/core/parameter.js +34 -0
  64. package/blz-rds/commands/core/remainder.js +16 -0
  65. package/blz-rds/commands/core/string.js +8 -0
  66. package/blz-rds/commands/core/subtract.js +13 -0
  67. package/blz-rds/commands/core/sum.js +10 -0
  68. package/blz-rds/commands/core/true.js +8 -0
  69. package/blz-rds/commands/core/tuple.js +13 -0
  70. package/blz-rds/commands/datetimes/add-days.js +11 -0
  71. package/blz-rds/commands/datetimes/add-hours.js +11 -0
  72. package/blz-rds/commands/datetimes/add-milliseconds.js +11 -0
  73. package/blz-rds/commands/datetimes/add-minutes.js +11 -0
  74. package/blz-rds/commands/datetimes/add-months.js +11 -0
  75. package/blz-rds/commands/datetimes/add-seconds.js +11 -0
  76. package/blz-rds/commands/datetimes/add-years.js +11 -0
  77. package/blz-rds/commands/datetimes/date-diff.js +11 -0
  78. package/blz-rds/commands/datetimes/date.js +12 -0
  79. package/blz-rds/commands/datetimes/datetime-diff.js +11 -0
  80. package/blz-rds/commands/datetimes/datetime.js +15 -0
  81. package/blz-rds/commands/datetimes/day.js +10 -0
  82. package/blz-rds/commands/datetimes/hour.js +10 -0
  83. package/blz-rds/commands/datetimes/millisecond.js +10 -0
  84. package/blz-rds/commands/datetimes/minute.js +10 -0
  85. package/blz-rds/commands/datetimes/month-text.js +10 -0
  86. package/blz-rds/commands/datetimes/month.js +10 -0
  87. package/blz-rds/commands/datetimes/now.js +9 -0
  88. package/blz-rds/commands/datetimes/second.js +10 -0
  89. package/blz-rds/commands/datetimes/subtract-days.js +11 -0
  90. package/blz-rds/commands/datetimes/subtract-hours.js +11 -0
  91. package/blz-rds/commands/datetimes/subtract-milliseconds.js +11 -0
  92. package/blz-rds/commands/datetimes/subtract-minutes.js +11 -0
  93. package/blz-rds/commands/datetimes/subtract-seconds.js +11 -0
  94. package/blz-rds/commands/datetimes/time-diff.js +11 -0
  95. package/blz-rds/commands/datetimes/time.js +13 -0
  96. package/blz-rds/commands/datetimes/today.js +9 -0
  97. package/blz-rds/commands/datetimes/week-day-text.js +10 -0
  98. package/blz-rds/commands/datetimes/week-day.js +10 -0
  99. package/blz-rds/commands/datetimes/week.js +10 -0
  100. package/blz-rds/commands/datetimes/year.js +10 -0
  101. package/blz-rds/commands/math/abs.js +10 -0
  102. package/blz-rds/commands/math/acos.js +10 -0
  103. package/blz-rds/commands/math/asin.js +10 -0
  104. package/blz-rds/commands/math/atan.js +10 -0
  105. package/blz-rds/commands/math/atan2.js +11 -0
  106. package/blz-rds/commands/math/ceil.js +10 -0
  107. package/blz-rds/commands/math/cos.js +10 -0
  108. package/blz-rds/commands/math/cosh.js +10 -0
  109. package/blz-rds/commands/math/exp.js +10 -0
  110. package/blz-rds/commands/math/floor.js +10 -0
  111. package/blz-rds/commands/math/log.js +18 -0
  112. package/blz-rds/commands/math/log10.js +10 -0
  113. package/blz-rds/commands/math/pow.js +11 -0
  114. package/blz-rds/commands/math/random.js +9 -0
  115. package/blz-rds/commands/math/round.js +18 -0
  116. package/blz-rds/commands/math/sign.js +10 -0
  117. package/blz-rds/commands/math/sin.js +10 -0
  118. package/blz-rds/commands/math/sinh.js +10 -0
  119. package/blz-rds/commands/math/sqrt.js +10 -0
  120. package/blz-rds/commands/math/tan.js +10 -0
  121. package/blz-rds/commands/math/tanh.js +10 -0
  122. package/blz-rds/commands/math/trunc.js +18 -0
  123. package/blz-rds/commands/strings/concat.js +20 -0
  124. package/blz-rds/commands/strings/contains.js +12 -0
  125. package/blz-rds/commands/strings/ends-with.js +12 -0
  126. package/blz-rds/commands/strings/index-of.js +11 -0
  127. package/blz-rds/commands/strings/is-null-or-empty.js +11 -0
  128. package/blz-rds/commands/strings/is-null-or-white-space.js +11 -0
  129. package/blz-rds/commands/strings/join.js +22 -0
  130. package/blz-rds/commands/strings/last-index-of.js +11 -0
  131. package/blz-rds/commands/strings/length.js +10 -0
  132. package/blz-rds/commands/strings/pad-left.js +20 -0
  133. package/blz-rds/commands/strings/pad-right.js +20 -0
  134. package/blz-rds/commands/strings/replace.js +12 -0
  135. package/blz-rds/commands/strings/starts-with.js +12 -0
  136. package/blz-rds/commands/strings/substring.js +12 -0
  137. package/blz-rds/commands/strings/to-lower.js +10 -0
  138. package/blz-rds/commands/strings/to-upper.js +10 -0
  139. package/blz-rds/commands/strings/trim-end.js +10 -0
  140. package/blz-rds/commands/strings/trim-start.js +10 -0
  141. package/blz-rds/commands/strings/trim.js +10 -0
  142. package/blz-rds/index.js +744 -0
  143. package/blz-rds-mysql/base.js +857 -0
  144. package/blz-rds-mysql/connection-manager.js +129 -0
  145. package/blz-rds-mysql/execute-bulk-insert.js +35 -0
  146. package/blz-rds-mysql/execute-bulk-merge.js +45 -0
  147. package/blz-rds-mysql/execute-non-query.js +34 -0
  148. package/blz-rds-mysql/execute-query.js +50 -0
  149. package/blz-rds-mysql/index.js +41 -0
  150. package/blz-rds-mysql/stored-procedure.js +207 -0
  151. package/blz-rds-mysql/syntaxis.json +114 -0
  152. package/blz-rds-mysqlx/base.js +846 -0
  153. package/blz-rds-mysqlx/connection-manager.js +141 -0
  154. package/blz-rds-mysqlx/execute-bulk-insert.js +35 -0
  155. package/blz-rds-mysqlx/execute-bulk-merge.js +45 -0
  156. package/blz-rds-mysqlx/execute-non-query.js +29 -0
  157. package/blz-rds-mysqlx/execute-query.js +39 -0
  158. package/blz-rds-mysqlx/index.js +41 -0
  159. package/blz-rds-mysqlx/stored-procedure.js +179 -0
  160. package/blz-rds-mysqlx/syntaxis.json +105 -0
  161. package/blz-rds-oracle/index.js +540 -0
  162. package/blz-rds-oracle/syntaxis.json +112 -0
  163. package/blz-rds-postgres/base.js +861 -0
  164. package/blz-rds-postgres/connection-manager.js +225 -0
  165. package/blz-rds-postgres/execute-bulk-insert.js +81 -0
  166. package/blz-rds-postgres/execute-bulk-merge.js +93 -0
  167. package/blz-rds-postgres/execute-non-query.js +23 -0
  168. package/blz-rds-postgres/execute-query.js +37 -0
  169. package/blz-rds-postgres/index.js +41 -0
  170. package/blz-rds-postgres/result-set.js +51 -0
  171. package/blz-rds-postgres/stored-procedure.js +116 -0
  172. package/blz-rds-postgres/syntaxis.json +114 -0
  173. package/blz-redis/index.js +217 -0
  174. package/blz-redis/lib/redisCache.js +265 -0
  175. package/blz-regex/index.js +25 -0
  176. package/blz-security/.eslintrc.js +15 -0
  177. package/blz-security/__test__/AuthorizationKpn.yaml +1043 -0
  178. package/blz-security/__test__/FinancingSetting.yaml +177 -0
  179. package/blz-security/__test__/KpnConfigPortal.yaml +330 -0
  180. package/blz-security/__test__/OrderManagement.yaml +5190 -0
  181. package/blz-security/__test__/Security.yaml +128 -0
  182. package/blz-security/__test__/autorization.test.js +105 -0
  183. package/blz-security/__test__/orderManagement.test.js +26 -0
  184. package/blz-security/__test__/secureUrl.test.js +79 -0
  185. package/blz-security/__test__/solveMergeRule.test.js +109 -0
  186. package/blz-security/__test__/sqlInjectionGuard.test.js +203 -0
  187. package/blz-security/__test__/xssGuard.test.js +204 -0
  188. package/blz-security/authorizationService.js +536 -0
  189. package/blz-security/config/global.js +8 -0
  190. package/blz-security/config/welcome +8 -0
  191. package/blz-security/doc/README.md +75 -0
  192. package/blz-security/filescanner/index.js +46 -0
  193. package/blz-security/helpers/consts.js +229 -0
  194. package/blz-security/helpers/utils.js +267 -0
  195. package/blz-security/implementations/cache.js +90 -0
  196. package/blz-security/implementations/oidc.js +404 -0
  197. package/blz-security/implementations/pkceCacheStore.js +23 -0
  198. package/blz-security/implementations/saml.js +10 -0
  199. package/blz-security/implementations/uma.js +63 -0
  200. package/blz-security/implementations/webAuthn.js +9 -0
  201. package/blz-security/implementations/wstg.js +72 -0
  202. package/blz-security/index.js +77 -0
  203. package/blz-security/lab/index.js +27 -0
  204. package/blz-security/middleware/HapiServerAzureAd.js +641 -0
  205. package/blz-security/middleware/HapiServerKeycloak.js +840 -0
  206. package/blz-security/middleware/HapiServerSimToken.js +247 -0
  207. package/blz-security/middleware/hapi.js +515 -0
  208. package/blz-security/middleware/hapiServer.js +974 -0
  209. package/blz-security/navigationMemoryRepository.js +15 -0
  210. package/blz-security/navigationMongoDbRepository.js +73 -0
  211. package/blz-security/secureUrlService.js +47 -0
  212. package/blz-security/securityService.js +409 -0
  213. package/blz-security/sqlInjectionGuard.js +162 -0
  214. package/blz-security/templates/forbidden.html +0 -0
  215. package/blz-security/templates/session-iframe-azure-ad.html +7 -0
  216. package/blz-security/templates/session-iframe.html +73 -0
  217. package/blz-security/templates/unauthorized.html +1 -0
  218. package/blz-security/xssGuard.js +87 -0
  219. package/blz-strings/index.js +167 -0
  220. package/blz-uuid/index.js +7 -0
  221. package/blz-yaml/index.js +19 -0
  222. package/index.js +84 -0
  223. package/package.json +97 -0
  224. package/process-managers/index.js +422 -0
@@ -0,0 +1,128 @@
1
+
2
+ permissions:
3
+ - name: menu
4
+ rules:
5
+ - path: /menu-security/*
6
+ enable: false
7
+ - name: views
8
+ rules:
9
+ - path: /widgets-containers
10
+ actions: '**'
11
+ enable: false
12
+ - path: /grid-columns
13
+ actions: emailColumn, ipColumn
14
+ enable: false
15
+ - path: /roles
16
+ actions: '**'
17
+ enable: false
18
+ - path: /api/service/roles
19
+ enable: false
20
+ - path: /api/service/roles/*
21
+ enable: false
22
+ - path: /api/service/role
23
+ enable: false
24
+ - path: /api/service/role/*
25
+ enable: false
26
+ - name: roleView
27
+ rules:
28
+ - path: /roles
29
+ actions: View
30
+ enable: true
31
+ - path: /api/service/roles
32
+ actions: GET
33
+ enable: true
34
+ - path: /api/service/role/*
35
+ actions: GET
36
+ enable: true
37
+ - name: roleEdit
38
+ extends: [roleView]
39
+ rules:
40
+ - path: /roles
41
+ actions: '**'
42
+ enable: true
43
+ - path: /api/service/roles/merged
44
+ actions: POST
45
+ enable: true
46
+ - path: /api/service/role/*
47
+ actions: DELETE, PATCH
48
+ enable: true
49
+ # Guest
50
+ - name: guestMenu
51
+ extends: [menu]
52
+ rules:
53
+ - path: /menu-security/guest
54
+ - name: guestView
55
+ extends: [views]
56
+ rules:
57
+ - path: /widgets-containers
58
+ actions: viewGuest
59
+ - name: guestActions
60
+ rules:
61
+ - path: /actions
62
+ actions: '**'
63
+ enable: false
64
+ - name: guestAccounts
65
+ rules:
66
+ - path: /account/*
67
+ enable: false
68
+ - path: /api/service/account
69
+ enable: false
70
+ - path: /api/service/account/*
71
+ enable: false
72
+ # User
73
+ - name: userMenu
74
+ extends: [menu]
75
+ rules:
76
+ - path: /menu-security/user
77
+ - name: userView
78
+ extends: [views]
79
+ rules:
80
+ - path: /widgets-containers
81
+ actions: viewUser
82
+ - path: /grid-columns
83
+ actions: emailColumn
84
+ - name: userActions
85
+ rules:
86
+ - path: /actions
87
+ actions: '**, edit:** , remove, view:**, hidden'
88
+ enable: false
89
+ - path: /actions
90
+ actions: 'add, remove:**, edit, id'
91
+ - path: /actions-dots
92
+ actions: id
93
+ - name: userAccounts
94
+ rules:
95
+ - path: /account/*
96
+ - path: /account/22
97
+ enable: false
98
+ - path: /api/service/account
99
+ - path: /api/service/account/*
100
+ enable: false
101
+ - path: /api/service/account/21
102
+ # Admin
103
+ - name: adminMenu
104
+ extends: [menu]
105
+ rules:
106
+ - path: /menu-security/*
107
+ - name: adminView
108
+ extends: [views]
109
+ rules:
110
+ - path: /grid-columns
111
+ actions: ipColumn
112
+ - name: adminActions
113
+ rules:
114
+ - path: /actions
115
+ actions: '**, edit:** , remove, view:**, hidden'
116
+ - name: adminAccounts
117
+ rules:
118
+ - path: /account/22
119
+ - path: /api/service/account/22
120
+ roles:
121
+ - name: Guest
122
+ permissions: [guestAccounts, guestMenu, guestView, guestActions ]
123
+ - name: User
124
+ extends: [Guest]
125
+ permissions: [ userAccounts, userMenu, userView, userActions, roleView]
126
+ - name: Admin
127
+ extends: [User]
128
+ permissions: [ adminAccounts,adminMenu, adminView, adminActions, roleEdit ]
@@ -0,0 +1,105 @@
1
+ /* eslint-disable no-undef */
2
+ const { h3lp } = require('h3lp')
3
+ const Yaml = require('js-yaml')
4
+ const path = require('path')
5
+ const AuthorizationService = require('../authorizationService')
6
+ const _ = require('underscore')
7
+ const logger = require('pino')()
8
+
9
+ let authorizationService = null
10
+ let config = null
11
+
12
+ describe('Permission Service', () => {
13
+ beforeAll(async () => {
14
+ authorizationService = new AuthorizationService(_,logger)
15
+ const content = await h3lp.fs.read(path.join(__dirname, '/Security.yaml'))
16
+ const list = await Yaml.loadAll(content)
17
+ config = authorizationService.importSecurityConfig(list[0])
18
+ })
19
+
20
+ test('Permissions by Guest', () => {
21
+ const permissions = config.roles.find(p => p.name === 'Guest').permissions.join(',')
22
+ expect('guestAccounts,guestMenu,guestView,guestActions').toStrictEqual(permissions)
23
+ })
24
+ test('Permissions by User', () => {
25
+ const permissions = config.roles.find(p => p.name === 'User').permissions.join(',')
26
+ expect('userAccounts,userMenu,userView,userActions,roleView,guestAccounts,guestMenu,guestView,guestActions').toStrictEqual(permissions)
27
+ })
28
+ test('Permissions by Admin', () => {
29
+ const permissions = config.roles.find(p => p.name === 'Admin').permissions.join(',')
30
+ expect('adminAccounts,adminMenu,adminView,adminActions,roleEdit,userAccounts,userMenu,userView,userActions,roleView,guestAccounts,guestMenu,guestView,guestActions').toStrictEqual(permissions)
31
+ })
32
+ test('authorized by Guest', () => {
33
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/api/service/account', '*', ['Guest']))
34
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/api/service/account/21', '*', ['Guest']))
35
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/api/service/account/22', '*', ['Guest']))
36
+
37
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/menu-security/guest', '', ['Guest']))
38
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/menu-security/user', '', ['Guest']))
39
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/menu-security/admin', '', ['Guest']))
40
+ })
41
+ test('authorized by User', () => {
42
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/service/account', '*', ['User']))
43
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/service/account/21', '*', ['User']))
44
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/api/service/account/22', '*', ['User']))
45
+
46
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/menu-security/guest', '', ['User']))
47
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/menu-security/user', '', ['User']))
48
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/menu-security/admin', '', ['User']))
49
+ })
50
+ test('authorized by Admin', () => {
51
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/service/account', '*', ['Admin']))
52
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/service/account/21', '*', ['Admin']))
53
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/service/account/22', '*', ['Admin']))
54
+
55
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/menu-security/guest', '', ['Admin']))
56
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/menu-security/user', '', ['Admin']))
57
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/menu-security/admin', '', ['Admin']))
58
+ })
59
+ test('authorized by Guest and User', () => {
60
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/service/account', '*', ['Guest', 'User']))
61
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/service/account/21', '*', ['Guest', 'User']))
62
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/api/service/account/22', '*', ['Guest', 'User']))
63
+ })
64
+ test('authorized by User and Admin', () => {
65
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/service/account', '*', ['User', 'Admin']))
66
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/service/account/21', '*', ['User', 'Admin']))
67
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/service/account/22', '*', ['User', 'Admin']))
68
+ })
69
+ test('Role access to Guest', () => {
70
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/roles', '', ['Guest']))
71
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/roles', 'View', ['Guest']))
72
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/roles', 'Add', ['Guest']))
73
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/roles', 'Edit', ['Guest']))
74
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/roles', 'Remove', ['Guest']))
75
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/api/service/roles', 'GET', ['Guest']))
76
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/api/service/roles/merged', 'POST', ['Guest']))
77
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/api/service/role/1', 'GET', ['Guest']))
78
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/api/service/role/1', 'DELETE', ['Guest']))
79
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/api/service/role/1', 'PATCH', ['Guest']))
80
+ })
81
+ test('Role access to User', () => {
82
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/roles', '', ['User']))
83
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/roles', 'View', ['User']))
84
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/roles', 'Add', ['User']))
85
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/roles', 'Edit', ['User']))
86
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/roles', 'Remove', ['User']))
87
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/service/roles', 'GET', ['User']))
88
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/api/service/roles/merged', 'POST', ['User']))
89
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/service/role/1', 'GET', ['User']))
90
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/api/service/role/1', 'DELETE', ['User']))
91
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/api/service/role/1', 'PATCH', ['User']))
92
+ })
93
+ test('Role access to Admin', () => {
94
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/roles', '', ['Admin']))
95
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/roles', 'View', ['Admin']))
96
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/roles', 'Add', ['Admin']))
97
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/roles', 'Edit', ['Admin']))
98
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/roles', 'Remove', ['Admin']))
99
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/service/roles', 'GET', ['Admin']))
100
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/service/roles/merged', 'POST', ['Admin']))
101
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/service/role/1', 'GET', ['Admin']))
102
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/service/role/1', 'DELETE', ['Admin']))
103
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/service/role/1', 'PATCH', ['Admin']))
104
+ })
105
+ })
@@ -0,0 +1,26 @@
1
+ /* eslint-disable no-undef */
2
+ const { h3lp } = require('h3lp')
3
+ const Yaml = require('js-yaml')
4
+ const path = require('path')
5
+ const AuthorizationService = require('../authorizationService')
6
+ const _ = require('underscore')
7
+ const logger = require('pino')()
8
+
9
+ let authorizationService = null
10
+
11
+ describe('Permission Service', () => {
12
+ beforeAll(async () => {
13
+ authorizationService = new AuthorizationService(_,logger)
14
+ const content = await h3lp.fs.read(path.join(__dirname, '/OrderManagement.yaml'))
15
+ const list = await Yaml.loadAll(content)
16
+ config = authorizationService.importSecurityConfig(list[0])
17
+ })
18
+
19
+ test('Paths with query parameters', () => {
20
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/api/ext-common-business/businessDomains', 'GET', ['OMUserMenu']))
21
+ expect(false).toStrictEqual(authorizationService.defaultAuthorized('/api/ext-common-business/businessDomains?offset=0&limit=1', 'GET', ['OMUserMenu']))
22
+
23
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/ext-common-business/businessDomains', 'delete', ['OMUserMenu']))
24
+ expect(true).toStrictEqual(authorizationService.defaultAuthorized('/api/ext-common-business/businessDomains?offset=0&limit=1', 'DELETE', ['OMUserMenu']))
25
+ })
26
+ })
@@ -0,0 +1,79 @@
1
+ /* eslint-disable no-undef */
2
+ const SecureUrlService = require('../secureUrlService')
3
+ const logger = require('pino')()
4
+ let secureUrlService = null
5
+
6
+ describe('SecureUrlService', () => {
7
+ beforeAll(async () => {
8
+ secureUrlService = new SecureUrlService(logger)
9
+ })
10
+
11
+ test('Front path', () => {
12
+ const session_key = 'N2ZkZGY4NmItYzVmYi00ZDFkLWI0OGEtMTY1MmM4YmI0ZThm'
13
+ const path = 'https://case-management-portal-beesion-dev.apps.ocp01.iplan.com.ar/#/tkt-incident/sw-2783/manage'
14
+ const token = secureUrlService.createToken(path, session_key)
15
+ expect(() => secureUrlService.validate(path, token, session_key, 15000)).not.toThrow();
16
+ expect(secureUrlService.validate(path, token, session_key, 15000)).toBeUndefined();
17
+ })
18
+
19
+ test('Front path with params', () => {
20
+ const session_key = 'N2ZkZGY4NmItYzVmYi00ZDFkLWI0OGEtMTY1MmM4YmI0ZThm'
21
+ const path = 'https://case-management-portal-beesion-dev.apps.ocp01.iplan.com.ar/#/tkt-incident/sw-2783/manage?param1=1&param2=a'
22
+ const token = secureUrlService.createToken(path, session_key)
23
+ expect(() => secureUrlService.validate(path, token, session_key, 15000)).not.toThrow();
24
+ expect(secureUrlService.validate(path, token, session_key, 15000)).toBeUndefined();
25
+ })
26
+
27
+ test('Api path', () => {
28
+ const session_key = 'N2ZkZGY4NmItYzVmYi00ZDFkLWI0OGEtMTY1MmM4YmI0ZThm'
29
+ const path = '/api/case-adapter/bpm'
30
+ const token = secureUrlService.createToken(path, session_key)
31
+ expect(() => secureUrlService.validate(path, token, session_key, 15000)).not.toThrow();
32
+ expect(secureUrlService.validate(path, token, session_key, 15000)).toBeUndefined();
33
+ })
34
+
35
+ test('Path with special characters with token expired', () => {
36
+ const session_key = '2cd68756-0099-48b4-9f42-57b3553f60c7'
37
+ const path = '/api/ms-business/party/%7BpartyId%7D'
38
+ const token = secureUrlService.createToken(path, session_key)
39
+ try {
40
+ secureUrlService.validate(path, token, session_key, -1);
41
+ fail('Expected SecureUrlService.validate to throw an error');
42
+ } catch (error) {
43
+ expect(error.message).toBe('The token has expired.');
44
+ expect(error.name).toBe('SecureUrlError');
45
+ expect(error.code).toBe(408); // o el campo que uses para el código
46
+ }
47
+ })
48
+
49
+ test('Path with special characters', () => {
50
+ const session_key = '2cd68756-0099-48b4-9f42-57b3553f60c7'
51
+ const path = '/api/ms-business/party/%7BpartyId%7D'
52
+ const token = secureUrlService.createToken(path, session_key)
53
+ expect(() => secureUrlService.validate(path, token, session_key, 15000)).not.toThrow();
54
+ expect(secureUrlService.validate(path, token, session_key, 15000)).toBeUndefined();
55
+ })
56
+
57
+ test('Path with special characters and session key in base64 with token expired', () => {
58
+ const session_key = 'N2ZkZGY4NmItYzVmYi00ZDFkLWI0OGEtMTY1MmM4YmI0ZThm'
59
+ const path = '/api/case-adapter/bpm/%7BinstanceId%7D/save-and-continue'
60
+ const token = secureUrlService.createToken(path, session_key)
61
+ try {
62
+ secureUrlService.validate(path, token, session_key, -1);
63
+ fail('Expected SecureUrlService.validate to throw an error');
64
+ } catch (error) {
65
+ expect(error.message).toBe('The token has expired.');
66
+ expect(error.name).toBe('SecureUrlError');
67
+ expect(error.code).toBe(408); // o el campo que uses para el código
68
+ }
69
+ })
70
+
71
+ test('Path with special characters and session key in base64', () => {
72
+ const session_key = 'N2ZkZGY4NmItYzVmYi00ZDFkLWI0OGEtMTY1MmM4YmI0ZThm'
73
+ const path = '/api/case-adapter/bpm/%7BinstanceId%7D/save-and-continue'
74
+ const token = secureUrlService.createToken(path, session_key)
75
+ expect(() => secureUrlService.validate(path, token, session_key, 15000)).not.toThrow();
76
+ expect(secureUrlService.validate(path, token, session_key, 15000)).toBeUndefined();
77
+ })
78
+
79
+ })
@@ -0,0 +1,109 @@
1
+ /* eslint-disable no-undef */
2
+ const AuthorizationService = require('../authorizationService')
3
+ const _ = require('underscore')
4
+ const logger = require('pino')()
5
+
6
+ const authorizationService = new AuthorizationService(_,logger)
7
+ const typesPreviousRules = [
8
+ { path: '/api/ms-financing-setting/fnc-types', actions: 'GET', enable: true },
9
+ { path: '/api/ms-financing-setting/fnc-types', actions: 'POST', enable: false }
10
+ ]
11
+ const actionPreviousRules = [
12
+ { path: '/api/ms-financing-setting/fnc-action', actions: '*', enable: false }
13
+ ]
14
+ const catalogPreviousRules = [
15
+ { path: '/api/ms-financing-setting/fnc-catalog', actions: '*', enable: true }
16
+ ]
17
+
18
+ describe('Types use case', () => {
19
+ test('Set disable previous disable', () => {
20
+ const result = JSON.stringify(authorizationService._solveMergeRule(typesPreviousRules, { path: '/api/ms-financing-setting/fnc-types', actions: 'POST', enable: false }))
21
+ expect('[{"path":"/api/ms-financing-setting/fnc-types","actions":"GET","enable":true},{"path":"/api/ms-financing-setting/fnc-types","actions":"POST","enable":false}]').toStrictEqual(result)
22
+ })
23
+ test('Set enable previous disable', () => {
24
+ const result = JSON.stringify(authorizationService._solveMergeRule(typesPreviousRules, { path: '/api/ms-financing-setting/fnc-types', actions: 'POST', enable: true }))
25
+ expect('[{"path":"/api/ms-financing-setting/fnc-types","actions":"GET,POST","enable":true}]').toStrictEqual(result)
26
+ })
27
+ test('Add enable', () => {
28
+ const result = JSON.stringify(authorizationService._solveMergeRule(typesPreviousRules, { path: '/api/ms-financing-setting/fnc-types', actions: 'PUT', enable: true }))
29
+ expect('[{"path":"/api/ms-financing-setting/fnc-types","actions":"GET,PUT","enable":true},{"path":"/api/ms-financing-setting/fnc-types","actions":"POST","enable":false}]').toStrictEqual(result)
30
+ })
31
+ test('disable two actions, one set disable previously and other not exists', () => {
32
+ const result = JSON.stringify(authorizationService._solveMergeRule(typesPreviousRules, { path: '/api/ms-financing-setting/fnc-types', actions: 'POST,DELETE', enable: false }))
33
+ expect('[{"path":"/api/ms-financing-setting/fnc-types","actions":"GET","enable":true},{"path":"/api/ms-financing-setting/fnc-types","actions":"POST,DELETE","enable":false}]').toStrictEqual(result)
34
+ })
35
+ test('Enable two actions, one set disable previously and other not exists', () => {
36
+ const result = JSON.stringify(authorizationService._solveMergeRule(typesPreviousRules, { path: '/api/ms-financing-setting/fnc-types', actions: 'POST,DELETE', enable: true }))
37
+ expect('[{"path":"/api/ms-financing-setting/fnc-types","actions":"GET,POST,DELETE","enable":true}]').toStrictEqual(result)
38
+ })
39
+ test('Add enable all rule', () => {
40
+ const result = JSON.stringify(authorizationService._solveMergeRule(typesPreviousRules, { path: '/api/ms-financing-setting/fnc-types', actions: '*', enable: true }))
41
+ expect('[{"path":"/api/ms-financing-setting/fnc-types","actions":"*","enable":true}]').toStrictEqual(result)
42
+ })
43
+ test('Add disable all rule', () => {
44
+ const result = JSON.stringify(authorizationService._solveMergeRule(typesPreviousRules, { path: '/api/ms-financing-setting/fnc-types', actions: '*', enable: false }))
45
+ expect('[{"path":"/api/ms-financing-setting/fnc-types","actions":"GET","enable":true},{"path":"/api/ms-financing-setting/fnc-types","actions":"*","enable":false}]').toStrictEqual(result)
46
+ })
47
+ })
48
+
49
+ describe('Action use case', () => {
50
+ test('Set disable previous disable', () => {
51
+ const result = JSON.stringify(authorizationService._solveMergeRule(actionPreviousRules, { path: '/api/ms-financing-setting/fnc-action', actions: 'POST', enable: false }))
52
+ expect('[{"path":"/api/ms-financing-setting/fnc-action","actions":"*","enable":false}]').toStrictEqual(result)
53
+ })
54
+ test('Set enable previous disable', () => {
55
+ const result = JSON.stringify(authorizationService._solveMergeRule(actionPreviousRules, { path: '/api/ms-financing-setting/fnc-action', actions: 'POST', enable: true }))
56
+ expect('[{"path":"/api/ms-financing-setting/fnc-action","actions":"*","enable":false},{"path":"/api/ms-financing-setting/fnc-action","actions":"POST","enable":true}]').toStrictEqual(result)
57
+ })
58
+ test('Add enable', () => {
59
+ const result = JSON.stringify(authorizationService._solveMergeRule(actionPreviousRules, { path: '/api/ms-financing-setting/fnc-action', actions: 'PUT', enable: true }))
60
+ expect('[{"path":"/api/ms-financing-setting/fnc-action","actions":"*","enable":false},{"path":"/api/ms-financing-setting/fnc-action","actions":"PUT","enable":true}]').toStrictEqual(result)
61
+ })
62
+ test('disable two actions, one set disable previously and other not exists', () => {
63
+ const result = JSON.stringify(authorizationService._solveMergeRule(actionPreviousRules, { path: '/api/ms-financing-setting/fnc-action', actions: 'POST,DELETE', enable: false }))
64
+ expect('[{"path":"/api/ms-financing-setting/fnc-action","actions":"*","enable":false}]').toStrictEqual(result)
65
+ })
66
+ test('Enable two actions, one set disable previously and other not exists', () => {
67
+ const result = JSON.stringify(authorizationService._solveMergeRule(actionPreviousRules, { path: '/api/ms-financing-setting/fnc-action', actions: 'POST,DELETE', enable: true }))
68
+ expect('[{"path":"/api/ms-financing-setting/fnc-action","actions":"*","enable":false},{"path":"/api/ms-financing-setting/fnc-action","actions":"POST,DELETE","enable":true}]').toStrictEqual(result)
69
+ })
70
+ test('Add enable all rule', () => {
71
+ const result = JSON.stringify(authorizationService._solveMergeRule(actionPreviousRules, { path: '/api/ms-financing-setting/fnc-action', actions: '*', enable: true }))
72
+ expect('[{"path":"/api/ms-financing-setting/fnc-action","actions":"*","enable":true}]').toStrictEqual(result)
73
+ })
74
+ test('Add disable all rule', () => {
75
+ const result = JSON.stringify(authorizationService._solveMergeRule(actionPreviousRules, { path: '/api/ms-financing-setting/fnc-action', actions: '*', enable: false }))
76
+ expect('[{"path":"/api/ms-financing-setting/fnc-action","actions":"*","enable":false}]').toStrictEqual(result)
77
+ })
78
+ })
79
+
80
+ describe('Catalog use case', () => {
81
+ test('Set disable previous disable', () => {
82
+ const result = JSON.stringify(authorizationService._solveMergeRule(catalogPreviousRules, { path: '/api/ms-financing-setting/fnc-catalog', actions: 'POST', enable: false }))
83
+ expect('[{"path":"/api/ms-financing-setting/fnc-catalog","actions":"*","enable":true}]').toStrictEqual(result)
84
+ })
85
+ test('Set enable previous disable', () => {
86
+ const result = JSON.stringify(authorizationService._solveMergeRule(catalogPreviousRules, { path: '/api/ms-financing-setting/fnc-catalog', actions: 'POST', enable: true }))
87
+ expect('[{"path":"/api/ms-financing-setting/fnc-catalog","actions":"*","enable":true}]').toStrictEqual(result)
88
+ })
89
+ test('Add enable', () => {
90
+ const result = JSON.stringify(authorizationService._solveMergeRule(catalogPreviousRules, { path: '/api/ms-financing-setting/fnc-catalog', actions: 'PUT', enable: true }))
91
+ expect('[{"path":"/api/ms-financing-setting/fnc-catalog","actions":"*","enable":true}]').toStrictEqual(result)
92
+ })
93
+ test('disable two actions, one set disable previously and other not exists', () => {
94
+ const result = JSON.stringify(authorizationService._solveMergeRule(catalogPreviousRules, { path: '/api/ms-financing-setting/fnc-catalog', actions: 'POST,DELETE', enable: false }))
95
+ expect('[{"path":"/api/ms-financing-setting/fnc-catalog","actions":"*","enable":true}]').toStrictEqual(result)
96
+ })
97
+ test('Enable two actions, one set disable previously and other not exists', () => {
98
+ const result = JSON.stringify(authorizationService._solveMergeRule(catalogPreviousRules, { path: '/api/ms-financing-setting/fnc-catalog', actions: 'POST,DELETE', enable: true }))
99
+ expect('[{"path":"/api/ms-financing-setting/fnc-catalog","actions":"*","enable":true}]').toStrictEqual(result)
100
+ })
101
+ test('Add enable all rule', () => {
102
+ const result = JSON.stringify(authorizationService._solveMergeRule(catalogPreviousRules, { path: '/api/ms-financing-setting/fnc-catalog', actions: '*', enable: true }))
103
+ expect('[{"path":"/api/ms-financing-setting/fnc-catalog","actions":"*","enable":true}]').toStrictEqual(result)
104
+ })
105
+ test('Add disable all rule', () => {
106
+ const result = JSON.stringify(authorizationService._solveMergeRule(catalogPreviousRules, { path: '/api/ms-financing-setting/fnc-catalog', actions: '*', enable: false }))
107
+ expect('[{"path":"/api/ms-financing-setting/fnc-catalog","actions":"*","enable":true}]').toStrictEqual(result)
108
+ })
109
+ })
@@ -0,0 +1,203 @@
1
+ /* eslint-disable no-undef */
2
+ const SqlInjectionGuard = require('../sqlInjectionGuard') // Adjust path as needed
3
+ const pino = require('pino')
4
+
5
+ describe('SqlInjectionGuard', () => {
6
+ let guard
7
+
8
+ beforeEach(() => {
9
+ delete process.env.blz_securityApiSanitizeOnlyLog
10
+ delete process.env.blz_securityApiSanitizeAllowedInputRegex
11
+ guard = new SqlInjectionGuard(pino({ level: 'silent' }))
12
+ })
13
+
14
+ test('accepts safe simple strings', () => {
15
+ const params = [{ name: 'username', value: 'john_doe' }]
16
+ expect(() => guard.validateParamList(params)).not.toThrow()
17
+ })
18
+
19
+ test('accepts safe identifiers with dots and dashes', () => {
20
+ const params = [{ name: 'email', value: 'test.user-name' }]
21
+ expect(() => guard.validateParamList(params)).not.toThrow()
22
+ })
23
+
24
+ test('blocks basic SQL injection attempt', () => {
25
+ const params = [{ name: 'query', value: "' OR 1=1 --" }]
26
+ expect(() => guard.validateParamList(params)).toThrow()
27
+ })
28
+
29
+ test('blocks semicolon followed by DROP statement', () => {
30
+ const sql = "SELECT * FROM users; DROP TABLE users;"
31
+ expect(() => guard.validateRawSql(sql)).toThrow()
32
+ })
33
+
34
+ test('blocks string with pg_sleep function', () => {
35
+ const sql = "SELECT pg_sleep(10);"
36
+ expect(() => guard.validateRawSql(sql)).toThrow()
37
+ })
38
+
39
+ test('blocks nested object with SQLi', () => {
40
+ const obj = {
41
+ user: {
42
+ comment: "'; DROP TABLE users;"
43
+ }
44
+ }
45
+ expect(() => guard.validateObject(obj)).toThrow()
46
+ })
47
+
48
+ test('blocks deep object traversal with SQLi', () => {
49
+ const obj = {
50
+ a: {
51
+ b: {
52
+ c: "' OR '1'='1"
53
+ }
54
+ }
55
+ }
56
+ expect(() => guard.validateObject(obj)).toThrow()
57
+ })
58
+
59
+ test('does not block number values', () => {
60
+ const params = [{ name: 'count', value: 12345 }]
61
+ expect(() => guard.validateParamList(params)).not.toThrow()
62
+ })
63
+
64
+ test('does not block boolean values', () => {
65
+ const params = [{ name: 'active', value: true }]
66
+ expect(() => guard.validateParamList(params)).not.toThrow()
67
+ })
68
+
69
+ test('does not block empty string', () => {
70
+ const params = [{ name: 'description', value: '' }]
71
+ expect(() => guard.validateParamList(params)).not.toThrow()
72
+ })
73
+
74
+ test('allows <script> input when custom regex allows all characters', () => {
75
+ process.env.blz_securityApiSanitizeAllowedInputRegex = '^.{1,100}$'
76
+ guard = new SqlInjectionGuard(pino({ level: 'silent' }))
77
+ const params = [{ name: 'comment', value: '<script>alert("x")</script>' }]
78
+ expect(() => guard.validateParamList(params)).not.toThrow()
79
+ })
80
+
81
+ test('blocks SQL injection even if allowedInputRegex allows special characters', () => {
82
+ process.env.blz_securityApiSanitizeAllowedInputRegex = '^.{1,100}$'
83
+ guard = new SqlInjectionGuard(pino({ level: 'silent' }))
84
+ const params = [{ name: 'input', value: "'; DROP TABLE users;" }]
85
+ expect(() => guard.validateParamList(params)).toThrow()
86
+ })
87
+
88
+ test('only logs when onlyLog mode is enabled', () => {
89
+ process.env.blz_securityApiSanitizeOnlyLog = 'true'
90
+ guard = new SqlInjectionGuard(pino({ level: 'silent' }))
91
+ const params = [{ name: 'input', value: "' OR 'x'='x" }]
92
+ expect(() => guard.validateParamList(params)).not.toThrow()
93
+ })
94
+
95
+ test('ignores non-string values in validateObject', () => {
96
+ const obj = {
97
+ safe: true,
98
+ count: 42,
99
+ list: [1, 2, 3],
100
+ nested: {
101
+ values: [false, null, undefined]
102
+ }
103
+ }
104
+ expect(() => guard.validateObject(obj)).not.toThrow()
105
+ })
106
+
107
+ test('blocks string containing EXEC', () => {
108
+ const sql = "EXEC('SELECT * FROM users')"
109
+ expect(() => guard.validateRawSql(sql)).toThrow()
110
+ })
111
+
112
+ test('blocks string using dbms_lock.sleep', () => {
113
+ const sql = "SELECT dbms_lock.sleep(10) FROM dual"
114
+ expect(() => guard.validateRawSql(sql)).toThrow()
115
+ })
116
+
117
+ test('does not block special characters like = or &', () => {
118
+ const params = [{ name: 'filter', value: 'key=value&x=1' }]
119
+ expect(() => guard.validateParamList(params)).not.toThrow()
120
+ })
121
+
122
+ test('does not block values containing HTML but not SQL', () => {
123
+ const params = [{ name: 'html', value: '<b>bold</b>' }]
124
+ expect(() => guard.validateParamList(params)).not.toThrow()
125
+ })
126
+
127
+ test('throws on invalid JSON pattern in env', () => {
128
+ process.env.blz_securityApiSanitizeDangerousParamPatterns = 'INVALID_JSON'
129
+ expect(() => {
130
+ new SqlInjectionGuard(pino({ level: 'silent' }))
131
+ }).not.toThrow()
132
+ })
133
+
134
+ test('blocks /* comment pattern in param', () => {
135
+ const params = [{ name: 'q', value: '*/ DROP TABLE' }]
136
+ expect(() => guard.validateParamList(params)).toThrow()
137
+ })
138
+
139
+ test('blocks SELECT-FROM pattern', () => {
140
+ const params = [{ name: 'sql', value: 'SELECT * FROM users' }]
141
+ expect(() => guard.validateParamList(params)).toThrow()
142
+ })
143
+
144
+ test('blocks INSERT INTO pattern', () => {
145
+ const params = [{ name: 'payload', value: 'INSERT INTO table VALUES (1)' }]
146
+ expect(() => guard.validateParamList(params)).toThrow()
147
+ })
148
+
149
+ test('blocks UPDATE SET = pattern', () => {
150
+ const params = [{ name: 'input', value: 'UPDATE table SET name="x"' }]
151
+ expect(() => guard.validateParamList(params)).toThrow()
152
+ })
153
+
154
+ test('blocks DELETE FROM pattern', () => {
155
+ const params = [{ name: 'delete', value: 'DELETE FROM users' }]
156
+ expect(() => guard.validateParamList(params)).toThrow()
157
+ })
158
+
159
+ test('allows input with only < at the end', () => {
160
+ const params = [{ name: 'input', value: 'allowed<' }]
161
+ expect(() => guard.validateParamList(params)).not.toThrow()
162
+ })
163
+
164
+ test('allows input with only > at the beginning', () => {
165
+ const params = [{ name: 'input', value: '>allowed' }]
166
+ expect(() => guard.validateParamList(params)).not.toThrow()
167
+ })
168
+
169
+ test('blocks OR with LIKE pattern', () => {
170
+ const params = [{ name: 'search', value: "' OR name LIKE '%admin%'" }]
171
+ expect(() => guard.validateParamList(params)).toThrow()
172
+ })
173
+
174
+ test('blocks AND with LIKE pattern', () => {
175
+ const params = [{ name: 'search', value: "' AND role LIKE '%user%'" }]
176
+ expect(() => guard.validateParamList(params)).toThrow()
177
+ })
178
+
179
+ test('blocks UNION SELECT statement', () => {
180
+ const params = [{ name: 'payload', value: "' UNION SELECT password FROM users --" }]
181
+ expect(() => guard.validateParamList(params)).toThrow()
182
+ })
183
+
184
+ test('blocks complex obfuscated SQL injection', () => {
185
+ const params = [{ name: 'value', value: "admin'/**/OR/**/'1'='1" }]
186
+ expect(() => guard.validateParamList(params)).toThrow()
187
+ })
188
+
189
+ test('does not block input that looks like markup but is valid by whitelist', () => {
190
+ const params = [{ name: 'input', value: 'example>' }]
191
+ expect(() => guard.validateParamList(params)).not.toThrow()
192
+ })
193
+
194
+ // test('blocks expression with encoded SQL keywords', () => {
195
+ // const params = [{ name: 'x', value: '%53%45%4C%45%43%54 * FROM users' }] // SELECT
196
+ // expect(() => guard.validateParamList(params)).toThrow()
197
+ // })
198
+
199
+ test('does not block input with common punctuation', () => {
200
+ const params = [{ name: 'text', value: 'Hello, world! How are you?' }]
201
+ expect(() => guard.validateParamList(params)).not.toThrow()
202
+ })
203
+ })