Files
intotheeast-com/docs/solutions/test-failures/new-user-grants-api-not-admin-on-admin2.md
T
m038andClaude Opus 4.8 66438836de docs: capture stale-GRAV_VERSION api-plugin-install failure (ce-compound)
Fresh prod install ran Grav rc.10 (stale .env.prod GRAV_VERSION), so GPM
would not serve the api plugin (needs >=2.0.4); admin2 (auth via /api/v1)
then 404'd login silently. Documents the dead ends (deploying api config,
gpm index -f, same-channel assumption) and the fix (self-upgrade core +
reinstall + bump .env.prod). Adds reciprocal 'same 2026-07-04 cutover'
cross-links across the three sibling deploy gotchas.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Np4cMQLF77i664CAQXySzU
2026-07-04 23:59:44 +02:00

5.6 KiB

title, date, category, module, problem_type, component, symptoms, root_cause, resolution_type, severity, related_components, tags
title date category module problem_type component symptoms root_cause resolution_type severity related_components tags
Grav login new-user grants api.* but not admin.* on Admin2-only installs 2026-07-04 docs/solutions/test-failures testing / account provisioning test_failure authentication
gpx-manager Playwright specs fail (401 / login form shown) after switching the suite onto a dedicated test account
an authenticated account still sees the login form at /gpx-manager instead of the manager UI
the generated accounts/*.yaml has an access.api block but no access.admin block
missing_permission tooling_addition medium
testing_framework
tooling
grav
login-plugin
admin2
permissions
playwright
test-account
gpx-manager

Grav login new-user grants api.* but not admin.* on Admin2-only installs

Problem

When the Playwright suite was moved onto a dedicated local testrunner account, every /gpx-manager spec started failing — the account could authenticate but was treated as unauthorized for the manager page. The account had been created with bin/plugin login new-user ... -P b (Admin + Site access) but without --admin-type, and on this Admin2-only install that grants api.* permissions and no admin.* permissions.

Symptoms

  • The /gpx-manager Playwright specs fail after switching from the real user to the testrunner account (they passed as the real user).
  • An authenticated testrunner still gets the Login plugin's login form at /gpx-manager instead of the manager UI.
  • The generated user/accounts/testrunner.yaml contains an access.api block (login: true, super: true) but no access.admin block.

What Didn't Work

  • Assuming -P b was enough. -P/--permissions b selects the category of access (Admin + Site), but the type of admin permission — classic admin.* vs Admin2 api.* — is a separate axis controlled by --admin-type, which defaults to auto-detect. -P b alone does not guarantee admin.login.
  • Blaming the wrong specs. In the same push, the home H1/map specs were also red, which looked like it might be the same auth problem. It was not — those were gated by site.yaml travelling: false hiding the active-trip view, a completely separate cause. Conflating the two delayed pinning the permission root cause.

Solution

Create the account with an explicit --admin-type both, and bake it into the idempotent make test-account target so every recreation is faithful:

test-account:
	@docker exec intotheeast_grav sh -c 'test -f /var/www/html/user/accounts/$(GRAV_TEST_USER).yaml \
		|| php bin/plugin login new-user -u $(GRAV_TEST_USER) -p "$(GRAV_TEST_PASS)" \
		   -e $(GRAV_TEST_USER)@example.test -N "Test Runner" -P b --admin-type both -s enabled -n'

Verify the resulting permissions actually include admin.login:

docker exec intotheeast_grav rm -f /var/www/html/user/accounts/testrunner.yaml
make test-account
docker exec intotheeast_grav sh -c 'grep -A6 "^access:" /var/www/html/user/accounts/testrunner.yaml'
# access:
#   admin:
#     login: true
#     super: true
#   api:
#     login: true
#     super: true

Why This Works

The login new-user help text spells out the axis:

--admin-type — Which admin permission type to grant when permissions include Admin: admin (classic Admin plugin, admin.*), api (Admin2, api.*), or both. If omitted, auto-detects from which admin plugin is installed.

This site runs Admin2 only (the classic admin plugin is disabled), so auto-detect resolves to api and emits api.* alone. /gpx-manager is gated by access.admin.login: true in its page frontmatter (enforced by the Login plugin), and that check looks specifically for the admin.login permission — api.login does not satisfy it. Passing --admin-type both forces both namespaces into the account, so the admin-gated page accepts the session.

Prevention

  • On Admin2-only Grav installs, always pass --admin-type both (or admin) to login new-user when the account must reach any page gated by access.admin.login (e.g. /gpx-manager). Auto-detect will otherwise silently give you api-only.
  • Assert the permission, not the exit code. After provisioning an account for admin-gated pages, check that access.admin.login exists in the generated YAML rather than trusting that account creation "succeeded."
  • Keep provisioning in one idempotent place. The make test-account target is the single source of truth; tests/global-setup.js calls it, so make test and a bare npx playwright test both get identical permissions. Don't hand-create the account out-of-band with different flags — that reintroduces the drift this fix removed.
  • docs/working/plans/2026-07-04-grav-2.0.4-upgrade.md — the self-contained test-account infrastructure shipped alongside the Grav 2.0.4 upgrade.
  • Sibling gotchas from the same 2026-07-04 Grav 2.0.4 production cutover (all surface around admin2/api but with distinct root causes): docs/solutions/integration-issues/stale-grav-version-blocks-api-plugin-install.md (stale GRAV_VERSION → rc core → GPM won't serve the api plugin → login 404s) and docs/solutions/integration-issues/grav-double-content-encoding-garbage-page.md (double Content-Encoding header → garbage page).
  • docs/solutions/architecture-patterns/dual-repo-submodule-workflow.md — accounts live in the user/ repo; the testrunner account is gitignored so it never reaches production.
  • GPX manager auth model (access.admin.login: true frontmatter + Login plugin) — see the project's GPX manager notes.