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 }