From 53af1b99c0622b75db6b71ccbdb013b7eb8d1ee6 Mon Sep 17 00:00:00 2001 From: Stavros Date: Wed, 17 Jun 2026 17:03:30 +0300 Subject: [PATCH] tests: don't use _test suffix in service and controller tests (#944) --- .../controller/context_controller_test.go | 21 ++- internal/controller/health_controller_test.go | 5 +- internal/controller/oidc_controller_test.go | 15 +- internal/controller/proxy_controller_test.go | 5 +- .../controller/resources_controller_test.go | 5 +- internal/controller/user_controller_test.go | 25 ++- .../controller/well_known_controller_test.go | 9 +- .../middleware/context_middleware_test.go | 5 +- internal/model/context_test.go | 163 +++++++++--------- internal/service/oidc_service_test.go | 35 ++-- internal/service/policy_engine_test.go | 37 ++-- 11 files changed, 157 insertions(+), 168 deletions(-) diff --git a/internal/controller/context_controller_test.go b/internal/controller/context_controller_test.go index 4d729911..708824c1 100644 --- a/internal/controller/context_controller_test.go +++ b/internal/controller/context_controller_test.go @@ -1,4 +1,4 @@ -package controller_test +package controller import ( "encoding/json" @@ -9,7 +9,6 @@ import ( "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tinyauthapp/tinyauth/internal/controller" "github.com/tinyauthapp/tinyauth/internal/model" "github.com/tinyauthapp/tinyauth/internal/test" "github.com/tinyauthapp/tinyauth/internal/utils" @@ -33,22 +32,22 @@ func TestContextController(t *testing.T) { middlewares: []gin.HandlerFunc{}, path: "/api/context/app", expected: func() string { - expectedAppContextResponse := controller.AppContextResponse{ + expectedAppContextResponse := AppContextResponse{ Status: 200, Message: "Success", - Auth: controller.ACRAuth{ + Auth: ACRAuth{ Providers: runtime.ConfiguredProviders, }, - OAuth: controller.ACROAuth{ + OAuth: ACROAuth{ AutoRedirect: cfg.OAuth.AutoRedirect, }, - UI: controller.ACRUI{ + UI: ACRUI{ Title: cfg.UI.Title, ForgotPasswordMessage: cfg.UI.ForgotPasswordMessage, BackgroundImage: cfg.UI.BackgroundImage, WarningsEnabled: cfg.UI.WarningsEnabled, }, - App: controller.ACRApp{ + App: ACRApp{ AppURL: runtime.AppURL, CookieDomain: runtime.CookieDomain, TrustedDomains: runtime.TrustedDomains, @@ -64,7 +63,7 @@ func TestContextController(t *testing.T) { middlewares: []gin.HandlerFunc{}, path: "/api/context/user", expected: func() string { - expectedUserContextResponse := controller.UserContextResponse{ + expectedUserContextResponse := UserContextResponse{ Status: 401, Message: "Unauthorized", } @@ -92,10 +91,10 @@ func TestContextController(t *testing.T) { }, path: "/api/context/user", expected: func() string { - expectedUserContextResponse := controller.UserContextResponse{ + expectedUserContextResponse := UserContextResponse{ Status: 200, Message: "Success", - Auth: controller.UCRAuth{ + Auth: UCRAuth{ Authenticated: true, Username: "johndoe", Name: "John Doe", @@ -121,7 +120,7 @@ func TestContextController(t *testing.T) { group := router.Group("/api") gin.SetMode(gin.TestMode) - controller.NewContextController(controller.ContextControllerInput{ + NewContextController(ContextControllerInput{ Log: log, Config: &cfg, Runtime: &runtime, diff --git a/internal/controller/health_controller_test.go b/internal/controller/health_controller_test.go index 9517a0d8..d670f018 100644 --- a/internal/controller/health_controller_test.go +++ b/internal/controller/health_controller_test.go @@ -1,4 +1,4 @@ -package controller_test +package controller import ( "encoding/json" @@ -9,7 +9,6 @@ import ( "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tinyauthapp/tinyauth/internal/controller" ) func TestHealthController(t *testing.T) { @@ -55,7 +54,7 @@ func TestHealthController(t *testing.T) { group := router.Group("/api") gin.SetMode(gin.TestMode) - controller.NewHealthController(controller.HealthControllerInput{ + NewHealthController(HealthControllerInput{ RouterGroup: group, }) diff --git a/internal/controller/oidc_controller_test.go b/internal/controller/oidc_controller_test.go index d8bbef17..78796c49 100644 --- a/internal/controller/oidc_controller_test.go +++ b/internal/controller/oidc_controller_test.go @@ -1,4 +1,4 @@ -package controller_test +package controller import ( "context" @@ -15,7 +15,6 @@ import ( "github.com/steveiliop56/ding" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tinyauthapp/tinyauth/internal/controller" "github.com/tinyauthapp/tinyauth/internal/model" "github.com/tinyauthapp/tinyauth/internal/repository" "github.com/tinyauthapp/tinyauth/internal/repository/memory" @@ -45,7 +44,7 @@ func TestOIDCController(t *testing.T) { require.NoError(t, err) // Middleware that injects an authenticated local user into the gin context, - // mimicking the context middleware that runs before the OIDC controller. + // mimicking the context middleware that runs before the OIDC authedUser := func(c *gin.Context) { c.Set("context", &model.UserContext{ Authenticated: true, @@ -213,7 +212,7 @@ func TestOIDCController(t *testing.T) { { description: "Authorize complete returns a JSON error when the user context is missing", run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) { - body, err := json.Marshal(controller.AuthorizeCompleteRequest{Ticket: "some-ticket"}) + body, err := json.Marshal(AuthorizeCompleteRequest{Ticket: "some-ticket"}) require.NoError(t, err) req := httptest.NewRequest("POST", "/api/oidc/authorize-complete", strings.NewReader(string(body))) @@ -243,7 +242,7 @@ func TestOIDCController(t *testing.T) { }, }, run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) { - body, err := json.Marshal(controller.AuthorizeCompleteRequest{Ticket: "some-ticket"}) + body, err := json.Marshal(AuthorizeCompleteRequest{Ticket: "some-ticket"}) require.NoError(t, err) req := httptest.NewRequest("POST", "/api/oidc/authorize-complete", strings.NewReader(string(body))) @@ -263,7 +262,7 @@ func TestOIDCController(t *testing.T) { description: "Authorize complete returns a JSON error when the ticket is invalid", middlewares: []gin.HandlerFunc{authedUser}, run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) { - body, err := json.Marshal(controller.AuthorizeCompleteRequest{Ticket: "nonexistent-ticket"}) + body, err := json.Marshal(AuthorizeCompleteRequest{Ticket: "nonexistent-ticket"}) require.NoError(t, err) req := httptest.NewRequest("POST", "/api/oidc/authorize-complete", strings.NewReader(string(body))) @@ -291,7 +290,7 @@ func TestOIDCController(t *testing.T) { State: "state-123", }) - body, err := json.Marshal(controller.AuthorizeCompleteRequest{Ticket: ticket}) + body, err := json.Marshal(AuthorizeCompleteRequest{Ticket: ticket}) require.NoError(t, err) req := httptest.NewRequest("POST", "/api/oidc/authorize-complete", strings.NewReader(string(body))) @@ -837,7 +836,7 @@ func TestOIDCController(t *testing.T) { svc = nil } - controller.NewOIDCController(controller.OIDCControllerInput{ + NewOIDCController(OIDCControllerInput{ Log: log, OIDCService: svc, RuntimeConfig: &runtime, diff --git a/internal/controller/proxy_controller_test.go b/internal/controller/proxy_controller_test.go index 79e3e198..1b2eb5c6 100644 --- a/internal/controller/proxy_controller_test.go +++ b/internal/controller/proxy_controller_test.go @@ -1,4 +1,4 @@ -package controller_test +package controller import ( "context" @@ -10,7 +10,6 @@ import ( "github.com/steveiliop56/ding" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tinyauthapp/tinyauth/internal/controller" "github.com/tinyauthapp/tinyauth/internal/model" "github.com/tinyauthapp/tinyauth/internal/repository/memory" "github.com/tinyauthapp/tinyauth/internal/service" @@ -432,7 +431,7 @@ func TestProxyController(t *testing.T) { recorder := httptest.NewRecorder() - controller.NewProxyController(controller.ProxyControllerInput{ + NewProxyController(ProxyControllerInput{ Log: log, RuntimeConfig: &runtime, RouterGroup: group, diff --git a/internal/controller/resources_controller_test.go b/internal/controller/resources_controller_test.go index ef225ec8..fe8cf48b 100644 --- a/internal/controller/resources_controller_test.go +++ b/internal/controller/resources_controller_test.go @@ -1,4 +1,4 @@ -package controller_test +package controller import ( "net/http/httptest" @@ -9,7 +9,6 @@ import ( "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tinyauthapp/tinyauth/internal/controller" "github.com/tinyauthapp/tinyauth/internal/test" ) @@ -69,7 +68,7 @@ func TestResourcesController(t *testing.T) { group := router.Group("/") gin.SetMode(gin.TestMode) - controller.NewResourcesController(controller.ResourcesControllerInput{ + NewResourcesController(ResourcesControllerInput{ RouterGroup: group, Config: &cfg, }) diff --git a/internal/controller/user_controller_test.go b/internal/controller/user_controller_test.go index 18b8772f..0ee63dfc 100644 --- a/internal/controller/user_controller_test.go +++ b/internal/controller/user_controller_test.go @@ -1,4 +1,4 @@ -package controller_test +package controller import ( "context" @@ -14,7 +14,6 @@ import ( "github.com/steveiliop56/ding" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tinyauthapp/tinyauth/internal/controller" "github.com/tinyauthapp/tinyauth/internal/model" "github.com/tinyauthapp/tinyauth/internal/repository" "github.com/tinyauthapp/tinyauth/internal/repository/memory" @@ -86,7 +85,7 @@ func TestUserController(t *testing.T) { description: "Should be able to login with valid credentials", middlewares: []gin.HandlerFunc{}, run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) { - loginReq := controller.LoginRequest{ + loginReq := LoginRequest{ Username: "testuser", Password: "password", } @@ -114,7 +113,7 @@ func TestUserController(t *testing.T) { description: "Should reject login with invalid credentials", middlewares: []gin.HandlerFunc{}, run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) { - loginReq := controller.LoginRequest{ + loginReq := LoginRequest{ Username: "testuser", Password: "wrongpassword", } @@ -135,7 +134,7 @@ func TestUserController(t *testing.T) { description: "Should rate limit on 3 invalid attempts", middlewares: []gin.HandlerFunc{}, run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) { - loginReq := controller.LoginRequest{ + loginReq := LoginRequest{ Username: "testuser", Password: "wrongpassword", } @@ -170,7 +169,7 @@ func TestUserController(t *testing.T) { description: "Should not allow full login with totp", middlewares: []gin.HandlerFunc{}, run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) { - loginReq := controller.LoginRequest{ + loginReq := LoginRequest{ Username: "totpuser", Password: "password", } @@ -207,7 +206,7 @@ func TestUserController(t *testing.T) { }, run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) { // First login to get a session cookie - loginReq := controller.LoginRequest{ + loginReq := LoginRequest{ Username: "testuser", Password: "password", } @@ -264,7 +263,7 @@ func TestUserController(t *testing.T) { code, err := totp.GenerateCode("JPIEBDKJH6UGWJMX66RR3S55UFP2SGKK", time.Now()) require.NoError(t, err) - totpReq := controller.TotpRequest{ + totpReq := TotpRequest{ Code: code, } @@ -302,7 +301,7 @@ func TestUserController(t *testing.T) { }, run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) { for range 3 { - totpReq := controller.TotpRequest{ + totpReq := TotpRequest{ Code: "000000", // invalid code } @@ -334,7 +333,7 @@ func TestUserController(t *testing.T) { description: "Login uses name and email from user attributes", middlewares: []gin.HandlerFunc{}, run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) { - loginReq := controller.LoginRequest{Username: "attruser", Password: "password"} + loginReq := LoginRequest{Username: "attruser", Password: "password"} body, err := json.Marshal(loginReq) require.NoError(t, err) @@ -352,7 +351,7 @@ func TestUserController(t *testing.T) { description: "Login with TOTP uses name and email from user attributes in pending session", middlewares: []gin.HandlerFunc{}, run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) { - loginReq := controller.LoginRequest{Username: "attrtotpuser", Password: "password"} + loginReq := LoginRequest{Username: "attrtotpuser", Password: "password"} body, err := json.Marshal(loginReq) require.NoError(t, err) @@ -388,7 +387,7 @@ func TestUserController(t *testing.T) { code, err := totp.GenerateCode("JPIEBDKJH6UGWJMX66RR3S55UFP2SGKK", time.Now()) require.NoError(t, err) - totpReq := controller.TotpRequest{Code: code} + totpReq := TotpRequest{Code: code} body, err := json.Marshal(totpReq) require.NoError(t, err) @@ -455,7 +454,7 @@ func TestUserController(t *testing.T) { group := router.Group("/api") gin.SetMode(gin.TestMode) - controller.NewUserController(controller.UserControllerInput{ + NewUserController(UserControllerInput{ Log: log, RuntimeConfig: &runtime, RouterGroup: group, diff --git a/internal/controller/well_known_controller_test.go b/internal/controller/well_known_controller_test.go index aa421603..4098c152 100644 --- a/internal/controller/well_known_controller_test.go +++ b/internal/controller/well_known_controller_test.go @@ -1,4 +1,4 @@ -package controller_test +package controller import ( "context" @@ -11,7 +11,6 @@ import ( "github.com/steveiliop56/ding" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tinyauthapp/tinyauth/internal/controller" "github.com/tinyauthapp/tinyauth/internal/repository/memory" "github.com/tinyauthapp/tinyauth/internal/service" "github.com/tinyauthapp/tinyauth/internal/test" @@ -38,11 +37,11 @@ func TestWellKnownController(t *testing.T) { assert.Equal(t, 200, recorder.Code) - res := controller.OpenIDConnectConfiguration{} + res := OpenIDConnectConfiguration{} err := json.Unmarshal(recorder.Body.Bytes(), &res) assert.NoError(t, err) - expected := controller.OpenIDConnectConfiguration{ + expected := OpenIDConnectConfiguration{ Issuer: runtime.AppURL, AuthorizationEndpoint: fmt.Sprintf("%s/authorize", runtime.AppURL), TokenEndpoint: fmt.Sprintf("%s/api/oidc/token", runtime.AppURL), @@ -109,7 +108,7 @@ func TestWellKnownController(t *testing.T) { recorder := httptest.NewRecorder() - controller.NewWellKnownController(controller.WellKnownControllerInput{ + NewWellKnownController(WellKnownControllerInput{ OIDCService: oidcService, RouterGroup: &router.RouterGroup, }) diff --git a/internal/middleware/context_middleware_test.go b/internal/middleware/context_middleware_test.go index 7468dec0..8a89e419 100644 --- a/internal/middleware/context_middleware_test.go +++ b/internal/middleware/context_middleware_test.go @@ -1,4 +1,4 @@ -package middleware_test +package middleware import ( "context" @@ -12,7 +12,6 @@ import ( "github.com/steveiliop56/ding" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tinyauthapp/tinyauth/internal/middleware" "github.com/tinyauthapp/tinyauth/internal/model" "github.com/tinyauthapp/tinyauth/internal/repository" "github.com/tinyauthapp/tinyauth/internal/repository/memory" @@ -278,7 +277,7 @@ func TestContextMiddleware(t *testing.T) { PolicyEngine: policyEngine, }) - contextMiddleware := middleware.NewContextMiddleware(middleware.ContextMiddlewareInput{ + contextMiddleware := NewContextMiddleware(ContextMiddlewareInput{ Log: log, RuntimeConfig: &runtime, AuthService: authService, diff --git a/internal/model/context_test.go b/internal/model/context_test.go index 79bc97b0..ab9da7cf 100644 --- a/internal/model/context_test.go +++ b/internal/model/context_test.go @@ -1,4 +1,4 @@ -package model_test +package model import ( "net/http/httptest" @@ -7,7 +7,6 @@ import ( "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tinyauthapp/tinyauth/internal/model" "github.com/tinyauthapp/tinyauth/internal/repository" ) @@ -22,44 +21,44 @@ func TestContext(t *testing.T) { tests := []struct { description string - context *model.UserContext - run func(*testing.T, *model.UserContext) any + context *UserContext + run func(*testing.T, *UserContext) any expected any }{ { description: "IsAuthenticated reflects Authenticated field", - context: &model.UserContext{Authenticated: true}, - run: func(t *testing.T, c *model.UserContext) any { return c.IsAuthenticated() }, + context: &UserContext{Authenticated: true}, + run: func(t *testing.T, c *UserContext) any { return c.IsAuthenticated() }, expected: true, }, { description: "IsLocal returns true for ProviderLocal", - context: &model.UserContext{Provider: model.ProviderLocal, Local: &model.LocalContext{}}, - run: func(t *testing.T, c *model.UserContext) any { return c.IsLocal() }, + context: &UserContext{Provider: ProviderLocal, Local: &LocalContext{}}, + run: func(t *testing.T, c *UserContext) any { return c.IsLocal() }, expected: true, }, { description: "IsOAuth returns true for ProviderOAuth", - context: &model.UserContext{Provider: model.ProviderOAuth, OAuth: &model.OAuthContext{}}, - run: func(t *testing.T, c *model.UserContext) any { return c.IsOAuth() }, + context: &UserContext{Provider: ProviderOAuth, OAuth: &OAuthContext{}}, + run: func(t *testing.T, c *UserContext) any { return c.IsOAuth() }, expected: true, }, { description: "IsLDAP returns true for ProviderLDAP", - context: &model.UserContext{Provider: model.ProviderLDAP, LDAP: &model.LDAPContext{}}, - run: func(t *testing.T, c *model.UserContext) any { return c.IsLDAP() }, + context: &UserContext{Provider: ProviderLDAP, LDAP: &LDAPContext{}}, + run: func(t *testing.T, c *UserContext) any { return c.IsLDAP() }, expected: true, }, { description: "IsBasicAuth returns true for ProviderBasicAuth", - context: &model.UserContext{Provider: model.ProviderBasicAuth, Local: &model.LocalContext{}}, - run: func(t *testing.T, c *model.UserContext) any { return c.IsBasicAuth() }, + context: &UserContext{Provider: ProviderBasicAuth, Local: &LocalContext{}}, + run: func(t *testing.T, c *UserContext) any { return c.IsBasicAuth() }, expected: true, }, { description: "NewFromSession local session is authenticated and ProviderLocal", - context: &model.UserContext{}, - run: func(t *testing.T, c *model.UserContext) any { + context: &UserContext{}, + run: func(t *testing.T, c *UserContext) any { got, err := c.NewFromSession(&repository.Session{ Username: "alice", Email: "alice@example.com", Name: "Alice", Provider: "local", @@ -67,12 +66,12 @@ func TestContext(t *testing.T) { require.NoError(t, err) return [2]any{got.Provider, got.Authenticated} }, - expected: [2]any{model.ProviderLocal, true}, + expected: [2]any{ProviderLocal, true}, }, { description: "NewFromSession local session with TotpPending is not authenticated", - context: &model.UserContext{}, - run: func(t *testing.T, c *model.UserContext) any { + context: &UserContext{}, + run: func(t *testing.T, c *UserContext) any { got, err := c.NewFromSession(&repository.Session{ Username: "bob", Provider: "local", TotpPending: true, }) @@ -83,20 +82,20 @@ func TestContext(t *testing.T) { }, { description: "NewFromSession ldap session is ProviderLDAP", - context: &model.UserContext{}, - run: func(t *testing.T, c *model.UserContext) any { + context: &UserContext{}, + run: func(t *testing.T, c *UserContext) any { got, err := c.NewFromSession(&repository.Session{ Username: "carol", Provider: "ldap", }) require.NoError(t, err) return got.Provider }, - expected: model.ProviderLDAP, + expected: ProviderLDAP, }, { description: "NewFromSession unknown provider defaults to OAuth and populates oauth fields", - context: &model.UserContext{}, - run: func(t *testing.T, c *model.UserContext) any { + context: &UserContext{}, + run: func(t *testing.T, c *UserContext) any { got, err := c.NewFromSession(&repository.Session{ Username: "dave", Provider: "github", OAuthGroups: "devs,admins", OAuthSub: "sub-123", OAuthName: "GitHub", @@ -104,126 +103,126 @@ func TestContext(t *testing.T) { require.NoError(t, err) return [5]any{got.Provider, got.OAuth.ID, got.OAuth.Sub, got.OAuth.DisplayName, got.OAuth.Groups} }, - expected: [5]any{model.ProviderOAuth, "github", "sub-123", "GitHub", []string{"devs", "admins"}}, + expected: [5]any{ProviderOAuth, "github", "sub-123", "GitHub", []string{"devs", "admins"}}, }, { description: "Local getters return BaseContext fields", - context: &model.UserContext{ - Provider: model.ProviderLocal, - Local: &model.LocalContext{BaseContext: model.BaseContext{Username: "alice", Email: "alice@example.com", Name: "Alice"}}, + context: &UserContext{ + Provider: ProviderLocal, + Local: &LocalContext{BaseContext: BaseContext{Username: "alice", Email: "alice@example.com", Name: "Alice"}}, }, - run: func(t *testing.T, c *model.UserContext) any { + run: func(t *testing.T, c *UserContext) any { return [3]string{c.GetUsername(), c.GetEmail(), c.GetName()} }, expected: [3]string{"alice", "alice@example.com", "Alice"}, }, { description: "BasicAuth getters fall back to local fields", - context: &model.UserContext{ - Provider: model.ProviderBasicAuth, - Local: &model.LocalContext{BaseContext: model.BaseContext{Username: "bob", Email: "bob@example.com", Name: "Bob"}}, + context: &UserContext{ + Provider: ProviderBasicAuth, + Local: &LocalContext{BaseContext: BaseContext{Username: "bob", Email: "bob@example.com", Name: "Bob"}}, }, - run: func(t *testing.T, c *model.UserContext) any { + run: func(t *testing.T, c *UserContext) any { return [3]string{c.GetUsername(), c.GetEmail(), c.GetName()} }, expected: [3]string{"bob", "bob@example.com", "Bob"}, }, { description: "LDAP getters return LDAP fields", - context: &model.UserContext{ - Provider: model.ProviderLDAP, - LDAP: &model.LDAPContext{BaseContext: model.BaseContext{Username: "carol", Email: "carol@example.com", Name: "Carol"}}, + context: &UserContext{ + Provider: ProviderLDAP, + LDAP: &LDAPContext{BaseContext: BaseContext{Username: "carol", Email: "carol@example.com", Name: "Carol"}}, }, - run: func(t *testing.T, c *model.UserContext) any { + run: func(t *testing.T, c *UserContext) any { return [3]string{c.GetUsername(), c.GetEmail(), c.GetName()} }, expected: [3]string{"carol", "carol@example.com", "Carol"}, }, { description: "OAuth getters return OAuth fields", - context: &model.UserContext{ - Provider: model.ProviderOAuth, - OAuth: &model.OAuthContext{BaseContext: model.BaseContext{Username: "dave", Email: "dave@example.com", Name: "Dave"}}, + context: &UserContext{ + Provider: ProviderOAuth, + OAuth: &OAuthContext{BaseContext: BaseContext{Username: "dave", Email: "dave@example.com", Name: "Dave"}}, }, - run: func(t *testing.T, c *model.UserContext) any { + run: func(t *testing.T, c *UserContext) any { return [3]string{c.GetUsername(), c.GetEmail(), c.GetName()} }, expected: [3]string{"dave", "dave@example.com", "Dave"}, }, { description: "ProviderName returns 'local' for ProviderLocal", - context: &model.UserContext{Provider: model.ProviderLocal}, - run: func(t *testing.T, c *model.UserContext) any { return c.GetProviderID() }, + context: &UserContext{Provider: ProviderLocal}, + run: func(t *testing.T, c *UserContext) any { return c.GetProviderID() }, expected: "local", }, { description: "ProviderName returns 'local' for ProviderBasicAuth", - context: &model.UserContext{Provider: model.ProviderBasicAuth}, - run: func(t *testing.T, c *model.UserContext) any { return c.GetProviderID() }, + context: &UserContext{Provider: ProviderBasicAuth}, + run: func(t *testing.T, c *UserContext) any { return c.GetProviderID() }, expected: "local", }, { description: "ProviderName returns 'ldap' for ProviderLDAP", - context: &model.UserContext{Provider: model.ProviderLDAP}, - run: func(t *testing.T, c *model.UserContext) any { return c.GetProviderID() }, + context: &UserContext{Provider: ProviderLDAP}, + run: func(t *testing.T, c *UserContext) any { return c.GetProviderID() }, expected: "ldap", }, { description: "ProviderName returns OAuth provider ID for ProviderOAuth", - context: &model.UserContext{ - Provider: model.ProviderOAuth, - OAuth: &model.OAuthContext{ID: "github"}, + context: &UserContext{ + Provider: ProviderOAuth, + OAuth: &OAuthContext{ID: "github"}, }, - run: func(t *testing.T, c *model.UserContext) any { return c.GetProviderID() }, + run: func(t *testing.T, c *UserContext) any { return c.GetProviderID() }, expected: "github", }, { description: "TOTPPending returns true when local context is pending", - context: &model.UserContext{ - Provider: model.ProviderLocal, - Local: &model.LocalContext{TOTPPending: true}, + context: &UserContext{ + Provider: ProviderLocal, + Local: &LocalContext{TOTPPending: true}, }, - run: func(t *testing.T, c *model.UserContext) any { return c.TOTPPending() }, + run: func(t *testing.T, c *UserContext) any { return c.TOTPPending() }, expected: true, }, { description: "TOTPPending returns false when local context is not pending", - context: &model.UserContext{ - Provider: model.ProviderLocal, - Local: &model.LocalContext{TOTPPending: false}, + context: &UserContext{ + Provider: ProviderLocal, + Local: &LocalContext{TOTPPending: false}, }, - run: func(t *testing.T, c *model.UserContext) any { return c.TOTPPending() }, + run: func(t *testing.T, c *UserContext) any { return c.TOTPPending() }, expected: false, }, { description: "TOTPPending returns false for non-local providers", - context: &model.UserContext{Provider: model.ProviderOAuth, OAuth: &model.OAuthContext{}}, - run: func(t *testing.T, c *model.UserContext) any { return c.TOTPPending() }, + context: &UserContext{Provider: ProviderOAuth, OAuth: &OAuthContext{}}, + run: func(t *testing.T, c *UserContext) any { return c.TOTPPending() }, expected: false, }, { description: "OAuthName returns DisplayName for ProviderOAuth", - context: &model.UserContext{ - Provider: model.ProviderOAuth, - OAuth: &model.OAuthContext{DisplayName: "Google"}, + context: &UserContext{ + Provider: ProviderOAuth, + OAuth: &OAuthContext{DisplayName: "Google"}, }, - run: func(t *testing.T, c *model.UserContext) any { return c.OAuthName() }, + run: func(t *testing.T, c *UserContext) any { return c.OAuthName() }, expected: "Google", }, { description: "OAuthName returns empty string for non-oauth providers", - context: &model.UserContext{Provider: model.ProviderLocal, Local: &model.LocalContext{}}, - run: func(t *testing.T, c *model.UserContext) any { return c.OAuthName() }, + context: &UserContext{Provider: ProviderLocal, Local: &LocalContext{}}, + run: func(t *testing.T, c *UserContext) any { return c.OAuthName() }, expected: "", }, { description: "NewFromGin populates context from gin value", - context: &model.UserContext{}, - run: func(t *testing.T, c *model.UserContext) any { - stored := &model.UserContext{ + context: &UserContext{}, + run: func(t *testing.T, c *UserContext) any { + stored := &UserContext{ Authenticated: true, - Provider: model.ProviderLocal, - Local: &model.LocalContext{BaseContext: model.BaseContext{Username: "alice"}}, + Provider: ProviderLocal, + Local: &LocalContext{BaseContext: BaseContext{Username: "alice"}}, } got, err := c.NewFromGin(newGinCtx(stored, true)) require.NoError(t, err) @@ -233,17 +232,17 @@ func TestContext(t *testing.T) { }, { description: "NewFromGin returns error when context value is missing", - context: &model.UserContext{}, - run: func(t *testing.T, c *model.UserContext) any { + context: &UserContext{}, + run: func(t *testing.T, c *UserContext) any { _, err := c.NewFromGin(newGinCtx(nil, false)) return err.Error() }, - expected: model.ErrUserContextNotFound.Error(), + expected: ErrUserContextNotFound.Error(), }, { description: "NewFromGin returns error when context value has wrong type", - context: &model.UserContext{}, - run: func(t *testing.T, c *model.UserContext) any { + context: &UserContext{}, + run: func(t *testing.T, c *UserContext) any { _, err := c.NewFromGin(newGinCtx("not a user context", true)) return err.Error() }, @@ -251,17 +250,17 @@ func TestContext(t *testing.T) { }, { description: "NewFromGin returns an error when context doesn't include user information", - context: &model.UserContext{}, - run: func(t *testing.T, c *model.UserContext) any { - _, err := c.NewFromGin(newGinCtx(&model.UserContext{Provider: model.ProviderLocal}, true)) + context: &UserContext{}, + run: func(t *testing.T, c *UserContext) any { + _, err := c.NewFromGin(newGinCtx(&UserContext{Provider: ProviderLocal}, true)) return err.Error() }, expected: "incomplete user context", }, { description: "Getters should not panic if provider context is empty", - context: &model.UserContext{Provider: model.ProviderLocal}, - run: func(t *testing.T, c *model.UserContext) any { + context: &UserContext{Provider: ProviderLocal}, + run: func(t *testing.T, c *UserContext) any { return [3]string{c.GetUsername(), c.GetEmail(), c.GetName()} }, expected: [3]string{"", "", ""}, diff --git a/internal/service/oidc_service_test.go b/internal/service/oidc_service_test.go index 5197d7c7..4ef39cb2 100644 --- a/internal/service/oidc_service_test.go +++ b/internal/service/oidc_service_test.go @@ -1,4 +1,4 @@ -package service_test +package service import ( "context" @@ -10,12 +10,11 @@ import ( "github.com/tinyauthapp/tinyauth/internal/model" "github.com/tinyauthapp/tinyauth/internal/repository/memory" - "github.com/tinyauthapp/tinyauth/internal/service" "github.com/tinyauthapp/tinyauth/internal/utils/logger" ) -func newTestUser() service.UserinfoResponse { - return service.UserinfoResponse{ +func newTestUser() UserinfoResponse { + return UserinfoResponse{ Sub: "test-sub", Name: "Test User", PreferredUsername: "testuser", @@ -70,7 +69,7 @@ func TestCompileUserinfo(t *testing.T) { store := memory.New() - svc, err := service.NewOIDCService(service.OIDCServiceInput{ + svc, err := NewOIDCService(OIDCServiceInput{ Log: log, Config: &cfg, Runtime: &runtime, @@ -81,16 +80,16 @@ func TestCompileUserinfo(t *testing.T) { type testCase struct { description string - mutate func(u *service.UserinfoResponse) + mutate func(u *UserinfoResponse) scope string - run func(t *testing.T, info service.UserinfoResponse) + run func(t *testing.T, info UserinfoResponse) } tests := []testCase{ { description: "openid scope only returns sub and updated_at", scope: "openid", - run: func(t *testing.T, info service.UserinfoResponse) { + run: func(t *testing.T, info UserinfoResponse) { assert.Equal(t, "test-sub", info.Sub) assert.Equal(t, int64(1234567890), info.UpdatedAt) assert.Empty(t, info.Name) @@ -103,7 +102,7 @@ func TestCompileUserinfo(t *testing.T) { { description: "profile scope returns all profile fields", scope: "openid profile", - run: func(t *testing.T, info service.UserinfoResponse) { + run: func(t *testing.T, info UserinfoResponse) { assert.Equal(t, "Test User", info.Name) assert.Equal(t, "testuser", info.PreferredUsername) assert.Equal(t, "Test", info.GivenName) @@ -123,7 +122,7 @@ func TestCompileUserinfo(t *testing.T) { { description: "email scope sets email and email_verified true when email present", scope: "openid email", - run: func(t *testing.T, info service.UserinfoResponse) { + run: func(t *testing.T, info UserinfoResponse) { assert.Equal(t, "test@example.com", info.Email) assert.True(t, info.EmailVerified) assert.Empty(t, info.Name) @@ -132,8 +131,8 @@ func TestCompileUserinfo(t *testing.T) { { description: "email scope sets email_verified false when email absent", scope: "openid email", - mutate: func(u *service.UserinfoResponse) { u.Email = "" }, - run: func(t *testing.T, info service.UserinfoResponse) { + mutate: func(u *UserinfoResponse) { u.Email = "" }, + run: func(t *testing.T, info UserinfoResponse) { assert.Empty(t, info.Email) assert.False(t, info.EmailVerified) }, @@ -141,7 +140,7 @@ func TestCompileUserinfo(t *testing.T) { { description: "phone scope sets phone_number_verified true when phone present", scope: "openid phone", - run: func(t *testing.T, info service.UserinfoResponse) { + run: func(t *testing.T, info UserinfoResponse) { assert.Equal(t, "+15555550100", info.PhoneNumber) require.NotNil(t, info.PhoneNumberVerified) assert.True(t, *info.PhoneNumberVerified) @@ -150,8 +149,8 @@ func TestCompileUserinfo(t *testing.T) { { description: "phone scope sets phone_number_verified false when phone absent", scope: "openid phone", - mutate: func(u *service.UserinfoResponse) { u.PhoneNumber = "" }, - run: func(t *testing.T, info service.UserinfoResponse) { + mutate: func(u *UserinfoResponse) { u.PhoneNumber = "" }, + run: func(t *testing.T, info UserinfoResponse) { require.NotNil(t, info.PhoneNumberVerified) assert.False(t, *info.PhoneNumberVerified) }, @@ -159,7 +158,7 @@ func TestCompileUserinfo(t *testing.T) { { description: "address scope returns parsed address", scope: "openid address", - run: func(t *testing.T, info service.UserinfoResponse) { + run: func(t *testing.T, info UserinfoResponse) { require.NotNil(t, info.Address) assert.Equal(t, "123 Main St", info.Address.Formatted) assert.Equal(t, "123 Main St", info.Address.StreetAddress) @@ -172,14 +171,14 @@ func TestCompileUserinfo(t *testing.T) { { description: "groups scope returns split groups", scope: "openid groups", - run: func(t *testing.T, info service.UserinfoResponse) { + run: func(t *testing.T, info UserinfoResponse) { assert.Equal(t, []string{"admins", "users"}, info.Groups) }, }, { description: "all scopes return all fields", scope: "openid profile email phone address groups", - run: func(t *testing.T, info service.UserinfoResponse) { + run: func(t *testing.T, info UserinfoResponse) { assert.Equal(t, "Test User", info.Name) assert.Equal(t, "test@example.com", info.Email) assert.Equal(t, "+15555550100", info.PhoneNumber) diff --git a/internal/service/policy_engine_test.go b/internal/service/policy_engine_test.go index 1c6120a0..ffaea2d9 100644 --- a/internal/service/policy_engine_test.go +++ b/internal/service/policy_engine_test.go @@ -1,10 +1,9 @@ -package service_test +package service import ( "testing" "github.com/stretchr/testify/assert" - "github.com/tinyauthapp/tinyauth/internal/service" "github.com/tinyauthapp/tinyauth/internal/test" "github.com/tinyauthapp/tinyauth/internal/utils/logger" ) @@ -12,14 +11,14 @@ import ( // Create test rule type TestRule struct{} -func (rule *TestRule) Evaluate(ctx *service.ACLContext) service.Effect { +func (rule *TestRule) Evaluate(ctx *ACLContext) Effect { switch ctx.Path { case "/allowed": - return service.EffectAllow + return EffectAllow case "/denied": - return service.EffectDeny + return EffectDeny default: - return service.EffectAbstain + return EffectAbstain } } @@ -33,32 +32,32 @@ func TestPolicyEngine(t *testing.T) { // Engine should fail with invalid policy cfg.Auth.ACLs.Policy = "invalid_policy" - _, err := service.NewPolicyEngine(service.PolicyEngineInput{ + _, err := NewPolicyEngine(PolicyEngineInput{ Log: log, Config: &cfg, }) assert.Error(t, err) // Engine should initialize with 'allow' policy - cfg.Auth.ACLs.Policy = string(service.PolicyAllow) - engine, err := service.NewPolicyEngine(service.PolicyEngineInput{ + cfg.Auth.ACLs.Policy = string(PolicyAllow) + engine, err := NewPolicyEngine(PolicyEngineInput{ Log: log, Config: &cfg, }) assert.NoError(t, err) - assert.Equal(t, service.PolicyAllow, engine.Policy()) + assert.Equal(t, PolicyAllow, engine.Policy()) // Engine should initialize with 'deny' policy - cfg.Auth.ACLs.Policy = string(service.PolicyDeny) - engine, err = service.NewPolicyEngine(service.PolicyEngineInput{ + cfg.Auth.ACLs.Policy = string(PolicyDeny) + engine, err = NewPolicyEngine(PolicyEngineInput{ Log: log, Config: &cfg, }) assert.NoError(t, err) - assert.Equal(t, service.PolicyDeny, engine.Policy()) + assert.Equal(t, PolicyDeny, engine.Policy()) // Engine should allow adding rules - engine, err = service.NewPolicyEngine(service.PolicyEngineInput{ + engine, err = NewPolicyEngine(PolicyEngineInput{ Log: log, Config: &cfg, }) @@ -68,8 +67,8 @@ func TestPolicyEngine(t *testing.T) { assert.True(t, ok) // Begin allow policy tests - cfg.Auth.ACLs.Policy = string(service.PolicyAllow) - engine, err = service.NewPolicyEngine(service.PolicyEngineInput{ + cfg.Auth.ACLs.Policy = string(PolicyAllow) + engine, err = NewPolicyEngine(PolicyEngineInput{ Log: log, Config: &cfg, }) @@ -77,7 +76,7 @@ func TestPolicyEngine(t *testing.T) { engine.RegisterRule("test-rule", testRule) // With allow policy, if rule allows, access should be allowed - ctx := &service.ACLContext{Path: "/allowed"} + ctx := &ACLContext{Path: "/allowed"} assert.Equal(t, true, engine.Evaluate("test-rule", ctx)) // With allow policy, if rule denies, access should be denied @@ -89,8 +88,8 @@ func TestPolicyEngine(t *testing.T) { assert.Equal(t, true, engine.Evaluate("test-rule", ctx)) // Begin deny policy tests - cfg.Auth.ACLs.Policy = string(service.PolicyDeny) - engine, err = service.NewPolicyEngine(service.PolicyEngineInput{ + cfg.Auth.ACLs.Policy = string(PolicyDeny) + engine, err = NewPolicyEngine(PolicyEngineInput{ Log: log, Config: &cfg, })