114 lines
2.5 KiB
Go
114 lines
2.5 KiB
Go
package middleware
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"affiliate_dash/internal/pkg/jwt"
|
|
"affiliate_dash/internal/pkg/response"
|
|
"affiliate_dash/internal/service"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
const (
|
|
CtxUserID = "user_id"
|
|
CtxUsername = "username"
|
|
CtxRole = "role"
|
|
CtxMerchantRole = "merchant_role"
|
|
)
|
|
|
|
func Auth(jm *jwt.Manager) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
auth := c.GetHeader("Authorization")
|
|
if auth == "" {
|
|
response.Unauthorized(c, "未登录")
|
|
c.Abort()
|
|
return
|
|
}
|
|
parts := strings.SplitN(auth, " ", 2)
|
|
if len(parts) != 2 || !strings.EqualFold(parts[0], "Bearer") {
|
|
response.Unauthorized(c, "无效的认证头")
|
|
c.Abort()
|
|
return
|
|
}
|
|
claims, err := jm.Parse(parts[1])
|
|
if err != nil {
|
|
response.Unauthorized(c, "登录已过期,请重新登录")
|
|
c.Abort()
|
|
return
|
|
}
|
|
c.Set(CtxUserID, claims.UserID)
|
|
c.Set(CtxUsername, claims.Username)
|
|
c.Set(CtxRole, claims.Role)
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
func RequireRole(roles ...string) gin.HandlerFunc {
|
|
set := make(map[string]struct{}, len(roles))
|
|
for _, r := range roles {
|
|
set[r] = struct{}{}
|
|
}
|
|
return func(c *gin.Context) {
|
|
role, _ := c.Get(CtxRole)
|
|
roleStr, _ := role.(string)
|
|
if _, ok := set[roleStr]; !ok {
|
|
response.Forbidden(c, "权限不足")
|
|
c.Abort()
|
|
return
|
|
}
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
func GetUserID(c *gin.Context) uint {
|
|
v, _ := c.Get(CtxUserID)
|
|
id, _ := v.(uint)
|
|
return id
|
|
}
|
|
|
|
func GetRole(c *gin.Context) string {
|
|
v, _ := c.Get(CtxRole)
|
|
role, _ := v.(string)
|
|
return role
|
|
}
|
|
|
|
// Tenant 根据 X-Merchant-ID(商户 ID 或编码)解析当前后台请求所属商户。
|
|
// 未指定时选择该账号的默认商户,确保旧后台继续落到“自营商户”。
|
|
func Tenant(tenantSvc *service.TenantService) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
member, err := tenantSvc.ResolveMember(GetUserID(c), c.GetHeader("X-Merchant-ID"))
|
|
if err != nil {
|
|
response.Forbidden(c, err.Error())
|
|
c.Abort()
|
|
return
|
|
}
|
|
c.Set(CtxMerchantID, member.MerchantID)
|
|
c.Set(CtxMerchantRole, member.Role)
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
func RequireMerchantRole(roles ...string) gin.HandlerFunc {
|
|
allowed := make(map[string]struct{}, len(roles))
|
|
for _, role := range roles {
|
|
allowed[role] = struct{}{}
|
|
}
|
|
return func(c *gin.Context) {
|
|
value, _ := c.Get(CtxMerchantRole)
|
|
role, _ := value.(string)
|
|
if _, ok := allowed[role]; !ok {
|
|
response.Forbidden(c, "商户权限不足")
|
|
c.Abort()
|
|
return
|
|
}
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
func GetMerchantRole(c *gin.Context) string {
|
|
value, _ := c.Get(CtxMerchantRole)
|
|
role, _ := value.(string)
|
|
return role
|
|
}
|