mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 00:20:25 +08:00 
			
		
		
		
	Password Complexity Checks (#6230)
Add password complexity checks. The default settings require a lowercase, uppercase, number and a special character within passwords. Co-Authored-By: T-M-A <maxim.tkachenko@gmail.com> Co-Authored-By: Lanre Adelowo <adelowomailbox@gmail.com> Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> Co-Authored-By: Lauris BH <lauris@nix.lv>
This commit is contained in:
		
				
					committed by
					
						
						zeripath
					
				
			
			
				
	
			
			
			
						parent
						
							f9aba9ba0f
						
					
				
				
					commit
					db657192d0
				
			@@ -12,6 +12,7 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/modules/base"
 | 
			
		||||
	"code.gitea.io/gitea/modules/context"
 | 
			
		||||
	"code.gitea.io/gitea/modules/log"
 | 
			
		||||
	"code.gitea.io/gitea/modules/password"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	"code.gitea.io/gitea/routers"
 | 
			
		||||
	"code.gitea.io/gitea/services/mailer"
 | 
			
		||||
@@ -94,7 +95,10 @@ func NewUserPost(ctx *context.Context, form auth.AdminCreateUserForm) {
 | 
			
		||||
			u.LoginName = form.LoginName
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !password.IsComplexEnough(form.Password) {
 | 
			
		||||
		ctx.RenderWithErr(ctx.Tr("form.password_complexity"), tplUserNew, &form)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if err := models.CreateUser(u); err != nil {
 | 
			
		||||
		switch {
 | 
			
		||||
		case models.IsErrUserAlreadyExist(err):
 | 
			
		||||
@@ -201,6 +205,10 @@ func EditUserPost(ctx *context.Context, form auth.AdminEditUserForm) {
 | 
			
		||||
			ctx.ServerError("UpdateUser", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		if !password.IsComplexEnough(form.Password) {
 | 
			
		||||
			ctx.RenderWithErr(ctx.Tr("form.password_complexity"), tplUserEdit, &form)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		u.HashPassword(form.Password)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,9 +6,12 @@
 | 
			
		||||
package admin
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
	"code.gitea.io/gitea/modules/context"
 | 
			
		||||
	"code.gitea.io/gitea/modules/log"
 | 
			
		||||
	"code.gitea.io/gitea/modules/password"
 | 
			
		||||
	api "code.gitea.io/gitea/modules/structs"
 | 
			
		||||
	"code.gitea.io/gitea/routers/api/v1/convert"
 | 
			
		||||
	"code.gitea.io/gitea/routers/api/v1/user"
 | 
			
		||||
@@ -73,7 +76,11 @@ func CreateUser(ctx *context.APIContext, form api.CreateUserOption) {
 | 
			
		||||
	if ctx.Written() {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !password.IsComplexEnough(form.Password) {
 | 
			
		||||
		err := errors.New("PasswordComplexity")
 | 
			
		||||
		ctx.Error(400, "PasswordComplexity", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if err := models.CreateUser(u); err != nil {
 | 
			
		||||
		if models.IsErrUserAlreadyExist(err) ||
 | 
			
		||||
			models.IsErrEmailAlreadyUsed(err) ||
 | 
			
		||||
@@ -131,6 +138,11 @@ func EditUser(ctx *context.APIContext, form api.EditUserOption) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(form.Password) > 0 {
 | 
			
		||||
		if !password.IsComplexEnough(form.Password) {
 | 
			
		||||
			err := errors.New("PasswordComplexity")
 | 
			
		||||
			ctx.Error(400, "PasswordComplexity", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		var err error
 | 
			
		||||
		if u.Salt, err = models.GetUserSalt(); err != nil {
 | 
			
		||||
			ctx.Error(500, "UpdateUser", err)
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/modules/base"
 | 
			
		||||
	"code.gitea.io/gitea/modules/context"
 | 
			
		||||
	"code.gitea.io/gitea/modules/log"
 | 
			
		||||
	"code.gitea.io/gitea/modules/password"
 | 
			
		||||
	"code.gitea.io/gitea/modules/recaptcha"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	"code.gitea.io/gitea/modules/timeutil"
 | 
			
		||||
@@ -1334,6 +1335,11 @@ func ResetPasswdPost(ctx *context.Context) {
 | 
			
		||||
		ctx.Data["Err_Password"] = true
 | 
			
		||||
		ctx.RenderWithErr(ctx.Tr("auth.password_too_short", setting.MinPasswordLength), tplResetPassword, nil)
 | 
			
		||||
		return
 | 
			
		||||
	} else if !password.IsComplexEnough(passwd) {
 | 
			
		||||
		ctx.Data["IsResetForm"] = true
 | 
			
		||||
		ctx.Data["Err_Password"] = true
 | 
			
		||||
		ctx.RenderWithErr(ctx.Tr("form.password_complexity"), tplResetPassword, nil)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var err error
 | 
			
		||||
@@ -1364,7 +1370,6 @@ func ResetPasswdPost(ctx *context.Context) {
 | 
			
		||||
func MustChangePassword(ctx *context.Context) {
 | 
			
		||||
	ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
 | 
			
		||||
	ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/settings/change_password"
 | 
			
		||||
 | 
			
		||||
	ctx.HTML(200, tplMustChangePassword)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1372,16 +1377,12 @@ func MustChangePassword(ctx *context.Context) {
 | 
			
		||||
// account was created by an admin
 | 
			
		||||
func MustChangePasswordPost(ctx *context.Context, cpt *captcha.Captcha, form auth.MustChangePasswordForm) {
 | 
			
		||||
	ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
 | 
			
		||||
 | 
			
		||||
	ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/settings/change_password"
 | 
			
		||||
 | 
			
		||||
	if ctx.HasError() {
 | 
			
		||||
		ctx.HTML(200, tplMustChangePassword)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	u := ctx.User
 | 
			
		||||
 | 
			
		||||
	// Make sure only requests for users who are eligible to change their password via
 | 
			
		||||
	// this method passes through
 | 
			
		||||
	if !u.MustChangePassword {
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/modules/base"
 | 
			
		||||
	"code.gitea.io/gitea/modules/context"
 | 
			
		||||
	"code.gitea.io/gitea/modules/log"
 | 
			
		||||
	"code.gitea.io/gitea/modules/password"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	"code.gitea.io/gitea/modules/timeutil"
 | 
			
		||||
	"code.gitea.io/gitea/services/mailer"
 | 
			
		||||
@@ -52,6 +53,8 @@ func AccountPost(ctx *context.Context, form auth.ChangePasswordForm) {
 | 
			
		||||
		ctx.Flash.Error(ctx.Tr("settings.password_incorrect"))
 | 
			
		||||
	} else if form.Password != form.Retype {
 | 
			
		||||
		ctx.Flash.Error(ctx.Tr("form.password_not_match"))
 | 
			
		||||
	} else if !password.IsComplexEnough(form.Password) {
 | 
			
		||||
		ctx.Flash.Error(ctx.Tr("settings.password_complexity"))
 | 
			
		||||
	} else {
 | 
			
		||||
		var err error
 | 
			
		||||
		if ctx.User.Salt, err = models.GetUserSalt(); err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -19,36 +19,77 @@ import (
 | 
			
		||||
func TestChangePassword(t *testing.T) {
 | 
			
		||||
	oldPassword := "password"
 | 
			
		||||
	setting.MinPasswordLength = 6
 | 
			
		||||
	setting.PasswordComplexity = map[string]string{
 | 
			
		||||
		"lower": "[a-z]+",
 | 
			
		||||
		"upper": "[A-Z]+",
 | 
			
		||||
		"digit": "[0-9]+",
 | 
			
		||||
		"spec":  "[-_]+",
 | 
			
		||||
	}
 | 
			
		||||
	var pcLUN = map[string]string{
 | 
			
		||||
		"lower": "[a-z]+",
 | 
			
		||||
		"upper": "[A-Z]+",
 | 
			
		||||
		"digit": "[0-9]+",
 | 
			
		||||
	}
 | 
			
		||||
	var pcLU = map[string]string{
 | 
			
		||||
		"lower": "[a-z]+",
 | 
			
		||||
		"upper": "[A-Z]+",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, req := range []struct {
 | 
			
		||||
		OldPassword string
 | 
			
		||||
		NewPassword string
 | 
			
		||||
		Retype      string
 | 
			
		||||
		Message     string
 | 
			
		||||
		OldPassword        string
 | 
			
		||||
		NewPassword        string
 | 
			
		||||
		Retype             string
 | 
			
		||||
		Message            string
 | 
			
		||||
		PasswordComplexity map[string]string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			OldPassword: oldPassword,
 | 
			
		||||
			NewPassword: "123456",
 | 
			
		||||
			Retype:      "123456",
 | 
			
		||||
			Message:     "",
 | 
			
		||||
			OldPassword:        oldPassword,
 | 
			
		||||
			NewPassword:        "Qwerty123456-",
 | 
			
		||||
			Retype:             "Qwerty123456-",
 | 
			
		||||
			Message:            "",
 | 
			
		||||
			PasswordComplexity: setting.PasswordComplexity,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			OldPassword: oldPassword,
 | 
			
		||||
			NewPassword: "12345",
 | 
			
		||||
			Retype:      "12345",
 | 
			
		||||
			Message:     "auth.password_too_short",
 | 
			
		||||
			OldPassword:        oldPassword,
 | 
			
		||||
			NewPassword:        "12345",
 | 
			
		||||
			Retype:             "12345",
 | 
			
		||||
			Message:            "auth.password_too_short",
 | 
			
		||||
			PasswordComplexity: setting.PasswordComplexity,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			OldPassword: "12334",
 | 
			
		||||
			NewPassword: "123456",
 | 
			
		||||
			Retype:      "123456",
 | 
			
		||||
			Message:     "settings.password_incorrect",
 | 
			
		||||
			OldPassword:        "12334",
 | 
			
		||||
			NewPassword:        "123456",
 | 
			
		||||
			Retype:             "123456",
 | 
			
		||||
			Message:            "settings.password_incorrect",
 | 
			
		||||
			PasswordComplexity: setting.PasswordComplexity,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			OldPassword: oldPassword,
 | 
			
		||||
			NewPassword: "123456",
 | 
			
		||||
			Retype:      "12345",
 | 
			
		||||
			Message:     "form.password_not_match",
 | 
			
		||||
			OldPassword:        oldPassword,
 | 
			
		||||
			NewPassword:        "123456",
 | 
			
		||||
			Retype:             "12345",
 | 
			
		||||
			Message:            "form.password_not_match",
 | 
			
		||||
			PasswordComplexity: setting.PasswordComplexity,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			OldPassword:        oldPassword,
 | 
			
		||||
			NewPassword:        "Qwerty",
 | 
			
		||||
			Retype:             "Qwerty",
 | 
			
		||||
			Message:            "settings.password_complexity",
 | 
			
		||||
			PasswordComplexity: setting.PasswordComplexity,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			OldPassword:        oldPassword,
 | 
			
		||||
			NewPassword:        "Qwerty",
 | 
			
		||||
			Retype:             "Qwerty",
 | 
			
		||||
			Message:            "settings.password_complexity",
 | 
			
		||||
			PasswordComplexity: pcLUN,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			OldPassword:        oldPassword,
 | 
			
		||||
			NewPassword:        "QWERTY",
 | 
			
		||||
			Retype:             "QWERTY",
 | 
			
		||||
			Message:            "settings.password_complexity",
 | 
			
		||||
			PasswordComplexity: pcLU,
 | 
			
		||||
		},
 | 
			
		||||
	} {
 | 
			
		||||
		models.PrepareTestEnv(t)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user