package main import ( "context" "encoding/json" "fmt" "io" "log" "net/http" "os" "time" "github.com/spf13/cobra" "github.com/spf13/viper" ) var ( dbUsername string dbToken string ) type DatabaseCredentials struct { Host string `json:"host"` Port int `json:"port"` Name string `json:"name"` User string `json:"user"` Password string `json:"password"` } type ErrorResponse struct { Error string `json:"error"` } var databaseCmd = &cobra.Command{ Use: "database", Short: "Manage database credentials", Long: `Commands for managing database credentials in the MCIAS system.`, } var addDBUserCmd = &cobra.Command{ Use: "add-user [database-id] [user-id]", Short: "Associate a user with a database", Long: `Associate a user with a database, allowing them to read its credentials.`, Args: cobra.ExactArgs(2), Run: func(cmd *cobra.Command, args []string) { addUserToDatabase(args[0], args[1]) }, } var removeDBUserCmd = &cobra.Command{ Use: "remove-user [database-id] [user-id]", Short: "Remove a user's association with a database", Long: `Remove a user's association with a database, preventing them from reading its credentials.`, Args: cobra.ExactArgs(2), Run: func(_ *cobra.Command, args []string) { removeUserFromDatabase(args[0], args[1]) }, } var listDBUsersCmd = &cobra.Command{ Use: "list-users [database-id]", Short: "List users associated with a database", Long: `List all users who have access to read the credentials of a specific database.`, Args: cobra.ExactArgs(1), Run: func(_ *cobra.Command, args []string) { listDatabaseUsers(args[0]) }, } 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(_ *cobra.Command, args []string) { getCredentials() }, } func init() { rootCmd.AddCommand(databaseCmd) databaseCmd.AddCommand(getCredentialsCmd) databaseCmd.AddCommand(addDBUserCmd) databaseCmd.AddCommand(removeDBUserCmd) databaseCmd.AddCommand(listDBUsersCmd) getCredentialsCmd.Flags().StringVarP(&dbUsername, "username", "u", "", "Username for authentication") getCredentialsCmd.Flags().StringVarP(&dbToken, "token", "t", "", "Authentication token") if err := getCredentialsCmd.MarkFlagRequired("username"); err != nil { fmt.Fprintf(os.Stderr, "Error marking username flag as required: %v\n", err) } if err := getCredentialsCmd.MarkFlagRequired("token"); err != nil { fmt.Fprintf(os.Stderr, "Error marking token flag as required: %v\n", err) } } func getCredentials() { logger := log.New(os.Stdout, "MCIAS: ", log.LstdFlags) serverAddr := viper.GetString("server") if serverAddr == "" { serverAddr = "http://localhost:8080" } url := fmt.Sprintf("%s/v1/database/credentials?username=%s", serverAddr, dbUsername) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() req, err := http.NewRequestWithContext(ctx, "GET", url, nil) if err != nil { logger.Fatalf("Failed to create request: %v", err) } req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", dbToken)) client := &http.Client{} resp, err := client.Do(req) if err != nil { logger.Fatalf("Failed to send request: %v", err) } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { logger.Fatalf("Failed to read response: %v", err) } if resp.StatusCode != http.StatusOK { var errResp ErrorResponse if unmarshalErr := json.Unmarshal(body, &errResp); unmarshalErr == nil { logger.Fatalf("Error: %s", errResp.Error) } else { logger.Fatalf("Error: %s", resp.Status) } } var creds DatabaseCredentials if unmarshalErr := json.Unmarshal(body, &creds); unmarshalErr != nil { logger.Fatalf("Failed to parse response: %v", unmarshalErr) } 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) }