Jonathan Apodaca e278c40de1
Some checks failed
CI / build (push) Has been cancelled
initial commit
2025-05-08 21:22:46 -06:00

126 lines
3.6 KiB
Go

package daemon
import (
"encoding/json"
"fmt"
"net"
"os"
"path/filepath"
"git.jrop.me/jonathan/envvault/internal"
)
// Client provides methods to interact with the password daemon
type Client struct {
socketPath string
}
// NewClient creates a new client for the password daemon
func NewClient(socketPath string) *Client {
return &Client{
socketPath: socketPath,
}
}
// IsRunning checks if the daemon is running
func (c *Client) IsRunning() bool {
internal.DaemonLog.Printf("Checking if daemon is running at: %s", c.socketPath)
conn, err := net.Dial("unix", c.socketPath)
if err != nil {
internal.DaemonLog.Printf("Daemon is not running: %v", err)
return false
}
conn.Close()
internal.DaemonLog.Printf("Daemon is running")
return true
}
// StorePassword sends the password to the daemon for caching
func (c *Client) StorePassword(password []byte) error {
internal.DaemonLog.Printf("Storing password in daemon")
msg := Message{
Command: "store",
Password: string(password),
}
internal.DaemonLog.Printf("Sending store message to daemon")
resp, err := c.sendMessage(msg)
if err != nil {
internal.DaemonLog.Printf("Failed to send store message: %v", err)
return err
}
if !resp.Success {
internal.DaemonLog.Printf("Daemon reported error: %s", resp.Error)
return fmt.Errorf("failed to store password: %s", resp.Error)
}
internal.DaemonLog.Printf("Password stored successfully")
return nil
}
// RetrievePassword gets the cached password from the daemon
func (c *Client) RetrievePassword() ([]byte, error) {
internal.DaemonLog.Printf("Retrieving password from daemon")
msg := Message{
Command: "retrieve",
}
internal.DaemonLog.Printf("Sending retrieve message to daemon")
resp, err := c.sendMessage(msg)
if err != nil {
internal.DaemonLog.Printf("Failed to send retrieve message: %v", err)
return nil, err
}
if !resp.Success {
internal.DaemonLog.Printf("Daemon reported error: %s", resp.Error)
return nil, fmt.Errorf("failed to retrieve password: %s", resp.Error)
}
internal.DaemonLog.Printf("Password retrieved successfully")
return []byte(resp.Data), nil
}
// sendMessage sends a message to the daemon and returns the response
func (c *Client) sendMessage(msg Message) (*Response, error) {
internal.DaemonLog.Printf("Connecting to daemon socket: %s", c.socketPath)
conn, err := net.Dial("unix", c.socketPath)
if err != nil {
internal.DaemonLog.Printf("Failed to connect to daemon: %v", err)
return nil, fmt.Errorf("failed to connect to daemon: %w", err)
}
defer conn.Close()
internal.DaemonLog.Printf("Connected to daemon, encoding message")
encoder := json.NewEncoder(conn)
decoder := json.NewDecoder(conn)
if err := encoder.Encode(msg); err != nil {
internal.DaemonLog.Printf("Failed to encode message: %v", err)
return nil, fmt.Errorf("failed to encode message: %w", err)
}
internal.DaemonLog.Printf("Message sent, waiting for response")
var resp Response
if err := decoder.Decode(&resp); err != nil {
internal.DaemonLog.Printf("Failed to decode response: %v", err)
return nil, fmt.Errorf("failed to decode response: %w", err)
}
internal.DaemonLog.Printf("Response received: success=%v", resp.Success)
return &resp, nil
}
// GetSocketPath returns the default socket path for the current user
func GetSocketPath() string {
homeDir, err := os.UserHomeDir()
if err != nil {
// Fall back to current directory if home dir can't be determined
internal.DaemonLog.Printf("Failed to get user home directory: %v", err)
return filepath.Join(".local/cache/envvault", "daemon.sock")
}
runtimeDir := filepath.Join(homeDir, ".local/cache/envvault")
return filepath.Join(runtimeDir, "daemon.sock")
}