Files
login-api/app/repositories/sessions.go
2026-01-19 09:23:25 +01:00

128 lines
4.9 KiB
Go

package repositories
import (
"encoding/json"
"time"
"git.secnex.io/secnex/auth-api/cache"
"git.secnex.io/secnex/auth-api/database"
"git.secnex.io/secnex/auth-api/models"
"git.secnex.io/secnex/masterlog"
"github.com/google/uuid"
)
type SessionDetails struct {
UserID uuid.UUID `json:"user_id"`
Username string `json:"username"`
Email string `json:"email"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}
func CreateSession(user *models.User) *models.Session {
session := &models.Session{
ID: uuid.New(),
UserID: user.ID,
}
if err := database.DB.Create(session).Error; err != nil {
masterlog.Debug("Failed to create session in database", map[string]interface{}{"error": err.Error(), "user_id": user.ID})
return nil
}
sessionDetails := SessionDetails{
UserID: user.ID,
Username: user.Username,
Email: user.Email,
FirstName: user.FirstName,
LastName: user.LastName,
}
jsonData, err := json.Marshal(sessionDetails)
if err != nil {
masterlog.Debug("Failed to marshal session details", map[string]interface{}{"error": err.Error(), "session_id": session.ID})
return nil
}
ttl := time.Hour * 24
if cache.Cache.Client == nil {
masterlog.Debug("Redis client not initialized, skipping cache storage", map[string]interface{}{"session_id": session.ID})
return session
}
if err := cache.Cache.Client.Do(cache.Cache.Context, cache.Cache.Client.B().Set().Key(session.ID.String()).Value(string(jsonData)).Ex(ttl).Build()).Error(); err != nil {
masterlog.Debug("Failed to store session in cache", map[string]interface{}{"error": err.Error(), "session_id": session.ID})
return session
}
masterlog.Debug("Session stored in cache", map[string]interface{}{"session_id": session.ID})
return session
}
func GetSessionCache(sessionID string) *SessionDetails {
masterlog.Debug("Retrieving session from cache", map[string]interface{}{"session_id": sessionID})
if cache.Cache.Client == nil {
masterlog.Debug("Redis client not initialized", map[string]interface{}{"session_id": sessionID})
return nil
}
res := cache.Cache.Client.Do(cache.Cache.Context, cache.Cache.Client.B().Get().Key(sessionID).Build())
if res.Error() != nil {
masterlog.Debug("Failed to get session from cache", map[string]interface{}{"error": res.Error(), "session_id": sessionID})
return nil
}
rawStr := res.String()
if rawStr == "" {
masterlog.Debug("Session not found in cache", map[string]interface{}{"session_id": sessionID})
return nil
}
// Parse the valkey response structure to extract the actual JSON string
var valkeyResponse struct {
Message struct {
Value string `json:"Value"`
Type string `json:"Type"`
} `json:"Message"`
}
if err := json.Unmarshal([]byte(rawStr), &valkeyResponse); err != nil {
// If it's not the wrapped format, use it directly
masterlog.Debug("Cache response not in wrapped format, using directly", map[string]interface{}{"session_id": sessionID})
} else {
// Extract the actual JSON string from Message.Value
rawStr = valkeyResponse.Message.Value
masterlog.Debug("Extracted JSON from cache response", map[string]interface{}{"session_id": sessionID})
}
var sessionDetails SessionDetails
if err := json.Unmarshal([]byte(rawStr), &sessionDetails); err != nil {
masterlog.Debug("Failed to unmarshal session details", map[string]interface{}{"error": err.Error(), "session_id": sessionID})
return nil
}
masterlog.Debug("Session retrieved from cache", map[string]interface{}{"session_id": sessionID, "user_id": sessionDetails.UserID})
return &sessionDetails
}
func DeleteSession(sessionID string) error {
masterlog.Debug("Deleting session from database and cache", map[string]interface{}{"session_id": sessionID})
if err := DeleteSessionCache(sessionID); err != nil {
masterlog.Debug("Failed to delete session from cache", map[string]interface{}{"error": err.Error(), "session_id": sessionID})
return err
}
if err := database.DB.Where("id = ?", sessionID).Delete(&models.Session{}).Error; err != nil {
masterlog.Debug("Failed to delete session from database", map[string]interface{}{"error": err.Error(), "session_id": sessionID})
return err
}
masterlog.Debug("Session deleted from database and cache", map[string]interface{}{"session_id": sessionID})
return nil
}
func DeleteSessionCache(sessionID string) error {
masterlog.Debug("Deleting session from cache", map[string]interface{}{"session_id": sessionID})
if cache.Cache.Client == nil {
masterlog.Debug("Redis client not initialized", map[string]interface{}{"session_id": sessionID})
return nil
}
if err := cache.Cache.Client.Do(cache.Cache.Context, cache.Cache.Client.B().Del().Key(sessionID).Build()).Error(); err != nil {
masterlog.Debug("Failed to delete session from cache", map[string]interface{}{"error": err.Error(), "session_id": sessionID})
return err
}
masterlog.Debug("Session deleted from cache", map[string]interface{}{"session_id": sessionID})
return nil
}