Skip to content

Commit d7608e5

Browse files
committed
fix email in token
1 parent 7a5c808 commit d7608e5

File tree

5 files changed

+37
-22
lines changed

5 files changed

+37
-22
lines changed

models/user/email_address.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,8 +357,8 @@ func VerifyActiveEmailCode(ctx context.Context, code, email string) *EmailAddres
357357
if user := GetVerifyUser(ctx, code); user != nil {
358358
// time limit code
359359
prefix := code[:base.TimeLimitCodeLength]
360-
data := fmt.Sprintf("%d%s%s%s%s", user.ID, email, user.LowerName, user.Passwd, user.Rands)
361-
360+
opts := &TimeLimitCodeOptions{Purpose: TimeLimitCodeActivateEmail, NewEmail: email}
361+
data := makeTimeLimitCodeHashData(opts, user)
362362
if base.VerifyTimeLimitCode(time.Now(), data, setting.Service.ActiveCodeLives, prefix) {
363363
emailAddress := &EmailAddress{UID: user.ID, Email: email}
364364
if has, _ := db.GetEngine(ctx).Get(emailAddress); has {

models/user/user.go

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -311,17 +311,6 @@ func (u *User) OrganisationLink() string {
311311
return setting.AppSubURL + "/org/" + url.PathEscape(u.Name)
312312
}
313313

314-
// GenerateEmailActivateCode generates an activate code based on user information and given e-mail.
315-
func (u *User) GenerateEmailActivateCode(email string) string {
316-
code := base.CreateTimeLimitCode(
317-
fmt.Sprintf("%d%s%s%s%s", u.ID, email, u.LowerName, u.Passwd, u.Rands),
318-
setting.Service.ActiveCodeLives, time.Now(), nil)
319-
320-
// Add tail hex username
321-
code += hex.EncodeToString([]byte(u.LowerName))
322-
return code
323-
}
324-
325314
// GetUserFollowers returns range of user's followers.
326315
func GetUserFollowers(ctx context.Context, u, viewer *User, listOptions db.ListOptions) ([]*User, int64, error) {
327316
sess := db.GetEngine(ctx).
@@ -864,12 +853,35 @@ func GetVerifyUser(ctx context.Context, code string) (user *User) {
864853
return nil
865854
}
866855

867-
// VerifyUserActiveCode verifies active code when active account
868-
func VerifyUserActiveCode(ctx context.Context, code string) (user *User) {
856+
type TimeLimitCodePurpose string
857+
858+
const TimeLimitCodeActivateAccount TimeLimitCodePurpose = "activate_account"
859+
const TimeLimitCodeActivateEmail TimeLimitCodePurpose = "activate_email"
860+
const TimeLimitCodeResetPassword TimeLimitCodePurpose = "reset_password"
861+
862+
type TimeLimitCodeOptions struct {
863+
Purpose TimeLimitCodePurpose
864+
NewEmail string
865+
}
866+
867+
func makeTimeLimitCodeHashData(opts *TimeLimitCodeOptions, u *User) string {
868+
return fmt.Sprintf("%s|%d|%s|%s|%s|%s", opts.Purpose, u.ID, strings.ToLower(util.IfZero(opts.NewEmail, u.Email)), u.LowerName, u.Passwd, u.Rands)
869+
}
870+
871+
// GenerateUserTimeLimitCode generates an activate code based on user information and given e-mail.
872+
func GenerateUserTimeLimitCode(opts *TimeLimitCodeOptions, u *User) string {
873+
data := makeTimeLimitCodeHashData(opts, u)
874+
code := base.CreateTimeLimitCode(data, setting.Service.ActiveCodeLives, time.Now(), nil)
875+
code += hex.EncodeToString([]byte(u.LowerName)) // Add tail hex username
876+
return code
877+
}
878+
879+
// VerifyUserTimeLimitCode verifies active code when active account
880+
func VerifyUserTimeLimitCode(ctx context.Context, opts *TimeLimitCodeOptions, code string) (user *User) {
869881
if user = GetVerifyUser(ctx, code); user != nil {
870882
// time limit code
871883
prefix := code[:base.TimeLimitCodeLength]
872-
data := fmt.Sprintf("%d%s%s%s%s", user.ID, user.Email, user.LowerName, user.Passwd, user.Rands)
884+
data := makeTimeLimitCodeHashData(opts, user)
873885
if base.VerifyTimeLimitCode(time.Now(), data, setting.Service.ActiveCodeLives, prefix) {
874886
return user
875887
}

routers/web/auth/auth.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ func Activate(ctx *context.Context) {
689689
}
690690

691691
// TODO: ctx.Doer/ctx.Data["SignedUser"] could be nil or not the same user as the one being activated
692-
user := user_model.VerifyUserActiveCode(ctx, code)
692+
user := user_model.VerifyUserTimeLimitCode(ctx, &user_model.TimeLimitCodeOptions{Purpose: user_model.TimeLimitCodeActivateAccount}, code)
693693
if user == nil { // if code is wrong
694694
renderActivationPromptMessage(ctx, ctx.Locale.Tr("auth.invalid_code"))
695695
return
@@ -734,7 +734,7 @@ func ActivatePost(ctx *context.Context) {
734734
}
735735

736736
// TODO: ctx.Doer/ctx.Data["SignedUser"] could be nil or not the same user as the one being activated
737-
user := user_model.VerifyUserActiveCode(ctx, code)
737+
user := user_model.VerifyUserTimeLimitCode(ctx, &user_model.TimeLimitCodeOptions{Purpose: user_model.TimeLimitCodeActivateAccount}, code)
738738
if user == nil { // if code is wrong
739739
renderActivationPromptMessage(ctx, ctx.Locale.Tr("auth.invalid_code"))
740740
return

routers/web/auth/password.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ func commonResetPassword(ctx *context.Context) (*user_model.User, *auth.TwoFacto
113113
}
114114

115115
// Fail early, don't frustrate the user
116-
u := user_model.VerifyUserActiveCode(ctx, code)
116+
u := user_model.VerifyUserTimeLimitCode(ctx, &user_model.TimeLimitCodeOptions{Purpose: user_model.TimeLimitCodeResetPassword}, code)
117117
if u == nil {
118118
ctx.Flash.Error(ctx.Tr("auth.invalid_code_forgot_password", fmt.Sprintf("%s/user/forgot_password", setting.AppSubURL)), true)
119119
return nil, nil

services/mailer/mail.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ func SendActivateAccountMail(locale translation.Locale, u *user_model.User) {
9393
// No mail service configured
9494
return
9595
}
96-
sendUserMail(locale.Language(), u, mailAuthActivate, u.GenerateEmailActivateCode(u.Email), locale.TrString("mail.activate_account"), "activate account")
96+
opts := &user_model.TimeLimitCodeOptions{Purpose: user_model.TimeLimitCodeActivateAccount}
97+
sendUserMail(locale.Language(), u, mailAuthActivate, user_model.GenerateUserTimeLimitCode(opts, u), locale.TrString("mail.activate_account"), "activate account")
9798
}
9899

99100
// SendResetPasswordMail sends a password reset mail to the user
@@ -103,7 +104,8 @@ func SendResetPasswordMail(u *user_model.User) {
103104
return
104105
}
105106
locale := translation.NewLocale(u.Language)
106-
sendUserMail(u.Language, u, mailAuthResetPassword, u.GenerateEmailActivateCode(u.Email), locale.TrString("mail.reset_password"), "recover account")
107+
opts := &user_model.TimeLimitCodeOptions{Purpose: user_model.TimeLimitCodeResetPassword}
108+
sendUserMail(u.Language, u, mailAuthResetPassword, user_model.GenerateUserTimeLimitCode(opts, u), locale.TrString("mail.reset_password"), "recover account")
107109
}
108110

109111
// SendActivateEmailMail sends confirmation email to confirm new email address
@@ -113,11 +115,12 @@ func SendActivateEmailMail(u *user_model.User, email string) {
113115
return
114116
}
115117
locale := translation.NewLocale(u.Language)
118+
opts := &user_model.TimeLimitCodeOptions{Purpose: user_model.TimeLimitCodeActivateEmail, NewEmail: email}
116119
data := map[string]any{
117120
"locale": locale,
118121
"DisplayName": u.DisplayName(),
119122
"ActiveCodeLives": timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, locale),
120-
"Code": u.GenerateEmailActivateCode(email),
123+
"Code": user_model.GenerateUserTimeLimitCode(opts, u),
121124
"Email": email,
122125
"Language": locale.Language(),
123126
}

0 commit comments

Comments
 (0)