Browse Source

阶段提交

yjp 1 year ago
parent
commit
eda31261f9

+ 66 - 35
convenient/domain/auth/auth.go

@@ -1,6 +1,7 @@
 package auth
 
 import (
+	"git.sxidc.com/go-framework/baize/convenient/domain/auth/jwt_tools"
 	"git.sxidc.com/go-framework/baize/convenient/domain/auth/middlewares"
 	"git.sxidc.com/go-framework/baize/convenient/domain/auth/permission"
 	"git.sxidc.com/go-framework/baize/convenient/domain/auth/permission_group"
@@ -36,6 +37,8 @@ type Simple struct {
 }
 
 func (simple *Simple) bind(binder *binding.Binder) {
+	jwt_tools.SetJWTSecretKey(simple.JWTSecretKey)
+
 	(&permission.Simple{Schema: simple.Schema}).Bind(binder)
 	(&permission_group.Simple{Schema: simple.Schema}).Bind(binder)
 	(&role.Simple{Schema: simple.Schema}).Bind(binder)
@@ -86,7 +89,7 @@ func (simple *Simple) bind(binder *binding.Binder) {
 				return errResponse, err
 			}
 
-			token, err := newJWT(simple.JWTSecretKey, existUser.ID, simple.JWTExpiredSec)
+			token, err := jwt_tools.NewJWT(existUser.ID, simple.JWTExpiredSec)
 			if err != nil {
 				return errResponse, errors.New(err.Error())
 			}
@@ -111,65 +114,93 @@ func (simple *Simple) bind(binder *binding.Binder) {
 		Path:             "/logout",
 		SendResponseFunc: response.SendMsgResponse,
 		ServiceFunc: func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) {
-			errResponse := map[string]any{
-				"token": "",
-			}
+			userInfo := c.GetUserInfo()
 
-			jsonBody, err := request.ToConcrete[*LoginJsonBody](params)
+			userTableName := domain.TableName(simple.Schema, &user.Entity{})
+
+			dbExecutor := i.DBExecutor()
+
+			err := database.Update(dbExecutor, &sql.UpdateExecuteParams{
+				TableName:  userTableName,
+				TableRow:   sql.NewTableRow().Add(user.ColumnToken, ""),
+				Conditions: sql.NewConditions().Equal(entity.ColumnID, userInfo.GetID()),
+			})
 			if err != nil {
-				return errResponse, err
+				return nil, errors.New(err.Error())
 			}
 
-			encryptedPassword, err := encoding.AESEncrypt(jsonBody.Password, simple.AESKey)
-			if err != nil {
-				return errResponse, errors.New(err.Error())
+			return nil, nil
+		},
+	}, middlewares.Authentication())
+
+	// Challenge
+	binding.PostBind(binder, &binding.SimpleBindItem[UserWithRoleInfo]{
+		Path:             "/challenge",
+		SendResponseFunc: response.SendInfoResponse[UserWithRoleInfo],
+		ServiceFunc: func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (UserWithRoleInfo, error) {
+			errInfo := UserWithRoleInfo{
+				RoleInfos: make([]role.Info, 0),
 			}
 
-			userTableName := domain.TableName(simple.Schema, &user.Entity{})
+			userInfo := c.GetUserInfo()
+
+			userAndRoleTableName := domain.RelationTableName(simple.Schema, &user.Entity{}, &role.Entity{})
+			roleTableName := domain.TableName(simple.Schema, &role.Entity{})
 
 			dbExecutor := i.DBExecutor()
 
-			result, err := database.QueryOne(dbExecutor, &sql.QueryOneExecuteParams{
-				TableName: userTableName,
-				Conditions: sql.NewConditions().
-					Equal(user.ColumnUserName, jsonBody.UserName).
-					Equal(user.ColumnPassword, encryptedPassword),
+			roleIDResults, totalCount, err := database.Query(dbExecutor, &sql.QueryExecuteParams{
+				TableName:     userAndRoleTableName,
+				SelectColumns: []string{domain.RelationColumnName(&role.Entity{})},
+				Conditions:    sql.NewConditions().Equal(domain.RelationColumnName(&user.Entity{}), userInfo.GetID()),
+				PageNo:        0,
+				PageSize:      0,
 			})
 			if err != nil {
-				if database.IsErrorDBRecordNotExist(err) {
-					return errResponse, errors.New("用户名或密码错误")
-				}
+				return errInfo, errors.New(err.Error())
+			}
 
-				return errResponse, errors.New(err.Error())
+			if totalCount == 0 {
+				return UserWithRoleInfo{
+					UserInfo:  *(userInfo.(*user.Info)),
+					RoleInfos: make([]role.Info, 0),
+				}, nil
 			}
 
-			existUser := new(user.Entity)
-			err = sql.ParseSqlResult(result, existUser)
-			if err != nil {
-				return errResponse, err
+			roleIDs := make([]string, len(roleIDResults))
+			for index, roleIDResult := range roleIDResults {
+				roleIDs[index] = roleIDResult.ColumnValueString(domain.RelationColumnName(&role.Entity{}))
 			}
 
-			token, err := newJWT(simple.JWTSecretKey, existUser.ID, simple.JWTExpiredSec)
+			roleResults, totalCount, err := database.Query(dbExecutor, &sql.QueryExecuteParams{
+				TableName:  roleTableName,
+				Conditions: sql.NewConditions().In(entity.ColumnID, roleIDs),
+				PageNo:     0,
+				PageSize:   0,
+			})
 			if err != nil {
-				return errResponse, errors.New(err.Error())
+				return errInfo, errors.New(err.Error())
 			}
 
-			err = database.Update(dbExecutor, &sql.UpdateExecuteParams{
-				TableName:  userTableName,
-				TableRow:   sql.NewTableRow().Add(user.ColumnToken, token),
-				Conditions: sql.NewConditions().Equal(entity.ColumnID, existUser.ID),
-			})
+			if totalCount == 0 {
+				return UserWithRoleInfo{
+					UserInfo:  *(userInfo.(*user.Info)),
+					RoleInfos: make([]role.Info, 0),
+				}, nil
+			}
+
+			roleInfos := make([]role.Info, 0)
+			err = sql.ParseSqlResult(roleResults, &roleInfos)
 			if err != nil {
-				return errResponse, errors.New(err.Error())
+				return errInfo, errors.New(err.Error())
 			}
 
-			return map[string]any{
-				"token": token,
+			return UserWithRoleInfo{
+				UserInfo:  *(userInfo.(*user.Info)),
+				RoleInfos: roleInfos,
 			}, nil
 		},
 	}, middlewares.Authentication())
-
-	// TODO Challenge
 }
 
 func BindAuth(binder *binding.Binder, simple *Simple) {

+ 13 - 0
convenient/domain/auth/info.go

@@ -0,0 +1,13 @@
+package auth
+
+import (
+	"git.sxidc.com/go-framework/baize/convenient/domain/auth/role"
+	"git.sxidc.com/go-framework/baize/convenient/domain/auth/user"
+)
+
+type (
+	UserWithRoleInfo struct {
+		UserInfo  user.Info
+		RoleInfos []role.Info
+	}
+)

+ 11 - 5
convenient/domain/auth/jwt.go → convenient/domain/auth/jwt_tools/jwt_tools.go

@@ -1,4 +1,4 @@
-package auth
+package jwt_tools
 
 import (
 	"github.com/dgrijalva/jwt-go"
@@ -6,7 +6,13 @@ import (
 	"time"
 )
 
-func newJWT(jwtSecretKey string, userID string, expSec int64) (string, error) {
+var secretKey string
+
+func SetJWTSecretKey(secretKey string) {
+	secretKey = secretKey
+}
+
+func NewJWT(userID string, expSec int64) (string, error) {
 	token := jwt.New(jwt.SigningMethodHS256)
 	claims := make(jwt.MapClaims)
 
@@ -18,7 +24,7 @@ func newJWT(jwtSecretKey string, userID string, expSec int64) (string, error) {
 	claims["iat"] = time.Now().Unix()
 	token.Claims = claims
 
-	tokenString, err := token.SignedString([]byte(jwtSecretKey))
+	tokenString, err := token.SignedString([]byte(secretKey))
 	if err != nil {
 		return "", errors.New(err.Error())
 	}
@@ -26,9 +32,9 @@ func newJWT(jwtSecretKey string, userID string, expSec int64) (string, error) {
 	return tokenString, nil
 }
 
-func checkJWT(jwtSecretKey string, tokenStr string) (bool, string, error) {
+func CheckJWT(tokenStr string) (bool, string, error) {
 	token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
-		return []byte(jwtSecretKey), nil
+		return []byte(secretKey), nil
 	})
 	if err != nil {
 		var validationErr *jwt.ValidationError

+ 0 - 29
convenient/domain/auth/middlewares/middleware.go

@@ -1,29 +0,0 @@
-package middlewares
-
-import (
-	"git.sxidc.com/go-framework/baize/framework/binding"
-	"git.sxidc.com/go-framework/baize/framework/core/api"
-	"git.sxidc.com/go-framework/baize/framework/core/infrastructure"
-	"github.com/pkg/errors"
-)
-
-const (
-	tokenContextKey = "auth-context-token"
-)
-
-func Authentication() binding.Middleware {
-	return func(c *api.Context, i *infrastructure.Infrastructure) {
-		// TODO 中间件
-		//dbExecutor := i.DBExecutor()
-		c.Next()
-	}
-}
-
-func GetTokenContext(c *api.Context) (string, error) {
-	value, exist := c.Get(tokenContextKey)
-	if !exist {
-		return "", errors.New("没有找到token")
-	}
-
-	return value.(string), nil
-}

+ 54 - 0
convenient/domain/auth/middlewares/middlewares.go

@@ -0,0 +1,54 @@
+package middlewares
+
+import (
+	"git.sxidc.com/go-framework/baize/convenient/domain/auth/jwt_tools"
+	"git.sxidc.com/go-framework/baize/convenient/domain/auth/user"
+	"git.sxidc.com/go-framework/baize/framework/binding"
+	"git.sxidc.com/go-framework/baize/framework/core/api"
+	"git.sxidc.com/go-framework/baize/framework/core/api/response"
+	"git.sxidc.com/go-framework/baize/framework/core/domain"
+	"git.sxidc.com/go-framework/baize/framework/core/infrastructure"
+	"github.com/dgrijalva/jwt-go/request"
+	"github.com/pkg/errors"
+	"net/http"
+)
+
+var dbSchema string
+
+func SetDBSchema(schema string) {
+	dbSchema = schema
+}
+
+func Authentication() binding.Middleware {
+	return func(c *api.Context, i *infrastructure.Infrastructure) {
+		respFunc := response.SendMapResponse
+
+		// 获取token
+		token, err := request.AuthorizationHeaderExtractor.ExtractToken(c.Request)
+		if err != nil {
+			respFunc(c, http.StatusUnauthorized, nil, errors.New(err.Error()))
+			c.Abort()
+			return
+		}
+
+		// 校验token
+		valid, _, err := jwt_tools.CheckJWT(token)
+		if err != nil {
+			respFunc(c, http.StatusUnauthorized, nil, errors.New(err.Error()))
+			c.Abort()
+			return
+		}
+
+		if !valid {
+			respFunc(c, http.StatusUnauthorized, nil, errors.New("无效token"))
+			c.Abort()
+			return
+		}
+
+		// 获取用户信息
+		userTableName := domain.TableName(simple.Schema, &user.Entity{})
+		dbExecutor := i.DBExecutor()
+
+		c.Next()
+	}
+}

+ 6 - 1
convenient/domain/auth/permission/api.go

@@ -1,6 +1,7 @@
 package permission
 
 import (
+	"git.sxidc.com/go-framework/baize/convenient/domain/auth/middlewares"
 	"git.sxidc.com/go-framework/baize/convenient/entity_crud"
 	"git.sxidc.com/go-framework/baize/framework/binding"
 )
@@ -20,5 +21,9 @@ func (simple *Simple) Bind(binder *binding.Binder) {
 		UpdateJsonBody:     &UpdatePermissionJsonBody{},
 		QueryQueryParams:   &GetPermissionsQueryParams{},
 		GetByIDQueryParams: &GetPermissionQueryParams{},
-	}, entity_crud.WithCreateMiddlewares())
+	}, entity_crud.WithCreateMiddlewares(middlewares.Authentication()),
+		entity_crud.WithDeleteMiddlewares(middlewares.Authentication()),
+		entity_crud.WithUpdateMiddlewares(middlewares.Authentication()),
+		entity_crud.WithQueryMiddlewares[Info](middlewares.Authentication()),
+		entity_crud.WithGetByIDMiddlewares[Info](middlewares.Authentication()))
 }

+ 6 - 1
convenient/domain/auth/permission_group/api.go

@@ -1,6 +1,7 @@
 package permission_group
 
 import (
+	"git.sxidc.com/go-framework/baize/convenient/domain/auth/middlewares"
 	"git.sxidc.com/go-framework/baize/convenient/entity_crud"
 	"git.sxidc.com/go-framework/baize/framework/binding"
 )
@@ -20,5 +21,9 @@ func (simple *Simple) Bind(binder *binding.Binder) {
 		UpdateJsonBody:     &UpdatePermissionGroupJsonBody{},
 		QueryQueryParams:   &GetPermissionGroupsQueryParams{},
 		GetByIDQueryParams: &GetPermissionGroupQueryParams{},
-	})
+	}, entity_crud.WithCreateMiddlewares(middlewares.Authentication()),
+		entity_crud.WithDeleteMiddlewares(middlewares.Authentication()),
+		entity_crud.WithUpdateMiddlewares(middlewares.Authentication()),
+		entity_crud.WithQueryMiddlewares[Info](middlewares.Authentication()),
+		entity_crud.WithGetByIDMiddlewares[Info](middlewares.Authentication()))
 }

+ 5 - 1
convenient/domain/auth/relations/permission_group_and_permission.go

@@ -1,6 +1,7 @@
 package relations
 
 import (
+	"git.sxidc.com/go-framework/baize/convenient/domain/auth/middlewares"
 	"git.sxidc.com/go-framework/baize/convenient/domain/auth/permission"
 	"git.sxidc.com/go-framework/baize/convenient/domain/auth/permission_group"
 	"git.sxidc.com/go-framework/baize/convenient/relation/many2many"
@@ -22,5 +23,8 @@ func (simple *SimplePermissionGroupAndPermission) Bind(binder *binding.Binder) {
 		LeftQueryQueryParams:  &permission_group.GetPermissionsOfPermissionGroupQueryParams{},
 		RightUpdateJsonBody:   &permission.UpdatePermissionGroupsOfPermissionJsonBody{},
 		RightQueryQueryParams: &permission.GetPermissionGroupsOfPermissionQueryParams{},
-	})
+	}, many2many.WithLeftUpdateMiddlewares(middlewares.Authentication()),
+		many2many.WithLeftQueryMiddlewares(middlewares.Authentication()),
+		many2many.WithRightUpdateMiddlewares(middlewares.Authentication()),
+		many2many.WithRightQueryMiddlewares(middlewares.Authentication()))
 }

