ci: swap deprecated ep_readonly_guest for ep_guest in plugin matrix (#7808)

ep_readonly_guest is archived (read-only on GitHub) and its
authenticate hook unconditionally swaps req.session.user with a
read-only guest, even when the request carries an HTTP Authorization
header. That silently demoted admin login attempts and stalled the
anonymizeAuthorSocket tests for 14 min/run on every with-plugins CI
matrix (#7795). The pre-fix theory blamed ep_hash_auth.handleMessage;
the actual hook trace is a red herring — handleMessage only fires on
the /pad namespace and never on /settings.

ep_guest is the maintained successor (same authors, same purpose).
1.0.72 on npm already includes the "defer to basic auth / admin
paths" fix backported to ep_readonly_guest by intent here. Swapping
the matrix unblocks the anonymizeAuthorSocket suite on Linux,
Windows, and the upgrade-from-latest-release workflow.

The runtime probe added in #7796 stays — it still catches any other
authenticate-hook plugin that rejects the test's plain-text
credentials (e.g. a future ep_hash_auth-style hashed-only plugin).
Reattribute its comment so future readers don't chase ep_hash_auth.

Closes #7795.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
John McLear 2026-05-18 13:30:58 +01:00 committed by GitHub
parent 4d94b1b465
commit 271eb6ab5c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 20 additions and 15 deletions

View file

@ -146,7 +146,7 @@ jobs:
ep_hash_auth
ep_headings2
ep_markdown
ep_readonly_guest
ep_guest
ep_set_title_on_pad
ep_spellcheck
ep_subscript_and_superscript
@ -289,7 +289,7 @@ jobs:
ep_hash_auth
ep_headings2
ep_markdown
ep_readonly_guest
ep_guest
ep_set_title_on_pad
ep_spellcheck
ep_subscript_and_superscript

View file

@ -219,7 +219,7 @@ jobs:
ep_hash_auth
ep_headings2
ep_markdown
ep_readonly_guest
ep_guest
ep_set_title_on_pad
ep_spellcheck
ep_subscript_and_superscript
@ -308,7 +308,7 @@ jobs:
ep_hash_auth
ep_headings2
ep_markdown
ep_readonly_guest
ep_guest
ep_set_title_on_pad
ep_spellcheck
ep_subscript_and_superscript

View file

@ -93,7 +93,7 @@ jobs:
ep_hash_auth
ep_headings2
ep_markdown
ep_readonly_guest
ep_guest
ep_set_title_on_pad
ep_spellcheck
ep_subscript_and_superscript

View file

@ -76,7 +76,7 @@ jobs:
ep_hash_auth
ep_headings2
ep_markdown
ep_readonly_guest
ep_guest
ep_set_title_on_pad
ep_spellcheck
ep_subscript_and_superscript

View file

@ -62,17 +62,21 @@ const ask = (socket: any, evt: string, payload: any, replyEvt: string) =>
});
// adminSocket() depends on Etherpad's default plain-text password check for
// settings.users[name].password. Plugins like ep_hash_auth replace the
// authenticate hook to expect hashed credentials, so the basic-auth probe
// returns no admin session, /settings's connection handler returns without
// settings.users[name].password. Any authenticate-hook plugin that claims
// the request before the built-in basic-auth fallback can block this:
// the historical offender was ep_readonly_guest, whose authenticate hook
// sorts itself first and silently swaps req.session.user with a guest
// (#7795); ep_hash_auth-style plugins that expect hashed credentials
// would do the same. When that happens the basic-auth probe returns no
// admin session, /settings's connection handler returns without
// registering listeners (see src/node/hooks/express/adminsettings.ts:25),
// and every socket.emit() afterwards waits forever for a reply that
// nothing will ever send. The socket itself still connects when admin
// session is missing, so the probe has to run at the application layer:
// emit a known `/settings` event (`load`) and wait for the matching reply
// (`settings`). If it doesn't arrive within the budget, skip — much
// cheaper than letting mocha's 120s per-test timeout absorb 7 stalled
// tests. Tracked in #7795.
// emit a known `/settings` event (`authorLoad`) and wait for the matching
// reply (`results:authorLoad`). If it doesn't arrive within the budget,
// skip — much cheaper than letting mocha's 120s per-test timeout absorb
// 7 stalled tests.
const PROBE_BUDGET_MS = 15000;
const adminSocketWithProbe = async (budgetMs: number): Promise<{
ok: true; socket: any;
@ -135,8 +139,9 @@ describe(__filename, function () {
if (!probe.ok) {
console.warn(
`[anonymizeAuthorSocket] admin socket probe failed (${probe.reason}); ` +
'skipping suite — likely an authenticate-hook plugin (e.g. ep_hash_auth) ' +
'rejecting the test\'s plain-text admin credentials. Tracked in #7795.');
'skipping suite — an authenticate-hook plugin (e.g. ep_readonly_guest, ' +
'or an ep_hash_auth-style plugin requiring hashed credentials) is ' +
'rejecting the test\'s plain-text admin credentials.');
this.skip();
return;
}