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) {
|
||||
args := m.Called(s)
|
||||
if args.Get(0) == nil {
|
||||
return nil, args.Error(1)
|
||||
}
|
||||
return args.Get(0).(*models.User), args.Error(1)
|
||||
}
|
||||
|
||||
|
||||
@@ -106,10 +106,13 @@ func (h *LoginHandler) PostLogin(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
user, err := h.userSrvc.GetUserById(login.Username)
|
||||
if err != nil {
|
||||
// try to get by email if given username is an email address (checked inside service)
|
||||
if user, err = h.userSrvc.GetUserByEmail(login.Username); err != nil {
|
||||
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) {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
|
||||
@@ -162,6 +162,7 @@ func (suite *LoginHandlerTestSuite) TestPostLogin_NonExistingUser() {
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
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.Sut.PostLogin(w, r)
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
"github.com/gofrs/uuid/v5"
|
||||
"github.com/leandro-lugaresi/hub"
|
||||
"github.com/patrickmn/go-cache"
|
||||
@@ -127,6 +128,9 @@ func (srv *UserService) GetUserByEmail(email string) (*models.User, error) {
|
||||
if email == "" {
|
||||
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})
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,38 @@ func TestUserServiceTestSuite(t *testing.T) {
|
||||
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() {
|
||||
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