diff --git a/i18n/en_US.yaml b/i18n/en_US.yaml index b5fdcdc9..0271ce76 100644 --- a/i18n/en_US.yaml +++ b/i18n/en_US.yaml @@ -1,19 +1,4 @@ # The following fields are used for back-end -# backend.email.tpl.change_email.title.other = Confirm your new email address for {{.SiteName}} by clicking on the following link:\u003cbr\u003e\u003cbr\u003e\n\n\u003ca href='{{.ChangeEmailUrl}}' target='_blank'\u003e{{.ChangeEmailUrl}}\u003c/a\u003e\u003cbr\u003e\u003cbr\u003e\n\nIf you did not request this change, please ignore this email.\n -# backend.email.tpl.change_email.body.other = [{{.SiteName}}] Confirm your new email address -# backend.email.tpl.new_answer.title.other = \u003cstrong\u003e\u003ca href='{{.AnswerUrl}}'\u003e{{.QuestionTitle}}\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\u003cbr\u003e\n\n\u003csmall\u003e{{.DisplayName}}:\u003c/small\u003e\u003cbr\u003e\n\u003cblockquote\u003e{{.AnswerSummary}}\u003c/blockquote\u003e\u003cbr\u003e\n\u003ca href='{{.AnswerUrl}}'\u003eView it on {{.SiteName}}\u003c/a\u003e\u003cbr\u003e\u003cbr\u003e\n\n\u003csmall\u003eYou are receiving this because you authored the thread. \u003ca href='{{.UnsubscribeUrl}}'\u003eUnsubscribe\u003c/a\u003e\u003c/small\u003e -# backend.email.tpl.new_answer.body.other = [{{.SiteName}}] {{.DisplayName}} answered your question -# backend.email.tpl.new_comment.title.other = \u003cstrong\u003e\u003ca href='{{.CommentUrl}}'\u003e{{.QuestionTitle}}\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\u003cbr\u003e\n\n\u003csmall\u003e{{.DisplayName}}:\u003c/small\u003e\u003cbr\u003e\n\u003cblockquote\u003e{{.CommentSummary}}\u003c/blockquote\u003e\u003cbr\u003e\n\u003ca href='{{.CommentUrl}}'\u003eView it on {{.SiteName}}\u003c/a\u003e\u003cbr\u003e\u003cbr\u003e\n\n\u003csmall\u003eYou are receiving this because you authored the thread. \u003ca href='{{.UnsubscribeUrl}}'\u003eUnsubscribe\u003c/a\u003e\u003c/small\u003e -# backend.email.tpl.new_comment.body.other = [{{.SiteName}}] {{.DisplayName}} commented on your post -# backend.email.tpl.pass_reset.title.other = Somebody asked to reset your password on [{{.SiteName}}].\u003cbr\u003e\u003cbr\u003e\n\nIf it was not you, you can safely ignore this email.\u003cbr\u003e\u003cbr\u003e\n\nClick the following link to choose a new password:\u003cbr\u003e\n\u003ca href='{{.PassResetUrl}}' target='_blank'\u003e{{.PassResetUrl}}\u003c/a\u003e\n -# backend.email.tpl.pass_reset.body.other = [{{.SiteName }}] Password reset -# backend.email.tpl.register.title.other = Welcome to {{.SiteName}}\u003cbr\u003e\u003cbr\u003e\n\nClick the following link to confirm and activate your new account:\u003cbr\u003e\n\u003ca href='{{.RegisterUrl}}' target='_blank'\u003e{{.RegisterUrl}}\u003c/a\u003e\u003cbr\u003e\u003cbr\u003e\n\nIf the above link is not clickable, try copying and pasting it into the address bar of your web browser.\n -# backend.email.tpl.register.body.other = [{{.SiteName}}] Confirm your new account -# backend.email.tpl.test.title.other = This is a test email. -# backend.email.tpl.test.body.other = [{{.SiteName}}] Test Email - - - backend: base: success: @@ -123,6 +108,9 @@ backend: email_or_password_wrong_error: other: Email and password do not match. error: + password: + space_invalid: + other: Password cannot contain spaces. admin: cannot_update_their_password: other: You cannot modify your password. diff --git a/i18n/zh_CN.yaml b/i18n/zh_CN.yaml index 29ca8cbb..84036e10 100644 --- a/i18n/zh_CN.yaml +++ b/i18n/zh_CN.yaml @@ -97,13 +97,16 @@ backend: other: 编辑标签描述(无需审核) rank_tag_synonym_label: other: 管理标签同义词 - email: + e_mail: other: 邮箱 password: other: 密码 email_or_password_wrong_error: other: 邮箱和密码不匹配。 error: + password: + space_invalid: + other: 密码不能包含空格。 admin: cannot_update_their_password: other: 您无法修改自己的密码。 diff --git a/internal/base/validator/validator.go b/internal/base/validator/validator.go index 3ce824a4..9f46d229 100644 --- a/internal/base/validator/validator.go +++ b/internal/base/validator/validator.go @@ -207,10 +207,12 @@ func (m *MyValidator) Check(value interface{}) (errFields []*FormErrorField, err if err == nil { return nil, nil } + errMsg := "" for _, errField := range errFields { errField.ErrorMsg = translator.Tr(m.Lang, errField.ErrorMsg) + errMsg = errField.ErrorMsg } - return errFields, err + return errFields, myErrors.BadRequest(reason.RequestFormatError).WithMsg(errMsg) } return nil, nil } diff --git a/internal/migrations/v10.go b/internal/migrations/v10.go index 7ad0c990..2d669b19 100644 --- a/internal/migrations/v10.go +++ b/internal/migrations/v10.go @@ -24,6 +24,8 @@ func addLoginLimitations(x *xorm.Engine) error { _ = json.Unmarshal([]byte(loginSiteInfo.Content), content) content.AllowEmailRegistrations = true content.AllowEmailDomains = make([]string, 0) + data, _ := json.Marshal(content) + loginSiteInfo.Content = string(data) _, err = x.ID(loginSiteInfo.ID).Cols("content").Update(loginSiteInfo) if err != nil { return fmt.Errorf("update site info failed: %w", err) diff --git a/internal/schema/user_schema.go b/internal/schema/user_schema.go index f1f2bc2f..f0bdafff 100644 --- a/internal/schema/user_schema.go +++ b/internal/schema/user_schema.go @@ -262,35 +262,29 @@ type UserRegisterReq struct { } func (u *UserRegisterReq) Check() (errFields []*validator.FormErrorField, err error) { - // TODO i18n - err = checker.CheckPassword(8, 32, 0, u.Pass) - if err != nil { - errField := &validator.FormErrorField{ + if err = checker.CheckPassword(u.Pass); err != nil { + errFields = append(errFields, &validator.FormErrorField{ ErrorField: "pass", ErrorMsg: err.Error(), - } - errFields = append(errFields, errField) + }) return errFields, err } return nil, nil } type UserModifyPasswordReq struct { - OldPass string `validate:"omitempty,gte=8,lte=32" json:"old_pass"` - Pass string `validate:"required,gte=8,lte=32" json:"pass"` + OldPass string `validate:"omitempty,gte=8,lte=32" json:"old_pass"` + Pass string `validate:"required,gte=8,lte=32" json:"pass"` UserID string `json:"-"` AccessToken string `json:"-"` } func (u *UserModifyPasswordReq) Check() (errFields []*validator.FormErrorField, err error) { - // TODO i18n - err = checker.CheckPassword(8, 32, 0, u.Pass) - if err != nil { - errField := &validator.FormErrorField{ + if err = checker.CheckPassword(u.Pass); err != nil { + errFields = append(errFields, &validator.FormErrorField{ ErrorField: "pass", ErrorMsg: err.Error(), - } - errFields = append(errFields, errField) + }) return errFields, err } return nil, nil @@ -352,14 +346,11 @@ type UserRePassWordRequest struct { } func (u *UserRePassWordRequest) Check() (errFields []*validator.FormErrorField, err error) { - // TODO i18n - err = checker.CheckPassword(8, 32, 0, u.Pass) - if err != nil { - errField := &validator.FormErrorField{ + if err = checker.CheckPassword(u.Pass); err != nil { + errFields = append(errFields, &validator.FormErrorField{ ErrorField: "pass", ErrorMsg: err.Error(), - } - errFields = append(errFields, errField) + }) return errFields, err } return nil, nil diff --git a/pkg/checker/password.go b/pkg/checker/password.go index 966b851c..34321350 100644 --- a/pkg/checker/password.go +++ b/pkg/checker/password.go @@ -3,6 +3,7 @@ package checker import ( "fmt" "regexp" + "strings" ) const ( @@ -13,27 +14,26 @@ const ( LevelS ) -// CheckPassword -// minLength: Specifies the minimum length of a password -// maxLength:Specifies the maximum length of a password -// minLevel:Specifies the minimum strength level required for passwords -// pwd:Text passwords -func CheckPassword(minLength, maxLength, minLevel int, pwd string) error { - // First check whether the password length is within the range - if len(pwd) < minLength { - return fmt.Errorf("BAD PASSWORD: The password is shorter than %d characters", minLength) - } - if len(pwd) > maxLength { - return fmt.Errorf("BAD PASSWORD: The password is logner than %d characters", maxLength) +const ( + PasswordCannotContainSpaces = "error.password.space_invalid" +) + +// CheckPassword checks the password strength +func CheckPassword(password string) error { + if strings.Contains(password, " ") { + return fmt.Errorf(PasswordCannotContainSpaces) } + // TODO Currently there is no requirement for password strength + minLevel := 0 + // The password strength level is initialized to D. // The regular is used to verify the password strength. // If the matching is successful, the password strength increases by 1 level := levelD patternList := []string{`[0-9]+`, `[a-z]+`, `[A-Z]+`, `[~!@#$%^&*?_-]+`} for _, pattern := range patternList { - match, _ := regexp.MatchString(pattern, pwd) + match, _ := regexp.MatchString(pattern, password) if match { level++ }