package platform 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" ) // LoginRequest 是平台总后台的账号密码登录请求。 type LoginRequest struct { Username string `json:"username" binding:"required,max=64"` Password string `json:"password" binding:"required,min=8,max=128"` } // LoginReply 是后台登录成功后的访问凭证与账号状态。 type LoginReply struct { AccessToken string `json:"access_token"` TokenType string `json:"token_type"` Identity string `json:"identity"` DisplayName string `json:"display_name"` RoleCode string `json:"role_code"` } // Login 校验平台账号密码并签发 BSM 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.PlatformAccount err := impl.DBService.Where("username = ?", strings.TrimSpace(request.Username)).First(&account).Error if err != nil { if err == gorm.ErrRecordNotFound { infra.Response.Error(ctx, errcode.ErrPassword) return } infra.Response.Error(ctx, err) return } if account.Status != "enabled" { infra.Response.Error(ctx, errcode.ErrAccountDisabled) return } if 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, "platform_admin", account.PlatformRoleCode, map[string]string{"username": account.Username, "display_name": account.DisplayName}, nil, ) if err != nil { infra.Response.Error(ctx, err) return } infra.Response.Success(ctx, LoginReply{ AccessToken: accessToken, TokenType: "JWT", Identity: account.Identity, DisplayName: account.DisplayName, RoleCode: account.PlatformRoleCode, }) } // CurrentProfile 返回当前已认证的平台管理员资料。 func CurrentProfile(ctx *gin.Context) { claims, err := middleware.ParseAuth(ctx) if err != nil { infra.Response.Error(ctx, err) return } var account models.PlatformAccount if err := impl.DBService.Where("identity = ?", claims.Identity).First(&account).Error; err != nil { infra.Response.Error(ctx, errcode.ErrRecordNotFound) return } menus, err := common.LoadPlatformMenus(account.PlatformRoleCode) if err != nil { infra.Response.Error(ctx, errcode.ErrPermissionDenied) return } menuCodes := make([]string, 0, len(menus)) seenMenuCodes := make(map[string]bool, len(menus)) for _, menu := range menus { codes := []string{menu.MenuCode} if path := strings.Trim(menu.Path, "/"); path != "" { codes = append(codes, strings.Split(path, "/")[0]) } for _, code := range codes { if code != "" && !seenMenuCodes[code] { menuCodes = append(menuCodes, code) seenMenuCodes[code] = true } } } infra.Response.Success(ctx, gin.H{ "identity": account.Identity, "username": account.Username, "display_name": account.DisplayName, "avatar": account.Avatar, "role_code": account.PlatformRoleCode, "menu_codes": menuCodes, }) } // 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"` } // ChangePassword 修改当前账号密码并解除首次登录改密限制。 func ChangePassword(ctx *gin.Context) { claims, err := middleware.ParseAuth(ctx) if err != nil { infra.Response.Error(ctx, err) return } var request ChangePasswordRequest if err := ctx.ShouldBindJSON(&request); err != nil { 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) return } if bcrypt.CompareHashAndPassword([]byte(account.PasswordHash), []byte(request.CurrentPassword)) != nil { infra.Response.Error(ctx, errcode.ErrPassword) return } passwordHash, err := bcrypt.GenerateFromPassword([]byte(request.NewPassword), bcrypt.DefaultCost) if err != nil { infra.Response.Error(ctx, err) return } if err := impl.DBService.Model(&account).Update("password_hash", string(passwordHash)).Error; err != nil { infra.Response.Error(ctx, err) return } infra.Response.Success(ctx, gin.H{"changed": true}) }