package main import ( "context" "encoding/json" "fmt" "io" "net/http" "os" "time" "github.com/spf13/cobra" "github.com/spf13/viper" ) type DatabaseCredentials struct { Host string `json:"host"` Port int `json:"port"` Name string `json:"name"` User string `json:"user"` Password string `json:"password"` } var ( dbUsername string dbToken string useStored bool ) var databaseCmd = &cobra.Command{ Use: "database", Short: "Manage database credentials", Long: `Commands for managing database credentials in the MCIAS system.`, } var getCredentialsCmd = &cobra.Command{ Use: "credentials", Short: "Get database credentials", Long: `Retrieve database credentials from the MCIAS system. This command requires authentication with a username and token.`, Run: func(cmd *cobra.Command, args []string) { getCredentials() }, } func init() { rootCmd.AddCommand(databaseCmd) databaseCmd.AddCommand(getCredentialsCmd) getCredentialsCmd.Flags().StringVarP(&dbUsername, "username", "u", "", "Username for authentication") getCredentialsCmd.Flags().StringVarP(&dbToken, "token", "t", "", "Authentication token") getCredentialsCmd.Flags().BoolVarP(&useStored, "use-stored", "s", false, "Use stored token from previous login") // Make username required only if not using stored token getCredentialsCmd.MarkFlagsMutuallyExclusive("token", "use-stored") } func getCredentials() { // If using stored token, load it from the token file if useStored { tokenInfo, err := loadToken() if err != nil { fmt.Fprintf(os.Stderr, "Error loading token: %v\n", err) os.Exit(1) } dbUsername = tokenInfo.Username dbToken = tokenInfo.Token } // Validate required parameters if dbUsername == "" { fmt.Fprintf(os.Stderr, "Error: username is required\n") os.Exit(1) } if dbToken == "" { fmt.Fprintf(os.Stderr, "Error: token is required (either provide --token or use --use-stored)\n") os.Exit(1) } serverAddr := viper.GetString("server") if serverAddr == "" { serverAddr = "http://localhost:8080" } url := fmt.Sprintf("%s/v1/database/credentials?username=%s", serverAddr, dbUsername) // Create a context with timeout ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() req, err := http.NewRequestWithContext(ctx, "GET", url, nil) if err != nil { fmt.Fprintf(os.Stderr, "Failed to create request: %v\n", err) os.Exit(1) } req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", dbToken)) client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Fprintf(os.Stderr, "Failed to send request: %v\n", err) os.Exit(1) } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { fmt.Fprintf(os.Stderr, "Failed to read response: %v\n", err) os.Exit(1) } if resp.StatusCode != http.StatusOK { var errResp ErrorResponse if unmarshalErr := json.Unmarshal(body, &errResp); unmarshalErr == nil { fmt.Fprintf(os.Stderr, "Error: %s\n", errResp.Error) } else { fmt.Fprintf(os.Stderr, "Error: %s\n", resp.Status) } os.Exit(1) } var creds DatabaseCredentials if unmarshalErr := json.Unmarshal(body, &creds); unmarshalErr != nil { fmt.Fprintf(os.Stderr, "Failed to parse response: %v\n", unmarshalErr) os.Exit(1) } fmt.Println("Database Credentials:") fmt.Printf("Host: %s\n", creds.Host) fmt.Printf("Port: %d\n", creds.Port) fmt.Printf("Name: %s\n", creds.Name) fmt.Printf("User: %s\n", creds.User) fmt.Printf("Password: %s\n", creds.Password) }