Fix external auth unit tests
This commit is contained in:
@@ -19,6 +19,9 @@ type (
|
||||
|
||||
credentials repository.CredentialsRepository
|
||||
users repository.UserRepository
|
||||
|
||||
providerValidator func(string) error
|
||||
now func() *time.Time
|
||||
}
|
||||
|
||||
AuthService interface {
|
||||
@@ -33,6 +36,11 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
func defaultProviderValidator(provider string) error {
|
||||
_, err := goth.GetProvider(provider)
|
||||
return err
|
||||
}
|
||||
|
||||
func Auth(ctx context.Context) AuthService {
|
||||
return (&auth{}).With(ctx)
|
||||
}
|
||||
@@ -45,6 +53,12 @@ func (svc *auth) With(ctx context.Context) AuthService {
|
||||
|
||||
credentials: repository.Credentials(ctx, db),
|
||||
users: repository.User(ctx, db),
|
||||
|
||||
providerValidator: defaultProviderValidator,
|
||||
now: func() *time.Time {
|
||||
var now = time.Now()
|
||||
return &now
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,9 +66,7 @@ func (svc *auth) With(ctx context.Context) AuthService {
|
||||
//
|
||||
// It does not update user's info
|
||||
func (svc *auth) External(profile goth.User) (u *types.User, err error) {
|
||||
var lastUsedAt = time.Now()
|
||||
|
||||
if _, err := goth.GetProvider(profile.Provider); err != nil {
|
||||
if err = svc.providerValidator(profile.Provider); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -119,23 +131,20 @@ func (svc *auth) External(profile goth.User) (u *types.User, err error) {
|
||||
}
|
||||
|
||||
if u, err = svc.users.Create(u); err != nil {
|
||||
return errors.Wrap(err, "could not create user after successful social auth")
|
||||
return errors.Wrap(err, "could not create user after successful external authentication")
|
||||
}
|
||||
|
||||
log.Printf("Created new user after successful social auth (%v, %v)", u.ID, u.Email)
|
||||
|
||||
// Owner created
|
||||
return nil
|
||||
log.Printf("created new user after successful social auth (%v, %v)", u.ID, u.Email)
|
||||
} else if err != nil {
|
||||
return err
|
||||
} else if !u.Valid() {
|
||||
return errors.Errorf(
|
||||
"Social login to an invalid/suspended user (user ID: %v)",
|
||||
"can not use invalid user (user ID: %v)",
|
||||
u.ID,
|
||||
)
|
||||
} else {
|
||||
log.Printf(
|
||||
"Autheticated user (%v, %v) via %s, existing user",
|
||||
"autheticated user (%v, %v) via %s, existing user",
|
||||
u.ID,
|
||||
u.Email,
|
||||
profile.Provider,
|
||||
@@ -147,7 +156,7 @@ func (svc *auth) External(profile goth.User) (u *types.User, err error) {
|
||||
Kind: profile.Provider,
|
||||
OwnerID: u.ID,
|
||||
Credentials: profile.UserID,
|
||||
LastUsedAt: &lastUsedAt,
|
||||
LastUsedAt: svc.now(),
|
||||
}
|
||||
|
||||
if !profile.ExpiresAt.IsZero() {
|
||||
@@ -160,7 +169,7 @@ func (svc *auth) External(profile goth.User) (u *types.User, err error) {
|
||||
}
|
||||
|
||||
log.Printf(
|
||||
"Creating new credential entry (%v, %v) for exisintg user (%v, %v)",
|
||||
"creating new credential entry (%v, %v) for exisintg user (%v, %v)",
|
||||
c.ID,
|
||||
profile.Provider,
|
||||
u.ID,
|
||||
@@ -172,13 +181,13 @@ func (svc *auth) External(profile goth.User) (u *types.User, err error) {
|
||||
c.ExpiresAt = &profile.ExpiresAt
|
||||
}
|
||||
|
||||
c.LastUsedAt = &lastUsedAt
|
||||
c.LastUsedAt = svc.now()
|
||||
if c, err = svc.credentials.Update(c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf(
|
||||
"Updating credential entry (%v, %v) for exisintg user (%v, %v)",
|
||||
"updating credential entry (%v, %v) for exisintg user (%v, %v)",
|
||||
c.ID,
|
||||
profile.Provider,
|
||||
u.ID,
|
||||
|
||||
@@ -4,6 +4,7 @@ package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/markbates/goth"
|
||||
@@ -14,37 +15,59 @@ import (
|
||||
"github.com/crusttech/crust/system/types"
|
||||
)
|
||||
|
||||
func TestSocialSigninWithExistingCredentials(t *testing.T) {
|
||||
// @todo this mockDB will be probably be used by other tests, move it to some common place
|
||||
type mockDB struct{}
|
||||
|
||||
func (mockDB) Transaction(callback func() error) error { return callback() }
|
||||
|
||||
// Mock auth service with nil for current time, dummy provider validator and mock db
|
||||
func makeMockAuthService(u repository.UserRepository, c repository.CredentialsRepository) *auth {
|
||||
return &auth{
|
||||
db: &mockDB{},
|
||||
users: u,
|
||||
credentials: c,
|
||||
|
||||
providerValidator: func(s string) error {
|
||||
// All providers are valid.
|
||||
return nil
|
||||
},
|
||||
|
||||
now: func() *time.Time {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuth_External_Existing(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
|
||||
// Create some virtual user and credentials
|
||||
var u = &types.User{ID: 300000, Email: "foo@example.tld"}
|
||||
var c = &types.Credentials{ID: 200000, OwnerID: u.ID}
|
||||
|
||||
// Profile to be used. make sure email matches
|
||||
var p = goth.User{UserID: "some-profile-id", Provider: "gplus", Email: u.Email}
|
||||
|
||||
crdRpoMock := repomock.NewMockCredentialsRepository(mockCtrl)
|
||||
crdRpoMock.EXPECT().
|
||||
FindByCredentials("g+", p.UserID).
|
||||
FindByCredentials("gplus", p.UserID).
|
||||
Times(1).
|
||||
Return(types.CredentialsSet{c}, nil)
|
||||
|
||||
usrRpoMock := repomock.NewMockUserRepository(mockCtrl)
|
||||
usrRpoMock.EXPECT().FindByID(u.ID).Times(1).Return(u, nil)
|
||||
|
||||
svc := &auth{
|
||||
db: &mockDB{},
|
||||
users: usrRpoMock,
|
||||
credentials: crdRpoMock,
|
||||
}
|
||||
svc := makeMockAuthService(usrRpoMock, crdRpoMock)
|
||||
|
||||
{
|
||||
auser, err := svc.Social(p)
|
||||
test.Assert(t, err == nil, "Auth.Social error: %+v", err)
|
||||
auser, err := svc.External(p)
|
||||
test.NoError(t, err, "unexpected error from auth.External", err)
|
||||
test.Assert(t, auser.ID == u.ID, "Did not receive expected user")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSocialSigninWithNewUserCredentials(t *testing.T) {
|
||||
func TestAuth_External_NonExisting(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
|
||||
@@ -54,12 +77,12 @@ func TestSocialSigninWithNewUserCredentials(t *testing.T) {
|
||||
|
||||
crdRpoMock := repomock.NewMockCredentialsRepository(mockCtrl)
|
||||
crdRpoMock.EXPECT().
|
||||
FindByCredentials("g+", p.UserID).
|
||||
FindByCredentials("gplus", p.UserID).
|
||||
Times(1).
|
||||
Return(types.CredentialsSet{}, nil)
|
||||
|
||||
crdRpoMock.EXPECT().
|
||||
Create(&types.Credentials{Kind: "g+", OwnerID: u.ID, Credentials: p.UserID}).
|
||||
Create(&types.Credentials{Kind: "gplus", OwnerID: u.ID, Credentials: p.UserID}).
|
||||
Times(1).
|
||||
Return(c, nil)
|
||||
|
||||
@@ -74,15 +97,11 @@ func TestSocialSigninWithNewUserCredentials(t *testing.T) {
|
||||
Times(1).
|
||||
Return(u, nil)
|
||||
|
||||
svc := &auth{
|
||||
db: &mockDB{},
|
||||
users: usrRpoMock,
|
||||
credentials: crdRpoMock,
|
||||
}
|
||||
svc := makeMockAuthService(usrRpoMock, crdRpoMock)
|
||||
|
||||
{
|
||||
auser, err := svc.Social(p)
|
||||
test.Assert(t, err == nil, "Auth.Social error: %+v", err)
|
||||
auser, err := svc.External(p)
|
||||
test.NoError(t, err, "unexpected error from auth.External", err)
|
||||
test.Assert(t, auser.ID == u.ID, "Did not receive expected user")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,6 @@ import (
|
||||
systemMigrate "github.com/crusttech/crust/system/db"
|
||||
)
|
||||
|
||||
type mockDB struct{}
|
||||
|
||||
func (mockDB) Transaction(callback func() error) error { return callback() }
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
dsn := ""
|
||||
flag.StringVar(&dsn, "db-dsn", "crust:crust@tcp(crust-db:3306)/crust?collation=utf8mb4_general_ci", "DSN for database connection")
|
||||
|
||||
Reference in New Issue
Block a user