fix(routes): complete post-refactor dependency wiring cleanup
This commit is contained in:
@@ -17,8 +17,7 @@ const platformPaths = require('../../platform-paths');
|
||||
* @param {Object} deps.log - Logger instance
|
||||
* @returns {Object} Helper functions
|
||||
*/
|
||||
module.exports = function(ctx) {
|
||||
const { docker, caddy, credentialManager, servicesStateManager, fetchT, log } = ctx;
|
||||
module.exports = function({ docker, caddy, credentialManager, servicesStateManager, fetchT, log, ctx }) {
|
||||
|
||||
async function checkPortConflicts(ports, excludeContainerName = null) {
|
||||
const conflicts = [];
|
||||
|
||||
@@ -27,17 +27,21 @@ module.exports = function(ctx) {
|
||||
log: ctx.log,
|
||||
// Additional context properties needed by routes
|
||||
APP_TEMPLATES: ctx.APP_TEMPLATES,
|
||||
TEMPLATE_CATEGORIES: ctx.TEMPLATE_CATEGORIES,
|
||||
DIFFICULTY_LEVELS: ctx.DIFFICULTY_LEVELS,
|
||||
siteConfig: ctx.siteConfig,
|
||||
buildDomain: ctx.buildDomain,
|
||||
buildServiceUrl: ctx.buildServiceUrl,
|
||||
addServiceToConfig: ctx.addServiceToConfig,
|
||||
dns: ctx.dns,
|
||||
notification: ctx.notification,
|
||||
safeErrorMessage: ctx.safeErrorMessage
|
||||
safeErrorMessage: ctx.safeErrorMessage,
|
||||
SERVICES_FILE: ctx.SERVICES_FILE,
|
||||
ctx: ctx
|
||||
};
|
||||
|
||||
// Initialize helpers with dependencies
|
||||
const helpers = initHelpers(ctx);
|
||||
// Initialize helpers with dependencies (ctx is the Koa context)
|
||||
const helpers = initHelpers({ ...deps, ctx });
|
||||
|
||||
// Mount sub-routes — pass full ctx so sub-routes can reference ctx.* properties
|
||||
const subCtx = Object.assign({}, ctx, { helpers });
|
||||
|
||||
@@ -1,20 +1,40 @@
|
||||
const express = require('express');
|
||||
const { exists } = require('../../fs-helpers');
|
||||
const { logError } = require('../../src/utils/logging');
|
||||
|
||||
module.exports = function(ctx) {
|
||||
const { docker, caddy, servicesStateManager, asyncHandler, errorResponse, log, helpers } = ctx;
|
||||
module.exports = function({
|
||||
docker, caddy, servicesStateManager, asyncHandler, log, helpers,
|
||||
errorResponse, dns, siteConfig, buildDomain, SERVICES_FILE, safeErrorMessage
|
||||
}) {
|
||||
const router = express.Router();
|
||||
/**
|
||||
* Apps removal routes factory
|
||||
* @param {Object} deps - Explicit dependencies
|
||||
* @param {Object} deps.docker - Docker client wrapper
|
||||
* @param {Object} deps.caddy - Caddy client
|
||||
* @param {Object} deps.servicesStateManager - Services state manager
|
||||
* @param {Function} deps.asyncHandler - Async route handler wrapper
|
||||
* @param {Object} deps.log - Logger instance
|
||||
* @param {Object} deps.helpers - Apps helpers module
|
||||
* @returns {express.Router}
|
||||
*/
|
||||
|
||||
// Ctx shim for backward compatibility with existing route code
|
||||
const ctx = {
|
||||
dns,
|
||||
siteConfig,
|
||||
buildDomain,
|
||||
SERVICES_FILE,
|
||||
safeErrorMessage
|
||||
};
|
||||
|
||||
// Remove deployed app
|
||||
/**
|
||||
* Apps removal routes factory
|
||||
* @param {Object} deps - Explicit dependencies
|
||||
* @param {Object} deps.docker - Docker client wrapper
|
||||
* @param {Object} deps.caddy - Caddy client
|
||||
* @param {Object} deps.servicesStateManager - Services state manager
|
||||
* @param {Function} deps.asyncHandler - Async route handler wrapper
|
||||
* @param {Object} deps.log - Logger instance
|
||||
* @param {Object} deps.helpers - Apps helpers module
|
||||
* @param {Function} deps.errorResponse - Error response helper
|
||||
* @param {Object} deps.dns - DNS context
|
||||
* @param {Object} deps.siteConfig - Site configuration
|
||||
* @param {Function} deps.buildDomain - Build domain helper
|
||||
* @param {string} deps.SERVICES_FILE - Services file path
|
||||
* @param {Function} deps.safeErrorMessage - Safe error message formatter
|
||||
* @returns {express.Router}
|
||||
*/
|
||||
router.delete('/apps/:appId', asyncHandler(async (req, res) => {
|
||||
const { appId } = req.params;
|
||||
const { containerId, subdomain, ip, deleteContainer } = req.query;
|
||||
|
||||
@@ -8,14 +8,23 @@ const { DOCKER } = require('../../constants');
|
||||
* @param {Object} deps.caddy - Caddy client
|
||||
* @param {Object} deps.servicesStateManager - Services state manager
|
||||
* @param {Function} deps.asyncHandler - Async route handler wrapper
|
||||
* @param {Function} deps.errorResponse - Error response helper
|
||||
* @param {Object} deps.log - Logger instance
|
||||
* @param {Object} deps.helpers - Apps helpers module
|
||||
* @param {Object} deps.APP_TEMPLATES - App templates registry
|
||||
* @param {Object} deps.dns - DNS client
|
||||
* @param {Function} deps.buildServiceUrl - Service URL builder
|
||||
* @returns {express.Router}
|
||||
*/
|
||||
module.exports = function(ctx) {
|
||||
const { docker, caddy, servicesStateManager, asyncHandler, log, helpers } = ctx;
|
||||
module.exports = function({ docker, caddy, servicesStateManager, asyncHandler, errorResponse, log, helpers, APP_TEMPLATES, dns, buildServiceUrl }) {
|
||||
const router = express.Router();
|
||||
|
||||
const ctx = {
|
||||
APP_TEMPLATES,
|
||||
dns,
|
||||
buildServiceUrl
|
||||
};
|
||||
|
||||
/**
|
||||
* Restore a single service from its deployment manifest.
|
||||
* Pulls image, creates container, starts it, recreates Caddy config.
|
||||
@@ -125,11 +134,6 @@ module.exports = function(ctx) {
|
||||
// Static sites: just recreate Caddy config
|
||||
if (template?.isStaticSite) {
|
||||
log.info('restore', `Restoring static site Caddy config: ${service.name}`);
|
||||
const caddyOptions = {
|
||||
tailscaleOnly: manifest.caddy.tailscaleOnly,
|
||||
allowedIPs: manifest.caddy.allowedIPs,
|
||||
subpathSupport: manifest.caddy.subpathSupport,
|
||||
};
|
||||
// Static site Caddy config would need to be regenerated
|
||||
// For now, just confirm the service entry exists
|
||||
return {
|
||||
@@ -288,7 +292,7 @@ module.exports = function(ctx) {
|
||||
const svc = services.find(s => s.id === service.id);
|
||||
if (svc) {
|
||||
svc.containerId = container.id;
|
||||
svc.url = ctx.buildServiceUrl(manifest.config.subdomain);
|
||||
svc.url = buildServiceUrl(manifest.config.subdomain);
|
||||
}
|
||||
return services;
|
||||
});
|
||||
|
||||
@@ -6,14 +6,40 @@ const { exists } = require('../../fs-helpers');
|
||||
* @param {Object} deps.servicesStateManager - Services state manager
|
||||
* @param {Function} deps.asyncHandler - Async route handler wrapper
|
||||
* @param {Object} deps.helpers - Apps helpers module
|
||||
* @param {Object} deps.APP_TEMPLATES - App templates registry
|
||||
* @param {Object} deps.TEMPLATE_CATEGORIES - Template categories
|
||||
* @param {Object} deps.DIFFICULTY_LEVELS - Difficulty levels
|
||||
* @param {Object} deps.docker - Docker client
|
||||
* @param {Object} deps.caddy - Caddy client
|
||||
* @param {Object} deps.dns - DNS context
|
||||
* @param {Object} deps.siteConfig - Site configuration
|
||||
* @param {Function} deps.buildDomain - Build domain helper
|
||||
* @param {Function} deps.errorResponse - Error response helper
|
||||
* @param {Object} deps.log - Logger instance
|
||||
* @param {string} deps.SERVICES_FILE - Services file path
|
||||
* @returns {express.Router}
|
||||
*/
|
||||
const { REGEX } = require('../../constants');
|
||||
|
||||
module.exports = function(ctx) {
|
||||
const { servicesStateManager, asyncHandler, helpers, docker, caddy, log, errorResponse } = ctx;
|
||||
module.exports = function({
|
||||
servicesStateManager, asyncHandler, helpers,
|
||||
APP_TEMPLATES, TEMPLATE_CATEGORIES, DIFFICULTY_LEVELS,
|
||||
docker, caddy, dns, siteConfig, buildDomain,
|
||||
errorResponse, log, SERVICES_FILE
|
||||
}) {
|
||||
const router = express.Router();
|
||||
|
||||
// Ctx shim for backward compatibility with existing route code
|
||||
const ctx = {
|
||||
APP_TEMPLATES,
|
||||
TEMPLATE_CATEGORIES,
|
||||
DIFFICULTY_LEVELS,
|
||||
dns,
|
||||
siteConfig,
|
||||
buildDomain,
|
||||
SERVICES_FILE
|
||||
};
|
||||
|
||||
// Get available app templates
|
||||
router.get('/apps/templates', asyncHandler(async (req, res) => {
|
||||
res.json({
|
||||
@@ -64,6 +90,8 @@ module.exports = function(ctx) {
|
||||
// Update subdomain for deployed app
|
||||
router.post('/apps/update-subdomain', asyncHandler(async (req, res) => {
|
||||
const { serviceId, oldSubdomain, newSubdomain, containerId, ip } = req.body;
|
||||
const { ValidationError } = require('../../errors');
|
||||
|
||||
if (!oldSubdomain || typeof oldSubdomain !== 'string') {
|
||||
throw new ValidationError('oldSubdomain is required');
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ module.exports = function(ctx) {
|
||||
const results = { radarr: null, sonarr: null };
|
||||
|
||||
// Step 1: Authenticate with Overseerr via Plex token
|
||||
let overseerrUrl = `http://host.docker.internal:${APP_PORTS.overseerr}`;
|
||||
const overseerrUrl = `http://host.docker.internal:${APP_PORTS.overseerr}`;
|
||||
const overseerrSession = await helpers.getOverseerrSession();
|
||||
|
||||
if (!overseerrSession) {
|
||||
@@ -227,7 +227,7 @@ module.exports = function(ctx) {
|
||||
}
|
||||
|
||||
// Normalize URL - remove trailing slash
|
||||
let baseUrl = url.replace(/\/+$/, '');
|
||||
const baseUrl = url.replace(/\/+$/, '');
|
||||
|
||||
// Build the API endpoint
|
||||
let apiEndpoint;
|
||||
|
||||
@@ -9,12 +9,18 @@ const { APP_PORTS } = require('../../constants');
|
||||
* @param {Function} deps.errorResponse - Error response helper
|
||||
* @param {Object} deps.log - Logger instance
|
||||
* @param {Object} deps.helpers - Arr helpers module
|
||||
* @param {Object} deps.credentialManager - Credential manager
|
||||
* @param {Object} deps.servicesStateManager - Services state manager
|
||||
* @returns {express.Router}
|
||||
*/
|
||||
module.exports = function(ctx) {
|
||||
const { fetchT, asyncHandler, errorResponse, log, helpers } = ctx;
|
||||
module.exports = function({ fetchT, asyncHandler, errorResponse, log: _log, helpers, credentialManager, servicesStateManager }) {
|
||||
const router = express.Router();
|
||||
|
||||
const ctx = {
|
||||
credentialManager,
|
||||
servicesStateManager
|
||||
};
|
||||
|
||||
// Plex Libraries endpoint
|
||||
router.get('/plex/libraries', asyncHandler(async (req, res) => {
|
||||
// Get Plex token
|
||||
|
||||
@@ -10,12 +10,18 @@ const { APP_PORTS } = require('../../constants');
|
||||
* @param {Function} deps.errorResponse - Error response helper
|
||||
* @param {Object} deps.log - Logger instance
|
||||
* @param {Object} deps.helpers - Arr helpers module
|
||||
* @param {Object} deps.servicesStateManager - Services state manager
|
||||
* @param {Object} deps.notification - Notification helper
|
||||
* @returns {express.Router}
|
||||
*/
|
||||
module.exports = function(ctx) {
|
||||
const { credentialManager, fetchT, asyncHandler, errorResponse, log, helpers } = ctx;
|
||||
module.exports = function({ credentialManager, servicesStateManager, fetchT, asyncHandler, errorResponse: _errorResponse, log: _log, helpers, notification }) {
|
||||
const router = express.Router();
|
||||
|
||||
const ctx = {
|
||||
servicesStateManager,
|
||||
notification
|
||||
};
|
||||
|
||||
// Smart Connect: Unified orchestration endpoint
|
||||
router.post('/arr/smart-connect', asyncHandler(async (req, res) => {
|
||||
const { services: inputServices, configurePlex, configureProwlarr, configureSeerr, saveCredentials } = req.body;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
const { SESSION_TTL, APP, PLEX, TIMEOUTS, buildMediaAuth } = require('../../constants');
|
||||
const { createCache, CACHE_CONFIGS } = require('../../cache-config');
|
||||
|
||||
module.exports = function({ authManager, credentialManager, fetchT, asyncHandler, errorResponse, log }) {
|
||||
// App session cache for auto-login
|
||||
/**
|
||||
* Auth session handlers routes factory
|
||||
* @param {Object} deps - Explicit dependencies
|
||||
@@ -11,8 +9,11 @@ module.exports = function({ authManager, credentialManager, fetchT, asyncHandler
|
||||
* @param {Function} deps.asyncHandler - Async route handler wrapper
|
||||
* @param {Function} deps.errorResponse - Error response helper
|
||||
* @param {Object} deps.log - Logger instance
|
||||
* @returns {express.Router}
|
||||
* @param {Function} deps.fetchT - Timeout-wrapped fetch
|
||||
* @returns {{ getAppSession: Function, appSessionCache: Object }}
|
||||
*/
|
||||
module.exports = function({ authManager: _authManager, credentialManager: _credentialManager, asyncHandler: _asyncHandler, errorResponse: _errorResponse, log, fetchT }) {
|
||||
const ctx = { fetchT };
|
||||
const appSessionCache = createCache(CACHE_CONFIGS.appSessions);
|
||||
|
||||
async function getAppSession(serviceId, baseUrl, username, password) {
|
||||
|
||||
@@ -4,7 +4,7 @@ const fsp = require('fs').promises;
|
||||
const path = require('path');
|
||||
const { exists, isAccessible } = require('../fs-helpers');
|
||||
const { paginate, parsePaginationParams } = require('../pagination');
|
||||
const { ValidationError } = require('../errors');
|
||||
const { ValidationError, ForbiddenError } = require('../errors');
|
||||
|
||||
/**
|
||||
* Browse route factory
|
||||
|
||||
@@ -4,6 +4,7 @@ const fsp = require('fs').promises;
|
||||
const path = require('path');
|
||||
const { execSync } = require('child_process');
|
||||
const { exists } = require('../fs-helpers');
|
||||
const { ValidationError } = require('../errors');
|
||||
const platformPaths = require('../platform-paths');
|
||||
|
||||
module.exports = function(ctx) {
|
||||
|
||||
@@ -22,9 +22,9 @@ try {
|
||||
// Image processing libraries not available — favicon conversion disabled
|
||||
}
|
||||
|
||||
module.exports = function(ctx) {
|
||||
const { servicesStateManager, asyncHandler, log } = ctx;
|
||||
module.exports = function({ servicesStateManager: _servicesStateManager, asyncHandler, log: _log, CONFIG_FILE, readConfig, saveConfig, errorResponse }) {
|
||||
const router = express.Router();
|
||||
const ctx = { CONFIG_FILE, readConfig, saveConfig, errorResponse };
|
||||
|
||||
// ===== ASSET UPLOAD =====
|
||||
|
||||
@@ -47,7 +47,6 @@ module.exports = function(ctx) {
|
||||
throw new ValidationError('Invalid image data format');
|
||||
}
|
||||
|
||||
const extension = matches[1] === 'svg+xml' ? 'svg' : matches[1];
|
||||
const base64Data = matches[2];
|
||||
const buffer = Buffer.from(base64Data, 'base64');
|
||||
|
||||
@@ -109,6 +108,7 @@ module.exports = function(ctx) {
|
||||
|
||||
// Upload custom logo(s) and/or update position and title
|
||||
// Supports: dataDark/dataLight (separate variants) or data (single logo for both)
|
||||
// eslint-disable-next-line complexity
|
||||
router.post('/logo', express.json({ limit: LIMITS.BODY_UPLOAD }), asyncHandler(async (req, res) => {
|
||||
const { data, dataDark, dataLight, position, dashboardTitle } = req.body;
|
||||
|
||||
@@ -231,7 +231,6 @@ module.exports = function(ctx) {
|
||||
throw new ValidationError('Invalid image data format');
|
||||
}
|
||||
|
||||
const imageType = matches[1];
|
||||
const base64Data = matches[2];
|
||||
const buffer = Buffer.from(base64Data, 'base64');
|
||||
|
||||
|
||||
@@ -13,7 +13,10 @@ module.exports = function(ctx) {
|
||||
configStateManager: ctx.configStateManager,
|
||||
servicesStateManager: ctx.servicesStateManager,
|
||||
asyncHandler: ctx.asyncHandler,
|
||||
log: ctx.log
|
||||
log: ctx.log,
|
||||
CONFIG_FILE: ctx.CONFIG_FILE,
|
||||
errorResponse: ctx.errorResponse,
|
||||
loadSiteConfig: ctx.loadSiteConfig
|
||||
};
|
||||
|
||||
// Additional deps for backup route
|
||||
@@ -35,8 +38,8 @@ module.exports = function(ctx) {
|
||||
saveTotpConfig: ctx.saveTotpConfig
|
||||
};
|
||||
|
||||
router.use(require('./settings')(ctx));
|
||||
router.use(require('./assets')(ctx));
|
||||
router.use(require('./settings')(baseDeps));
|
||||
router.use(require('./assets')({ ...baseDeps, readConfig: ctx.readConfig, saveConfig: ctx.saveConfig }));
|
||||
router.use(require('./backup')(backupDeps));
|
||||
return router;
|
||||
};
|
||||
|
||||
@@ -5,13 +5,19 @@ const { ValidationError } = require('../../errors');
|
||||
|
||||
/**
|
||||
* Config settings routes factory
|
||||
* @param {Object} ctx - Application context
|
||||
* @param {Object} deps - Explicit dependencies
|
||||
* @param {Object} deps.configStateManager - Config state manager
|
||||
* @param {Function} deps.asyncHandler - Async route handler wrapper
|
||||
* @param {Object} deps.log - Logger instance
|
||||
* @param {string} deps.CONFIG_FILE - Config file path
|
||||
* @param {Function} deps.errorResponse - Error response helper
|
||||
* @param {Function} deps.loadSiteConfig - Site config reload helper
|
||||
* @returns {express.Router}
|
||||
*/
|
||||
module.exports = function(ctx) {
|
||||
const { configStateManager, asyncHandler, log } = ctx;
|
||||
module.exports = function({ configStateManager: _configStateManager, asyncHandler, log, CONFIG_FILE, errorResponse, loadSiteConfig }) {
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const ctx = { CONFIG_FILE, errorResponse, loadSiteConfig };
|
||||
|
||||
// ===== DASHCADDY CONFIG ENDPOINTS =====
|
||||
// Server-side config storage for setup wizard (shared across all browsers/machines)
|
||||
@@ -60,7 +66,9 @@ module.exports = function(ctx) {
|
||||
config.updatedAt = new Date().toISOString();
|
||||
|
||||
await fsp.writeFile(ctx.CONFIG_FILE, JSON.stringify(config, null, 2), 'utf8');
|
||||
ctx.loadSiteConfig(); // Refresh in-memory config
|
||||
if (typeof ctx.loadSiteConfig === 'function') {
|
||||
ctx.loadSiteConfig(); // Refresh in-memory config
|
||||
}
|
||||
log.info('config', 'Config saved', { path: ctx.CONFIG_FILE });
|
||||
|
||||
res.json({ success: true, message: 'Configuration saved', config, warnings });
|
||||
|
||||
@@ -8,6 +8,7 @@ const { paginate, parsePaginationParams } = require('../pagination');
|
||||
const platformPaths = require('../platform-paths');
|
||||
const { resolveServiceUrl } = require('../url-resolver');
|
||||
const { success, error: errorResponse } = require('../response-helpers');
|
||||
const { ValidationError } = require('../errors');
|
||||
|
||||
/**
|
||||
* Health routes factory
|
||||
@@ -54,7 +55,7 @@ module.exports = function({
|
||||
url,
|
||||
checkedAt: new Date().toISOString()
|
||||
};
|
||||
} catch (_) {}
|
||||
} catch { /* ignore */ }
|
||||
|
||||
// Fallback to GET
|
||||
try {
|
||||
|
||||
@@ -4,7 +4,7 @@ const fsp = require('fs').promises;
|
||||
const path = require('path');
|
||||
const { exists } = require('../fs-helpers');
|
||||
const { paginate, parsePaginationParams } = require('../pagination');
|
||||
const { NotFoundError } = require('../errors');
|
||||
const { NotFoundError, ValidationError, ForbiddenError } = require('../errors');
|
||||
|
||||
/**
|
||||
* Logs route factory
|
||||
|
||||
@@ -14,9 +14,9 @@ const { DOCKER } = require('../../constants');
|
||||
* @param {Object} deps.log - Logger instance
|
||||
* @returns {express.Router}
|
||||
*/
|
||||
module.exports = function(ctx) {
|
||||
const { docker, credentialManager, servicesStateManager, asyncHandler, errorResponse, log } = ctx;
|
||||
module.exports = function({ docker, credentialManager: _credentialManager, servicesStateManager: _servicesStateManager, asyncHandler, errorResponse: _errorResponse, log, addServiceToConfig, notification, APP_TEMPLATES, siteConfig, caddy, buildDomain }) {
|
||||
const router = express.Router();
|
||||
const ctx = { addServiceToConfig, notification, APP_TEMPLATES, siteConfig, caddy, buildDomain };
|
||||
|
||||
/**
|
||||
* Deploy a recipe — creates multiple containers as a coordinated stack
|
||||
@@ -24,6 +24,7 @@ module.exports = function(ctx) {
|
||||
* POST /api/recipes/deploy
|
||||
* Body: { recipeId, config: { selectedComponents, sharedConfig, componentOverrides } }
|
||||
*/
|
||||
// eslint-disable-next-line complexity
|
||||
router.post('/deploy', asyncHandler(async (req, res) => {
|
||||
const { recipeId, config } = req.body;
|
||||
const { RECIPE_TEMPLATES } = require('../../recipe-templates');
|
||||
@@ -44,7 +45,6 @@ module.exports = function(ctx) {
|
||||
|
||||
// Generate shared passwords for the recipe (consistent across components)
|
||||
const generatedPasswords = {};
|
||||
const passwordKey = `recipe-${recipeId}-${Date.now()}`;
|
||||
generatedPasswords.default = crypto.randomBytes(24).toString('base64url');
|
||||
|
||||
// Create Docker network if defined
|
||||
@@ -185,6 +185,7 @@ module.exports = function(ctx) {
|
||||
/**
|
||||
* Deploy a single component of a recipe
|
||||
*/
|
||||
// eslint-disable-next-line complexity
|
||||
async function deployComponent(component, recipe, config, passwords, networkName) {
|
||||
const sharedConfig = config.sharedConfig || {};
|
||||
const overrides = config.componentOverrides?.[component.id] || {};
|
||||
@@ -364,7 +365,7 @@ module.exports = function(ctx) {
|
||||
/**
|
||||
* Run auto-connect steps after recipe deployment
|
||||
*/
|
||||
async function runAutoConnect(recipe, deployedComponents, config) {
|
||||
async function runAutoConnect(recipe, _deployedComponents, _config) {
|
||||
if (!recipe.autoConnect?.steps) return;
|
||||
|
||||
// Wait for services to be fully ready
|
||||
|
||||
@@ -17,7 +17,13 @@ module.exports = function(ctx) {
|
||||
servicesStateManager: ctx.servicesStateManager,
|
||||
asyncHandler: ctx.asyncHandler,
|
||||
errorResponse: ctx.errorResponse,
|
||||
log: ctx.log
|
||||
log: ctx.log,
|
||||
notification: ctx.notification,
|
||||
buildDomain: ctx.buildDomain,
|
||||
caddy: ctx.caddy,
|
||||
addServiceToConfig: ctx.addServiceToConfig,
|
||||
APP_TEMPLATES: ctx.APP_TEMPLATES,
|
||||
siteConfig: ctx.siteConfig
|
||||
};
|
||||
|
||||
// All recipe routes require premium license
|
||||
|
||||
@@ -2,9 +2,12 @@ const express = require('express');
|
||||
const { DOCKER } = require('../../constants');
|
||||
const { NotFoundError } = require('../../errors');
|
||||
|
||||
module.exports = function(ctx) {
|
||||
const { servicesStateManager, asyncHandler, log } = ctx;
|
||||
module.exports = function({ servicesStateManager, asyncHandler, log, docker, notification, buildDomain, caddy }) {
|
||||
const router = express.Router();
|
||||
|
||||
// Ctx shim for backward compatibility
|
||||
const ctx = { docker, notification, buildDomain, caddy };
|
||||
|
||||
/**
|
||||
* Recipes management routes factory
|
||||
* @param {Object} deps - Explicit dependencies
|
||||
@@ -303,7 +306,7 @@ module.exports = function(ctx) {
|
||||
*/
|
||||
async function removeCaddyBlock(subdomain) {
|
||||
const domain = ctx.buildDomain(subdomain);
|
||||
let content = await ctx.caddy.read();
|
||||
const content = await ctx.caddy.read();
|
||||
|
||||
// Find and remove the block for this domain
|
||||
const escapedDomain = domain.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
|
||||
@@ -8,6 +8,7 @@ const { APP, REGEX, TIMEOUTS } = require('../constants');
|
||||
const { validateServiceConfig, isValidPort } = require('../input-validator');
|
||||
const { exists } = require('../fs-helpers');
|
||||
const { paginate, parsePaginationParams } = require('../pagination');
|
||||
const { ValidationError, NotFoundError } = require('../errors');
|
||||
const { resolveServiceUrl } = require('../url-resolver');
|
||||
const { success, error: errorResponse } = require('../response-helpers');
|
||||
const { ConflictError, ValidationError, NotFoundError } = require('../errors');
|
||||
@@ -470,7 +471,7 @@ module.exports = function({
|
||||
const oldDomain = buildDomain(oldSubdomain);
|
||||
const newDomain = buildDomain(newSubdomain);
|
||||
|
||||
let content = await caddy.read();
|
||||
const content = await caddy.read();
|
||||
|
||||
const escapedOldDomain = oldDomain.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
const siteBlockRegex = new RegExp(
|
||||
|
||||
@@ -164,7 +164,7 @@ module.exports = function({ asyncHandler, caddy, dns, fetchT, buildDomain, addSe
|
||||
const upstreamRegex = /^[a-z0-9.-]+:\d{1,5}$/i;
|
||||
if (!upstreamRegex.test(upstream)) throw new ValidationError('Invalid upstream format. Use host:port');
|
||||
|
||||
let content = await caddy.read();
|
||||
const content = await caddy.read();
|
||||
const escapedDomain = domain.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
const siteBlockRegex = new RegExp(`\\n?${escapedDomain}\\s*\\{`, 'g');
|
||||
if (siteBlockRegex.test(content)) {
|
||||
@@ -203,7 +203,6 @@ module.exports = function({ asyncHandler, caddy, dns, fetchT, buildDomain, addSe
|
||||
const domain = buildDomain(subdomain);
|
||||
let dnsWarning = null;
|
||||
|
||||
try {
|
||||
if (createDns) {
|
||||
try {
|
||||
await dns.createRecord(subdomain, siteConfig.dnsServerIp);
|
||||
@@ -267,9 +266,6 @@ module.exports = function({ asyncHandler, caddy, dns, fetchT, buildDomain, addSe
|
||||
};
|
||||
if (dnsWarning) response.warning = dnsWarning;
|
||||
res.json(response);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}, 'site-external'));
|
||||
|
||||
return router;
|
||||
|
||||
@@ -152,7 +152,7 @@ module.exports = function({
|
||||
throw new ValidationError('subdomain is required');
|
||||
}
|
||||
|
||||
let content = await caddy.read();
|
||||
const content = await caddy.read();
|
||||
const domain = buildDomain(subdomain);
|
||||
|
||||
const blockRegex = new RegExp(`(${domain.replace('.', '\\.')}\\s*\\{[^}]*\\})`, 's');
|
||||
|
||||
Reference in New Issue
Block a user