fix: service edit, CSRF token stability, and license restore (v1.1.1)
- Fix service edit double-write bug (was creating duplicate entries) - Add editable display name field to service edit modal - Backend update endpoint now accepts name, logo, and recalculates url - Fix CSRF token regeneration breaking all POST requests (nonce was being regenerated on every request, invalidating cached tokens) - CSRF nonce now persists across requests, rotated only on TOTP login - Frontend secureFetch auto-retries on CSRF failure with fresh token - Restore lifetime license activation on DNS2 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -371,9 +371,9 @@ module.exports = function(ctx) {
|
||||
res.json({ success: true, message: `Service "${id}" removed from dashboard` });
|
||||
}, 'services-delete'));
|
||||
|
||||
// Update service configuration (subdomain, port, IP, tailscale)
|
||||
// Update service configuration (subdomain, port, IP, tailscale, name, logo)
|
||||
router.post('/services/update', ctx.asyncHandler(async (req, res) => {
|
||||
const { oldSubdomain, newSubdomain, port, ip, tailscaleOnly } = req.body;
|
||||
const { oldSubdomain, newSubdomain, port, ip, tailscaleOnly, name, logo } = req.body;
|
||||
|
||||
if (!oldSubdomain || !newSubdomain) {
|
||||
return ctx.errorResponse(res, 400, 'oldSubdomain and newSubdomain are required');
|
||||
@@ -440,13 +440,20 @@ module.exports = function(ctx) {
|
||||
await ctx.servicesStateManager.update(services => {
|
||||
const serviceIndex = services.findIndex(s => s.id === oldSubdomain);
|
||||
if (serviceIndex !== -1) {
|
||||
const existing = services[serviceIndex];
|
||||
const finalPort = port || existing.port;
|
||||
const finalIp = ip || existing.ip;
|
||||
|
||||
services[serviceIndex] = {
|
||||
...services[serviceIndex],
|
||||
...existing,
|
||||
id: newSubdomain,
|
||||
port: port || services[serviceIndex].port,
|
||||
ip: ip || services[serviceIndex].ip,
|
||||
tailscaleOnly: tailscaleOnly || false
|
||||
port: finalPort,
|
||||
ip: finalIp,
|
||||
tailscaleOnly: tailscaleOnly || false,
|
||||
url: ctx.buildServiceUrl(newSubdomain)
|
||||
};
|
||||
if (name) services[serviceIndex].name = name;
|
||||
if (logo) services[serviceIndex].logo = logo;
|
||||
results.services = 'updated';
|
||||
} else {
|
||||
results.services = 'not found';
|
||||
|
||||
Reference in New Issue
Block a user