diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 6cebf4a..925d268 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -1,6 +1,6 @@ # GoReleaser Configuration for DeBros Network -# Builds and releases the dbn binary for multiple platforms -# Other binaries (node, gateway, identity) are installed via: dbn setup +# Builds and releases the orama binary for multiple platforms +# Other binaries (node, gateway, identity) are installed via: orama setup project_name: debros-network @@ -8,10 +8,10 @@ env: - GO111MODULE=on builds: - # dbn binary - only build the CLI - - id: dbn + # orama binary - only build the CLI + - id: orama main: ./cmd/cli - binary: dbn + binary: orama goos: - linux - darwin @@ -26,7 +26,7 @@ builds: mod_timestamp: "{{ .CommitTimestamp }}" archives: - # Tar.gz archives for dbn + # Tar.gz archives for orama - id: binaries format: tar.gz name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}" diff --git a/cmd/cli/main.go b/cmd/cli/main.go index 4518577..49bad75 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -86,6 +86,10 @@ func main() { case "db": cli.HandleDBCommand(args) + // Environment management + case "env": + cli.HandleEnvCommand(args) + // Help case "help", "--help", "-h": showHelp() @@ -160,6 +164,11 @@ func showHelp() { fmt.Printf(" db backup - Backup database to IPFS\n") fmt.Printf(" db backups - List database backups\n\n") + fmt.Printf("šŸŒ Environments:\n") + fmt.Printf(" env list - List all environments\n") + fmt.Printf(" env current - Show current environment\n") + fmt.Printf(" env switch - Switch to environment\n\n") + fmt.Printf("Global Flags:\n") fmt.Printf(" -f, --format - Output format: table, json (default: table)\n") fmt.Printf(" -t, --timeout - Operation timeout (default: 30s)\n") diff --git a/cmd/gateway/config.go b/cmd/gateway/config.go index 639a84b..feee2f5 100644 --- a/cmd/gateway/config.go +++ b/cmd/gateway/config.go @@ -95,7 +95,7 @@ func parseGatewayConfig(logger *logging.ColoredLogger) *gateway.Config { zap.String("path", configPath), zap.Error(err)) fmt.Fprintf(os.Stderr, "\nConfig file not found at %s\n", configPath) - fmt.Fprintf(os.Stderr, "Generate it using: dbn config init --type gateway\n") + fmt.Fprintf(os.Stderr, "Generate it using: orama config init --type gateway\n") os.Exit(1) } diff --git a/pkg/auth/credentials.go b/pkg/auth/credentials.go index a6dbf69..5017165 100644 --- a/pkg/auth/credentials.go +++ b/pkg/auth/credentials.go @@ -165,17 +165,59 @@ func (creds *Credentials) UpdateLastUsed() { creds.LastUsedAt = time.Now() } -// GetDefaultGatewayURL returns the default gateway URL from environment or fallback +// GetDefaultGatewayURL returns the default gateway URL from environment config, env vars, or fallback func GetDefaultGatewayURL() string { + // Check environment variables first (for backwards compatibility) if envURL := os.Getenv("DEBROS_GATEWAY_URL"); envURL != "" { return envURL } if envURL := os.Getenv("DEBROS_GATEWAY"); envURL != "" { return envURL } + + // Try to read from environment config file + if gwURL := getGatewayFromEnvConfig(); gwURL != "" { + return gwURL + } + return "http://localhost:6001" } +// getGatewayFromEnvConfig reads the active environment's gateway URL from the config file +func getGatewayFromEnvConfig() string { + homeDir, err := os.UserHomeDir() + if err != nil { + return "" + } + + envConfigPath := filepath.Join(homeDir, ".orama", "environments.json") + data, err := os.ReadFile(envConfigPath) + if err != nil { + return "" + } + + var config struct { + Environments []struct { + Name string `json:"name"` + GatewayURL string `json:"gateway_url"` + } `json:"environments"` + ActiveEnvironment string `json:"active_environment"` + } + + if err := json.Unmarshal(data, &config); err != nil { + return "" + } + + // Find the active environment + for _, env := range config.Environments { + if env.Name == config.ActiveEnvironment { + return env.GatewayURL + } + } + + return "" +} + // HasValidCredentials checks if there are valid credentials for the default gateway func HasValidCredentials() (bool, error) { store, err := LoadCredentials() diff --git a/pkg/auth/enhanced_auth.go b/pkg/auth/enhanced_auth.go index 3e5a057..5efed25 100644 --- a/pkg/auth/enhanced_auth.go +++ b/pkg/auth/enhanced_auth.go @@ -86,7 +86,8 @@ func LoadEnhancedCredentials() (*EnhancedCredentialStore, error) { } } - // Parse as legacy v2.0 format (single credential per gateway) and migrate + // Parse as legacy format (single credential per gateway) and migrate + // Supports both v1.0 and v2.0 legacy formats var legacyStore struct { Gateways map[string]*Credentials `json:"gateways"` Version string `json:"version"` @@ -96,8 +97,8 @@ func LoadEnhancedCredentials() (*EnhancedCredentialStore, error) { return nil, fmt.Errorf("invalid credentials file format: %w", err) } - if legacyStore.Version != "2.0" { - return nil, fmt.Errorf("unsupported credentials version %q; expected \"2.0\"", legacyStore.Version) + if legacyStore.Version != "1.0" && legacyStore.Version != "2.0" { + return nil, fmt.Errorf("unsupported credentials version %q; expected \"1.0\" or \"2.0\"", legacyStore.Version) } // Convert legacy format to enhanced format diff --git a/pkg/cli/auth_commands.go b/pkg/cli/auth_commands.go index 79b027b..5958432 100644 --- a/pkg/cli/auth_commands.go +++ b/pkg/cli/auth_commands.go @@ -26,6 +26,10 @@ func HandleAuthCommand(args []string) { handleAuthWhoami() case "status": handleAuthStatus() + case "list": + handleAuthList() + case "switch": + handleAuthSwitch() default: fmt.Fprintf(os.Stderr, "Unknown auth command: %s\n", subcommand) showAuthHelp() @@ -35,42 +39,106 @@ func HandleAuthCommand(args []string) { func showAuthHelp() { fmt.Printf("šŸ” Authentication Commands\n\n") - fmt.Printf("Usage: dbn auth \n\n") + fmt.Printf("Usage: orama auth \n\n") fmt.Printf("Subcommands:\n") fmt.Printf(" login - Authenticate by providing your wallet address\n") fmt.Printf(" logout - Clear stored credentials\n") fmt.Printf(" whoami - Show current authentication status\n") - fmt.Printf(" status - Show detailed authentication info\n\n") + fmt.Printf(" status - Show detailed authentication info\n") + fmt.Printf(" list - List all stored credentials for current environment\n") + fmt.Printf(" switch - Switch between stored credentials\n\n") fmt.Printf("Examples:\n") - fmt.Printf(" dbn auth login # Enter wallet address interactively\n") - fmt.Printf(" dbn auth whoami # Check who you're logged in as\n") - fmt.Printf(" dbn auth status # View detailed authentication info\n") - fmt.Printf(" dbn auth logout # Clear all stored credentials\n\n") + fmt.Printf(" orama auth login # Enter wallet address interactively\n") + fmt.Printf(" orama auth whoami # Check who you're logged in as\n") + fmt.Printf(" orama auth status # View detailed authentication info\n") + fmt.Printf(" orama auth logout # Clear all stored credentials\n\n") fmt.Printf("Environment Variables:\n") fmt.Printf(" DEBROS_GATEWAY_URL - Gateway URL (overrides environment config)\n\n") fmt.Printf("Authentication Flow:\n") - fmt.Printf(" 1. Run 'dbn auth login'\n") + fmt.Printf(" 1. Run 'orama auth login'\n") fmt.Printf(" 2. Enter your wallet address when prompted\n") fmt.Printf(" 3. Enter your namespace (or press Enter for 'default')\n") fmt.Printf(" 4. An API key will be generated and saved to ~/.orama/credentials.json\n\n") fmt.Printf("Note: Authentication uses the currently active environment.\n") - fmt.Printf(" Use 'dbn env current' to see your active environment.\n") + fmt.Printf(" Use 'orama env current' to see your active environment.\n") } func handleAuthLogin() { - // Prompt for node selection - gatewayURL := promptForGatewayURL() - fmt.Printf("šŸ” Authenticating with gateway at: %s\n", gatewayURL) + // Get gateway URL from active environment + gatewayURL := getGatewayURL() - // Use the simple authentication flow + // Show active environment + env, err := GetActiveEnvironment() + if err == nil { + fmt.Printf("šŸŒ Environment: %s\n", env.Name) + } + fmt.Printf("šŸ” Authenticating with gateway at: %s\n\n", gatewayURL) + + // Load enhanced credential store + store, err := auth.LoadEnhancedCredentials() + if err != nil { + fmt.Fprintf(os.Stderr, "āŒ Failed to load credentials: %v\n", err) + os.Exit(1) + } + + // Check if we already have credentials for this gateway + gwCreds := store.Gateways[gatewayURL] + if gwCreds != nil && len(gwCreds.Credentials) > 0 { + // Show existing credentials and offer choice + choice, credIndex, err := store.DisplayCredentialMenu(gatewayURL) + if err != nil { + fmt.Fprintf(os.Stderr, "āŒ Menu selection failed: %v\n", err) + os.Exit(1) + } + + switch choice { + case auth.AuthChoiceUseCredential: + selectedCreds := gwCreds.Credentials[credIndex] + store.SetDefaultCredential(gatewayURL, credIndex) + selectedCreds.UpdateLastUsed() + if err := store.Save(); err != nil { + fmt.Fprintf(os.Stderr, "āŒ Failed to save credentials: %v\n", err) + os.Exit(1) + } + fmt.Printf("āœ… Switched to wallet: %s\n", selectedCreds.Wallet) + fmt.Printf("šŸ¢ Namespace: %s\n", selectedCreds.Namespace) + return + + case auth.AuthChoiceLogout: + store.ClearAllCredentials() + if err := store.Save(); err != nil { + fmt.Fprintf(os.Stderr, "āŒ Failed to clear credentials: %v\n", err) + os.Exit(1) + } + fmt.Println("āœ… All credentials cleared") + return + + case auth.AuthChoiceExit: + fmt.Println("Exiting...") + return + + case auth.AuthChoiceAddCredential: + // Fall through to add new credential + } + } + + // Perform simple authentication to add a new credential creds, err := auth.PerformSimpleAuthentication(gatewayURL) if err != nil { fmt.Fprintf(os.Stderr, "āŒ Authentication failed: %v\n", err) os.Exit(1) } - // Save credentials to file - if err := auth.SaveCredentialsForDefaultGateway(creds); err != nil { + // Add to enhanced store + store.AddCredential(gatewayURL, creds) + + // Set as default + gwCreds = store.Gateways[gatewayURL] + if gwCreds != nil { + store.SetDefaultCredential(gatewayURL, len(gwCreds.Credentials)-1) + } + + if err := store.Save(); err != nil { fmt.Fprintf(os.Stderr, "āŒ Failed to save credentials: %v\n", err) os.Exit(1) } @@ -92,17 +160,17 @@ func handleAuthLogout() { } func handleAuthWhoami() { - store, err := auth.LoadCredentials() + store, err := auth.LoadEnhancedCredentials() if err != nil { fmt.Fprintf(os.Stderr, "āŒ Failed to load credentials: %v\n", err) os.Exit(1) } gatewayURL := getGatewayURL() - creds, exists := store.GetCredentialsForGateway(gatewayURL) + creds := store.GetDefaultCredential(gatewayURL) - if !exists || !creds.IsValid() { - fmt.Println("āŒ Not authenticated - run 'dbn auth login' to authenticate") + if creds == nil || !creds.IsValid() { + fmt.Println("āŒ Not authenticated - run 'orama auth login' to authenticate") os.Exit(1) } @@ -122,14 +190,14 @@ func handleAuthWhoami() { } func handleAuthStatus() { - store, err := auth.LoadCredentials() + store, err := auth.LoadEnhancedCredentials() if err != nil { fmt.Fprintf(os.Stderr, "āŒ Failed to load credentials: %v\n", err) os.Exit(1) } gatewayURL := getGatewayURL() - creds, exists := store.GetCredentialsForGateway(gatewayURL) + creds := store.GetDefaultCredential(gatewayURL) // Show active environment env, err := GetActiveEnvironment() @@ -140,7 +208,7 @@ func handleAuthStatus() { fmt.Println("šŸ” Authentication Status") fmt.Printf(" Gateway URL: %s\n", gatewayURL) - if !exists || creds == nil { + if creds == nil { fmt.Println(" Status: āŒ Not authenticated") return } @@ -228,3 +296,108 @@ func getGatewayURL() string { // Fallback to default (node-1) return "http://localhost:6001" } + +func handleAuthList() { + store, err := auth.LoadEnhancedCredentials() + if err != nil { + fmt.Fprintf(os.Stderr, "āŒ Failed to load credentials: %v\n", err) + os.Exit(1) + } + + gatewayURL := getGatewayURL() + + // Show active environment + env, err := GetActiveEnvironment() + if err == nil { + fmt.Printf("šŸŒ Environment: %s\n", env.Name) + } + fmt.Printf("šŸ”— Gateway: %s\n\n", gatewayURL) + + gwCreds := store.Gateways[gatewayURL] + if gwCreds == nil || len(gwCreds.Credentials) == 0 { + fmt.Println("No credentials stored for this environment.") + fmt.Println("Run 'orama auth login' to authenticate.") + return + } + + fmt.Printf("šŸ” Stored Credentials (%d):\n\n", len(gwCreds.Credentials)) + for i, creds := range gwCreds.Credentials { + defaultMark := "" + if i == gwCreds.DefaultIndex { + defaultMark = " ← active" + } + + statusEmoji := "āœ…" + statusText := "valid" + if !creds.IsValid() { + statusEmoji = "āŒ" + statusText = "expired" + } + + fmt.Printf(" %d. %s Wallet: %s%s\n", i+1, statusEmoji, creds.Wallet, defaultMark) + fmt.Printf(" Namespace: %s | Status: %s\n", creds.Namespace, statusText) + if creds.Plan != "" { + fmt.Printf(" Plan: %s\n", creds.Plan) + } + if !creds.IssuedAt.IsZero() { + fmt.Printf(" Issued: %s\n", creds.IssuedAt.Format("2006-01-02 15:04:05")) + } + fmt.Println() + } +} + +func handleAuthSwitch() { + store, err := auth.LoadEnhancedCredentials() + if err != nil { + fmt.Fprintf(os.Stderr, "āŒ Failed to load credentials: %v\n", err) + os.Exit(1) + } + + gatewayURL := getGatewayURL() + + gwCreds := store.Gateways[gatewayURL] + if gwCreds == nil || len(gwCreds.Credentials) == 0 { + fmt.Println("No credentials stored for this environment.") + fmt.Println("Run 'orama auth login' to authenticate first.") + os.Exit(1) + } + + if len(gwCreds.Credentials) == 1 { + fmt.Println("Only one credential stored. Nothing to switch to.") + return + } + + // Display menu + choice, credIndex, err := store.DisplayCredentialMenu(gatewayURL) + if err != nil { + fmt.Fprintf(os.Stderr, "āŒ Menu selection failed: %v\n", err) + os.Exit(1) + } + + switch choice { + case auth.AuthChoiceUseCredential: + selectedCreds := gwCreds.Credentials[credIndex] + store.SetDefaultCredential(gatewayURL, credIndex) + selectedCreds.UpdateLastUsed() + if err := store.Save(); err != nil { + fmt.Fprintf(os.Stderr, "āŒ Failed to save credentials: %v\n", err) + os.Exit(1) + } + fmt.Printf("āœ… Switched to wallet: %s\n", selectedCreds.Wallet) + fmt.Printf("šŸ¢ Namespace: %s\n", selectedCreds.Namespace) + + case auth.AuthChoiceAddCredential: + fmt.Println("Use 'orama auth login' to add a new credential.") + + case auth.AuthChoiceLogout: + store.ClearAllCredentials() + if err := store.Save(); err != nil { + fmt.Fprintf(os.Stderr, "āŒ Failed to clear credentials: %v\n", err) + os.Exit(1) + } + fmt.Println("āœ… All credentials cleared") + + case auth.AuthChoiceExit: + fmt.Println("Cancelled.") + } +} diff --git a/pkg/cli/basic_commands.go b/pkg/cli/basic_commands.go index 968e657..f341ffc 100644 --- a/pkg/cli/basic_commands.go +++ b/pkg/cli/basic_commands.go @@ -158,7 +158,7 @@ func HandlePeerIDCommand(format string, timeout time.Duration) { // HandlePubSubCommand handles pubsub commands func HandlePubSubCommand(args []string, format string, timeout time.Duration) { if len(args) == 0 { - fmt.Fprintf(os.Stderr, "Usage: dbn pubsub [args...]\n") + fmt.Fprintf(os.Stderr, "Usage: orama pubsub [args...]\n") os.Exit(1) } @@ -179,7 +179,7 @@ func HandlePubSubCommand(args []string, format string, timeout time.Duration) { switch subcommand { case "publish": if len(args) < 3 { - fmt.Fprintf(os.Stderr, "Usage: dbn pubsub publish \n") + fmt.Fprintf(os.Stderr, "Usage: orama pubsub publish \n") os.Exit(1) } err := cli.PubSub().Publish(ctx, args[1], []byte(args[2])) @@ -191,7 +191,7 @@ func HandlePubSubCommand(args []string, format string, timeout time.Duration) { case "subscribe": if len(args) < 2 { - fmt.Fprintf(os.Stderr, "Usage: dbn pubsub subscribe [duration]\n") + fmt.Fprintf(os.Stderr, "Usage: orama pubsub subscribe [duration]\n") os.Exit(1) } duration := 30 * time.Second @@ -243,7 +243,7 @@ func HandlePubSubCommand(args []string, format string, timeout time.Duration) { // Helper functions func createClient() (client.NetworkClient, error) { - config := client.DefaultClientConfig("dbn") + config := client.DefaultClientConfig("orama") // Use active environment's gateway URL gatewayURL := getGatewayURL() diff --git a/pkg/cli/db/commands.go b/pkg/cli/db/commands.go index 9cdb9b6..0b56281 100644 --- a/pkg/cli/db/commands.go +++ b/pkg/cli/db/commands.go @@ -10,6 +10,7 @@ import ( "text/tabwriter" "time" + "github.com/DeBrosOfficial/network/pkg/auth" "github.com/spf13/cobra" ) @@ -439,14 +440,31 @@ func getAPIURL() string { if url := os.Getenv("ORAMA_API_URL"); url != "" { return url } - return "https://gateway.orama.network" + return auth.GetDefaultGatewayURL() } func getAuthToken() (string, error) { if token := os.Getenv("ORAMA_TOKEN"); token != "" { return token, nil } - return "", fmt.Errorf("no authentication token found. Set ORAMA_TOKEN environment variable") + + // Try to get from enhanced credentials store + store, err := auth.LoadEnhancedCredentials() + if err != nil { + return "", fmt.Errorf("failed to load credentials: %w", err) + } + + gatewayURL := auth.GetDefaultGatewayURL() + creds := store.GetDefaultCredential(gatewayURL) + if creds == nil { + return "", fmt.Errorf("no credentials found for %s. Run 'orama auth login' to authenticate", gatewayURL) + } + + if !creds.IsValid() { + return "", fmt.Errorf("credentials expired for %s. Run 'orama auth login' to re-authenticate", gatewayURL) + } + + return creds.APIKey, nil } func formatBytes(bytes int64) string { diff --git a/pkg/cli/deployments/deploy.go b/pkg/cli/deployments/deploy.go index 12980eb..54d240c 100644 --- a/pkg/cli/deployments/deploy.go +++ b/pkg/cli/deployments/deploy.go @@ -13,6 +13,7 @@ import ( "path/filepath" "strings" + "github.com/DeBrosOfficial/network/pkg/auth" "github.com/spf13/cobra" ) @@ -383,17 +384,35 @@ func printDeploymentInfo(resp map[string]interface{}) { } func getAPIURL() string { - // TODO: Read from config file + // Check environment variable first if url := os.Getenv("ORAMA_API_URL"); url != "" { return url } - return "https://gateway.orama.network" + // Get from active environment config + return auth.GetDefaultGatewayURL() } func getAuthToken() (string, error) { - // TODO: Read from config file + // Check environment variable first if token := os.Getenv("ORAMA_TOKEN"); token != "" { return token, nil } - return "", fmt.Errorf("no authentication token found. Set ORAMA_TOKEN environment variable") + + // Try to get from enhanced credentials store + store, err := auth.LoadEnhancedCredentials() + if err != nil { + return "", fmt.Errorf("failed to load credentials: %w", err) + } + + gatewayURL := auth.GetDefaultGatewayURL() + creds := store.GetDefaultCredential(gatewayURL) + if creds == nil { + return "", fmt.Errorf("no credentials found for %s. Run 'orama auth login' to authenticate", gatewayURL) + } + + if !creds.IsValid() { + return "", fmt.Errorf("credentials expired for %s. Run 'orama auth login' to re-authenticate", gatewayURL) + } + + return creds.APIKey, nil } diff --git a/pkg/cli/dev_commands.go b/pkg/cli/dev_commands.go index 2d289af..ae38a4d 100644 --- a/pkg/cli/dev_commands.go +++ b/pkg/cli/dev_commands.go @@ -158,7 +158,7 @@ func handleDevStatus(args []string) { func handleDevLogs(args []string) { if len(args) == 0 { - fmt.Fprintf(os.Stderr, "Usage: dbn dev logs [--follow]\n") + fmt.Fprintf(os.Stderr, "Usage: orama dev logs [--follow]\n") fmt.Fprintf(os.Stderr, "\nComponents: node-1, node-2, node-3, node-4, node-5, gateway, ipfs-node-1, ipfs-node-2, ipfs-node-3, ipfs-node-4, ipfs-node-5, olric, anon\n") os.Exit(1) } diff --git a/pkg/cli/env_commands.go b/pkg/cli/env_commands.go index abcd85d..621a9eb 100644 --- a/pkg/cli/env_commands.go +++ b/pkg/cli/env_commands.go @@ -24,6 +24,10 @@ func HandleEnvCommand(args []string) { handleEnvSwitch(subargs) case "enable": handleEnvEnable(subargs) + case "add": + handleEnvAdd(subargs) + case "remove": + handleEnvRemove(subargs) case "help": showEnvHelp() default: @@ -35,7 +39,7 @@ func HandleEnvCommand(args []string) { func showEnvHelp() { fmt.Printf("šŸŒ Environment Management Commands\n\n") - fmt.Printf("Usage: dbn env \n\n") + fmt.Printf("Usage: orama env \n\n") fmt.Printf("Subcommands:\n") fmt.Printf(" list - List all available environments\n") fmt.Printf(" current - Show current active environment\n") @@ -46,12 +50,12 @@ func showEnvHelp() { fmt.Printf(" devnet - Development network (https://devnet.orama.network)\n") fmt.Printf(" testnet - Test network (https://testnet.orama.network)\n\n") fmt.Printf("Examples:\n") - fmt.Printf(" dbn env list\n") - fmt.Printf(" dbn env current\n") - fmt.Printf(" dbn env switch devnet\n") - fmt.Printf(" dbn env enable testnet\n") - fmt.Printf(" dbn devnet enable # Shorthand for switch to devnet\n") - fmt.Printf(" dbn testnet enable # Shorthand for switch to testnet\n") + fmt.Printf(" orama env list\n") + fmt.Printf(" orama env current\n") + fmt.Printf(" orama env switch devnet\n") + fmt.Printf(" orama env enable testnet\n") + fmt.Printf(" orama devnet enable # Shorthand for switch to devnet\n") + fmt.Printf(" orama testnet enable # Shorthand for switch to testnet\n") } func handleEnvList() { @@ -99,7 +103,7 @@ func handleEnvCurrent() { func handleEnvSwitch(args []string) { if len(args) == 0 { - fmt.Fprintf(os.Stderr, "Usage: dbn env switch \n") + fmt.Fprintf(os.Stderr, "Usage: orama env switch \n") fmt.Fprintf(os.Stderr, "Available: local, devnet, testnet\n") os.Exit(1) } @@ -140,3 +144,108 @@ func handleEnvEnable(args []string) { // 'enable' is just an alias for 'switch' handleEnvSwitch(args) } + +func handleEnvAdd(args []string) { + if len(args) < 2 { + fmt.Fprintf(os.Stderr, "Usage: orama env add [description]\n") + fmt.Fprintf(os.Stderr, "Example: orama env add production http://dbrs.space \"Production network\"\n") + os.Exit(1) + } + + name := args[0] + gatewayURL := args[1] + description := "" + if len(args) > 2 { + description = args[2] + } + + // Initialize environments if needed + if err := InitializeEnvironments(); err != nil { + fmt.Fprintf(os.Stderr, "āŒ Failed to initialize environments: %v\n", err) + os.Exit(1) + } + + envConfig, err := LoadEnvironmentConfig() + if err != nil { + fmt.Fprintf(os.Stderr, "āŒ Failed to load environment config: %v\n", err) + os.Exit(1) + } + + // Check if environment already exists + for _, env := range envConfig.Environments { + if env.Name == name { + fmt.Fprintf(os.Stderr, "āŒ Environment '%s' already exists\n", name) + os.Exit(1) + } + } + + // Add new environment + envConfig.Environments = append(envConfig.Environments, Environment{ + Name: name, + GatewayURL: gatewayURL, + Description: description, + IsActive: false, + }) + + if err := SaveEnvironmentConfig(envConfig); err != nil { + fmt.Fprintf(os.Stderr, "āŒ Failed to save environment config: %v\n", err) + os.Exit(1) + } + + fmt.Printf("āœ… Added environment: %s\n", name) + fmt.Printf(" Gateway URL: %s\n", gatewayURL) + if description != "" { + fmt.Printf(" Description: %s\n", description) + } +} + +func handleEnvRemove(args []string) { + if len(args) == 0 { + fmt.Fprintf(os.Stderr, "Usage: orama env remove \n") + os.Exit(1) + } + + name := args[0] + + // Don't allow removing 'local' + if name == "local" { + fmt.Fprintf(os.Stderr, "āŒ Cannot remove the 'local' environment\n") + os.Exit(1) + } + + envConfig, err := LoadEnvironmentConfig() + if err != nil { + fmt.Fprintf(os.Stderr, "āŒ Failed to load environment config: %v\n", err) + os.Exit(1) + } + + // Find and remove environment + found := false + newEnvs := make([]Environment, 0, len(envConfig.Environments)) + for _, env := range envConfig.Environments { + if env.Name == name { + found = true + continue + } + newEnvs = append(newEnvs, env) + } + + if !found { + fmt.Fprintf(os.Stderr, "āŒ Environment '%s' not found\n", name) + os.Exit(1) + } + + envConfig.Environments = newEnvs + + // If we removed the active environment, switch to local + if envConfig.ActiveEnvironment == name { + envConfig.ActiveEnvironment = "local" + } + + if err := SaveEnvironmentConfig(envConfig); err != nil { + fmt.Fprintf(os.Stderr, "āŒ Failed to save environment config: %v\n", err) + os.Exit(1) + } + + fmt.Printf("āœ… Removed environment: %s\n", name) +} diff --git a/pkg/cli/environment.go b/pkg/cli/environment.go index b52fba6..038ce32 100644 --- a/pkg/cli/environment.go +++ b/pkg/cli/environment.go @@ -31,6 +31,12 @@ var DefaultEnvironments = []Environment{ Description: "Local development environment (node-1)", IsActive: true, }, + { + Name: "production", + GatewayURL: "http://dbrs.space", + Description: "Production network (dbrs.space)", + IsActive: false, + }, { Name: "devnet", GatewayURL: "https://devnet.orama.network", diff --git a/pkg/cli/production/install/validator.go b/pkg/cli/production/install/validator.go index 7329cb8..6e8bf5c 100644 --- a/pkg/cli/production/install/validator.go +++ b/pkg/cli/production/install/validator.go @@ -11,16 +11,16 @@ import ( // Validator validates install command inputs type Validator struct { - flags *Flags - oramaDir string + flags *Flags + oramaDir string isFirstNode bool } // NewValidator creates a new validator func NewValidator(flags *Flags, oramaDir string) *Validator { return &Validator{ - flags: flags, - oramaDir: oramaDir, + flags: flags, + oramaDir: oramaDir, isFirstNode: flags.JoinAddress == "", } } @@ -28,7 +28,7 @@ func NewValidator(flags *Flags, oramaDir string) *Validator { // ValidateFlags validates required flags func (v *Validator) ValidateFlags() error { if v.flags.VpsIP == "" && !v.flags.DryRun { - return fmt.Errorf("--vps-ip is required for installation\nExample: dbn prod install --vps-ip 1.2.3.4") + return fmt.Errorf("--vps-ip is required for installation\nExample: orama prod install --vps-ip 1.2.3.4") } return nil } diff --git a/pkg/cli/production/lifecycle/start.go b/pkg/cli/production/lifecycle/start.go index 26ba28f..ce36de6 100644 --- a/pkg/cli/production/lifecycle/start.go +++ b/pkg/cli/production/lifecycle/start.go @@ -51,7 +51,7 @@ func HandleStart() { } if active { fmt.Printf(" ā„¹ļø %s already running\n", svc) - // Re-enable if disabled (in case it was stopped with 'dbn prod stop') + // Re-enable if disabled (in case it was stopped with 'orama prod stop') enabled, err := utils.IsServiceEnabled(svc) if err == nil && !enabled { if err := exec.Command("systemctl", "enable", svc).Run(); err != nil { @@ -83,7 +83,7 @@ func HandleStart() { // Enable and start inactive services for _, svc := range inactive { - // Re-enable the service first (in case it was disabled by 'dbn prod stop') + // Re-enable the service first (in case it was disabled by 'orama prod stop') enabled, err := utils.IsServiceEnabled(svc) if err == nil && !enabled { if err := exec.Command("systemctl", "enable", svc).Run(); err != nil { diff --git a/pkg/cli/production/lifecycle/stop.go b/pkg/cli/production/lifecycle/stop.go index aeaec4d..ffd7332 100644 --- a/pkg/cli/production/lifecycle/stop.go +++ b/pkg/cli/production/lifecycle/stop.go @@ -107,6 +107,6 @@ func HandleStop() { fmt.Fprintf(os.Stderr, " If services are still restarting, they may need manual intervention\n") } else { fmt.Printf("\nāœ… All services stopped and disabled (will not auto-start on boot)\n") - fmt.Printf(" Use 'dbn prod start' to start and re-enable services\n") + fmt.Printf(" Use 'orama prod start' to start and re-enable services\n") } } diff --git a/pkg/cli/production/logs/command.go b/pkg/cli/production/logs/command.go index f06ecbf..7c66baf 100644 --- a/pkg/cli/production/logs/command.go +++ b/pkg/cli/production/logs/command.go @@ -47,7 +47,7 @@ func Handle(args []string) { } func showUsage() { - fmt.Fprintf(os.Stderr, "Usage: dbn prod logs [--follow]\n") + fmt.Fprintf(os.Stderr, "Usage: orama prod logs [--follow]\n") fmt.Fprintf(os.Stderr, "\nService aliases:\n") fmt.Fprintf(os.Stderr, " node, ipfs, cluster, gateway, olric\n") fmt.Fprintf(os.Stderr, "\nOr use full service name:\n") diff --git a/pkg/cli/production/status/command.go b/pkg/cli/production/status/command.go index af082d9..ff43b38 100644 --- a/pkg/cli/production/status/command.go +++ b/pkg/cli/production/status/command.go @@ -54,5 +54,5 @@ func Handle() { fmt.Printf(" āŒ %s not found\n", oramaDir) } - fmt.Printf("\nView logs with: dbn prod logs \n") + fmt.Printf("\nView logs with: orama prod logs \n") }