test(authentication): add missing tests (#5482)
Signed-off-by: James Elliott <james-d-elliott@users.noreply.github.com>pull/5483/head
parent
f1b3fc7b31
commit
fbbeef3ae8
4
go.mod
4
go.mod
|
@ -11,7 +11,7 @@ require (
|
||||||
github.com/fasthttp/session/v2 v2.5.0
|
github.com/fasthttp/session/v2 v2.5.0
|
||||||
github.com/fsnotify/fsnotify v1.6.0
|
github.com/fsnotify/fsnotify v1.6.0
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.4
|
github.com/go-asn1-ber/asn1-ber v1.5.4
|
||||||
github.com/go-crypt/crypt v0.2.7
|
github.com/go-crypt/crypt v0.2.9
|
||||||
github.com/go-ldap/ldap/v3 v3.4.5-0.20230521105649-cdb0754f6668
|
github.com/go-ldap/ldap/v3 v3.4.5-0.20230521105649-cdb0754f6668
|
||||||
github.com/go-rod/rod v0.113.0
|
github.com/go-rod/rod v0.113.0
|
||||||
github.com/go-sql-driver/mysql v1.7.1
|
github.com/go-sql-driver/mysql v1.7.1
|
||||||
|
@ -70,7 +70,7 @@ require (
|
||||||
github.com/ecordell/optgen v0.0.6 // indirect
|
github.com/ecordell/optgen v0.0.6 // indirect
|
||||||
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
|
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
|
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
|
||||||
github.com/go-crypt/x v0.2.0 // indirect
|
github.com/go-crypt/x v0.2.1 // indirect
|
||||||
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
||||||
github.com/go-webauthn/revoke v0.1.9 // indirect
|
github.com/go-webauthn/revoke v0.1.9 // indirect
|
||||||
github.com/golang/glog v1.0.0 // indirect
|
github.com/golang/glog v1.0.0 // indirect
|
||||||
|
|
6
go.sum
6
go.sum
|
@ -132,8 +132,14 @@ github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||||
github.com/go-crypt/crypt v0.2.7 h1:Ir6E59c1wrskJhpJXMqaynHA2xAxpGN7nQXlLkbpzR0=
|
github.com/go-crypt/crypt v0.2.7 h1:Ir6E59c1wrskJhpJXMqaynHA2xAxpGN7nQXlLkbpzR0=
|
||||||
github.com/go-crypt/crypt v0.2.7/go.mod h1:ulieouNs4qwFCq4wF61oyTQYXAXSoOv995EU4hcHwMU=
|
github.com/go-crypt/crypt v0.2.7/go.mod h1:ulieouNs4qwFCq4wF61oyTQYXAXSoOv995EU4hcHwMU=
|
||||||
|
github.com/go-crypt/crypt v0.2.8 h1:nI4HYMSHpXi68N5/LrhZCV8gDqLcIwtnHs8Xkuipooo=
|
||||||
|
github.com/go-crypt/crypt v0.2.8/go.mod h1:JjzdTYE2mArb6nBoIvvpF7o46/rK/1pfmlArCRMTFUk=
|
||||||
|
github.com/go-crypt/crypt v0.2.9 h1:5gWWTId2Qyqs9ROIsegt5pnqo9wUSRLbhpkR6JSftjg=
|
||||||
|
github.com/go-crypt/crypt v0.2.9/go.mod h1:JjzdTYE2mArb6nBoIvvpF7o46/rK/1pfmlArCRMTFUk=
|
||||||
github.com/go-crypt/x v0.2.0 h1:rHMiKRAu6kFc+xAnQywDb3iHGpvrFbIGXnP3IfCZ+2U=
|
github.com/go-crypt/x v0.2.0 h1:rHMiKRAu6kFc+xAnQywDb3iHGpvrFbIGXnP3IfCZ+2U=
|
||||||
github.com/go-crypt/x v0.2.0/go.mod h1:uLo5o+Cc8nvahDASQpntR1g3ZMUoq2LM/859PkhykC4=
|
github.com/go-crypt/x v0.2.0/go.mod h1:uLo5o+Cc8nvahDASQpntR1g3ZMUoq2LM/859PkhykC4=
|
||||||
|
github.com/go-crypt/x v0.2.1 h1:OGw78Bswme9lffCOX6tyuC280ouU5391glsvThMtM5U=
|
||||||
|
github.com/go-crypt/x v0.2.1/go.mod h1:Q/y9rms7yw4/1CavBlNGn0Itg4HqwNpe1N9FX0TxXrc=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
|
|
@ -23,7 +23,7 @@ import (
|
||||||
type FileUserProvider struct {
|
type FileUserProvider struct {
|
||||||
config *schema.FileAuthenticationBackend
|
config *schema.FileAuthenticationBackend
|
||||||
hash algorithm.Hash
|
hash algorithm.Hash
|
||||||
database *FileUserDatabase
|
database FileUserDatabase
|
||||||
mutex *sync.Mutex
|
mutex *sync.Mutex
|
||||||
timeoutReload time.Time
|
timeoutReload time.Time
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ func NewFileUserProvider(config *schema.FileAuthenticationBackend) (provider *Fi
|
||||||
config: config,
|
config: config,
|
||||||
mutex: &sync.Mutex{},
|
mutex: &sync.Mutex{},
|
||||||
timeoutReload: time.Now().Add(-1 * time.Second),
|
timeoutReload: time.Now().Add(-1 * time.Second),
|
||||||
database: NewFileUserDatabase(config.Path, config.Search.Email, config.Search.CaseInsensitive),
|
database: NewYAMLUserDatabase(config.Path, config.Search.Email, config.Search.CaseInsensitive),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ func (p *FileUserProvider) StartupCheck() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.database == nil {
|
if p.database == nil {
|
||||||
p.database = NewFileUserDatabase(p.config.Path, p.config.Search.Email, p.config.Search.CaseInsensitive)
|
p.database = NewYAMLUserDatabase(p.config.Path, p.config.Search.Email, p.config.Search.CaseInsensitive)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = p.database.Load(); err != nil {
|
if err = p.database.Load(); err != nil {
|
||||||
|
@ -197,10 +197,6 @@ func NewFileCryptoHashFromConfig(config schema.Password) (hash algorithm.Hash, e
|
||||||
return nil, fmt.Errorf("failed to initialize hash settings: %w", err)
|
return nil, fmt.Errorf("failed to initialize hash settings: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = hash.Validate(); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to validate hash settings: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash, nil
|
return hash, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,16 @@ import (
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewFileUserDatabase creates a new FileUserDatabase.
|
type FileUserDatabase interface {
|
||||||
func NewFileUserDatabase(filePath string, searchEmail, searchCI bool) (database *FileUserDatabase) {
|
Save() (err error)
|
||||||
return &FileUserDatabase{
|
Load() (err error)
|
||||||
|
GetUserDetails(username string) (user DatabaseUserDetails, err error)
|
||||||
|
SetUserDetails(username string, details *DatabaseUserDetails)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewYAMLUserDatabase creates a new YAMLUserDatabase.
|
||||||
|
func NewYAMLUserDatabase(filePath string, searchEmail, searchCI bool) (database *YAMLUserDatabase) {
|
||||||
|
return &YAMLUserDatabase{
|
||||||
RWMutex: &sync.RWMutex{},
|
RWMutex: &sync.RWMutex{},
|
||||||
Path: filePath,
|
Path: filePath,
|
||||||
Users: map[string]DatabaseUserDetails{},
|
Users: map[string]DatabaseUserDetails{},
|
||||||
|
@ -25,8 +32,8 @@ func NewFileUserDatabase(filePath string, searchEmail, searchCI bool) (database
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileUserDatabase is a user details database that is concurrency safe database and can be reloaded.
|
// YAMLUserDatabase is a user details database that is concurrency safe database and can be reloaded.
|
||||||
type FileUserDatabase struct {
|
type YAMLUserDatabase struct {
|
||||||
*sync.RWMutex
|
*sync.RWMutex
|
||||||
|
|
||||||
Path string
|
Path string
|
||||||
|
@ -39,7 +46,7 @@ type FileUserDatabase struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the database to disk.
|
// Save the database to disk.
|
||||||
func (m *FileUserDatabase) Save() (err error) {
|
func (m *YAMLUserDatabase) Save() (err error) {
|
||||||
m.RLock()
|
m.RLock()
|
||||||
|
|
||||||
defer m.RUnlock()
|
defer m.RUnlock()
|
||||||
|
@ -52,7 +59,7 @@ func (m *FileUserDatabase) Save() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the database from disk.
|
// Load the database from disk.
|
||||||
func (m *FileUserDatabase) Load() (err error) {
|
func (m *YAMLUserDatabase) Load() (err error) {
|
||||||
yml := &DatabaseModel{Users: map[string]UserDetailsModel{}}
|
yml := &DatabaseModel{Users: map[string]UserDetailsModel{}}
|
||||||
|
|
||||||
if err = yml.Read(m.Path); err != nil {
|
if err = yml.Read(m.Path); err != nil {
|
||||||
|
@ -71,7 +78,7 @@ func (m *FileUserDatabase) Load() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadAliases performs the loading of alias information from the database.
|
// LoadAliases performs the loading of alias information from the database.
|
||||||
func (m *FileUserDatabase) LoadAliases() (err error) {
|
func (m *YAMLUserDatabase) LoadAliases() (err error) {
|
||||||
if m.SearchEmail || m.SearchCI {
|
if m.SearchEmail || m.SearchCI {
|
||||||
for k, user := range m.Users {
|
for k, user := range m.Users {
|
||||||
if m.SearchEmail && user.Email != "" {
|
if m.SearchEmail && user.Email != "" {
|
||||||
|
@ -91,7 +98,7 @@ func (m *FileUserDatabase) LoadAliases() (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *FileUserDatabase) loadAlias(k string) (err error) {
|
func (m *YAMLUserDatabase) loadAlias(k string) (err error) {
|
||||||
u := strings.ToLower(k)
|
u := strings.ToLower(k)
|
||||||
|
|
||||||
if u != k {
|
if u != k {
|
||||||
|
@ -113,7 +120,7 @@ func (m *FileUserDatabase) loadAlias(k string) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *FileUserDatabase) loadAliasEmail(k string, user DatabaseUserDetails) (err error) {
|
func (m *YAMLUserDatabase) loadAliasEmail(k string, user DatabaseUserDetails) (err error) {
|
||||||
e := strings.ToLower(user.Email)
|
e := strings.ToLower(user.Email)
|
||||||
|
|
||||||
var duplicates []string
|
var duplicates []string
|
||||||
|
@ -145,7 +152,7 @@ func (m *FileUserDatabase) loadAliasEmail(k string, user DatabaseUserDetails) (e
|
||||||
|
|
||||||
// GetUserDetails get a DatabaseUserDetails given a username as a value type where the username must be the users actual
|
// GetUserDetails get a DatabaseUserDetails given a username as a value type where the username must be the users actual
|
||||||
// username.
|
// username.
|
||||||
func (m *FileUserDatabase) GetUserDetails(username string) (user DatabaseUserDetails, err error) {
|
func (m *YAMLUserDatabase) GetUserDetails(username string) (user DatabaseUserDetails, err error) {
|
||||||
m.RLock()
|
m.RLock()
|
||||||
|
|
||||||
defer m.RUnlock()
|
defer m.RUnlock()
|
||||||
|
@ -172,7 +179,7 @@ func (m *FileUserDatabase) GetUserDetails(username string) (user DatabaseUserDet
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetUserDetails sets the DatabaseUserDetails for a given user.
|
// SetUserDetails sets the DatabaseUserDetails for a given user.
|
||||||
func (m *FileUserDatabase) SetUserDetails(username string, details *DatabaseUserDetails) {
|
func (m *YAMLUserDatabase) SetUserDetails(username string, details *DatabaseUserDetails) {
|
||||||
if details == nil {
|
if details == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -184,8 +191,8 @@ func (m *FileUserDatabase) SetUserDetails(username string, details *DatabaseUser
|
||||||
m.Unlock()
|
m.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToDatabaseModel converts the FileUserDatabase into the DatabaseModel for saving.
|
// ToDatabaseModel converts the YAMLUserDatabase into the DatabaseModel for saving.
|
||||||
func (m *FileUserDatabase) ToDatabaseModel() (model *DatabaseModel) {
|
func (m *YAMLUserDatabase) ToDatabaseModel() (model *DatabaseModel) {
|
||||||
model = &DatabaseModel{
|
model = &DatabaseModel{
|
||||||
Users: map[string]UserDetailsModel{},
|
Users: map[string]UserDetailsModel{},
|
||||||
}
|
}
|
||||||
|
@ -236,8 +243,8 @@ type DatabaseModel struct {
|
||||||
Users map[string]UserDetailsModel `yaml:"users" valid:"required"`
|
Users map[string]UserDetailsModel `yaml:"users" valid:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadToFileUserDatabase reads the DatabaseModel into a FileUserDatabase.
|
// ReadToFileUserDatabase reads the DatabaseModel into a YAMLUserDatabase.
|
||||||
func (m *DatabaseModel) ReadToFileUserDatabase(db *FileUserDatabase) (err error) {
|
func (m *DatabaseModel) ReadToFileUserDatabase(db *YAMLUserDatabase) (err error) {
|
||||||
users := map[string]DatabaseUserDetails{}
|
users := map[string]DatabaseUserDetails{}
|
||||||
|
|
||||||
var udm *DatabaseUserDetails
|
var udm *DatabaseUserDetails
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
|
// Source: github.com/authelia/authelia/v4/internal/authentication (interfaces: FileUserDatabase)
|
||||||
|
|
||||||
|
// Package authentication is a generated GoMock package.
|
||||||
|
package authentication
|
||||||
|
|
||||||
|
import (
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockFileUserDatabase is a mock of FileUserDatabase interface.
|
||||||
|
type MockFileUserDatabase struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockFileUserDatabaseMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockFileUserDatabaseMockRecorder is the mock recorder for MockFileUserDatabase.
|
||||||
|
type MockFileUserDatabaseMockRecorder struct {
|
||||||
|
mock *MockFileUserDatabase
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockFileUserDatabase creates a new mock instance.
|
||||||
|
func NewMockFileUserDatabase(ctrl *gomock.Controller) *MockFileUserDatabase {
|
||||||
|
mock := &MockFileUserDatabase{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockFileUserDatabaseMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockFileUserDatabase) EXPECT() *MockFileUserDatabaseMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserDetails mocks base method.
|
||||||
|
func (m *MockFileUserDatabase) GetUserDetails(arg0 string) (DatabaseUserDetails, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "GetUserDetails", arg0)
|
||||||
|
ret0, _ := ret[0].(DatabaseUserDetails)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserDetails indicates an expected call of GetUserDetails.
|
||||||
|
func (mr *MockFileUserDatabaseMockRecorder) GetUserDetails(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserDetails", reflect.TypeOf((*MockFileUserDatabase)(nil).GetUserDetails), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load mocks base method.
|
||||||
|
func (m *MockFileUserDatabase) Load() error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Load")
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load indicates an expected call of Load.
|
||||||
|
func (mr *MockFileUserDatabaseMockRecorder) Load() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Load", reflect.TypeOf((*MockFileUserDatabase)(nil).Load))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save mocks base method.
|
||||||
|
func (m *MockFileUserDatabase) Save() error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Save")
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save indicates an expected call of Save.
|
||||||
|
func (mr *MockFileUserDatabaseMockRecorder) Save() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Save", reflect.TypeOf((*MockFileUserDatabase)(nil).Save))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUserDetails mocks base method.
|
||||||
|
func (m *MockFileUserDatabase) SetUserDetails(arg0 string, arg1 *DatabaseUserDetails) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
m.ctrl.Call(m, "SetUserDetails", arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUserDetails indicates an expected call of SetUserDetails.
|
||||||
|
func (mr *MockFileUserDatabaseMockRecorder) SetUserDetails(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetUserDetails", reflect.TypeOf((*MockFileUserDatabase)(nil).SetUserDetails), arg0, arg1)
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
|
// Source: github.com/go-crypt/crypt/algorithm (interfaces: Hash)
|
||||||
|
|
||||||
|
// Package authentication is a generated GoMock package.
|
||||||
|
package authentication
|
||||||
|
|
||||||
|
import (
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
|
algorithm "github.com/go-crypt/crypt/algorithm"
|
||||||
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockHash is a mock of Hash interface.
|
||||||
|
type MockHash struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockHashMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockHashMockRecorder is the mock recorder for MockHash.
|
||||||
|
type MockHashMockRecorder struct {
|
||||||
|
mock *MockHash
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockHash creates a new mock instance.
|
||||||
|
func NewMockHash(ctrl *gomock.Controller) *MockHash {
|
||||||
|
mock := &MockHash{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockHashMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockHash) EXPECT() *MockHashMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash mocks base method.
|
||||||
|
func (m *MockHash) Hash(arg0 string) (algorithm.Digest, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Hash", arg0)
|
||||||
|
ret0, _ := ret[0].(algorithm.Digest)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash indicates an expected call of Hash.
|
||||||
|
func (mr *MockHashMockRecorder) Hash(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Hash", reflect.TypeOf((*MockHash)(nil).Hash), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashWithSalt mocks base method.
|
||||||
|
func (m *MockHash) HashWithSalt(arg0 string, arg1 []byte) (algorithm.Digest, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "HashWithSalt", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].(algorithm.Digest)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashWithSalt indicates an expected call of HashWithSalt.
|
||||||
|
func (mr *MockHashMockRecorder) HashWithSalt(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HashWithSalt", reflect.TypeOf((*MockHash)(nil).HashWithSalt), arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustHash mocks base method.
|
||||||
|
func (m *MockHash) MustHash(arg0 string) algorithm.Digest {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "MustHash", arg0)
|
||||||
|
ret0, _ := ret[0].(algorithm.Digest)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustHash indicates an expected call of MustHash.
|
||||||
|
func (mr *MockHashMockRecorder) MustHash(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MustHash", reflect.TypeOf((*MockHash)(nil).MustHash), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate mocks base method.
|
||||||
|
func (m *MockHash) Validate() error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Validate")
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate indicates an expected call of Validate.
|
||||||
|
func (mr *MockHashMockRecorder) Validate() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Validate", reflect.TypeOf((*MockHash)(nil).Validate))
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/go-crypt/crypt/algorithm/bcrypt"
|
"github.com/go-crypt/crypt/algorithm/bcrypt"
|
||||||
"github.com/go-crypt/crypt/algorithm/pbkdf2"
|
"github.com/go-crypt/crypt/algorithm/pbkdf2"
|
||||||
"github.com/go-crypt/crypt/algorithm/scrypt"
|
"github.com/go-crypt/crypt/algorithm/scrypt"
|
||||||
|
"github.com/golang/mock/gomock"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
@ -129,7 +130,7 @@ func TestShouldReloadDatabase(t *testing.T) {
|
||||||
|
|
||||||
provider.config.Path = p
|
provider.config.Path = p
|
||||||
|
|
||||||
provider.database = NewFileUserDatabase(p, provider.config.Search.Email, provider.config.Search.CaseInsensitive)
|
provider.database = NewYAMLUserDatabase(p, provider.config.Search.Email, provider.config.Search.CaseInsensitive)
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
"",
|
"",
|
||||||
|
@ -306,7 +307,10 @@ func TestShouldUpdatePasswordHashingAlgorithmToArgon2id(t *testing.T) {
|
||||||
|
|
||||||
assert.NoError(t, provider.StartupCheck())
|
assert.NoError(t, provider.StartupCheck())
|
||||||
|
|
||||||
assert.True(t, strings.HasPrefix(provider.database.Users["harry"].Digest.Encode(), "$6$"))
|
db, ok := provider.database.(*YAMLUserDatabase)
|
||||||
|
require.True(t, ok)
|
||||||
|
|
||||||
|
assert.True(t, strings.HasPrefix(db.Users["harry"].Digest.Encode(), "$6$"))
|
||||||
err := provider.UpdatePassword("harry", "newpassword")
|
err := provider.UpdatePassword("harry", "newpassword")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
@ -315,10 +319,10 @@ func TestShouldUpdatePasswordHashingAlgorithmToArgon2id(t *testing.T) {
|
||||||
|
|
||||||
assert.NoError(t, provider.StartupCheck())
|
assert.NoError(t, provider.StartupCheck())
|
||||||
|
|
||||||
ok, err := provider.CheckUserPassword("harry", "newpassword")
|
ok, err = provider.CheckUserPassword("harry", "newpassword")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.True(t, strings.HasPrefix(provider.database.Users["harry"].Digest.Encode(), "$argon2id$"))
|
assert.True(t, strings.HasPrefix(db.Users["harry"].Digest.Encode(), "$argon2id$"))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,7 +337,10 @@ func TestShouldUpdatePasswordHashingAlgorithmToSHA512(t *testing.T) {
|
||||||
|
|
||||||
assert.NoError(t, provider.StartupCheck())
|
assert.NoError(t, provider.StartupCheck())
|
||||||
|
|
||||||
assert.True(t, strings.HasPrefix(provider.database.Users["john"].Digest.Encode(), "$argon2id$"))
|
db, ok := provider.database.(*YAMLUserDatabase)
|
||||||
|
require.True(t, ok)
|
||||||
|
|
||||||
|
assert.True(t, strings.HasPrefix(db.Users["john"].Digest.Encode(), "$argon2id$"))
|
||||||
err := provider.UpdatePassword("john", "newpassword")
|
err := provider.UpdatePassword("john", "newpassword")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
@ -342,10 +349,10 @@ func TestShouldUpdatePasswordHashingAlgorithmToSHA512(t *testing.T) {
|
||||||
|
|
||||||
assert.NoError(t, provider.StartupCheck())
|
assert.NoError(t, provider.StartupCheck())
|
||||||
|
|
||||||
ok, err := provider.CheckUserPassword("john", "newpassword")
|
ok, err = provider.CheckUserPassword("john", "newpassword")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.True(t, strings.HasPrefix(provider.database.Users["john"].Digest.Encode(), "$6$"))
|
assert.True(t, strings.HasPrefix(db.Users["john"].Digest.Encode(), "$6$"))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -657,6 +664,58 @@ func TestNewFileCryptoHashFromConfig(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHashError(t *testing.T) {
|
||||||
|
WithDatabase(t, UserDatabaseContent, func(path string) {
|
||||||
|
config := DefaultFileAuthenticationBackendConfiguration
|
||||||
|
config.Search.CaseInsensitive = true
|
||||||
|
config.Path = path
|
||||||
|
|
||||||
|
provider := NewFileUserProvider(&config)
|
||||||
|
|
||||||
|
assert.NoError(t, provider.StartupCheck())
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
mock := NewMockHash(ctrl)
|
||||||
|
provider.hash = mock
|
||||||
|
|
||||||
|
mock.EXPECT().Hash("apple123").Return(nil, fmt.Errorf("failed to mock hash"))
|
||||||
|
|
||||||
|
assert.EqualError(t, provider.UpdatePassword("john", "apple123"), "failed to mock hash")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDatabaseError(t *testing.T) {
|
||||||
|
WithDatabase(t, UserDatabaseContent, func(path string) {
|
||||||
|
db := NewYAMLUserDatabase(path, false, false)
|
||||||
|
assert.NoError(t, db.Load())
|
||||||
|
|
||||||
|
config := DefaultFileAuthenticationBackendConfiguration
|
||||||
|
config.Search.CaseInsensitive = true
|
||||||
|
config.Path = path
|
||||||
|
|
||||||
|
provider := NewFileUserProvider(&config)
|
||||||
|
|
||||||
|
assert.NoError(t, provider.StartupCheck())
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
mock := NewMockFileUserDatabase(ctrl)
|
||||||
|
|
||||||
|
provider.database = mock
|
||||||
|
|
||||||
|
gomock.InOrder(
|
||||||
|
mock.EXPECT().GetUserDetails("john").Return(db.GetUserDetails("john")),
|
||||||
|
mock.EXPECT().SetUserDetails("john", gomock.Any()),
|
||||||
|
mock.EXPECT().Save().Return(fmt.Errorf("failed to mock save")),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.EqualError(t, provider.UpdatePassword("john", "apple123"), "failed to mock save")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
DefaultFileAuthenticationBackendConfiguration = schema.FileAuthenticationBackend{
|
DefaultFileAuthenticationBackendConfiguration = schema.FileAuthenticationBackend{
|
||||||
Path: "",
|
Path: "",
|
||||||
|
|
|
@ -5,3 +5,5 @@ package authentication
|
||||||
|
|
||||||
//go:generate mockgen -package authentication -destination ldap_client_mock.go -mock_names LDAPClient=MockLDAPClient github.com/authelia/authelia/v4/internal/authentication LDAPClient
|
//go:generate mockgen -package authentication -destination ldap_client_mock.go -mock_names LDAPClient=MockLDAPClient github.com/authelia/authelia/v4/internal/authentication LDAPClient
|
||||||
//go:generate mockgen -package authentication -destination ldap_client_factory_mock.go -mock_names LDAPClientFactory=MockLDAPClientFactory github.com/authelia/authelia/v4/internal/authentication LDAPClientFactory
|
//go:generate mockgen -package authentication -destination ldap_client_factory_mock.go -mock_names LDAPClientFactory=MockLDAPClientFactory github.com/authelia/authelia/v4/internal/authentication LDAPClientFactory
|
||||||
|
//go:generate mockgen -package authentication -destination file_user_provider_database_mock_test.go -mock_names FileUserDatabase=MockFileUserDatabase github.com/authelia/authelia/v4/internal/authentication FileUserDatabase
|
||||||
|
//go:generate mockgen -package authentication -destination file_user_provider_hash_mock_test.go -mock_names Hash=MockHash github.com/go-crypt/crypt/algorithm Hash
|
||||||
|
|
|
@ -154,6 +154,8 @@ func TestIssuerURL(t *testing.T) {
|
||||||
|
|
||||||
func TestShouldCallNextWithAutheliaCtx(t *testing.T) {
|
func TestShouldCallNextWithAutheliaCtx(t *testing.T) {
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
ctx := &fasthttp.RequestCtx{}
|
ctx := &fasthttp.RequestCtx{}
|
||||||
configuration := schema.Configuration{}
|
configuration := schema.Configuration{}
|
||||||
userProvider := mocks.NewMockUserProvider(ctrl)
|
userProvider := mocks.NewMockUserProvider(ctrl)
|
||||||
|
|
Loading…
Reference in New Issue