* clear

* feat: Add everything

* fix: Commenht
This commit is contained in:
Prad Nukala
2025-10-03 14:45:52 -04:00
committed by GitHub
parent 43b4a11c06
commit 13e6c3e84d
1935 changed files with 655061 additions and 40058 deletions
+535
View File
@@ -0,0 +1,535 @@
package handlers
import (
"fmt"
"net/http"
"time"
"github.com/golang-jwt/jwt/v5"
"github.com/hibiken/asynq"
"github.com/labstack/echo/v4"
"github.com/sonr-io/sonr/bridge/tasks"
"github.com/sonr-io/sonr/crypto/mpc"
"github.com/sonr-io/sonr/types/ipfs"
)
// VaultHandlers holds all vault-related handlers and their dependencies
type VaultHandlers struct {
IPFSClient ipfs.IPFSClient
ConnectionManager *ConnectionManager
SSEManager *SSEManager
}
// NewVaultHandlers creates a new VaultHandlers instance
func NewVaultHandlers(
ipfsClient ipfs.IPFSClient,
connManager *ConnectionManager,
sseManager *SSEManager,
) *VaultHandlers {
return &VaultHandlers{
IPFSClient: ipfsClient,
ConnectionManager: connManager,
SSEManager: sseManager,
}
}
// GetQueueFromPriority determines the appropriate queue based on priority
func GetQueueFromPriority(priority string) string {
switch priority {
case "critical", "high":
return "critical"
case "low":
return "low"
default:
return "default"
}
}
// GenerateHandler handles vault generation requests
func (vh *VaultHandlers) GenerateHandler(client *asynq.Client) echo.HandlerFunc {
return func(c echo.Context) error {
// Extract user info from JWT token
user := c.Get("user").(*jwt.Token)
claims := user.Claims.(jwt.MapClaims)
userID := claims["user_id"].(string)
var req struct {
UserID int `json:"user_id"`
Priority string `json:"priority,omitempty"`
}
if err := c.Bind(&req); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid JSON payload"})
}
task, err := tasks.NewUCANDIDTask(req.UserID)
if err != nil {
return c.JSON(
http.StatusInternalServerError,
map[string]string{"error": "Failed to create task"},
)
}
queue := GetQueueFromPriority(req.Priority)
info, err := client.Enqueue(task, asynq.Queue(queue))
if err != nil {
return c.JSON(
http.StatusInternalServerError,
map[string]string{"error": "Failed to enqueue task"},
)
}
// Broadcast task status to WebSocket and SSE connections
go func() {
message := TaskStatusMessage{
TaskID: info.ID,
Status: "enqueued",
Time: time.Now(),
}
vh.ConnectionManager.BroadcastToTask(info.ID, message)
vh.SSEManager.BroadcastToSSE(info.ID, message)
// Simulate task progression for demonstration
// In a real implementation, this would be triggered by the actual task processors
time.Sleep(1 * time.Second)
processingMessage := TaskStatusMessage{
TaskID: info.ID,
Status: "processing",
Progress: 50,
Time: time.Now(),
}
vh.ConnectionManager.BroadcastToTask(info.ID, processingMessage)
vh.SSEManager.BroadcastToSSE(info.ID, processingMessage)
// Simulate completion
time.Sleep(2 * time.Second)
completedMessage := TaskStatusMessage{
TaskID: info.ID,
Status: "completed",
Progress: 100,
Time: time.Now(),
}
vh.ConnectionManager.BroadcastToTask(info.ID, completedMessage)
vh.SSEManager.BroadcastToSSE(info.ID, completedMessage)
}()
return c.JSON(http.StatusOK, map[string]any{
"task_id": info.ID,
"queue": queue,
"status": "enqueued",
"user_id": userID,
})
}
}
// SignHandler handles vault signing requests
func (vh *VaultHandlers) SignHandler(client *asynq.Client) echo.HandlerFunc {
return func(c echo.Context) error {
var req struct {
Message []byte `json:"message"`
Enclave *mpc.EnclaveData `json:"enclave,omitempty"` // Direct enclave data (fallback)
EnclaveCID string `json:"enclave_cid,omitempty"` // IPFS CID reference
Password []byte `json:"password,omitempty"` // Decryption password for IPFS stored data
UCANToken string `json:"ucan_token,omitempty"` // UCAN token for authorization
Priority string `json:"priority,omitempty"`
}
if err := c.Bind(&req); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid JSON payload"})
}
if len(req.Message) == 0 {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Message is required"})
}
// Handle enclave data - either direct or via IPFS CID
var enclave *mpc.EnclaveData
if req.EnclaveCID != "" {
// Retrieve enclave from IPFS
if vh.IPFSClient == nil {
return c.JSON(
http.StatusServiceUnavailable,
map[string]string{"error": "IPFS client not available"},
)
}
encryptedData, err := vh.IPFSClient.Get(req.EnclaveCID)
if err != nil {
return c.JSON(
http.StatusNotFound,
map[string]string{"error": "Failed to retrieve enclave from IPFS"},
)
}
// Create temporary enclave for decryption
tempEnclave := &mpc.EnclaveData{}
decryptedData, err := tempEnclave.Decrypt(req.Password, encryptedData)
if err != nil {
return c.JSON(
http.StatusBadRequest,
map[string]string{"error": "Failed to decrypt enclave data"},
)
}
// Unmarshal decrypted data
enclave = &mpc.EnclaveData{}
if err := enclave.Unmarshal(decryptedData); err != nil {
return c.JSON(
http.StatusBadRequest,
map[string]string{"error": "Failed to parse enclave data"},
)
}
} else if req.Enclave != nil {
// Use directly provided enclave data
enclave = req.Enclave
} else {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Either enclave or enclave_cid is required"})
}
task, err := tasks.NewUCANSignTask(
0,
req.Message,
) // TODO: Extract userID from JWT or context
if err != nil {
return c.JSON(
http.StatusInternalServerError,
map[string]string{"error": "Failed to create task"},
)
}
queue := GetQueueFromPriority(req.Priority)
info, err := client.Enqueue(task, asynq.Queue(queue))
if err != nil {
return c.JSON(
http.StatusInternalServerError,
map[string]string{"error": "Failed to enqueue task"},
)
}
return c.JSON(http.StatusOK, map[string]any{
"task_id": info.ID,
"queue": queue,
"status": "enqueued",
})
}
}
// VerifyHandler handles vault verification requests
func (vh *VaultHandlers) VerifyHandler(client *asynq.Client) echo.HandlerFunc {
return func(c echo.Context) error {
var req struct {
PublicKey []byte `json:"public_key"`
Message []byte `json:"message"`
Signature []byte `json:"signature"`
Priority string `json:"priority,omitempty"`
}
if err := c.Bind(&req); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid JSON payload"})
}
if len(req.PublicKey) == 0 || len(req.Message) == 0 || len(req.Signature) == 0 {
return c.JSON(
http.StatusBadRequest,
map[string]string{"error": "PublicKey, message, and signature are required"},
)
}
task, err := tasks.NewUCANVerifyTask(
0,
req.Message,
req.Signature,
) // TODO: Extract userID from JWT or context
if err != nil {
return c.JSON(
http.StatusInternalServerError,
map[string]string{"error": "Failed to create task"},
)
}
queue := GetQueueFromPriority(req.Priority)
info, err := client.Enqueue(task, asynq.Queue(queue))
if err != nil {
return c.JSON(
http.StatusInternalServerError,
map[string]string{"error": "Failed to enqueue task"},
)
}
return c.JSON(http.StatusOK, map[string]any{
"task_id": info.ID,
"queue": queue,
"status": "enqueued",
})
}
}
// ExportHandler handles vault export requests
func (vh *VaultHandlers) ExportHandler(client *asynq.Client) echo.HandlerFunc {
return func(c echo.Context) error {
var req struct {
Enclave *mpc.EnclaveData `json:"enclave,omitempty"` // Direct enclave data
EnclaveCID string `json:"enclave_cid,omitempty"` // IPFS CID reference
Password []byte `json:"password"` // For encryption/decryption
StoreIPFS bool `json:"store_ipfs,omitempty"` // Whether to store result in IPFS
Priority string `json:"priority,omitempty"`
}
if err := c.Bind(&req); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid JSON payload"})
}
if len(req.Password) == 0 {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Password is required"})
}
// Handle enclave data - either direct or via IPFS CID
var enclave *mpc.EnclaveData
if req.EnclaveCID != "" {
// Retrieve enclave from IPFS
if vh.IPFSClient == nil {
return c.JSON(
http.StatusServiceUnavailable,
map[string]string{"error": "IPFS client not available"},
)
}
encryptedData, err := vh.IPFSClient.Get(req.EnclaveCID)
if err != nil {
return c.JSON(
http.StatusNotFound,
map[string]string{"error": "Failed to retrieve enclave from IPFS"},
)
}
// Create temporary enclave for decryption
tempEnclave := &mpc.EnclaveData{}
decryptedData, err := tempEnclave.Decrypt(req.Password, encryptedData)
if err != nil {
return c.JSON(
http.StatusBadRequest,
map[string]string{"error": "Failed to decrypt enclave data"},
)
}
// Unmarshal decrypted data
enclave = &mpc.EnclaveData{}
if err := enclave.Unmarshal(decryptedData); err != nil {
return c.JSON(
http.StatusBadRequest,
map[string]string{"error": "Failed to parse enclave data"},
)
}
} else if req.Enclave != nil {
// Use directly provided enclave data
enclave = req.Enclave
} else {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Either enclave or enclave_cid is required"})
}
// If store_ipfs is true, encrypt and store the enclave in IPFS first
if req.StoreIPFS && vh.IPFSClient != nil {
encryptedData, err := enclave.Encrypt(req.Password)
if err != nil {
return c.JSON(
http.StatusInternalServerError,
map[string]string{"error": "Failed to encrypt enclave data"},
)
}
cid, err := vh.IPFSClient.Add(encryptedData)
if err != nil {
return c.JSON(
http.StatusInternalServerError,
map[string]string{"error": "Failed to store enclave in IPFS"},
)
}
// Return the CID for future reference
return c.JSON(http.StatusOK, map[string]any{
"cid": cid,
"status": "stored",
"message": "Enclave data encrypted and stored in IPFS",
})
}
// Export functionality replaced with UCAN token creation for data access
// Convert export operation to UCAN token generation with export permissions
attenuations := []map[string]any{
{
"can": []string{"export", "read"},
"with": "vault://exported-data",
},
}
task, err := tasks.NewUCANTokenTask(
0,
"did:sonr:export-recipient",
attenuations,
time.Now().Add(24*time.Hour).Unix(),
)
if err != nil {
return c.JSON(
http.StatusInternalServerError,
map[string]string{"error": "Failed to create task"},
)
}
queue := GetQueueFromPriority(req.Priority)
info, err := client.Enqueue(task, asynq.Queue(queue))
if err != nil {
return c.JSON(
http.StatusInternalServerError,
map[string]string{"error": "Failed to enqueue task"},
)
}
return c.JSON(http.StatusOK, map[string]any{
"task_id": info.ID,
"queue": queue,
"status": "enqueued",
})
}
}
// ImportHandler handles vault import requests
func (vh *VaultHandlers) ImportHandler(client *asynq.Client) echo.HandlerFunc {
return func(c echo.Context) error {
var req struct {
CID string `json:"cid"`
Password []byte `json:"password"`
Priority string `json:"priority,omitempty"`
}
if err := c.Bind(&req); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid JSON payload"})
}
if req.CID == "" || len(req.Password) == 0 {
return c.JSON(
http.StatusBadRequest,
map[string]string{"error": "CID and password are required"},
)
}
// Import functionality replaced with UCAN token creation for data import
// Convert import operation to UCAN token generation with import permissions
attenuations := []map[string]any{
{
"can": []string{"import", "write"},
"with": fmt.Sprintf("ipfs://%s", req.CID),
},
}
task, err := tasks.NewUCANTokenTask(
0,
"did:sonr:import-recipient",
attenuations,
time.Now().Add(1*time.Hour).Unix(),
)
if err != nil {
return c.JSON(
http.StatusInternalServerError,
map[string]string{"error": "Failed to create task"},
)
}
queue := GetQueueFromPriority(req.Priority)
info, err := client.Enqueue(task, asynq.Queue(queue))
if err != nil {
return c.JSON(
http.StatusInternalServerError,
map[string]string{"error": "Failed to enqueue task"},
)
}
return c.JSON(http.StatusOK, map[string]any{
"task_id": info.ID,
"queue": queue,
"status": "enqueued",
})
}
}
// RefreshHandler handles vault refresh requests
func (vh *VaultHandlers) RefreshHandler(client *asynq.Client) echo.HandlerFunc {
return func(c echo.Context) error {
var req struct {
Enclave *mpc.EnclaveData `json:"enclave,omitempty"` // Direct enclave data
EnclaveCID string `json:"enclave_cid,omitempty"` // IPFS CID reference
Password []byte `json:"password,omitempty"` // Decryption password for IPFS stored data
Priority string `json:"priority,omitempty"`
}
if err := c.Bind(&req); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid JSON payload"})
}
// Handle enclave data - either direct or via IPFS CID
var enclave *mpc.EnclaveData
if req.EnclaveCID != "" {
// Retrieve enclave from IPFS
if vh.IPFSClient == nil {
return c.JSON(
http.StatusServiceUnavailable,
map[string]string{"error": "IPFS client not available"},
)
}
encryptedData, err := vh.IPFSClient.Get(req.EnclaveCID)
if err != nil {
return c.JSON(
http.StatusNotFound,
map[string]string{"error": "Failed to retrieve enclave from IPFS"},
)
}
// Create temporary enclave for decryption
tempEnclave := &mpc.EnclaveData{}
decryptedData, err := tempEnclave.Decrypt(req.Password, encryptedData)
if err != nil {
return c.JSON(
http.StatusBadRequest,
map[string]string{"error": "Failed to decrypt enclave data"},
)
}
// Unmarshal decrypted data
enclave = &mpc.EnclaveData{}
if err := enclave.Unmarshal(decryptedData); err != nil {
return c.JSON(
http.StatusBadRequest,
map[string]string{"error": "Failed to parse enclave data"},
)
}
} else if req.Enclave != nil {
// Use directly provided enclave data
enclave = req.Enclave
} else {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Either enclave or enclave_cid is required"})
}
// Refresh functionality replaced with UCAN DID generation for new identity
// Convert refresh operation to DID generation which includes key refresh
task, err := tasks.NewUCANDIDTask(0) // TODO: Extract userID from JWT or context
if err != nil {
return c.JSON(
http.StatusInternalServerError,
map[string]string{"error": "Failed to create task"},
)
}
queue := GetQueueFromPriority(req.Priority)
info, err := client.Enqueue(task, asynq.Queue(queue))
if err != nil {
return c.JSON(
http.StatusInternalServerError,
map[string]string{"error": "Failed to enqueue task"},
)
}
return c.JSON(http.StatusOK, map[string]any{
"task_id": info.ID,
"queue": queue,
"status": "enqueued",
})
}
}