package gas import ( "strings" "git.apinb.com/bsm-sdk/core/crypto/token" "git.apinb.com/bsm-sdk/core/env" "git.apinb.com/bsm-sdk/core/errcode" "git.apinb.com/bsm-sdk/core/infra" "git.apinb.com/bsm-sdk/core/middleware" "git.apinb.com/heqiapp/platforms/backend/api/internal/impl" "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common" "git.apinb.com/heqiapp/platforms/backend/api/internal/models" "github.com/gin-gonic/gin" "golang.org/x/crypto/bcrypt" "gorm.io/gorm" ) type loginRequest struct { Username string `json:"username" binding:"required,max=64"` Password string `json:"password" binding:"required"` } // Login 校验气站账号并签发独立 gas_admin JWT。 func Login(ctx *gin.Context) { var request loginRequest if err := ctx.ShouldBindJSON(&request); err != nil { infra.Response.Error(ctx, errcode.ErrInvalidArgument) return } var account models.GasAccount err := impl.DBService.Where("username = ?", strings.TrimSpace(request.Username)).First(&account).Error if err != nil { infra.Response.Error(ctx, errcode.ErrPassword) return } var station models.GasBasic if account.Status != common.StatusEnable || account.RoleCode != "admin" || impl.DBService.First(&station, account.GasBasicID).Error != nil || station.Status != common.StatusEnable || bcrypt.CompareHashAndPassword([]byte(account.PasswordHash), []byte(request.Password)) != nil { infra.Response.Error(ctx, errcode.ErrPassword) return } accessToken, err := token.New(env.Runtime.JwtSecretKey).GenerateJwt( 0, account.Identity, "gas_admin", account.RoleCode, nil, map[string]string{"gas_basic_identity": station.Identity, "username": account.Username, "display_name": account.DisplayName}, ) if err != nil { infra.Response.Error(ctx, err) return } infra.Response.Success(ctx, gin.H{ "access_token": accessToken, "token_type": "JWT", "identity": account.Identity, "display_name": account.DisplayName, "role_code": account.RoleCode, "gas_basic_identity": station.Identity, }) } // RequireGasAdmin 拒绝平台令牌和非本站管理员令牌。 func RequireGasAdmin() gin.HandlerFunc { return func(ctx *gin.Context) { claims, err := middleware.ParseAuth(ctx) if err != nil || claims.Client != "gas_admin" || claims.Role != "admin" || claims.Extend["gas_basic_identity"] == "" { infra.Response.Error(ctx, errcode.ErrPermissionDenied) ctx.Abort() return } var count int64 err = impl.DBService.Model(&models.GasAccount{}). Joins("JOIN gas_basic ON gas_basic.id = gas_account.gas_basic_id"). Where("gas_account.identity = ? AND gas_account.status = ? AND gas_account.role_code = ? AND gas_basic.identity = ? AND gas_basic.status = ?", claims.Identity, common.StatusEnable, "admin", claims.Extend["gas_basic_identity"], common.StatusEnable). Count(&count).Error if err != nil || count != 1 { infra.Response.Error(ctx, errcode.ErrPermissionDenied) ctx.Abort() return } ctx.Next() } } // CurrentProfile 返回气站账号、所属气站和菜单。 func CurrentProfile(ctx *gin.Context) { account, station, ok := CurrentGasAccount(ctx) if !ok { return } menus := MenusForRole(account.RoleCode) menuCodes := make([]string, 0, len(menus)) for _, menu := range menus { menuCodes = append(menuCodes, menu.Identity) } infra.Response.Success(ctx, gin.H{ "identity": account.Identity, "username": account.Username, "display_name": account.DisplayName, "role_code": account.RoleCode, "gas_basic_identity": station.Identity, "gas_basic_name": station.Name, "menu_codes": menuCodes, }) } // ChangePassword 修改当前气站账号密码。 func ChangePassword(ctx *gin.Context) { var request struct { CurrentPassword string `json:"current_password" binding:"required"` NewPassword string `json:"new_password" binding:"required"` } if err := ctx.ShouldBindJSON(&request); err != nil || !common.IsValidAccountPassword(request.NewPassword) { infra.Response.Error(ctx, errcode.ErrInvalidArgument) return } claims, _ := middleware.ParseAuth(ctx) var account models.GasAccount if err := impl.DBService.Where("identity = ?", claims.Identity).First(&account).Error; err != nil { infra.Response.Error(ctx, errcode.ErrRecordNotFound) return } if bcrypt.CompareHashAndPassword([]byte(account.PasswordHash), []byte(request.CurrentPassword)) != nil { infra.Response.Error(ctx, errcode.ErrPassword) return } hash, err := common.PasswordHash(request.NewPassword) if err != nil { infra.Response.Error(ctx, err) return } if err := impl.DBService.Model(&account).Update("password_hash", hash).Error; err != nil { infra.Response.Error(ctx, err) return } infra.Response.Success(ctx, gin.H{"changed": true}) } // CurrentGasAccount 解析当前账户和气站。 func CurrentGasAccount(ctx *gin.Context) (models.GasAccount, models.GasBasic, bool) { claims, err := middleware.ParseAuth(ctx) if err != nil { infra.Response.Error(ctx, err) return models.GasAccount{}, models.GasBasic{}, false } var account models.GasAccount if err := impl.DBService.Where("identity = ?", claims.Identity).First(&account).Error; err != nil { if err == gorm.ErrRecordNotFound { infra.Response.Error(ctx, errcode.ErrRecordNotFound) } else { infra.Response.Error(ctx, err) } return models.GasAccount{}, models.GasBasic{}, false } var station models.GasBasic if err := impl.DBService.First(&station, account.GasBasicID).Error; err != nil { infra.Response.Error(ctx, errcode.ErrRecordNotFound) return models.GasAccount{}, models.GasBasic{}, false } return account, station, true }