- self-updater.js: polls for new versions, downloads/verifies tarballs, triggers host-side rebuild via systemd path unit - dashcaddy-update.sh + systemd units: host-side container rebuild with automatic rollback on health check failure - 7 new /api/v1/system/* endpoints for version info, update check/apply, rollback, and update history - Frontend: DashCaddy tab in Updates modal with version display, changelog, update button, rollback, and notification dot - install.sh: updater service installation, volume mounts, env vars - build-release.sh + webhook-handler.js: release server pipeline (Gitea webhook → build tarball → deploy to get.dashcaddy.net) - Dockerfile: DASHCADDY_COMMIT build arg → VERSION file - Version bump to 1.1.0 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
142 lines
4.8 KiB
JavaScript
142 lines
4.8 KiB
JavaScript
/**
|
|
* Shared route context — holds all dependencies needed by route modules.
|
|
* Populated once by server.js at startup, then passed to each route factory.
|
|
*
|
|
* Usage in a route module:
|
|
* module.exports = function(ctx) {
|
|
* const router = require('express').Router();
|
|
* router.get('/status', ctx.asyncHandler(async (req, res) => { ... }));
|
|
* return router;
|
|
* };
|
|
*
|
|
* Namespaces: ctx.docker.*, ctx.caddy.*, ctx.dns.*, ctx.session.*,
|
|
* ctx.notification.*, ctx.tailscale.*
|
|
*/
|
|
const ctx = {
|
|
// ── Namespaced groups ──
|
|
docker: {
|
|
client: null, // Dockerode instance
|
|
pull: null, // dockerPull(imageName, timeoutMs)
|
|
findContainer: null, // findContainerByName(name, opts)
|
|
getUsedPorts: null, // getUsedPorts() → Set<number>
|
|
security: null, // dockerSecurity module
|
|
},
|
|
caddy: {
|
|
modify: null, // modifyCaddyfile(modifyFn) → {success, error?}
|
|
read: null, // readCaddyfile() → string
|
|
reload: null, // reloadCaddy(content)
|
|
generateConfig: null, // generateCaddyConfig(subdomain, ip, port, opts)
|
|
verifySite: null, // verifySiteAccessible(domain, maxAttempts)
|
|
adminUrl: null, // CADDY_ADMIN_URL string
|
|
filePath: null, // CADDYFILE_PATH string
|
|
},
|
|
dns: {
|
|
call: null, // callDns(server, apiPath, params)
|
|
buildUrl: null, // buildDnsUrl(server, apiPath, params)
|
|
requireToken: null, // requireDnsToken(providedToken)
|
|
ensureToken: null, // ensureValidDnsToken()
|
|
createRecord: null, // createDnsRecord(subdomain, ip)
|
|
getToken: null, // () => dnsToken
|
|
setToken: null, // (t) => { dnsToken = t }
|
|
getTokenExpiry: null, // () => dnsTokenExpiry
|
|
setTokenExpiry: null, // (e) => { dnsTokenExpiry = e }
|
|
getTokenForServer: null, // getTokenForServer(serverIp)
|
|
refresh: null, // refreshDnsToken()
|
|
credentialsFile: null,// DNS_CREDENTIALS_FILE path
|
|
},
|
|
session: {
|
|
ipSessions: null, // Map of IP → session
|
|
durations: null, // SESSION_DURATIONS map
|
|
getClientIP: null, // getClientIP(req)
|
|
create: null, // createIPSession(ip, duration)
|
|
setCookie: null, // setSessionCookie(res, duration)
|
|
clear: null, // clearIPSession(ip)
|
|
clearCookie: null, // clearSessionCookie(res)
|
|
isValid: null, // isSessionValid(req)
|
|
},
|
|
notification: {
|
|
getConfig: null, // () => notificationConfig
|
|
saveConfig: null, // saveNotificationConfig()
|
|
send: null, // sendNotification(event, title, message, type)
|
|
sendDiscord: null, // sendDiscordNotification(title, message, type)
|
|
sendTelegram: null, // sendTelegramNotification(title, message, type)
|
|
sendNtfy: null, // sendNtfyNotification(title, message, type)
|
|
getHistory: null, // () => notificationHistory
|
|
clearHistory: null, // () => { notificationHistory = [] }
|
|
startHealthDaemon: null, // startHealthCheckDaemon()
|
|
stopHealthDaemon: null, // stopHealthCheckDaemon()
|
|
checkHealth: null, // checkContainerHealth()
|
|
getHealthState: null, // () => containerHealthState
|
|
},
|
|
tailscale: {
|
|
config: null, // tailscaleConfig object
|
|
save: null, // saveTailscaleConfig()
|
|
getStatus: null, // getTailscaleStatus()
|
|
getLocalIP: null, // getLocalTailscaleIP()
|
|
isTailscaleIP: null, // isTailscaleIP(ip)
|
|
getAccessToken: null, // getTailscaleAccessToken()
|
|
syncAPI: null, // syncFromTailscaleAPI()
|
|
startSync: null, // startTailscaleSyncTimer()
|
|
stopSync: null, // stopTailscaleSyncTimer()
|
|
},
|
|
|
|
// ── Flat (shared across domains) ──
|
|
app: null,
|
|
siteConfig: null,
|
|
servicesStateManager: null,
|
|
configStateManager: null,
|
|
credentialManager: null,
|
|
authManager: null,
|
|
|
|
// Feature modules
|
|
healthChecker: null,
|
|
updateManager: null,
|
|
backupManager: null,
|
|
resourceMonitor: null,
|
|
auditLogger: null,
|
|
portLockManager: null,
|
|
selfUpdater: null,
|
|
|
|
// Templates
|
|
APP_TEMPLATES: null,
|
|
TEMPLATE_CATEGORIES: null,
|
|
DIFFICULTY_LEVELS: null,
|
|
|
|
// Shared helpers
|
|
asyncHandler: null,
|
|
errorResponse: null,
|
|
ok: null,
|
|
fetchT: null,
|
|
log: null,
|
|
logError: null,
|
|
safeErrorMessage: null,
|
|
buildDomain: null,
|
|
getServiceById: null,
|
|
readConfig: null,
|
|
saveConfig: null,
|
|
addServiceToConfig: null,
|
|
validateURL: null,
|
|
|
|
// Middleware
|
|
strictLimiter: null,
|
|
|
|
// TOTP (flat — used alongside session namespace)
|
|
totpConfig: null,
|
|
saveTotpConfig: null,
|
|
|
|
// Config lifecycle
|
|
loadSiteConfig: null,
|
|
loadDnsCredentials: null,
|
|
loadNotificationConfig: null,
|
|
|
|
// Config paths (flat)
|
|
SERVICES_FILE: null,
|
|
CONFIG_FILE: null,
|
|
TOTP_CONFIG_FILE: null,
|
|
TAILSCALE_CONFIG_FILE: null,
|
|
NOTIFICATIONS_FILE: null,
|
|
ERROR_LOG_FILE: null,
|
|
};
|
|
|
|
module.exports = ctx;
|