package web import ( "context" "time" ) // UserInfo represents user information with tracking details type UserInfo struct { UserID string `json:"user_id"` UserName string `json:"user_name"` Trace string `json:"trace"` VisitTime time.Time `json:"visit_time"` FromIP string `json:"from_ip"` } // contextKey is the type for context keys to prevent collisions type contextKey string const ( // Context keys for each field UserIDKey contextKey = "userID" UserNameKey contextKey = "userName" TraceKey contextKey = "trace" VisitTimeKey contextKey = "visitTime" FromIPKey contextKey = "fromIP" ) // GetUserID returns user ID from context func GetUserID(ctx context.Context) string { if ctx == nil { return "" } if val, ok := ctx.Value(UserIDKey).(string); ok { return val } return "" } // SetUserID sets user ID in context and returns new context func SetUserID(ctx context.Context, userID string) context.Context { if ctx == nil { ctx = context.Background() } return context.WithValue(ctx, UserIDKey, userID) } // GetUserName returns user name from context func GetUserName(ctx context.Context) string { if ctx == nil { return "" } if val, ok := ctx.Value(UserNameKey).(string); ok { return val } return "" } // SetUserName sets user name in context and returns new context func SetUserName(ctx context.Context, userName string) context.Context { if ctx == nil { ctx = context.Background() } return context.WithValue(ctx, UserNameKey, userName) } // GetTrace returns trace ID from context func GetTrace(ctx context.Context) string { if ctx == nil { return "" } if val, ok := ctx.Value(TraceKey).(string); ok { return val } return "" } // SetTrace sets trace ID in context and returns new context func SetTrace(ctx context.Context, trace string) context.Context { if ctx == nil { ctx = context.Background() } return context.WithValue(ctx, TraceKey, trace) } // GetVisitTime returns visit time from context func GetVisitTime(ctx context.Context) time.Time { if ctx == nil { return time.Time{} } if val, ok := ctx.Value(VisitTimeKey).(time.Time); ok { return val } return time.Time{} } // SetVisitTime sets visit time in context and returns new context func SetVisitTime(ctx context.Context, visitTime time.Time) context.Context { if ctx == nil { ctx = context.Background() } return context.WithValue(ctx, VisitTimeKey, visitTime) } // GetFromIP returns from IP from context func GetFromIP(ctx context.Context) string { if ctx == nil { return "" } if val, ok := ctx.Value(FromIPKey).(string); ok { return val } return "" } // SetFromIP sets from IP in context and returns new context func SetFromIP(ctx context.Context, fromIP string) context.Context { if ctx == nil { ctx = context.Background() } return context.WithValue(ctx, FromIPKey, fromIP) } // FromContext builds UserInfo from individual context fields // Returns nil if no fields are found func FromContext(ctx context.Context) *UserInfo { if ctx == nil { return nil } info := &UserInfo{} hasData := false if userID := GetUserID(ctx); userID != "" { info.UserID = userID hasData = true } if userName := GetUserName(ctx); userName != "" { info.UserName = userName hasData = true } if trace := GetTrace(ctx); trace != "" { info.Trace = trace hasData = true } if visitTime := GetVisitTime(ctx); !visitTime.IsZero() { info.VisitTime = visitTime hasData = true } if fromIP := GetFromIP(ctx); fromIP != "" { info.FromIP = fromIP hasData = true } if !hasData { return nil } return info } // ToContext sets all UserInfo fields to context and returns new context func ToContext(ctx context.Context, userInfo *UserInfo) context.Context { if ctx == nil { ctx = context.Background() } if userInfo == nil { return ctx } ctx = SetUserID(ctx, userInfo.UserID) ctx = SetUserName(ctx, userInfo.UserName) ctx = SetTrace(ctx, userInfo.Trace) ctx = SetVisitTime(ctx, userInfo.VisitTime) ctx = SetFromIP(ctx, userInfo.FromIP) return ctx } // NewUserInfo creates a new UserInfo instance func NewUserInfo() *UserInfo { return &UserInfo{ VisitTime: time.Now(), } } // WithUserID sets the user ID func (u *UserInfo) WithUserID(userID string) *UserInfo { u.UserID = userID return u } // WithUserName sets the user name func (u *UserInfo) WithUserName(userName string) *UserInfo { u.UserName = userName return u } // WithTrace sets the trace ID func (u *UserInfo) WithTrace(trace string) *UserInfo { u.Trace = trace return u } // WithFromIP sets the from IP address func (u *UserInfo) WithFromIP(ip string) *UserInfo { u.FromIP = ip return u } // WithVisitTime sets the visit time func (u *UserInfo) WithVisitTime(visitTime time.Time) *UserInfo { u.VisitTime = visitTime return u }