package cmd import ( "context" "fmt" "git.faercol.me/faercol/polyculeconnect/polyculeconnect/cmd/utils" "git.faercol.me/faercol/polyculeconnect/polyculeconnect/internal/db" "git.faercol.me/faercol/polyculeconnect/polyculeconnect/internal/model" "git.faercol.me/faercol/polyculeconnect/polyculeconnect/logger" "git.faercol.me/faercol/polyculeconnect/polyculeconnect/services" "github.com/spf13/cobra" ) var ( appID string appClientID string appClientSecret string appName string appRedirectURIs []string appInteractive bool ) var appAddCmd = &cobra.Command{ Use: "add", Short: "Add a new app to the storage", Long: `Add a new app to the storage. Parameters to provide: - id: Unique ID to represent the app in the storage - name: Human readable name to represent the app. - redirect-uri: list of allowed redirection URIs for this app Optional parameters: - client-id: Client ID used by the OpenIDConnect protocol, automatically generated if not provided - client-secret: Client secret used by the OpenIDConnect protocol, automatically generated if not provided - interactive: Pass this parameter to use a prompt to pass unset parameters (client id and secret)`, Run: func(cmd *cobra.Command, args []string) { addNewApp() }, } func generateSecret(interactive bool, currentValue, valueName string) (string, error) { if currentValue != "" { return currentValue, nil } if !interactive { val, err := services.GenerateRandomHex(services.IDSecretSize) if err != nil { return "", fmt.Errorf("failed to generate %s: %w", valueName, err) } return val, nil } fmt.Printf("Enter value for %s, use an empty value to automatically generate it.\n", valueName) var enteredVal string fmt.Scanln(&enteredVal) if enteredVal == "" { return generateSecret(false, currentValue, valueName) } return enteredVal, nil } func addNewApp() { c := utils.InitConfig("") logger.Init(c.LogLevel) s, err := db.New(*c) if err != nil { utils.Failf("failed to init storage: %s", err.Error()) } clientID, err := generateSecret(appInteractive, appClientID, "client ID") if err != nil { utils.Fail(err.Error()) } clientSecret, err := generateSecret(appInteractive, appClientSecret, "client secret") if err != nil { utils.Fail(err.Error()) } appConf := model.ClientConfig{ ID: clientID, Secret: clientSecret, Name: appName, RedirectURIs: appRedirectURIs, } clt := model.Client{ ClientConfig: appConf, } if err := s.ClientStorage().AddClient(context.Background(), &clt); err != nil { utils.Failf("failed to create app: %s", err) } fmt.Printf("New app %s added.\n", appName) printProperty("Client ID", clientID, 1) printProperty("Client secret", clientSecret, 1) } func init() { appCmd.AddCommand(appAddCmd) appAddCmd.Flags().StringVarP(&appName, "name", "n", "", "Name to represent the app") appAddCmd.Flags().StringVarP(&appID, "id", "i", "", "ID to identify the app in the storage") appAddCmd.Flags().StringVarP(&appClientID, "client-id", "", "", "OpenIDConnect client secret") appAddCmd.Flags().StringVarP(&appClientSecret, "client-secret", "", "", "OpenIDConnect client secret") appAddCmd.Flags().StringSliceVarP(&appRedirectURIs, "redirect-uri", "r", []string{}, "Allowed redirect URI") appAddCmd.Flags().BoolVar(&appInteractive, "interactive", false, "Set the client ID and secret in an interactive way") appAddCmd.MarkFlagRequired("name") appAddCmd.MarkFlagRequired("redirect-uri") }