fix(auth): make login status check case-insensitive
This commit is contained in:
parent
7e0a58feb4
commit
bc7b8f53f4
3 changed files with 110 additions and 3 deletions
|
|
@ -14,6 +14,10 @@ const (
|
||||||
RoleRecruiter = "recruiter"
|
RoleRecruiter = "recruiter"
|
||||||
// RoleCandidate is a job seeker (formerly candidate)
|
// RoleCandidate is a job seeker (formerly candidate)
|
||||||
RoleCandidate = "candidate"
|
RoleCandidate = "candidate"
|
||||||
|
|
||||||
|
// User Status
|
||||||
|
UserStatusActive = "active"
|
||||||
|
UserStatusInactive = "inactive"
|
||||||
)
|
)
|
||||||
|
|
||||||
// User represents a user within a specific Tenant (Company).
|
// User represents a user within a specific Tenant (Company).
|
||||||
|
|
@ -37,7 +41,7 @@ func NewUser(id, tenantID, name, email string) *User {
|
||||||
TenantID: tenantID,
|
TenantID: tenantID,
|
||||||
Name: name,
|
Name: name,
|
||||||
Email: email,
|
Email: email,
|
||||||
Status: "ACTIVE",
|
Status: UserStatusActive,
|
||||||
Roles: []Role{},
|
Roles: []Role{},
|
||||||
CreatedAt: time.Now(),
|
CreatedAt: time.Now(),
|
||||||
UpdatedAt: time.Now(),
|
UpdatedAt: time.Now(),
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,9 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/rede5/gohorsejobs/backend/internal/core/domain/entity"
|
||||||
"github.com/rede5/gohorsejobs/backend/internal/core/dto"
|
"github.com/rede5/gohorsejobs/backend/internal/core/dto"
|
||||||
"github.com/rede5/gohorsejobs/backend/internal/core/ports"
|
"github.com/rede5/gohorsejobs/backend/internal/core/ports"
|
||||||
)
|
)
|
||||||
|
|
@ -46,8 +48,8 @@ func (uc *LoginUseCase) Execute(ctx context.Context, input dto.LoginRequest) (*d
|
||||||
fmt.Printf("[LOGIN DEBUG] Password verification PASSED\n")
|
fmt.Printf("[LOGIN DEBUG] Password verification PASSED\n")
|
||||||
|
|
||||||
// 3. Check Status
|
// 3. Check Status
|
||||||
if user.Status != "ACTIVE" {
|
if !strings.EqualFold(user.Status, entity.UserStatusActive) {
|
||||||
fmt.Printf("[LOGIN DEBUG] Status check FAILED: Expected ACTIVE, got '%s'\n", user.Status)
|
fmt.Printf("[LOGIN DEBUG] Status check FAILED: Expected %s, got '%s'\n", entity.UserStatusActive, user.Status)
|
||||||
return nil, errors.New("account inactive")
|
return nil, errors.New("account inactive")
|
||||||
}
|
}
|
||||||
fmt.Printf("[LOGIN DEBUG] Status check PASSED\n")
|
fmt.Printf("[LOGIN DEBUG] Status check PASSED\n")
|
||||||
|
|
|
||||||
101
backend/internal/core/usecases/auth/login_test.go
Normal file
101
backend/internal/core/usecases/auth/login_test.go
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
package auth_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rede5/gohorsejobs/backend/internal/core/domain/entity"
|
||||||
|
"github.com/rede5/gohorsejobs/backend/internal/core/dto"
|
||||||
|
"github.com/rede5/gohorsejobs/backend/internal/core/usecases/auth"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reuse mocks (could be moved to a shared test helper)
|
||||||
|
// Reposting necessary mocks here for standalone execution if needed,
|
||||||
|
// though if in same package `auth_test` they might conflict if I'm not careful.
|
||||||
|
// Since `register_candidate_test.go` is package `auth_test`, I can reuse `MockUserRepo` if it's in the same package.
|
||||||
|
// But `MockUserRepo` is defined in `register_candidate_test.go`, so it is available to other files in `auth_test` in the same directory?
|
||||||
|
// Yes, Go tests in the same package and directory share symbols.
|
||||||
|
// I will assuming `register_candidate_test.go` provides the mocks.
|
||||||
|
|
||||||
|
func TestLoginUseCase_Execute_StatusCheck(t *testing.T) {
|
||||||
|
// Setup shared mocks
|
||||||
|
authSvc := &MockAuthService{
|
||||||
|
GenerateTokenFunc: func(userID, tenantID string, roles []string) (string, error) {
|
||||||
|
return "mock-token", nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
userStatus string
|
||||||
|
expectError bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Active user (lowercase) - Should Success",
|
||||||
|
userStatus: "active",
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Active user (uppercase) - Should Success",
|
||||||
|
userStatus: "ACTIVE",
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Active user (mixed case) - Should Success",
|
||||||
|
userStatus: "Active",
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Inactive user - Should Fail",
|
||||||
|
userStatus: "inactive",
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Banned user - Should Fail",
|
||||||
|
userStatus: "banned",
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
userRepo := &MockUserRepo{
|
||||||
|
FindByEmailFunc: func(ctx context.Context, email string) (*entity.User, error) {
|
||||||
|
return &entity.User{
|
||||||
|
ID: "user-123",
|
||||||
|
Email: email,
|
||||||
|
PasswordHash: "hashed_pass",
|
||||||
|
Status: tt.userStatus,
|
||||||
|
Roles: []entity.Role{},
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
uc := auth.NewLoginUseCase(userRepo, authSvc)
|
||||||
|
|
||||||
|
input := dto.LoginRequest{
|
||||||
|
Email: "test@example.com",
|
||||||
|
Password: "password",
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := uc.Execute(context.Background(), input)
|
||||||
|
|
||||||
|
if tt.expectError {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Expected error for status '%s', got nil", tt.userStatus)
|
||||||
|
} else if !strings.Contains(err.Error(), "account inactive") {
|
||||||
|
// The actual error message from login.go is "account inactive"
|
||||||
|
t.Errorf("Expected 'account inactive' error, got '%v'", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected success for status '%s', got error: %v", tt.userStatus, err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Error("Expected response, got nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue