- 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.
192 lines
4.1 KiB
Go
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
|
|
}
|