Files
lone-services/bff/internal/response/user.go
T
2026-09-02 17:37:12 +08:00

175 lines
5.4 KiB
Go

package response
import (
"context"
"lone-services/pkg/utils"
"net/http"
"net/url"
"strconv"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)
type ctxKey string
const (
CtxUserId ctxKey = "X-User-Id"
CtxUserName ctxKey = "X-User-Name"
CtxRefresh ctxKey = "X-Refresh"
CtxClientIP ctxKey = "X-Client-Ip"
CtxUserAgent ctxKey = "X-User-Agent"
CtxClientCode ctxKey = "X-Client-Code"
CtxSaleId ctxKey = "X-Sale-Id"
CtxSaleName ctxKey = "X-Sale-Name"
CtxSaleMobile ctxKey = "X-Sale-Mobile"
CtxSaleProvince ctxKey = "X-Sale-Province"
CtxStoreId ctxKey = "X-Store-Id"
CtxStoreName ctxKey = "X-Store-Name"
CtxGroupId ctxKey = "X-Group-Id"
CtxGroupName ctxKey = "X-Group-Name"
CtxUserType ctxKey = "X-User-Type"
)
type UserInfo struct {
ID int64
Name string
RawUID string
Refresh string
ClientIP string
UserAgent string
Type string
ClientCode string
SaleId string
SaleName string
SaleMobile string
SaleProvince string
StoreId string
StoreName string
GroupId string
GroupName string
Valid bool
}
func GetUserInfo(ctx context.Context) UserInfo {
rawUID, _ := ctx.Value(CtxUserId).(string)
name, _ := ctx.Value(CtxUserName).(string)
refresh, _ := ctx.Value(CtxRefresh).(string)
clientIP, _ := ctx.Value(CtxClientIP).(string)
userAgent, _ := ctx.Value(CtxUserAgent).(string)
userType, _ := ctx.Value(CtxUserType).(string)
clientCode, _ := ctx.Value(CtxClientCode).(string)
saleId, _ := ctx.Value(CtxSaleId).(string)
saleName, _ := ctx.Value(CtxSaleName).(string)
saleMobile, _ := ctx.Value(CtxSaleMobile).(string)
saleProvince, _ := ctx.Value(CtxSaleProvince).(string)
storeId, _ := ctx.Value(CtxStoreId).(string)
storeName, _ := ctx.Value(CtxStoreName).(string)
groupId, _ := ctx.Value(CtxGroupId).(string)
groupName, _ := ctx.Value(CtxGroupName).(string)
info := UserInfo{
RawUID: rawUID,
Name: name,
Refresh: refresh,
ClientIP: clientIP,
UserAgent: userAgent,
Type: userType,
ClientCode: clientCode,
SaleId: saleId,
SaleName: saleName,
SaleMobile: saleMobile,
SaleProvince: saleProvince,
StoreId: storeId,
StoreName: storeName,
GroupId: groupId,
GroupName: groupName,
}
if rawUID == "" {
return info
}
uid, err := strconv.ParseInt(rawUID, 10, 64)
if err != nil {
info.Valid = false
return info
}
info.ID = uid
info.Valid = true
return info
}
func getRealClientIP(r *http.Request) string {
xff := r.Header.Get("X-Forwarded-For")
if xff != "" {
return xff
}
xri := r.Header.Get("X-Real-Ip")
if xri != "" {
return xri
}
return r.RemoteAddr
}
func UserReadMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
newCtx := r.Context()
newCtx = context.WithValue(newCtx, CtxUserId, r.Header.Get("X-User-Id"))
newCtx = context.WithValue(newCtx, CtxUserName, r.Header.Get("X-User-Name"))
newCtx = context.WithValue(newCtx, CtxRefresh, r.Header.Get("X-Refresh"))
newCtx = context.WithValue(newCtx, CtxClientIP, getRealClientIP(r))
newCtx = context.WithValue(newCtx, CtxUserAgent, r.UserAgent())
newCtx = context.WithValue(newCtx, CtxUserType, r.Header.Get("X-User-Type"))
newCtx = context.WithValue(newCtx, CtxClientCode, r.Header.Get("X-Client-Code"))
newCtx = context.WithValue(newCtx, CtxSaleId, r.Header.Get("X-Sale-Id"))
newCtx = context.WithValue(newCtx, CtxSaleName, r.Header.Get("X-Sale-Name"))
newCtx = context.WithValue(newCtx, CtxSaleMobile, r.Header.Get("X-Sale-Mobile"))
newCtx = context.WithValue(newCtx, CtxSaleProvince, r.Header.Get("X-Sale-Province"))
newCtx = context.WithValue(newCtx, CtxStoreId, r.Header.Get("X-Store-Id"))
newCtx = context.WithValue(newCtx, CtxStoreName, r.Header.Get("X-Store-Name"))
newCtx = context.WithValue(newCtx, CtxGroupId, r.Header.Get("X-Group-Id"))
newCtx = context.WithValue(newCtx, CtxGroupName, r.Header.Get("X-Group-Name"))
next(w, r.WithContext(newCtx))
}
}
func setMDIfNotEmpty(md metadata.MD, key, value string) {
if value != utils.StringEmpty {
md.Set(key, value)
}
}
func UserClientInterceptor(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
user := GetUserInfo(ctx)
md := metadata.New(map[string]string{})
if user.Valid {
md.Set("x-user-id", user.RawUID)
md.Set("x-user-name", url.QueryEscape(user.Name))
}
setMDIfNotEmpty(md, "x-refresh", user.Refresh)
setMDIfNotEmpty(md, "x-client-ip", user.ClientIP)
if user.UserAgent != utils.StringEmpty {
md.Set("x-user-agent", url.QueryEscape(user.UserAgent))
}
setMDIfNotEmpty(md, "x-user-type", user.Type)
setMDIfNotEmpty(md, "x-client-code", user.ClientCode)
setMDIfNotEmpty(md, "x-sale-id", user.SaleId)
if user.SaleName != utils.StringEmpty {
md.Set("x-sale-name", url.QueryEscape(user.SaleName))
}
setMDIfNotEmpty(md, "x-sale-mobile", user.SaleMobile)
setMDIfNotEmpty(md, "x-sale-province", user.SaleProvince)
setMDIfNotEmpty(md, "x-store-id", user.StoreId)
if user.StoreName != utils.StringEmpty {
md.Set("x-store-name", url.QueryEscape(user.StoreName))
}
setMDIfNotEmpty(md, "x-group-id", user.GroupId)
if user.GroupName != utils.StringEmpty {
md.Set("x-group-name", url.QueryEscape(user.GroupName))
}
ctx = metadata.NewOutgoingContext(ctx, md)
return invoker(ctx, method, req, reply, cc, opts...)
}