Skip to content

Commit b830aaf

Browse files
committed
update tests
1 parent 8c81a2b commit b830aaf

2 files changed

Lines changed: 241 additions & 306 deletions

File tree

internal/controller/user_controller_test.go

Lines changed: 103 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"encoding/json"
55
"net/http/httptest"
66
"path"
7-
"slices"
87
"strings"
98
"testing"
109
"time"
@@ -37,6 +36,23 @@ func TestUserController(t *testing.T) {
3736
Password: "$2a$10$ZwVYQH07JX2zq7Fjkt3gU.BjwvvwPeli4OqOno04RQIv0P7usBrXa", // password
3837
TotpSecret: "JPIEBDKJH6UGWJMX66RR3S55UFP2SGKK",
3938
},
39+
{
40+
Username: "attruser",
41+
Password: "$2a$10$ZwVYQH07JX2zq7Fjkt3gU.BjwvvwPeli4OqOno04RQIv0P7usBrXa", // password
42+
Attributes: config.UserAttributes{
43+
Name: "Alice Smith",
44+
Email: "alice@example.com",
45+
},
46+
},
47+
{
48+
Username: "attrtotpuser",
49+
Password: "$2a$10$ZwVYQH07JX2zq7Fjkt3gU.BjwvvwPeli4OqOno04RQIv0P7usBrXa", // password
50+
TotpSecret: "JPIEBDKJH6UGWJMX66RR3S55UFP2SGKK",
51+
Attributes: config.UserAttributes{
52+
Name: "Bob Jones",
53+
Email: "bob@example.com",
54+
},
55+
},
4056
},
4157
SessionExpiry: 10, // 10 seconds, useful for testing
4258
CookieDomain: "example.com",
@@ -274,6 +290,64 @@ func TestUserController(t *testing.T) {
274290
assert.Contains(t, recorder.Body.String(), "Too many failed TOTP attempts.")
275291
},
276292
},
293+
{
294+
description: "Login uses name and email from user attributes",
295+
middlewares: []gin.HandlerFunc{},
296+
run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) {
297+
loginReq := controller.LoginRequest{Username: "attruser", Password: "password"}
298+
body, err := json.Marshal(loginReq)
299+
require.NoError(t, err)
300+
301+
req := httptest.NewRequest("POST", "/api/user/login", strings.NewReader(string(body)))
302+
req.Header.Set("Content-Type", "application/json")
303+
router.ServeHTTP(recorder, req)
304+
305+
require.Equal(t, 200, recorder.Code)
306+
cookies := recorder.Result().Cookies()
307+
require.Len(t, cookies, 1)
308+
assert.Equal(t, "tinyauth-session", cookies[0].Name)
309+
},
310+
},
311+
{
312+
description: "Login with TOTP uses name and email from user attributes in pending session",
313+
middlewares: []gin.HandlerFunc{},
314+
run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) {
315+
loginReq := controller.LoginRequest{Username: "attrtotpuser", Password: "password"}
316+
body, err := json.Marshal(loginReq)
317+
require.NoError(t, err)
318+
319+
req := httptest.NewRequest("POST", "/api/user/login", strings.NewReader(string(body)))
320+
req.Header.Set("Content-Type", "application/json")
321+
router.ServeHTTP(recorder, req)
322+
323+
require.Equal(t, 200, recorder.Code)
324+
var res map[string]any
325+
require.NoError(t, json.Unmarshal(recorder.Body.Bytes(), &res))
326+
assert.Equal(t, true, res["totpPending"])
327+
require.Len(t, recorder.Result().Cookies(), 1)
328+
},
329+
},
330+
{
331+
description: "TOTP completion uses name and email from user attributes",
332+
middlewares: []gin.HandlerFunc{},
333+
run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) {
334+
code, err := totp.GenerateCode("JPIEBDKJH6UGWJMX66RR3S55UFP2SGKK", time.Now())
335+
require.NoError(t, err)
336+
337+
totpReq := controller.TotpRequest{Code: code}
338+
body, err := json.Marshal(totpReq)
339+
require.NoError(t, err)
340+
341+
req := httptest.NewRequest("POST", "/api/user/totp", strings.NewReader(string(body)))
342+
req.Header.Set("Content-Type", "application/json")
343+
router.ServeHTTP(recorder, req)
344+
345+
require.Equal(t, 200, recorder.Code)
346+
cookies := recorder.Result().Cookies()
347+
require.Len(t, cookies, 1)
348+
assert.Equal(t, "tinyauth-session", cookies[0].Name)
349+
},
350+
},
277351
}
278352

