refactoring login process

This commit is contained in:
Lars Hoogestraat 2018-09-06 14:21:20 +02:00
parent da85c6fce8
commit 81d1025f04
11 changed files with 82 additions and 60 deletions

View File

@ -84,6 +84,23 @@ func ValueRequired(param string) *Error {
}
}
func Equals(a error, b error) bool {
v, ok := a.(*Error)
v2, ok2 := b.(*Error)
if ok && ok2 {
return v.Err == v2.Err
} else if !ok && !ok2 {
return v == v2
} else if ok && !ok2 {
return v.Err == b
} else if !ok && ok2 {
return a == v2.Err
}
return false
}
func (e Error) Error() string {
return fmt.Sprintf("code=[%d], error=[%s], displayMsg=[%s]", e.HTTPStatus, e.Err.Error(), e.DisplayMsg)
}

View File

@ -58,3 +58,7 @@ func (s Service) Send(m Mail) error {
return smtp.SendMail(fmt.Sprintf("%s:%d", s.SMTPConfig.Address, s.SMTPConfig.Port), auth, s.From, []string{m.To}, m.buildMessage(s))
}
func (s Service) SendAsync(m Mail) chan error {
return nil
}

View File

@ -271,14 +271,21 @@ func ForgotPasswordPostHandler(ctx *middleware.AppContext, w http.ResponseWriter
u, err := ctx.UserService.GetUserByMail(email)
if err != nil {
return &middleware.Template{
Name: tplAdminForgotPassword,
Err: err,
Data: map[string]interface{}{
"user": models.User{
Email: email,
if httperror.Equals(err, sql.ErrNoRows) {
return &middleware.Template{
RedirectPath: "admin",
SuccessMsg: "An email with password reset instructions is on the way.",
}
} else {
return &middleware.Template{
Name: tplAdminForgotPassword,
Err: err,
Data: map[string]interface{}{
"user": models.User{
Email: email,
},
},
},
}
}
}

View File

@ -4,6 +4,7 @@ import (
"fmt"
"net/http"
"git.hoogi.eu/go-blog/components/logger"
"git.hoogi.eu/go-blog/middleware"
"git.hoogi.eu/go-blog/models"
)
@ -39,6 +40,12 @@ func AdminUserInviteNewPostHandler(ctx *middleware.AppContext, w http.ResponseWr
}
}
err = ctx.Mailer.SendActivationLink(ui)
if err != nil {
logger.Log.Error(err)
}
return &middleware.Template{
RedirectPath: "admin/users",
Active: "users",
@ -51,6 +58,7 @@ func AdminUserInviteNewPostHandler(ctx *middleware.AppContext, w http.ResponseWr
func AdminUserInviteDeleteHandler(ctx *middleware.AppContext, w http.ResponseWriter, r *http.Request) *middleware.Template {
inviteID, err := parseInt(getVar(r, "inviteID"))
if err != nil {
return &middleware.Template{
RedirectPath: "admin/user-invite",

View File

@ -7,9 +7,6 @@ package controllers
import (
"net/http"
"golang.org/x/crypto/bcrypt"
"git.hoogi.eu/go-blog/components/httperror"
"git.hoogi.eu/go-blog/middleware"
"git.hoogi.eu/go-blog/models"
)
@ -49,39 +46,20 @@ func LoginPostHandler(ctx *middleware.AppContext, rw http.ResponseWriter, r *htt
redirectTo = "admin/articles"
}
user := &models.User{
u := &models.User{
Username: username,
Email: username,
}
user, err := ctx.UserService.Authenticate(user, ctx.ConfigService.LoginMethod, password)
user, err := ctx.UserService.Authenticate(u, ctx.ConfigService.LoginMethod, password)
if err != nil {
//Do some extra work
if user == nil {
bcrypt.CompareHashAndPassword([]byte("$2a$12$bQlRnXTNZMp6kCyoAlnf3uZW5vtmSj9CHP7pYplRUVK2n0C5xBHBa"), password)
}
hErr, ok := err.(*httperror.Error)
if ok {
return &middleware.Template{
Name: tplAdminLogin,
Err: httperror.New(http.StatusUnauthorized, "Your username or password is invalid.", hErr.Err),
Data: map[string]interface{}{
"user": models.User{
Username: username,
},
},
}
}
return &middleware.Template{
Name: tplAdminLogin,
Err: httperror.New(http.StatusUnauthorized, "Your username or password is invalid.", err),
Name: tplAdminLogin,
Active: "users",
Err: err,
Data: map[string]interface{}{
"user": models.User{
Username: username,
},
"user": u,
},
}
}

View File

@ -87,8 +87,6 @@ func AdminUserNewPostHandler(ctx *middleware.AppContext, w http.ResponseWriter,
IsAdmin: convertCheckbox(r, "admin"),
}
sendRegLink := convertCheckbox(r, "active")
userID, err := ctx.UserService.CreateUser(u)
if err != nil {
return &middleware.Template{
@ -101,10 +99,6 @@ func AdminUserNewPostHandler(ctx *middleware.AppContext, w http.ResponseWriter,
}
}
if sendRegLink {
}
return &middleware.Template{
RedirectPath: "admin/users",
Active: "users",

View File

@ -13,6 +13,18 @@ type Mailer struct {
MailService *mail.Service
}
func (m Mailer) SendActivationLink(ui *UserInvite) error {
activation := utils.AppendString(m.AppConfig.Domain, "/admin/activate-account/", ui.Hash)
mail := mail.Mail{
To: ui.Email,
Subject: "Password change",
Body: fmt.Sprintf("Hi %s, \n\n you are invited join %s. Please click the following link to enter a password and activate your account: %s", ui.DisplayName, activation),
}
return m.MailService.Send(mail)
}
func (m Mailer) SendPasswordChangeConfirmation(u *User) error {
mail := mail.Mail{
To: u.Email,

Binary file not shown.

View File

@ -189,7 +189,7 @@ func (us UserService) GetUserByUsername(username string) (*User, error) {
u, err := us.Datasource.GetByUsername(username)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperror.NotFound("user", fmt.Errorf("the user with username %s was not found", username))
return nil, httperror.NotFound("user", err)
}
return nil, err
}
@ -203,8 +203,10 @@ func (us UserService) GetUserByMail(mail string) (*User, error) {
if err != nil {
if err == sql.ErrNoRows {
return nil, httperror.NotFound("user", fmt.Errorf("the user with mail %s was not found", mail))
return nil, httperror.NotFound("user", err)
}
return nil, err
}
return u, nil
}
@ -332,18 +334,30 @@ func (us UserService) Authenticate(u *User, loginMethod settings.LoginMethod, pa
var err error
if loginMethod == settings.EMail {
u, err = us.GetUserByMail(u.Email)
u, err = us.Datasource.GetByMail(u.Email)
} else {
u, err = us.GetUserByUsername(u.Username)
u, err = us.Datasource.GetByUsername(u.Username)
}
if err != nil {
if err == sql.ErrNoRows {
//Do some extra work
bcrypt.CompareHashAndPassword([]byte("$2a$12$bQlRnXTNZMp6kCyoAlnf3uZW5vtmSj9CHP7pYplRUVK2n0C5xBHBa"), password)
return nil, httperror.New(http.StatusUnauthorized, "Your username or password is invalid.", err)
}
return nil, err
}
if err := u.comparePassword(password); err != nil {
return u, err
return u, httperror.New(http.StatusUnauthorized, "Your username or password is invalid.", err)
}
if !u.Active {
return nil, httperror.New(http.StatusUnprocessableEntity,
"Your account is deactivated.",
fmt.Errorf("the user with id %d tried to logged in but the account is deactivated", u.ID))
}
return u, nil
}

View File

@ -69,18 +69,6 @@ func (uis UserInviteService) CreateUserInvite(ui *UserInvite) (int, error) {
return -1, err
}
// go func(ui UserInvite) {
// m := mail.Mail{
// To: ui.Email,
// Subject: "User invitation",
// Body: fmt.Sprintf("Hi %s, \n\n you received an invitation to join %s.", ui.DisplayName),
// }
// err = ctx.MailService.Send(m)
// logger.Log.Errorf("could not send invitation %v", err)
// }(ui, appCfg)
return uis.Datasource.Create(ui)
}

View File

@ -68,7 +68,7 @@ func (rdb SQLiteUserDatasource) Get(userID int) (*User, error) {
func (rdb SQLiteUserDatasource) GetByMail(mail string) (*User, error) {
var u User
if err := rdb.SQLConn.QueryRow("SELECT rowid, is_admin, active, display_name, username, email, salt, password FROM user WHERE email=? AND active='1' ", mail).
if err := rdb.SQLConn.QueryRow("SELECT rowid, is_admin, active, display_name, username, email, salt, password FROM user WHERE email=? ", mail).
Scan(&u.ID, &u.IsAdmin, &u.Active, &u.DisplayName, &u.Username, &u.Email, &u.Salt, &u.Password); err != nil {
return nil, err
}
@ -79,7 +79,7 @@ func (rdb SQLiteUserDatasource) GetByMail(mail string) (*User, error) {
func (rdb SQLiteUserDatasource) GetByUsername(username string) (*User, error) {
var u User
if err := rdb.SQLConn.QueryRow("SELECT rowid, is_admin, active, display_name, username, email, salt, password FROM user WHERE username=? AND active='1' ", username).
if err := rdb.SQLConn.QueryRow("SELECT rowid, is_admin, active, display_name, username, email, salt, password FROM user WHERE username=? ", username).
Scan(&u.ID, &u.IsAdmin, &u.Active, &u.DisplayName, &u.Username, &u.Email, &u.Salt, &u.Password); err != nil {
return nil, err
}