From b212681d091e5c3d6be4671d60e838d120cd99c0 Mon Sep 17 00:00:00 2001 From: quinton Date: Sat, 25 Nov 2023 09:44:51 +0000 Subject: [PATCH 1/4] feat: cli-folders-cmd --- cli/packages/api/api.go | 76 +++++++++++ cli/packages/api/model.go | 41 ++++++ cli/packages/cmd/folder.go | 191 ++++++++++++++++++++++++++ cli/packages/models/cli.go | 28 ++++ cli/packages/util/folders.go | 217 ++++++++++++++++++++++++++++++ cli/packages/visualize/folders.go | 14 ++ 6 files changed, 567 insertions(+) create mode 100644 cli/packages/cmd/folder.go create mode 100644 cli/packages/util/folders.go create mode 100644 cli/packages/visualize/folders.go diff --git a/cli/packages/api/api.go b/cli/packages/api/api.go index 1be58985c..d9278d08c 100644 --- a/cli/packages/api/api.go +++ b/cli/packages/api/api.go @@ -260,6 +260,82 @@ func CallGetSecretsV3(httpClient *resty.Client, request GetEncryptedSecretsV3Req return secretsResponse, nil } +func CallGetFoldersV1(httpClient *resty.Client, request GetFoldersV1Request) (GetFoldersV1Response, error) { + var foldersResponse GetFoldersV1Response + httpRequest := httpClient. + R(). + SetResult(&foldersResponse). + SetHeader("User-Agent", USER_AGENT). + SetQueryParam("environment", request.Environment). + SetQueryParam("workspaceId", request.WorkspaceId). + SetQueryParam("directory", request.FoldersPath) + + response, err := httpRequest.Get(fmt.Sprintf("%v/v1/folders", config.INFISICAL_URL)) + + if err != nil { + return GetFoldersV1Response{}, fmt.Errorf("CallGetFoldersV1: Unable to complete api request [err=%s]", err) + } + + if response.IsError() { + return GetFoldersV1Response{}, fmt.Errorf("CallGetFoldersV1: Unsuccessful response. Please make sure your secret path, workspace and environment name are all correct [response=%s]", response) + } + + return foldersResponse, nil +} + +func CallCreateFolderV1(httpClient *resty.Client, request CreateFolderV1Request) (CreateFolderV1Response, error) { + var folderResponse CreateFolderV1Response + httpRequest := httpClient. + R(). + SetResult(&folderResponse). + SetHeader("User-Agent", USER_AGENT). + SetBody(request) + + response, err := httpRequest.Post(fmt.Sprintf("%v/v1/folders", config.INFISICAL_URL)) + if err != nil { + return CreateFolderV1Response{}, fmt.Errorf("CallCreateFolderV1: Unable to complete api request [err=%s]", err) + } + + if response.IsError() { + return CreateFolderV1Response{}, fmt.Errorf("CallCreateFolderV1: Unsuccessful response. Please make sure your secret path, workspace and environment name are all correct [response=%s]", response) + } + + return folderResponse, nil +} + +func CallDeleteFolderV1(httpClient *resty.Client, request DeleteFolderV1Request) (DeleteFolderV1Response, error) { + var folderResponse DeleteFolderV1Response + + type deleteFolderRequest struct { + WorkspaceId string `json:"workspaceId"` + Environment string `json:"environment"` + Directory string `json:"folderPath"` + } + + body := deleteFolderRequest{ + WorkspaceId: request.WorkspaceId, + Environment: request.Environment, + Directory: request.Directory, + } + + httpRequest := httpClient. + R(). + SetResult(&folderResponse). + SetHeader("User-Agent", USER_AGENT). + SetBody(body) + + response, err := httpRequest.Delete(fmt.Sprintf("%v/v1/folders/%v", config.INFISICAL_URL, request.FolderName)) + if err != nil { + return DeleteFolderV1Response{}, fmt.Errorf("CallDeleteFolderV1: Unable to complete api request [err=%s]", err) + } + + if response.IsError() { + return DeleteFolderV1Response{}, fmt.Errorf("CallDeleteFolderV1: Unsuccessful response. Please make sure your secret path, workspace and environment name are all correct [response=%s]", response) + } + + return folderResponse, nil +} + func CallCreateSecretsV3(httpClient *resty.Client, request CreateSecretV3Request) error { var secretsResponse GetEncryptedSecretsV3Response response, err := httpClient. diff --git a/cli/packages/api/model.go b/cli/packages/api/model.go index 1531dce36..e8cc03b3a 100644 --- a/cli/packages/api/model.go +++ b/cli/packages/api/model.go @@ -278,6 +278,47 @@ type GetEncryptedSecretsV3Request struct { IncludeImport bool `json:"include_imports"` } +type GetFoldersV1Request struct { + Environment string `json:"environment"` + WorkspaceId string `json:"workspaceId"` + FoldersPath string `json:"foldersPath"` +} + +type GetFoldersV1Response struct { + Folders []struct { + ID string `json:"id"` + Name string `json:"name"` + } `json:"folders"` +} + +type CreateFolderV1Request struct { + FolderName string `json:"folderName"` + WorkspaceId string `json:"workspaceId"` + Environment string `json:"environment"` + Directory string `json:"directory"` +} + +type CreateFolderV1Response struct { + Folder struct { + ID string `json:"id"` + Name string `json:"name"` + } `json:"folder"` +} + +type DeleteFolderV1Request struct { + FolderName string `json:"folderName"` + WorkspaceId string `json:"workspaceId"` + Environment string `json:"environment"` + Directory string `json:"directory"` +} + +type DeleteFolderV1Response struct { + Folders []struct { + ID string `json:"id"` + Name string `json:"name"` + } `json:"folders"` +} + type EncryptedSecretV3 struct { ID string `json:"_id"` Version int `json:"version"` diff --git a/cli/packages/cmd/folder.go b/cli/packages/cmd/folder.go new file mode 100644 index 000000000..681fd731c --- /dev/null +++ b/cli/packages/cmd/folder.go @@ -0,0 +1,191 @@ +package cmd + +import ( + "fmt" + + "github.com/Infisical/infisical-merge/packages/models" + "github.com/Infisical/infisical-merge/packages/util" + "github.com/Infisical/infisical-merge/packages/visualize" + "github.com/posthog/posthog-go" + "github.com/spf13/cobra" +) + +var folderCmd = &cobra.Command{ + Use: "folders", + Short: "Create, delete, and list folders", + DisableFlagsInUseLine: true, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} + +var getCmd = &cobra.Command{ + Use: "get", + Short: "Get folders in a directory", + DisableFlagsInUseLine: true, + Run: func(cmd *cobra.Command, args []string) { + + environmentName, _ := cmd.Flags().GetString("env") + if !cmd.Flags().Changed("env") { + environmentFromWorkspace := util.GetEnvFromWorkspaceFile() + if environmentFromWorkspace != "" { + environmentName = environmentFromWorkspace + } + } + + infisicalToken, err := cmd.Flags().GetString("token") + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + + foldersPath, err := cmd.Flags().GetString("path") + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + + folders, err := util.GetAllFolders(models.GetAllFoldersParameters{Environment: environmentName, InfisicalToken: infisicalToken, FoldersPath: foldersPath}) + if err != nil { + util.HandleError(err, "Unable to get folders") + } + + visualize.PrintAllFoldersDetails(folders) + Telemetry.CaptureEvent("cli-command:folders get", posthog.NewProperties().Set("folderCount", len(folders)).Set("version", util.CLI_VERSION)) + }, +} + +var createCmd = &cobra.Command{ + Use: "create", + Short: "Create a folder", + DisableFlagsInUseLine: true, + Run: func(cmd *cobra.Command, args []string) { + util.RequireLocalWorkspaceFile() + environmentName, _ := cmd.Flags().GetString("env") + if !cmd.Flags().Changed("env") { + environmentFromWorkspace := util.GetEnvFromWorkspaceFile() + if environmentFromWorkspace != "" { + environmentName = environmentFromWorkspace + } + } + + infisicalToken, err := cmd.Flags().GetString("token") + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + + folderPath, err := cmd.Flags().GetString("path") + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + + folderName, err := cmd.Flags().GetString("name") + if err != nil { + util.HandleError(err, "Unable to parse name flag") + } + + if folderName == "" { + util.HandleError(fmt.Errorf("Invalid folder name"), "Folder name cannot be empty") + } + + workspaceFile, err := util.GetWorkSpaceFromFile() + if err != nil { + util.HandleError(err, "Unable to get workspace file") + } + + params := models.CreateFolderParameters{ + FolderName: folderName, + WorkspaceId: workspaceFile.WorkspaceId, + Environment: environmentName, + FolderPath: folderPath, + InfisicalToken: infisicalToken} + + folder, err := util.CreateFolder(params) + if err != nil { + util.HandleError(err, "Unable to create folder") + } + + folders := []models.SingleFolder{folder} + visualize.PrintAllFoldersDetails(folders) + Telemetry.CaptureEvent("cli-command:folders create", posthog.NewProperties().Set("version", util.CLI_VERSION)) + }, +} + +var deleteCmd = &cobra.Command{ + Use: "delete", + Short: "Delete a folder", + Run: func(cmd *cobra.Command, args []string) { + util.RequireLocalWorkspaceFile() + + environmentName, _ := cmd.Flags().GetString("env") + if !cmd.Flags().Changed("env") { + environmentFromWorkspace := util.GetEnvFromWorkspaceFile() + if environmentFromWorkspace != "" { + environmentName = environmentFromWorkspace + } + } + + infisicalToken, err := cmd.Flags().GetString("token") + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + + folderPath, err := cmd.Flags().GetString("path") + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + + folderName, err := cmd.Flags().GetString("name") + if err != nil { + util.HandleError(err, "Unable to parse name flag") + } + + if folderName == "" { + util.HandleError(fmt.Errorf("Invalid folder name"), "Folder name cannot be empty") + } + + workspaceFile, err := util.GetWorkSpaceFromFile() + if err != nil { + util.HandleError(err, "Unable to get workspace file") + } + + params := models.DeleteFolderParameters{ + FolderName: folderName, + WorkspaceId: workspaceFile.WorkspaceId, + Environment: environmentName, + FolderPath: folderPath, + InfisicalToken: infisicalToken, + } + + folders, err := util.DeleteFolder(params) + if err != nil { + util.HandleError(err, "Unable to delete folder") + } + + visualize.PrintAllFoldersDetails(folders) + Telemetry.CaptureEvent("cli-command:folders delete", posthog.NewProperties().Set("version", util.CLI_VERSION)) + }, +} + +func init() { + + folderCmd.PersistentFlags().String("env", "dev", "Used to select the environment name on which actions should be taken on") + + // Add getCmd, createCmd and deleteCmd flags here + getCmd.Flags().StringP("path", "p", "/", "Path to the directory whose folders will be fetched") + getCmd.Flags().StringP("token", "t", "", "Fetch folders using the infisical token") + folderCmd.AddCommand(getCmd) + + // Add createCmd flags here + createCmd.Flags().StringP("path", "p", "/", "Path to the directory where the folder will be created") + createCmd.Flags().StringP("token", "t", "", "Create folder using the infisical token") + createCmd.Flags().StringP("name", "n", "", "Name of the folder to be created") + folderCmd.AddCommand(createCmd) + + // Add deleteCmd flags here + deleteCmd.Flags().StringP("path", "p", "/", "Path to the directory where the folder will be deleted") + deleteCmd.Flags().StringP("token", "t", "", "Delete folder using the infisical token") + deleteCmd.Flags().StringP("name", "n", "", "Name of the folder to be deleted") + folderCmd.AddCommand(deleteCmd) + + rootCmd.AddCommand(folderCmd) + +} diff --git a/cli/packages/models/cli.go b/cli/packages/models/cli.go index 8e012a86f..165982a77 100644 --- a/cli/packages/models/cli.go +++ b/cli/packages/models/cli.go @@ -34,6 +34,11 @@ type SingleEnvironmentVariable struct { Comment string `json:"comment"` } +type SingleFolder struct { + ID string `json:"_id"` + Name string `json:"name"` +} + type Workspace struct { ID string `json:"_id"` Name string `json:"name"` @@ -63,3 +68,26 @@ type GetAllSecretsParameters struct { SecretsPath string IncludeImport bool } + +type GetAllFoldersParameters struct { + WorkspaceId string + Environment string + FoldersPath string + InfisicalToken string +} + +type CreateFolderParameters struct { + FolderName string + WorkspaceId string + Environment string + FolderPath string + InfisicalToken string +} + +type DeleteFolderParameters struct { + FolderName string + WorkspaceId string + Environment string + FolderPath string + InfisicalToken string +} diff --git a/cli/packages/util/folders.go b/cli/packages/util/folders.go new file mode 100644 index 000000000..67ed66fa2 --- /dev/null +++ b/cli/packages/util/folders.go @@ -0,0 +1,217 @@ +package util + +import ( + "fmt" + "os" + "strings" + + "github.com/Infisical/infisical-merge/packages/api" + "github.com/Infisical/infisical-merge/packages/models" + "github.com/go-resty/resty/v2" + "github.com/rs/zerolog/log" +) + +func GetAllFolders(params models.GetAllFoldersParameters) ([]models.SingleFolder, error) { + + if params.InfisicalToken == "" { + params.InfisicalToken = os.Getenv(INFISICAL_TOKEN_NAME) + } + + isConnected := CheckIsConnectedToInternet() + var foldersToReturn []models.SingleFolder + var folderErr error + if params.InfisicalToken == "" { + if isConnected { + log.Debug().Msg("GetAllFolders: Connected to internet, checking logged in creds") + RequireLocalWorkspaceFile() + RequireLogin() + } + + log.Debug().Msg("GetAllEnvironmentVariables: Trying to fetch secrets using logged in details") + + loggedInUserDetails, err := GetCurrentLoggedInUserDetails() + if err != nil { + return nil, err + } + + if loggedInUserDetails.LoginExpired { + PrintErrorMessageAndExit("Your login session has expired, please run [infisical login] and try again") + } + + workspaceFile, err := GetWorkSpaceFromFile() + if err != nil { + return nil, err + } + + if params.WorkspaceId != "" { + workspaceFile.WorkspaceId = params.WorkspaceId + } + + folders, err := GetFoldersViaJTW(loggedInUserDetails.UserCredentials.JTWToken, workspaceFile.WorkspaceId, params.Environment, params.FoldersPath) + folderErr = err + foldersToReturn = folders + } else { + // get folders via service token + folders, err := GetFoldersViaServiceToken(params.InfisicalToken, params.WorkspaceId, params.Environment, params.FoldersPath) + folderErr = err + foldersToReturn = folders + } + return foldersToReturn, folderErr +} + +func GetFoldersViaJTW(JTWToken string, workspaceId string, environmentName string, foldersPath string) ([]models.SingleFolder, error) { + // set up resty client + httpClient := resty.New() + httpClient.SetAuthToken(JTWToken). + SetHeader("Accept", "application/json") + + getFoldersRequest := api.GetFoldersV1Request{ + WorkspaceId: workspaceId, + Environment: environmentName, + FoldersPath: foldersPath, + } + + apiResponse, err := api.CallGetFoldersV1(httpClient, getFoldersRequest) + if err != nil { + return nil, err + } + + var folders []models.SingleFolder + + for _, folder := range apiResponse.Folders { + folders = append(folders, models.SingleFolder{ + Name: folder.Name, + ID: folder.ID, + }) + } + + return folders, nil +} + +func GetFoldersViaServiceToken(fullServiceToken string, workspaceId string, environmentName string, foldersPath string) ([]models.SingleFolder, error) { + serviceTokenParts := strings.SplitN(fullServiceToken, ".", 4) + if len(serviceTokenParts) < 4 { + return nil, fmt.Errorf("invalid service token entered. Please double check your service token and try again") + } + + serviceToken := fmt.Sprintf("%v.%v.%v", serviceTokenParts[0], serviceTokenParts[1], serviceTokenParts[2]) + + httpClient := resty.New() + + httpClient.SetAuthToken(serviceToken). + SetHeader("Accept", "application/json") + + serviceTokenDetails, err := api.CallGetServiceTokenDetailsV2(httpClient) + if err != nil { + return nil, fmt.Errorf("unable to get service token details. [err=%v]", err) + } + + // if multiple scopes are there then user needs to specify which environment and folder path + if environmentName == "" { + if len(serviceTokenDetails.Scopes) != 1 { + return nil, fmt.Errorf("you need to provide the --env for multiple environment scoped token") + } else { + environmentName = serviceTokenDetails.Scopes[0].Environment + } + } + + getFoldersRequest := api.GetFoldersV1Request{ + WorkspaceId: serviceTokenDetails.Workspace, + Environment: environmentName, + FoldersPath: foldersPath, + } + + apiResponse, err := api.CallGetFoldersV1(httpClient, getFoldersRequest) + if err != nil { + return nil, fmt.Errorf("unable to get folders. [err=%v]", err) + } + + var folders []models.SingleFolder + + for _, folder := range apiResponse.Folders { + folders = append(folders, models.SingleFolder{ + Name: folder.Name, + ID: folder.ID, + }) + } + + return folders, nil +} + +// CreateFolder creates a folder in Infisical +func CreateFolder(params models.CreateFolderParameters) (models.SingleFolder, error) { + loggedInUserDetails, err := GetCurrentLoggedInUserDetails() + if err != nil { + return models.SingleFolder{}, err + } + + if loggedInUserDetails.LoginExpired { + PrintErrorMessageAndExit("Your login session has expired, please run [infisical login] and try again") + } + + // set up resty client + httpClient := resty.New() + httpClient. + SetAuthToken(loggedInUserDetails.UserCredentials.JTWToken). + SetHeader("Accept", "application/json"). + SetHeader("Content-Type", "application/json") + + createFolderRequest := api.CreateFolderV1Request{ + WorkspaceId: params.WorkspaceId, + Environment: params.Environment, + FolderName: params.FolderName, + Directory: params.FolderPath, + } + + apiResponse, err := api.CallCreateFolderV1(httpClient, createFolderRequest) + if err != nil { + return models.SingleFolder{}, err + } + + folder := apiResponse.Folder + + return models.SingleFolder{ + Name: folder.Name, + ID: folder.ID, + }, nil +} + +func DeleteFolder(params models.DeleteFolderParameters) ([]models.SingleFolder, error) { + loggedInUserDetails, err := GetCurrentLoggedInUserDetails() + if err != nil { + return nil, err + } + + if loggedInUserDetails.LoginExpired { + PrintErrorMessageAndExit("Your login session has expired, please run [infisical login] and try again") + } + + // set up resty client + httpClient := resty.New() + httpClient. + SetAuthToken(loggedInUserDetails.UserCredentials.JTWToken). + SetHeader("Accept", "application/json"). + SetHeader("Content-Type", "application/json") + + deleteFolderRequest := api.DeleteFolderV1Request{ + WorkspaceId: params.WorkspaceId, + Environment: params.Environment, + FolderName: params.FolderName, + } + + apiResponse, err := api.CallDeleteFolderV1(httpClient, deleteFolderRequest) + if err != nil { + return nil, err + } + + var folders []models.SingleFolder + + for _, folder := range apiResponse.Folders { + folders = append(folders, models.SingleFolder{ + Name: folder.Name, + ID: folder.ID, + }) + } + + return folders, nil +} diff --git a/cli/packages/visualize/folders.go b/cli/packages/visualize/folders.go new file mode 100644 index 000000000..9c23763c1 --- /dev/null +++ b/cli/packages/visualize/folders.go @@ -0,0 +1,14 @@ +package visualize + +import "github.com/Infisical/infisical-merge/packages/models" + +func PrintAllFoldersDetails(folders []models.SingleFolder) { + rows := [][3]string{} + for _, folder := range folders { + rows = append(rows, [...]string{folder.ID, folder.Name, ""}) + } + + headers := [...]string{"FOLDER ID", "FOLDER NAME", "VERSION"} + + Table(headers, rows) +} From 46c76e3984c88b221f08f15d6d69ea04830756ad Mon Sep 17 00:00:00 2001 From: quinton Date: Sat, 25 Nov 2023 10:11:53 +0000 Subject: [PATCH 2/4] chore: refactor --- cli/packages/cmd/folder.go | 55 ++++++++++++++++-------------------- cli/packages/util/folders.go | 8 +----- 2 files changed, 26 insertions(+), 37 deletions(-) diff --git a/cli/packages/cmd/folder.go b/cli/packages/cmd/folder.go index 681fd731c..f38259fbc 100644 --- a/cli/packages/cmd/folder.go +++ b/cli/packages/cmd/folder.go @@ -20,9 +20,12 @@ var folderCmd = &cobra.Command{ } var getCmd = &cobra.Command{ - Use: "get", - Short: "Get folders in a directory", - DisableFlagsInUseLine: true, + Use: "get", + Short: "Get folders in a directory", + PersistentPreRun: func(cmd *cobra.Command, args []string) { + util.RequireLocalWorkspaceFile() + util.RequireLogin() + }, Run: func(cmd *cobra.Command, args []string) { environmentName, _ := cmd.Flags().GetString("env") @@ -54,11 +57,13 @@ var getCmd = &cobra.Command{ } var createCmd = &cobra.Command{ - Use: "create", - Short: "Create a folder", - DisableFlagsInUseLine: true, - Run: func(cmd *cobra.Command, args []string) { + Use: "create", + Short: "Create a folder", + PersistentPreRun: func(cmd *cobra.Command, args []string) { + util.RequireLogin() util.RequireLocalWorkspaceFile() + }, + Run: func(cmd *cobra.Command, args []string) { environmentName, _ := cmd.Flags().GetString("env") if !cmd.Flags().Changed("env") { environmentFromWorkspace := util.GetEnvFromWorkspaceFile() @@ -67,11 +72,6 @@ var createCmd = &cobra.Command{ } } - infisicalToken, err := cmd.Flags().GetString("token") - if err != nil { - util.HandleError(err, "Unable to parse flag") - } - folderPath, err := cmd.Flags().GetString("path") if err != nil { util.HandleError(err, "Unable to parse flag") @@ -92,11 +92,11 @@ var createCmd = &cobra.Command{ } params := models.CreateFolderParameters{ - FolderName: folderName, - WorkspaceId: workspaceFile.WorkspaceId, - Environment: environmentName, - FolderPath: folderPath, - InfisicalToken: infisicalToken} + FolderName: folderName, + WorkspaceId: workspaceFile.WorkspaceId, + Environment: environmentName, + FolderPath: folderPath, + } folder, err := util.CreateFolder(params) if err != nil { @@ -112,8 +112,11 @@ var createCmd = &cobra.Command{ var deleteCmd = &cobra.Command{ Use: "delete", Short: "Delete a folder", - Run: func(cmd *cobra.Command, args []string) { + PersistentPreRun: func(cmd *cobra.Command, args []string) { + util.RequireLogin() util.RequireLocalWorkspaceFile() + }, + Run: func(cmd *cobra.Command, args []string) { environmentName, _ := cmd.Flags().GetString("env") if !cmd.Flags().Changed("env") { @@ -123,11 +126,6 @@ var deleteCmd = &cobra.Command{ } } - infisicalToken, err := cmd.Flags().GetString("token") - if err != nil { - util.HandleError(err, "Unable to parse flag") - } - folderPath, err := cmd.Flags().GetString("path") if err != nil { util.HandleError(err, "Unable to parse flag") @@ -148,11 +146,10 @@ var deleteCmd = &cobra.Command{ } params := models.DeleteFolderParameters{ - FolderName: folderName, - WorkspaceId: workspaceFile.WorkspaceId, - Environment: environmentName, - FolderPath: folderPath, - InfisicalToken: infisicalToken, + FolderName: folderName, + WorkspaceId: workspaceFile.WorkspaceId, + Environment: environmentName, + FolderPath: folderPath, } folders, err := util.DeleteFolder(params) @@ -176,13 +173,11 @@ func init() { // Add createCmd flags here createCmd.Flags().StringP("path", "p", "/", "Path to the directory where the folder will be created") - createCmd.Flags().StringP("token", "t", "", "Create folder using the infisical token") createCmd.Flags().StringP("name", "n", "", "Name of the folder to be created") folderCmd.AddCommand(createCmd) // Add deleteCmd flags here deleteCmd.Flags().StringP("path", "p", "/", "Path to the directory where the folder will be deleted") - deleteCmd.Flags().StringP("token", "t", "", "Delete folder using the infisical token") deleteCmd.Flags().StringP("name", "n", "", "Name of the folder to be deleted") folderCmd.AddCommand(deleteCmd) diff --git a/cli/packages/util/folders.go b/cli/packages/util/folders.go index 67ed66fa2..d11b6d983 100644 --- a/cli/packages/util/folders.go +++ b/cli/packages/util/folders.go @@ -17,17 +17,11 @@ func GetAllFolders(params models.GetAllFoldersParameters) ([]models.SingleFolder params.InfisicalToken = os.Getenv(INFISICAL_TOKEN_NAME) } - isConnected := CheckIsConnectedToInternet() var foldersToReturn []models.SingleFolder var folderErr error if params.InfisicalToken == "" { - if isConnected { - log.Debug().Msg("GetAllFolders: Connected to internet, checking logged in creds") - RequireLocalWorkspaceFile() - RequireLogin() - } - log.Debug().Msg("GetAllEnvironmentVariables: Trying to fetch secrets using logged in details") + log.Debug().Msg("GetAllFolders: Trying to fetch folders using logged in details") loggedInUserDetails, err := GetCurrentLoggedInUserDetails() if err != nil { From ed94d218fdd8fd7bc23104de4ffb91d1486da64a Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Tue, 28 Nov 2023 19:27:30 -0500 Subject: [PATCH 3/4] move folders to secrets --- cli/packages/api/api.go | 22 ++++----------- cli/packages/cmd/folder.go | 45 ++++++++++++++++--------------- cli/packages/cmd/secrets.go | 22 +++++++++++++++ cli/packages/util/folders.go | 1 + cli/packages/visualize/folders.go | 6 ++--- 5 files changed, 54 insertions(+), 42 deletions(-) diff --git a/cli/packages/api/api.go b/cli/packages/api/api.go index d9278d08c..2342f32e7 100644 --- a/cli/packages/api/api.go +++ b/cli/packages/api/api.go @@ -273,11 +273,11 @@ func CallGetFoldersV1(httpClient *resty.Client, request GetFoldersV1Request) (Ge response, err := httpRequest.Get(fmt.Sprintf("%v/v1/folders", config.INFISICAL_URL)) if err != nil { - return GetFoldersV1Response{}, fmt.Errorf("CallGetFoldersV1: Unable to complete api request [err=%s]", err) + return GetFoldersV1Response{}, fmt.Errorf("CallGetFoldersV1: Unable to complete api request [err=%v]", err) } if response.IsError() { - return GetFoldersV1Response{}, fmt.Errorf("CallGetFoldersV1: Unsuccessful response. Please make sure your secret path, workspace and environment name are all correct [response=%s]", response) + return GetFoldersV1Response{}, fmt.Errorf("CallGetFoldersV1: Unsuccessful [response=%s]", response) } return foldersResponse, nil @@ -297,7 +297,7 @@ func CallCreateFolderV1(httpClient *resty.Client, request CreateFolderV1Request) } if response.IsError() { - return CreateFolderV1Response{}, fmt.Errorf("CallCreateFolderV1: Unsuccessful response. Please make sure your secret path, workspace and environment name are all correct [response=%s]", response) + return CreateFolderV1Response{}, fmt.Errorf("CallCreateFolderV1: Unsuccessful [response=%s]", response.String()) } return folderResponse, nil @@ -306,23 +306,11 @@ func CallCreateFolderV1(httpClient *resty.Client, request CreateFolderV1Request) func CallDeleteFolderV1(httpClient *resty.Client, request DeleteFolderV1Request) (DeleteFolderV1Response, error) { var folderResponse DeleteFolderV1Response - type deleteFolderRequest struct { - WorkspaceId string `json:"workspaceId"` - Environment string `json:"environment"` - Directory string `json:"folderPath"` - } - - body := deleteFolderRequest{ - WorkspaceId: request.WorkspaceId, - Environment: request.Environment, - Directory: request.Directory, - } - httpRequest := httpClient. R(). SetResult(&folderResponse). SetHeader("User-Agent", USER_AGENT). - SetBody(body) + SetBody(request) response, err := httpRequest.Delete(fmt.Sprintf("%v/v1/folders/%v", config.INFISICAL_URL, request.FolderName)) if err != nil { @@ -330,7 +318,7 @@ func CallDeleteFolderV1(httpClient *resty.Client, request DeleteFolderV1Request) } if response.IsError() { - return DeleteFolderV1Response{}, fmt.Errorf("CallDeleteFolderV1: Unsuccessful response. Please make sure your secret path, workspace and environment name are all correct [response=%s]", response) + return DeleteFolderV1Response{}, fmt.Errorf("CallDeleteFolderV1: Unsuccessful [response=%s]", response.String()) } return folderResponse, nil diff --git a/cli/packages/cmd/folder.go b/cli/packages/cmd/folder.go index f38259fbc..b59be0266 100644 --- a/cli/packages/cmd/folder.go +++ b/cli/packages/cmd/folder.go @@ -51,7 +51,7 @@ var getCmd = &cobra.Command{ util.HandleError(err, "Unable to get folders") } - visualize.PrintAllFoldersDetails(folders) + visualize.PrintAllFoldersDetails(folders, foldersPath) Telemetry.CaptureEvent("cli-command:folders get", posthog.NewProperties().Set("folderCount", len(folders)).Set("version", util.CLI_VERSION)) }, } @@ -98,13 +98,13 @@ var createCmd = &cobra.Command{ FolderPath: folderPath, } - folder, err := util.CreateFolder(params) + _, err = util.CreateFolder(params) if err != nil { util.HandleError(err, "Unable to create folder") } - folders := []models.SingleFolder{folder} - visualize.PrintAllFoldersDetails(folders) + util.PrintSuccessMessage(fmt.Sprintf("folder named `%s` created in path %s", folderName, folderPath)) + Telemetry.CaptureEvent("cli-command:folders create", posthog.NewProperties().Set("version", util.CLI_VERSION)) }, } @@ -152,35 +152,36 @@ var deleteCmd = &cobra.Command{ FolderPath: folderPath, } - folders, err := util.DeleteFolder(params) + _, err = util.DeleteFolder(params) if err != nil { util.HandleError(err, "Unable to delete folder") } - visualize.PrintAllFoldersDetails(folders) + util.PrintSuccessMessage(fmt.Sprintf("folder named `%s` deleted in path %s", folderName, folderPath)) + Telemetry.CaptureEvent("cli-command:folders delete", posthog.NewProperties().Set("version", util.CLI_VERSION)) }, } -func init() { +// func init() { - folderCmd.PersistentFlags().String("env", "dev", "Used to select the environment name on which actions should be taken on") +// folderCmd.PersistentFlags().String("env", "dev", "Used to select the environment name on which actions should be taken on") - // Add getCmd, createCmd and deleteCmd flags here - getCmd.Flags().StringP("path", "p", "/", "Path to the directory whose folders will be fetched") - getCmd.Flags().StringP("token", "t", "", "Fetch folders using the infisical token") - folderCmd.AddCommand(getCmd) +// // Add getCmd, createCmd and deleteCmd flags here +// getCmd.Flags().StringP("path", "p", "/", "The path from where folders should be fetched from") +// getCmd.Flags().StringP("token", "t", "", "Fetch folders using the infisical token") +// folderCmd.AddCommand(getCmd) - // Add createCmd flags here - createCmd.Flags().StringP("path", "p", "/", "Path to the directory where the folder will be created") - createCmd.Flags().StringP("name", "n", "", "Name of the folder to be created") - folderCmd.AddCommand(createCmd) +// // Add createCmd flags here +// createCmd.Flags().StringP("path", "p", "/", "Path to where the folder should be created") +// createCmd.Flags().StringP("name", "n", "", "Name of the folder to be created") +// folderCmd.AddCommand(createCmd) - // Add deleteCmd flags here - deleteCmd.Flags().StringP("path", "p", "/", "Path to the directory where the folder will be deleted") - deleteCmd.Flags().StringP("name", "n", "", "Name of the folder to be deleted") - folderCmd.AddCommand(deleteCmd) +// // Add deleteCmd flags here +// deleteCmd.Flags().StringP("path", "p", "/", "Path to the folder to be deleted") +// deleteCmd.Flags().StringP("name", "n", "", "Name of the folder to be deleted") +// folderCmd.AddCommand(deleteCmd) - rootCmd.AddCommand(folderCmd) +// rootCmd.AddCommand(folderCmd) -} +// } diff --git a/cli/packages/cmd/secrets.go b/cli/packages/cmd/secrets.go index 5c4d314f5..186776837 100644 --- a/cli/packages/cmd/secrets.go +++ b/cli/packages/cmd/secrets.go @@ -679,6 +679,28 @@ func init() { util.RequireLocalWorkspaceFile() } + // *** Folders sub command *** + folderCmd.PersistentFlags().String("env", "dev", "Used to select the environment name on which actions should be taken on") + + // Add getCmd, createCmd and deleteCmd flags here + getCmd.Flags().StringP("path", "p", "/", "The path from where folders should be fetched from") + getCmd.Flags().String("token", "", "Fetch folders using the infisical token") + folderCmd.AddCommand(getCmd) + + // Add createCmd flags here + createCmd.Flags().StringP("path", "p", "/", "Path to where the folder should be created") + createCmd.Flags().StringP("name", "n", "", "Name of the folder to be created") + folderCmd.AddCommand(createCmd) + + // Add deleteCmd flags here + deleteCmd.Flags().StringP("path", "p", "/", "Path to the folder to be deleted") + deleteCmd.Flags().StringP("name", "n", "", "Name of the folder to be deleted") + folderCmd.AddCommand(deleteCmd) + + secretsCmd.AddCommand(folderCmd) + + // ** End of folders sub command + secretsCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") secretsCmd.PersistentFlags().String("env", "dev", "Used to select the environment name on which actions should be taken on") secretsCmd.Flags().Bool("expand", true, "Parse shell parameter expansions in your secrets") diff --git a/cli/packages/util/folders.go b/cli/packages/util/folders.go index d11b6d983..7275653d9 100644 --- a/cli/packages/util/folders.go +++ b/cli/packages/util/folders.go @@ -191,6 +191,7 @@ func DeleteFolder(params models.DeleteFolderParameters) ([]models.SingleFolder, WorkspaceId: params.WorkspaceId, Environment: params.Environment, FolderName: params.FolderName, + Directory: params.FolderPath, } apiResponse, err := api.CallDeleteFolderV1(httpClient, deleteFolderRequest) diff --git a/cli/packages/visualize/folders.go b/cli/packages/visualize/folders.go index 9c23763c1..74f053c4f 100644 --- a/cli/packages/visualize/folders.go +++ b/cli/packages/visualize/folders.go @@ -2,13 +2,13 @@ package visualize import "github.com/Infisical/infisical-merge/packages/models" -func PrintAllFoldersDetails(folders []models.SingleFolder) { +func PrintAllFoldersDetails(folders []models.SingleFolder, path string) { rows := [][3]string{} for _, folder := range folders { - rows = append(rows, [...]string{folder.ID, folder.Name, ""}) + rows = append(rows, [...]string{folder.Name, path, folder.ID}) } - headers := [...]string{"FOLDER ID", "FOLDER NAME", "VERSION"} + headers := [...]string{"FOLDER NAME", "PATH", "FOLDER ID"} Table(headers, rows) } From d01c6e4df9c1d3a2404b9de948248f387cedd4e7 Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Tue, 28 Nov 2023 19:30:08 -0500 Subject: [PATCH 4/4] remove init from folders cmd --- cli/packages/cmd/folder.go | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/cli/packages/cmd/folder.go b/cli/packages/cmd/folder.go index b59be0266..12e2206fa 100644 --- a/cli/packages/cmd/folder.go +++ b/cli/packages/cmd/folder.go @@ -162,26 +162,3 @@ var deleteCmd = &cobra.Command{ Telemetry.CaptureEvent("cli-command:folders delete", posthog.NewProperties().Set("version", util.CLI_VERSION)) }, } - -// func init() { - -// folderCmd.PersistentFlags().String("env", "dev", "Used to select the environment name on which actions should be taken on") - -// // Add getCmd, createCmd and deleteCmd flags here -// getCmd.Flags().StringP("path", "p", "/", "The path from where folders should be fetched from") -// getCmd.Flags().StringP("token", "t", "", "Fetch folders using the infisical token") -// folderCmd.AddCommand(getCmd) - -// // Add createCmd flags here -// createCmd.Flags().StringP("path", "p", "/", "Path to where the folder should be created") -// createCmd.Flags().StringP("name", "n", "", "Name of the folder to be created") -// folderCmd.AddCommand(createCmd) - -// // Add deleteCmd flags here -// deleteCmd.Flags().StringP("path", "p", "/", "Path to the folder to be deleted") -// deleteCmd.Flags().StringP("name", "n", "", "Name of the folder to be deleted") -// folderCmd.AddCommand(deleteCmd) - -// rootCmd.AddCommand(folderCmd) - -// }