Files
tinyauth/internal/utils/user_utils_test.go
T
Scott McKendry 5d95123dcb feat(oidc): support for all in-spec attributes and scopes (#777)
* feat(oidc): support for all in-spec attributes and scopes

* add tests

* assert phone/email verified when either is set

* update tests

* add claims back to userinfo

* remove redundant column drop in migration

* fix duplicate migration id

* fix clobbered imports post-rebase
2026-04-27 19:25:52 +03:00

160 lines
4.2 KiB
Go

package utils_test
import (
"os"
"testing"
"github.com/tinyauthapp/tinyauth/internal/config"
"github.com/tinyauthapp/tinyauth/internal/utils"
"gotest.tools/v3/assert"
)
func TestGetUsers(t *testing.T) {
hash := "$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G"
// Setup
file, err := os.Create("/tmp/tinyauth_users_test.txt")
assert.NilError(t, err)
_, err = file.WriteString(" user1:" + hash + " \n user2:" + hash + " ") // Spacing is on purpose
assert.NilError(t, err)
err = file.Close()
assert.NilError(t, err)
defer os.Remove("/tmp/tinyauth_users_test.txt")
noAttrs := map[string]config.UserAttributes{}
// Test file only
users, err := utils.GetUsers([]string{}, "/tmp/tinyauth_users_test.txt", noAttrs)
assert.NilError(t, err)
assert.Equal(t, 2, len(users))
assert.Equal(t, "user1", users[0].Username)
assert.Equal(t, hash, users[0].Password)
assert.Equal(t, "user2", users[1].Username)
assert.Equal(t, hash, users[1].Password)
// Test inline config only
users, err = utils.GetUsers([]string{"user3:" + hash, "user4:" + hash}, "", noAttrs)
assert.NilError(t, err)
assert.Equal(t, 2, len(users))
assert.Equal(t, "user3", users[0].Username)
assert.Equal(t, "user4", users[1].Username)
// Test both
users, err = utils.GetUsers([]string{"user5:" + hash}, "/tmp/tinyauth_users_test.txt", noAttrs)
assert.NilError(t, err)
assert.Equal(t, 3, len(users))
usernames := map[string]bool{}
for _, u := range users {
usernames[u.Username] = true
}
assert.Assert(t, usernames["user1"])
assert.Assert(t, usernames["user2"])
assert.Assert(t, usernames["user5"])
// Test attributes applied from userAttributes map
attrs := map[string]config.UserAttributes{
"user1": {Name: "User One", Email: "user1@example.com"},
}
users, err = utils.GetUsers([]string{}, "/tmp/tinyauth_users_test.txt", attrs)
assert.NilError(t, err)
assert.Equal(t, 2, len(users))
for _, u := range users {
if u.Username == "user1" {
assert.Equal(t, "User One", u.Attributes.Name)
assert.Equal(t, "user1@example.com", u.Attributes.Email)
}
if u.Username == "user2" {
assert.Equal(t, "", u.Attributes.Name)
}
}
// Test empty
users, err = utils.GetUsers([]string{}, "", noAttrs)
assert.NilError(t, err)
assert.Equal(t, 0, len(users))
// Test non-existent file
users, err = utils.GetUsers([]string{}, "/tmp/non_existent_file.txt", noAttrs)
assert.ErrorContains(t, err, "no such file or directory")
assert.Equal(t, 0, len(users))
}
func TestParseUser(t *testing.T) {
hash := "$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G"
// Valid user without TOTP
user, err := utils.ParseUser("user1:" + hash)
assert.NilError(t, err)
assert.Equal(t, "user1", user.Username)
assert.Equal(t, hash, user.Password)
assert.Equal(t, "", user.TotpSecret)
// Valid user with TOTP
user, err = utils.ParseUser("user2:" + hash + ":ABCDEF")
assert.NilError(t, err)
assert.Equal(t, "user2", user.Username)
assert.Equal(t, hash, user.Password)
assert.Equal(t, "ABCDEF", user.TotpSecret)
// Valid user with $$ in password
user, err = utils.ParseUser("user3:pa$$word123")
assert.NilError(t, err)
assert.Equal(t, "user3", user.Username)
assert.Equal(t, "pa$word123", user.Password)
assert.Equal(t, "", user.TotpSecret)
// User with spaces
user, err = utils.ParseUser(" user4 : password123 : TOTPSECRET ")
assert.NilError(t, err)
assert.Equal(t, "user4", user.Username)
assert.Equal(t, "password123", user.Password)
assert.Equal(t, "TOTPSECRET", user.TotpSecret)
// Invalid users
_, err = utils.ParseUser("user1") // Missing password
assert.ErrorContains(t, err, "invalid user format")
_, err = utils.ParseUser("user1:")
assert.ErrorContains(t, err, "invalid user format")
_, err = utils.ParseUser(":password123")
assert.ErrorContains(t, err, "invalid user format")
_, err = utils.ParseUser("user1:password123:ABC:EXTRA") // Too many parts
assert.ErrorContains(t, err, "invalid user format")
_, err = utils.ParseUser("user1::ABC")
assert.ErrorContains(t, err, "invalid user format")
_, err = utils.ParseUser(":password123:ABC")
assert.ErrorContains(t, err, "invalid user format")
_, err = utils.ParseUser(" : : ")
assert.ErrorContains(t, err, "invalid user format")
}