155 lines
5.5 KiB
Go
155 lines
5.5 KiB
Go
|
|
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
|
||
|
|
}
|