Files
dance-lessons-coach/pkg/user/user_test.go
Gabriel Radureau 08202a578d
Some checks failed
CI/CD Pipeline / CI Pipeline (push) Has been cancelled
CI/CD Pipeline / CI Pipeline (pull_request) Successful in 15m34s
📝 docs: add comprehensive SOLID analysis and code review findings
- Documented SOLID principle violations across codebase
- Identified security best practice improvements needed
- Analyzed performance optimization opportunities
- Added detailed refactoring recommendations
- Updated ADR-0018 with JWT secret rotation reference
- Enabled gitea-client skill for programmer agent

This commit captures the current state analysis before implementing improvements.
2026-04-06 23:49:03 +02:00

223 lines
6.2 KiB
Go

package user
import (
"context"
"os"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestSQLiteRepository(t *testing.T) {
t.Run("CRUD operations", func(t *testing.T) {
// Create a temporary database
dbPath := "test_db.sqlite"
defer os.Remove(dbPath)
repo, err := NewSQLiteRepository(dbPath)
require.NoError(t, err)
defer repo.Close()
ctx := context.Background()
// Test CreateUser
user := &User{
Username: "testuser",
PasswordHash: "hashedpassword",
Description: ptrString("Test user"),
CurrentGoal: ptrString("Learn to dance"),
IsAdmin: false,
}
err = repo.CreateUser(ctx, user)
require.NoError(t, err)
assert.NotZero(t, user.ID)
// Test GetUserByUsername
retrievedUser, err := repo.GetUserByUsername(ctx, "testuser")
require.NoError(t, err)
assert.NotNil(t, retrievedUser)
assert.Equal(t, "testuser", retrievedUser.Username)
// Test UserExists
exists, err := repo.UserExists(ctx, "testuser")
require.NoError(t, err)
assert.True(t, exists)
// Test UpdateUser
retrievedUser.Description = ptrString("Updated description")
err = repo.UpdateUser(ctx, retrievedUser)
require.NoError(t, err)
// Verify update
updatedUser, err := repo.GetUserByUsername(ctx, "testuser")
require.NoError(t, err)
assert.Equal(t, "Updated description", *updatedUser.Description)
// Test AllowPasswordReset
err = repo.AllowPasswordReset(ctx, "testuser")
require.NoError(t, err)
// Verify password reset flag
userWithReset, err := repo.GetUserByUsername(ctx, "testuser")
require.NoError(t, err)
assert.True(t, userWithReset.AllowPasswordReset)
// Test CompletePasswordReset
err = repo.CompletePasswordReset(ctx, "testuser", "newhashedpassword")
require.NoError(t, err)
// Verify password reset completion
userAfterReset, err := repo.GetUserByUsername(ctx, "testuser")
require.NoError(t, err)
assert.Equal(t, "newhashedpassword", userAfterReset.PasswordHash)
assert.False(t, userAfterReset.AllowPasswordReset)
// Test DeleteUser
err = repo.DeleteUser(ctx, userAfterReset.ID)
require.NoError(t, err)
// Verify deletion
deletedUser, err := repo.GetUserByUsername(ctx, "testuser")
require.NoError(t, err)
assert.Nil(t, deletedUser)
})
}
func TestAuthService(t *testing.T) {
t.Run("Password hashing and authentication", func(t *testing.T) {
// Create a temporary database
dbPath := "test_auth_db.sqlite"
defer os.Remove(dbPath)
repo, err := NewSQLiteRepository(dbPath)
require.NoError(t, err)
defer repo.Close()
ctx := context.Background()
// Create auth service
jwtConfig := JWTConfig{
Secret: "test-secret",
ExpirationTime: time.Hour,
Issuer: "test-issuer",
}
authService := NewAuthService(repo, jwtConfig, "admin123")
// Test password hashing
password := "testpassword123"
hashedPassword, err := authService.HashPassword(ctx, password)
require.NoError(t, err)
assert.NotEmpty(t, hashedPassword)
// Create a test user
user := &User{
Username: "testuser",
PasswordHash: hashedPassword,
}
err = repo.CreateUser(ctx, user)
require.NoError(t, err)
// Test successful authentication
authenticatedUser, err := authService.Authenticate(ctx, "testuser", password)
require.NoError(t, err)
assert.NotNil(t, authenticatedUser)
assert.Equal(t, "testuser", authenticatedUser.Username)
// Test failed authentication with wrong password
_, err = authService.Authenticate(ctx, "testuser", "wrongpassword")
assert.Error(t, err)
assert.Equal(t, "invalid credentials", err.Error())
// Test JWT generation
token, err := authService.GenerateJWT(ctx, authenticatedUser)
require.NoError(t, err)
assert.NotEmpty(t, token)
// Test JWT validation
validatedUser, err := authService.ValidateJWT(ctx, token)
require.NoError(t, err)
assert.NotNil(t, validatedUser)
assert.Equal(t, authenticatedUser.ID, validatedUser.ID)
// Test admin authentication
adminUser, err := authService.AdminAuthenticate(ctx, "admin123")
require.NoError(t, err)
assert.NotNil(t, adminUser)
assert.True(t, adminUser.IsAdmin)
assert.Equal(t, "admin", adminUser.Username)
// Test failed admin authentication
_, err = authService.AdminAuthenticate(ctx, "wrongadminpassword")
assert.Error(t, err)
assert.Equal(t, "invalid admin credentials", err.Error())
})
}
func TestPasswordResetService(t *testing.T) {
t.Run("Password reset workflow", func(t *testing.T) {
// Create a temporary database
dbPath := "test_reset_db.sqlite"
defer os.Remove(dbPath)
repo, err := NewSQLiteRepository(dbPath)
require.NoError(t, err)
defer repo.Close()
ctx := context.Background()
// Create auth service
jwtConfig := JWTConfig{
Secret: "test-secret",
ExpirationTime: time.Hour,
Issuer: "test-issuer",
}
authService := NewAuthService(repo, jwtConfig, "admin123")
passwordResetService := NewPasswordResetService(repo, authService)
// Create a test user
password := "oldpassword123"
hashedPassword, err := authService.HashPassword(ctx, password)
require.NoError(t, err)
user := &User{
Username: "resetuser",
PasswordHash: hashedPassword,
}
err = repo.CreateUser(ctx, user)
require.NoError(t, err)
// Test password reset request
err = passwordResetService.RequestPasswordReset(ctx, "resetuser")
require.NoError(t, err)
// Verify user is flagged for reset
userAfterRequest, err := repo.GetUserByUsername(ctx, "resetuser")
require.NoError(t, err)
assert.True(t, userAfterRequest.AllowPasswordReset)
// Test password reset completion
newPassword := "newpassword123"
err = passwordResetService.CompletePasswordReset(ctx, "resetuser", newPassword)
require.NoError(t, err)
// Verify password was updated and reset flag was cleared
userAfterReset, err := repo.GetUserByUsername(ctx, "resetuser")
require.NoError(t, err)
assert.False(t, userAfterReset.AllowPasswordReset)
// Verify new password works by authenticating with the new password
authenticatedUser, err := authService.Authenticate(ctx, "resetuser", newPassword)
require.NoError(t, err)
assert.NotNil(t, authenticatedUser)
assert.Equal(t, "resetuser", authenticatedUser.Username)
})
}
// Helper function to create string pointers
func ptrString(s string) *string {
return &s
}