tercul-backend/internal/app/auth/main_test.go
google-labs-jules[bot] 53aa4d0344
Security Hardening and GraphQL Caching (#69)
* feat: add security middleware, graphql apq, and improved linting

- Add RateLimit, RequestValidation, and CORS middleware.
- Configure middleware chain in API server.
- Implement Redis cache for GraphQL Automatic Persisted Queries.
- Add .golangci.yml and fix linting issues (shadowing, timeouts).

* feat: security, caching and linting config

- Fix .golangci.yml config for govet shadow check
- (Previous changes: Security middleware, GraphQL APQ, Linting fixes)

* fix: resolve remaining lint errors

- Fix unhandled errors in tests (errcheck)
- Define constants for repeated strings (goconst)
- Suppress high complexity warnings with nolint:gocyclo
- Fix integer overflow warnings (gosec)
- Add package comments
- Split long lines (lll)
- Rename Analyse -> Analyze (misspell)
- Fix naked returns and unused params

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2025-12-01 00:14:22 +01:00

140 lines
4.7 KiB
Go

package auth
import (
"context"
"errors"
"gorm.io/gorm"
"tercul/internal/domain"
"tercul/internal/platform/auth"
)
// mockUserRepository is a local mock for the UserRepository interface.
type mockUserRepository struct {
users map[uint]domain.User
findByEmailFunc func(ctx context.Context, email string) (*domain.User, error)
findByUsernameFunc func(ctx context.Context, username string) (*domain.User, error)
createFunc func(ctx context.Context, user *domain.User) error
updateFunc func(ctx context.Context, user *domain.User) error
getByIDFunc func(ctx context.Context, id uint) (*domain.User, error)
}
func newMockUserRepository() *mockUserRepository {
return &mockUserRepository{users: make(map[uint]domain.User)}
}
func (m *mockUserRepository) FindByEmail(ctx context.Context, email string) (*domain.User, error) {
if m.findByEmailFunc != nil {
return m.findByEmailFunc(ctx, email)
}
for _, u := range m.users {
if u.Email == email {
return &u, nil
}
}
return nil, errors.New("user not found")
}
func (m *mockUserRepository) FindByUsername(ctx context.Context, username string) (*domain.User, error) {
if m.findByUsernameFunc != nil {
return m.findByUsernameFunc(ctx, username)
}
for _, u := range m.users {
if u.Username == username {
return &u, nil
}
}
return nil, errors.New("user not found")
}
func (m *mockUserRepository) Create(ctx context.Context, user *domain.User) error {
if m.createFunc != nil {
return m.createFunc(ctx, user)
}
// Simulate the BeforeSave hook for password hashing
if err := user.BeforeSave(nil); err != nil {
return err
}
//nolint:gosec // G115: len is always positive
user.ID = uint(len(m.users) + 1)
m.users[user.ID] = *user
return nil
}
func (m *mockUserRepository) Update(ctx context.Context, user *domain.User) error {
if m.updateFunc != nil {
return m.updateFunc(ctx, user)
}
if _, ok := m.users[user.ID]; ok {
m.users[user.ID] = *user
return nil
}
return errors.New("user not found")
}
func (m *mockUserRepository) GetByID(ctx context.Context, id uint) (*domain.User, error) {
if m.getByIDFunc != nil {
return m.getByIDFunc(ctx, id)
}
if user, ok := m.users[id]; ok {
return &user, nil
}
return nil, errors.New("user not found")
}
// Implement the rest of the UserRepository interface with empty methods.
func (m *mockUserRepository) List(ctx context.Context, page, pageSize int) (*domain.PaginatedResult[domain.User], error) {
return nil, nil
}
func (m *mockUserRepository) ListAll(ctx context.Context) ([]domain.User, error) { return nil, nil }
func (m *mockUserRepository) Count(ctx context.Context) (int64, error) { return 0, nil }
func (m *mockUserRepository) ListByRole(ctx context.Context, role domain.UserRole) ([]domain.User, error) {
return nil, nil
}
func (m *mockUserRepository) Delete(ctx context.Context, id uint) error { return nil }
func (m *mockUserRepository) CreateInTx(ctx context.Context, tx *gorm.DB, entity *domain.User) error {
return nil
}
func (m *mockUserRepository) GetByIDWithOptions(ctx context.Context, id uint, options *domain.QueryOptions) (*domain.User, error) {
return nil, nil
}
func (m *mockUserRepository) UpdateInTx(ctx context.Context, tx *gorm.DB, entity *domain.User) error {
return nil
}
func (m *mockUserRepository) DeleteInTx(ctx context.Context, tx *gorm.DB, id uint) error { return nil }
func (m *mockUserRepository) ListWithOptions(ctx context.Context, options *domain.QueryOptions) ([]domain.User, error) {
return nil, nil
}
func (m *mockUserRepository) CountWithOptions(ctx context.Context, options *domain.QueryOptions) (int64, error) {
return 0, nil
}
func (m *mockUserRepository) FindWithPreload(ctx context.Context, preloads []string, id uint) (*domain.User, error) {
return nil, nil
}
func (m *mockUserRepository) GetAllForSync(ctx context.Context, batchSize, offset int) ([]domain.User, error) {
return nil, nil
}
func (m *mockUserRepository) Exists(ctx context.Context, id uint) (bool, error) { return false, nil }
func (m *mockUserRepository) BeginTx(ctx context.Context) (*gorm.DB, error) { return nil, nil }
func (m *mockUserRepository) WithTx(ctx context.Context, fn func(tx *gorm.DB) error) error {
return nil
}
// mockJWTManager is a local mock for the JWTManager.
type mockJWTManager struct {
generateTokenFunc func(user *domain.User) (string, error)
validateTokenFunc func(tokenString string) (*auth.Claims, error)
}
func (m *mockJWTManager) GenerateToken(user *domain.User) (string, error) {
if m.generateTokenFunc != nil {
return m.generateTokenFunc(user)
}
return "test-token", nil
}
func (m *mockJWTManager) ValidateToken(tokenString string) (*auth.Claims, error) {
if m.validateTokenFunc != nil {
return m.validateTokenFunc(tokenString)
}
return &auth.Claims{UserID: 1}, nil
}