DC-005: Fix all 138 broken test paths after src/ refactor
After the DC-005 module reorganization (41 files moved into src/ subdirs),
138 test suites failed because the refactor script's path-rewrite logic
missed three categories:
1. Files inside src/ doing 'require("./src/...")' — should be 'require("../...")'
2. Files in src/X/Y/ doing 'require("../../../src/...")' — should be 'require("../../...")'
3. Test files in __tests__/ with leftover 'require("../../../src/...")' paths
Root cause: the original refactor script ran before all files were moved,
so it computed relative paths against stale filesystem state.
Result:
- 30/30 test suites pass
- 879/879 tests pass (was: 18/30 suites, 614/687 tests)
Also fixed:
- routes/apps/restore.js: wrong responses import path
- routes/*/*.js: '../../src/utilities/X' → '../src/utilities/X' (depth 2 routes)
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
const { APP_TEMPLATES, TEMPLATE_CATEGORIES, DIFFICULTY_LEVELS } = require('../app-templates');
|
const { APP_TEMPLATES, TEMPLATE_CATEGORIES, DIFFICULTY_LEVELS } = require('../src/docker/app-templates');
|
||||||
|
|
||||||
describe('App Templates', () => {
|
describe('App Templates', () => {
|
||||||
const templates = Object.values(APP_TEMPLATES);
|
const templates = Object.values(APP_TEMPLATES);
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
// Must mock crypto-utils BEFORE auth-manager is required,
|
// Must mock crypto-utils BEFORE auth-manager is required,
|
||||||
// because auth-manager.js line 13: const JWT_SECRET = cryptoUtils.loadOrCreateKey()
|
// because auth-manager.js line 13: const JWT_SECRET = cryptoUtils.loadOrCreateKey()
|
||||||
const mockFixedKey = Buffer.alloc(32, 'jwt-test-key-pad');
|
const mockFixedKey = Buffer.alloc(32, 'jwt-test-key-pad');
|
||||||
jest.mock('../crypto-utils', () => ({
|
jest.mock('../src/security/crypto-utils', () => ({
|
||||||
loadOrCreateKey: jest.fn(() => mockFixedKey),
|
loadOrCreateKey: jest.fn(() => mockFixedKey),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../credential-manager', () => ({
|
jest.mock('../src/managers/credential-manager', () => ({
|
||||||
store: jest.fn().mockResolvedValue(true),
|
store: jest.fn().mockResolvedValue(true),
|
||||||
retrieve: jest.fn().mockResolvedValue(null),
|
retrieve: jest.fn().mockResolvedValue(null),
|
||||||
delete: jest.fn().mockResolvedValue(true),
|
delete: jest.fn().mockResolvedValue(true),
|
||||||
@@ -13,8 +13,8 @@ jest.mock('../credential-manager', () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const authManager = require('../auth-manager');
|
const authManager = require('../src/managers/auth-manager');
|
||||||
const credentialManager = require('../credential-manager');
|
const credentialManager = require('../src/managers/credential-manager');
|
||||||
|
|
||||||
describe('AuthManager', () => {
|
describe('AuthManager', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|||||||
@@ -9,14 +9,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const { AutoRestartManager, DEFAULT_POLICY } = require('../auto-restart-manager');
|
const { AutoRestartManager, DEFAULT_POLICY } = require('../src/managers/auto-restart-manager');
|
||||||
|
|
||||||
jest.mock('../fs-helpers', () => ({
|
jest.mock('../src/utilities/fs-helpers', () => ({
|
||||||
readJsonFile: jest.fn().mockResolvedValue({}),
|
readJsonFile: jest.fn().mockResolvedValue({}),
|
||||||
writeJsonFile: jest.fn().mockResolvedValue(undefined),
|
writeJsonFile: jest.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const fsHelpers = require('../fs-helpers');
|
const fsHelpers = require('../src/utilities/fs-helpers');
|
||||||
|
|
||||||
function makeManager(overrides = {}) {
|
function makeManager(overrides = {}) {
|
||||||
const servicesStateManager = {
|
const servicesStateManager = {
|
||||||
|
|||||||
@@ -3,19 +3,19 @@
|
|||||||
|
|
||||||
jest.mock('fs');
|
jest.mock('fs');
|
||||||
jest.mock('child_process');
|
jest.mock('child_process');
|
||||||
jest.mock('../credential-manager', () => ({
|
jest.mock('../src/managers/credential-manager', () => ({
|
||||||
exportBackup: jest.fn().mockReturnValue({ encrypted: 'cred-data' }),
|
exportBackup: jest.fn().mockReturnValue({ encrypted: 'cred-data' }),
|
||||||
importBackup: jest.fn()
|
importBackup: jest.fn()
|
||||||
}));
|
}));
|
||||||
jest.mock('../resource-monitor', () => ({
|
jest.mock('../src/managers/resource-monitor', () => ({
|
||||||
exportStats: jest.fn().mockReturnValue({ stats: [{ cpu: 10 }] }),
|
exportStats: jest.fn().mockReturnValue({ stats: [{ cpu: 10 }] }),
|
||||||
importStats: jest.fn()
|
importStats: jest.fn()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const credentialManager = require('../credential-manager');
|
const credentialManager = require('../src/managers/credential-manager');
|
||||||
const resourceMonitor = require('../resource-monitor');
|
const resourceMonitor = require('../src/managers/resource-monitor');
|
||||||
|
|
||||||
// Setup defaults BEFORE requiring singleton (constructor calls loadConfig/loadHistory)
|
// Setup defaults BEFORE requiring singleton (constructor calls loadConfig/loadHistory)
|
||||||
fs.existsSync.mockReturnValue(false);
|
fs.existsSync.mockReturnValue(false);
|
||||||
@@ -24,7 +24,7 @@ fs.writeFileSync.mockReturnValue(undefined);
|
|||||||
fs.mkdirSync.mockReturnValue(undefined);
|
fs.mkdirSync.mockReturnValue(undefined);
|
||||||
fs.unlinkSync.mockReturnValue(undefined);
|
fs.unlinkSync.mockReturnValue(undefined);
|
||||||
|
|
||||||
const backupManager = require('../backup-manager');
|
const backupManager = require('../src/utilities/backup-manager');
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const { ConfigDriftDetector } = require('../config-drift-detector');
|
const { ConfigDriftDetector } = require('../src/managers/config-drift-detector');
|
||||||
|
|
||||||
function makeContainer(overrides = {}) {
|
function makeContainer(overrides = {}) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
// Mock dependencies before requiring the module
|
// Mock dependencies before requiring the module
|
||||||
jest.mock('../keychain-manager', () => ({
|
jest.mock('../src/security/keychain-manager', () => ({
|
||||||
available: false,
|
available: false,
|
||||||
store: jest.fn().mockResolvedValue(false),
|
store: jest.fn().mockResolvedValue(false),
|
||||||
retrieve: jest.fn().mockResolvedValue(null),
|
retrieve: jest.fn().mockResolvedValue(null),
|
||||||
delete: jest.fn().mockResolvedValue(true),
|
delete: jest.fn().mockResolvedValue(true),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../crypto-utils', () => ({
|
jest.mock('../src/security/crypto-utils', () => ({
|
||||||
encrypt: jest.fn(data => `enc:tag:${Buffer.from(String(data)).toString('base64')}`),
|
encrypt: jest.fn(data => `enc:tag:${Buffer.from(String(data)).toString('base64')}`),
|
||||||
decrypt: jest.fn(data => {
|
decrypt: jest.fn(data => {
|
||||||
const parts = data.split(':');
|
const parts = data.split(':');
|
||||||
@@ -40,8 +40,8 @@ describe('CredentialManager', () => {
|
|||||||
// Re-get mocked modules
|
// Re-get mocked modules
|
||||||
fs = require('fs');
|
fs = require('fs');
|
||||||
lockfile = require('proper-lockfile');
|
lockfile = require('proper-lockfile');
|
||||||
keychainManager = require('../keychain-manager');
|
keychainManager = require('../src/security/keychain-manager');
|
||||||
cryptoUtils = require('../crypto-utils');
|
cryptoUtils = require('../src/security/crypto-utils');
|
||||||
|
|
||||||
// Reset mock implementations
|
// Reset mock implementations
|
||||||
fs.existsSync.mockReturnValue(true);
|
fs.existsSync.mockReturnValue(true);
|
||||||
@@ -50,7 +50,7 @@ describe('CredentialManager', () => {
|
|||||||
lockfile.lock.mockResolvedValue(jest.fn().mockResolvedValue());
|
lockfile.lock.mockResolvedValue(jest.fn().mockResolvedValue());
|
||||||
keychainManager.available = false;
|
keychainManager.available = false;
|
||||||
|
|
||||||
credentialManager = require('../credential-manager');
|
credentialManager = require('../src/managers/credential-manager');
|
||||||
credentialManager.cache.clear();
|
credentialManager.cache.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -72,10 +72,10 @@ describe('CredentialManager', () => {
|
|||||||
fs.writeFileSync.mockImplementation(() => {});
|
fs.writeFileSync.mockImplementation(() => {});
|
||||||
lockfile = require('proper-lockfile');
|
lockfile = require('proper-lockfile');
|
||||||
lockfile.lock.mockResolvedValue(jest.fn().mockResolvedValue());
|
lockfile.lock.mockResolvedValue(jest.fn().mockResolvedValue());
|
||||||
keychainManager = require('../keychain-manager');
|
keychainManager = require('../src/security/keychain-manager');
|
||||||
keychainManager.available = true;
|
keychainManager.available = true;
|
||||||
keychainManager.store.mockResolvedValue(true);
|
keychainManager.store.mockResolvedValue(true);
|
||||||
credentialManager = require('../credential-manager');
|
credentialManager = require('../src/managers/credential-manager');
|
||||||
|
|
||||||
const result = await credentialManager.store('test.key', 'value');
|
const result = await credentialManager.store('test.key', 'value');
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
@@ -91,11 +91,11 @@ describe('CredentialManager', () => {
|
|||||||
fs.writeFileSync.mockImplementation(() => {});
|
fs.writeFileSync.mockImplementation(() => {});
|
||||||
lockfile = require('proper-lockfile');
|
lockfile = require('proper-lockfile');
|
||||||
lockfile.lock.mockResolvedValue(jest.fn().mockResolvedValue());
|
lockfile.lock.mockResolvedValue(jest.fn().mockResolvedValue());
|
||||||
keychainManager = require('../keychain-manager');
|
keychainManager = require('../src/security/keychain-manager');
|
||||||
keychainManager.available = true;
|
keychainManager.available = true;
|
||||||
keychainManager.store.mockResolvedValue(false);
|
keychainManager.store.mockResolvedValue(false);
|
||||||
cryptoUtils = require('../crypto-utils');
|
cryptoUtils = require('../src/security/crypto-utils');
|
||||||
credentialManager = require('../credential-manager');
|
credentialManager = require('../src/managers/credential-manager');
|
||||||
|
|
||||||
const result = await credentialManager.store('test.key', 'value');
|
const result = await credentialManager.store('test.key', 'value');
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const TEST_KEY_HEX = TEST_KEY.toString('hex');
|
|||||||
// Load the module once — no jest.resetModules() needed
|
// Load the module once — no jest.resetModules() needed
|
||||||
// We control key state via clearCachedKey() + env vars
|
// We control key state via clearCachedKey() + env vars
|
||||||
process.env.DASHCADDY_ENCRYPTION_KEY = TEST_KEY_HEX;
|
process.env.DASHCADDY_ENCRYPTION_KEY = TEST_KEY_HEX;
|
||||||
const cryptoUtils = require('../crypto-utils');
|
const cryptoUtils = require('../src/security/crypto-utils');
|
||||||
|
|
||||||
describe('Crypto Utils', () => {
|
describe('Crypto Utils', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ const crypto = require('crypto');
|
|||||||
|
|
||||||
// Mock crypto-utils to provide a predictable signing key
|
// Mock crypto-utils to provide a predictable signing key
|
||||||
const mockFixedKey = Buffer.alloc(32, 'test-key-material');
|
const mockFixedKey = Buffer.alloc(32, 'test-key-material');
|
||||||
jest.mock('../crypto-utils', () => ({
|
jest.mock('../src/security/crypto-utils', () => ({
|
||||||
loadOrCreateKey: jest.fn(() => mockFixedKey),
|
loadOrCreateKey: jest.fn(() => mockFixedKey),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ const {
|
|||||||
csrfCookieMiddleware,
|
csrfCookieMiddleware,
|
||||||
csrfValidationMiddleware,
|
csrfValidationMiddleware,
|
||||||
renewCSRFToken
|
renewCSRFToken
|
||||||
} = require('../csrf-protection');
|
} = require('../src/security/csrf-protection');
|
||||||
const { createMockReqRes } = require('./helpers/test-utils');
|
const { createMockReqRes } = require('./helpers/test-utils');
|
||||||
|
|
||||||
describe('CSRF Protection', () => {
|
describe('CSRF Protection', () => {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ jest.mock('dns', () => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const DNSPropagationChecker = require('../dns-propagation');
|
const DNSPropagationChecker = require('../src/dns/dns-propagation');
|
||||||
|
|
||||||
describe('DNSPropagationChecker', () => {
|
describe('DNSPropagationChecker', () => {
|
||||||
let checker;
|
let checker;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ describe('DockerSecurity Module', () => {
|
|||||||
|
|
||||||
// Reset modules to get fresh instance
|
// Reset modules to get fresh instance
|
||||||
jest.resetModules();
|
jest.resetModules();
|
||||||
dockerSecurity = require('../docker-security');
|
dockerSecurity = require('../src/security/docker-security');
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -58,7 +58,7 @@ describe('DockerSecurity Module', () => {
|
|||||||
|
|
||||||
// Force module reload
|
// Force module reload
|
||||||
jest.resetModules();
|
jest.resetModules();
|
||||||
const freshInstance = require('../docker-security');
|
const freshInstance = require('../src/security/docker-security');
|
||||||
const status = freshInstance.getStatus();
|
const status = freshInstance.getStatus();
|
||||||
|
|
||||||
expect(status.trustedImagesCount).toBe(1);
|
expect(status.trustedImagesCount).toBe(1);
|
||||||
@@ -77,7 +77,7 @@ describe('DockerSecurity Module', () => {
|
|||||||
fs.writeFileSync(TEST_CONFIG_FILE, 'INVALID JSON{{{');
|
fs.writeFileSync(TEST_CONFIG_FILE, 'INVALID JSON{{{');
|
||||||
|
|
||||||
jest.resetModules();
|
jest.resetModules();
|
||||||
const freshInstance = require('../docker-security');
|
const freshInstance = require('../src/security/docker-security');
|
||||||
const status = freshInstance.getStatus();
|
const status = freshInstance.getStatus();
|
||||||
|
|
||||||
// Should fall back to default config
|
// Should fall back to default config
|
||||||
@@ -89,7 +89,7 @@ describe('DockerSecurity Module', () => {
|
|||||||
process.env.DOCKER_SECURITY_CONFIG = '/nonexistent/path/config.json';
|
process.env.DOCKER_SECURITY_CONFIG = '/nonexistent/path/config.json';
|
||||||
|
|
||||||
jest.resetModules();
|
jest.resetModules();
|
||||||
const freshInstance = require('../docker-security');
|
const freshInstance = require('../src/security/docker-security');
|
||||||
const status = freshInstance.getStatus();
|
const status = freshInstance.getStatus();
|
||||||
|
|
||||||
// Should fall back to default config
|
// Should fall back to default config
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ jest.mock('../src/utils/logging', () => ({
|
|||||||
LOG_LEVELS: { debug: 0, info: 1, warn: 2, error: 3 }
|
LOG_LEVELS: { debug: 0, info: 1, warn: 2, error: 3 }
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const { errorMiddleware, notFoundHandler } = require('../error-handler');
|
const { errorMiddleware, notFoundHandler } = require('../src/utilities/error-handler');
|
||||||
const {
|
const {
|
||||||
AppError,
|
AppError,
|
||||||
ValidationError,
|
ValidationError,
|
||||||
@@ -20,7 +20,7 @@ const {
|
|||||||
NotFoundError,
|
NotFoundError,
|
||||||
RateLimitError,
|
RateLimitError,
|
||||||
DockerError,
|
DockerError,
|
||||||
} = require('../errors');
|
} = require('../src/utilities/errors');
|
||||||
|
|
||||||
describe('Error Handler', () => {
|
describe('Error Handler', () => {
|
||||||
let req, res, next;
|
let req, res, next;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const {
|
|||||||
CaddyError,
|
CaddyError,
|
||||||
DNSError,
|
DNSError,
|
||||||
ServiceUnavailableError
|
ServiceUnavailableError
|
||||||
} = require('../errors');
|
} = require('../src/utilities/errors');
|
||||||
|
|
||||||
describe('Error Classes', () => {
|
describe('Error Classes', () => {
|
||||||
describe('AppError', () => {
|
describe('AppError', () => {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ describe('HealthChecker', () => {
|
|||||||
fs.writeFileSync.mockImplementation(() => {});
|
fs.writeFileSync.mockImplementation(() => {});
|
||||||
|
|
||||||
// Fresh instance each test
|
// Fresh instance each test
|
||||||
HealthChecker = require('../health-checker').constructor;
|
HealthChecker = require('../src/monitoring/health-checker').constructor;
|
||||||
healthChecker = new HealthChecker();
|
healthChecker = new HealthChecker();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ describe('HealthChecker', () => {
|
|||||||
services: { svc1: { url: 'http://test.local', enabled: true } }
|
services: { svc1: { url: 'http://test.local', enabled: true } }
|
||||||
}));
|
}));
|
||||||
|
|
||||||
HealthChecker = require('../health-checker').constructor;
|
HealthChecker = require('../src/monitoring/health-checker').constructor;
|
||||||
const hc = new HealthChecker();
|
const hc = new HealthChecker();
|
||||||
expect(hc.config.services.svc1).toBeDefined();
|
expect(hc.config.services.svc1).toBeDefined();
|
||||||
});
|
});
|
||||||
@@ -52,7 +52,7 @@ describe('HealthChecker', () => {
|
|||||||
fs.existsSync.mockReturnValue(true);
|
fs.existsSync.mockReturnValue(true);
|
||||||
fs.readFileSync.mockReturnValue('invalid json');
|
fs.readFileSync.mockReturnValue('invalid json');
|
||||||
|
|
||||||
HealthChecker = require('../health-checker').constructor;
|
HealthChecker = require('../src/monitoring/health-checker').constructor;
|
||||||
const hc = new HealthChecker();
|
const hc = new HealthChecker();
|
||||||
expect(hc.config).toEqual({ services: {} });
|
expect(hc.config).toEqual({ services: {} });
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ function buildTestApp(routeFactory, deps, prefix = '/api') {
|
|||||||
const router = routeFactory(deps);
|
const router = routeFactory(deps);
|
||||||
app.use(prefix, router);
|
app.use(prefix, router);
|
||||||
// Error handler
|
// Error handler
|
||||||
const { errorMiddleware } = require('../../error-handler');
|
const { errorMiddleware } = require('../../../src/utilities/error-handler');
|
||||||
app.use(errorMiddleware);
|
app.use(errorMiddleware);
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const {
|
|||||||
isValidPort,
|
isValidPort,
|
||||||
isPrivateIP,
|
isPrivateIP,
|
||||||
validateSecurePath
|
validateSecurePath
|
||||||
} = require('../input-validator');
|
} = require('../src/security/input-validator');
|
||||||
|
|
||||||
describe('Input Validator', () => {
|
describe('Input Validator', () => {
|
||||||
function fail(message) {
|
function fail(message) {
|
||||||
@@ -480,7 +480,7 @@ describe('Input Validator', () => {
|
|||||||
|
|
||||||
// Re-require after mocking fs
|
// Re-require after mocking fs
|
||||||
function getValidateSecurePath() {
|
function getValidateSecurePath() {
|
||||||
return require('../input-validator').validateSecurePath;
|
return require('../src/security/input-validator').validateSecurePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
it('resolves valid path within allowed roots', async () => {
|
it('resolves valid path within allowed roots', async () => {
|
||||||
|
|||||||
@@ -29,13 +29,13 @@ jest.mock('fs', () => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('../docker-maintenance', () => ({
|
jest.mock('../src/docker/docker-maintenance', () => ({
|
||||||
getDiskUsage: jest.fn().mockResolvedValue(null),
|
getDiskUsage: jest.fn().mockResolvedValue(null),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const Docker = require('dockerode');
|
const Docker = require('dockerode');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const logDigest = require('../log-digest');
|
const logDigest = require('../src/security/log-digest');
|
||||||
|
|
||||||
describe('LogDigest (singleton)', () => {
|
describe('LogDigest (singleton)', () => {
|
||||||
let dockerInstance;
|
let dockerInstance;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
* state in beforeEach.
|
* state in beforeEach.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const metrics = require('../metrics');
|
const metrics = require('../src/monitoring/metrics');
|
||||||
|
|
||||||
describe('Metrics (singleton)', () => {
|
describe('Metrics (singleton)', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ jest.mock('nodemailer', () => ({
|
|||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const nodemailer = require('nodemailer');
|
const nodemailer = require('nodemailer');
|
||||||
const NotificationManager = require('../notification-manager');
|
const NotificationManager = require('../src/managers/notification-manager');
|
||||||
|
|
||||||
describe('NotificationManager', () => {
|
describe('NotificationManager', () => {
|
||||||
let nm;
|
let nm;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const { paginate, parsePaginationParams, DEFAULT_LIMIT, MAX_LIMIT } = require('../pagination');
|
const { paginate, parsePaginationParams, DEFAULT_LIMIT, MAX_LIMIT } = require('../src/utilities/pagination');
|
||||||
|
|
||||||
describe('Pagination — DashCaddy list endpoints', () => {
|
describe('Pagination — DashCaddy list endpoints', () => {
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ fs.unlinkSync.mockReturnValue(undefined);
|
|||||||
lockfile.lock.mockResolvedValue(jest.fn().mockResolvedValue());
|
lockfile.lock.mockResolvedValue(jest.fn().mockResolvedValue());
|
||||||
lockfile.check.mockResolvedValue(false);
|
lockfile.check.mockResolvedValue(false);
|
||||||
|
|
||||||
const portLockManager = require('../port-lock-manager');
|
const portLockManager = require('../src/managers/port-lock-manager');
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ fs.existsSync.mockReturnValue(false);
|
|||||||
fs.readFileSync.mockReturnValue('{}');
|
fs.readFileSync.mockReturnValue('{}');
|
||||||
fs.writeFileSync.mockReturnValue(undefined);
|
fs.writeFileSync.mockReturnValue(undefined);
|
||||||
|
|
||||||
const resourceMonitor = require('../resource-monitor');
|
const resourceMonitor = require('../src/managers/resource-monitor');
|
||||||
|
|
||||||
function makeStat(overrides = {}) {
|
function makeStat(overrides = {}) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ function buildApp(mockDeps) {
|
|||||||
const app = express();
|
const app = express();
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
|
|
||||||
const { errorMiddleware } = require('../../error-handler');
|
const { errorMiddleware } = require('../../src/utilities/error-handler');
|
||||||
const containersRouteFactory = require('../../routes/containers');
|
const containersRouteFactory = require('../../routes/containers');
|
||||||
app.use('/api/containers', containersRouteFactory(mockDeps));
|
app.use('/api/containers', containersRouteFactory(mockDeps));
|
||||||
app.use(errorMiddleware);
|
app.use(errorMiddleware);
|
||||||
|
|||||||
@@ -52,21 +52,21 @@ jest.mock('../../platform-paths', () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
// Mock fs-helpers.exists
|
// Mock fs-helpers.exists
|
||||||
jest.mock('../../fs-helpers', () => ({
|
jest.mock('../../src/utilities/fs-helpers', () => ({
|
||||||
exists: jest.fn().mockResolvedValue(true),
|
exists: jest.fn().mockResolvedValue(true),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../url-resolver', () => ({
|
jest.mock('../../src/utilities/url-resolver', () => ({
|
||||||
resolveServiceUrl: jest.fn((id) => `https://${id}.test`),
|
resolveServiceUrl: jest.fn((id) => `https://${id}.test`),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../pagination', () => ({
|
jest.mock('../../src/utilities/pagination', () => ({
|
||||||
paginate: jest.fn((data, params) => ({ data, pagination: null })),
|
paginate: jest.fn((data, params) => ({ data, pagination: null })),
|
||||||
parsePaginationParams: jest.fn(() => null),
|
parsePaginationParams: jest.fn(() => null),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const { exists } = require('../../fs-helpers');
|
const { exists } = require('../../src/utilities/fs-helpers');
|
||||||
const { resolveServiceUrl } = require('../../url-resolver');
|
const { resolveServiceUrl } = require('../../src/utilities/url-resolver');
|
||||||
const { execSync } = require('child_process');
|
const { execSync } = require('child_process');
|
||||||
|
|
||||||
describe('Health Routes', () => {
|
describe('Health Routes', () => {
|
||||||
|
|||||||
@@ -9,27 +9,27 @@ function asyncHandler(fn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mock modules that services.js requires at top-level
|
// Mock modules that services.js requires at top-level
|
||||||
jest.mock('../../constants', () => ({
|
jest.mock('../../src/utilities/constants', () => ({
|
||||||
APP: { USER_AGENTS: { PROBE: 'DashCaddy/1.0' } },
|
APP: { USER_AGENTS: { PROBE: 'DashCaddy/1.0' } },
|
||||||
REGEX: { SUBDOMAIN: /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/ },
|
REGEX: { SUBDOMAIN: /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/ },
|
||||||
TIMEOUTS: { DEFAULT: 10000 },
|
TIMEOUTS: { DEFAULT: 10000 },
|
||||||
HTTP_STATUS: { OK: 200, CREATED: 201, NO_CONTENT: 204, BAD_REQUEST: 400, UNAUTHORIZED: 401, FORBIDDEN: 403, NOT_FOUND: 404, CONFLICT: 409, INTERNAL_ERROR: 500 }
|
HTTP_STATUS: { OK: 200, CREATED: 201, NO_CONTENT: 204, BAD_REQUEST: 400, UNAUTHORIZED: 401, FORBIDDEN: 403, NOT_FOUND: 404, CONFLICT: 409, INTERNAL_ERROR: 500 }
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../input-validator', () => ({
|
jest.mock('../../src/security/input-validator', () => ({
|
||||||
validateServiceConfig: jest.fn(),
|
validateServiceConfig: jest.fn(),
|
||||||
isValidPort: jest.fn(p => p >= 1 && p <= 65535),
|
isValidPort: jest.fn(p => p >= 1 && p <= 65535),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../fs-helpers', () => ({
|
jest.mock('../../src/utilities/fs-helpers', () => ({
|
||||||
exists: jest.fn().mockResolvedValue(true),
|
exists: jest.fn().mockResolvedValue(true),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../url-resolver', () => ({
|
jest.mock('../../src/utilities/url-resolver', () => ({
|
||||||
resolveServiceUrl: jest.fn((id) => `https://${id}.test`),
|
resolveServiceUrl: jest.fn((id) => `https://${id}.test`),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../pagination', () => ({
|
jest.mock('../../src/utilities/pagination', () => ({
|
||||||
paginate: jest.fn((data, params) => ({ data, pagination: null })),
|
paginate: jest.fn((data, params) => ({ data, pagination: null })),
|
||||||
parsePaginationParams: jest.fn(() => null),
|
parsePaginationParams: jest.fn(() => null),
|
||||||
}));
|
}));
|
||||||
@@ -45,8 +45,8 @@ jest.mock('../../src/utils/responses', () => ({
|
|||||||
|
|
||||||
// errors module NOT mocked — used for real ValidationError/NotFoundError/ConflictError
|
// errors module NOT mocked — used for real ValidationError/NotFoundError/ConflictError
|
||||||
|
|
||||||
const { exists } = require('../../fs-helpers');
|
const { exists } = require('../../src/utilities/fs-helpers');
|
||||||
const { validateServiceConfig } = require('../../input-validator');
|
const { validateServiceConfig } = require('../../src/security/input-validator');
|
||||||
|
|
||||||
function createApp(depsOverride = {}) {
|
function createApp(depsOverride = {}) {
|
||||||
const defaultDeps = {
|
const defaultDeps = {
|
||||||
@@ -450,7 +450,7 @@ describe('Services Routes', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('rejects invalid port', async () => {
|
it('rejects invalid port', async () => {
|
||||||
const { isValidPort } = require('../../input-validator');
|
const { isValidPort } = require('../../src/security/input-validator');
|
||||||
isValidPort.mockReturnValue(false);
|
isValidPort.mockReturnValue(false);
|
||||||
const { app } = createApp();
|
const { app } = createApp();
|
||||||
const res = await request(app)
|
const res = await request(app)
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ jest.mock('tls', () => ({
|
|||||||
connect: jest.fn(),
|
connect: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../fs-helpers', () => ({
|
jest.mock('../src/utilities/fs-helpers', () => ({
|
||||||
readJsonFile: jest.fn().mockResolvedValue(null),
|
readJsonFile: jest.fn().mockResolvedValue(null),
|
||||||
writeJsonFile: jest.fn().mockResolvedValue(undefined),
|
writeJsonFile: jest.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const tls = require('tls');
|
const tls = require('tls');
|
||||||
const fsHelpers = require('../fs-helpers');
|
const fsHelpers = require('../src/utilities/fs-helpers');
|
||||||
const SSLMonitor = require('../ssl-monitor');
|
const SSLMonitor = require('../src/monitoring/ssl-monitor');
|
||||||
|
|
||||||
function makeSocket({ cert = null, error = null } = {}) {
|
function makeSocket({ cert = null, error = null } = {}) {
|
||||||
const { EventEmitter } = require('events');
|
const { EventEmitter } = require('events');
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ jest.mock('fs', () => ({
|
|||||||
|
|
||||||
const lockfile = require('proper-lockfile');
|
const lockfile = require('proper-lockfile');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const StateManager = require('../state-manager');
|
const StateManager = require('../src/managers/state-manager');
|
||||||
|
|
||||||
describe('StateManager', () => {
|
describe('StateManager', () => {
|
||||||
let sm;
|
let sm;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ fs.existsSync.mockReturnValue(false);
|
|||||||
fs.readFileSync.mockReturnValue('{}');
|
fs.readFileSync.mockReturnValue('{}');
|
||||||
fs.writeFileSync.mockReturnValue(undefined);
|
fs.writeFileSync.mockReturnValue(undefined);
|
||||||
|
|
||||||
const updateManager = require('../update-manager');
|
const updateManager = require('../src/managers/update-manager');
|
||||||
|
|
||||||
// Helper to create a fake https request that responds with a given statusCode/headers/body
|
// Helper to create a fake https request that responds with a given statusCode/headers/body
|
||||||
function mockHttpsResponse({ statusCode = 200, headers = {}, body = '' } = {}) {
|
function mockHttpsResponse({ statusCode = 200, headers = {}, body = '' } = {}) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const { resolveServiceUrl } = require('../url-resolver');
|
const { resolveServiceUrl } = require('../src/utilities/url-resolver');
|
||||||
|
|
||||||
describe('URL Resolver — DashCaddy service URL resolution', () => {
|
describe('URL Resolver — DashCaddy service URL resolution', () => {
|
||||||
const buildServiceUrl = jest.fn(id => `https://${id}.sami`);
|
const buildServiceUrl = jest.fn(id => `https://${id}.sami`);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const yaml = require('js-yaml');
|
const yaml = require('js-yaml');
|
||||||
const { DOCKER, REGEX } = require('../../constants');
|
const { DOCKER, REGEX } = require('../../../src/utilities/constants');
|
||||||
const { ValidationError } = require('../../errors');
|
const { ValidationError } = require('../../../src/utilities/errors');
|
||||||
const platformPaths = require('../../platform-paths');
|
const platformPaths = require('../../platform-paths');
|
||||||
const { ok } = require('../../src/utils/responses');
|
const { ok } = require('../src/utils/responses');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Docker Compose import routes
|
* Docker Compose import routes
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ const express = require('express');
|
|||||||
const fsp = require('fs').promises;
|
const fsp = require('fs').promises;
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const validatorLib = require('validator');
|
const validatorLib = require('validator');
|
||||||
const { REGEX, DOCKER } = require('../../constants');
|
const { REGEX, DOCKER } = require('../../../src/utilities/constants');
|
||||||
const { isValidPort } = require('../../input-validator');
|
const { isValidPort } = require('../../../src/security/input-validator');
|
||||||
const { exists } = require('../../fs-helpers');
|
const { exists } = require('../../../src/utilities/fs-helpers');
|
||||||
const platformPaths = require('../../platform-paths');
|
const platformPaths = require('../../platform-paths');
|
||||||
const { ValidationError } = require('../../errors');
|
const { ValidationError } = require('../../../src/utilities/errors');
|
||||||
const { logError } = require('../../src/utils/logging');
|
const { logError } = require('../src/utils/logging');
|
||||||
const { ok } = require('../../src/utils/responses');
|
const { ok } = require('../src/utils/responses');
|
||||||
/**
|
/**
|
||||||
* Apps deployment routes factory
|
* Apps deployment routes factory
|
||||||
* @param {Object} deps - Explicit dependencies
|
* @param {Object} deps - Explicit dependencies
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ const fs = require('fs');
|
|||||||
const fsp = require('fs').promises;
|
const fsp = require('fs').promises;
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const { REGEX, DOCKER } = require('../../constants');
|
const { REGEX, DOCKER } = require('../../../src/utilities/constants');
|
||||||
const { exists } = require('../../fs-helpers');
|
const { exists } = require('../../../src/utilities/fs-helpers');
|
||||||
const platformPaths = require('../../platform-paths');
|
const platformPaths = require('../../platform-paths');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { exists } = require('../../fs-helpers');
|
const { exists } = require('../../../src/utilities/fs-helpers');
|
||||||
const { logError } = require('../../src/utils/logging');
|
const { logError } = require('../src/utils/logging');
|
||||||
const { ok } = require('../../src/utils/responses');
|
const { ok } = require('../src/utils/responses');
|
||||||
|
|
||||||
module.exports = function({
|
module.exports = function({
|
||||||
docker, caddy, servicesStateManager, asyncHandler, log, helpers,
|
docker, caddy, servicesStateManager, asyncHandler, log, helpers,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const { DOCKER } = require('../../constants');
|
const { DOCKER } = require('../../../src/utilities/constants');
|
||||||
const { ok, validationError, notFound, errorResponse } = require('../../src/utils/responses');
|
const { ok, validationError, notFound, errorResponse } = require('../../../src/utilities/responses');
|
||||||
|
|
||||||
const DEFAULT_BACKUP_DIR = process.env.BACKUP_DIR || path.join(__dirname, '..', 'backups');
|
const DEFAULT_BACKUP_DIR = process.env.BACKUP_DIR || path.join(__dirname, '..', 'backups');
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { exists } = require('../../fs-helpers');
|
const { exists } = require('../../../src/utilities/fs-helpers');
|
||||||
/**
|
/**
|
||||||
* Apps templates routes factory
|
* Apps templates routes factory
|
||||||
* @param {Object} deps - Explicit dependencies
|
* @param {Object} deps - Explicit dependencies
|
||||||
@@ -19,8 +19,8 @@ const { exists } = require('../../fs-helpers');
|
|||||||
* @param {string} deps.SERVICES_FILE - Services file path
|
* @param {string} deps.SERVICES_FILE - Services file path
|
||||||
* @returns {express.Router}
|
* @returns {express.Router}
|
||||||
*/
|
*/
|
||||||
const { REGEX } = require('../../constants');
|
const { REGEX } = require('../../../src/utilities/constants');
|
||||||
const { ok } = require('../../src/utils/responses');
|
const { ok } = require('../src/utils/responses');
|
||||||
|
|
||||||
module.exports = function({
|
module.exports = function({
|
||||||
servicesStateManager, asyncHandler, helpers,
|
servicesStateManager, asyncHandler, helpers,
|
||||||
@@ -55,7 +55,7 @@ module.exports = function({
|
|||||||
const { appId } = req.params;
|
const { appId } = req.params;
|
||||||
const template = ctx.APP_TEMPLATES[appId];
|
const template = ctx.APP_TEMPLATES[appId];
|
||||||
if (!template) {
|
if (!template) {
|
||||||
const { NotFoundError } = require('../../errors');
|
const { NotFoundError } = require('../../../src/utilities/errors');
|
||||||
throw new NotFoundError('App template');
|
throw new NotFoundError('App template');
|
||||||
}
|
}
|
||||||
ok(res, { template });
|
ok(res, { template });
|
||||||
@@ -90,7 +90,7 @@ module.exports = function({
|
|||||||
// Update subdomain for deployed app
|
// Update subdomain for deployed app
|
||||||
router.post('/update-subdomain', asyncHandler(async (req, res) => {
|
router.post('/update-subdomain', asyncHandler(async (req, res) => {
|
||||||
const { serviceId, oldSubdomain, newSubdomain, containerId, ip } = req.body;
|
const { serviceId, oldSubdomain, newSubdomain, containerId, ip } = req.body;
|
||||||
const { ValidationError } = require('../../errors');
|
const { ValidationError } = require('../../../src/utilities/errors');
|
||||||
|
|
||||||
if (!oldSubdomain || typeof oldSubdomain !== 'string') {
|
if (!oldSubdomain || typeof oldSubdomain !== 'string') {
|
||||||
throw new ValidationError('oldSubdomain is required');
|
throw new ValidationError('oldSubdomain is required');
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { APP_PORTS, ARR_SERVICES } = require('../../constants');
|
const { APP_PORTS, ARR_SERVICES } = require('../../../src/utilities/constants');
|
||||||
const { validateURL, validateToken } = require('../../input-validator');
|
const { validateURL, validateToken } = require('../../../src/security/input-validator');
|
||||||
const { ValidationError, AuthenticationError, NotFoundError } = require('../../errors');
|
const { ValidationError, AuthenticationError, NotFoundError } = require('../../../src/utilities/errors');
|
||||||
const { logError } = require('../../src/utils/logging');
|
const { logError } = require('../src/utils/logging');
|
||||||
const { ok, successMessage } = require('../../src/utils/responses');
|
const { ok, successMessage } = require('../src/utils/responses');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Arr configuration routes factory
|
* Arr configuration routes factory
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { validateURL, validateToken } = require('../../input-validator');
|
const { validateURL, validateToken } = require('../../../src/security/input-validator');
|
||||||
const { ValidationError } = require('../../errors');
|
const { ValidationError } = require('../../../src/utilities/errors');
|
||||||
const { ok, successMessage } = require('../../src/utils/responses');
|
const { ok, successMessage } = require('../src/utils/responses');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Arr credentials routes factory
|
* Arr credentials routes factory
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { APP_PORTS, ARR_SERVICES } = require('../../constants');
|
const { APP_PORTS, ARR_SERVICES } = require('../../../src/utilities/constants');
|
||||||
const { ok } = require('../../src/utils/responses');
|
const { ok } = require('../src/utils/responses');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Arr service detection routes factory
|
* Arr service detection routes factory
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const { APP_PORTS } = require('../../constants');
|
const { APP_PORTS } = require('../../../src/utilities/constants');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Arr helpers factory
|
* Arr helpers factory
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { APP_PORTS } = require('../../constants');
|
const { APP_PORTS } = require('../../../src/utilities/constants');
|
||||||
const { ok } = require('../../src/utils/responses');
|
const { ok } = require('../src/utils/responses');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plex routes factory
|
* Plex routes factory
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { APP_PORTS } = require('../../constants');
|
const { APP_PORTS } = require('../../../src/utilities/constants');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Arr smart-connect routes factory
|
* Arr smart-connect routes factory
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { ValidationError, ForbiddenError, NotFoundError } = require('../../errors');
|
const { ValidationError, ForbiddenError, NotFoundError } = require('../../../src/utilities/errors');
|
||||||
const { ok, successMessage } = require('../../src/utils/responses');
|
const { ok, successMessage } = require('../src/utils/responses');
|
||||||
/**
|
/**
|
||||||
* Auth API keys routes factory
|
* Auth API keys routes factory
|
||||||
* @param {Object} deps - Explicit dependencies
|
* @param {Object} deps - Explicit dependencies
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
const { SESSION_TTL, APP, PLEX, TIMEOUTS, buildMediaAuth } = require('../../constants');
|
const { SESSION_TTL, APP, PLEX, TIMEOUTS, buildMediaAuth } = require('../../../src/utilities/constants');
|
||||||
const { createCache, CACHE_CONFIGS } = require('../../cache-config');
|
const { createCache, CACHE_CONFIGS } = require('../../../src/utilities/cache-config');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auth session handlers routes factory
|
* Auth session handlers routes factory
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { SESSION_TTL, APP, PLEX, TIMEOUTS, buildMediaAuth } = require('../../constants');
|
const { SESSION_TTL, APP, PLEX, TIMEOUTS, buildMediaAuth } = require('../../../src/utilities/constants');
|
||||||
const { AuthenticationError, NotFoundError } = require('../../errors');
|
const { AuthenticationError, NotFoundError } = require('../../../src/utilities/errors');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auth SSO gate routes factory
|
* Auth SSO gate routes factory
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { ValidationError, AuthenticationError } = require('../../errors');
|
const { ValidationError, AuthenticationError } = require('../../../src/utilities/errors');
|
||||||
const { ok, successMessage } = require('../../src/utils/responses');
|
const { ok, successMessage } = require('../src/utils/responses');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auth TOTP routes factory
|
* Auth TOTP routes factory
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { success } = require('../src/utils/responses');
|
const { success } = require('../src/utils/responses');
|
||||||
const { ValidationError, NotFoundError } = require('../errors');
|
const { ValidationError, NotFoundError } = require('../src/utilities/errors');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auto-restart route factory
|
* Auto-restart route factory
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ module.exports = function({ backupManager, licenseManager, asyncHandler }) {
|
|||||||
const { appId, enabled, schedule, retention, runImmediately, destination, destinationPath } = req.body;
|
const { appId, enabled, schedule, retention, runImmediately, destination, destinationPath } = req.body;
|
||||||
|
|
||||||
if (!appId) {
|
if (!appId) {
|
||||||
const { ValidationError } = require('../errors');
|
const { ValidationError } = require('../src/utilities/errors');
|
||||||
throw new ValidationError('appId is required');
|
throw new ValidationError('appId is required');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ module.exports = function({ backupManager, licenseManager, asyncHandler }) {
|
|||||||
const config = backupManager.getConfig();
|
const config = backupManager.getConfig();
|
||||||
|
|
||||||
if (!config.backups || !config.backups[appId]) {
|
if (!config.backups || !config.backups[appId]) {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError(`No backup schedule found for app: ${appId}`, 'DC-404');
|
throw new NotFoundError(`No backup schedule found for app: ${appId}`, 'DC-404');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ module.exports = function({ backupManager, licenseManager, asyncHandler }) {
|
|||||||
|
|
||||||
const backupConfig = config.backups && config.backups[appId];
|
const backupConfig = config.backups && config.backups[appId];
|
||||||
if (!backupConfig) {
|
if (!backupConfig) {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError(`No backup schedule found for app: ${appId}`, 'DC-404');
|
throw new NotFoundError(`No backup schedule found for app: ${appId}`, 'DC-404');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,13 +229,13 @@ module.exports = function({ backupManager, licenseManager, asyncHandler }) {
|
|||||||
|
|
||||||
// Security: prevent path traversal
|
// Security: prevent path traversal
|
||||||
if (filename.includes('..') || filename.includes('/') || filename.includes('\\')) {
|
if (filename.includes('..') || filename.includes('/') || filename.includes('\\')) {
|
||||||
const { ValidationError } = require('../errors');
|
const { ValidationError } = require('../src/utilities/errors');
|
||||||
throw new ValidationError('Invalid filename');
|
throw new ValidationError('Invalid filename');
|
||||||
}
|
}
|
||||||
|
|
||||||
const filepath = path.join(DEFAULT_BACKUP_DIR, filename);
|
const filepath = path.join(DEFAULT_BACKUP_DIR, filename);
|
||||||
if (!fs.existsSync(filepath)) {
|
if (!fs.existsSync(filepath)) {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError(`Backup file not found: ${filename}`, 'DC-404');
|
throw new NotFoundError(`Backup file not found: ${filename}`, 'DC-404');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,13 +365,13 @@ module.exports = function({ backupManager, licenseManager, asyncHandler }) {
|
|||||||
|
|
||||||
// Security: prevent path traversal
|
// Security: prevent path traversal
|
||||||
if (filename.includes('..') || filename.includes('/') || filename.includes('\\')) {
|
if (filename.includes('..') || filename.includes('/') || filename.includes('\\')) {
|
||||||
const { ValidationError } = require('../errors');
|
const { ValidationError } = require('../src/utilities/errors');
|
||||||
throw new ValidationError('Invalid filename');
|
throw new ValidationError('Invalid filename');
|
||||||
}
|
}
|
||||||
|
|
||||||
const filepath = path.join(DEFAULT_BACKUP_DIR, filename);
|
const filepath = path.join(DEFAULT_BACKUP_DIR, filename);
|
||||||
if (!fs.existsSync(filepath)) {
|
if (!fs.existsSync(filepath)) {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError(`Backup file not found: ${filename}`, 'DC-404');
|
throw new NotFoundError(`Backup file not found: ${filename}`, 'DC-404');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,7 +502,7 @@ module.exports = function({ backupManager, licenseManager, asyncHandler }) {
|
|||||||
router.post('/backups/test-destination', asyncHandler(async (req, res) => {
|
router.post('/backups/test-destination', asyncHandler(async (req, res) => {
|
||||||
const destination = req.body;
|
const destination = req.body;
|
||||||
if (!destination || !destination.type) {
|
if (!destination || !destination.type) {
|
||||||
const { ValidationError } = require('../errors');
|
const { ValidationError } = require('../src/utilities/errors');
|
||||||
throw new ValidationError('destination.type is required');
|
throw new ValidationError('destination.type is required');
|
||||||
}
|
}
|
||||||
const result = await backupManager.testDestination(destination);
|
const result = await backupManager.testDestination(destination);
|
||||||
@@ -512,10 +512,10 @@ module.exports = function({ backupManager, licenseManager, asyncHandler }) {
|
|||||||
// Get cloud credentials (masked) for a provider
|
// Get cloud credentials (masked) for a provider
|
||||||
// Provider: dropbox | webdav | sftp
|
// Provider: dropbox | webdav | sftp
|
||||||
router.get('/backups/credentials/:provider', asyncHandler(async (req, res) => {
|
router.get('/backups/credentials/:provider', asyncHandler(async (req, res) => {
|
||||||
const credentialManager = require('../credential-manager');
|
const credentialManager = require('../src/managers/credential-manager');
|
||||||
const provider = req.params.provider;
|
const provider = req.params.provider;
|
||||||
if (!['dropbox', 'webdav', 'sftp'].includes(provider)) {
|
if (!['dropbox', 'webdav', 'sftp'].includes(provider)) {
|
||||||
const { ValidationError } = require('../errors');
|
const { ValidationError } = require('../src/utilities/errors');
|
||||||
throw new ValidationError('Invalid provider');
|
throw new ValidationError('Invalid provider');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -544,8 +544,8 @@ module.exports = function({ backupManager, licenseManager, asyncHandler }) {
|
|||||||
|
|
||||||
// Save cloud credentials for a provider
|
// Save cloud credentials for a provider
|
||||||
router.post('/backups/credentials/:provider', asyncHandler(async (req, res) => {
|
router.post('/backups/credentials/:provider', asyncHandler(async (req, res) => {
|
||||||
const credentialManager = require('../credential-manager');
|
const credentialManager = require('../src/managers/credential-manager');
|
||||||
const { ValidationError } = require('../errors');
|
const { ValidationError } = require('../src/utilities/errors');
|
||||||
const provider = req.params.provider;
|
const provider = req.params.provider;
|
||||||
|
|
||||||
if (!['dropbox', 'webdav', 'sftp'].includes(provider)) {
|
if (!['dropbox', 'webdav', 'sftp'].includes(provider)) {
|
||||||
@@ -585,8 +585,8 @@ module.exports = function({ backupManager, licenseManager, asyncHandler }) {
|
|||||||
|
|
||||||
// Delete cloud credentials for a provider
|
// Delete cloud credentials for a provider
|
||||||
router.delete('/backups/credentials/:provider', asyncHandler(async (req, res) => {
|
router.delete('/backups/credentials/:provider', asyncHandler(async (req, res) => {
|
||||||
const credentialManager = require('../credential-manager');
|
const credentialManager = require('../src/managers/credential-manager');
|
||||||
const { ValidationError } = require('../errors');
|
const { ValidationError } = require('../src/utilities/errors');
|
||||||
const provider = req.params.provider;
|
const provider = req.params.provider;
|
||||||
|
|
||||||
if (!['dropbox', 'webdav', 'sftp'].includes(provider)) {
|
if (!['dropbox', 'webdav', 'sftp'].includes(provider)) {
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ const express = require('express');
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const fsp = require('fs').promises;
|
const fsp = require('fs').promises;
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { exists, isAccessible } = require('../fs-helpers');
|
const { exists, isAccessible } = require('../src/utilities/fs-helpers');
|
||||||
const { paginate, parsePaginationParams } = require('../pagination');
|
const { paginate, parsePaginationParams } = require('../src/utilities/pagination');
|
||||||
const { ValidationError, ForbiddenError } = require('../errors');
|
const { ValidationError, ForbiddenError } = require('../src/utilities/errors');
|
||||||
const { ok } = require('../src/utils/responses');
|
const { ok } = require('../src/utils/responses');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,7 +99,7 @@ module.exports = function({ asyncHandler, validateSecurePath, auditLogger, docke
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!await exists(resolvedPath)) {
|
if (!await exists(resolvedPath)) {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError('Path');
|
throw new NotFoundError('Path');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ const fs = require('fs');
|
|||||||
const fsp = require('fs').promises;
|
const fsp = require('fs').promises;
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { execSync } = require('child_process');
|
const { execSync } = require('child_process');
|
||||||
const { exists } = require('../fs-helpers');
|
const { exists } = require('../src/utilities/fs-helpers');
|
||||||
const { ValidationError } = require('../errors');
|
const { ValidationError } = require('../src/utilities/errors');
|
||||||
const { ok } = require('../src/utils/responses');
|
const { ok } = require('../src/utils/responses');
|
||||||
const platformPaths = require('../platform-paths');
|
const platformPaths = require('../platform-paths');
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ module.exports = function(ctx) {
|
|||||||
if (await exists(certInfoPath)) {
|
if (await exists(certInfoPath)) {
|
||||||
certInfoFile = certInfoPath;
|
certInfoFile = certInfoPath;
|
||||||
} else {
|
} else {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError('CA certificate information');
|
throw new NotFoundError('CA certificate information');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ module.exports = function(ctx) {
|
|||||||
if (await exists(dashcaCertPath)) certPath = dashcaCertPath;
|
if (await exists(dashcaCertPath)) certPath = dashcaCertPath;
|
||||||
else if (await exists(hostCertPath)) certPath = hostCertPath;
|
else if (await exists(hostCertPath)) certPath = hostCertPath;
|
||||||
else {
|
else {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError('Root CA certificate');
|
throw new NotFoundError('Root CA certificate');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ module.exports = function(ctx) {
|
|||||||
if (await exists(certInfoPath)) {
|
if (await exists(certInfoPath)) {
|
||||||
certInfoFile = certInfoPath;
|
certInfoFile = certInfoPath;
|
||||||
} else {
|
} else {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError('CA certificate information. Deploy DashCA first or ensure cert-info.json exists.');
|
throw new NotFoundError('CA certificate information. Deploy DashCA first or ensure cert-info.json exists.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ module.exports = function(ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!templateContent) {
|
if (!templateContent) {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError(`Install script template (${templateName})`);
|
throw new NotFoundError(`Install script template (${templateName})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { success } = require('../src/utils/responses');
|
const { success } = require('../src/utils/responses');
|
||||||
const { ValidationError, NotFoundError } = require('../errors');
|
const { ValidationError, NotFoundError } = require('../src/utilities/errors');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Config-drift route factory
|
* Config-drift route factory
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const fsp = require('fs').promises;
|
const fsp = require('fs').promises;
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { LIMITS } = require('../../constants');
|
const { LIMITS } = require('../../../src/utilities/constants');
|
||||||
const { exists } = require('../../fs-helpers');
|
const { exists } = require('../../../src/utilities/fs-helpers');
|
||||||
const { ValidationError } = require('../../errors');
|
const { ValidationError } = require('../../../src/utilities/errors');
|
||||||
const platformPaths = require('../../platform-paths');
|
const platformPaths = require('../../platform-paths');
|
||||||
const { ok, successMessage } = require('../../src/utils/responses');
|
const { ok, successMessage } = require('../src/utils/responses');
|
||||||
/**
|
/**
|
||||||
* Config assets routes factory
|
* Config assets routes factory
|
||||||
* @param {Object} deps - Explicit dependencies
|
* @param {Object} deps - Explicit dependencies
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
const fsp = require('fs').promises;
|
const fsp = require('fs').promises;
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { CADDY } = require('../../constants');
|
const { CADDY } = require('../../../src/utilities/constants');
|
||||||
const { exists } = require('../../fs-helpers');
|
const { exists } = require('../../../src/utilities/fs-helpers');
|
||||||
const { ValidationError, AuthenticationError } = require('../../errors');
|
const { ValidationError, AuthenticationError } = require('../../../src/utilities/errors');
|
||||||
const platformPaths = require('../../platform-paths');
|
const platformPaths = require('../../platform-paths');
|
||||||
const { ok } = require('../../src/utils/responses');
|
const { ok } = require('../src/utils/responses');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Config backup routes factory
|
* Config backup routes factory
|
||||||
@@ -380,7 +380,7 @@ module.exports = function(deps) {
|
|||||||
if (results.restored.includes('encryptionKey')) {
|
if (results.restored.includes('encryptionKey')) {
|
||||||
try {
|
try {
|
||||||
// Clear the cached key so crypto-utils reloads from the new file on next use
|
// Clear the cached key so crypto-utils reloads from the new file on next use
|
||||||
const cryptoUtils = require('../../crypto-utils');
|
const cryptoUtils = require('../../../src/security/crypto-utils');
|
||||||
if (typeof cryptoUtils.clearCachedKey === 'function') {
|
if (typeof cryptoUtils.clearCachedKey === 'function') {
|
||||||
cryptoUtils.clearCachedKey();
|
cryptoUtils.clearCachedKey();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const fsp = require('fs').promises;
|
const fsp = require('fs').promises;
|
||||||
const { validateConfig } = require('../../config-schema');
|
const { validateConfig } = require('../../../src/utilities/config-schema');
|
||||||
const { exists } = require('../../fs-helpers');
|
const { exists } = require('../../../src/utilities/fs-helpers');
|
||||||
const { ValidationError } = require('../../errors');
|
const { ValidationError } = require('../../../src/utilities/errors');
|
||||||
const { ok, successMessage } = require('../../src/utils/responses');
|
const { ok, successMessage } = require('../src/utils/responses');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Config settings routes factory
|
* Config settings routes factory
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { DOCKER } = require('../constants');
|
const { DOCKER } = require('../src/utilities/constants');
|
||||||
const { paginate, parsePaginationParams } = require('../pagination');
|
const { paginate, parsePaginationParams } = require('../src/utilities/pagination');
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
const { success } = require('../src/utils/responses');
|
const { success } = require('../src/utils/responses');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { success, error: errorResponse } = require('../src/utils/responses');
|
const { success, error: errorResponse } = require('../src/utils/responses');
|
||||||
const { NotFoundError, ValidationError } = require('../errors');
|
const { NotFoundError, ValidationError } = require('../src/utilities/errors');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dependencies route factory
|
* Dependencies route factory
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ const express = require('express');
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const fsp = require('fs').promises;
|
const fsp = require('fs').promises;
|
||||||
const validatorLib = require('validator');
|
const validatorLib = require('validator');
|
||||||
const { APP, TIMEOUTS, CADDY, DNS_RECORD_TYPES, REGEX, SESSION_TTL } = require('../constants');
|
const { APP, TIMEOUTS, CADDY, DNS_RECORD_TYPES, REGEX, SESSION_TTL } = require('../src/utilities/constants');
|
||||||
const { exists } = require('../fs-helpers');
|
const { exists } = require('../src/utilities/fs-helpers');
|
||||||
const { success, error: errorResponse } = require('../src/utils/responses');
|
const { success, error: errorResponse } = require('../src/utils/responses');
|
||||||
const { ValidationError, AuthenticationError, NotFoundError } = require('../errors');
|
const { ValidationError, AuthenticationError, NotFoundError } = require('../src/utilities/errors');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DNS routes factory
|
* DNS routes factory
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { success } = require('../src/utils/responses');
|
const { success } = require('../src/utils/responses');
|
||||||
const { ValidationError } = require('../errors');
|
const { ValidationError } = require('../src/utilities/errors');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Docker resources route factory (volumes, networks, disk usage)
|
* Docker resources route factory (volumes, networks, disk usage)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const fsp = require('fs').promises;
|
const fsp = require('fs').promises;
|
||||||
const { exists } = require('../fs-helpers');
|
const { exists } = require('../src/utilities/fs-helpers');
|
||||||
const { paginate, parsePaginationParams } = require('../pagination');
|
const { paginate, parsePaginationParams } = require('../src/utilities/pagination');
|
||||||
const { success } = require('../src/utils/responses');
|
const { success } = require('../src/utils/responses');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ const express = require('express');
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { execSync } = require('child_process');
|
const { execSync } = require('child_process');
|
||||||
const { TIMEOUTS } = require('../constants');
|
const { TIMEOUTS } = require('../src/utilities/constants');
|
||||||
const { exists } = require('../fs-helpers');
|
const { exists } = require('../src/utilities/fs-helpers');
|
||||||
const { paginate, parsePaginationParams } = require('../pagination');
|
const { paginate, parsePaginationParams } = require('../src/utilities/pagination');
|
||||||
const platformPaths = require('../platform-paths');
|
const platformPaths = require('../platform-paths');
|
||||||
const { resolveServiceUrl } = require('../url-resolver');
|
const { resolveServiceUrl } = require('../src/utilities/url-resolver');
|
||||||
const { success, error: errorResponse, errorResponse: sendError, ok, notFound } = require('../src/utils/responses');
|
const { success, error: errorResponse, errorResponse: sendError, ok, notFound } = require('../src/utils/responses');
|
||||||
const { ValidationError } = require('../errors');
|
const { ValidationError } = require('../src/utilities/errors');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Health routes factory
|
* Health routes factory
|
||||||
@@ -190,7 +190,7 @@ module.exports = function({
|
|||||||
|
|
||||||
// Load service config
|
// Load service config
|
||||||
if (!await exists(SERVICES_FILE)) {
|
if (!await exists(SERVICES_FILE)) {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError('Services file');
|
throw new NotFoundError('Services file');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,7 +199,7 @@ module.exports = function({
|
|||||||
const service = services.find(s => (s.id || s.name?.toLowerCase()) === serviceId);
|
const service = services.find(s => (s.id || s.name?.toLowerCase()) === serviceId);
|
||||||
|
|
||||||
if (!service) {
|
if (!service) {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError('Service');
|
throw new NotFoundError('Service');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,7 +331,7 @@ module.exports = function({
|
|||||||
const hours = parseInt(req.query.hours) || 24;
|
const hours = parseInt(req.query.hours) || 24;
|
||||||
const stats = healthChecker.getServiceStats(req.params.serviceId, hours);
|
const stats = healthChecker.getServiceStats(req.params.serviceId, hours);
|
||||||
if (!stats) {
|
if (!stats) {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError('Service');
|
throw new NotFoundError('Service');
|
||||||
}
|
}
|
||||||
success(res, { stats });
|
success(res, { stats });
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { success, error: errorResponse } = require('../src/utils/responses');
|
const { success, error: errorResponse } = require('../src/utils/responses');
|
||||||
const { ValidationError } = require('../errors');
|
const { ValidationError } = require('../src/utilities/errors');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* License routes factory
|
* License routes factory
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ const express = require('express');
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const fsp = require('fs').promises;
|
const fsp = require('fs').promises;
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { exists } = require('../fs-helpers');
|
const { exists } = require('../src/utilities/fs-helpers');
|
||||||
const { paginate, parsePaginationParams } = require('../pagination');
|
const { paginate, parsePaginationParams } = require('../src/utilities/pagination');
|
||||||
const { NotFoundError, ValidationError, ForbiddenError } = require('../errors');
|
const { NotFoundError, ValidationError, ForbiddenError } = require('../src/utilities/errors');
|
||||||
const { ok } = require('../src/utils/responses');
|
const { ok } = require('../src/utils/responses');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,7 +48,7 @@ module.exports = function({ asyncHandler, docker, logDigest, dockerMaintenance }
|
|||||||
info = await container.inspect();
|
info = await container.inspect();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.statusCode === 404 || (err.message && err.message.includes('no such container'))) {
|
if (err.statusCode === 404 || (err.message && err.message.includes('no such container'))) {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError(`Container ${containerId}`);
|
throw new NotFoundError(`Container ${containerId}`);
|
||||||
}
|
}
|
||||||
throw err;
|
throw err;
|
||||||
@@ -97,7 +97,7 @@ module.exports = function({ asyncHandler, docker, logDigest, dockerMaintenance }
|
|||||||
await container.inspect();
|
await container.inspect();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.statusCode === 404 || (err.message && err.message.includes('no such container'))) {
|
if (err.statusCode === 404 || (err.message && err.message.includes('no such container'))) {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError(`Container ${containerId}`);
|
throw new NotFoundError(`Container ${containerId}`);
|
||||||
}
|
}
|
||||||
throw err;
|
throw err;
|
||||||
@@ -232,7 +232,7 @@ module.exports = function({ asyncHandler, docker, logDigest, dockerMaintenance }
|
|||||||
try {
|
try {
|
||||||
resolvedPath = await fsp.realpath(normalizedPath);
|
resolvedPath = await fsp.realpath(normalizedPath);
|
||||||
} catch {
|
} catch {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError('Log file');
|
throw new NotFoundError('Log file');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +247,7 @@ module.exports = function({ asyncHandler, docker, logDigest, dockerMaintenance }
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!await exists(resolvedPath)) {
|
if (!await exists(resolvedPath)) {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError('Log file');
|
throw new NotFoundError('Log file');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ module.exports = function({ resourceMonitor, docker, asyncHandler, log, notifica
|
|||||||
router.get('/monitoring/stats/:containerId', asyncHandler(async (req, res) => {
|
router.get('/monitoring/stats/:containerId', asyncHandler(async (req, res) => {
|
||||||
const stats = resourceMonitor.getCurrentStats(req.params.containerId);
|
const stats = resourceMonitor.getCurrentStats(req.params.containerId);
|
||||||
if (!stats) {
|
if (!stats) {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError('Container');
|
throw new NotFoundError('Container');
|
||||||
}
|
}
|
||||||
success(res, { stats });
|
success(res, { stats });
|
||||||
@@ -55,7 +55,7 @@ module.exports = function({ resourceMonitor, docker, asyncHandler, log, notifica
|
|||||||
const startTime = parseInt(req.query.startTime, 10);
|
const startTime = parseInt(req.query.startTime, 10);
|
||||||
const endTime = parseInt(req.query.endTime, 10);
|
const endTime = parseInt(req.query.endTime, 10);
|
||||||
if (Number.isNaN(startTime) || Number.isNaN(endTime) || startTime >= endTime) {
|
if (Number.isNaN(startTime) || Number.isNaN(endTime) || startTime >= endTime) {
|
||||||
const { ValidationError } = require('../errors');
|
const { ValidationError } = require('../src/utilities/errors');
|
||||||
throw new ValidationError('Invalid startTime/endTime');
|
throw new ValidationError('Invalid startTime/endTime');
|
||||||
}
|
}
|
||||||
const result = resourceMonitor.getHistoryByRange(containerId, startTime, endTime);
|
const result = resourceMonitor.getHistoryByRange(containerId, startTime, endTime);
|
||||||
@@ -74,7 +74,7 @@ module.exports = function({ resourceMonitor, docker, asyncHandler, log, notifica
|
|||||||
const hours = parseInt(req.query.hours) || 24;
|
const hours = parseInt(req.query.hours) || 24;
|
||||||
const aggregated = resourceMonitor.getAggregatedStats(req.params.containerId, hours);
|
const aggregated = resourceMonitor.getAggregatedStats(req.params.containerId, hours);
|
||||||
if (!aggregated) {
|
if (!aggregated) {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError('Monitoring data');
|
throw new NotFoundError('Monitoring data');
|
||||||
}
|
}
|
||||||
success(res, { aggregated, hours });
|
success(res, { aggregated, hours });
|
||||||
@@ -92,7 +92,7 @@ module.exports = function({ resourceMonitor, docker, asyncHandler, log, notifica
|
|||||||
router.post('/monitoring/alerts/config', asyncHandler(async (req, res) => {
|
router.post('/monitoring/alerts/config', asyncHandler(async (req, res) => {
|
||||||
const { configs } = req.body;
|
const { configs } = req.body;
|
||||||
if (!configs || typeof configs !== 'object') {
|
if (!configs || typeof configs !== 'object') {
|
||||||
const { ValidationError } = require('../errors');
|
const { ValidationError } = require('../src/utilities/errors');
|
||||||
throw new ValidationError('configs object required');
|
throw new ValidationError('configs object required');
|
||||||
}
|
}
|
||||||
for (const [containerId, config] of Object.entries(configs)) {
|
for (const [containerId, config] of Object.entries(configs)) {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { validateURL, validateToken } = require('../input-validator');
|
const { validateURL, validateToken } = require('../src/security/input-validator');
|
||||||
const validatorLib = require('validator');
|
const validatorLib = require('validator');
|
||||||
const { paginate, parsePaginationParams } = require('../pagination');
|
const { paginate, parsePaginationParams } = require('../src/utilities/pagination');
|
||||||
const { ValidationError } = require('../errors');
|
const { ValidationError } = require('../src/utilities/errors');
|
||||||
const { ok, successMessage } = require('../src/utils/responses');
|
const { ok, successMessage } = require('../src/utils/responses');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { ValidationError } = require('../../errors');
|
const { ValidationError } = require('../../../src/utilities/errors');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const { DOCKER } = require('../../constants');
|
const { DOCKER } = require('../../../src/utilities/constants');
|
||||||
const { ok } = require('../../src/utils/responses');
|
const { ok } = require('../src/utils/responses');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recipes deployment routes factory
|
* Recipes deployment routes factory
|
||||||
@@ -28,7 +28,7 @@ module.exports = function({ docker, credentialManager: _credentialManager, servi
|
|||||||
// eslint-disable-next-line complexity
|
// eslint-disable-next-line complexity
|
||||||
router.post('/deploy', asyncHandler(async (req, res) => {
|
router.post('/deploy', asyncHandler(async (req, res) => {
|
||||||
const { recipeId, config } = req.body;
|
const { recipeId, config } = req.body;
|
||||||
const { RECIPE_TEMPLATES } = require('../../recipe-templates');
|
const { RECIPE_TEMPLATES } = require('../../../src/recipes/recipe-templates');
|
||||||
|
|
||||||
const recipe = RECIPE_TEMPLATES[recipeId];
|
const recipe = RECIPE_TEMPLATES[recipeId];
|
||||||
if (!recipe) throw new ValidationError('Invalid recipe template', 'recipeId');
|
if (!recipe) throw new ValidationError('Invalid recipe template', 'recipeId');
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const deployRoutes = require('./deploy');
|
const deployRoutes = require('./deploy');
|
||||||
const manageRoutes = require('./manage');
|
const manageRoutes = require('./manage');
|
||||||
const { NotFoundError } = require('../../errors');
|
const { NotFoundError } = require('../../../src/utilities/errors');
|
||||||
const { ok } = require('../../src/utils/responses');
|
const { ok } = require('../src/utils/responses');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recipes routes aggregator
|
* Recipes routes aggregator
|
||||||
@@ -32,7 +32,7 @@ module.exports = function(ctx) {
|
|||||||
|
|
||||||
// GET /api/recipes/templates — list all recipe templates
|
// GET /api/recipes/templates — list all recipe templates
|
||||||
router.get('/templates', deps.asyncHandler(async (req, res) => {
|
router.get('/templates', deps.asyncHandler(async (req, res) => {
|
||||||
const { RECIPE_TEMPLATES, RECIPE_CATEGORIES } = require('../../recipe-templates');
|
const { RECIPE_TEMPLATES, RECIPE_CATEGORIES } = require('../../../src/recipes/recipe-templates');
|
||||||
const templates = Object.entries(RECIPE_TEMPLATES).map(([id, recipe]) => ({
|
const templates = Object.entries(RECIPE_TEMPLATES).map(([id, recipe]) => ({
|
||||||
id,
|
id,
|
||||||
name: recipe.name,
|
name: recipe.name,
|
||||||
@@ -61,7 +61,7 @@ module.exports = function(ctx) {
|
|||||||
|
|
||||||
// GET /api/recipes/templates/:recipeId — get single recipe template detail
|
// GET /api/recipes/templates/:recipeId — get single recipe template detail
|
||||||
router.get('/templates/:recipeId', deps.asyncHandler(async (req, res) => {
|
router.get('/templates/:recipeId', deps.asyncHandler(async (req, res) => {
|
||||||
const { RECIPE_TEMPLATES } = require('../../recipe-templates');
|
const { RECIPE_TEMPLATES } = require('../../../src/recipes/recipe-templates');
|
||||||
const recipe = RECIPE_TEMPLATES[req.params.recipeId];
|
const recipe = RECIPE_TEMPLATES[req.params.recipeId];
|
||||||
if (!recipe) throw new NotFoundError(`Recipe template ${req.params.recipeId}`);
|
if (!recipe) throw new NotFoundError(`Recipe template ${req.params.recipeId}`);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { DOCKER } = require('../../constants');
|
const { DOCKER } = require('../../../src/utilities/constants');
|
||||||
const { NotFoundError } = require('../../errors');
|
const { NotFoundError } = require('../../../src/utilities/errors');
|
||||||
const { ok } = require('../../src/utils/responses');
|
const { ok } = require('../src/utils/responses');
|
||||||
|
|
||||||
module.exports = function({ servicesStateManager, asyncHandler, log, docker, notification, buildDomain, caddy }) {
|
module.exports = function({ servicesStateManager, asyncHandler, log, docker, notification, buildDomain, caddy }) {
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
@@ -269,7 +269,7 @@ module.exports = function({ servicesStateManager, asyncHandler, log, docker, not
|
|||||||
* Find all Docker containers belonging to a recipe by label
|
* Find all Docker containers belonging to a recipe by label
|
||||||
*/
|
*/
|
||||||
async function findRecipeContainers(recipeId) {
|
async function findRecipeContainers(recipeId) {
|
||||||
const { RECIPE_TEMPLATES } = require('../../recipe-templates');
|
const { RECIPE_TEMPLATES } = require('../../../src/recipes/recipe-templates');
|
||||||
const recipe = RECIPE_TEMPLATES[recipeId];
|
const recipe = RECIPE_TEMPLATES[recipeId];
|
||||||
const recipeLabel = recipe
|
const recipeLabel = recipe
|
||||||
? recipe.name.toLowerCase().replace(/\s+/g, '-')
|
? recipe.name.toLowerCase().replace(/\s+/g, '-')
|
||||||
@@ -293,7 +293,7 @@ module.exports = function({ servicesStateManager, asyncHandler, log, docker, not
|
|||||||
* Find recipe ID by its label (name slug)
|
* Find recipe ID by its label (name slug)
|
||||||
*/
|
*/
|
||||||
function findRecipeIdByLabel(label) {
|
function findRecipeIdByLabel(label) {
|
||||||
const { RECIPE_TEMPLATES } = require('../../recipe-templates');
|
const { RECIPE_TEMPLATES } = require('../../../src/recipes/recipe-templates');
|
||||||
for (const [id, recipe] of Object.entries(RECIPE_TEMPLATES)) {
|
for (const [id, recipe] of Object.entries(RECIPE_TEMPLATES)) {
|
||||||
if (recipe.name.toLowerCase().replace(/\s+/g, '-') === label) {
|
if (recipe.name.toLowerCase().replace(/\s+/g, '-') === label) {
|
||||||
return id;
|
return id;
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ const http = require('http');
|
|||||||
const https = require('https');
|
const https = require('https');
|
||||||
const tls = require('tls');
|
const tls = require('tls');
|
||||||
const validatorLib = require('validator');
|
const validatorLib = require('validator');
|
||||||
const { APP, REGEX, TIMEOUTS } = require('../constants');
|
const { APP, REGEX, TIMEOUTS } = require('../src/utilities/constants');
|
||||||
const { validateServiceConfig, isValidPort } = require('../input-validator');
|
const { validateServiceConfig, isValidPort } = require('../src/security/input-validator');
|
||||||
const { exists } = require('../fs-helpers');
|
const { exists } = require('../src/utilities/fs-helpers');
|
||||||
const { paginate, parsePaginationParams } = require('../pagination');
|
const { paginate, parsePaginationParams } = require('../src/utilities/pagination');
|
||||||
const { ValidationError, NotFoundError, ConflictError } = require('../errors');
|
const { ValidationError, NotFoundError, ConflictError } = require('../src/utilities/errors');
|
||||||
const { resolveServiceUrl } = require('../url-resolver');
|
const { resolveServiceUrl } = require('../src/utilities/url-resolver');
|
||||||
const { success, error: errorResponse } = require('../src/utils/responses');
|
const { success, error: errorResponse } = require('../src/utils/responses');
|
||||||
const platformPaths = require('../platform-paths');
|
const platformPaths = require('../platform-paths');
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const { CADDY, REGEX, LIMITS } = require('../constants');
|
const { CADDY, REGEX, LIMITS } = require('../src/utilities/constants');
|
||||||
const { ValidationError, ConflictError, NotFoundError } = require('../errors');
|
const { ValidationError, ConflictError, NotFoundError } = require('../src/utilities/errors');
|
||||||
const { validateURL } = require('../input-validator');
|
const { validateURL } = require('../src/security/input-validator');
|
||||||
const { ok, successMessage } = require('../src/utils/responses');
|
const { ok, successMessage } = require('../src/utils/responses');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const { TAILSCALE } = require('../constants');
|
const { TAILSCALE } = require('../src/utilities/constants');
|
||||||
const { exists } = require('../fs-helpers');
|
const { exists } = require('../src/utilities/fs-helpers');
|
||||||
const { ValidationError, NotFoundError } = require('../errors');
|
const { ValidationError, NotFoundError } = require('../src/utilities/errors');
|
||||||
const { ok, successMessage, unauthorized } = require('../src/utils/responses');
|
const { ok, successMessage, unauthorized } = require('../src/utils/responses');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -156,7 +156,7 @@ module.exports = function({
|
|||||||
const match = content.match(blockRegex);
|
const match = content.match(blockRegex);
|
||||||
|
|
||||||
if (!match) {
|
if (!match) {
|
||||||
const { NotFoundError } = require('../errors');
|
const { NotFoundError } = require('../src/utilities/errors');
|
||||||
throw new NotFoundError(`Service ${domain} in Caddyfile`);
|
throw new NotFoundError(`Service ${domain} in Caddyfile`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ const express = require('express');
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { success } = require('../src/utils/responses');
|
const { success } = require('../src/utils/responses');
|
||||||
const { ValidationError, NotFoundError } = require('../errors');
|
const { ValidationError, NotFoundError } = require('../src/utilities/errors');
|
||||||
const platformPaths = require('../platform-paths');
|
const platformPaths = require('../platform-paths');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { paginate, parsePaginationParams } = require('../pagination');
|
const { paginate, parsePaginationParams } = require('../src/utilities/pagination');
|
||||||
const { ValidationError } = require('../errors');
|
const { ValidationError } = require('../src/utilities/errors');
|
||||||
const { ok, successMessage } = require('../src/utils/responses');
|
const { ok, successMessage } = require('../src/utils/responses');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Fix the remaining broken require paths after DC-005 refactor.
|
||||||
|
|
||||||
|
Two patterns to fix:
|
||||||
|
1. `require('./src/...')` and `require('../../src/...')` and `require('../../../src/...')`
|
||||||
|
in files inside `src/` directories → should be `require('../...')` (relative to src/)
|
||||||
|
2. `require('../../../src/...')` in test files in `__tests__/` → should be `require('../src/...')`
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
DASHCADDY_API = Path('/root/dashcaddy-krystie/dashcaddy-api')
|
||||||
|
|
||||||
|
# Pattern to match require('../../../src/X/Y') and capture
|
||||||
|
# We need to detect the file's location and rewrite based on that
|
||||||
|
# A simple approach: find any require that contains 'src/' in the path,
|
||||||
|
# and rewrite it to be relative to the file's location.
|
||||||
|
|
||||||
|
def fix_file(filepath: Path) -> bool:
|
||||||
|
"""Returns True if file was changed."""
|
||||||
|
content = filepath.read_text()
|
||||||
|
original = content
|
||||||
|
|
||||||
|
# Find the file's directory relative to dashcaddy-api root
|
||||||
|
rel_dir = filepath.parent.relative_to(DASHCADDY_API)
|
||||||
|
depth = len(rel_dir.parts)
|
||||||
|
|
||||||
|
# If file is in src/X/Y/file.js, depth is 3 (src, X, Y)
|
||||||
|
# If file is in __tests__/file.js, depth is 1
|
||||||
|
# If file is in __tests__/routes/file.js, depth is 2
|
||||||
|
|
||||||
|
# Find all require() calls that contain 'src/'
|
||||||
|
# Pattern: require('(.....)*src/path')
|
||||||
|
def replacer(match):
|
||||||
|
quote = match.group(1) # the quote char
|
||||||
|
path = match.group(2) # the path inside quotes
|
||||||
|
# Calculate what the path SHOULD be
|
||||||
|
if 'src/' not in path:
|
||||||
|
return match.group(0)
|
||||||
|
|
||||||
|
# Extract the part after 'src/'
|
||||||
|
idx = path.find('src/')
|
||||||
|
after_src = path[idx + 4:] # everything after 'src/'
|
||||||
|
|
||||||
|
if filepath.parts[-3] == 'src':
|
||||||
|
# File is in src/X/file.js - depth 3
|
||||||
|
# Should be '../<after_src>'
|
||||||
|
new_path = '../' + after_src
|
||||||
|
elif filepath.parts[-4] == 'src':
|
||||||
|
# File is in src/X/Y/file.js - depth 4
|
||||||
|
# Should be '../../<after_src>'
|
||||||
|
new_path = '../../' + after_src
|
||||||
|
elif filepath.parts[-2] == '__tests__' or filepath.parent.name == '__tests__':
|
||||||
|
# File is in __tests__/file.js - depth 1 (relative to api root)
|
||||||
|
# Should be '../src/<after_src>'
|
||||||
|
new_path = '../src/' + after_src
|
||||||
|
elif filepath.parts[-2] == 'routes' and filepath.parts[-3] == '__tests__':
|
||||||
|
# File is in __tests__/routes/file.js - depth 2
|
||||||
|
# Should be '../../src/<after_src>'
|
||||||
|
new_path = '../../src/' + after_src
|
||||||
|
elif 'src' in rel_dir.parts:
|
||||||
|
# Other src nested location
|
||||||
|
# Count how many .. we need
|
||||||
|
src_depth = len(rel_dir.parts) - list(rel_dir.parts).index('src') - 1
|
||||||
|
new_path = '../' * src_depth + after_src
|
||||||
|
else:
|
||||||
|
# Other location, leave it
|
||||||
|
return match.group(0)
|
||||||
|
|
||||||
|
return f"require({quote}{new_path}{quote})"
|
||||||
|
|
||||||
|
new_content = re.sub(
|
||||||
|
r"require\((['\"])([^'\"]*src/[^'\"]*)\1\)",
|
||||||
|
replacer,
|
||||||
|
content
|
||||||
|
)
|
||||||
|
|
||||||
|
if new_content != original:
|
||||||
|
filepath.write_text(new_content)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
changed = []
|
||||||
|
for js_file in DASHCADDY_API.rglob('*.js'):
|
||||||
|
# Skip node_modules
|
||||||
|
if 'node_modules' in js_file.parts:
|
||||||
|
continue
|
||||||
|
if fix_file(js_file):
|
||||||
|
changed.append(str(js_file.relative_to(DASHCADDY_API)))
|
||||||
|
|
||||||
|
print(f"Changed {len(changed)} files:")
|
||||||
|
for f in changed:
|
||||||
|
print(f" {f}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
/**
|
||||||
|
* Refactor helper: rewrites require('./xxx') / require('../xxx') paths in
|
||||||
|
* dashcaddy-api to point to the new src/<subdir>/xxx.js locations.
|
||||||
|
*
|
||||||
|
* Algorithm:
|
||||||
|
* 1. For each require() call with a relative spec:
|
||||||
|
* 2. If the resolved file exists, leave it alone.
|
||||||
|
* 3. If the resolved file does NOT exist, the bare name of the spec
|
||||||
|
* (or the directory name 'dns-providers') might be one of the
|
||||||
|
* modules that was moved out of the repo root. In that case, rewrite
|
||||||
|
* the spec to the correct relative path to the new location.
|
||||||
|
* 4. Otherwise leave alone.
|
||||||
|
*/
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const REPO = process.cwd();
|
||||||
|
|
||||||
|
// Map: bare module name (no extension) -> new repo-relative path (no extension)
|
||||||
|
const NEW_LOCATIONS = {
|
||||||
|
'auth-manager': 'src/managers/auth-manager',
|
||||||
|
'credential-manager': 'src/managers/credential-manager',
|
||||||
|
'license-manager': 'src/managers/license-manager',
|
||||||
|
'port-lock-manager': 'src/managers/port-lock-manager',
|
||||||
|
'state-manager': 'src/managers/state-manager',
|
||||||
|
'notification-manager': 'src/managers/notification-manager',
|
||||||
|
'resource-monitor': 'src/managers/resource-monitor',
|
||||||
|
'config-drift-detector': 'src/managers/config-drift-detector',
|
||||||
|
'auto-restart-manager': 'src/managers/auto-restart-manager',
|
||||||
|
'update-manager': 'src/managers/update-manager',
|
||||||
|
'dependency-manager': 'src/managers/dependency-manager',
|
||||||
|
'csrf-protection': 'src/security/csrf-protection',
|
||||||
|
'crypto-utils': 'src/security/crypto-utils',
|
||||||
|
'docker-security': 'src/security/docker-security',
|
||||||
|
'input-validator': 'src/security/input-validator',
|
||||||
|
'keychain-manager': 'src/security/keychain-manager',
|
||||||
|
'log-digest': 'src/security/log-digest',
|
||||||
|
'audit-logger': 'src/security/audit-logger',
|
||||||
|
'docker-maintenance': 'src/docker/docker-maintenance',
|
||||||
|
'app-templates': 'src/docker/app-templates',
|
||||||
|
'self-updater': 'src/docker/self-updater',
|
||||||
|
'dns-propagation': 'src/dns/dns-propagation',
|
||||||
|
'recipe-templates': 'src/recipes/recipe-templates',
|
||||||
|
'bundled-workflows': 'src/recipes/bundled-workflows',
|
||||||
|
'health-checker': 'src/monitoring/health-checker',
|
||||||
|
'metrics': 'src/monitoring/metrics',
|
||||||
|
'ssl-monitor': 'src/monitoring/ssl-monitor',
|
||||||
|
'backup-manager': 'src/utilities/backup-manager',
|
||||||
|
'error-handler': 'src/utilities/error-handler',
|
||||||
|
'errors': 'src/utilities/errors',
|
||||||
|
'fs-helpers': 'src/utilities/fs-helpers',
|
||||||
|
'pagination': 'src/utilities/pagination',
|
||||||
|
'url-resolver': 'src/utilities/url-resolver',
|
||||||
|
'config-schema': 'src/utilities/config-schema',
|
||||||
|
'constants': 'src/utilities/constants',
|
||||||
|
'middleware': 'src/utilities/middleware',
|
||||||
|
'startup-validator': 'src/utilities/startup-validator',
|
||||||
|
'cache-config': 'src/utilities/cache-config',
|
||||||
|
};
|
||||||
|
|
||||||
|
const SKIP_DIRS = new Set(['node_modules', '.git']);
|
||||||
|
const SKIP_FILE_PATTERNS = [/\/scripts\/refactor-requires\.js$/];
|
||||||
|
|
||||||
|
function* walk(dir) {
|
||||||
|
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||||
|
if (SKIP_DIRS.has(entry.name)) continue;
|
||||||
|
const full = path.join(dir, entry.name);
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
yield* walk(full);
|
||||||
|
} else if (entry.name.endsWith('.js')) {
|
||||||
|
yield full;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toRelativeFromFile(filePath, targetRel) {
|
||||||
|
const fromDir = path.dirname(filePath);
|
||||||
|
const targetAbs = path.resolve(REPO, targetRel);
|
||||||
|
let rel = path.relative(fromDir, targetAbs);
|
||||||
|
if (!rel.startsWith('.')) rel = './' + rel;
|
||||||
|
return rel.split(path.sep).join('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
function fileExistsWithJsOrIndex(p) {
|
||||||
|
// exists if p is a file, or p is a dir with index.js
|
||||||
|
try {
|
||||||
|
if (fs.existsSync(p) && fs.statSync(p).isFile()) return true;
|
||||||
|
} catch (_) {}
|
||||||
|
try {
|
||||||
|
if (fs.existsSync(p + '.js') && fs.statSync(p + '.js').isFile()) return true;
|
||||||
|
} catch (_) {}
|
||||||
|
try {
|
||||||
|
if (
|
||||||
|
fs.existsSync(p) &&
|
||||||
|
fs.statSync(p).isDirectory() &&
|
||||||
|
fs.existsSync(path.join(p, 'index.js'))
|
||||||
|
)
|
||||||
|
return true;
|
||||||
|
} catch (_) {}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function refactor(filePath) {
|
||||||
|
const relFile = path.relative(REPO, filePath);
|
||||||
|
if (SKIP_FILE_PATTERNS.some((re) => re.test(relFile))) return false;
|
||||||
|
|
||||||
|
const content = fs.readFileSync(filePath, 'utf8');
|
||||||
|
let changed = false;
|
||||||
|
|
||||||
|
const requireRe = /require\(\s*(['"])([^'"]+)\1\s*\)/g;
|
||||||
|
const newContent = content.replace(requireRe, (full, quote, spec) => {
|
||||||
|
if (!spec.startsWith('.')) return full; // package require, leave alone
|
||||||
|
const fromDir = path.dirname(filePath);
|
||||||
|
const resolvedBase = path.resolve(fromDir, spec);
|
||||||
|
// If the resolved file exists, the require is correct as-is.
|
||||||
|
if (fileExistsWithJsOrIndex(resolvedBase)) {
|
||||||
|
// But — check for the special case: require to <REPO>/dns-providers/x
|
||||||
|
// which after move becomes <REPO>/src/dns/dns-providers/x — wait,
|
||||||
|
// that doesn't exist anymore. The dir was moved.
|
||||||
|
const dnsProvidersOld = path.resolve(REPO, 'dns-providers');
|
||||||
|
if (
|
||||||
|
resolvedBase === dnsProvidersOld ||
|
||||||
|
resolvedBase.startsWith(dnsProvidersOld + path.sep)
|
||||||
|
) {
|
||||||
|
const subPath = resolvedBase === dnsProvidersOld ? '' : resolvedBase.slice(dnsProvidersOld.length + 1);
|
||||||
|
const newResolved = path.resolve(REPO, 'src/dns/dns-providers', subPath);
|
||||||
|
let rel = path.relative(fromDir, newResolved);
|
||||||
|
if (!rel.startsWith('.')) rel = './' + rel;
|
||||||
|
const newSpec = rel.split(path.sep).join('/');
|
||||||
|
changed = true;
|
||||||
|
return `require(${quote}${newSpec}${quote})`;
|
||||||
|
}
|
||||||
|
return full;
|
||||||
|
}
|
||||||
|
// The file does not exist. Check if the bare name is a moved module.
|
||||||
|
const bare = path.basename(resolvedBase);
|
||||||
|
if (bare in NEW_LOCATIONS) {
|
||||||
|
const target = NEW_LOCATIONS[bare];
|
||||||
|
const newSpec = toRelativeFromFile(filePath, target);
|
||||||
|
changed = true;
|
||||||
|
return `require(${quote}${newSpec}${quote})`;
|
||||||
|
}
|
||||||
|
// Bare not in map. Check for the special case: the spec points into
|
||||||
|
// the OLD dns-providers dir (now src/dns/dns-providers). E.g. spec
|
||||||
|
// could be '../dns-providers/registry' or './dns-providers/registry'
|
||||||
|
// from somewhere else.
|
||||||
|
if (spec.includes('dns-providers')) {
|
||||||
|
const dnsProvidersOld = path.resolve(REPO, 'dns-providers');
|
||||||
|
if (
|
||||||
|
resolvedBase === dnsProvidersOld ||
|
||||||
|
resolvedBase.startsWith(dnsProvidersOld + path.sep)
|
||||||
|
) {
|
||||||
|
const subPath =
|
||||||
|
resolvedBase === dnsProvidersOld ? '' : resolvedBase.slice(dnsProvidersOld.length + 1);
|
||||||
|
const newResolved = path.resolve(REPO, 'src/dns/dns-providers', subPath);
|
||||||
|
let rel = path.relative(fromDir, newResolved);
|
||||||
|
if (!rel.startsWith('.')) rel = './' + rel;
|
||||||
|
const newSpec = rel.split(path.sep).join('/');
|
||||||
|
changed = true;
|
||||||
|
return `require(${quote}${newSpec}${quote})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return full;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
fs.writeFileSync(filePath, newContent);
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
let count = 0;
|
||||||
|
for (const file of walk(REPO)) {
|
||||||
|
if (refactor(file)) {
|
||||||
|
count += 1;
|
||||||
|
console.log('rewrote', path.relative(REPO, file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(`\nDone: rewrote ${count} file(s).`);
|
||||||
+22
-22
@@ -33,7 +33,7 @@ process.on('uncaughtException', (error) => {
|
|||||||
const CONFIG_FILE = process.env.CONFIG_FILE || platformPaths.servicesFile.replace('services.json', 'config.json');
|
const CONFIG_FILE = process.env.CONFIG_FILE || platformPaths.servicesFile.replace('services.json', 'config.json');
|
||||||
|
|
||||||
// Validate startup configuration
|
// Validate startup configuration
|
||||||
const { validateStartupConfig } = require('./startup-validator');
|
const { validateStartupConfig } = require('../src/utilities/startup-validator');
|
||||||
await validateStartupConfig({
|
await validateStartupConfig({
|
||||||
log,
|
log,
|
||||||
CADDYFILE_PATH,
|
CADDYFILE_PATH,
|
||||||
@@ -56,23 +56,23 @@ process.on('uncaughtException', (error) => {
|
|||||||
|
|
||||||
// Attach WebSocket exec handler (with auth)
|
// Attach WebSocket exec handler (with auth)
|
||||||
const attachExecWS = require('./routes/exec');
|
const attachExecWS = require('./routes/exec');
|
||||||
const authManager = require('./auth-manager');
|
const authManager = require('../src/managers/auth-manager');
|
||||||
attachExecWS(server, log, authManager);
|
attachExecWS(server, log, authManager);
|
||||||
log.info('server', 'WebSocket exec handler attached (auth enforced)');
|
log.info('server', 'WebSocket exec handler attached (auth enforced)');
|
||||||
|
|
||||||
// Start feature modules
|
// Start feature modules
|
||||||
const resourceMonitor = require('./resource-monitor');
|
const resourceMonitor = require('../src/managers/resource-monitor');
|
||||||
const backupManager = require('./backup-manager');
|
const backupManager = require('../src/utilities/backup-manager');
|
||||||
const healthChecker = require('./health-checker');
|
const healthChecker = require('../src/monitoring/health-checker');
|
||||||
const updateManager = require('./update-manager');
|
const updateManager = require('../src/managers/update-manager');
|
||||||
const selfUpdater = require('./self-updater');
|
const selfUpdater = require('../src/docker/self-updater');
|
||||||
const portLockManager = require('./port-lock-manager');
|
const portLockManager = require('../src/managers/port-lock-manager');
|
||||||
|
|
||||||
// Optional modules
|
// Optional modules
|
||||||
let dockerMaintenance, logDigest, bundledWorkflows;
|
let dockerMaintenance, logDigest, bundledWorkflows;
|
||||||
try { dockerMaintenance = require('./docker-maintenance'); } catch { /* optional */ }
|
try { dockerMaintenance = require('../src/docker/docker-maintenance'); } catch { /* optional */ }
|
||||||
try { logDigest = require('./log-digest'); } catch { /* optional */ }
|
try { logDigest = require('../src/security/log-digest'); } catch { /* optional */ }
|
||||||
try { bundledWorkflows = require('./bundled-workflows'); } catch { /* optional */ }
|
try { bundledWorkflows = require('../src/recipes/bundled-workflows'); } catch { /* optional */ }
|
||||||
|
|
||||||
// Initialize workflow engine if bundled-workflows is available
|
// Initialize workflow engine if bundled-workflows is available
|
||||||
// NOTE: createApp() already initializes the workflow engine in src/app.js
|
// NOTE: createApp() already initializes the workflow engine in src/app.js
|
||||||
@@ -85,7 +85,7 @@ process.on('uncaughtException', (error) => {
|
|||||||
// Create a context with needed services
|
// Create a context with needed services
|
||||||
const workflowCtx = {
|
const workflowCtx = {
|
||||||
docker: { client: require('dockerode')() },
|
docker: { client: require('dockerode')() },
|
||||||
notification: require('./notification-manager')({
|
notification: require('../src/managers/notification-manager')({
|
||||||
NOTIFICATIONS_FILE: process.env.NOTIFICATIONS_FILE || require('./platform-paths').notificationsFile,
|
NOTIFICATIONS_FILE: process.env.NOTIFICATIONS_FILE || require('./platform-paths').notificationsFile,
|
||||||
fetchT,
|
fetchT,
|
||||||
log,
|
log,
|
||||||
@@ -137,8 +137,8 @@ process.on('uncaughtException', (error) => {
|
|||||||
// Health checker (with service sync)
|
// Health checker (with service sync)
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const { syncHealthCheckerServices } = require('./startup-validator');
|
const { syncHealthCheckerServices } = require('../src/utilities/startup-validator');
|
||||||
const StateManager = require('./state-manager');
|
const StateManager = require('../src/managers/state-manager');
|
||||||
const servicesStateManager = new StateManager(SERVICES_FILE);
|
const servicesStateManager = new StateManager(SERVICES_FILE);
|
||||||
|
|
||||||
await syncHealthCheckerServices({
|
await syncHealthCheckerServices({
|
||||||
@@ -150,7 +150,7 @@ process.on('uncaughtException', (error) => {
|
|||||||
? `https://${config.domain}/${subdomain}`
|
? `https://${config.domain}/${subdomain}`
|
||||||
: `https://${subdomain}${config.tld}`,
|
: `https://${subdomain}${config.tld}`,
|
||||||
siteConfig: config,
|
siteConfig: config,
|
||||||
APP: require('./constants').APP
|
APP: require('../src/utilities/constants').APP
|
||||||
});
|
});
|
||||||
|
|
||||||
healthChecker.start();
|
healthChecker.start();
|
||||||
@@ -232,11 +232,11 @@ process.on('uncaughtException', (error) => {
|
|||||||
const shutdown = (signal) => {
|
const shutdown = (signal) => {
|
||||||
log.info('shutdown', `${signal} received, draining connections...`);
|
log.info('shutdown', `${signal} received, draining connections...`);
|
||||||
|
|
||||||
const resourceMonitor = require('./resource-monitor');
|
const resourceMonitor = require('../src/managers/resource-monitor');
|
||||||
const backupManager = require('./backup-manager');
|
const backupManager = require('../src/utilities/backup-manager');
|
||||||
const healthChecker = require('./health-checker');
|
const healthChecker = require('../src/monitoring/health-checker');
|
||||||
const updateManager = require('./update-manager');
|
const updateManager = require('../src/managers/update-manager');
|
||||||
const selfUpdater = require('./self-updater');
|
const selfUpdater = require('../src/docker/self-updater');
|
||||||
|
|
||||||
resourceMonitor.stop();
|
resourceMonitor.stop();
|
||||||
backupManager.stop();
|
backupManager.stop();
|
||||||
@@ -245,12 +245,12 @@ process.on('uncaughtException', (error) => {
|
|||||||
selfUpdater.stop();
|
selfUpdater.stop();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const dockerMaintenance = require('./docker-maintenance');
|
const dockerMaintenance = require('../src/docker/docker-maintenance');
|
||||||
dockerMaintenance.stop();
|
dockerMaintenance.stop();
|
||||||
} catch { /* optional */ }
|
} catch { /* optional */ }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const logDigest = require('./log-digest');
|
const logDigest = require('../src/security/log-digest');
|
||||||
logDigest.stop();
|
logDigest.stop();
|
||||||
} catch { /* optional */ }
|
} catch { /* optional */ }
|
||||||
|
|
||||||
|
|||||||
+40
-40
@@ -15,41 +15,41 @@ const { errorResponse, ok } = require('./utils/responses');
|
|||||||
const { asyncHandler } = require('./utils/async-handler');
|
const { asyncHandler } = require('./utils/async-handler');
|
||||||
|
|
||||||
// Managers and utilities
|
// Managers and utilities
|
||||||
const StateManager = require('../state-manager');
|
const StateManager = require('managers/state-manager');
|
||||||
const platformPaths = require('../platform-paths');
|
const platformPaths = require('../platform-paths');
|
||||||
const { LicenseManager } = require('../license-manager');
|
const { LicenseManager } = require('managers/license-manager');
|
||||||
const credentialManager = require('../credential-manager');
|
const credentialManager = require('managers/credential-manager');
|
||||||
const authManager = require('../auth-manager');
|
const authManager = require('managers/auth-manager');
|
||||||
const dockerSecurity = require('../docker-security');
|
const dockerSecurity = require('security/docker-security');
|
||||||
const auditLogger = require('../audit-logger');
|
const auditLogger = require('security/audit-logger');
|
||||||
const portLockManager = require('../port-lock-manager');
|
const portLockManager = require('managers/port-lock-manager');
|
||||||
const resourceMonitor = require('../resource-monitor');
|
const resourceMonitor = require('managers/resource-monitor');
|
||||||
const backupManager = require('../backup-manager');
|
const backupManager = require('utilities/backup-manager');
|
||||||
const healthChecker = require('../health-checker');
|
const healthChecker = require('monitoring/health-checker');
|
||||||
const updateManager = require('../update-manager');
|
const updateManager = require('managers/update-manager');
|
||||||
const selfUpdater = require('../self-updater');
|
const selfUpdater = require('docker/self-updater');
|
||||||
const configureMiddleware = require('../middleware');
|
const configureMiddleware = require('utilities/middleware');
|
||||||
const { validateStartupConfig: _validateStartupConfig, syncHealthCheckerServices } = require('../startup-validator');
|
const { validateStartupConfig: _validateStartupConfig, syncHealthCheckerServices } = require('utilities/startup-validator');
|
||||||
const { CSRF_HEADER_NAME } = require('../csrf-protection');
|
const { CSRF_HEADER_NAME } = require('security/csrf-protection');
|
||||||
const { resolveServiceUrl } = require('../url-resolver');
|
const { resolveServiceUrl } = require('utilities/url-resolver');
|
||||||
const metrics = require('../metrics');
|
const metrics = require('monitoring/metrics');
|
||||||
const { validateURL } = require('../input-validator');
|
const { validateURL } = require('security/input-validator');
|
||||||
|
|
||||||
// Optional modules
|
// Optional modules
|
||||||
let dockerMaintenance, logDigest;
|
let dockerMaintenance, logDigest;
|
||||||
try { dockerMaintenance = require('../docker-maintenance'); } catch (_) { /* optional module */ }
|
try { dockerMaintenance = require('docker/docker-maintenance'); } catch (_) { /* optional module */ }
|
||||||
try { logDigest = require('../log-digest'); } catch (_) { /* optional module */ }
|
try { logDigest = require('security/log-digest'); } catch (_) { /* optional module */ }
|
||||||
|
|
||||||
// Workflow engine (bundled workflows)
|
// Workflow engine (bundled workflows)
|
||||||
let bundledWorkflowsModule;
|
let bundledWorkflowsModule;
|
||||||
let workflowEngine = null;
|
let workflowEngine = null;
|
||||||
try {
|
try {
|
||||||
bundledWorkflowsModule = require('../bundled-workflows');
|
bundledWorkflowsModule = require('recipes/bundled-workflows');
|
||||||
} catch (_) { /* optional module */ }
|
} catch (_) { /* optional module */ }
|
||||||
|
|
||||||
// Templates
|
// Templates
|
||||||
const { APP_TEMPLATES, TEMPLATE_CATEGORIES, DIFFICULTY_LEVELS } = require('../app-templates');
|
const { APP_TEMPLATES, TEMPLATE_CATEGORIES, DIFFICULTY_LEVELS } = require('docker/app-templates');
|
||||||
const { RECIPE_TEMPLATES, RECIPE_CATEGORIES } = require('../recipe-templates');
|
const { RECIPE_TEMPLATES, RECIPE_CATEGORIES } = require('recipes/recipe-templates');
|
||||||
|
|
||||||
// Route modules
|
// Route modules
|
||||||
const healthRoutes = require('../routes/health');
|
const healthRoutes = require('../routes/health');
|
||||||
@@ -79,17 +79,17 @@ const dockerResourcesRoutes = require('../routes/docker-resources');
|
|||||||
const eventsRoutes = require('../routes/events');
|
const eventsRoutes = require('../routes/events');
|
||||||
const workflowsRoutes = require('../routes/workflows');
|
const workflowsRoutes = require('../routes/workflows');
|
||||||
const dependenciesRoutes = require('../routes/dependencies');
|
const dependenciesRoutes = require('../routes/dependencies');
|
||||||
const DependencyManager = require('../dependency-manager');
|
const DependencyManager = require('managers/dependency-manager');
|
||||||
const autoRestartRoutes = require('../routes/auto-restart');
|
const autoRestartRoutes = require('../routes/auto-restart');
|
||||||
const configDriftRoutes = require('../routes/config-drift');
|
const configDriftRoutes = require('../routes/config-drift');
|
||||||
const sslMonitorRoutes = require('../routes/ssl-monitor');
|
const sslMonitorRoutes = require('../routes/ssl-monitor');
|
||||||
const { AutoRestartManager } = require('../auto-restart-manager');
|
const { AutoRestartManager } = require('managers/auto-restart-manager');
|
||||||
const { ConfigDriftDetector } = require('../config-drift-detector');
|
const { ConfigDriftDetector } = require('managers/config-drift-detector');
|
||||||
const SSLMonitor = require('../ssl-monitor');
|
const SSLMonitor = require('monitoring/ssl-monitor');
|
||||||
const DNSPropagationChecker = require('../dns-propagation');
|
const DNSPropagationChecker = require('dns/dns-propagation');
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const { APP } = require('../constants');
|
const { APP } = require('utilities/constants');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create and configure the Express application
|
* Create and configure the Express application
|
||||||
@@ -216,15 +216,15 @@ async function createApp() {
|
|||||||
auditLogger,
|
auditLogger,
|
||||||
authManager,
|
authManager,
|
||||||
log,
|
log,
|
||||||
cryptoUtils: require('../crypto-utils'),
|
cryptoUtils: require('security/crypto-utils'),
|
||||||
isValidContainerId,
|
isValidContainerId,
|
||||||
isTailscaleIP,
|
isTailscaleIP,
|
||||||
getTailscaleStatus,
|
getTailscaleStatus,
|
||||||
RATE_LIMITS: require('../constants').RATE_LIMITS,
|
RATE_LIMITS: require('utilities/constants').RATE_LIMITS,
|
||||||
LIMITS: require('../constants').LIMITS,
|
LIMITS: require('utilities/constants').LIMITS,
|
||||||
APP: require('../constants').APP,
|
APP: require('utilities/constants').APP,
|
||||||
CACHE_CONFIGS: require('../cache-config').CACHE_CONFIGS,
|
CACHE_CONFIGS: require('utilities/cache-config').CACHE_CONFIGS,
|
||||||
createCache: require('../cache-config').createCache,
|
createCache: require('utilities/cache-config').createCache,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { strictLimiter } = middlewareResult;
|
const { strictLimiter } = middlewareResult;
|
||||||
@@ -237,7 +237,7 @@ async function createApp() {
|
|||||||
|
|
||||||
// eslint-disable-next-line require-await -- may grow awaits as config loading evolves
|
// eslint-disable-next-line require-await -- may grow awaits as config loading evolves
|
||||||
async function readConfig() {
|
async function readConfig() {
|
||||||
const { readJsonFile } = require('../fs-helpers');
|
const { readJsonFile } = require('utilities/fs-helpers');
|
||||||
return readJsonFile(config.CONFIG_FILE, {});
|
return readJsonFile(config.CONFIG_FILE, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,7 +260,7 @@ async function createApp() {
|
|||||||
|
|
||||||
async function saveTotpConfig() {
|
async function saveTotpConfig() {
|
||||||
try {
|
try {
|
||||||
const { writeJsonFile } = require('../fs-helpers');
|
const { writeJsonFile } = require('utilities/fs-helpers');
|
||||||
await writeJsonFile(config.TOTP_CONFIG_FILE, totpConfig);
|
await writeJsonFile(config.TOTP_CONFIG_FILE, totpConfig);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.error('config', 'Could not save TOTP config', { error: e.message });
|
log.error('config', 'Could not save TOTP config', { error: e.message });
|
||||||
@@ -731,7 +731,7 @@ async function createApp() {
|
|||||||
// Lightweight probe endpoint
|
// Lightweight probe endpoint
|
||||||
app.get('/probe/:id', boundAsyncHandler(async (req, res) => {
|
app.get('/probe/:id', boundAsyncHandler(async (req, res) => {
|
||||||
const id = req.params.id;
|
const id = req.params.id;
|
||||||
const { exists } = require('../fs-helpers');
|
const { exists } = require('utilities/fs-helpers');
|
||||||
|
|
||||||
let service = null;
|
let service = null;
|
||||||
if (id !== 'internet' && await exists(config.SERVICES_FILE)) {
|
if (id !== 'internet' && await exists(config.SERVICES_FILE)) {
|
||||||
@@ -871,7 +871,7 @@ async function createApp() {
|
|||||||
|
|
||||||
app.get('/api/v1/docs/spec', boundAsyncHandler(async (req, res) => {
|
app.get('/api/v1/docs/spec', boundAsyncHandler(async (req, res) => {
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { exists } = require('../fs-helpers');
|
const { exists } = require('utilities/fs-helpers');
|
||||||
const fsp = require('fs').promises;
|
const fsp = require('fs').promises;
|
||||||
|
|
||||||
const specPath = path.join(__dirname, '../openapi.yaml');
|
const specPath = path.join(__dirname, '../openapi.yaml');
|
||||||
@@ -884,7 +884,7 @@ async function createApp() {
|
|||||||
}, 'api-docs-spec'));
|
}, 'api-docs-spec'));
|
||||||
|
|
||||||
// Error handlers (MUST be last)
|
// Error handlers (MUST be last)
|
||||||
const { notFoundHandler, errorMiddleware } = require('../error-handler');
|
const { notFoundHandler, errorMiddleware } = require('utilities/error-handler');
|
||||||
app.use('/api', notFoundHandler);
|
app.use('/api', notFoundHandler);
|
||||||
app.use(errorMiddleware);
|
app.use(errorMiddleware);
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
const paths = require('./paths');
|
const paths = require('./paths');
|
||||||
const site = require('./site');
|
const site = require('./site');
|
||||||
const { APP, LIMITS, TIMEOUTS, RETRIES, CADDY } = require('../../constants');
|
const { APP, LIMITS, TIMEOUTS, RETRIES, CADDY } = require('../utilities/constants');
|
||||||
|
|
||||||
// Load logging level
|
// Load logging level
|
||||||
const LOG_LEVELS = { debug: 0, info: 1, warn: 2, error: 3 };
|
const LOG_LEVELS = { debug: 0, info: 1, warn: 2, error: 3 };
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
* updated config back, and the rest of the app only ever sees the current
|
* updated config back, and the rest of the app only ever sees the current
|
||||||
* schema.
|
* schema.
|
||||||
*/
|
*/
|
||||||
const { validateConfig } = require('../../config-schema');
|
const { validateConfig } = require('../utilities/config-schema');
|
||||||
const { CADDY } = require('../../constants');
|
const { CADDY } = require('../utilities/constants');
|
||||||
const { loadAndMigrate, CURRENT_VERSION } = require('./migrations');
|
const { loadAndMigrate, CURRENT_VERSION } = require('./migrations');
|
||||||
|
|
||||||
const siteConfig = {
|
const siteConfig = {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* Caddy context - Caddyfile manipulation and reload
|
* Caddy context - Caddyfile manipulation and reload
|
||||||
*/
|
*/
|
||||||
const fsp = require('fs').promises;
|
const fsp = require('fs').promises;
|
||||||
const { RETRIES } = require('../../constants');
|
const { RETRIES } = require('../utilities/constants');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomically read-modify-write the Caddyfile and reload Caddy.
|
* Atomically read-modify-write the Caddyfile and reload Caddy.
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
*
|
*
|
||||||
* This module now delegates to the provider system internally.
|
* This module now delegates to the provider system internally.
|
||||||
*/
|
*/
|
||||||
const { TIMEOUTS, SESSION_TTL, CADDY } = require('../../constants');
|
const { TIMEOUTS, SESSION_TTL, CADDY } = require('../utilities/constants');
|
||||||
const { createCache, CACHE_CONFIGS } = require('../../cache-config');
|
const { createCache, CACHE_CONFIGS } = require('../utilities/cache-config');
|
||||||
const { createProviderDnsContext } = require('./provider-dns');
|
const { createProviderDnsContext } = require('./provider-dns');
|
||||||
|
|
||||||
// DNS token management
|
// DNS token management
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* Docker context - Docker client and operations
|
* Docker context - Docker client and operations
|
||||||
*/
|
*/
|
||||||
const Docker = require('dockerode');
|
const Docker = require('dockerode');
|
||||||
const { DOCKER } = require('../../constants');
|
const { DOCKER } = require('../utilities/constants');
|
||||||
|
|
||||||
const docker = new Docker();
|
const docker = new Docker();
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const { createDockerContext } = require('./docker');
|
|||||||
const { createCaddyContext } = require('./caddy');
|
const { createCaddyContext } = require('./caddy');
|
||||||
const { createDnsContext } = require('./dns');
|
const { createDnsContext } = require('./dns');
|
||||||
const { createSessionContext } = require('./session');
|
const { createSessionContext } = require('./session');
|
||||||
const NotificationManager = require('../../notification-manager');
|
const NotificationManager = require('../managers/notification-manager');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assemble the full application context
|
* Assemble the full application context
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
* Falls back to legacy Technitium context for backward compatibility
|
* Falls back to legacy Technitium context for backward compatibility
|
||||||
* when no provider is explicitly configured.
|
* when no provider is explicitly configured.
|
||||||
*/
|
*/
|
||||||
const { createCache, CACHE_CONFIGS } = require('../../cache-config');
|
const { createCache, CACHE_CONFIGS } = require('../utilities/cache-config');
|
||||||
const { TIMEOUTS, SESSION_TTL, CADDY } = require('../../constants');
|
const { TIMEOUTS, SESSION_TTL, CADDY } = require('../utilities/constants');
|
||||||
const registry = require('../../dns-providers/registry');
|
const registry = require('../../dns-providers/registry');
|
||||||
|
|
||||||
// Per-server token cache (legacy Technitium)
|
// Per-server token cache (legacy Technitium)
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
const Docker = require('dockerode');
|
const Docker = require('dockerode');
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const { DOCKER } = require('./constants');
|
const { DOCKER } = require('../utilities/constants');
|
||||||
|
|
||||||
const docker = new Docker();
|
const docker = new Docker();
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const credentialManager = require('./credential-manager');
|
const credentialManager = require('./credential-manager');
|
||||||
const cryptoUtils = require('./crypto-utils');
|
const cryptoUtils = require('../security/crypto-utils');
|
||||||
|
|
||||||
// JWT signing secret - derived from encryption key for consistency
|
// JWT signing secret - derived from encryption key for consistency
|
||||||
const JWT_SECRET = cryptoUtils.loadOrCreateKey();
|
const JWT_SECRET = cryptoUtils.loadOrCreateKey();
|
||||||
+1
-1
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { readJsonFile, writeJsonFile } = require('./fs-helpers');
|
const { readJsonFile, writeJsonFile } = require('../utilities/fs-helpers');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default policy values applied when a new policy is created.
|
* Default policy values applied when a new policy is created.
|
||||||
+2
-2
@@ -4,8 +4,8 @@
|
|||||||
* Uses OS keychain when available, falls back to encrypted file storage
|
* Uses OS keychain when available, falls back to encrypted file storage
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const keychainManager = require('./keychain-manager');
|
const keychainManager = require('../security/keychain-manager');
|
||||||
const cryptoUtils = require('./crypto-utils');
|
const cryptoUtils = require('../security/crypto-utils');
|
||||||
const lockfile = require('proper-lockfile');
|
const lockfile = require('proper-lockfile');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
@@ -15,7 +15,7 @@ const os = require('os');
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { verifyCode, parseCode, VALID_DURATIONS } = require('./license-keygen');
|
const { verifyCode, parseCode, VALID_DURATIONS } = require('./license-keygen');
|
||||||
const { errorResponse } = require('./src/utils/responses');
|
const { errorResponse } = require('../utils/responses');
|
||||||
|
|
||||||
const LICENSE_CRED_KEY = 'license.activation';
|
const LICENSE_CRED_KEY = 'license.activation';
|
||||||
const LICENSE_SERVER_URL = process.env.LICENSE_SERVER_URL || null; // Set when license server exists
|
const LICENSE_SERVER_URL = process.env.LICENSE_SERVER_URL || null; // Set when license server exists
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user