Host form/list UX polish: editable hostname, created-by column, mobile tabs, more help text
- Plain hosts can now be renamed after creation (wildcard/child/cache hosts stay locked, since other records reference them by name). Migrates the cert cache key on rename. - Along the way, found and fixed a real bug in the vendored model-redis library: its rename path leaves a stray, incomplete hash behind under the old key when an `always`-type field (updated_on) is defined earlier in the schema than the primary key -- silently blocking that hostname from ever being reused. Worked around at the Host model level (can't patch node_modules). - Host list now shows who created each host, and when. - Host modal's tabs now scroll horizontally on narrow screens instead of overflowing awkwardly. - Added missing inline help text (Target SSL, wildcard matching behavior). Bumps to v1.1.9. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KDEx8ghuZR61pqPXc6da9C
This commit is contained in:
+34
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
const Table = require('.');
|
||||
const {Domain} = require('.').models;
|
||||
const {deleteCert} = require('./cert');
|
||||
const {getCert, setCert, deleteCert} = require('./cert');
|
||||
const ModelPs = require('../utils/model_pubsub');
|
||||
|
||||
const tldExtract = require('tld-extract').parse_host;
|
||||
@@ -343,10 +343,43 @@ class Host extends Table{
|
||||
}
|
||||
}
|
||||
|
||||
// Real hostname rename. model-redis's own update() (see super.update()
|
||||
// below) already handles the Redis primary-key RENAME + collision
|
||||
// check, and Host.buildLookUpObj() below already rebuilds the lookup
|
||||
// tree afterward -- but the cert cache (models/cert.js, `${host}:latest`)
|
||||
// is a separate record keyed by hostname string that the generic field
|
||||
// system doesn't know about, so it doesn't move on its own. Only
|
||||
// wildcard hosts (createWildcardCert) ever populate this key -- for a
|
||||
// plain HTTP-01 host this is a no-op (nothing to migrate; auto-ssl
|
||||
// transparently issues a fresh cert under the new name on first
|
||||
// access, same as it does for any newly-created host).
|
||||
let oldHost = this.host;
|
||||
let renaming = data && typeof data.host === 'string' && data.host !== oldHost;
|
||||
if(renaming){
|
||||
let cert = await getCert(oldHost);
|
||||
if(cert && Object.keys(cert).length) await setCert(data.host, cert);
|
||||
}
|
||||
|
||||
let out = await super.update(data, ...args)
|
||||
await this.bustCache(this.host);
|
||||
await Host.buildLookUpObj();
|
||||
|
||||
if(renaming){
|
||||
await deleteCert(oldHost);
|
||||
|
||||
// Work around a model-redis bug (as of ^1.5.0): super.update()'s
|
||||
// field-application loop iterates _keyMap's definition order and
|
||||
// only reassigns this[_key] (this.host) to the NEW value once it
|
||||
// reaches the `host` field itself -- but `updated_on` (always:
|
||||
// true, so always included) is defined BEFORE `host` in _keyMap,
|
||||
// so it gets HSET while this.host is still the OLD name. Redis's
|
||||
// HSET on a non-existent key (the old hash, just RENAMEd away)
|
||||
// silently recreates it -- leaving a stray, incomplete hash under
|
||||
// the old hostname that makes Host.exists(oldHost) wrongly return
|
||||
// true forever, blocking that name from ever being reused.
|
||||
await this.constructor.redisClient.DEL(`${conf.redis.prefix || ''}Host_${oldHost}`);
|
||||
}
|
||||
|
||||
return out;
|
||||
} catch(error){
|
||||
throw error;
|
||||
|
||||
Reference in New Issue
Block a user