- Introduced methods to set and retrieve authorized information from the context, enhancing the OAuth guard functionality. - Added a new `AuthorizedInfo` type to encapsulate user-related data such as subject, client ID, user ID, and scope. - Implemented session ID retrieval from various sources (cookies, headers, query strings) to improve session management. - Updated test utilities to support the creation of test users and access tokens, ensuring comprehensive testing of OAuth functionalities.
149 lines
3 KiB
Go
149 lines
3 KiB
Go
package user
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/yaoapp/gou/process"
|
|
"github.com/yaoapp/gou/session"
|
|
"github.com/yaoapp/kun/exception"
|
|
)
|
|
|
|
// Session Utilities
|
|
|
|
// GetUserIDFromSession gets the current user ID from session
|
|
// Returns the user ID string or throws an exception if not authenticated
|
|
func GetUserIDFromSession(process *process.Process) string {
|
|
sessionData, err := session.Global().ID(process.Sid).Get("__user_id")
|
|
if err != nil || sessionData == nil {
|
|
exception.New("user not authenticated", 401).Throw()
|
|
}
|
|
|
|
userIDStr, ok := sessionData.(string)
|
|
if !ok {
|
|
exception.New("invalid user_id in session", 401).Throw()
|
|
}
|
|
|
|
return userIDStr
|
|
}
|
|
|
|
// Type Conversion Utilities
|
|
|
|
// toBool converts various types to boolean
|
|
// Supports: bool, int, int64, float64, string
|
|
// Returns false for nil or unsupported types
|
|
func toBool(v interface{}) bool {
|
|
if v == nil {
|
|
return false
|
|
}
|
|
|
|
switch val := v.(type) {
|
|
case bool:
|
|
return val
|
|
case int:
|
|
return val != 0
|
|
case int64:
|
|
return val != 0
|
|
case float64:
|
|
return val != 0
|
|
case string:
|
|
return val == "true" || val == "1"
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// toString converts various types to string
|
|
// Supports: string, int, int64, float64, bool
|
|
// Returns empty string for nil or unsupported types
|
|
func toString(v interface{}) string {
|
|
if v == nil {
|
|
return ""
|
|
}
|
|
|
|
switch val := v.(type) {
|
|
case string:
|
|
return val
|
|
case int:
|
|
return fmt.Sprintf("%d", val)
|
|
case int64:
|
|
return fmt.Sprintf("%d", val)
|
|
case float64:
|
|
return fmt.Sprintf("%.0f", val)
|
|
case bool:
|
|
if val {
|
|
return "true"
|
|
}
|
|
return "false"
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
// toInt64 converts various types to int64
|
|
// Supports: int, int64, float64, string
|
|
// Returns 0 for nil or unsupported types
|
|
func toInt64(v interface{}) int64 {
|
|
if v == nil {
|
|
return 0
|
|
}
|
|
|
|
switch val := v.(type) {
|
|
case int64:
|
|
return val
|
|
case int:
|
|
return int64(val)
|
|
case float64:
|
|
return int64(val)
|
|
case string:
|
|
if parsed, err := strconv.ParseInt(val, 10, 64); err == nil {
|
|
return parsed
|
|
}
|
|
return 0
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
// toTimeString converts various time types to RFC3339 string
|
|
// Supports: time.Time, string, int64 (unix timestamp)
|
|
// Returns empty string for nil or unsupported types
|
|
func toTimeString(v interface{}) string {
|
|
if v == nil {
|
|
return ""
|
|
}
|
|
|
|
switch val := v.(type) {
|
|
case time.Time:
|
|
if val.IsZero() {
|
|
return ""
|
|
}
|
|
return val.Format(time.RFC3339)
|
|
case string:
|
|
// Try to parse as RFC3339 first
|
|
if t, err := time.Parse(time.RFC3339, val); err == nil {
|
|
return t.Format(time.RFC3339)
|
|
}
|
|
// Try to parse as other common formats
|
|
formats := []string{
|
|
"2006-01-02 15:04:05",
|
|
"2006-01-02T15:04:05Z",
|
|
"2006-01-02T15:04:05.000Z",
|
|
}
|
|
for _, format := range formats {
|
|
if t, err := time.Parse(format, val); err == nil {
|
|
return t.Format(time.RFC3339)
|
|
}
|
|
}
|
|
return val // Return as-is if can't parse
|
|
case int64:
|
|
// Assume unix timestamp
|
|
if val > 0 {
|
|
return time.Unix(val, 0).Format(time.RFC3339)
|
|
}
|
|
return ""
|
|
default:
|
|
return ""
|
|
}
|
|
}
|