279353
oauthBrokerCfgs := make(map[string]config.OAuthServiceConfig)
@@ -306,9 +380,31 @@ func TestUserController(t *testing.T) {
306380
authService.ClearRateLimitsTestingOnly()
307381
}
308382

309-
setTotpMiddlewareOverrides := []string{
310-
"Should be able to login with totp",
311-
"Totp should rate limit on multiple invalid attempts",
383+
setTotpMiddlewareOverrides := map[string]config.UserContext{
384+
"Should be able to login with totp": {
385+
Username: "totpuser",
386+
Name: "Totpuser",
387+
Email: "totpuser@example.com",
388+
Provider: "local",
389+
TotpPending: true,
390+
TotpEnabled: true,
391+
},
392+
"Totp should rate limit on multiple invalid attempts": {
393+
Username: "totpuser",
394+
Name: "Totpuser",
395+
Email: "totpuser@example.com",
396+
Provider: "local",
397+
TotpPending: true,
398+
TotpEnabled: true,
399+
},
400+
"TOTP completion uses name and email from user attributes": {
401+
Username: "attrtotpuser",
402+
Name: "Bob Jones",
403+
Email: "bob@example.com",
404+
Provider: "local",
405+
TotpPending: true,
406+
TotpEnabled: true,
407+
},
312408
}
313409

314410
for _, test := range tests {
@@ -322,18 +418,10 @@ func TestUserController(t *testing.T) {
322418

323419
// Gin is stupid and doesn't allow setting a middleware after the groups
324420
// so we need to do some stupid overrides here
325-
if slices.Contains(setTotpMiddlewareOverrides, test.description) {
326-
// Assuming the cookie is set, it should be picked up by the
327-
// context middleware
421+
if ctx, ok := setTotpMiddlewareOverrides[test.description]; ok {
422+
ctx := ctx
328423
router.Use(func(c *gin.Context) {
329-
c.Set("context", &config.UserContext{
330-
Username: "totpuser",
331-
Name: "Totpuser",
332-
Email: "totpuser@example.com",
333-
Provider: "local",
334-
TotpPending: true,
335-
TotpEnabled: true,
336-
})
424+
c.Set("context", &ctx)
337425
})
338426
}
339427

@@ -354,150 +442,3 @@ func TestUserController(t *testing.T) {
354442
require.NoError(t, err)
355443
})
356444
}
357-
358-
func TestUserControllerAttributes(t *testing.T) {
359-
tlog.NewTestLogger().Init()
360-
tempDir := t.TempDir()
361-
362-
authServiceCfg := service.AuthServiceConfig{
363-
Users: []config.User{
364-
{
365-
Username: "attruser",
366-
Password: "$2a$10$ZwVYQH07JX2zq7Fjkt3gU.BjwvvwPeli4OqOno04RQIv0P7usBrXa", // password
367-
Attributes: config.UserAttributes{
368-
Name: "Alice Smith",
369-
Email: "alice@example.com",
370-
},
371-
},
372-
{
373-
Username: "attrtotpuser",
374-
Password: "$2a$10$ZwVYQH07JX2zq7Fjkt3gU.BjwvvwPeli4OqOno04RQIv0P7usBrXa", // password
375-
TotpSecret: "JPIEBDKJH6UGWJMX66RR3S55UFP2SGKK",
376-
Attributes: config.UserAttributes{
377-
Name: "Bob Jones",
378-
Email: "bob@example.com",
379-
},
380-
},
381-
},
382-
SessionExpiry: 10,
383-
CookieDomain: "example.com",
384-
LoginTimeout: 10,
385-
LoginMaxRetries: 3,
386-
SessionCookieName: "tinyauth-session",
387-
}
388-
389-
userControllerCfg := controller.UserControllerConfig{
390-
CookieDomain: "example.com",
391-
}
392-
393-
app := bootstrap.NewBootstrapApp(config.Config{})
394-
db, err := app.SetupDatabase(path.Join(tempDir, "tinyauth_attrs.db"))
395-
require.NoError(t, err)
396-
397-
queries := repository.New(db)
398-
399-
docker := service.NewDockerService()
400-
err = docker.Init()
401-
require.NoError(t, err)
402-
403-
ldap := service.NewLdapService(service.LdapServiceConfig{})
404-
err = ldap.Init()
405-
require.NoError(t, err)
406-
407-
broker := service.NewOAuthBrokerService(make(map[string]config.OAuthServiceConfig))
408-
err = broker.Init()
409-
require.NoError(t, err)
410-
411-
authService := service.NewAuthService(authServiceCfg, docker, ldap, queries, broker)
412-
err = authService.Init()
413-
require.NoError(t, err)
414-
415-
makeRouter := func(extraMiddlewares ...gin.HandlerFunc) *gin.Engine {
416-
router := gin.Default()
417-
for _, m := range extraMiddlewares {
418-
router.Use(m)
419-
}
420-
gin.SetMode(gin.TestMode)
421-
group := router.Group("/api")
422-
ctrl := controller.NewUserController(userControllerCfg, group, authService)
423-
ctrl.SetupRoutes()
424-
return router
425-
}
426-
427-
t.Run("Login uses name and email from user attributes", func(t *testing.T) {
428-
authService.ClearRateLimitsTestingOnly()
429-
router := makeRouter()
430-
431-
loginReq := controller.LoginRequest{Username: "attruser", Password: "password"}
432-
body, err := json.Marshal(loginReq)
433-
require.NoError(t, err)
434-
435-
req := httptest.NewRequest("POST", "/api/user/login", strings.NewReader(string(body)))
436-
req.Header.Set("Content-Type", "application/json")
437-
rec := httptest.NewRecorder()
438-
router.ServeHTTP(rec, req)
439-
440-
require.Equal(t, 200, rec.Code)
441-
cookies := rec.Result().Cookies()
442-
require.Len(t, cookies, 1)
443-
assert.Equal(t, "tinyauth-session", cookies[0].Name)
444-
})
445-
446-
t.Run("Login with TOTP uses name and email from user attributes in pending session", func(t *testing.T) {
447-
authService.ClearRateLimitsTestingOnly()
448-
router := makeRouter()
449-
450-
loginReq := controller.LoginRequest{Username: "attrtotpuser", Password: "password"}
451-
body, err := json.Marshal(loginReq)
452-
require.NoError(t, err)
453-
454-
req := httptest.NewRequest("POST", "/api/user/login", strings.NewReader(string(body)))
455-
req.Header.Set("Content-Type", "application/json")
456-
rec := httptest.NewRecorder()
457-
router.ServeHTTP(rec, req)
458-
459-
require.Equal(t, 200, rec.Code)
460-
var res map[string]any
461-
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &res))
462-
assert.Equal(t, true, res["totpPending"])
463-
require.Len(t, rec.Result().Cookies(), 1)
464-
})
465-
466-
t.Run("TOTP completion uses name and email from user attributes", func(t *testing.T) {
467-
authService.ClearRateLimitsTestingOnly()
468-
469-
// First: login to get TOTP-pending session
470-
router := makeRouter(func(c *gin.Context) {
471-
c.Set("context", &config.UserContext{
472-
Username: "attrtotpuser",
473-
Name: "Bob Jones",
474-
Email: "bob@example.com",
475-
Provider: "local",
476-
TotpPending: true,
477-
TotpEnabled: true,
478-
})
479-
})
480-
481-
code, err := totp.GenerateCode("JPIEBDKJH6UGWJMX66RR3S55UFP2SGKK", time.Now())
482-
require.NoError(t, err)
483-
484-
totpReq := controller.TotpRequest{Code: code}
485-
body, err := json.Marshal(totpReq)
486-
require.NoError(t, err)
487-
488-
req := httptest.NewRequest("POST", "/api/user/totp", strings.NewReader(string(body)))
489-
req.Header.Set("Content-Type", "application/json")
490-
rec := httptest.NewRecorder()
491-
router.ServeHTTP(rec, req)
492-
493-
require.Equal(t, 200, rec.Code)
494-
cookies := rec.Result().Cookies()
495-
require.Len(t, cookies, 1)
496-
assert.Equal(t, "tinyauth-session", cookies[0].Name)
497-
})
498-
499-
t.Cleanup(func() {
500-
err = db.Close()
501-
require.NoError(t, err)
502-
})
503-
}

0 commit comments

Comments
 (0)