package cmd import ( "fmt" "os" "git.jnss.me/joakim/opal/internal/api" "git.jnss.me/joakim/opal/internal/engine" "github.com/spf13/cobra" ) var serverCmd = &cobra.Command{ Use: "server", Short: "Server management commands", Long: `Commands for running and managing the opal API server`, } var serverStartCmd = &cobra.Command{ Use: "start", Short: "Start the opal API server", Long: `Starts the opal-task REST API server for remote access. Examples: opal server start opal server start --addr :8080 opal server start --db /var/lib/opal/opal.db`, Run: func(cmd *cobra.Command, args []string) { addr, _ := cmd.Flags().GetString("addr") dbPath, _ := cmd.Flags().GetString("db") // Override DB path if specified if dbPath != "" { os.Setenv("OPAL_DB_PATH", dbPath) } // Initialize database if err := engine.InitDB(); err != nil { fmt.Fprintf(os.Stderr, "Error initializing database: %v\n", err) os.Exit(1) } defer engine.CloseDB() // Create and start server server := api.NewServer(addr) if err := server.Start(); err != nil { fmt.Fprintf(os.Stderr, "Error starting server: %v\n", err) os.Exit(1) } }, } var keygenCmd = &cobra.Command{ Use: "keygen", Short: "Generate API key for server authentication", Long: `Generate a new API key for authenticating with the opal server. This command should be run on the server with direct database access. The generated key will be displayed once and cannot be retrieved again. Examples: opal server keygen --name "My Phone" opal server keygen --name "Laptop" --db /var/lib/opal/opal.db`, Run: func(cmd *cobra.Command, args []string) { name, _ := cmd.Flags().GetString("name") dbPath, _ := cmd.Flags().GetString("db") if name == "" { fmt.Fprintf(os.Stderr, "Error: --name is required\n") os.Exit(1) } // Override DB path if specified if dbPath != "" { os.Setenv("OPAL_DB_PATH", dbPath) } if err := engine.InitDB(); err != nil { fmt.Fprintf(os.Stderr, "Error initializing database: %v\n", err) os.Exit(1) } defer engine.CloseDB() key, err := engine.GenerateAPIKey(name) if err != nil { fmt.Fprintf(os.Stderr, "Error generating API key: %v\n", err) os.Exit(1) } fmt.Println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━") fmt.Println("API Key Generated Successfully") fmt.Println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━") fmt.Printf("Name: %s\n", name) fmt.Printf("Key: %s\n", key) fmt.Println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━") fmt.Println("") fmt.Println("⚠️ IMPORTANT: Save this key securely!") fmt.Println(" It will not be displayed again.") fmt.Println("") fmt.Println("To configure a client:") fmt.Printf(" opal sync init --url https://opal.yourdomain.com --key %s\n", key) }, } func init() { rootCmd.AddCommand(serverCmd) serverCmd.AddCommand(serverStartCmd) serverCmd.AddCommand(keygenCmd) serverStartCmd.Flags().StringP("addr", "a", ":8080", "Server address") serverStartCmd.Flags().StringP("db", "d", "", "Database path (default: config directory)") keygenCmd.Flags().StringP("name", "n", "", "Name for this API key (e.g., device name)") keygenCmd.Flags().StringP("db", "d", "", "Database path (default: config directory)") keygenCmd.MarkFlagRequired("name") }