Skip to content

feat: add support for oauth whitelist file (#817)#826

Merged
steveiliop56 merged 5 commits intotinyauthapp:mainfrom
djedditt:feat/oauth-whitelist-file
May 7, 2026
Merged

feat: add support for oauth whitelist file (#817)#826
steveiliop56 merged 5 commits intotinyauthapp:mainfrom
djedditt:feat/oauth-whitelist-file

Conversation

@djedditt
Copy link
Copy Markdown
Contributor

@djedditt djedditt commented Apr 29, 2026

Fixes #817.

Added TINYAUTH_OAUTH_WHITELISTFILE support for loading whitelist entries from a file, merged with the existing inline whitelist config. This follows the same pattern as auth users/usersfile. Extracted shared inline/file parsing into reusable string utils.

Summary by CodeRabbit

  • New Features

    • OAuth whitelist configuration now supports loading from a file path via the new TINYAUTH_OAUTH_WHITELISTFILE environment variable, providing an alternative to comma-separated values.
  • Tests

    • Added test coverage for new utility functions handling string parsing and list consolidation.

@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Apr 29, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 29, 2026

📝 Walkthrough

Walkthrough

This PR adds file-based OAuth whitelist support via a new TINYAUTH_OAUTH_WHITELISTFILE environment variable, mirroring the existing pattern for user lists. It introduces shared string-parsing utilities, updates the configuration model, and refactors OAuth and user initialization to consolidate loading logic.

Changes

OAuth Whitelist File Support

Layer / File(s) Summary
Configuration Model
internal/model/config.go
OAuthConfig gains a new WhitelistFile field to store a file path for the OAuth whitelist.
String Utility Functions
internal/utils/string_utils.go
New ParseNonEmptyLines() normalizes multi-line text into trimmed, non-empty strings. New GetStringList() consolidates inline config values with optional file-loaded lines, returning a merged []string or an error.
Bootstrap: Config Loading
internal/bootstrap/app_bootstrap.go
BootstrapApp.Setup() loads the OAuth whitelist using GetStringList() with both OAuth.Whitelist and OAuth.WhitelistFile, stores the result in app.context.oauthWhitelist.
Bootstrap: Service Initialization
internal/bootstrap/service_bootstrap.go
AuthService is now wired with OauthWhitelist from the precomputed app.context.oauthWhitelist instead of directly from config.
Refactoring
internal/utils/user_utils.go
GetUsers() is simplified to delegate list building to GetStringList(), reducing duplication. ParseUsers() now returns nil for empty input instead of an empty slice pointer.
Tests & Documentation
internal/utils/string_utils_test.go, .env.example
New test coverage for ParseNonEmptyLines() and GetStringList() including empty inputs, file loading, merging, and error cases. .env.example documents the new TINYAUTH_OAUTH_WHITELISTFILE variable.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

A rabbit hops through files with glee,
Whitelist now lives in a file, you see!
No comma strings tangled and long,
Just one line per domain, clean and strong. 🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main feature: adding OAuth whitelist file support, which matches the primary changeset objective.
Linked Issues check ✅ Passed All core requirements from #817 are implemented: file-based OAuth whitelist loading via TINYAUTH_OAUTH_WHITELISTFILE, merged with existing inline configuration, and following the USERS/USERSFILE pattern.
Out of Scope Changes check ✅ Passed All changes are focused on implementing OAuth whitelist file support. No unrelated modifications to other features or functionality are present.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

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.

🧹 Nitpick comments (1)
internal/utils/string_utils_test.go (1)

4-4: Harden temp-file test setup to avoid collisions and OS-specific assertions.

Line 69 and Line 87 use fixed /tmp/... paths, and Line 88 asserts an OS-specific error string. Prefer t.TempDir() + errors.Is(err, os.ErrNotExist) for stable tests.

Proposed test hardening diff
 import (
+	"errors"
 	"os"
+	"path/filepath"
 	"testing"
@@
 func TestGetStringList(t *testing.T) {
-	file, err := os.Create("/tmp/tinyauth_list_test_file")
-	assert.NilError(t, err)
-
-	_, err = file.WriteString(" third@example.com \n\n fourth@example.com \n")
-	assert.NilError(t, err)
-
-	err = file.Close()
-	assert.NilError(t, err)
-	defer os.Remove("/tmp/tinyauth_list_test_file")
+	tmpDir := t.TempDir()
+	filePath := filepath.Join(tmpDir, "tinyauth_list_test_file")
+	err := os.WriteFile(filePath, []byte(" third@example.com \n\n fourth@example.com \n"), 0o600)
+	assert.NilError(t, err)
 
-	values, err := utils.GetStringList([]string{" first@example.com ", "", "second@example.com"}, "/tmp/tinyauth_list_test_file")
+	values, err := utils.GetStringList([]string{" first@example.com ", "", "second@example.com"}, filePath)
 	assert.NilError(t, err)
 	assert.DeepEqual(t, []string{"first@example.com", "second@example.com", "third@example.com", "fourth@example.com"}, values)
@@
-	values, err = utils.GetStringList(nil, "/tmp/non_existing_list_file")
-	assert.ErrorContains(t, err, "no such file or directory")
+	values, err = utils.GetStringList(nil, filepath.Join(tmpDir, "non_existing_list_file"))
+	assert.Assert(t, errors.Is(err, os.ErrNotExist))
 	assert.DeepEqual(t, []string{}, values)
 }

Also applies to: 69-90

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/utils/string_utils_test.go` at line 4, Tests in
internal/utils/string_utils_test.go use hard-coded /tmp/... paths and assert
OS-specific error text; update the failing test setup to use t.TempDir() to
create unique temp directories and files, construct expected paths relative to
that temp dir instead of using fixed /tmp paths, and replace string equality on
the error with errors.Is(err, os.ErrNotExist) (importing "errors" and "os" as
needed). Locate the test function(s) that reference the fixed paths and the
error assertion (search for the hard-coded "/tmp/" literals and the assertion
comparing err.Error()) and modify them to use t.TempDir(), build paths with
filepath.Join, and use errors.Is for the non-existence check.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@internal/utils/string_utils_test.go`:
- Line 4: Tests in internal/utils/string_utils_test.go use hard-coded /tmp/...
paths and assert OS-specific error text; update the failing test setup to use
t.TempDir() to create unique temp directories and files, construct expected
paths relative to that temp dir instead of using fixed /tmp paths, and replace
string equality on the error with errors.Is(err, os.ErrNotExist) (importing
"errors" and "os" as needed). Locate the test function(s) that reference the
fixed paths and the error assertion (search for the hard-coded "/tmp/" literals
and the assertion comparing err.Error()) and modify them to use t.TempDir(),
build paths with filepath.Join, and use errors.Is for the non-existence check.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b5b80f72-6e46-43a7-abcc-42c066793a67

📥 Commits

Reviewing files that changed from the base of the PR and between d51e3ef and 6b5a6bd.

📒 Files selected for processing (7)
  • .env.example
  • internal/bootstrap/app_bootstrap.go
  • internal/bootstrap/service_bootstrap.go
  • internal/config/config.go
  • internal/utils/string_utils.go
  • internal/utils/string_utils_test.go
  • internal/utils/user_utils.go

@dosubot dosubot Bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:M This PR changes 30-99 lines, ignoring generated files. labels May 7, 2026
@steveiliop56
Copy link
Copy Markdown
Member

steveiliop56 commented May 7, 2026

What the heck is GitHub doing.

Fixed it.

@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. and removed size:XL This PR changes 500-999 lines, ignoring generated files. labels May 7, 2026
steveiliop56
steveiliop56 previously approved these changes May 7, 2026
@dosubot dosubot Bot added the lgtm This PR has been approved by a maintainer label May 7, 2026
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.

🧹 Nitpick comments (1)
internal/model/config.go (1)

249-252: ⚡ Quick win

AppOAuth has no WhitelistFile counterpart — consider whether per-app file-based whitelists are in scope.

Issue #817 explicitly calls out TINYAUTH_APPS_name_OAUTH_WHITELISTFILE as desired behavior. If per-app file support is intended for this PR, AppOAuth needs the same treatment:

💡 Suggested addition to AppOAuth
 type AppOAuth struct {
 	Whitelist string `description:"Comma-separated list of allowed OAuth groups." yaml:"whitelist"`
+	WhitelistFile string `description:"Path to file containing allowed OAuth groups/emails." yaml:"whitelistFile"`
 	Groups    string `description:"Comma-separated list of required OAuth groups." yaml:"groups"`
 }

If per-app file support is intentionally deferred, a follow-up issue or TODO comment would make that explicit.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/model/config.go` around lines 249 - 252, AppOAuth currently defines
Whitelist and Groups but lacks a WhitelistFile field requested by Issue `#817`;
add a WhitelistFile string field to the AppOAuth struct (with description and
yaml tag consistent with Whitelist) to support per-app file-based whitelists, or
if you intentionally defer this, add a clear TODO comment on the AppOAuth
definition noting that TINYAUTH_APPS_name_OAUTH_WHITELISTFILE support is pending
and reference Issue `#817` so the missing per-app file support is explicit.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@internal/model/config.go`:
- Around line 249-252: AppOAuth currently defines Whitelist and Groups but lacks
a WhitelistFile field requested by Issue `#817`; add a WhitelistFile string field
to the AppOAuth struct (with description and yaml tag consistent with Whitelist)
to support per-app file-based whitelists, or if you intentionally defer this,
add a clear TODO comment on the AppOAuth definition noting that
TINYAUTH_APPS_name_OAUTH_WHITELISTFILE support is pending and reference Issue
`#817` so the missing per-app file support is explicit.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2c0e1c84-1805-4fd8-9b50-038ea294b901

📥 Commits

Reviewing files that changed from the base of the PR and between 6b5a6bd and ffdf324.

📒 Files selected for processing (5)
  • internal/bootstrap/app_bootstrap.go
  • internal/bootstrap/service_bootstrap.go
  • internal/model/config.go
  • internal/utils/string_utils_test.go
  • internal/utils/user_utils.go
✅ Files skipped from review due to trivial changes (1)
  • internal/bootstrap/app_bootstrap.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • internal/bootstrap/service_bootstrap.go
  • internal/utils/string_utils_test.go
  • internal/utils/user_utils.go

@codecov
Copy link
Copy Markdown

codecov Bot commented May 7, 2026

Codecov Report

❌ Patch coverage is 83.87097% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/bootstrap/app_bootstrap.go 0.00% 4 Missing ⚠️
internal/bootstrap/service_bootstrap.go 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@steveiliop56 steveiliop56 merged commit 6602b52 into tinyauthapp:main May 7, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm This PR has been approved by a maintainer size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] add OAUTH_WHITELISTFILE support (file-based alternative to OAUTH_WHITELIST env var)

3 participants