package utils_test import ( "os" "testing" "tinyauth/internal/utils" "gotest.tools/v3/assert" ) func TestGetUsers(t *testing.T) { // Setup file, err := os.Create("/tmp/tinyauth_users_test.txt") assert.NilError(t, err) _, err = file.WriteString(" user1:$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G \n user2:$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G ") // Spacing is on purpose assert.NilError(t, err) err = file.Close() assert.NilError(t, err) defer os.Remove("/tmp/tinyauth_users_test.txt") // Test file users, err := utils.GetUsers("", "/tmp/tinyauth_users_test.txt") assert.NilError(t, err) assert.Equal(t, 2, len(users)) assert.Equal(t, "user1", users[0].Username) assert.Equal(t, "$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G", users[0].Password) assert.Equal(t, "user2", users[1].Username) assert.Equal(t, "$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G", users[1].Password) // Test config users, err = utils.GetUsers("user3:$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G,user4:$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G", "") assert.NilError(t, err) assert.Equal(t, 2, len(users)) assert.Equal(t, "user3", users[0].Username) assert.Equal(t, "$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G", users[0].Password) assert.Equal(t, "user4", users[1].Username) assert.Equal(t, "$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G", users[1].Password) // Test both users, err = utils.GetUsers("user5:$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G", "/tmp/tinyauth_users_test.txt") assert.NilError(t, err) assert.Equal(t, 3, len(users)) assert.Equal(t, "user5", users[0].Username) assert.Equal(t, "$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G", users[0].Password) assert.Equal(t, "user1", users[1].Username) assert.Equal(t, "$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G", users[1].Password) assert.Equal(t, "user2", users[2].Username) assert.Equal(t, "$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G", users[2].Password) // Test empty users, err = utils.GetUsers("", "") assert.NilError(t, err) assert.Equal(t, 0, len(users)) // Test non-existent file users, err = utils.GetUsers("", "/tmp/non_existent_file.txt") assert.ErrorContains(t, err, "no such file or directory") assert.Equal(t, 0, len(users)) } func TestParseUsers(t *testing.T) { // Valid users users, err := utils.ParseUsers("user1:$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G,user2:$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G:ABCDEF") // user2 has TOTP assert.NilError(t, err) assert.Equal(t, 2, len(users)) assert.Equal(t, "user1", users[0].Username) assert.Equal(t, "$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G", users[0].Password) assert.Equal(t, "", users[0].TotpSecret) assert.Equal(t, "user2", users[1].Username) assert.Equal(t, "$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G", users[1].Password) assert.Equal(t, "ABCDEF", users[1].TotpSecret) // Valid weirdly spaced users users, err = utils.ParseUsers(" user1:$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G , user2:$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G:ABCDEF ") // Spacing is on purpose assert.NilError(t, err) assert.Equal(t, 2, len(users)) assert.Equal(t, "user1", users[0].Username) assert.Equal(t, "$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G", users[0].Password) assert.Equal(t, "", users[0].TotpSecret) assert.Equal(t, "user2", users[1].Username) assert.Equal(t, "$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G", users[1].Password) assert.Equal(t, "ABCDEF", users[1].TotpSecret) } func TestParseUser(t *testing.T) { // Valid user without TOTP user, err := utils.ParseUser("user1:$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G") assert.NilError(t, err) assert.Equal(t, "user1", user.Username) assert.Equal(t, "$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G", user.Password) assert.Equal(t, "", user.TotpSecret) // Valid user with TOTP user, err = utils.ParseUser("user2:$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G:ABCDEF") assert.NilError(t, err) assert.Equal(t, "user2", user.Username) assert.Equal(t, "$2a$10$Mz5xhkfSJUtPWkzCd/TdaePh9CaXc5QcGII5wIMPLSR46eTwma30G", 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") }