authelia/internal/handlers/handler_user_info_test.go

247 lines
6.6 KiB
Go
Raw Normal View History

package handlers
import (
"fmt"
"testing"
"github.com/golang/mock/gomock"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"github.com/authelia/authelia/v4/internal/mocks"
"github.com/authelia/authelia/v4/internal/storage"
)
type FetchSuite struct {
suite.Suite
mock *mocks.MockAutheliaCtx
}
func (s *FetchSuite) SetupTest() {
s.mock = mocks.NewMockAutheliaCtx(s.T())
2020-01-05 23:03:16 +00:00
// Set the initial user session.
userSession := s.mock.Ctx.GetSession()
userSession.Username = testUsername
userSession.AuthenticationLevel = 1
err := s.mock.Ctx.SaveSession(userSession)
require.NoError(s.T(), err)
}
func (s *FetchSuite) TearDownTest() {
s.mock.Close()
}
func setPreferencesExpectations(preferences UserInfo, provider *storage.MockProvider) {
2019-12-07 17:51:47 +00:00
provider.
EXPECT().
2020-01-05 23:03:16 +00:00
LoadPreferred2FAMethod(gomock.Eq("john")).
Return(preferences.Method, nil)
if preferences.HasU2F {
2019-12-07 17:51:47 +00:00
u2fData := []byte("abc")
provider.
EXPECT().
LoadU2FDeviceHandle(gomock.Eq("john")).
Return(u2fData, u2fData, nil)
} else {
provider.
EXPECT().
LoadU2FDeviceHandle(gomock.Eq("john")).
Return(nil, nil, storage.ErrNoU2FDeviceHandle)
}
if preferences.HasTOTP {
2019-12-07 17:51:47 +00:00
totpSecret := "secret"
provider.
EXPECT().
LoadTOTPSecret(gomock.Eq("john")).
Return(totpSecret, nil)
} else {
provider.
EXPECT().
LoadTOTPSecret(gomock.Eq("john")).
Return("", storage.ErrNoTOTPSecret)
}
}
2019-12-07 17:51:47 +00:00
func TestMethodSetToU2F(t *testing.T) {
table := []UserInfo{
{
Method: "totp",
},
{
Method: "u2f",
HasU2F: true,
HasTOTP: true,
},
{
Method: "u2f",
HasU2F: true,
HasTOTP: false,
},
{
2019-12-07 17:51:47 +00:00
Method: "mobile_push",
HasU2F: false,
HasTOTP: false,
},
}
for _, expectedPreferences := range table {
2019-12-07 17:51:47 +00:00
mock := mocks.NewMockAutheliaCtx(t)
2020-01-05 23:03:16 +00:00
// Set the initial user session.
2019-12-07 17:51:47 +00:00
userSession := mock.Ctx.GetSession()
userSession.Username = testUsername
2019-12-07 17:51:47 +00:00
userSession.AuthenticationLevel = 1
err := mock.Ctx.SaveSession(userSession)
require.NoError(t, err)
2019-12-07 17:51:47 +00:00
setPreferencesExpectations(expectedPreferences, mock.StorageProviderMock)
UserInfoGet(mock.Ctx)
actualPreferences := UserInfo{}
2019-12-07 17:51:47 +00:00
mock.GetResponseData(t, &actualPreferences)
2019-12-07 17:51:47 +00:00
t.Run("expected method", func(t *testing.T) {
assert.Equal(t, expectedPreferences.Method, actualPreferences.Method)
})
2019-12-07 17:51:47 +00:00
t.Run("registered u2f", func(t *testing.T) {
assert.Equal(t, expectedPreferences.HasU2F, actualPreferences.HasU2F)
})
2019-12-07 17:51:47 +00:00
t.Run("registered totp", func(t *testing.T) {
assert.Equal(t, expectedPreferences.HasTOTP, actualPreferences.HasTOTP)
})
2019-12-07 17:51:47 +00:00
mock.Close()
}
}
func (s *FetchSuite) TestShouldGetDefaultPreferenceIfNotInDB() {
s.mock.StorageProviderMock.
EXPECT().
2020-01-05 23:03:16 +00:00
LoadPreferred2FAMethod(gomock.Eq("john")).
Return("", nil)
s.mock.StorageProviderMock.
EXPECT().
LoadU2FDeviceHandle(gomock.Eq("john")).
2019-12-07 17:51:47 +00:00
Return(nil, nil, storage.ErrNoU2FDeviceHandle)
s.mock.StorageProviderMock.
EXPECT().
LoadTOTPSecret(gomock.Eq("john")).
2019-12-07 17:51:47 +00:00
Return("", storage.ErrNoTOTPSecret)
UserInfoGet(s.mock.Ctx)
s.mock.Assert200OK(s.T(), UserInfo{Method: "totp"})
}
func (s *FetchSuite) TestShouldReturnError500WhenStorageFailsToLoad() {
s.mock.StorageProviderMock.EXPECT().
2020-01-05 23:03:16 +00:00
LoadPreferred2FAMethod(gomock.Eq("john")).
Return("", fmt.Errorf("Failure"))
2019-12-07 17:51:47 +00:00
s.mock.StorageProviderMock.
EXPECT().
LoadU2FDeviceHandle(gomock.Eq("john"))
s.mock.StorageProviderMock.
EXPECT().
LoadTOTPSecret(gomock.Eq("john"))
UserInfoGet(s.mock.Ctx)
s.mock.Assert200KO(s.T(), "Operation failed.")
assert.Equal(s.T(), "unable to load user information", s.mock.Hook.LastEntry().Message)
assert.Equal(s.T(), logrus.ErrorLevel, s.mock.Hook.LastEntry().Level)
}
func TestFetchSuite(t *testing.T) {
suite.Run(t, &FetchSuite{})
}
type SaveSuite struct {
suite.Suite
mock *mocks.MockAutheliaCtx
}
func (s *SaveSuite) SetupTest() {
s.mock = mocks.NewMockAutheliaCtx(s.T())
2020-01-05 23:03:16 +00:00
// Set the initial user session.
userSession := s.mock.Ctx.GetSession()
userSession.Username = testUsername
userSession.AuthenticationLevel = 1
err := s.mock.Ctx.SaveSession(userSession)
require.NoError(s.T(), err)
}
func (s *SaveSuite) TearDownTest() {
s.mock.Close()
}
func (s *SaveSuite) TestShouldReturnError500WhenNoBodyProvided() {
s.mock.Ctx.Request.SetBody(nil)
MethodPreferencePost(s.mock.Ctx)
s.mock.Assert200KO(s.T(), "Operation failed.")
assert.Equal(s.T(), "Unable to parse body: unexpected end of JSON input", s.mock.Hook.LastEntry().Message)
assert.Equal(s.T(), logrus.ErrorLevel, s.mock.Hook.LastEntry().Level)
}
func (s *SaveSuite) TestShouldReturnError500WhenMalformedBodyProvided() {
s.mock.Ctx.Request.SetBody([]byte("{\"method\":\"abc\""))
MethodPreferencePost(s.mock.Ctx)
s.mock.Assert200KO(s.T(), "Operation failed.")
assert.Equal(s.T(), "Unable to parse body: unexpected end of JSON input", s.mock.Hook.LastEntry().Message)
assert.Equal(s.T(), logrus.ErrorLevel, s.mock.Hook.LastEntry().Level)
}
func (s *SaveSuite) TestShouldReturnError500WhenBadBodyProvided() {
s.mock.Ctx.Request.SetBody([]byte("{\"weird_key\":\"abc\"}"))
MethodPreferencePost(s.mock.Ctx)
s.mock.Assert200KO(s.T(), "Operation failed.")
assert.Equal(s.T(), "Unable to validate body: method: non zero value required", s.mock.Hook.LastEntry().Message)
assert.Equal(s.T(), logrus.ErrorLevel, s.mock.Hook.LastEntry().Level)
}
func (s *SaveSuite) TestShouldReturnError500WhenBadMethodProvided() {
s.mock.Ctx.Request.SetBody([]byte("{\"method\":\"abc\"}"))
MethodPreferencePost(s.mock.Ctx)
s.mock.Assert200KO(s.T(), "Operation failed.")
assert.Equal(s.T(), "unknown method 'abc', it should be one of totp, u2f, mobile_push", s.mock.Hook.LastEntry().Message)
assert.Equal(s.T(), logrus.ErrorLevel, s.mock.Hook.LastEntry().Level)
}
func (s *SaveSuite) TestShouldReturnError500WhenDatabaseFailsToSave() {
s.mock.Ctx.Request.SetBody([]byte("{\"method\":\"u2f\"}"))
s.mock.StorageProviderMock.EXPECT().
2020-01-05 23:03:16 +00:00
SavePreferred2FAMethod(gomock.Eq("john"), gomock.Eq("u2f")).
Return(fmt.Errorf("Failure"))
MethodPreferencePost(s.mock.Ctx)
s.mock.Assert200KO(s.T(), "Operation failed.")
assert.Equal(s.T(), "unable to save new preferred 2FA method: Failure", s.mock.Hook.LastEntry().Message)
assert.Equal(s.T(), logrus.ErrorLevel, s.mock.Hook.LastEntry().Level)
}
func (s *SaveSuite) TestShouldReturn200WhenMethodIsSuccessfullySaved() {
s.mock.Ctx.Request.SetBody([]byte("{\"method\":\"u2f\"}"))
s.mock.StorageProviderMock.EXPECT().
2020-01-05 23:03:16 +00:00
SavePreferred2FAMethod(gomock.Eq("john"), gomock.Eq("u2f")).
Return(nil)
MethodPreferencePost(s.mock.Ctx)
assert.Equal(s.T(), 200, s.mock.Ctx.Response.StatusCode())
}
func TestSaveSuite(t *testing.T) {
suite.Run(t, &SaveSuite{})
}