tests: fix controller tests

This commit is contained in:
Stavros
2026-05-09 13:17:35 +03:00
parent 8c8d56f87c
commit 9fccb63097
10 changed files with 201 additions and 232 deletions
+4
View File
@@ -56,3 +56,7 @@ func (app *BootstrapApp) SetupDatabase() error {
app.db = db
return nil
}
func (app *BootstrapApp) GetDB() *sql.DB {
return app.db
}
+1 -1
View File
@@ -95,7 +95,7 @@ func (controller *ContextController) userContextHandler(c *gin.Context) {
}
func (controller *ContextController) appContextHandler(c *gin.Context) {
appUrl, err := url.Parse(controller.config.AppURL)
appUrl, err := url.Parse(controller.runtime.AppURL)
if err != nil {
controller.log.App.Error().Err(err).Msg("Failed to parse app URL")
+16 -30
View File
@@ -11,27 +11,14 @@ import (
"github.com/tinyauthapp/tinyauth/internal/controller"
"github.com/tinyauthapp/tinyauth/internal/model"
"github.com/tinyauthapp/tinyauth/internal/utils"
"github.com/tinyauthapp/tinyauth/internal/utils/tlog"
"github.com/tinyauthapp/tinyauth/internal/utils/logger"
)
func TestContextController(t *testing.T) {
tlog.NewTestLogger().Init()
controllerConfig := controller.ContextControllerConfig{
Providers: []controller.Provider{
{
Name: "Local",
ID: "local",
OAuth: false,
},
},
Title: "Tinyauth",
AppURL: "https://tinyauth.example.com",
CookieDomain: "example.com",
ForgotPasswordMessage: "foo",
BackgroundImage: "/background.jpg",
OAuthAutoRedirect: "none",
WarningsEnabled: true,
}
log := logger.NewLogger().WithTestConfig()
log.Init()
cfg, runtime := createTestConfigs(t)
tests := []struct {
description string
@@ -47,14 +34,14 @@ func TestContextController(t *testing.T) {
expectedAppContextResponse := controller.AppContextResponse{
Status: 200,
Message: "Success",
Providers: controllerConfig.Providers,
Title: controllerConfig.Title,
AppURL: controllerConfig.AppURL,
CookieDomain: controllerConfig.CookieDomain,
ForgotPasswordMessage: controllerConfig.ForgotPasswordMessage,
BackgroundImage: controllerConfig.BackgroundImage,
OAuthAutoRedirect: controllerConfig.OAuthAutoRedirect,
WarningsEnabled: controllerConfig.WarningsEnabled,
Providers: runtime.ConfiguredProviders,
Title: cfg.UI.Title,
AppURL: runtime.AppURL,
CookieDomain: runtime.CookieDomain,
ForgotPasswordMessage: cfg.UI.ForgotPasswordMessage,
BackgroundImage: cfg.UI.BackgroundImage,
OAuthAutoRedirect: cfg.OAuth.AutoRedirect,
WarningsEnabled: cfg.UI.WarningsEnabled,
}
bytes, err := json.Marshal(expectedAppContextResponse)
assert.NoError(t, err)
@@ -86,7 +73,7 @@ func TestContextController(t *testing.T) {
BaseContext: model.BaseContext{
Username: "johndoe",
Name: "John Doe",
Email: utils.CompileUserEmail("johndoe", controllerConfig.CookieDomain),
Email: utils.CompileUserEmail("johndoe", runtime.CookieDomain),
},
},
})
@@ -100,7 +87,7 @@ func TestContextController(t *testing.T) {
IsLoggedIn: true,
Username: "johndoe",
Name: "John Doe",
Email: utils.CompileUserEmail("johndoe", controllerConfig.CookieDomain),
Email: utils.CompileUserEmail("johndoe", runtime.CookieDomain),
Provider: "local",
}
bytes, err := json.Marshal(expectedUserContextResponse)
@@ -121,8 +108,7 @@ func TestContextController(t *testing.T) {
group := router.Group("/api")
gin.SetMode(gin.TestMode)
contextController := controller.NewContextController(controllerConfig, group)
contextController.SetupRoutes()
controller.NewContextController(log, cfg, runtime, group)
recorder := httptest.NewRecorder()
+106
View File
@@ -0,0 +1,106 @@
package controller_test
import (
"path"
"testing"
"github.com/stretchr/testify/require"
"github.com/tinyauthapp/tinyauth/internal/model"
"golang.org/x/crypto/bcrypt"
)
var testingTOTPSecret = "JPIEBDKJH6UGWJMX66RR3S55UFP2SGKK"
func createTestConfigs(t *testing.T) (model.Config, model.RuntimeConfig) {
tempDir := t.TempDir()
config := model.Config{
UI: model.UIConfig{
Title: "Tinyauth Test",
ForgotPasswordMessage: "foo",
BackgroundImage: "/background.jpg",
WarningsEnabled: true,
},
OAuth: model.OAuthConfig{
AutoRedirect: "none",
},
OIDC: model.OIDCConfig{
Clients: map[string]model.OIDCClientConfig{
"test": {
ClientID: "some-client-id",
ClientSecret: "some-client-secret",
TrustedRedirectURIs: []string{"https://test.example.com/callback"},
Name: "Test Client",
},
},
PrivateKeyPath: path.Join(tempDir, "key.pem"),
PublicKeyPath: path.Join(tempDir, "key.pub"),
},
Auth: model.AuthConfig{
SessionExpiry: 10,
LoginTimeout: 10,
LoginMaxRetries: 3,
},
Database: model.DatabaseConfig{
Path: path.Join(tempDir, "test.db"),
},
Resources: model.ResourcesConfig{
Enabled: true,
Path: path.Join(tempDir, "resources"),
},
}
passwd, err := bcrypt.GenerateFromPassword([]byte("password"), bcrypt.DefaultCost)
require.NoError(t, err)
runtime := model.RuntimeConfig{
ConfiguredProviders: []model.Provider{
{
Name: "Local",
ID: "local",
OAuth: false,
},
},
LocalUsers: []model.LocalUser{
{
Username: "testuser",
Password: string(passwd),
},
{
Username: "totpuser",
Password: string(passwd),
TOTPSecret: testingTOTPSecret,
},
{
Username: "attruser",
Password: string(passwd),
Attributes: model.UserAttributes{
Name: "Alice Smith",
Email: "alice@example.com",
},
},
{
Username: "attrtotpuser",
Password: string(passwd),
TOTPSecret: testingTOTPSecret,
Attributes: model.UserAttributes{
Name: "Bob Jones",
Email: "bob@example.com",
},
},
},
CookieDomain: "example.com",
AppURL: "https://tinyauth.example.com",
SessionCookieName: "tinyauth-session",
OIDCClients: func() []model.OIDCClientConfig {
var clients []model.OIDCClientConfig
for id, client := range config.OIDC.Clients {
client.ID = id
clients = append(clients, client)
}
return clients
}(),
}
return config, runtime
}
@@ -7,13 +7,11 @@ import (
"testing"
"github.com/gin-gonic/gin"
"github.com/tinyauthapp/tinyauth/internal/controller"
"github.com/tinyauthapp/tinyauth/internal/utils/tlog"
"github.com/stretchr/testify/assert"
"github.com/tinyauthapp/tinyauth/internal/controller"
)
func TestHealthController(t *testing.T) {
tlog.NewTestLogger().Init()
tests := []struct {
description string
path string
@@ -56,8 +54,7 @@ func TestHealthController(t *testing.T) {
group := router.Group("/api")
gin.SetMode(gin.TestMode)
healthController := controller.NewHealthController(group)
healthController.SetupRoutes()
controller.NewHealthController(group)
recorder := httptest.NewRecorder()
+15 -29
View File
@@ -1,13 +1,14 @@
package controller_test
import (
"context"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"net/http/httptest"
"net/url"
"path"
"strings"
"sync"
"testing"
"github.com/gin-gonic/gin"
@@ -19,29 +20,14 @@ import (
"github.com/tinyauthapp/tinyauth/internal/model"
"github.com/tinyauthapp/tinyauth/internal/repository"
"github.com/tinyauthapp/tinyauth/internal/service"
"github.com/tinyauthapp/tinyauth/internal/utils/tlog"
"github.com/tinyauthapp/tinyauth/internal/utils/logger"
)
func TestOIDCController(t *testing.T) {
tlog.NewTestLogger().Init()
tempDir := t.TempDir()
log := logger.NewLogger().WithTestConfig()
log.Init()
oidcServiceCfg := service.OIDCServiceConfig{
Clients: map[string]model.OIDCClientConfig{
"test": {
ClientID: "some-client-id",
ClientSecret: "some-client-secret",
TrustedRedirectURIs: []string{"https://test.example.com/callback"},
Name: "Test Client",
},
},
PrivateKeyPath: path.Join(tempDir, "key.pem"),
PublicKeyPath: path.Join(tempDir, "key.pub"),
Issuer: "https://tinyauth.example.com",
SessionExpiry: 500,
}
controllerCfg := controller.OIDCControllerConfig{}
cfg, runtime := createTestConfigs(t)
simpleCtx := func(c *gin.Context) {
c.Set("context", &model.UserContext{
@@ -852,14 +838,16 @@ func TestOIDCController(t *testing.T) {
},
}
app := bootstrap.NewBootstrapApp(model.Config{})
app := bootstrap.NewBootstrapApp(cfg)
db, err := app.SetupDatabase(path.Join(tempDir, "tinyauth.db"))
err := app.SetupDatabase()
require.NoError(t, err)
queries := repository.New(db)
oidcService := service.NewOIDCService(oidcServiceCfg, queries)
err = oidcService.Init()
queries := repository.New(app.GetDB())
wg := &sync.WaitGroup{}
oidcService, err := service.NewOIDCService(log, cfg, runtime, queries, context.TODO(), wg)
require.NoError(t, err)
for _, test := range tests {
@@ -873,8 +861,7 @@ func TestOIDCController(t *testing.T) {
group := router.Group("/api")
gin.SetMode(gin.TestMode)
oidcController := controller.NewOIDCController(controllerCfg, oidcService, group)
oidcController.SetupRoutes()
controller.NewOIDCController(log, oidcService, group)
recorder := httptest.NewRecorder()
@@ -883,7 +870,6 @@ func TestOIDCController(t *testing.T) {
}
t.Cleanup(func() {
err = db.Close()
require.NoError(t, err)
app.GetDB().Close()
})
}
+16 -51
View File
@@ -1,8 +1,9 @@
package controller_test
import (
"context"
"net/http/httptest"
"path"
"sync"
"testing"
"github.com/gin-gonic/gin"
@@ -13,35 +14,14 @@ import (
"github.com/tinyauthapp/tinyauth/internal/model"
"github.com/tinyauthapp/tinyauth/internal/repository"
"github.com/tinyauthapp/tinyauth/internal/service"
"github.com/tinyauthapp/tinyauth/internal/utils/tlog"
"github.com/tinyauthapp/tinyauth/internal/utils/logger"
)
func TestProxyController(t *testing.T) {
tlog.NewTestLogger().Init()
tempDir := t.TempDir()
log := logger.NewLogger().WithTestConfig()
log.Init()
authServiceCfg := service.AuthServiceConfig{
LocalUsers: &[]model.LocalUser{
{
Username: "testuser",
Password: "$2a$10$ZwVYQH07JX2zq7Fjkt3gU.BjwvvwPeli4OqOno04RQIv0P7usBrXa", // password
},
{
Username: "totpuser",
Password: "$2a$10$ZwVYQH07JX2zq7Fjkt3gU.BjwvvwPeli4OqOno04RQIv0P7usBrXa", // password
TOTPSecret: "JPIEBDKJH6UGWJMX66RR3S55UFP2SGKK",
},
},
SessionExpiry: 10, // 10 seconds, useful for testing
CookieDomain: "example.com",
LoginTimeout: 10, // 10 seconds, useful for testing
LoginMaxRetries: 3,
SessionCookieName: "tinyauth-session",
}
controllerCfg := controller.ProxyControllerConfig{
AppURL: "https://tinyauth.example.com",
}
cfg, runtime := createTestConfigs(t)
acls := map[string]model.App{
"app_path_allow": {
@@ -398,32 +378,19 @@ func TestProxyController(t *testing.T) {
},
}
oauthBrokerCfgs := make(map[string]model.OAuthServiceConfig)
app := bootstrap.NewBootstrapApp(cfg)
app := bootstrap.NewBootstrapApp(model.Config{})
db, err := app.SetupDatabase(path.Join(tempDir, "tinyauth.db"))
err := app.SetupDatabase()
require.NoError(t, err)
queries := repository.New(db)
queries := repository.New(app.GetDB())
docker := service.NewDockerService()
err = docker.Init()
require.NoError(t, err)
wg := &sync.WaitGroup{}
ctx := context.TODO()
ldap := service.NewLdapService(service.LdapServiceConfig{})
err = ldap.Init()
require.NoError(t, err)
broker := service.NewOAuthBrokerService(oauthBrokerCfgs)
err = broker.Init()
require.NoError(t, err)
authService := service.NewAuthService(authServiceCfg, ldap, queries, broker)
err = authService.Init()
require.NoError(t, err)
aclsService := service.NewAccessControlsService(docker, acls)
broker := service.NewOAuthBrokerService(log, map[string]model.OAuthServiceConfig{}, ctx)
authService := service.NewAuthService(log, cfg, runtime, ctx, wg, nil, queries, broker)
aclsService := service.NewAccessControlsService(log, nil, acls)
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
@@ -438,15 +405,13 @@ func TestProxyController(t *testing.T) {
recorder := httptest.NewRecorder()
proxyController := controller.NewProxyController(controllerCfg, group, aclsService, authService)
proxyController.SetupRoutes()
controller.NewProxyController(log, runtime, group, aclsService, authService)
test.run(t, router, recorder)
})
}
t.Cleanup(func() {
err = db.Close()
require.NoError(t, err)
app.GetDB().Close()
})
}
@@ -3,26 +3,19 @@ package controller_test
import (
"net/http/httptest"
"os"
"path"
"path/filepath"
"testing"
"github.com/gin-gonic/gin"
"github.com/tinyauthapp/tinyauth/internal/controller"
"github.com/tinyauthapp/tinyauth/internal/utils/tlog"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tinyauthapp/tinyauth/internal/controller"
)
func TestResourcesController(t *testing.T) {
tlog.NewTestLogger().Init()
tempDir := t.TempDir()
cfg, _ := createTestConfigs(t)
resourcesControllerCfg := controller.ResourcesControllerConfig{
Path: path.Join(tempDir, "resources"),
Enabled: true,
}
err := os.Mkdir(resourcesControllerCfg.Path, 0777)
err := os.MkdirAll(cfg.Resources.Path, 0777)
require.NoError(t, err)
type testCase struct {
@@ -61,11 +54,11 @@ func TestResourcesController(t *testing.T) {
},
}
testFilePath := resourcesControllerCfg.Path + "/testfile.txt"
testFilePath := cfg.Resources.Path + "/testfile.txt"
err = os.WriteFile(testFilePath, []byte("This is a test file."), 0777)
require.NoError(t, err)
testFilePathParent := tempDir + "/somefile.txt"
testFilePathParent := filepath.Dir(cfg.Resources.Path) + "/somefile.txt"
err = os.WriteFile(testFilePathParent, []byte("This file should not be accessible."), 0777)
require.NoError(t, err)
@@ -75,8 +68,7 @@ func TestResourcesController(t *testing.T) {
group := router.Group("/")
gin.SetMode(gin.TestMode)
resourcesController := controller.NewResourcesController(resourcesControllerCfg, group)
resourcesController.SetupRoutes()
controller.NewResourcesController(cfg, group)
recorder := httptest.NewRecorder()
test.run(t, router, recorder)
+14 -67
View File
@@ -5,8 +5,8 @@ import (
"encoding/json"
"net/http"
"net/http/httptest"
"path"
"strings"
"sync"
"testing"
"time"
@@ -19,53 +19,14 @@ import (
"github.com/tinyauthapp/tinyauth/internal/model"
"github.com/tinyauthapp/tinyauth/internal/repository"
"github.com/tinyauthapp/tinyauth/internal/service"
"github.com/tinyauthapp/tinyauth/internal/utils/tlog"
"github.com/tinyauthapp/tinyauth/internal/utils/logger"
)
func TestUserController(t *testing.T) {
tlog.NewTestLogger().Init()
tempDir := t.TempDir()
log := logger.NewLogger().WithTestConfig()
log.Init()
authServiceCfg := service.AuthServiceConfig{
LocalUsers: &[]model.LocalUser{
{
Username: "testuser",
Password: "$2a$10$ZwVYQH07JX2zq7Fjkt3gU.BjwvvwPeli4OqOno04RQIv0P7usBrXa", // password
},
{
Username: "totpuser",
Password: "$2a$10$ZwVYQH07JX2zq7Fjkt3gU.BjwvvwPeli4OqOno04RQIv0P7usBrXa", // password
TOTPSecret: "JPIEBDKJH6UGWJMX66RR3S55UFP2SGKK",
},
{
Username: "attruser",
Password: "$2a$10$ZwVYQH07JX2zq7Fjkt3gU.BjwvvwPeli4OqOno04RQIv0P7usBrXa", // password
Attributes: model.UserAttributes{
Name: "Alice Smith",
Email: "alice@example.com",
},
},
{
Username: "attrtotpuser",
Password: "$2a$10$ZwVYQH07JX2zq7Fjkt3gU.BjwvvwPeli4OqOno04RQIv0P7usBrXa", // password
TOTPSecret: "JPIEBDKJH6UGWJMX66RR3S55UFP2SGKK",
Attributes: model.UserAttributes{
Name: "Bob Jones",
Email: "bob@example.com",
},
},
},
SessionExpiry: 10, // 10 seconds, useful for testing
CookieDomain: "example.com",
LoginTimeout: 10, // 10 seconds, useful for testing
LoginMaxRetries: 3,
SessionCookieName: "tinyauth-session",
}
userControllerCfg := controller.UserControllerConfig{
CookieDomain: "example.com",
SessionCookieName: "tinyauth-session",
}
cfg, runtime := createTestConfigs(t)
totpCtx := func(c *gin.Context) {
c.Set("context", &model.UserContext{
@@ -111,14 +72,12 @@ func TestUserController(t *testing.T) {
})
}
oauthBrokerCfgs := make(map[string]model.OAuthServiceConfig)
app := bootstrap.NewBootstrapApp(cfg)
app := bootstrap.NewBootstrapApp(model.Config{})
db, err := app.SetupDatabase(path.Join(tempDir, "tinyauth.db"))
err := app.SetupDatabase()
require.NoError(t, err)
queries := repository.New(db)
queries := repository.New(app.GetDB())
type testCase struct {
description string
@@ -456,21 +415,11 @@ func TestUserController(t *testing.T) {
},
}
docker := service.NewDockerService()
err = docker.Init()
require.NoError(t, err)
ctx := context.TODO()
wg := &sync.WaitGroup{}
ldap := service.NewLdapService(service.LdapServiceConfig{})
err = ldap.Init()
require.NoError(t, err)
broker := service.NewOAuthBrokerService(oauthBrokerCfgs)
err = broker.Init()
require.NoError(t, err)
authService := service.NewAuthService(authServiceCfg, ldap, queries, broker)
err = authService.Init()
require.NoError(t, err)
broker := service.NewOAuthBrokerService(log, map[string]model.OAuthServiceConfig{}, ctx)
authService := service.NewAuthService(log, cfg, runtime, ctx, wg, nil, queries, broker)
beforeEach := func() {
// Clear failed login attempts before each test
@@ -489,8 +438,7 @@ func TestUserController(t *testing.T) {
group := router.Group("/api")
gin.SetMode(gin.TestMode)
userController := controller.NewUserController(userControllerCfg, group, authService)
userController.SetupRoutes()
controller.NewUserController(log, runtime, group, authService)
recorder := httptest.NewRecorder()
@@ -499,7 +447,6 @@ func TestUserController(t *testing.T) {
}
t.Cleanup(func() {
err = db.Close()
require.NoError(t, err)
app.GetDB().Close()
})
}
@@ -1,10 +1,11 @@
package controller_test
import (
"context"
"encoding/json"
"fmt"
"net/http/httptest"
"path"
"sync"
"testing"
"github.com/gin-gonic/gin"
@@ -12,30 +13,16 @@ import (
"github.com/stretchr/testify/require"
"github.com/tinyauthapp/tinyauth/internal/bootstrap"
"github.com/tinyauthapp/tinyauth/internal/controller"
"github.com/tinyauthapp/tinyauth/internal/model"
"github.com/tinyauthapp/tinyauth/internal/repository"
"github.com/tinyauthapp/tinyauth/internal/service"
"github.com/tinyauthapp/tinyauth/internal/utils/tlog"
"github.com/tinyauthapp/tinyauth/internal/utils/logger"
)
func TestWellKnownController(t *testing.T) {
tlog.NewTestLogger().Init()
tempDir := t.TempDir()
log := logger.NewLogger().WithTestConfig()
log.Init()
oidcServiceCfg := service.OIDCServiceConfig{
Clients: map[string]model.OIDCClientConfig{
"test": {
ClientID: "some-client-id",
ClientSecret: "some-client-secret",
TrustedRedirectURIs: []string{"https://test.example.com/callback"},
Name: "Test Client",
},
},
PrivateKeyPath: path.Join(tempDir, "key.pem"),
PublicKeyPath: path.Join(tempDir, "key.pub"),
Issuer: "https://tinyauth.example.com",
SessionExpiry: 500,
}
cfg, runtime := createTestConfigs(t)
type testCase struct {
description string
@@ -56,11 +43,11 @@ func TestWellKnownController(t *testing.T) {
assert.NoError(t, err)
expected := controller.OpenIDConnectConfiguration{
Issuer: oidcServiceCfg.Issuer,
AuthorizationEndpoint: fmt.Sprintf("%s/authorize", oidcServiceCfg.Issuer),
TokenEndpoint: fmt.Sprintf("%s/api/oidc/token", oidcServiceCfg.Issuer),
UserinfoEndpoint: fmt.Sprintf("%s/api/oidc/userinfo", oidcServiceCfg.Issuer),
JwksUri: fmt.Sprintf("%s/.well-known/jwks.json", oidcServiceCfg.Issuer),
Issuer: runtime.AppURL,
AuthorizationEndpoint: fmt.Sprintf("%s/authorize", runtime.AppURL),
TokenEndpoint: fmt.Sprintf("%s/api/oidc/token", runtime.AppURL),
UserinfoEndpoint: fmt.Sprintf("%s/api/oidc/userinfo", runtime.AppURL),
JwksUri: fmt.Sprintf("%s/.well-known/jwks.json", runtime.AppURL),
ScopesSupported: service.SupportedScopes,
ResponseTypesSupported: service.SupportedResponseTypes,
GrantTypesSupported: service.SupportedGrantTypes,
@@ -101,16 +88,17 @@ func TestWellKnownController(t *testing.T) {
},
}
app := bootstrap.NewBootstrapApp(model.Config{})
ctx := context.TODO()
wg := &sync.WaitGroup{}
db, err := app.SetupDatabase(path.Join(tempDir, "tinyauth.db"))
app := bootstrap.NewBootstrapApp(cfg)
err := app.SetupDatabase()
require.NoError(t, err)
queries := repository.New(db)
queries := repository.New(app.GetDB())
oidcService := service.NewOIDCService(oidcServiceCfg, queries)
err = oidcService.Init()
require.NoError(t, err)
oidcService, err := service.NewOIDCService(log, cfg, runtime, queries, ctx, wg)
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
@@ -119,15 +107,13 @@ func TestWellKnownController(t *testing.T) {
recorder := httptest.NewRecorder()
wellKnownController := controller.NewWellKnownController(controller.WellKnownControllerConfig{}, oidcService, router)
wellKnownController.SetupRoutes()
controller.NewWellKnownController(oidcService, &router.RouterGroup)
test.run(t, router, recorder)
})
}
t.Cleanup(func() {
err = db.Close()
require.NoError(t, err)
app.GetDB().Close()
})
}