mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-17 00:12:11 +08:00
add email verification
This commit is contained in:
@@ -52,7 +52,7 @@ func (s *ForgetPasswordService) SendPasswordResetEmail(c *core.Context, user *mo
|
||||
expireTimeInMinutes := s.CurrentConfig().PasswordResetTokenExpiredTimeDuration.Minutes()
|
||||
passwordResetUrl := fmt.Sprintf(passwordResetUrlFormat, s.CurrentConfig().RootUrl, url.QueryEscape(passwordResetToken))
|
||||
|
||||
tmpl, err := templates.GetTemplate("email/password_reset")
|
||||
tmpl, err := templates.GetTemplate(templates.TEMPLATE_PASSWORD_RESET)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -88,6 +88,11 @@ func (s *TokenService) CreateRequire2FAToken(c *core.Context, user *models.User)
|
||||
return s.createToken(c, user, core.USER_TOKEN_TYPE_REQUIRE_2FA, s.getUserAgent(c), s.CurrentConfig().TemporaryTokenExpiredTimeDuration)
|
||||
}
|
||||
|
||||
// CreateEmailVerifyToken generates a new email verify token and saves to database
|
||||
func (s *TokenService) CreateEmailVerifyToken(c *core.Context, user *models.User) (string, *core.UserTokenClaims, error) {
|
||||
return s.createToken(c, user, core.USER_TOKEN_TYPE_EMAIL_VERIFY, s.getUserAgent(c), s.CurrentConfig().EmailVerifyTokenExpiredTimeDuration)
|
||||
}
|
||||
|
||||
// CreatePasswordResetToken generates a new password reset token and saves to database
|
||||
func (s *TokenService) CreatePasswordResetToken(c *core.Context, user *models.User) (string, *core.UserTokenClaims, error) {
|
||||
return s.createToken(c, user, core.USER_TOKEN_TYPE_PASSWORD_RESET, s.getUserAgent(c), s.CurrentConfig().PasswordResetTokenExpiredTimeDuration)
|
||||
@@ -165,6 +170,18 @@ func (s *TokenService) DeleteTokensBeforeTime(c *core.Context, uid int64, expire
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteTokensByTypeBeforeTime deletes tokens that is specified type and created before specific time
|
||||
func (s *TokenService) DeleteTokensByTypeBeforeTime(c *core.Context, uid int64, tokenType core.TokenType, expireTime int64) error {
|
||||
if uid <= 0 {
|
||||
return errs.ErrUserIdInvalid
|
||||
}
|
||||
|
||||
return s.TokenDB(uid).DoTransaction(c, func(sess *xorm.Session) error {
|
||||
_, err := sess.Where("uid=? AND token_type=? AND created_unix_time<?", uid, tokenType, expireTime).Delete(&models.TokenRecord{})
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// ParseFromTokenId returns token model according to token id
|
||||
func (s *TokenService) ParseFromTokenId(tokenId string) (*models.TokenRecord, error) {
|
||||
pairs := strings.Split(tokenId, ":")
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"xorm.io/xorm"
|
||||
@@ -8,14 +11,22 @@ import (
|
||||
"github.com/mayswind/ezbookkeeping/pkg/core"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/datastore"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/locales"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/mail"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/models"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/settings"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/templates"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/utils"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/uuid"
|
||||
)
|
||||
|
||||
const verifyEmailUrlFormat = "%sdesktop/#/verify_email?token=%s"
|
||||
|
||||
// UserService represents user service
|
||||
type UserService struct {
|
||||
ServiceUsingDB
|
||||
ServiceUsingConfig
|
||||
ServiceUsingMailer
|
||||
ServiceUsingUuid
|
||||
}
|
||||
|
||||
@@ -25,6 +36,12 @@ var (
|
||||
ServiceUsingDB: ServiceUsingDB{
|
||||
container: datastore.Container,
|
||||
},
|
||||
ServiceUsingConfig: ServiceUsingConfig{
|
||||
container: settings.Container,
|
||||
},
|
||||
ServiceUsingMailer: ServiceUsingMailer{
|
||||
container: mail.Container,
|
||||
},
|
||||
ServiceUsingUuid: ServiceUsingUuid{
|
||||
container: uuid.Container,
|
||||
},
|
||||
@@ -390,6 +407,60 @@ func (s *UserService) ExistsEmail(c *core.Context, email string) (bool, error) {
|
||||
return s.UserDB().NewSession(c).Cols("email").Where("email=? AND deleted=?", email, false).Exist(&models.User{})
|
||||
}
|
||||
|
||||
// SendVerifyEmail sends verify email according to specified parameters
|
||||
func (s *UserService) SendVerifyEmail(user *models.User, verifyEmailToken string, backupLocale string) error {
|
||||
if !s.CurrentConfig().EnableSMTP {
|
||||
return errs.ErrSMTPServerNotEnabled
|
||||
}
|
||||
|
||||
locale := user.Language
|
||||
|
||||
if locale == "" {
|
||||
locale = backupLocale
|
||||
}
|
||||
|
||||
localeTextItems := locales.GetLocaleTextItems(locale)
|
||||
verifyEmailTextItems := localeTextItems.VerifyEmailTextItems
|
||||
|
||||
expireTimeInMinutes := s.CurrentConfig().EmailVerifyTokenExpiredTimeDuration.Minutes()
|
||||
verifyEmailUrl := fmt.Sprintf(verifyEmailUrlFormat, s.CurrentConfig().RootUrl, url.QueryEscape(verifyEmailToken))
|
||||
|
||||
tmpl, err := templates.GetTemplate(templates.TEMPLATE_VERIFY_EMAIL)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
templateParams := map[string]interface{}{
|
||||
"AppName": s.CurrentConfig().AppName,
|
||||
"VerifyEmail": map[string]interface{}{
|
||||
"Title": verifyEmailTextItems.Title,
|
||||
"Salutation": fmt.Sprintf(verifyEmailTextItems.SalutationFormat, user.Nickname),
|
||||
"DescriptionAboveBtn": verifyEmailTextItems.DescriptionAboveBtn,
|
||||
"VerifyEmailUrl": verifyEmailUrl,
|
||||
"VerifyEmail": verifyEmailTextItems.VerifyEmail,
|
||||
"DescriptionBelowBtn": fmt.Sprintf(verifyEmailTextItems.DescriptionBelowBtnFormat, s.CurrentConfig().AppName, expireTimeInMinutes),
|
||||
},
|
||||
}
|
||||
|
||||
var bodyBuffer bytes.Buffer
|
||||
err = tmpl.Execute(&bodyBuffer, templateParams)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
message := &mail.MailMessage{
|
||||
To: user.Email,
|
||||
Subject: verifyEmailTextItems.Title,
|
||||
Body: bodyBuffer.String(),
|
||||
}
|
||||
|
||||
err = s.SendMail(message)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// IsPasswordEqualsUserPassword returns whether the given password is correct
|
||||
func (s *UserService) IsPasswordEqualsUserPassword(password string, user *models.User) bool {
|
||||
return user.Password == utils.EncodePassword(password, user.Salt)
|
||||
|
||||
Reference in New Issue
Block a user