fix(api): relax account password validation
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
@@ -16,6 +17,14 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// AccountPasswordMinLength 是账号密码允许的最低字符数。
|
||||
const AccountPasswordMinLength = 6
|
||||
|
||||
// IsValidAccountPassword 仅校验账号密码的最低字符长度。
|
||||
func IsValidAccountPassword(password string) bool {
|
||||
return utf8.RuneCountInString(password) >= AccountPasswordMinLength
|
||||
}
|
||||
|
||||
// PasswordHash creates the shared password representation used by account modules.
|
||||
func PasswordHash(password string) (string, error) {
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
|
||||
24
backend/api/internal/logic/common/password_test.go
Normal file
24
backend/api/internal/logic/common/password_test.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package common
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestIsValidAccountPassword(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
password string
|
||||
want bool
|
||||
}{
|
||||
{name: "five characters", password: "12345", want: false},
|
||||
{name: "six digits", password: "123456", want: true},
|
||||
{name: "six letters without complexity", password: "abcdef", want: true},
|
||||
{name: "six unicode characters", password: "密码密码密码", want: true},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
if got := IsValidAccountPassword(test.password); got != test.want {
|
||||
t.Fatalf("IsValidAccountPassword(%q) = %v, want %v", test.password, got, test.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
// LoginRequest 是平台总后台的账号密码登录请求。
|
||||
type LoginRequest struct {
|
||||
Username string `json:"username" binding:"required,max=64"`
|
||||
Password string `json:"password" binding:"required,min=8,max=128"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
}
|
||||
|
||||
// LoginReply 是后台登录成功后的访问凭证与账号状态。
|
||||
@@ -122,8 +122,8 @@ func CurrentProfile(ctx *gin.Context) {
|
||||
|
||||
// ChangePasswordRequest 是已登录账号的改密请求。
|
||||
type ChangePasswordRequest struct {
|
||||
CurrentPassword string `json:"current_password" binding:"required,min=8,max=128"`
|
||||
NewPassword string `json:"new_password" binding:"required,min=12,max=128"`
|
||||
CurrentPassword string `json:"current_password" binding:"required"`
|
||||
NewPassword string `json:"new_password" binding:"required"`
|
||||
}
|
||||
|
||||
// ChangePassword 修改当前账号密码并解除首次登录改密限制。
|
||||
@@ -138,6 +138,10 @@ func ChangePassword(ctx *gin.Context) {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
if !common.IsValidAccountPassword(request.NewPassword) {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
var account models.PlatformAccount
|
||||
if err := impl.DBService.Where("identity = ?", claims.Identity).First(&account).Error; err != nil {
|
||||
infra.Response.Error(ctx, errcode.ErrRecordNotFound)
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
|
||||
type accountRequest struct {
|
||||
Username string `json:"username" binding:"required,max=64"`
|
||||
Password string `json:"password" binding:"required,min=8,max=128"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
DisplayName string `json:"display_name" binding:"max=64"`
|
||||
RoleCode string `json:"role_code" binding:"max=64"`
|
||||
DeliveryBasicIdentity string `json:"delivery_basic_identity"`
|
||||
@@ -50,6 +50,10 @@ func CreateDeliveryAccount(ctx *gin.Context) {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
if !common.IsValidAccountPassword(request.Password) {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
deliveryBasicID, err := common.ResolveIdentityID(&models.DeliveryBasic{}, request.DeliveryBasicIdentity, true)
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
|
||||
type accountRequest struct {
|
||||
Username string `json:"username" binding:"required,max=64"`
|
||||
Password string `json:"password" binding:"required,min=8,max=128"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
DisplayName string `json:"display_name" binding:"max=64"`
|
||||
RoleCode string `json:"role_code" binding:"max=64"`
|
||||
GasBasicIdentity string `json:"gas_basic_identity"`
|
||||
@@ -49,6 +49,10 @@ func CreateGasAccount(ctx *gin.Context) {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
if !common.IsValidAccountPassword(request.Password) {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
gasBasicID, err := common.ResolveIdentityID(&models.GasBasic{}, request.GasBasicIdentity, true)
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
|
||||
@@ -36,7 +36,7 @@ func ListPlatformAccount(ctx *gin.Context) {
|
||||
|
||||
type platformAccountRequest struct {
|
||||
Username string `json:"username" binding:"required,max=64"`
|
||||
Password string `json:"password" binding:"required,min=8,max=128"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
DisplayName string `json:"display_name" binding:"max=64"`
|
||||
Avatar string `json:"avatar" binding:"max=512"`
|
||||
PlatformRoleCode string `json:"platform_role_code" binding:"required,max=64"`
|
||||
@@ -70,6 +70,10 @@ func CreatePlatformAccount(ctx *gin.Context) {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
if !common.IsValidAccountPassword(request.Password) {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
if !isAssignablePlatformRole(request.PlatformRoleCode) {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
|
||||
@@ -51,7 +51,7 @@ func GetStaff(ctx *gin.Context) { common.GetByIdentity[models.StaffAccount](ctx)
|
||||
func CreateStaff(ctx *gin.Context) {
|
||||
var request struct {
|
||||
Username string `json:"username" binding:"required,max=64"`
|
||||
Password string `json:"password" binding:"required,min=8,max=128"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
Name string `json:"name" binding:"required,max=64"`
|
||||
Phone string `json:"phone" binding:"max=32"`
|
||||
Avatar string `json:"avatar" binding:"max=512"`
|
||||
@@ -60,7 +60,9 @@ func CreateStaff(ctx *gin.Context) {
|
||||
DeliveryBasicIdentity string `json:"delivery_basic_identity"`
|
||||
WorkStatus string `json:"work_status" binding:"max=32"`
|
||||
}
|
||||
if err := ctx.ShouldBindJSON(&request); err != nil || !validStaffRole(request.RoleCode) {
|
||||
if err := ctx.ShouldBindJSON(&request); err != nil ||
|
||||
!common.IsValidAccountPassword(request.Password) ||
|
||||
!validStaffRole(request.RoleCode) {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ func GetUser(ctx *gin.Context) { common.GetByIdentity[models.UserAccount](ctx) }
|
||||
func CreateUser(ctx *gin.Context) {
|
||||
var request struct {
|
||||
Username string `json:"username" binding:"required,max=64"`
|
||||
Password string `json:"password" binding:"required,min=8,max=128"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
Name string `json:"name" binding:"required,max=64"`
|
||||
Phone string `json:"phone" binding:"max=32"`
|
||||
Avatar string `json:"avatar" binding:"max=512"`
|
||||
@@ -29,6 +29,10 @@ func CreateUser(ctx *gin.Context) {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
if !common.IsValidAccountPassword(request.Password) {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
hash, err := common.PasswordHash(request.Password)
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
|
||||
Reference in New Issue
Block a user