odac 0.9.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/.github/workflows/auto-pr-description.yml +0 -2
  2. package/.github/workflows/codeql.yml +46 -0
  3. package/.github/workflows/release.yml +13 -6
  4. package/.github/workflows/test-coverage.yml +10 -9
  5. package/.releaserc.js +9 -6
  6. package/CHANGELOG.md +62 -150
  7. package/CODE_OF_CONDUCT.md +1 -1
  8. package/CONTRIBUTING.md +8 -8
  9. package/LICENSE +21 -661
  10. package/README.md +12 -12
  11. package/SECURITY.md +4 -4
  12. package/bin/odac.js +101 -0
  13. package/{framework/web/candy.js → client/odac.js} +310 -44
  14. package/docs/backend/01-overview/{01-whats-in-the-candy-box.md → 01-whats-in-the-odac-box.md} +4 -2
  15. package/docs/backend/01-overview/02-super-handy-helper-functions.md +29 -1
  16. package/docs/backend/01-overview/03-development-server.md +11 -11
  17. package/docs/backend/02-structure/01-typical-project-layout.md +4 -4
  18. package/docs/backend/03-config/00-configuration-overview.md +6 -6
  19. package/docs/backend/03-config/01-database-connection.md +1 -1
  20. package/docs/backend/03-config/02-static-route-mapping-optional.md +4 -4
  21. package/docs/backend/03-config/04-environment-variables.md +20 -20
  22. package/docs/backend/03-config/05-early-hints.md +4 -4
  23. package/docs/backend/04-routing/01-basic-page-routes.md +4 -4
  24. package/docs/backend/04-routing/02-controller-less-view-routes.md +5 -5
  25. package/docs/backend/04-routing/03-api-and-data-routes.md +3 -3
  26. package/docs/backend/04-routing/04-authentication-aware-routes.md +5 -5
  27. package/docs/backend/04-routing/05-advanced-routing.md +3 -3
  28. package/docs/backend/04-routing/06-error-pages.md +17 -17
  29. package/docs/backend/04-routing/07-cron-jobs.md +13 -13
  30. package/docs/backend/04-routing/08-middleware.md +214 -0
  31. package/docs/backend/04-routing/09-websocket-auth-middleware.md +292 -0
  32. package/docs/backend/04-routing/09-websocket-examples.md +381 -0
  33. package/docs/backend/04-routing/09-websocket-quick-reference.md +211 -0
  34. package/docs/backend/04-routing/09-websocket.md +298 -0
  35. package/docs/backend/05-controllers/01-how-to-build-a-controller.md +3 -3
  36. package/docs/backend/05-controllers/02-your-trusty-odac-assistant.md +41 -0
  37. package/docs/backend/05-controllers/03-controller-classes.md +19 -19
  38. package/docs/backend/05-forms/01-custom-forms.md +114 -114
  39. package/docs/backend/05-forms/02-automatic-database-insert.md +82 -82
  40. package/docs/backend/06-request-and-response/01-the-request-object-what-is-the-user-asking-for.md +26 -26
  41. package/docs/backend/06-request-and-response/02-sending-a-response-replying-to-the-user.md +10 -10
  42. package/docs/backend/07-views/01-the-view-directory.md +1 -1
  43. package/docs/backend/07-views/02-rendering-a-view.md +22 -22
  44. package/docs/backend/07-views/03-template-syntax.md +52 -52
  45. package/docs/backend/07-views/03-variables.md +84 -84
  46. package/docs/backend/07-views/04-request-data.md +57 -57
  47. package/docs/backend/07-views/05-conditionals.md +78 -78
  48. package/docs/backend/07-views/06-loops.md +114 -114
  49. package/docs/backend/07-views/07-translations.md +66 -66
  50. package/docs/backend/07-views/08-backend-javascript.md +103 -103
  51. package/docs/backend/07-views/09-comments.md +71 -71
  52. package/docs/backend/08-database/01-database-connection.md +8 -8
  53. package/docs/backend/08-database/02-using-mysql.md +49 -49
  54. package/docs/backend/09-validation/01-the-validator-service.md +38 -38
  55. package/docs/backend/10-authentication/01-user-logins-with-authjs.md +15 -15
  56. package/docs/backend/10-authentication/02-foiling-villains-with-csrf-protection.md +10 -10
  57. package/docs/backend/10-authentication/03-register.md +12 -12
  58. package/docs/backend/10-authentication/{04-candy-register-forms.md → 04-odac-register-forms.md} +141 -141
  59. package/docs/backend/10-authentication/05-session-management.md +10 -10
  60. package/docs/backend/10-authentication/{06-candy-login-forms.md → 06-odac-login-forms.md} +125 -125
  61. package/docs/backend/11-mail/01-the-mail-service.md +5 -5
  62. package/docs/backend/12-streaming/01-streaming-overview.md +96 -54
  63. package/docs/backend/13-utilities/{01-candy-var.md → 01-odac-var.md} +109 -109
  64. package/docs/frontend/01-overview/01-introduction.md +30 -30
  65. package/docs/frontend/02-ajax-navigation/01-quick-start.md +45 -45
  66. package/docs/frontend/02-ajax-navigation/02-configuration.md +14 -14
  67. package/docs/frontend/02-ajax-navigation/03-advanced-usage.md +36 -36
  68. package/docs/frontend/03-forms/01-form-handling.md +32 -32
  69. package/docs/frontend/04-api-requests/01-get-post.md +33 -33
  70. package/docs/frontend/05-streaming/01-client-streaming.md +15 -15
  71. package/docs/frontend/06-websocket/00-overview.md +76 -0
  72. package/docs/frontend/06-websocket/01-websocket-client.md +139 -0
  73. package/docs/frontend/06-websocket/02-shared-websocket.md +149 -0
  74. package/docs/index.json +49 -11
  75. package/eslint.config.mjs +6 -6
  76. package/{framework/index.js → index.js} +1 -1
  77. package/package.json +14 -39
  78. package/{framework/src → src}/Auth.js +59 -59
  79. package/{framework/src → src}/Config.js +3 -3
  80. package/{framework/src → src}/Lang.js +7 -7
  81. package/{framework/src → src}/Mail.js +5 -5
  82. package/{framework/src → src}/Mysql.js +42 -42
  83. package/src/Odac.js +112 -0
  84. package/{framework/src → src}/Request.js +38 -36
  85. package/{framework/src → src}/Route/Internal.js +116 -116
  86. package/src/Route/Middleware.js +75 -0
  87. package/src/Route.js +621 -0
  88. package/src/Server.js +22 -0
  89. package/{framework/src → src}/Stream.js +11 -3
  90. package/{framework/src → src}/Validator.js +21 -21
  91. package/{framework/src → src}/Var.js +5 -5
  92. package/{framework/src → src}/View/EarlyHints.js +1 -1
  93. package/{framework/src → src}/View/Form.js +69 -69
  94. package/{framework/src → src}/View.js +78 -81
  95. package/src/WebSocket.js +403 -0
  96. package/template/config.json +5 -0
  97. package/{web → template}/controller/page/about.js +6 -6
  98. package/{web → template}/controller/page/index.js +9 -9
  99. package/{web → template}/package.json +4 -5
  100. package/{web → template}/public/assets/css/style.css +4 -4
  101. package/{web → template}/public/assets/js/app.js +6 -6
  102. package/{web → template}/route/www.js +6 -6
  103. package/{web → template}/skeleton/main.html +1 -1
  104. package/{web → template}/view/content/about.html +5 -5
  105. package/{web → template}/view/content/home.html +12 -12
  106. package/template/view/footer/main.html +11 -0
  107. package/{web → template}/view/head/main.html +1 -1
  108. package/{web → template}/view/header/main.html +2 -2
  109. package/test/core/Candy.test.js +58 -58
  110. package/test/core/Commands.test.js +7 -7
  111. package/test/core/Config.test.js +82 -85
  112. package/test/core/Lang.test.js +2 -2
  113. package/test/core/Process.test.js +6 -6
  114. package/test/framework/Route.test.js +56 -37
  115. package/test/framework/View/EarlyHints.test.js +2 -2
  116. package/test/framework/WebSocket.test.js +100 -0
  117. package/test/framework/middleware.test.js +85 -0
  118. package/test/server/Api.test.js +31 -31
  119. package/test/server/DNS.test.js +11 -11
  120. package/test/server/Hub.test.js +497 -0
  121. package/test/server/Mail.account.test_.js +3 -3
  122. package/test/server/Mail.init.test_.js +10 -10
  123. package/test/server/Mail.test_.js +20 -20
  124. package/test/server/SSL.test_.js +54 -54
  125. package/test/server/Server.test.js +39 -39
  126. package/test/server/Service.test_.js +7 -7
  127. package/test/server/Subdomain.test.js +7 -7
  128. package/test/server/Web/Firewall.test.js +87 -87
  129. package/test/server/Web/Proxy.test.js +397 -0
  130. package/test/server/{Web.test_.js → Web.test.js} +137 -205
  131. package/test/server/__mocks__/fs.js +2 -2
  132. package/test/server/__mocks__/{globalCandy.js → globalOdac.js} +5 -5
  133. package/test/server/__mocks__/index.js +6 -6
  134. package/test/server/__mocks__/testFactories.js +1 -1
  135. package/test/server/__mocks__/testHelpers.js +7 -7
  136. package/.husky/pre-commit +0 -2
  137. package/.kiro/steering/code-style.md +0 -56
  138. package/.kiro/steering/product.md +0 -20
  139. package/.kiro/steering/structure.md +0 -77
  140. package/.kiro/steering/tech.md +0 -87
  141. package/AGENTS.md +0 -84
  142. package/bin/candy +0 -10
  143. package/bin/candypack +0 -10
  144. package/cli/index.js +0 -3
  145. package/cli/src/Cli.js +0 -348
  146. package/cli/src/Connector.js +0 -93
  147. package/cli/src/Monitor.js +0 -416
  148. package/core/Candy.js +0 -87
  149. package/core/Commands.js +0 -239
  150. package/core/Config.js +0 -1094
  151. package/core/Lang.js +0 -52
  152. package/core/Log.js +0 -43
  153. package/core/Process.js +0 -26
  154. package/docs/backend/05-controllers/02-your-trusty-candy-assistant.md +0 -20
  155. package/docs/server/01-installation/01-quick-install.md +0 -19
  156. package/docs/server/01-installation/02-manual-installation-via-npm.md +0 -9
  157. package/docs/server/02-get-started/01-core-concepts.md +0 -7
  158. package/docs/server/02-get-started/02-basic-commands.md +0 -57
  159. package/docs/server/02-get-started/03-cli-reference.md +0 -276
  160. package/docs/server/02-get-started/04-cli-quick-reference.md +0 -102
  161. package/docs/server/03-service/01-start-a-new-service.md +0 -57
  162. package/docs/server/03-service/02-delete-a-service.md +0 -48
  163. package/docs/server/04-web/01-create-a-website.md +0 -36
  164. package/docs/server/04-web/02-list-websites.md +0 -9
  165. package/docs/server/04-web/03-delete-a-website.md +0 -29
  166. package/docs/server/05-subdomain/01-create-a-subdomain.md +0 -32
  167. package/docs/server/05-subdomain/02-list-subdomains.md +0 -33
  168. package/docs/server/05-subdomain/03-delete-a-subdomain.md +0 -41
  169. package/docs/server/06-ssl/01-renew-an-ssl-certificate.md +0 -34
  170. package/docs/server/07-mail/01-create-a-mail-account.md +0 -23
  171. package/docs/server/07-mail/02-delete-a-mail-account.md +0 -20
  172. package/docs/server/07-mail/03-list-mail-accounts.md +0 -20
  173. package/docs/server/07-mail/04-change-account-password.md +0 -23
  174. package/framework/src/Candy.js +0 -81
  175. package/framework/src/Route.js +0 -455
  176. package/framework/src/Server.js +0 -15
  177. package/locale/de-DE.json +0 -80
  178. package/locale/en-US.json +0 -79
  179. package/locale/es-ES.json +0 -80
  180. package/locale/fr-FR.json +0 -80
  181. package/locale/pt-BR.json +0 -80
  182. package/locale/ru-RU.json +0 -80
  183. package/locale/tr-TR.json +0 -85
  184. package/locale/zh-CN.json +0 -80
  185. package/server/index.js +0 -5
  186. package/server/src/Api.js +0 -88
  187. package/server/src/DNS.js +0 -940
  188. package/server/src/Hub.js +0 -535
  189. package/server/src/Mail.js +0 -571
  190. package/server/src/SSL.js +0 -180
  191. package/server/src/Server.js +0 -27
  192. package/server/src/Service.js +0 -248
  193. package/server/src/Subdomain.js +0 -64
  194. package/server/src/Web/Firewall.js +0 -170
  195. package/server/src/Web/Proxy.js +0 -134
  196. package/server/src/Web.js +0 -451
  197. package/server/src/mail/imap.js +0 -1091
  198. package/server/src/mail/server.js +0 -32
  199. package/server/src/mail/smtp.js +0 -786
  200. package/test/server/Client.test.js +0 -338
  201. package/test/server/__mocks__/http-proxy.js +0 -105
  202. package/watchdog/index.js +0 -3
  203. package/watchdog/src/Watchdog.js +0 -156
  204. package/web/config.json +0 -5
  205. package/web/view/footer/main.html +0 -11
  206. /package/{framework/src → src}/Env.js +0 -0
  207. /package/{framework/src → src}/Route/Cron.js +0 -0
  208. /package/{framework/src → src}/Token.js +0 -0