+ 5 - 1
convenient/domain/auth/relations/role_and_permission.go

@@ -1,6 +1,7 @@
 package relations
 
 import (
+	"git.sxidc.com/go-framework/baize/convenient/domain/auth/middlewares"
 	"git.sxidc.com/go-framework/baize/convenient/domain/auth/permission"
 	"git.sxidc.com/go-framework/baize/convenient/domain/auth/role"
 	"git.sxidc.com/go-framework/baize/convenient/relation/many2many"
@@ -22,5 +23,8 @@ func (simple *SimpleRoleAndPermission) Bind(binder *binding.Binder) {
 		LeftQueryQueryParams:  &role.GetPermissionsOfRoleQueryParams{},
 		RightUpdateJsonBody:   &permission.UpdateRolesOfPermissionJsonBody{},
 		RightQueryQueryParams: &permission.GetRolesOfPermissionQueryParams{},
-	})
+	}, many2many.WithLeftUpdateMiddlewares(middlewares.Authentication()),
+		many2many.WithLeftQueryMiddlewares(middlewares.Authentication()),
+		many2many.WithRightUpdateMiddlewares(middlewares.Authentication()),
+		many2many.WithRightQueryMiddlewares(middlewares.Authentication()))
 }

+ 5 - 1
convenient/domain/auth/relations/role_and_user.go

