mirror of
https://github.com/muety/wakapi.git
synced 2025-12-05 22:20:24 -08:00
chore: allow to log in via email address as a fallback (resolve #878)
This commit is contained in:
@@ -28,6 +28,9 @@ func (m *UserServiceMock) GetUserByKey(s string, r bool) (*models.User, error) {
|
|||||||
|
|
||||||
func (m *UserServiceMock) GetUserByEmail(s string) (*models.User, error) {
|
func (m *UserServiceMock) GetUserByEmail(s string) (*models.User, error) {
|
||||||
args := m.Called(s)
|
args := m.Called(s)
|
||||||
|
if args.Get(0) == nil {
|
||||||
|
return nil, args.Error(1)
|
||||||
|
}
|
||||||
return args.Get(0).(*models.User), args.Error(1)
|
return args.Get(0).(*models.User), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,9 +106,12 @@ func (h *LoginHandler) PostLogin(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
user, err := h.userSrvc.GetUserById(login.Username)
|
user, err := h.userSrvc.GetUserById(login.Username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusNotFound)
|
// try to get by email if given username is an email address (checked inside service)
|
||||||
templates[conf.LoginTemplate].Execute(w, h.buildViewModel(r, w, false).WithError("resource not found"))
|
if user, err = h.userSrvc.GetUserByEmail(login.Username); err != nil {
|
||||||
return
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
templates[conf.LoginTemplate].Execute(w, h.buildViewModel(r, w, false).WithError("resource not found"))
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !utils.ComparePassword(user.Password, login.Password, h.config.Security.PasswordSalt) {
|
if !utils.ComparePassword(user.Password, login.Password, h.config.Security.PasswordSalt) {
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ func (suite *LoginHandlerTestSuite) TestPostLogin_NonExistingUser() {
|
|||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
suite.UserService.On("GetUserById", "nonexisting").Return(nil, errors.New(""))
|
suite.UserService.On("GetUserById", "nonexisting").Return(nil, errors.New(""))
|
||||||
|
suite.UserService.On("GetUserByEmail", "nonexisting").Return(nil, errors.New(""))
|
||||||
suite.UserService.On("Count").Return(1, nil)
|
suite.UserService.On("Count").Return(1, nil)
|
||||||
|
|
||||||
suite.Sut.PostLogin(w, r)
|
suite.Sut.PostLogin(w, r)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/duke-git/lancet/v2/convertor"
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
"github.com/duke-git/lancet/v2/datetime"
|
"github.com/duke-git/lancet/v2/datetime"
|
||||||
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
"github.com/gofrs/uuid/v5"
|
"github.com/gofrs/uuid/v5"
|
||||||
"github.com/leandro-lugaresi/hub"
|
"github.com/leandro-lugaresi/hub"
|
||||||
"github.com/patrickmn/go-cache"
|
"github.com/patrickmn/go-cache"
|
||||||
@@ -127,6 +128,9 @@ func (srv *UserService) GetUserByEmail(email string) (*models.User, error) {
|
|||||||
if email == "" {
|
if email == "" {
|
||||||
return nil, errors.New("email must not be empty")
|
return nil, errors.New("email must not be empty")
|
||||||
}
|
}
|
||||||
|
if !validator.IsEmail(email) {
|
||||||
|
return nil, errors.New("not a valid email")
|
||||||
|
}
|
||||||
return srv.repository.FindOne(models.User{Email: email})
|
return srv.repository.FindOne(models.User{Email: email})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,38 @@ func TestUserServiceTestSuite(t *testing.T) {
|
|||||||
suite.Run(t, new(UserServiceTestSuite))
|
suite.Run(t, new(UserServiceTestSuite))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *UserServiceTestSuite) TestUserService_GetByEmail_Empty() {
|
||||||
|
sut := NewUserService(suite.KeyValueService, suite.MailService, suite.ApiKeyService, suite.UserRepo)
|
||||||
|
|
||||||
|
result, err := sut.GetUserByEmail("")
|
||||||
|
|
||||||
|
suite.Nil(result)
|
||||||
|
suite.NotNil(err)
|
||||||
|
suite.Equal(err, errors.New("email must not be empty"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *UserServiceTestSuite) TestUserService_GetByEmail_Invalid() {
|
||||||
|
sut := NewUserService(suite.KeyValueService, suite.MailService, suite.ApiKeyService, suite.UserRepo)
|
||||||
|
|
||||||
|
result, err := sut.GetUserByEmail("notanemailaddress")
|
||||||
|
|
||||||
|
suite.Nil(result)
|
||||||
|
suite.NotNil(err)
|
||||||
|
suite.Equal(err, errors.New("not a valid email"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *UserServiceTestSuite) TestUserService_GetByEmail_Valid() {
|
||||||
|
const testEmail = "foo@bar.com"
|
||||||
|
|
||||||
|
suite.UserRepo.On("FindOne", models.User{Email: testEmail}).Return(suite.TestUser, nil)
|
||||||
|
|
||||||
|
sut := NewUserService(suite.KeyValueService, suite.MailService, suite.ApiKeyService, suite.UserRepo)
|
||||||
|
result, err := sut.GetUserByEmail(testEmail)
|
||||||
|
|
||||||
|
suite.Equal(suite.TestUser, result)
|
||||||
|
suite.Nil(err)
|
||||||
|
}
|
||||||
|
|
||||||
func (suite *UserServiceTestSuite) TestUserService_GetByEmptyKey_Failed() {
|
func (suite *UserServiceTestSuite) TestUserService_GetByEmptyKey_Failed() {
|
||||||
sut := NewUserService(suite.KeyValueService, suite.MailService, suite.ApiKeyService, suite.UserRepo)
|
sut := NewUserService(suite.KeyValueService, suite.MailService, suite.ApiKeyService, suite.UserRepo)
|
||||||
|
|
||||||
|
|||||||
32
testing/wakapi_api_tests/Auth/Login (by email).bru
Normal file
32
testing/wakapi_api_tests/Auth/Login (by email).bru
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
meta {
|
||||||
|
name: Login (by email)
|
||||||
|
type: http
|
||||||
|
seq: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: {{BASE_URL}}/login
|
||||||
|
body: formUrlEncoded
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
|
|
||||||
|
body:form-urlencoded {
|
||||||
|
username: testuser@wakapi.dev
|
||||||
|
password: testpassword
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {
|
||||||
|
res.status: eq 302
|
||||||
|
res.headers['location']: eq /summary
|
||||||
|
}
|
||||||
|
|
||||||
|
script:pre-request {
|
||||||
|
// Do not follow 3xx redirects
|
||||||
|
req.setMaxRedirects(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
tests {
|
||||||
|
test("Sets cookie", function () {
|
||||||
|
expect(res.headers["set-cookie"].some(str => str.includes("wakapi_auth="))).to.be.true
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user