feat(web): login page, auth context and admin pages - #201
Open
TartanLeGrand wants to merge 28 commits into
Open
TartanLeGrand wants to merge 28 commits into
TartanLeGrand wants to merge 28 commits into
Conversation
TartanLeGrand
force-pushed
the
feat/auth-web
branch
from
September 28, 2026 07:21
2801e29 to
2a33cad
Compare
TartanLeGrand
marked this pull request as ready for review
September 28, 2026 07:40
This was referenced Sep 28, 2026
Login only called reload() on the normal sign-in path. When the backend required an immediate password change, the app navigated to /account/password while the AuthContext still held the stale anonymous principal, so the RequirePermission guard bounced the user straight back to /login.
…assword change The top-level guard that sends an already-signed-in visitor away from /login used the plain redirect target, racing the explicit navigation to /account/password once the auth context refreshes mid-submit. The guard now redirects to /account/password itself when the principal still needs a password change, so the outcome is correct regardless of which navigation wins the race.
…s in flight Route changes are React transitions, so after sign-out a protected page re-rendered with the anonymous principal before the navigation committed and its guard pushed /login?redirect=<page>. The provider now shows the loading screen from the sign-out until the location reaches /login. Reproduced in a browser on the built image and pinned by a test that signs out from a guarded route.
main moved to react-router 7 (BananaOps#202), where the v7_* future flags are the default behaviour and no longer part of the MemoryRouter props.
Aligns with BananaOps#205 while keeping the actions pinned to commit SHAs.
main moved to Tailwind 4 (BananaOps#206): rounded becomes rounded-sm and outline-none becomes outline-hidden in the user menu and the API key dialog.
The login page now carries the Single Sign-On button announced by the OpenID Connect documentation, and CLAUDE.md said no frontend test runner existed.
TartanLeGrand
force-pushed
the
feat/auth-web
branch
from
October 2, 2026 14:07
2a33cad to
d49ca74
Compare
This was referenced Oct 2, 2026
The team dialog always sent scopeAll=true, so saving a team restricted through the API silently widened it to every service. The dialog now sends back the scope it loaded and shows it read-only; a new team still gets all services. Refs BananaOps#196
TartanLeGrand
added a commit
to TartanLeGrand/tracker
that referenced
this pull request
Oct 4, 2026
The web team dialog (BananaOps#201) now sends back the scope it loaded, so editing a restricted team from the UI no longer widens it. Refs BananaOps#196
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Second PR of the SSO / RBAC series (refs #196), on top of the backend merged in #200 and the react-router 7 upgrade from #202.
What
AuthProviderloadsGET /auth/configandGET /auth/meonce, exposesprincipal,hasPermission,inScope,logout,reload.withCredentials);VITE_API_TOKENis removed.401redirects to/login?redirect=<page>,403shows an "Access denied" toast./login(local form, SSO button whenoidcEnabled, generic error, rate-limit and cross-site messages, forced redirect to/account/passwordwhenmustChangePassword)./account/passwordfor local accounts.*:readpermission, create/edit/delete/lock buttons hidden without*:write, new Administration section, account menu (source, teams, change password, sign out), demo banner hint for anonymous visitors./admin/users,/admin/teams,/admin/api-keys(secret shown once with copy, revoke with confirmation), all behindaccess:manage.RequirePermissionfor pages,Canfor actions. Static (GitHub Pages) build keeps working with a read-mostly anonymous principal.Webworkflow (scoped ESLint, scoped tsc filter, vitest, build).Not in this PR
/api/v1alpha1/auth/oidc/login, hidden until the backend reportsoidcEnabled.linksApi.tsstill usesfetchand is not wired to the 401/403 interceptor; anonymous keepslinks:*until PR 5.Checks
npm test(75 tests, 14 files),npm run lint:auth,npm run build,npm run build:staticall green.mainafter feat(auth): local accounts, teams, permissions and API keys #200, fix(deps): upgrade react-router-dom to v7 and patch vulnerable transitive packages #202 and ci: update all GitHub Actions to their latest major versions #205: react-router 7 (future flags dropped from the test routers),web.ymlactions bumped to v7 and still pinned to commit SHAs;tscerror count identical tomain, none in the files this PR owns.rounded-sm,outline-hidden), the lockfile is regenerated on top of the Tailwind 4 / ESLint 10 one, and the OpenID Connect documentation now describes the Single Sign-On button of the login page.CLAUDE.mdmentions the newnpm test./admin/usersredirects to/login?redirect=...; wrong password shows an inline error and six quick failures trigger the rate limit message; correct admin login redirects through the forced password change and lands back on the original target; user, team (including builtin lock and delete confirmation) and API key administration all behave as specified; a team API key gets 200 then 403 then 401 after revocation, a global key gets 200 on an admin-only endpoint; the account menu and sign-out work; a non-admin user with partial permissions sees the matching subset of the navigation and gets "Access denied" on both/catalogand/admin/users.Known follow-ups (not blocking, tracked for PR 3+)
reload()has no request-generation guard, a late/auth/meresponse can produce one stale render.endsWith, harmless with the current route set.Refs #196