Fix wildcard-parent edit greying and deprecated nginx http2 directive
- The edit form's "Parent Wildcard" option stayed greyed out even when a valid wildcard existed, since hostEditOpen() never ran the eligibility check (only the host field's keyup handler did, which setting .val() programmatically doesn't fire) -- and the check itself, GET /host/lookup/:item, had the same self-match bug as the recently-fixed Host.prototype.update() case: it resolves an already-existing host to its own record instead of a sibling wildcard. Added a dedicated /host/wildcard-parent/:item route combining lookUp() (handles a brand-new subdomain) with lookUpWildcardParent() (handles an already-existing host), and hostEditOpen() now actually runs it. - Migrated ops/nginx_conf/autossl.conf's deprecated "listen ... http2" directive to the standalone "http2 on;" directive (nginx 1.25.1+). Bumps to v1.1.12. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KDEx8ghuZR61pqPXc6da9C
This commit is contained in:
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "proxy-api",
|
||||
"version": "1.1.11",
|
||||
"version": "1.1.12",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "proxy-api",
|
||||
"version": "1.1.11",
|
||||
"version": "1.1.12",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^7.3.0",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "proxy-api",
|
||||
"version": "1.1.11",
|
||||
"version": "1.1.12",
|
||||
"private": true,
|
||||
"author": [
|
||||
{
|
||||
|
||||
@@ -128,6 +128,29 @@ router.get('/lookup/:item', authz.requireDomainRole('viewer', authz.resolve.host
|
||||
}
|
||||
});
|
||||
|
||||
// Is there a wildcard host that could serve as :item's parent (i.e. an
|
||||
// already-issued cert :item could reuse instead of getting its own)? Two
|
||||
// cases, covered by two different lookups: a brand-new subdomain that has
|
||||
// never been created (lookUp()'s normal wildcard fallback finds it, since
|
||||
// the name has no leaf of its own yet), and an ALREADY-EXISTING host or the
|
||||
// wildcard's own base domain (lookUp() would just resolve to that host's
|
||||
// own leaf -- lookUpWildcardParent() checks the sibling "*" slot instead;
|
||||
// see its comment in models/host.js). Used by the host create/edit form to
|
||||
// decide whether to offer "Parent Wildcard" as a challenge type.
|
||||
router.get('/wildcard-parent/:item', authz.requireDomainRole('viewer', authz.resolve.hostParam), async function(req, res, next){
|
||||
try{
|
||||
let match = Model.lookUp(req.params.item);
|
||||
if(!match || !match.is_wildcard){
|
||||
match = Model.lookUpWildcardParent(req.params.item);
|
||||
}
|
||||
return res.json({
|
||||
results: (match && match.is_wildcard) ? match : null,
|
||||
});
|
||||
}catch(error){
|
||||
return next(error);
|
||||
}
|
||||
});
|
||||
|
||||
// The full lookup tree exposes every host, so restrict it to admins.
|
||||
router.get('/lookupobj', authz.requireAdmin, async function(req, res, next){
|
||||
try{
|
||||
|
||||
@@ -187,6 +187,52 @@ describe('Host wildcard base-domain lookup', () => {
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests for the exact fallback combination used by
|
||||
* routes/host.js's GET /wildcard-parent/:item (and, via hostMatchWildcard(),
|
||||
* the host create/edit form's "Parent Wildcard" option) -- lookUp() first
|
||||
* (handles a brand-new subdomain that has no leaf of its own yet), falling
|
||||
* back to lookUpWildcardParent() only when lookUp() didn't resolve to a
|
||||
* wildcard (handles an ALREADY-EXISTING host, which lookUp() would resolve
|
||||
* to its own record). Regression coverage for the edit-form bug where the
|
||||
* "Parent Wildcard" option stayed permanently greyed out for an existing
|
||||
* host, because the route only ever tried lookUp().
|
||||
*/
|
||||
describe('Host wildcard-parent route fallback (lookUp then lookUpWildcardParent)', () => {
|
||||
|
||||
let Host;
|
||||
|
||||
before(async () => {
|
||||
Host = createMockHostClassWithWildcardParentFix();
|
||||
});
|
||||
|
||||
function findWildcardParent(host){
|
||||
let match = Host.lookUp(host);
|
||||
if(!match || !match.is_wildcard) match = Host.lookUpWildcardParent(host);
|
||||
return (match && match.is_wildcard) ? match : null;
|
||||
}
|
||||
|
||||
test('finds the wildcard for a brand-new subdomain that was never created', async () => {
|
||||
await populateTree(Host, ['*.cool.mysite.com']);
|
||||
const result = findWildcardParent('newthing.cool.mysite.com');
|
||||
assert.ok(result);
|
||||
assert.strictEqual(result.host, '*.cool.mysite.com');
|
||||
});
|
||||
|
||||
test('finds the wildcard for the wildcard\'s own base domain, whether or not it is already a plain host', async () => {
|
||||
await populateTree(Host, ['*.cool.mysite.com']);
|
||||
assert.strictEqual(findWildcardParent('cool.mysite.com').host, '*.cool.mysite.com');
|
||||
|
||||
await populateTree(Host, ['*.cool.mysite.com', 'cool.mysite.com']);
|
||||
assert.strictEqual(findWildcardParent('cool.mysite.com').host, '*.cool.mysite.com');
|
||||
});
|
||||
|
||||
test('returns null when the host has no wildcard sibling at all', async () => {
|
||||
await populateTree(Host, ['cool.mysite.com']);
|
||||
assert.strictEqual(findWildcardParent('cool.mysite.com'), null);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Same mock shape as createMockHostClass() above, plus the parent-record
|
||||
* stamp in the tree-population loop and the lookUpWildcardParent() method --
|
||||
@@ -243,7 +289,11 @@ async function populateTree(Host, hosts) {
|
||||
}
|
||||
|
||||
if(fragments.length === 0){
|
||||
pointer[fragment]['#record'] = {host};
|
||||
// is_wildcard mirrors the real Host model's own field (set
|
||||
// whenever a host is DNS-01 wildcard-issued, i.e. starts with
|
||||
// "*."), needed by tests that check it the same way the real
|
||||
// /wildcard-parent/:item route does.
|
||||
pointer[fragment]['#record'] = {host, is_wildcard: host.startsWith('*.')};
|
||||
|
||||
if(fragment === '*' && !pointer['#record']){
|
||||
pointer['#record'] = pointer[fragment]['#record'];
|
||||
|
||||
+30
-5
@@ -212,7 +212,7 @@
|
||||
hostModal().show();
|
||||
}
|
||||
|
||||
function hostEditOpen(host){
|
||||
async function hostEditOpen(host){
|
||||
hostFormReset();
|
||||
let h = $.scope.hosts.getByKey(host);
|
||||
let $f = $('#hostForm');
|
||||
@@ -258,8 +258,31 @@
|
||||
let hostRenameable = !h.is_wildcard && !h.wildcard_parent && !h.is_cache;
|
||||
$f.find('[name=host]').prop('disabled', !hostRenameable);
|
||||
$('#host-rename-help').toggle(!hostRenameable);
|
||||
|
||||
// Reflect + enable the challenge-type options actually available for
|
||||
// this host. Setting the host field's .val() above does not fire a
|
||||
// 'keyup' event, so without this the "Parent Wildcard" option stayed
|
||||
// permanently greyed out on edit even when a valid parent wildcard
|
||||
// existed -- it only ever got un-greyed by the user re-typing the
|
||||
// hostname (the keyup handler further down).
|
||||
$('#challengeType-child-container, #challengeType-DNS-01-wildcard-container, #wildcard_matchAny-container')
|
||||
.addClass('challengeType-container');
|
||||
|
||||
if(h.is_wildcard){
|
||||
$('#challengeType-DNS-01-wildcard-container').removeClass('challengeType-container');
|
||||
$('#challengeType-DNS-01-wildcard').prop('checked', true);
|
||||
$('#wildcard_matchAny-container').removeClass('challengeType-container');
|
||||
}else{
|
||||
let wildcardParent = await hostMatchWildcard(h.host);
|
||||
if(wildcardParent){
|
||||
$('#challengeType-child-container').removeClass('challengeType-container');
|
||||
$('#challengeType-child-relatedHost').text(wildcardParent.host);
|
||||
}
|
||||
if(h.wildcard_parent){
|
||||
$('#challengeType-wildcardChild').prop('checked', true);
|
||||
}else{
|
||||
$('#challengeType-HTTP-01').prop('checked', true);
|
||||
}
|
||||
}
|
||||
|
||||
hostModal().show();
|
||||
@@ -306,10 +329,12 @@
|
||||
|
||||
async function hostMatchWildcard(host){
|
||||
try{
|
||||
let res = await app.api.get(`host/lookup/${host}`);
|
||||
if(res.results && res.results.is_wildcard){
|
||||
return res.results;
|
||||
}
|
||||
// Not /host/lookup/ -- that resolves an ALREADY-EXISTING host to its
|
||||
// own record, not a sibling wildcard (see the route's comment). This
|
||||
// dedicated endpoint correctly finds a usable wildcard parent whether
|
||||
// @host is brand new or already exists as its own host.
|
||||
let res = await app.api.get(`host/wildcard-parent/${host}`);
|
||||
return res.results || false;
|
||||
}catch(error){
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user