@@ -47,9 +47,9 @@ describe('Service', () => {
47
47
  beforeEach(() => {
48
48
  jest.clearAllMocks()
49
49
 
50
- // Setup global Candy mock
50
+ // Setup global Odac mock
51
51
  setupGlobalMocks()
52
- mockCandy = global.Candy
52
+ mockCandy = global.Odac
53
53
 
54
54
  // Mock child_process module
55
55
  mockChildProcess = createMockChildProcess()
@@ -700,14 +700,14 @@ describe('Service', () => {
700
700
  await Service.check()
701
701
 
702
702
  expect(fs.writeFile).toHaveBeenCalledWith(
703
- '/home/user/.candypack/logs/test-service.js.log',
703
+ '/home/user/.odac/logs/test-service.js.log',
704
704
  expect.stringContaining(stdoutData),
705
705
  'utf8',
706
706
  expect.any(Function)
707
707
  )
708
708
 
709
709
  expect(fs.writeFile).toHaveBeenCalledWith(
710
- '/home/user/.candypack/logs/test-service.js.err.log',
710
+ '/home/user/.odac/logs/test-service.js.err.log',
711
711
  expect.stringContaining(stderrData),
712
712
  'utf8',
713
713
  expect.any(Function)
@@ -836,7 +836,7 @@ describe('Service', () => {
836
836
 
837
837
  await Service.init()
838
838
 
839
- expect(fs.readFile).toHaveBeenCalledWith('/home/user/.candypack/logs/test-service.js.log', 'utf8', expect.any(Function))
839
+ expect(fs.readFile).toHaveBeenCalledWith('/home/user/.odac/logs/test-service.js.log', 'utf8', expect.any(Function))
840
840
  })
841
841
 
842
842
  test('should calculate and report service uptime correctly', async () => {
@@ -1008,14 +1008,14 @@ describe('Service', () => {
1008
1008
 
1009
1009
  // Should write to both regular log and error log
1010
1010
  expect(fs.writeFile).toHaveBeenCalledWith(
1011
- '/home/user/.candypack/logs/test-service.js.log',
1011
+ '/home/user/.odac/logs/test-service.js.log',
1012
1012
  expect.stringContaining('[ERR]'),
1013
1013
  'utf8',
1014
1014
  expect.any(Function)
1015
1015
  )
1016
1016
 
1017
1017
  expect(fs.writeFile).toHaveBeenCalledWith(
1018
- '/home/user/.candypack/logs/test-service.js.err.log',
1018
+ '/home/user/.odac/logs/test-service.js.err.log',
1019
1019
  expect.stringContaining(errorMessage),
1020
1020
  'utf8',
1021
1021
  expect.any(Function)
@@ -21,8 +21,8 @@ describe('Subdomain', () => {
21
21
  setupGlobalMocks()
22
22
 
23
23
  // Set up the Log mock before requiring Subdomain
24
- const {mockCandy} = require('./__mocks__/globalCandy')
25
- mockCandy.setMock('core', 'Log', {
24
+ const {mockOdac} = require('./__mocks__/globalOdac')
25
+ mockOdac.setMock('core', 'Log', {
26
26
  init: jest.fn().mockReturnValue({
27
27
  log: mockLog,
28
28
  error: mockError
@@ -58,11 +58,11 @@ describe('Subdomain', () => {
58
58
  result: jest.fn((success, data) => ({success, data}))
59
59
  }
60
60
 
61
- // Configure global Candy mocks
62
- global.Candy.setMock('core', 'Config', {config: mockConfig})
63
- global.Candy.setMock('server', 'DNS', mockDNS)
64
- global.Candy.setMock('server', 'SSL', mockSSL)
65
- global.Candy.setMock('server', 'Api', mockApi)
61
+ // Configure global Odac mocks
62
+ global.Odac.setMock('core', 'Config', {config: mockConfig})
63
+ global.Odac.setMock('server', 'DNS', mockDNS)
64
+ global.Odac.setMock('server', 'SSL', mockSSL)
65
+ global.Odac.setMock('server', 'Api', mockApi)
66
66
 
67
67
  // Mock the __ function to return the key with placeholders replaced correctly
68
68
  global.__ = jest.fn((key, ...args) => {
@@ -1,4 +1,3 @@
1
-
2
1
  // Mock dependencies
3
2
  const mockLog = {
4
3
  log: jest.fn(),
@@ -8,25 +7,26 @@ const mockLog = {
8
7
 
9
8
  // Global config store
10
9
  let mockConfigData = {
11
- firewall: {
12
- enabled: true,
13
- rateLimit: {
14
- enabled: true,
15
- windowMs: 1000,
16
- max: 2
17
- },
18
- blacklist: [],
19
- whitelist: []
20
- }
10
+ firewall: {
11
+ enabled: true,
12
+ rateLimit: {
13
+ enabled: true,
14
+ windowMs: 1000,
15
+ max: 2
16
+ },
17
+ blacklist: [],
18
+ whitelist: []
19
+ }
21
20
  }
22
21
 
23
- // Mock Candy global
24
- global.Candy = {
25
- core: jest.fn((module) => {
22
+ // Mock Odac global
23
+ global.Odac = {
24
+ core: jest.fn(module => {
26
25
  if (module === 'Log') return mockLog
27
- if (module === 'Config') return {
28
- config: mockConfigData
29
- }
26
+ if (module === 'Config')
27
+ return {
28
+ config: mockConfigData
29
+ }
30
30
  return {}
31
31
  })
32
32
  }
@@ -40,136 +40,136 @@ describe('Firewall', () => {
40
40
  jest.clearAllMocks()
41
41
  // Reset config
42
42
  mockConfigData.firewall = {
43
+ enabled: true,
44
+ rateLimit: {
43
45
  enabled: true,
44
- rateLimit: {
45
- enabled: true,
46
- windowMs: 1000,
47
- max: 2
48
- },
49
- blacklist: [],
50
- whitelist: []
46
+ windowMs: 1000,
47
+ max: 2
48
+ },
49
+ blacklist: [],
50
+ whitelist: []
51
51
  }
52
52
  firewall = new Firewall()
53
53
  })
54
54
 
55
55
  test('should allow requests from normal IPs', () => {
56
- const req = { socket: { remoteAddress: '127.0.0.1' }, headers: {} }
56
+ const req = {socket: {remoteAddress: '127.0.0.1'}, headers: {}}
57
57
  expect(firewall.check(req).allowed).toBe(true)
58
58
  })
59
59
 
60
60
  test('should block requests from blacklisted IPs', () => {
61
61
  firewall.addBlock('1.2.3.4')
62
- const req = { socket: { remoteAddress: '1.2.3.4' }, headers: {} }
62
+ const req = {socket: {remoteAddress: '1.2.3.4'}, headers: {}}
63
63
  const result = firewall.check(req)
64
64
  expect(result.allowed).toBe(false)
65
65
  expect(result.reason).toBe('blacklist')
66
66
  })
67
67
 
68
68
  test('should allow requests from whitelisted IPs even if rate limited', () => {
69
- // Mock rate limit config to be very strict
70
- mockConfigData.firewall.rateLimit.max = 0
71
- firewall = new Firewall() // reload config
69
+ // Mock rate limit config to be very strict
70
+ mockConfigData.firewall.rateLimit.max = 0
71
+ firewall = new Firewall() // reload config
72
72
 
73
- firewall.addWhitelist('1.2.3.4')
73
+ firewall.addWhitelist('1.2.3.4')
74
74
 
75
- const req = { socket: { remoteAddress: '1.2.3.4' }, headers: {} }
75
+ const req = {socket: {remoteAddress: '1.2.3.4'}, headers: {}}
76
76
 
77
- expect(firewall.check(req).allowed).toBe(true)
77
+ expect(firewall.check(req).allowed).toBe(true)
78
78
  })
79
79
 
80
80
  test('should enforce rate limits', () => {
81
- const req = { socket: { remoteAddress: '10.0.0.1' }, headers: {} }
82
-
83
- // Config is max 2 per 1000ms
84
- expect(firewall.check(req).allowed).toBe(true) // 1
85
- expect(firewall.check(req).allowed).toBe(true) // 2
86
- const result = firewall.check(req) // 3 - blocked
87
- expect(result.allowed).toBe(false)
88
- expect(result.reason).toBe('rate_limit')
81
+ const req = {socket: {remoteAddress: '10.0.0.1'}, headers: {}}
82
+
83
+ // Config is max 2 per 1000ms
84
+ expect(firewall.check(req).allowed).toBe(true) // 1
85
+ expect(firewall.check(req).allowed).toBe(true) // 2
86
+ const result = firewall.check(req) // 3 - blocked
87
+ expect(result.allowed).toBe(false)
88
+ expect(result.reason).toBe('rate_limit')
89
89
  })
90
90
 
91
91
  test('should reset rate limits after window', async () => {
92
- const req = { socket: { remoteAddress: '10.0.0.2' }, headers: {} }
92
+ const req = {socket: {remoteAddress: '10.0.0.2'}, headers: {}}
93
93
 
94
- expect(firewall.check(req).allowed).toBe(true) // 1
95
- expect(firewall.check(req).allowed).toBe(true) // 2
96
- expect(firewall.check(req).allowed).toBe(false) // 3
94
+ expect(firewall.check(req).allowed).toBe(true) // 1
95
+ expect(firewall.check(req).allowed).toBe(true) // 2
96
+ expect(firewall.check(req).allowed).toBe(false) // 3
97
97
 
98
- // Wait for window to pass (1000ms)
99
- await new Promise(resolve => setTimeout(resolve, 1100))
98
+ // Wait for window to pass (1000ms)
99
+ await new Promise(resolve => setTimeout(resolve, 1100))
100
100
 
101
- expect(firewall.check(req).allowed).toBe(true) // Should be allowed again
101
+ expect(firewall.check(req).allowed).toBe(true) // Should be allowed again
102
102
  })
103
103
 
104
104
  test('should handle IPv6 mapped IPv4 addresses', () => {
105
- const req = { socket: { remoteAddress: '::ffff:127.0.0.1' }, headers: {} }
106
- expect(firewall.check(req).allowed).toBe(true)
105
+ const req = {socket: {remoteAddress: '::ffff:127.0.0.1'}, headers: {}}
106
+ expect(firewall.check(req).allowed).toBe(true)
107
107
 
108
- firewall.addBlock('127.0.0.1')
109
- expect(firewall.check(req).allowed).toBe(false)
108
+ firewall.addBlock('127.0.0.1')
109
+ expect(firewall.check(req).allowed).toBe(false)
110
110
  })
111
111
 
112
112
  test('should use x-forwarded-for if socket address is missing', () => {
113
- const req = { socket: {}, headers: { 'x-forwarded-for': '1.2.3.4' } }
114
- firewall.addBlock('1.2.3.4')
115
- expect(firewall.check(req).allowed).toBe(false)
113
+ const req = {socket: {}, headers: {'x-forwarded-for': '1.2.3.4'}}
114
+ firewall.addBlock('1.2.3.4')
115
+ expect(firewall.check(req).allowed).toBe(false)
116
116
  })
117
117
 
118
118
  test('should handle x-forwarded-for with multiple IPs', () => {
119
- // First IP is client
120
- const req = { socket: {}, headers: { 'x-forwarded-for': '1.2.3.4, 5.6.7.8' } }
121
- firewall.addBlock('1.2.3.4')
122
- const result = firewall.check(req)
123
- expect(result.allowed).toBe(false)
124
- expect(result.reason).toBe('blacklist')
119
+ // First IP is client
120
+ const req = {socket: {}, headers: {'x-forwarded-for': '1.2.3.4, 5.6.7.8'}}
121
+ firewall.addBlock('1.2.3.4')
122
+ const result = firewall.check(req)
123
+ expect(result.allowed).toBe(false)
124
+ expect(result.reason).toBe('blacklist')
125
125
  })
126
126
 
127
127
  test('should handle x-forwarded-for with spaces', () => {
128
- const req = { socket: {}, headers: { 'x-forwarded-for': ' 1.2.3.4 , 5.6.7.8 ' } }
129
- firewall.addBlock('1.2.3.4')
130
- expect(firewall.check(req).allowed).toBe(false)
128
+ const req = {socket: {}, headers: {'x-forwarded-for': ' 1.2.3.4 , 5.6.7.8 '}}
129
+ firewall.addBlock('1.2.3.4')
130
+ expect(firewall.check(req).allowed).toBe(false)
131
131
  })
132
132
 
133
133
  test('should allow everything when disabled', () => {
134
- mockConfigData.firewall.enabled = false
135
- firewall = new Firewall() // reload config
134
+ mockConfigData.firewall.enabled = false
135
+ firewall = new Firewall() // reload config
136
136
 
137
- firewall.addBlock('1.2.3.4') // even if blocked
138
- const req = { socket: { remoteAddress: '1.2.3.4' }, headers: {} }
137
+ firewall.addBlock('1.2.3.4') // even if blocked
138
+ const req = {socket: {remoteAddress: '1.2.3.4'}, headers: {}}
139
139
 
140
- expect(firewall.check(req).allowed).toBe(true)
140
+ expect(firewall.check(req).allowed).toBe(true)
141
141
  })
142
142
 
143
143
  test('should remove block', () => {
144
- firewall.addBlock('1.2.3.4')
145
- const req = { socket: { remoteAddress: '1.2.3.4' }, headers: {} }
146
- expect(firewall.check(req).allowed).toBe(false)
144
+ firewall.addBlock('1.2.3.4')
145
+ const req = {socket: {remoteAddress: '1.2.3.4'}, headers: {}}
146
+ expect(firewall.check(req).allowed).toBe(false)
147
147
 
148
- firewall.removeBlock('1.2.3.4')
149
- expect(firewall.check(req).allowed).toBe(true)
148
+ firewall.removeBlock('1.2.3.4')
149
+ expect(firewall.check(req).allowed).toBe(true)
150
150
  })
151
151
 
152
152
  test('should remove whitelist', () => {
153
- // Set strict rate limit
154
- mockConfigData.firewall.rateLimit.max = 0
155
- firewall = new Firewall()
153
+ // Set strict rate limit
154
+ mockConfigData.firewall.rateLimit.max = 0
155
+ firewall = new Firewall()
156
156
 
157
- firewall.addWhitelist('1.2.3.4')
158
- const req = { socket: { remoteAddress: '1.2.3.4' }, headers: {} }
159
- expect(firewall.check(req).allowed).toBe(true)
157
+ firewall.addWhitelist('1.2.3.4')
158
+ const req = {socket: {remoteAddress: '1.2.3.4'}, headers: {}}
159
+ expect(firewall.check(req).allowed).toBe(true)
160
160
 
161
- firewall.removeWhitelist('1.2.3.4')
162
- expect(firewall.check(req).allowed).toBe(false) // rate limited
161
+ firewall.removeWhitelist('1.2.3.4')
162
+ expect(firewall.check(req).allowed).toBe(false) // rate limited
163
163
  })
164
164
 
165
165
  test('should persist changes to config', () => {
166
- firewall.addBlock('1.1.1.1')
167
- expect(mockConfigData.firewall.blacklist).toContain('1.1.1.1')
166
+ firewall.addBlock('1.1.1.1')
167
+ expect(mockConfigData.firewall.blacklist).toContain('1.1.1.1')
168
168
 
169
- firewall.addWhitelist('2.2.2.2')
170
- expect(mockConfigData.firewall.whitelist).toContain('2.2.2.2')
169
+ firewall.addWhitelist('2.2.2.2')
170
+ expect(mockConfigData.firewall.whitelist).toContain('2.2.2.2')
171
171
 
172
- firewall.removeBlock('1.1.1.1')
173
- expect(mockConfigData.firewall.blacklist).not.toContain('1.1.1.1')
172
+ firewall.removeBlock('1.1.1.1')
173
+ expect(mockConfigData.firewall.blacklist).not.toContain('1.1.1.1')
174
174
  })
175
175
  })