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" "git.sxidc.com/go-framework/baize/convenient/domain/auth/relations" "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/framework/binding" "git.sxidc.com/go-framework/baize/framework/core/api" "git.sxidc.com/go-framework/baize/framework/core/api/request" "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/domain/entity" "git.sxidc.com/go-framework/baize/framework/core/infrastructure" "git.sxidc.com/go-framework/baize/framework/core/infrastructure/database" "git.sxidc.com/go-framework/baize/framework/core/infrastructure/database/sql" "git.sxidc.com/go-tools/utils/encoding" "github.com/pkg/errors" ) // Simple Bind参数 type Simple struct { // schema Schema string // AES加密用到的Key AESKey string // JWT的Key JWTSecretKey string // JWT到期时间 JWTExpiredSec int64 } 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) (&user.Simple{Schema: simple.Schema, AESKey: simple.AESKey}).Bind(binder) (&relations.Simple{Schema: simple.Schema}).Bind(binder) // 登录 binding.PostBind(binder, &binding.SimpleBindItem[map[string]any]{ Path: "/login", SendResponseFunc: response.SendMapResponse, RequestParams: &LoginJsonBody{}, ServiceFunc: func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (map[string]any, error) { errResponse := map[string]any{ "token": "", } jsonBody, err := request.ToConcrete[*LoginJsonBody](params) if err != nil { return errResponse, err } encryptedPassword, err := encoding.AESEncrypt(jsonBody.Password, simple.AESKey) if err != nil { return errResponse, errors.New(err.Error()) } userTableName := domain.TableName(simple.Schema, &user.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), }) if err != nil { if database.IsErrorDBRecordNotExist(err) { return errResponse, errors.New("用户名或密码错误") } return errResponse, errors.New(err.Error()) } existUser := new(user.Entity) err = sql.ParseSqlResult(result, existUser) if err != nil { return errResponse, err } token, err := jwt_tools.NewJWT(existUser.ID, simple.JWTExpiredSec) if err != nil { return errResponse, 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 err != nil { return errResponse, errors.New(err.Error()) } return map[string]any{ "token": token, }, nil }, }) // 注销 binding.PostBind(binder, &binding.SimpleBindItem[any]{ Path: "/logout", SendResponseFunc: response.SendMsgResponse, ServiceFunc: func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) { userInfo := c.GetUserInfo() 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 nil, 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), } userInfo := c.GetUserInfo() userAndRoleTableName := domain.RelationTableName(simple.Schema, &user.Entity{}, &role.Entity{}) roleTableName := domain.TableName(simple.Schema, &role.Entity{}) dbExecutor := i.DBExecutor() 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 { return errInfo, errors.New(err.Error()) } if totalCount == 0 { return UserWithRoleInfo{ UserInfo: *(userInfo.(*user.Info)), RoleInfos: make([]role.Info, 0), }, nil } roleIDs := make([]string, len(roleIDResults)) for index, roleIDResult := range roleIDResults { roleIDs[index] = roleIDResult.ColumnValueString(domain.RelationColumnName(&role.Entity{})) } 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 errInfo, errors.New(err.Error()) } 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 errInfo, errors.New(err.Error()) } return UserWithRoleInfo{ UserInfo: *(userInfo.(*user.Info)), RoleInfos: roleInfos, }, nil }, }, middlewares.Authentication()) } func BindAuth(binder *binding.Binder, simple *Simple) { simple.bind(binder) }