yao/openapi/user/utils.go
Max 2569634ca2 Remove invitation management handlers and related business logic
- Deleted the invitation.go file, which contained handlers for team invitation management, including listing, creating, resending, and deleting invitations.
- Updated the user/member.go and user/team.go files to ensure consistent response handling by replacing direct JSON responses with a unified response method.
- Introduced a new PublicInvitationResponse type in user/types.go to facilitate public access to invitation details while excluding sensitive information.
- Refactored user/user.go to register new invitation-related process handlers for improved organization and clarity.
2025-10-10 08:42:05 +08:00

192 lines
4.1 KiB
Go

package user
import (
"fmt"
"strconv"
"strings"
"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 ""
}
}
// Security Utilities
// maskEmail masks an email address for privacy protection
// Keeps the first and last character of the local part, masks the middle with ***
// Examples:
// - "john.doe@example.com" -> "j***e@example.com"
// - "a@example.com" -> "a***@example.com"
// - "ab@example.com" -> "a***b@example.com"
//
// Returns empty string for invalid email or empty input
func maskEmail(email string) string {
if email == "" {
return ""
}
// Split email into local and domain parts
parts := strings.Split(email, "@")
if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
return "" // Invalid email format
}
local := parts[0]
domain := parts[1]
// Mask the local part
var masked string
localLen := len(local)
switch localLen {
case 1:
// Single character: show it with ***
masked = local + "***"
case 2:
// Two characters: show first + *** + last
masked = string(local[0]) + "***" + string(local[1])
default:
// Three or more characters: show first + *** + last
masked = string(local[0]) + "***" + string(local[localLen-1])
}
return masked + "@" + domain
}