Resolve access list group membership at login (#125) #138
No reviewers
Labels
No labels
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
qwc-open/asiakirjat!138
Loading…
Reference in a new issue
No description provided.
Delete branch "feature/access-list-login-sync"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Third of the #125 series, on top of #136 and #137. Fills in the half of a list the checker can't resolve by itself.
What it does
A list member naming a user is matched by username when access is checked — that already works. A member naming an LDAP or OAuth2 group can't be: group membership is only known while the user is signing in. This PR makes both authenticators record the result as
access_list_grantsrows, the same way they already resolveglobal_accessgroup rules.One implementation, not two
syncAccessListGrantslives ininternal/auth/access_lists.goand both authenticators call it. LDAP and OAuth2 differ only in the subject type they match (ldap_group/oauth2_group) and the source they record, so a copy each would be two statements of the same authorization rule — which is exactly howcanViewProjectdrifted into three versions before theaccesspackage was extracted.Reconcile, don't rewrite
The obvious implementation is "delete this source's grants, then re-grant what matches". I avoided it: that leaves a window mid-login where a user who never lost access has no grant, and a concurrent request would see a 403. Instead the sync reads what the source already holds and applies the difference — a user still in the group keeps an unbroken grant, and only genuinely removed memberships are deleted.
Grants from the other source are never touched, and members naming a user directly aren't grants at all, so no sync can disturb them.
Tests
internal/auth/access_lists_test.go:Authenticatewith the mock LDAP dialer: signing in grants editor on the list, and signing in again after leaving the group revokes it.Full suite green. (
gofmtflagsoauth2_test.goandtoken_test.go— both pre-existing onmain, in blocks this PR doesn't touch.)Note on
SetStoresBoth authenticators'
SetStoresgained anaccessListsparameter. Existing test call sites passnil, and a nil store means "no access lists" everywhere, so LDAP/OAuth2 deployments that never create a list behave exactly as before.Last step
Step 4 — the admin UI: managing lists and their members,
listas a choice in the project visibility picker (wired toprojects.ValidateVisibilityrather than another copy of the literal check), and the built-in docs. After thatvisibility = 'list'becomes reachable and #125 is done.Assisted by Claude Opus 5.