@@ -1,6 +1,7 @@
 package relations
 
 import (
+	"git.sxidc.com/go-framework/baize/convenient/domain/auth/middlewares"
 	"git.sxidc.com/go-framework/baize/convenient/domain/auth/role"
 	"git.sxidc.com/go-framework/baize/convenient/domain/auth/user"
 	"git.sxidc.com/go-framework/baize/convenient/relation/many2many"
@@ -22,5 +23,8 @@ func (simple *SimpleUserAndRole) Bind(binder *binding.Binder) {
 		LeftQueryQueryParams:  &user.GetRolesOfUserQueryParams{},
 		RightUpdateJsonBody:   &role.UpdateUsersOfRoleJsonBody{},
 		RightQueryQueryParams: &role.GetUsersOfRoleQueryParams{},
-	})
+	}, many2many.WithLeftUpdateMiddlewares(middlewares.Authentication()),
+		many2many.WithLeftQueryMiddlewares(middlewares.Authentication()),
+		many2many.WithRightUpdateMiddlewares(middlewares.Authentication()),
+		many2many.WithRightQueryMiddlewares(middlewares.Authentication()))
 }

+ 6 - 1
convenient/domain/auth/role/api.go

@@ -1,6 +1,7 @@
 package role
 
 import (
+	"git.sxidc.com/go-framework/baize/convenient/domain/auth/middlewares"
 	"git.sxidc.com/go-framework/baize/convenient/entity_crud"
 	"git.sxidc.com/go-framework/baize/framework/binding"
 )
