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.
- package/.github/workflows/auto-pr-description.yml +0 -2
- package/.github/workflows/codeql.yml +46 -0
- package/.github/workflows/release.yml +13 -6
- package/.github/workflows/test-coverage.yml +10 -9
- package/.releaserc.js +9 -6
- package/CHANGELOG.md +62 -150
- package/CODE_OF_CONDUCT.md +1 -1
- package/CONTRIBUTING.md +8 -8
- package/LICENSE +21 -661
- package/README.md +12 -12
- package/SECURITY.md +4 -4
- package/bin/odac.js +101 -0
- package/{framework/web/candy.js → client/odac.js} +310 -44
- package/docs/backend/01-overview/{01-whats-in-the-candy-box.md → 01-whats-in-the-odac-box.md} +4 -2
- package/docs/backend/01-overview/02-super-handy-helper-functions.md +29 -1
- package/docs/backend/01-overview/03-development-server.md +11 -11
- package/docs/backend/02-structure/01-typical-project-layout.md +4 -4
- package/docs/backend/03-config/00-configuration-overview.md +6 -6
- package/docs/backend/03-config/01-database-connection.md +1 -1
- package/docs/backend/03-config/02-static-route-mapping-optional.md +4 -4
- package/docs/backend/03-config/04-environment-variables.md +20 -20
- package/docs/backend/03-config/05-early-hints.md +4 -4
- package/docs/backend/04-routing/01-basic-page-routes.md +4 -4
- package/docs/backend/04-routing/02-controller-less-view-routes.md +5 -5
- package/docs/backend/04-routing/03-api-and-data-routes.md +3 -3
- package/docs/backend/04-routing/04-authentication-aware-routes.md +5 -5
- package/docs/backend/04-routing/05-advanced-routing.md +3 -3
- package/docs/backend/04-routing/06-error-pages.md +17 -17
- package/docs/backend/04-routing/07-cron-jobs.md +13 -13
- package/docs/backend/04-routing/08-middleware.md +214 -0
- package/docs/backend/04-routing/09-websocket-auth-middleware.md +292 -0
- package/docs/backend/04-routing/09-websocket-examples.md +381 -0
- package/docs/backend/04-routing/09-websocket-quick-reference.md +211 -0
- package/docs/backend/04-routing/09-websocket.md +298 -0
- package/docs/backend/05-controllers/01-how-to-build-a-controller.md +3 -3
- package/docs/backend/05-controllers/02-your-trusty-odac-assistant.md +41 -0
- package/docs/backend/05-controllers/03-controller-classes.md +19 -19
- package/docs/backend/05-forms/01-custom-forms.md +114 -114
- package/docs/backend/05-forms/02-automatic-database-insert.md +82 -82
- package/docs/backend/06-request-and-response/01-the-request-object-what-is-the-user-asking-for.md +26 -26
- package/docs/backend/06-request-and-response/02-sending-a-response-replying-to-the-user.md +10 -10
- package/docs/backend/07-views/01-the-view-directory.md +1 -1
- package/docs/backend/07-views/02-rendering-a-view.md +22 -22
- package/docs/backend/07-views/03-template-syntax.md +52 -52
- package/docs/backend/07-views/03-variables.md +84 -84
- package/docs/backend/07-views/04-request-data.md +57 -57
- package/docs/backend/07-views/05-conditionals.md +78 -78
- package/docs/backend/07-views/06-loops.md +114 -114
- package/docs/backend/07-views/07-translations.md +66 -66
- package/docs/backend/07-views/08-backend-javascript.md +103 -103
- package/docs/backend/07-views/09-comments.md +71 -71
- package/docs/backend/08-database/01-database-connection.md +8 -8
- package/docs/backend/08-database/02-using-mysql.md +49 -49
- package/docs/backend/09-validation/01-the-validator-service.md +38 -38
- package/docs/backend/10-authentication/01-user-logins-with-authjs.md +15 -15
- package/docs/backend/10-authentication/02-foiling-villains-with-csrf-protection.md +10 -10
- package/docs/backend/10-authentication/03-register.md +12 -12
- package/docs/backend/10-authentication/{04-candy-register-forms.md → 04-odac-register-forms.md} +141 -141
- package/docs/backend/10-authentication/05-session-management.md +10 -10
- package/docs/backend/10-authentication/{06-candy-login-forms.md → 06-odac-login-forms.md} +125 -125
- package/docs/backend/11-mail/01-the-mail-service.md +5 -5
- package/docs/backend/12-streaming/01-streaming-overview.md +96 -54
- package/docs/backend/13-utilities/{01-candy-var.md → 01-odac-var.md} +109 -109
- package/docs/frontend/01-overview/01-introduction.md +30 -30
- package/docs/frontend/02-ajax-navigation/01-quick-start.md +45 -45
- package/docs/frontend/02-ajax-navigation/02-configuration.md +14 -14
- package/docs/frontend/02-ajax-navigation/03-advanced-usage.md +36 -36
- package/docs/frontend/03-forms/01-form-handling.md +32 -32
- package/docs/frontend/04-api-requests/01-get-post.md +33 -33
- package/docs/frontend/05-streaming/01-client-streaming.md +15 -15
- package/docs/frontend/06-websocket/00-overview.md +76 -0
- package/docs/frontend/06-websocket/01-websocket-client.md +139 -0
- package/docs/frontend/06-websocket/02-shared-websocket.md +149 -0
- package/docs/index.json +49 -11
- package/eslint.config.mjs +6 -6
- package/{framework/index.js → index.js} +1 -1
- package/package.json +14 -39
- package/{framework/src → src}/Auth.js +59 -59
- package/{framework/src → src}/Config.js +3 -3
- package/{framework/src → src}/Lang.js +7 -7
- package/{framework/src → src}/Mail.js +5 -5
- package/{framework/src → src}/Mysql.js +42 -42
- package/src/Odac.js +112 -0
- package/{framework/src → src}/Request.js +38 -36
- package/{framework/src → src}/Route/Internal.js +116 -116
- package/src/Route/Middleware.js +75 -0
- package/src/Route.js +621 -0
- package/src/Server.js +22 -0
- package/{framework/src → src}/Stream.js +11 -3
- package/{framework/src → src}/Validator.js +21 -21
- package/{framework/src → src}/Var.js +5 -5
- package/{framework/src → src}/View/EarlyHints.js +1 -1
- package/{framework/src → src}/View/Form.js +69 -69
- package/{framework/src → src}/View.js +78 -81
- package/src/WebSocket.js +403 -0
- package/template/config.json +5 -0
- package/{web → template}/controller/page/about.js +6 -6
- package/{web → template}/controller/page/index.js +9 -9
- package/{web → template}/package.json +4 -5
- package/{web → template}/public/assets/css/style.css +4 -4
- package/{web → template}/public/assets/js/app.js +6 -6
- package/{web → template}/route/www.js +6 -6
- package/{web → template}/skeleton/main.html +1 -1
- package/{web → template}/view/content/about.html +5 -5
- package/{web → template}/view/content/home.html +12 -12
- package/template/view/footer/main.html +11 -0
- package/{web → template}/view/head/main.html +1 -1
- package/{web → template}/view/header/main.html +2 -2
- package/test/core/Candy.test.js +58 -58
- package/test/core/Commands.test.js +7 -7
- package/test/core/Config.test.js +82 -85
- package/test/core/Lang.test.js +2 -2
- package/test/core/Process.test.js +6 -6
- package/test/framework/Route.test.js +56 -37
- package/test/framework/View/EarlyHints.test.js +2 -2
- package/test/framework/WebSocket.test.js +100 -0
- package/test/framework/middleware.test.js +85 -0
- package/test/server/Api.test.js +31 -31
- package/test/server/DNS.test.js +11 -11
- package/test/server/Hub.test.js +497 -0
- package/test/server/Mail.account.test_.js +3 -3
- package/test/server/Mail.init.test_.js +10 -10
- package/test/server/Mail.test_.js +20 -20
- package/test/server/SSL.test_.js +54 -54
- package/test/server/Server.test.js +39 -39
- package/test/server/Service.test_.js +7 -7
- package/test/server/Subdomain.test.js +7 -7
- package/test/server/Web/Firewall.test.js +87 -87
- package/test/server/Web/Proxy.test.js +397 -0
- package/test/server/{Web.test_.js → Web.test.js} +137 -205
- package/test/server/__mocks__/fs.js +2 -2
- package/test/server/__mocks__/{globalCandy.js → globalOdac.js} +5 -5
- package/test/server/__mocks__/index.js +6 -6
- package/test/server/__mocks__/testFactories.js +1 -1
- package/test/server/__mocks__/testHelpers.js +7 -7
- package/.husky/pre-commit +0 -2
- package/.kiro/steering/code-style.md +0 -56
- package/.kiro/steering/product.md +0 -20
- package/.kiro/steering/structure.md +0 -77
- package/.kiro/steering/tech.md +0 -87
- package/AGENTS.md +0 -84
- package/bin/candy +0 -10
- package/bin/candypack +0 -10
- package/cli/index.js +0 -3
- package/cli/src/Cli.js +0 -348
- package/cli/src/Connector.js +0 -93
- package/cli/src/Monitor.js +0 -416
- package/core/Candy.js +0 -87
- package/core/Commands.js +0 -239
- package/core/Config.js +0 -1094
- package/core/Lang.js +0 -52
- package/core/Log.js +0 -43
- package/core/Process.js +0 -26
- package/docs/backend/05-controllers/02-your-trusty-candy-assistant.md +0 -20
- package/docs/server/01-installation/01-quick-install.md +0 -19
- package/docs/server/01-installation/02-manual-installation-via-npm.md +0 -9
- package/docs/server/02-get-started/01-core-concepts.md +0 -7
- package/docs/server/02-get-started/02-basic-commands.md +0 -57
- package/docs/server/02-get-started/03-cli-reference.md +0 -276
- package/docs/server/02-get-started/04-cli-quick-reference.md +0 -102
- package/docs/server/03-service/01-start-a-new-service.md +0 -57
- package/docs/server/03-service/02-delete-a-service.md +0 -48
- package/docs/server/04-web/01-create-a-website.md +0 -36
- package/docs/server/04-web/02-list-websites.md +0 -9
- package/docs/server/04-web/03-delete-a-website.md +0 -29
- package/docs/server/05-subdomain/01-create-a-subdomain.md +0 -32
- package/docs/server/05-subdomain/02-list-subdomains.md +0 -33
- package/docs/server/05-subdomain/03-delete-a-subdomain.md +0 -41
- package/docs/server/06-ssl/01-renew-an-ssl-certificate.md +0 -34
- package/docs/server/07-mail/01-create-a-mail-account.md +0 -23
- package/docs/server/07-mail/02-delete-a-mail-account.md +0 -20
- package/docs/server/07-mail/03-list-mail-accounts.md +0 -20
- package/docs/server/07-mail/04-change-account-password.md +0 -23
- package/framework/src/Candy.js +0 -81
- package/framework/src/Route.js +0 -455
- package/framework/src/Server.js +0 -15
- package/locale/de-DE.json +0 -80
- package/locale/en-US.json +0 -79
- package/locale/es-ES.json +0 -80
- package/locale/fr-FR.json +0 -80
- package/locale/pt-BR.json +0 -80
- package/locale/ru-RU.json +0 -80
- package/locale/tr-TR.json +0 -85
- package/locale/zh-CN.json +0 -80
- package/server/index.js +0 -5
- package/server/src/Api.js +0 -88
- package/server/src/DNS.js +0 -940
- package/server/src/Hub.js +0 -535
- package/server/src/Mail.js +0 -571
- package/server/src/SSL.js +0 -180
- package/server/src/Server.js +0 -27
- package/server/src/Service.js +0 -248
- package/server/src/Subdomain.js +0 -64
- package/server/src/Web/Firewall.js +0 -170
- package/server/src/Web/Proxy.js +0 -134
- package/server/src/Web.js +0 -451
- package/server/src/mail/imap.js +0 -1091
- package/server/src/mail/server.js +0 -32
- package/server/src/mail/smtp.js +0 -786
- package/test/server/Client.test.js +0 -338
- package/test/server/__mocks__/http-proxy.js +0 -105
- package/watchdog/index.js +0 -3
- package/watchdog/src/Watchdog.js +0 -156
- package/web/config.json +0 -5
- package/web/view/footer/main.html +0 -11
- /package/{framework/src → src}/Env.js +0 -0
- /package/{framework/src → src}/Route/Cron.js +0 -0
- /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
|
|
50
|
+
// Setup global Odac mock
|
|
51
51
|
setupGlobalMocks()
|
|
52
|
-
mockCandy = global.
|
|
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/.
|
|
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/.
|
|
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/.
|
|
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/.
|
|
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/.
|
|
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 {
|
|
25
|
-
|
|
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
|
|
62
|
-
global.
|
|
63
|
-
global.
|
|
64
|
-
global.
|
|
65
|
-
global.
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
|
24
|
-
global.
|
|
25
|
-
core: jest.fn(
|
|
22
|
+
// Mock Odac global
|
|
23
|
+
global.Odac = {
|
|
24
|
+
core: jest.fn(module => {
|
|
26
25
|
if (module === 'Log') return mockLog
|
|
27
|
-
if (module === 'Config')
|
|
28
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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 = {
|
|
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 = {
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
// Mock rate limit config to be very strict
|
|
70
|
+
mockConfigData.firewall.rateLimit.max = 0
|
|
71
|
+
firewall = new Firewall() // reload config
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
firewall.addWhitelist('1.2.3.4')
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
const req = {socket: {remoteAddress: '1.2.3.4'}, headers: {}}
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
expect(firewall.check(req).allowed).toBe(true)
|
|
78
78
|
})
|
|
79
79
|
|
|
80
80
|
test('should enforce rate limits', () => {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
92
|
+
const req = {socket: {remoteAddress: '10.0.0.2'}, headers: {}}
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
-
|
|
99
|
-
|
|
98
|
+
// Wait for window to pass (1000ms)
|
|
99
|
+
await new Promise(resolve => setTimeout(resolve, 1100))
|
|
100
100
|
|
|
101
|
-
|
|
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
|
-
|
|
106
|
-
|
|
105
|
+
const req = {socket: {remoteAddress: '::ffff:127.0.0.1'}, headers: {}}
|
|
106
|
+
expect(firewall.check(req).allowed).toBe(true)
|
|
107
107
|
|
|
108
|
-
|
|
109
|
-
|
|
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
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
-
|
|
135
|
-
|
|
134
|
+
mockConfigData.firewall.enabled = false
|
|
135
|
+
firewall = new Firewall() // reload config
|
|
136
136
|
|
|
137
|
-
|
|
138
|
-
|
|
137
|
+
firewall.addBlock('1.2.3.4') // even if blocked
|
|
138
|
+
const req = {socket: {remoteAddress: '1.2.3.4'}, headers: {}}
|
|
139
139
|
|
|
140
|
-
|
|
140
|
+
expect(firewall.check(req).allowed).toBe(true)
|
|
141
141
|
})
|
|
142
142
|
|
|
143
143
|
test('should remove block', () => {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
-
|
|
149
|
-
|
|
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
|
-
|
|
154
|
-
|
|
155
|
-
|
|
153
|
+
// Set strict rate limit
|
|
154
|
+
mockConfigData.firewall.rateLimit.max = 0
|
|
155
|
+
firewall = new Firewall()
|
|
156
156
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
|
|
162
|
-
|
|
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
|
-
|
|
167
|
-
|
|
166
|
+
firewall.addBlock('1.1.1.1')
|
|
167
|
+
expect(mockConfigData.firewall.blacklist).toContain('1.1.1.1')
|
|
168
168
|
|
|
169
|
-
|
|
170
|
-
|
|
169
|
+
firewall.addWhitelist('2.2.2.2')
|
|
170
|
+
expect(mockConfigData.firewall.whitelist).toContain('2.2.2.2')
|
|
171
171
|
|
|
172
|
-
|
|
173
|
-
|
|
172
|
+
firewall.removeBlock('1.1.1.1')
|
|
173
|
+
expect(mockConfigData.firewall.blacklist).not.toContain('1.1.1.1')
|
|
174
174
|
})
|
|
175
175
|
})
|