Files
platforms/backend/api/internal/logic/delivery/auth.go

139 lines
5.2 KiB
Go

package delivery
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"
)
func Login(ctx *gin.Context) {
var request struct {
Username string `json:"username" binding:"required,max=64"`
Password string `json:"password" binding:"required"`
}
if err := ctx.ShouldBindJSON(&request); err != nil {
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
return
}
var account models.DeliveryAccount
if err := impl.DBService.Where("username = ?", strings.TrimSpace(request.Username)).First(&account).Error; err != nil {
infra.Response.Error(ctx, errcode.ErrPassword)
return
}
var point models.DeliveryBasic
var station models.GasBasic
if account.Status != common.StatusEnable || account.RoleCode != "admin" ||
impl.DBService.First(&point, account.DeliveryBasicID).Error != nil || point.Status != common.StatusEnable ||
impl.DBService.First(&station, point.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, "delivery_admin", account.RoleCode, nil,
map[string]string{"delivery_basic_identity": point.Identity, "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,
"delivery_basic_identity": point.Identity, "gas_basic_identity": station.Identity,
})
}
func RequireDeliveryAdmin() gin.HandlerFunc {
return func(ctx *gin.Context) {
claims, err := middleware.ParseAuth(ctx)
if err != nil || claims.Client != "delivery_admin" || claims.Role != "admin" || claims.Extend["delivery_basic_identity"] == "" {
infra.Response.Error(ctx, errcode.ErrPermissionDenied)
ctx.Abort()
return
}
var count int64
err = impl.DBService.Model(&models.DeliveryAccount{}).
Joins("JOIN delivery_basic ON delivery_basic.id = delivery_account.delivery_basic_id").
Where("delivery_account.identity = ? AND delivery_account.status = ? AND delivery_account.role_code = ? AND delivery_basic.identity = ? AND delivery_basic.status = ?",
claims.Identity, common.StatusEnable, "admin", claims.Extend["delivery_basic_identity"], common.StatusEnable).
Count(&count).Error
if err != nil || count != 1 {
infra.Response.Error(ctx, errcode.ErrPermissionDenied)
ctx.Abort()
return
}
ctx.Next()
}
}
func CurrentDeliveryAccount(ctx *gin.Context) (models.DeliveryAccount, models.DeliveryBasic, models.GasBasic, bool) {
claims, err := middleware.ParseAuth(ctx)
if err != nil {
infra.Response.Error(ctx, err)
return models.DeliveryAccount{}, models.DeliveryBasic{}, models.GasBasic{}, false
}
var account models.DeliveryAccount
var point models.DeliveryBasic
var station models.GasBasic
if err := impl.DBService.Where("identity = ?", claims.Identity).First(&account).Error; err != nil ||
impl.DBService.First(&point, account.DeliveryBasicID).Error != nil ||
impl.DBService.First(&station, point.GasBasicID).Error != nil {
infra.Response.Error(ctx, errcode.ErrRecordNotFound)
return account, point, station, false
}
return account, point, station, true
}
func CurrentProfile(ctx *gin.Context) {
account, point, station, ok := CurrentDeliveryAccount(ctx)
if !ok {
return
}
menus := MenusForRole(account.RoleCode)
codes := make([]string, 0, len(menus))
for _, menu := range menus {
codes = append(codes, menu.Identity)
}
infra.Response.Success(ctx, gin.H{
"identity": account.Identity, "username": account.Username, "display_name": account.DisplayName,
"role_code": account.RoleCode, "delivery_basic_identity": point.Identity, "delivery_basic_name": point.Name,
"gas_basic_identity": station.Identity, "menu_codes": codes,
})
}
func ChangePassword(ctx *gin.Context) {
account, _, _, ok := CurrentDeliveryAccount(ctx)
if !ok {
return
}
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) ||
bcrypt.CompareHashAndPassword([]byte(account.PasswordHash), []byte(request.CurrentPassword)) != nil {
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
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})
}