161 lines
5.1 KiB
Go
161 lines
5.1 KiB
Go
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 != common.StatusEnable {
|
|
infra.Response.Error(ctx, errcode.ErrAccountDisabled)
|
|
return
|
|
}
|
|
if bcrypt.CompareHashAndPassword([]byte(account.PasswordHash), []byte(request.Password)) != nil {
|
|
infra.Response.Error(ctx, errcode.ErrPassword)
|
|
return
|
|
}
|
|
|
|
extend := map[string]string{"username": account.Username, "display_name": account.DisplayName}
|
|
if account.PlatformRoleCode == "root" {
|
|
extend["location_scope"] = "precise"
|
|
} else {
|
|
var role models.PlatformRole
|
|
if impl.DBService.Select("location_scope").Where("role_code = ? AND status = ?", account.PlatformRoleCode, common.StatusEnable).First(&role).Error == nil &&
|
|
role.LocationScope == "precise" {
|
|
extend["location_scope"] = "precise"
|
|
}
|
|
}
|
|
accessToken, err := token.New(env.Runtime.JwtSecretKey).GenerateJwt(
|
|
0,
|
|
account.Identity,
|
|
"platform_admin",
|
|
account.PlatformRoleCode,
|
|
extend,
|
|
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 := 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 {
|
|
if menu.Identity != "" && !seenMenuCodes[menu.Identity] {
|
|
menuCodes = append(menuCodes, menu.Identity)
|
|
seenMenuCodes[menu.Identity] = 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})
|
|
}
|