You've already forked openaccounting-server
mirror of
https://github.com/openaccounting/oa-server.git
synced 2025-12-09 00:50:59 +13:00
initial commit
This commit is contained in:
91
core/auth/auth.go
Normal file
91
core/auth/auth.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/openaccounting/oa-server/core/model/db"
|
||||
"github.com/openaccounting/oa-server/core/model/types"
|
||||
"github.com/openaccounting/oa-server/core/util"
|
||||
)
|
||||
|
||||
var Instance Interface
|
||||
|
||||
type AuthService struct {
|
||||
db db.Datastore
|
||||
bcrypt util.Bcrypt
|
||||
}
|
||||
|
||||
type Interface interface {
|
||||
Authenticate(string, string) (*types.User, error)
|
||||
AuthenticateUser(email string, password string) (*types.User, error)
|
||||
AuthenticateSession(string) (*types.User, error)
|
||||
AuthenticateApiKey(string) (*types.User, error)
|
||||
}
|
||||
|
||||
func NewAuthService(db db.Datastore, bcrypt util.Bcrypt) *AuthService {
|
||||
authService := &AuthService{db: db, 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)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
return nil, errors.New("Unauthorized")
|
||||
}
|
||||
|
||||
func (auth *AuthService) AuthenticateUser(email string, password string) (*types.User, error) {
|
||||
u, err := auth.db.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 *AuthService) AuthenticateSession(id string) (*types.User, error) {
|
||||
u, err := auth.db.GetUserByActiveSession(id)
|
||||
|
||||
if err != nil {
|
||||
return nil, errors.New("Invalid session")
|
||||
}
|
||||
|
||||
auth.db.UpdateSessionActivity(id)
|
||||
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (auth *AuthService) AuthenticateApiKey(id string) (*types.User, error) {
|
||||
u, err := auth.db.GetUserByApiKey(id)
|
||||
|
||||
if err != nil {
|
||||
return nil, errors.New("Access denied")
|
||||
}
|
||||
|
||||
auth.db.UpdateApiKeyActivity(id)
|
||||
|
||||
return u, nil
|
||||
}
|
||||
90
core/auth/auth_test.go
Normal file
90
core/auth/auth_test.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"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 {
|
||||
db.Datastore
|
||||
testNum int
|
||||
}
|
||||
|
||||
func (td *TdUser) GetVerifiedUserByEmail(email string) (*types.User, error) {
|
||||
switch td.testNum {
|
||||
case 1:
|
||||
return td.GetVerifiedUserByEmail_1(email)
|
||||
case 2:
|
||||
return td.GetVerifiedUserByEmail_2(email)
|
||||
}
|
||||
|
||||
return nil, errors.New("test 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,
|
||||
"",
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (td *TdUser) GetVerifiedUserByEmail_2(email string) (*types.User, error) {
|
||||
return nil, errors.New("sql error")
|
||||
}
|
||||
|
||||
func TestAuthenticateUser(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
err error
|
||||
email string
|
||||
password string
|
||||
saltedHash string
|
||||
testNum int
|
||||
}{
|
||||
"successful": {
|
||||
err: nil,
|
||||
email: "johndoe@email.com",
|
||||
password: "password",
|
||||
saltedHash: "$2a$10$KrtvADe7jwrmYIe3GXFbNupOQaPIvyOKeng5826g4VGOD47TpAisG",
|
||||
testNum: 1,
|
||||
},
|
||||
"non-existing user": {
|
||||
err: errors.New("Invalid email or password"),
|
||||
email: "nouser@email.com",
|
||||
password: "password",
|
||||
saltedHash: "",
|
||||
testNum: 2,
|
||||
},
|
||||
"wrong password": {
|
||||
err: errors.New("Invalid email or password"),
|
||||
email: "johndoe@email.com",
|
||||
password: "bad",
|
||||
saltedHash: "$2a$10$KrtvADe7jwrmYIe3GXFbNupOQaPIvyOKeng5826g4VGOD47TpAisG",
|
||||
testNum: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
t.Logf("Running test case: %s", name)
|
||||
|
||||
authService := NewAuthService(&TdUser{testNum: test.testNum}, new(util.StandardBcrypt))
|
||||
|
||||
_, err := authService.AuthenticateUser(test.email, test.password)
|
||||
|
||||
assert.Equal(t, err, test.err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user