package cli import ( "encoding/json" "fmt" "os" "path/filepath" ) // Credentials stores the logged-in user's session info. type Credentials struct { ServerURL string `json:"server_url"` Token string `json:"token"` UserID string `json:"user_id"` Email string `json:"email"` Name string `json:"name"` } // CredentialsPath returns ~/.pad/credentials.json. func CredentialsPath() (string, error) { homeDir, err := os.UserHomeDir() if err != nil { return "", fmt.Errorf("get home directory: %w", err) } return filepath.Join(homeDir, ".pad", "credentials.json"), nil } // credentialsPath is retained for internal call sites. func credentialsPath() (string, error) { return CredentialsPath() } // LoadCredentials reads the credentials file. Returns nil if the file // doesn't exist (not an error — just means not logged in). func LoadCredentials() (*Credentials, error) { path, err := credentialsPath() if err != nil { return nil, err } data, err := os.ReadFile(path) if err != nil { if os.IsNotExist(err) { return nil, nil } return nil, fmt.Errorf("read credentials: %w", err) } var creds Credentials if err := json.Unmarshal(data, &creds); err != nil { return nil, fmt.Errorf("parse credentials: %w", err) } return &creds, nil } // SaveCredentials writes credentials to disk with 0600 permissions. func SaveCredentials(creds *Credentials) error { path, err := credentialsPath() if err != nil { return err } // Ensure directory exists if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { return fmt.Errorf("create credentials directory: %w", err) } data, err := json.MarshalIndent(creds, "", " ") if err != nil { return fmt.Errorf("marshal credentials: %w", err) } if err := os.WriteFile(path, data, 0600); err != nil { return fmt.Errorf("write credentials: %w", err) } return nil } // DeleteCredentials removes the credentials file. func DeleteCredentials() error { path, err := credentialsPath() if err != nil { return err } if err := os.Remove(path); err != nil && !os.IsNotExist(err) { return fmt.Errorf("delete credentials: %w", err) } return nil }