diff --git a/api/result.go b/api/result.go index d96d27f..4c70aa2 100644 --- a/api/result.go +++ b/api/result.go @@ -2,6 +2,7 @@ package api import ( "context" + "encoding/json" "errors" "fmt" "net/http" @@ -45,3 +46,33 @@ func (c *Client) WaitAndGetResult(ctx context.Context, uuid string, maxWait int) } } } + +type ResultVisibilityOptions struct { + Visibility string `json:"visibility"` +} + +type ResultVisibilityOption func(*ResultVisibilityOptions) + +func WithResultVisibility(visibility string) ResultVisibilityOption { + return func(opts *ResultVisibilityOptions) { + if visibility != "" { + opts.Visibility = visibility + } + } +} + +func (c *Client) UpdateResultVisibility(uuid string, opts ...ResultVisibilityOption) (*Response, error) { + var options ResultVisibilityOptions + for _, opt := range opts { + opt(&options) + } + + marshalled, err := json.Marshal(options) + if err != nil { + return nil, err + } + + return c.NewRequest().SetBodyJSONBytes(marshalled).Put( + PrefixedPath(fmt.Sprintf("/result/%s/visibility/", uuid)), + ) +} diff --git a/cmd/pro/root.go b/cmd/pro/root.go index 9ad81f4..62b5baf 100644 --- a/cmd/pro/root.go +++ b/cmd/pro/root.go @@ -9,6 +9,7 @@ import ( "github.com/urlscan/urlscan-cli/cmd/pro/livescan" "github.com/urlscan/urlscan-cli/cmd/pro/search" "github.com/urlscan/urlscan-cli/cmd/pro/subscription" + "github.com/urlscan/urlscan-cli/cmd/pro/visibility" ) var RootCmd = &cobra.Command{ @@ -24,4 +25,5 @@ func init() { RootCmd.AddCommand(incident.RootCmd) RootCmd.AddCommand(livescan.RootCmd) RootCmd.AddCommand(datadump.RootCmd) + RootCmd.AddCommand(visibility.RootCmd) } diff --git a/cmd/pro/visibility/reset.go b/cmd/pro/visibility/reset.go new file mode 100644 index 0000000..2dd7c10 --- /dev/null +++ b/cmd/pro/visibility/reset.go @@ -0,0 +1,56 @@ +package visibility + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/urlscan/urlscan-cli/api" + "github.com/urlscan/urlscan-cli/pkg/utils" +) + +var resetCmdExample = ` urlscan pro visibility reset + echo | urlscan pro visibility reset -` + +var resetCmd = &cobra.Command{ + Use: "reset", + Short: "Reset the visibility of a scan owned by you or your team to its original visibility", + Example: resetCmdExample, + Annotations: map[string]string{ + "args": "exact1", + }, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) != 1 { + return cmd.Usage() + } + + reader := utils.StringReaderFromCmdArgs(args) + scanId, err := reader.ReadString() + if err != nil { + return err + } + + err = utils.ValidateUUID(scanId) + if err != nil { + return err + } + + client, err := utils.NewAPIClient() + if err != nil { + return err + } + + resp, err := client.NewRequest().Delete(api.PrefixedPath(fmt.Sprintf("/result/%s/visibility/", scanId))) + if err != nil { + return err + } + + fmt.Print(resp.PrettyJSON()) + + return nil + }, +} + +func init() { + RootCmd.AddCommand(resetCmd) +} diff --git a/cmd/pro/visibility/root.go b/cmd/pro/visibility/root.go new file mode 100644 index 0000000..c71112e --- /dev/null +++ b/cmd/pro/visibility/root.go @@ -0,0 +1,10 @@ +package visibility + +import ( + "github.com/spf13/cobra" +) + +var RootCmd = &cobra.Command{ + Use: "visibility", + Short: "Visibility sub-commands", +} diff --git a/cmd/pro/visibility/update.go b/cmd/pro/visibility/update.go new file mode 100644 index 0000000..9761554 --- /dev/null +++ b/cmd/pro/visibility/update.go @@ -0,0 +1,63 @@ +package visibility + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/urlscan/urlscan-cli/api" + "github.com/urlscan/urlscan-cli/pkg/utils" +) + +var updateCmdExample = ` urlscan pro visibility update -v private + echo | urlscan pro visibility update - -v public` + +var updateCmd = &cobra.Command{ + Use: "update", + Short: "Update visibility of a scan owned by you or your team", + Example: updateCmdExample, + Annotations: map[string]string{ + "args": "exact1", + }, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) != 1 { + return cmd.Usage() + } + + reader := utils.StringReaderFromCmdArgs(args) + scanId, err := reader.ReadString() + if err != nil { + return err + } + + err = utils.ValidateUUID(scanId) + if err != nil { + return err + } + + visibility, _ := cmd.Flags().GetString("visibility") + if visibility == "" { + return cmd.Usage() + } + + client, err := utils.NewAPIClient() + if err != nil { + return err + } + + resp, err := client.UpdateResultVisibility(scanId, api.WithResultVisibility(visibility)) + if err != nil { + return err + } + + fmt.Print(resp.PrettyJSON()) + + return nil + }, +} + +func init() { + updateCmd.Flags().StringP("visibility", "v", "", "The new visibility of the scan result: public, unlisted, private, deleted") + + RootCmd.AddCommand(updateCmd) +} diff --git a/docs/urlscan_pro.md b/docs/urlscan_pro.md index cc6f313..24c9fdb 100644 --- a/docs/urlscan_pro.md +++ b/docs/urlscan_pro.md @@ -21,4 +21,5 @@ Pro sub-commands * [urlscan pro saved-search](urlscan_pro_saved-search.md) - Saved search sub-commands * [urlscan pro structure-search](urlscan_pro_structure-search.md) - Get structurally similar results to a specific scan * [urlscan pro subscription](urlscan_pro_subscription.md) - Subscription sub-commands +* [urlscan pro visibility](urlscan_pro_visibility.md) - Visibility sub-commands diff --git a/docs/urlscan_pro_visibility.md b/docs/urlscan_pro_visibility.md new file mode 100644 index 0000000..ab52a54 --- /dev/null +++ b/docs/urlscan_pro_visibility.md @@ -0,0 +1,16 @@ +## urlscan pro visibility + +Visibility sub-commands + +### Options + +``` + -h, --help help for visibility +``` + +### SEE ALSO + +* [urlscan pro](urlscan_pro.md) - Pro sub-commands +* [urlscan pro visibility reset](urlscan_pro_visibility_reset.md) - Reset the visibility of a scan owned by you or your team to its original visibility +* [urlscan pro visibility update](urlscan_pro_visibility_update.md) - Update visibility of a scan owned by you or your team + diff --git a/docs/urlscan_pro_visibility_reset.md b/docs/urlscan_pro_visibility_reset.md new file mode 100644 index 0000000..5ca8476 --- /dev/null +++ b/docs/urlscan_pro_visibility_reset.md @@ -0,0 +1,25 @@ +## urlscan pro visibility reset + +Reset the visibility of a scan owned by you or your team to its original visibility + +``` +urlscan pro visibility reset [flags] +``` + +### Examples + +``` + urlscan pro visibility reset + echo | urlscan pro visibility reset - +``` + +### Options + +``` + -h, --help help for reset +``` + +### SEE ALSO + +* [urlscan pro visibility](urlscan_pro_visibility.md) - Visibility sub-commands + diff --git a/docs/urlscan_pro_visibility_update.md b/docs/urlscan_pro_visibility_update.md new file mode 100644 index 0000000..0554eb5 --- /dev/null +++ b/docs/urlscan_pro_visibility_update.md @@ -0,0 +1,26 @@ +## urlscan pro visibility update + +Update visibility of a scan owned by you or your team + +``` +urlscan pro visibility update [flags] +``` + +### Examples + +``` + urlscan pro visibility update -v private + echo | urlscan pro visibility update - -v public +``` + +### Options + +``` + -h, --help help for update + -v, --visibility string The new visibility of the scan result: public, unlisted, private, deleted +``` + +### SEE ALSO + +* [urlscan pro visibility](urlscan_pro_visibility.md) - Visibility sub-commands + diff --git a/test/pro/visibility.bats b/test/pro/visibility.bats new file mode 100644 index 0000000..4543625 --- /dev/null +++ b/test/pro/visibility.bats @@ -0,0 +1,15 @@ +#!/usr/bin/env bats + +load ../test_helper + +@test "scan, change and reset visibility" { + scan_id="$(./dist/urlscan scan submit "https://http-test.com/" -v private --wait | jq -r ".task.uuid")" + + message="$(./dist/urlscan pro visibility update "$scan_id" -v unlisted | jq -r ".message")" + assert_equal "Visibility updated" "$message" + + + message="$(./dist/urlscan pro visibility reset "$scan_id" | jq -r ".message")" + assert_equal "Visibility reset" "$message" +} +