@@ -20,5 +21,9 @@ func (simple *Simple) Bind(binder *binding.Binder) {
 		UpdateJsonBody:     &UpdateRoleJsonBody{},
 		QueryQueryParams:   &GetRolesQueryParams{},
 		GetByIDQueryParams: &GetRoleQueryParams{},
-	})
+	}, entity_crud.WithCreateMiddlewares(middlewares.Authentication()),
+		entity_crud.WithDeleteMiddlewares(middlewares.Authentication()),
+		entity_crud.WithUpdateMiddlewares(middlewares.Authentication()),
+		entity_crud.WithQueryMiddlewares[Info](middlewares.Authentication()),
+		entity_crud.WithGetByIDMiddlewares[Info](middlewares.Authentication()))
 }

+ 182 - 176
convenient/domain/auth/user/api.go

@@ -1,6 +1,7 @@
 package user
 
 import (
+	"git.sxidc.com/go-framework/baize/convenient/domain/auth/middlewares"
 	"git.sxidc.com/go-framework/baize/convenient/entity_crud"
 	"git.sxidc.com/go-framework/baize/framework/binding"
 	"git.sxidc.com/go-framework/baize/framework/core/api/response"
@@ -33,253 +34,258 @@ func (simple *Simple) Bind(binder *binding.Binder) {
 		UpdateJsonBody:     &UpdateUserJsonBody{},
 		QueryQueryParams:   &GetUsersQueryParams{},
 		GetByIDQueryParams: &GetUserQueryParams{},
-	}, entity_crud.WithCreateCallbacks(&entity_crud.CreateCallbacks{
-		Before: func(e entity.Entity, prepared map[string]any, i *infrastructure.Infrastructure, tx database.Executor) error {
-			userEntity, err := domain.ToConcrete[*Entity](e)
-			if err != nil {
-				return err
-			}
-
-			encryptedPassword, err := encoding.AESEncrypt(userEntity.Password, simple.AESKey)
-			if err != nil {
-				return errors.New(err.Error())
-			}
-
-			userEntity.Password = encryptedPassword
-
-			if strutils.IsStringEmpty(userEntity.Name) {
-				userEntity.Name = "匿名-" + strutils.SimpleUUID()[0:8]
-			}
-
-			encryptedPhone, err := encoding.AESEncrypt(userEntity.Phone, simple.AESKey)
-			if err != nil {
-				return errors.New(err.Error())
-			}
-
-			userEntity.Phone = encryptedPhone
-
-			encryptedEmail, err := encoding.AESEncrypt(userEntity.Email, simple.AESKey)
-			if err != nil {
-				return errors.New(err.Error())
-			}
-
-			userEntity.Email = encryptedEmail
-
-			checkResult := check.Struct(userEntity, fieldMap)
-
-			err = domain.CheckField(checkResult, userEntity.DomainCNName(), FieldPassword)
-			if err != nil {
-				return err
-			}
-
-			err = domain.CheckField(checkResult, userEntity.DomainCNName(), FieldName)
-			if err != nil {
-				return err
-			}
-
-			err = domain.CheckField(checkResult, userEntity.DomainCNName(), FieldPhone)
-			if err != nil {
-				return err
-			}
-
-			err = domain.CheckField(checkResult, userEntity.DomainCNName(), FieldEmail)
-			if err != nil {
-				return err
-			}
-
-			return nil
-		},
-	}), entity_crud.WithUpdateCallbacks(&entity_crud.UpdateCallbacks{
-		Before: func(e entity.Entity, prepared map[string]any, i *infrastructure.Infrastructure, tx database.Executor) error {
-			userEntity, err := domain.ToConcrete[*Entity](e)
-			if err != nil {
-				return err
-			}
+	}, entity_crud.WithCreateMiddlewares(middlewares.Authentication()),
+		entity_crud.WithDeleteMiddlewares(middlewares.Authentication()),
+		entity_crud.WithUpdateMiddlewares(middlewares.Authentication()),
+		entity_crud.WithQueryMiddlewares[Info](middlewares.Authentication()),
+		entity_crud.WithGetByIDMiddlewares[Info](middlewares.Authentication()),
+		entity_crud.WithCreateCallbacks(&entity_crud.CreateCallbacks{
+			Before: func(e entity.Entity, prepared map[string]any, i *infrastructure.Infrastructure, tx database.Executor) error {
+				userEntity, err := domain.ToConcrete[*Entity](e)
+				if err != nil {
+					return err
+				}
 
-			if strutils.IsStringNotEmpty(userEntity.Password) {
 				encryptedPassword, err := encoding.AESEncrypt(userEntity.Password, simple.AESKey)
 				if err != nil {
 					return errors.New(err.Error())
 				}
 
 				userEntity.Password = encryptedPassword
-			}
 
-			if strutils.IsStringEmpty(userEntity.Name) {
-				userEntity.Name = "匿名-" + strutils.SimpleUUID()[0:8]
-			}
+				if strutils.IsStringEmpty(userEntity.Name) {
+					userEntity.Name = "匿名-" + strutils.SimpleUUID()[0:8]
+				}
 
-			if strutils.IsStringNotEmpty(userEntity.Phone) {
 				encryptedPhone, err := encoding.AESEncrypt(userEntity.Phone, simple.AESKey)
 				if err != nil {
 					return errors.New(err.Error())
 				}
 
 				userEntity.Phone = encryptedPhone
-			}
 
-			if strutils.IsStringNotEmpty(userEntity.Email) {
 				encryptedEmail, err := encoding.AESEncrypt(userEntity.Email, simple.AESKey)
 				if err != nil {
 					return errors.New(err.Error())
 				}
 
 				userEntity.Email = encryptedEmail
-			}
 
-			checkResult := check.Struct(userEntity, fieldMap)
+				checkResult := check.Struct(userEntity, fieldMap)
 
-			if strutils.IsStringNotEmpty(userEntity.Password) {
-				err := domain.CheckField(checkResult, e.DomainCNName(), FieldPassword)
+				err = domain.CheckField(checkResult, userEntity.DomainCNName(), FieldPassword)
 				if err != nil {
 					return err
 				}
-			}
 
-			if strutils.IsStringNotEmpty(userEntity.Name) {
-				err := domain.CheckField(checkResult, e.DomainCNName(), FieldName)
+				err = domain.CheckField(checkResult, userEntity.DomainCNName(), FieldName)
 				if err != nil {
 					return err
 				}
-			}
 
-			if strutils.IsStringNotEmpty(userEntity.Phone) {
-				err := domain.CheckField(checkResult, e.DomainCNName(), FieldPhone)
+				err = domain.CheckField(checkResult, userEntity.DomainCNName(), FieldPhone)
 				if err != nil {
 					return err
 				}
-			}
 
-			if strutils.IsStringNotEmpty(userEntity.Email) {
-				err := domain.CheckField(checkResult, e.DomainCNName(), FieldEmail)
+				err = domain.CheckField(checkResult, userEntity.DomainCNName(), FieldEmail)
 				if err != nil {
 					return err
 				}
-			}
 
-			return nil
-		},
-	}), entity_crud.WithQueryConditionFieldCallback[Info](func(conditions *sql.Conditions, fieldName string, columnName string, value any) (hasDeal bool, err error) {
-		if value == nil {
-			return true, nil
-		}
-
-		switch fieldName {
-		case FieldUserName:
-			userName, ok := value.(string)
-			if !ok {
-				return false, errors.New("用户名字段类型不是string")
-			}
+				return nil
+			},
+		}), entity_crud.WithUpdateCallbacks(&entity_crud.UpdateCallbacks{
+			Before: func(e entity.Entity, prepared map[string]any, i *infrastructure.Infrastructure, tx database.Executor) error {
+				userEntity, err := domain.ToConcrete[*Entity](e)
+				if err != nil {
+					return err
+				}
 
-			if strutils.IsStringNotEmpty(userName) {
-				conditions.Like(ColumnUserName, "%"+userName+"%")
-			}
+				if strutils.IsStringNotEmpty(userEntity.Password) {
+					encryptedPassword, err := encoding.AESEncrypt(userEntity.Password, simple.AESKey)
+					if err != nil {
+						return errors.New(err.Error())
+					}
 
-			return true, nil
-		case FieldName:
-			name, ok := value.(string)
-			if !ok {
-				return false, errors.New("姓名字段类型不是string")
-			}
+					userEntity.Password = encryptedPassword
+				}
 
-			if strutils.IsStringNotEmpty(name) {
-				conditions.Like(ColumnName, "%"+name+"%")
-			}
+				if strutils.IsStringEmpty(userEntity.Name) {
+					userEntity.Name = "匿名-" + strutils.SimpleUUID()[0:8]
+				}
 
-			return true, nil
-		case FieldPhone:
-			phone, ok := value.(string)
-			if !ok {
-				return false, errors.New("手机号字段类型不是string")
-			}
+				if strutils.IsStringNotEmpty(userEntity.Phone) {
+					encryptedPhone, err := encoding.AESEncrypt(userEntity.Phone, simple.AESKey)
+					if err != nil {
+						return errors.New(err.Error())
+					}
 
-			if strutils.IsStringNotEmpty(phone) {
-				encryptedPassword, err := encoding.AESEncrypt(phone, simple.AESKey)
-				if err != nil {
-					return false, errors.New(err.Error())
+					userEntity.Phone = encryptedPhone
 				}
 
-				conditions.Equal(ColumnPassword, encryptedPassword)
-			}
+				if strutils.IsStringNotEmpty(userEntity.Email) {
+					encryptedEmail, err := encoding.AESEncrypt(userEntity.Email, simple.AESKey)
+					if err != nil {
+						return errors.New(err.Error())
+					}
 
-			return true, nil
-		case FieldEmail:
-			email, ok := value.(string)
-			if !ok {
-				return false, errors.New("邮箱字段类型不是string")
-			}
+					userEntity.Email = encryptedEmail
+				}
 
-			if strutils.IsStringNotEmpty(email) {
-				encryptedPassword, err := encoding.AESEncrypt(email, simple.AESKey)
-				if err != nil {
-					return false, errors.New(err.Error())
+				checkResult := check.Struct(userEntity, fieldMap)
+
+				if strutils.IsStringNotEmpty(userEntity.Password) {
+					err := domain.CheckField(checkResult, e.DomainCNName(), FieldPassword)
+					if err != nil {
+						return err
+					}
 				}
 
-				conditions.Equal(ColumnPassword, encryptedPassword)
-			}
+				if strutils.IsStringNotEmpty(userEntity.Name) {
+					err := domain.CheckField(checkResult, e.DomainCNName(), FieldName)
+					if err != nil {
+						return err
+					}
+				}
 
-			return true, nil
-		default:
-			return false, nil
-		}
-	}), entity_crud.WithQueryCallbacks(&entity_crud.QueryCallbacks[Info]{
-		OnSuccessReturn: func(e entity.Entity, i *infrastructure.Infrastructure, output response.InfosData[Info]) (response.InfosData[Info], error) {
-			errResponse := response.InfosData[Info]{
-				Infos: make([]Info, 0),
+				if strutils.IsStringNotEmpty(userEntity.Phone) {
+					err := domain.CheckField(checkResult, e.DomainCNName(), FieldPhone)
+					if err != nil {
+						return err
+					}
+				}
+
+				if strutils.IsStringNotEmpty(userEntity.Email) {
+					err := domain.CheckField(checkResult, e.DomainCNName(), FieldEmail)
+					if err != nil {
+						return err
+					}
+				}
+
+				return nil
+			},
+		}), entity_crud.WithQueryConditionFieldCallback[Info](func(conditions *sql.Conditions, fieldName string, columnName string, value any) (hasDeal bool, err error) {
+			if value == nil {
+				return true, nil
 			}
 
-			retInfos := make([]Info, len(output.Infos))
-			infos := output.Infos
+			switch fieldName {
+			case FieldUserName:
+				userName, ok := value.(string)
+				if !ok {
+					return false, errors.New("用户名字段类型不是string")
+				}
+
+				if strutils.IsStringNotEmpty(userName) {
+					conditions.Like(ColumnUserName, "%"+userName+"%")
+				}
+
+				return true, nil
+			case FieldName:
+				name, ok := value.(string)
+				if !ok {
+					return false, errors.New("姓名字段类型不是string")
+				}
+
+				if strutils.IsStringNotEmpty(name) {
+					conditions.Like(ColumnName, "%"+name+"%")
+				}
 
-			for index, info := range infos {
-				if strutils.IsStringNotEmpty(info.Name) {
-					encryptedName, err := encoding.AESEncrypt(info.Name, simple.AESKey)
+				return true, nil
+			case FieldPhone:
+				phone, ok := value.(string)
+				if !ok {
+					return false, errors.New("手机号字段类型不是string")
+				}
+
+				if strutils.IsStringNotEmpty(phone) {
+					encryptedPassword, err := encoding.AESEncrypt(phone, simple.AESKey)
 					if err != nil {
-						return errResponse, errors.New(err.Error())
+						return false, errors.New(err.Error())
 					}
 
-					info.Name = encryptedName
+					conditions.Equal(ColumnPassword, encryptedPassword)
+				}
+
+				return true, nil
+			case FieldEmail:
+				email, ok := value.(string)
+				if !ok {
+					return false, errors.New("邮箱字段类型不是string")
 				}
 
-				if strutils.IsStringNotEmpty(info.Email) {
-					encryptedEmail, err := encoding.AESEncrypt(info.Email, simple.AESKey)
+				if strutils.IsStringNotEmpty(email) {
+					encryptedPassword, err := encoding.AESEncrypt(email, simple.AESKey)
 					if err != nil {
-						return errResponse, errors.New(err.Error())
+						return false, errors.New(err.Error())
 					}
 
-					info.Email = encryptedEmail
+					conditions.Equal(ColumnPassword, encryptedPassword)
 				}
 
-				retInfos[index] = info
+				return true, nil
+			default:
+				return false, nil
 			}
+		}), entity_crud.WithQueryCallbacks(&entity_crud.QueryCallbacks[Info]{
+			OnSuccessReturn: func(e entity.Entity, i *infrastructure.Infrastructure, output response.InfosData[Info]) (response.InfosData[Info], error) {
+				errResponse := response.InfosData[Info]{
+					Infos: make([]Info, 0),
+				}
 
-			return response.InfosData[Info]{
-				Infos:      retInfos,
-				TotalCount: output.TotalCount,
-				PageNo:     output.PageNo,
-			}, nil
-		},
-	}), entity_crud.WithGetByIDCallbacks(&entity_crud.GetByIDCallbacks[Info]{
-		OnSuccessReturn: func(e entity.Entity, i *infrastructure.Infrastructure, output Info) (Info, error) {
-			if strutils.IsStringNotEmpty(output.Name) {
-				encryptedName, err := encoding.AESEncrypt(output.Name, simple.AESKey)
-				if err != nil {
-					return Info{}, errors.New(err.Error())
+				retInfos := make([]Info, len(output.Infos))
+				infos := output.Infos
+
+				for index, info := range infos {
+					if strutils.IsStringNotEmpty(info.Name) {
+						encryptedName, err := encoding.AESEncrypt(info.Name, simple.AESKey)
+						if err != nil {
+							return errResponse, errors.New(err.Error())
+						}
+
+						info.Name = encryptedName
+					}
+
+					if strutils.IsStringNotEmpty(info.Email) {
+						encryptedEmail, err := encoding.AESEncrypt(info.Email, simple.AESKey)
+						if err != nil {
+							return errResponse, errors.New(err.Error())
+						}
+
+						info.Email = encryptedEmail
+					}
+
+					retInfos[index] = info
 				}
 
-				output.Name = encryptedName
-			}
+				return response.InfosData[Info]{
+					Infos:      retInfos,
+					TotalCount: output.TotalCount,
+					PageNo:     output.PageNo,
+				}, nil
+			},
+		}), entity_crud.WithGetByIDCallbacks(&entity_crud.GetByIDCallbacks[Info]{
+			OnSuccessReturn: func(e entity.Entity, i *infrastructure.Infrastructure, output Info) (Info, error) {
+				if strutils.IsStringNotEmpty(output.Name) {
+					encryptedName, err := encoding.AESEncrypt(output.Name, simple.AESKey)
+					if err != nil {
+						return Info{}, errors.New(err.Error())
+					}
 
-			if strutils.IsStringNotEmpty(output.Email) {
-				encryptedEmail, err := encoding.AESEncrypt(output.Email, simple.AESKey)
-				if err != nil {
-					return Info{}, errors.New(err.Error())
+					output.Name = encryptedName
 				}
 
-				output.Email = encryptedEmail
-			}
+				if strutils.IsStringNotEmpty(output.Email) {
+					encryptedEmail, err := encoding.AESEncrypt(output.Email, simple.AESKey)
+					if err != nil {
+						return Info{}, errors.New(err.Error())
+					}
+
+					output.Email = encryptedEmail
+				}
 
-			return output, nil
-		},
-	}))
+				return output, nil
+			},
+		}))
 }