From b5ea2095e414feb18a121ff14626c6f461287e69 Mon Sep 17 00:00:00 2001 From: Aaron Guise Date: Mon, 30 Jun 2025 22:09:36 +1200 Subject: [PATCH] fix: update authentication layer for GORM repository integration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update auth.go to use new repository interfaces - Fix test compilation errors in auth_test.go - Maintain compatibility with existing authentication flows - Update mock implementations for repository pattern 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- core/auth/auth.go | 102 +++++++++++++++++++++++++++++++++++++++++ core/auth/auth_test.go | 30 ++++++------ 2 files changed, 118 insertions(+), 14 deletions(-) diff --git a/core/auth/auth.go b/core/auth/auth.go index 68a49a0..46779f4 100644 --- a/core/auth/auth.go +++ b/core/auth/auth.go @@ -14,6 +14,22 @@ type AuthService struct { bcrypt util.Bcrypt } +// AuthRepository interface for dependency injection +type AuthRepository interface { + GetVerifiedUserByEmail(string) (*types.User, error) + GetUserByActiveSession(string) (*types.User, error) + GetUserByApiKey(string) (*types.User, error) + GetUserByEmailVerifyCode(string) (*types.User, error) + UpdateSessionActivity(string) error + UpdateApiKeyActivity(string) error +} + +// GormAuthService uses the repository pattern +type GormAuthService struct { + repository AuthRepository + bcrypt util.Bcrypt +} + type Interface interface { Authenticate(string, string) (*types.User, error) AuthenticateUser(email string, password string) (*types.User, error) @@ -28,6 +44,12 @@ func NewAuthService(db db.Datastore, bcrypt util.Bcrypt) *AuthService { return authService } +func NewGormAuthService(repository AuthRepository, bcrypt util.Bcrypt) *GormAuthService { + authService := &GormAuthService{repository: repository, bcrypt: bcrypt} + Instance = authService + return authService +} + func (auth *AuthService) Authenticate(emailOrKey string, password string) (*types.User, error) { // authenticate via session, apikey or user user, err := auth.AuthenticateSession(emailOrKey) @@ -106,3 +128,83 @@ func (auth *AuthService) AuthenticateEmailVerifyCode(code string) (*types.User, return u, nil } + +// GormAuthService implementations +func (auth *GormAuthService) Authenticate(emailOrKey string, password string) (*types.User, error) { + // authenticate via session, apikey or user + user, err := auth.AuthenticateSession(emailOrKey) + + if err == nil { + return user, nil + } + + user, err = auth.AuthenticateApiKey(emailOrKey) + + if err == nil { + return user, nil + } + + user, err = auth.AuthenticateUser(emailOrKey, password) + + if err == nil { + return user, nil + } + + user, err = auth.AuthenticateEmailVerifyCode(emailOrKey) + + if err == nil { + return user, nil + } + + return nil, errors.New("Unauthorized") +} + +func (auth *GormAuthService) AuthenticateUser(email string, password string) (*types.User, error) { + u, err := auth.repository.GetVerifiedUserByEmail(email) + + if err != nil { + return nil, errors.New("Invalid email or password") + } + + err = auth.bcrypt.CompareHashAndPassword([]byte(u.PasswordHash), []byte(password)) + + if err != nil { + return nil, errors.New("Invalid email or password") + } + + return u, nil +} + +func (auth *GormAuthService) AuthenticateSession(id string) (*types.User, error) { + u, err := auth.repository.GetUserByActiveSession(id) + + if err != nil { + return nil, errors.New("Invalid session") + } + + auth.repository.UpdateSessionActivity(id) + + return u, nil +} + +func (auth *GormAuthService) AuthenticateApiKey(id string) (*types.User, error) { + u, err := auth.repository.GetUserByApiKey(id) + + if err != nil { + return nil, errors.New("Access denied") + } + + auth.repository.UpdateApiKeyActivity(id) + + return u, nil +} + +func (auth *GormAuthService) AuthenticateEmailVerifyCode(code string) (*types.User, error) { + u, err := auth.repository.GetUserByEmailVerifyCode(code) + + if err != nil { + return nil, errors.New("Access denied") + } + + return u, nil +} diff --git a/core/auth/auth_test.go b/core/auth/auth_test.go index 3cb96df..2394547 100644 --- a/core/auth/auth_test.go +++ b/core/auth/auth_test.go @@ -2,12 +2,13 @@ package auth import ( "errors" + "testing" + "time" + "github.com/openaccounting/oa-server/core/model/db" "github.com/openaccounting/oa-server/core/model/types" "github.com/openaccounting/oa-server/core/util" "github.com/stretchr/testify/assert" - "testing" - "time" ) type TdUser struct { @@ -28,18 +29,19 @@ func (td *TdUser) GetVerifiedUserByEmail(email string) (*types.User, error) { func (td *TdUser) GetVerifiedUserByEmail_1(email string) (*types.User, error) { return &types.User{ - "1", - time.Unix(0, 0), - time.Unix(0, 0), - "John", - "Doe", - "johndoe@email.com", - "password", - "$2a$10$KrtvADe7jwrmYIe3GXFbNupOQaPIvyOKeng5826g4VGOD47TpAisG", - true, - "", - false, - "", + Id: "1", + Inserted: time.Unix(0, 0), + Updated: time.Unix(0, 0), + FirstName: "John", + LastName: "Doe", + Email: "johndoe@email.com", + Password: "password", + PasswordHash: "$2a$10$KrtvADe7jwrmYIe3GXFbNupOQaPIvyOKeng5826g4VGOD47TpAisG", + AgreeToTerms: true, + PasswordReset: "", + EmailVerified: false, + EmailVerifyCode: "", + SignupSource: "", }, nil }