Skip to content

feat: ldap group acls#590

Merged
steveiliop56 merged 11 commits intomainfrom
feat/ldap-groups
Jan 17, 2026
Merged

feat: ldap group acls#590
steveiliop56 merged 11 commits intomainfrom
feat/ldap-groups

Conversation

@steveiliop56
Copy link
Copy Markdown
Member

@steveiliop56 steveiliop56 commented Jan 16, 2026

Summary by CodeRabbit

  • New Features

    • LDAP authentication with group membership lookup and caching
    • Basic-auth identification exposed in user context
    • Added SQL code generation target
    • Added remote debugger configuration
  • Changes

    • Renamed provider string to "local" and introduced "ldap"
    • Login UI provider filtering updated to exclude local/ldap
    • OAuth subject removed from user responses
    • Session and authorization flows updated to support multiple auth methods and LDAP integration

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 16, 2026

📝 Walkthrough

Walkthrough

Adds LDAP support and group-based authorization, migrates session handling to repository-backed sessions (including ldap_groups), introduces LDAP group caching with TTL, renames provider identifiers ("username" → "local"/"ldap"), updates middleware/controllers/services/tests, and adds sqlc mapping, Makefile sql target, and a Delve debug config.

Changes

Cohort / File(s) Summary
Debug & Build
/.zed/debug.json, Makefile, sqlc.yml
Add Delve remote debug configuration; add .PHONY: sql and sql target running sqlc generate; add sqlc override mapping sessions.ldap_groupsstring.
Config types & defaults
internal/config/config.go, cmd/tinyauth/tinyauth.go
Add LdapUser, AppLDAP; add UserContext fields IsBasicAuth and LdapGroups; add LdapConfig.GroupCacheTTL with default 900; remove SessionCookie type.
LDAP service
internal/service/ldap_service.go
Rename Search()GetUserDN() and add GetUserGroups(userDN string) to fetch and parse LDAP group names.
Auth service & caching
internal/service/auth_service.go, internal/bootstrap/service_bootstrap.go
Add LDAP groups cache and TTL config; implement GetLdapUser(), IsInLdapGroup(), LocalAuthConfigured(), LdapAuthConfigured(); migrate session APIs to use repository.Session; wire TTL from bootstrap.
Middleware
internal/middleware/context_middleware.go
Validate session provider vs user-search type; support LDAP/basic-auth flows; fetch LDAP groups and populate UserContext.LdapGroups and IsBasicAuth; refresh or delete sessions accordingly.
Controllers (session & auth flows)
internal/controller/user_controller.go, internal/controller/oauth_controller.go, internal/controller/context_controller.go
Switch session usage to repository.Session; default provider "local" (override to "ldap" when LDAP user); remove OAuthSub from user context responses; adjust pseudo-username email replacement to single @.
Proxy & Authorization
internal/controller/proxy_controller.go
Use IsBasicAuth for basic-auth checks; add LDAP group evaluation path and provider-aware Remote-Groups header; add GroupErr param on unauthorized responses and generalize group-mismatch logging.
Frontend
frontend/src/pages/login-page.tsx
Exclude "local" and "ldap" from OAuth provider list and treat them as configured local methods.
Tests
internal/controller/*.go tests
Update tests to use repository.Session, set IsBasicAuth where applicable, and change provider values from "username""local" to match runtime changes.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Middleware as Context\r\nMiddleware
    participant Repo as Repository\r\n(Session)
    participant LdapSvc as LDAP\r\nService
    participant AuthSvc as Auth\r\nService
    participant Proxy as Proxy\r\nController

    Client->>Middleware: Request (cookie or basic auth)
    Middleware->>Repo: GetSessionCookie(sessionID)
    Repo-->>Middleware: repository.Session {Provider: "ldap"/"local"/"oauth", UserDN, OAuthGroups}

    alt Provider == "ldap"
        Middleware->>LdapSvc: GetUserGroups(UserDN)
        LdapSvc-->>Middleware: []groups
        Middleware->>Middleware: Set UserContext.LdapGroups, IsBasicAuth as needed
    else Provider == "oauth"
        Middleware->>Middleware: Use OAuthGroups -> UserContext.OAuthGroups
    else Provider == "local"
        Middleware->>Middleware: Mark IsBasicAuth, no group enrichment
    end

    Middleware->>AuthSvc: IsInLdapGroup(UserContext, requiredGroups)
    AuthSvc-->>Middleware: boolean
    Middleware->>Proxy: Forward request + UserContext
    alt authorized
        Proxy-->>Client: 200 OK (forwarded)
    else unauthorized (group mismatch)
        Proxy-->>Client: 401 + GroupErr query param
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

merge

Poem

🐰 I hopped through configs, sessions, and groups,

local and ldap in tidy new loops,
Cookies now live where repositories play,
Makefile and debug keep devs on their way,
A cheerful hop — hooray, code in bloom!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'feat: ldap group acls' directly and concisely describes the main feature added: LDAP group-based access control lists.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Jan 16, 2026

Codecov Report

❌ Patch coverage is 4.69799% with 142 lines in your changes missing coverage. Please review.
✅ Project coverage is 19.37%. Comparing base (c0dd432) to head (acb37e2).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
internal/service/auth_service.go 0.00% 52 Missing ⚠️
internal/middleware/context_middleware.go 0.00% 32 Missing ⚠️
internal/service/ldap_service.go 0.00% 27 Missing ⚠️
internal/controller/proxy_controller.go 8.33% 8 Missing and 3 partials ⚠️
internal/bootstrap/app_bootstrap.go 0.00% 9 Missing ⚠️
cmd/tinyauth/tinyauth.go 0.00% 6 Missing ⚠️
internal/controller/oauth_controller.go 0.00% 2 Missing ⚠️
internal/controller/user_controller.go 75.00% 1 Missing and 1 partial ⚠️
internal/bootstrap/service_bootstrap.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #590      +/-   ##
==========================================
- Coverage   20.25%   19.37%   -0.89%     
==========================================
  Files          41       41              
  Lines        2389     2488      +99     
==========================================
- Hits          484      482       -2     
- Misses       1874     1972      +98     
- Partials       31       34       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
internal/controller/context_controller_test.go (1)

38-50: Inconsistent provider value in test data.

The userContext.Provider is still set to "username" (line 45), but the provider configuration now uses "local" as the ID (line 20). This inconsistency may cause test failures or mask bugs where provider matching is expected.

Suggested fix
 var userContext = config.UserContext{
 	Username:    "testuser",
 	Name:        "testuser",
 	Email:       "test@example.com",
 	IsLoggedIn:  true,
 	IsBasicAuth: false,
 	OAuth:       false,
-	Provider:    "username",
+	Provider:    "local",
 	TotpPending: false,
 	OAuthGroups: "",
 	TotpEnabled: false,
 	OAuthSub:    "",
 }
internal/controller/proxy_controller_test.go (2)

146-153: Session type migration looks correct, but provider value is inconsistent.

The migration to repository.Session is correct. However, the Provider value is still "username" (line 150), which is inconsistent with the new "local" naming convention used elsewhere in this PR.

Suggested fix
 	err := authService.CreateSessionCookie(c, &repository.Session{
 		Username:    "testuser",
 		Name:        "testuser",
 		Email:       "testuser@example.com",
-		Provider:    "username",
+		Provider:    "local",
 		TotpPending: false,
 		OAuthGroups: "",
 	})

159-174: Provider value inconsistency in test context.

The Provider value on line 167 is still "username", which should be updated to "local" for consistency with the provider renaming in this PR.

Suggested fix
 		func(c *gin.Context) {
 			c.Set("context", &config.UserContext{
 				Username:    "testuser",
 				Name:        "testuser",
 				Email:       "testuser@example.com",
 				IsLoggedIn:  true,
 				OAuth:       false,
-				Provider:    "username",
+				Provider:    "local",
 				TotpPending: false,
 				OAuthGroups: "",
 				TotpEnabled: false,
 			})
 			c.Next()
 		},
🤖 Fix all issues with AI agents
In @.zed/debug.json:
- Around line 8-13: The JSON contains trailing commas that make it invalid;
remove the commas after the "port": 4000 entry and any extraneous trailing
commas after the closing braces/array so the "tcp_connection" object (and the
surrounding objects/array) are properly closed with no trailing commas, ensuring
the file is valid JSON.

In `@internal/middleware/context_middleware.go`:
- Around line 60-92: Ensure the session cookie's Provider cannot be silently
overridden by m.auth.SearchUser results: require userSearch.Type to match
cookie.Provider (or invalidate the session) before proceeding; if they mismatch
call m.auth.DeleteSessionCookie(c) and goto basic. Use cookie.Provider as the
Provider value when constructing the config.UserContext, and only attempt
LDAP-specific work (calling m.auth.GetLdapUser and loading ldapGroups) when
cookie.Provider == "ldap"; keep the existing m.auth.RefreshSessionCookie(c)
behavior when the provider matches.

In `@internal/service/ldap_service.go`:
- Around line 150-157: GetUserGroups currently hardcodes groupOfUniqueNames and
uniquemember, pulls all groups and filters client-side, and parses names by
stripping "cn=" which breaks for other schemas; update LdapService.GetUserGroups
to accept configurable group objectClass and member attribute via
LdapServiceConfig (e.g., add fields GroupObjectClass and GroupMemberAttribute),
build a server-side search filter that matches membership (use the configured
member attribute with the provided userDN or username as appropriate), and
return group identifiers parsed robustly from the group DN or a chosen attribute
instead of naïve "cn=" stripping; ensure callers construct LdapService with the
new config fields and adjust parsing logic in GetUserGroups to handle AD
(member), groupOfUniqueNames (uniqueMember), and posixGroup (memberUid) formats.
🧹 Nitpick comments (2)
frontend/src/pages/login-page.tsx (1)

52-58: Use consistent strict equality operators.

Line 53 uses !== for the first comparison but != for the second. For consistency and to avoid type coercion issues in JavaScript/TypeScript, use strict equality throughout.

Suggested fix
  const oauthProviders = providers.filter(
-    (provider) => provider.id !== "local" && provider.id != "ldap",
+    (provider) => provider.id !== "local" && provider.id !== "ldap",
  );
internal/service/ldap_service.go (1)

177-186: Fragile DN parsing - consider using proper LDAP DN utilities.

The current parsing assumes the group DN starts with lowercase cn=. LDAP attribute names are case-insensitive, so CN=Admins,ou=groups,dc=example,dc=com would not be handled correctly.

Suggested fix using go-ldap DN parsing
-	// Should work for most ldap providers?
-	groups := []string{}
-
-	for _, groupDN := range groupDNs {
-		groupDN = strings.TrimPrefix(groupDN, "cn=")
-		parts := strings.SplitN(groupDN, ",", 2)
-		if len(parts) > 0 {
-			groups = append(groups, parts[0])
-		}
-	}
+	groups := []string{}
+
+	for _, groupDN := range groupDNs {
+		dn, err := ldapgo.ParseDN(groupDN)
+		if err != nil || len(dn.RDNs) == 0 || len(dn.RDNs[0].Attributes) == 0 {
+			continue
+		}
+		// Use the first RDN's value (typically the CN)
+		groups = append(groups, dn.RDNs[0].Attributes[0].Value)
+	}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c0dd432 and 4fc1832.

📒 Files selected for processing (16)
  • .zed/debug.json
  • Makefile
  • frontend/src/pages/login-page.tsx
  • internal/bootstrap/app_bootstrap.go
  • internal/config/config.go
  • internal/controller/context_controller.go
  • internal/controller/context_controller_test.go
  • internal/controller/oauth_controller.go
  • internal/controller/proxy_controller.go
  • internal/controller/proxy_controller_test.go
  • internal/controller/user_controller.go
  • internal/controller/user_controller_test.go
  • internal/middleware/context_middleware.go
  • internal/service/auth_service.go
  • internal/service/ldap_service.go
  • sqlc.yml
💤 Files with no reviewable changes (1)
  • internal/controller/context_controller.go
🧰 Additional context used
🧬 Code graph analysis (9)
internal/bootstrap/app_bootstrap.go (1)
internal/controller/context_controller.go (1)
  • Provider (39-43)
internal/controller/user_controller_test.go (1)
internal/controller/context_controller.go (1)
  • Provider (39-43)
internal/controller/context_controller_test.go (2)
internal/utils/security_utils_test.go (1)
  • TestGetBasicAuth (58-76)
internal/controller/context_controller.go (1)
  • Status (13-25)
internal/controller/proxy_controller.go (3)
internal/controller/context_controller.go (1)
  • Provider (39-43)
internal/config/config.go (1)
  • App (186-194)
internal/utils/label_utils.go (1)
  • SanitizeHeader (26-34)
internal/controller/oauth_controller.go (1)
internal/repository/models.go (1)
  • Session (7-19)
internal/controller/proxy_controller_test.go (1)
internal/repository/models.go (1)
  • Session (7-19)
internal/controller/user_controller.go (3)
internal/repository/models.go (1)
  • Session (7-19)
internal/utils/string_utils.go (1)
  • Capitalize (7-12)
internal/controller/context_controller.go (1)
  • Provider (39-43)
internal/service/auth_service.go (2)
internal/config/config.go (4)
  • UserSearch (146-149)
  • LdapUser (141-144)
  • SessionCookieName (11-11)
  • UserContext (151-165)
internal/repository/models.go (1)
  • Session (7-19)
internal/middleware/context_middleware.go (4)
internal/controller/context_controller.go (1)
  • Provider (39-43)
internal/config/config.go (2)
  • App (186-194)
  • UserContext (151-165)
internal/utils/tlog/log_wrapper.go (1)
  • App (22-22)
internal/utils/string_utils.go (1)
  • Capitalize (7-12)
🪛 Biome (2.1.2)
.zed/debug.json

[error] 11-11: Expected a property but instead found '}'.

Expected a property here.

(parse)


[error] 12-12: Expected a property but instead found '}'.

Expected a property here.

(parse)


[error] 12-13: Expected an array, an object, or a literal but instead found ']'.

Expected an array, an object, or a literal here.

(parse)

🪛 checkmake (0.2.2)
Makefile

[warning] 67-67: Missing required phony target "all"

(minphony)


[warning] 67-67: Missing required phony target "clean"

(minphony)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (go)
🔇 Additional comments (31)
Makefile (1)

66-69: LGTM!

The new sql target for sqlc code generation is correctly implemented and properly marked as .PHONY.

sqlc.yml (1)

22-23: LGTM!

The new override for sessions.ldap_groups is consistent with existing column overrides and aligns with the LdapGroups field added to UserContext.

internal/service/ldap_service.go (1)

121-148: LGTM!

The GetUserDN method properly escapes the username to prevent LDAP injection and correctly handles the search with appropriate mutex synchronization.

internal/config/config.go (3)

141-144: LGTM!

The LdapUser struct is well-defined and appropriately encapsulates LDAP user data needed for authentication and group authorization.


151-165: LGTM!

The additions of IsBasicAuth and LdapGroups to UserContext are consistent with the existing structure and follow the established pattern (e.g., OAuthGroups as a string for comma-separated groups).


210-213: LGTM!

The AppLDAP struct follows the established pattern of other ACL configuration types in this file.

internal/controller/context_controller_test.go (1)

19-20: LGTM!

The provider naming is correctly updated to "Local"/"local" to align with the multi-provider authentication path introduced in this PR.

internal/controller/user_controller_test.go (3)

207-207: LGTM!

Provider value correctly updated to "local" to align with the multi-provider authentication refactor.


270-270: LGTM!

Consistent with the provider renaming across the codebase.


293-293: LGTM!

Provider value correctly updated.

internal/controller/proxy_controller_test.go (1)

188-210: LGTM!

The test case for ensuring basic auth is disabled for TOTP-enabled users is well-structured. The IsBasicAuth: true and Provider: "basic" values correctly simulate the basic auth scenario being tested.

internal/bootstrap/app_bootstrap.go (1)

147-161: LGTM!

The multi-provider configuration logic is well-structured:

  • Local provider is conditionally added when LocalAuthConfigured() returns true.
  • LDAP provider is conditionally added when LdapAuthConfigured() returns true.
  • Both are correctly marked as non-OAuth providers.

This cleanly supports the new LDAP group ACLs feature while maintaining backward compatibility with local authentication.

internal/controller/oauth_controller.go (3)

10-10: LGTM!

Import addition necessary for the repository.Session type.


192-192: LGTM!

Using strings.Replace with count 1 is a reasonable defensive choice, ensuring only the first @ is replaced when deriving a pseudo username from the email address.


195-203: LGTM!

The migration to repository.Session is correct. The struct is properly initialized with the OAuth-specific fields (OAuthGroups, OAuthName, OAuthSub). The UUID, Expiry, and CreatedAt fields are generated fresh by CreateSessionCookie internally (not populated from the input object) and properly mapped into CreateSessionParams for persistence.

internal/controller/proxy_controller.go (3)

176-179: Basic-auth TOTP gate is correctly scoped.
Switching to IsBasicAuth keeps the restriction limited to basic-auth flows while honoring TOTP.


215-238: Provider-aware group checks + GroupErr signaling look good.
The OAuth vs LDAP branching and group-error redirect flag align the authorization flow with the provider.


261-265: Remote-Groups header selection matches provider semantics.
LDAP groups for LDAP and OAuth groups for non-local providers keeps downstream headers consistent.

internal/controller/user_controller.go (4)

8-9: Repository-based session import is consistent.
This aligns controller usage with the new session storage model.


115-121: TOTP-pending session now records provider cleanly.
Using repository.Session with Provider: "local" keeps the TOTP flow consistent.


141-150: Provider default/override logic is clear.
Defaulting to local and overriding to ldap makes the intent explicit.


255-260: Post‑TOTP session creation looks good.
The repository session usage mirrors the login flow and keeps provider consistent.

internal/middleware/context_middleware.go (3)

48-55: TOTP-pending context now correctly tags local provider.
Keeps downstream logic consistent with session provenance.


169-177: Local basic-auth context now carries IsBasicAuth.
This is consistent with the downstream basic-auth gate.


183-199: LDAP basic-auth context enrichment looks good.
Fetching LDAP groups and tagging the provider keeps auth decisions consistent.

internal/service/auth_service.go (6)

72-85: LDAP DN lookup update is clean and consistent.
Returning unknown on LDAP search failure aligns with the caller expectations.


134-145: GetLdapUser helper is a good addition.
Keeps LDAP user detail retrieval in one place.


206-233: Session creation now aligns with repository.Session.
The mapping preserves existing fields and behavior.


316-362: Repository-based session retrieval looks consistent.
Return paths and expiry handling are updated cleanly to the new type.


365-371: Auth configuration helpers are straightforward.
Clear separation between local and LDAP configuration checks.


413-427: LDAP group check mirrors OAuth group logic well.
Early return on empty requirements keeps behavior predictable.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread .zed/debug.json
Comment thread internal/middleware/context_middleware.go
Comment thread internal/service/ldap_service.go
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@internal/service/auth_service.go`:
- Around line 143-172: In GetLdapUser, replace the initial
auth.ldapGroupsMutex.Lock()/Unlock() with a reader lock
(auth.ldapGroupsMutex.RLock()/RUnlock()) when checking ldapGroupsCache to avoid
taking a write lock for reads, and keep the existing write lock when populating
the cache; additionally add a nil check for auth.ldap before calling
auth.ldap.GetUserGroups (return a clear error if auth.ldap is nil) so the call
cannot panic when LDAP is not configured.
♻️ Duplicate comments (2)
internal/service/ldap_service.go (1)

148-187: Make LDAP group search schema configurable.

Line 154 hardcodes groupOfUniqueNames/uniquemember with a DN-based match, which will fail for common schemas like Active Directory (group/member) or POSIX (posixGroup/memberUid). Consider making objectClass/member attribute (and the returned name attribute) configurable or accepting a configurable group search filter template.

🛠️ Suggested direction (requires adding config fields)
-	searchRequest := ldapgo.NewSearchRequest(
-		ldap.config.BaseDN,
-		ldapgo.ScopeWholeSubtree, ldapgo.NeverDerefAliases, 0, 0, false,
-		fmt.Sprintf("(&(objectclass=groupOfUniqueNames)(uniquemember=%s))", escapedUserDN),
-		[]string{"dn"},
-		nil,
-	)
+	filter := fmt.Sprintf(ldap.config.GroupSearchFilter, escapedUserDN)
+	attrs := []string{"dn"}
+	if ldap.config.GroupNameAttribute != "" {
+		attrs = []string{ldap.config.GroupNameAttribute}
+	}
+	searchRequest := ldapgo.NewSearchRequest(
+		ldap.config.BaseDN,
+		ldapgo.ScopeWholeSubtree, ldapgo.NeverDerefAliases, 0, 0, false,
+		filter,
+		attrs,
+		nil,
+	)
internal/middleware/context_middleware.go (1)

60-75: Allow basic-auth fallback after provider mismatch.

On Line 70-75 the code deletes the cookie and returns, which skips the basic path. This blocks basic auth for clients with stale cookies. Consider falling through to basic like other invalid-cookie paths.

🛠️ Suggested fix
 	if userSearch.Type != cookie.Provider {
 		tlog.App.Warn().Msg("User type from session cookie does not match user search type")
 		m.auth.DeleteSessionCookie(c)
-		c.Next()
-		return
+		goto basic
 	}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4fc1832 and 95ed36d.

📒 Files selected for processing (6)
  • cmd/tinyauth/tinyauth.go
  • internal/bootstrap/service_bootstrap.go
  • internal/config/config.go
  • internal/middleware/context_middleware.go
  • internal/service/auth_service.go
  • internal/service/ldap_service.go
🧰 Additional context used
🧬 Code graph analysis (2)
internal/middleware/context_middleware.go (1)
internal/config/config.go (1)
  • UserContext (152-166)
internal/service/auth_service.go (5)
internal/service/ldap_service.go (1)
  • LdapService (26-31)
internal/repository/db.go (1)
  • Queries (23-25)
internal/config/config.go (2)
  • UserSearch (147-150)
  • LdapUser (142-145)
internal/repository/models.go (1)
  • Session (7-19)
internal/utils/security_utils.go (1)
  • CheckFilter (77-102)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (go)
🔇 Additional comments (20)
internal/bootstrap/service_bootstrap.go (1)

59-71: LGTM: LDAP group cache TTL is wired into AuthServiceConfig.

Nice, this keeps the TTL plumbed through initialization as expected.

cmd/tinyauth/tinyauth.go (2)

24-27: LGTM: clarified auth defaults.

No functional impact; defaults remain sensible.


35-38: LGTM: default LDAP group cache TTL set to 15 minutes.

Clear default and aligns with the new caching behavior.

internal/service/ldap_service.go (1)

119-146: LGTM: GetUserDN rename + injected filter remains safe.

Clearer API name and still uses escaped input.

internal/config/config.go (5)

69-79: LGTM: GroupCacheTTL added to LDAP config.

Clear, additive config change.


142-145: LGTM: LdapUser encapsulates DN + groups.

Good clarity for LDAP user payloads.


152-166: LGTM: UserContext now carries IsBasicAuth + LdapGroups.

Consistent with the new auth flows.


187-195: LGTM: App now includes LDAP ACL configuration.

Nice extension for per-app LDAP rules.


211-213: LGTM: AppLDAP groups configuration added.

Straightforward, additive change.

internal/middleware/context_middleware.go (3)

47-55: LGTM: TOTP-pending sessions set to local provider.

Keeps provider semantics stable during TOTP flow.


174-184: LGTM: local basic-auth context now sets Provider + IsBasicAuth.

Looks correct and consistent with the new context schema.


188-206: LGTM: LDAP basic-auth context includes groups + IsBasicAuth.

Good propagation of LDAP group data.

internal/service/auth_service.go (8)

22-25: LGTM!

The cache structure is well-designed with a clear expiration mechanism.


44-56: LGTM!

The cache configuration and concurrent access protection with ldapGroupsMutex are properly structured.


58-67: LGTM!

Constructor properly initializes all new fields including the LDAP groups cache map.


81-95: LGTM!

The change from Search to GetUserDN and returning "unknown" on error (instead of "error") is a reasonable approach—it treats LDAP lookup failures as "user not found" while still logging the actual error for debugging.


233-271: LGTM!

The migration from config.SessionCookie to repository.Session is properly implemented with all required fields correctly mapped.


343-390: LGTM!

The return type migration to repository.Session is properly implemented with appropriate error handling and idiomatic Go zero-value returns on error paths.


392-398: LGTM!

Clean and straightforward configuration checks.


440-454: LGTM!

The implementation correctly mirrors IsInOAuthGroup and properly uses utils.CheckFilter for flexible group matching (supporting comma-separated lists and regex patterns).

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread internal/service/auth_service.go
@steveiliop56 steveiliop56 merged commit 4926e53 into main Jan 17, 2026
8 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Jan 25, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Mar 21, 2026
@Rycochet Rycochet deleted the feat/ldap-groups branch April 1, 2026 16:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant