summaryrefslogtreecommitdiff
path: root/internal/handlers/handler_change_password_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/handlers/handler_change_password_test.go')
-rw-r--r--internal/handlers/handler_change_password_test.go302
1 files changed, 302 insertions, 0 deletions
diff --git a/internal/handlers/handler_change_password_test.go b/internal/handlers/handler_change_password_test.go
new file mode 100644
index 000000000..3783fef8e
--- /dev/null
+++ b/internal/handlers/handler_change_password_test.go
@@ -0,0 +1,302 @@
+package handlers
+
+import (
+ "encoding/json"
+ "fmt"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/suite"
+ "github.com/valyala/fasthttp"
+ "go.uber.org/mock/gomock"
+
+ "github.com/authelia/authelia/v4/internal/authentication"
+
+ "github.com/authelia/authelia/v4/internal/configuration/schema"
+ "github.com/authelia/authelia/v4/internal/middlewares"
+ "github.com/authelia/authelia/v4/internal/mocks"
+)
+
+const (
+ testPasswordOld = "old_password123"
+ testPasswordNew = "new_password456"
+)
+
+type ChangePasswordSuite struct {
+ suite.Suite
+ mock *mocks.MockAutheliaCtx
+}
+
+func (s *ChangePasswordSuite) SetupTest() {
+ s.mock = mocks.NewMockAutheliaCtx(s.T())
+ userSession, err := s.mock.Ctx.GetSession()
+ s.Assert().NoError(err)
+
+ userSession.Username = testUsername
+ userSession.DisplayName = testUsername
+ userSession.Emails[0] = testEmail
+ userSession.AuthenticationMethodRefs.UsernameAndPassword = true
+ s.Assert().NoError(s.mock.Ctx.SaveSession(userSession))
+}
+
+func (s *ChangePasswordSuite) TearDownTest() {
+ s.mock.Close()
+}
+
+func TestChangePasswordPOST_ShouldSucceedWithValidCredentials(t *testing.T) {
+ mock := mocks.NewMockAutheliaCtx(t)
+
+ userSession, err := mock.Ctx.GetSession()
+ assert.NoError(t, err)
+
+ userSession.Username = testUsername
+
+ assert.NoError(t, mock.Ctx.SaveSession(userSession))
+
+ oldPassword := testPasswordOld
+ newPassword := testPasswordNew
+
+ requestBody := changePasswordRequestBody{
+ OldPassword: oldPassword,
+ NewPassword: newPassword,
+ }
+
+ bodyBytes, err := json.Marshal(requestBody)
+ assert.NoError(t, err)
+ mock.Ctx.Request.SetBody(bodyBytes)
+
+ mock.Ctx.Providers.PasswordPolicy = middlewares.NewPasswordPolicyProvider(schema.PasswordPolicy{})
+
+ mock.NotifierMock.EXPECT().
+ Send(mock.Ctx, gomock.Any(), "Password changed successfully", gomock.Any(), gomock.Any()).
+ Return(nil)
+
+ mock.UserProviderMock.EXPECT().
+ ChangePassword(userSession.Username, oldPassword, newPassword).
+ Return(nil)
+
+ mock.UserProviderMock.EXPECT().
+ GetDetails(testUsername).
+ Return(&authentication.UserDetails{
+ Emails: []string{testEmail},
+ }, nil)
+
+ ChangePasswordPOST(mock.Ctx)
+
+ assert.Equal(t, fasthttp.StatusOK, mock.Ctx.Response.StatusCode())
+}
+
+func TestChangePasswordPOST_ShouldFailWhenPasswordPolicyNotMet(t *testing.T) {
+ mock := mocks.NewMockAutheliaCtx(t)
+
+ userSession, err := mock.Ctx.GetSession()
+ assert.NoError(t, err)
+
+ userSession.Username = testUsername
+
+ assert.NoError(t, mock.Ctx.SaveSession(userSession))
+
+ oldPassword := testPasswordOld
+ newPassword := "weak"
+
+ requestBody := changePasswordRequestBody{
+ OldPassword: oldPassword,
+ NewPassword: newPassword,
+ }
+
+ bodyBytes, err := json.Marshal(requestBody)
+ assert.NoError(t, err)
+ mock.Ctx.Request.SetBody(bodyBytes)
+
+ passwordPolicy := middlewares.NewPasswordPolicyProvider(schema.PasswordPolicy{
+ Standard: schema.PasswordPolicyStandard{
+ Enabled: true,
+ MinLength: 8,
+ MaxLength: 64,
+ RequireNumber: true,
+ RequireSpecial: true,
+ RequireUppercase: true,
+ RequireLowercase: true,
+ },
+ })
+
+ mock.Ctx.Providers.PasswordPolicy = passwordPolicy
+
+ ChangePasswordPOST(mock.Ctx)
+
+ errResponse := mock.GetResponseError(t)
+
+ assert.Equal(t, "KO", errResponse.Status)
+ assert.Equal(t, "Your supplied password does not meet the password policy requirements.", errResponse.Message)
+}
+
+func TestChangePasswordPOST_ShouldFailWhenRequestBodyIsInvalid(t *testing.T) {
+ mock := mocks.NewMockAutheliaCtx(t)
+
+ userSession, err := mock.Ctx.GetSession()
+ assert.NoError(t, err)
+
+ userSession.Username = testUsername
+
+ assert.NoError(t, mock.Ctx.SaveSession(userSession))
+
+ mock.Ctx.Request.SetBody([]byte(`{invalid json`))
+
+ ChangePasswordPOST(mock.Ctx)
+
+ errResponse := mock.GetResponseError(t)
+ assert.Equal(t, "KO", errResponse.Status)
+ assert.Equal(t, messageUnableToChangePassword, errResponse.Message)
+}
+
+func TestChangePasswordPOST_ShouldFailWhenOldPasswordIsIncorrect(t *testing.T) {
+ mock := mocks.NewMockAutheliaCtx(t)
+
+ userSession, err := mock.Ctx.GetSession()
+ assert.NoError(t, err)
+
+ userSession.Username = testUsername
+
+ assert.NoError(t, mock.Ctx.SaveSession(userSession))
+
+ oldPassword := testPasswordOld
+ newPassword := testPasswordNew
+
+ requestBody := changePasswordRequestBody{
+ OldPassword: oldPassword,
+ NewPassword: newPassword,
+ }
+
+ bodyBytes, err := json.Marshal(requestBody)
+ assert.NoError(t, err)
+ mock.Ctx.Request.SetBody(bodyBytes)
+
+ mock.Ctx.Providers.PasswordPolicy = middlewares.NewPasswordPolicyProvider(schema.PasswordPolicy{})
+
+ mock.UserProviderMock.EXPECT().
+ ChangePassword(testUsername, oldPassword, newPassword).
+ Return(authentication.ErrIncorrectPassword)
+
+ ChangePasswordPOST(mock.Ctx)
+
+ errResponse := mock.GetResponseError(t)
+ assert.Equal(t, "KO", errResponse.Status)
+ assert.Equal(t, messageIncorrectPassword, errResponse.Message)
+}
+
+func TestChangePasswordPOST_ShouldFailWhenPasswordReuseIsNotAllowed(t *testing.T) {
+ mock := mocks.NewMockAutheliaCtx(t)
+
+ userSession, err := mock.Ctx.GetSession()
+ assert.NoError(t, err)
+
+ userSession.Username = testUsername
+
+ assert.NoError(t, mock.Ctx.SaveSession(userSession))
+
+ oldPassword := testPasswordOld
+ newPassword := testPasswordOld
+
+ requestBody := changePasswordRequestBody{
+ OldPassword: oldPassword,
+ NewPassword: newPassword,
+ }
+
+ bodyBytes, err := json.Marshal(requestBody)
+ assert.NoError(t, err)
+ mock.Ctx.Request.SetBody(bodyBytes)
+
+ mock.Ctx.Providers.PasswordPolicy = middlewares.NewPasswordPolicyProvider(schema.PasswordPolicy{})
+
+ mock.UserProviderMock.EXPECT().
+ ChangePassword(testUsername, oldPassword, newPassword).
+ Return(authentication.ErrPasswordWeak)
+
+ ChangePasswordPOST(mock.Ctx)
+
+ errResponse := mock.GetResponseError(t)
+ assert.Equal(t, "KO", errResponse.Status)
+ assert.Equal(t, messagePasswordWeak, errResponse.Message)
+}
+
+func TestChangePasswordPOST_ShouldSucceedButLogErrorWhenUserHasNoEmail(t *testing.T) {
+ mock := mocks.NewMockAutheliaCtx(t)
+
+ userSession, err := mock.Ctx.GetSession()
+ assert.NoError(t, err)
+
+ userSession.Username = testUsername
+
+ assert.NoError(t, mock.Ctx.SaveSession(userSession))
+
+ oldPassword := testPasswordOld
+ newPassword := testPasswordNew
+
+ requestBody := changePasswordRequestBody{
+ OldPassword: oldPassword,
+ NewPassword: newPassword,
+ }
+
+ bodyBytes, err := json.Marshal(requestBody)
+ assert.NoError(t, err)
+ mock.Ctx.Request.SetBody(bodyBytes)
+
+ mock.Ctx.Providers.PasswordPolicy = middlewares.NewPasswordPolicyProvider(schema.PasswordPolicy{})
+
+ mock.UserProviderMock.EXPECT().
+ ChangePassword(testUsername, oldPassword, newPassword).
+ Return(nil)
+
+ mock.UserProviderMock.EXPECT().
+ GetDetails(testUsername).
+ Return(&authentication.UserDetails{
+ Emails: []string{},
+ }, nil)
+
+ ChangePasswordPOST(mock.Ctx)
+
+ assert.Equal(t, fasthttp.StatusOK, mock.Ctx.Response.StatusCode())
+}
+
+func TestChangePasswordPOST_ShouldSucceedButLogErrorWhenNotificationFails(t *testing.T) {
+ mock := mocks.NewMockAutheliaCtx(t)
+
+ userSession, err := mock.Ctx.GetSession()
+ assert.NoError(t, err)
+
+ userSession.Username = testUsername
+
+ assert.NoError(t, mock.Ctx.SaveSession(userSession))
+
+ oldPassword := testPasswordOld
+ newPassword := testPasswordNew
+
+ requestBody := changePasswordRequestBody{
+ OldPassword: oldPassword,
+ NewPassword: newPassword,
+ }
+
+ bodyBytes, err := json.Marshal(requestBody)
+ assert.NoError(t, err)
+ mock.Ctx.Request.SetBody(bodyBytes)
+
+ mock.Ctx.Providers.PasswordPolicy = middlewares.NewPasswordPolicyProvider(schema.PasswordPolicy{})
+
+ mock.UserProviderMock.EXPECT().
+ ChangePassword(testUsername, testPasswordOld, newPassword).
+ Return(nil)
+
+ mock.UserProviderMock.EXPECT().
+ GetDetails(testUsername).
+ Return(&authentication.UserDetails{
+ Emails: []string{testEmail},
+ }, nil)
+
+ mock.NotifierMock.EXPECT().
+ Send(mock.Ctx, gomock.Any(), "Password changed successfully", gomock.Any(), gomock.Any()).
+ Return(fmt.Errorf("failed to send notification"))
+
+ ChangePasswordPOST(mock.Ctx)
+
+ assert.Equal(t, fasthttp.StatusOK, mock.Ctx.Response.StatusCode())
+}