Skip to content

Commit f48b9f9

Browse files
committed
Add board access, webhook delivery, and user export commands
1 parent 39a29d3 commit f48b9f9

9 files changed

Lines changed: 467 additions & 2 deletions

File tree

SURFACE.txt

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ CMD fizzy auth ls
4747
CMD fizzy auth status
4848
CMD fizzy auth switch
4949
CMD fizzy board
50+
CMD fizzy board accesses
5051
CMD fizzy board closed
5152
CMD fizzy board create
5253
CMD fizzy board delete
@@ -194,6 +195,8 @@ CMD fizzy upload help
194195
CMD fizzy user
195196
CMD fizzy user avatar-remove
196197
CMD fizzy user deactivate
198+
CMD fizzy user export-create
199+
CMD fizzy user export-show
197200
CMD fizzy user help
198201
CMD fizzy user list
199202
CMD fizzy user ls
@@ -207,6 +210,7 @@ CMD fizzy version
207210
CMD fizzy webhook
208211
CMD fizzy webhook create
209212
CMD fizzy webhook delete
213+
CMD fizzy webhook deliveries
210214
CMD fizzy webhook help
211215
CMD fizzy webhook list
212216
CMD fizzy webhook ls
@@ -514,6 +518,22 @@ FLAG fizzy board --quiet type=bool
514518
FLAG fizzy board --styled type=bool
515519
FLAG fizzy board --token type=string
516520
FLAG fizzy board --verbose type=bool
521+
FLAG fizzy board accesses --agent type=bool
522+
FLAG fizzy board accesses --api-url type=string
523+
FLAG fizzy board accesses --board type=string
524+
FLAG fizzy board accesses --count type=bool
525+
FLAG fizzy board accesses --help type=bool
526+
FLAG fizzy board accesses --ids-only type=bool
527+
FLAG fizzy board accesses --jq type=string
528+
FLAG fizzy board accesses --json type=bool
529+
FLAG fizzy board accesses --limit type=int
530+
FLAG fizzy board accesses --markdown type=bool
531+
FLAG fizzy board accesses --page type=int
532+
FLAG fizzy board accesses --profile type=string
533+
FLAG fizzy board accesses --quiet type=bool
534+
FLAG fizzy board accesses --styled type=bool
535+
FLAG fizzy board accesses --token type=string
536+
FLAG fizzy board accesses --verbose type=bool
517537
FLAG fizzy board closed --agent type=bool
518538
FLAG fizzy board closed --all type=bool
519539
FLAG fizzy board closed --api-url type=string
@@ -2730,6 +2750,34 @@ FLAG fizzy user deactivate --quiet type=bool
27302750
FLAG fizzy user deactivate --styled type=bool
27312751
FLAG fizzy user deactivate --token type=string
27322752
FLAG fizzy user deactivate --verbose type=bool
2753+
FLAG fizzy user export-create --agent type=bool
2754+
FLAG fizzy user export-create --api-url type=string
2755+
FLAG fizzy user export-create --count type=bool
2756+
FLAG fizzy user export-create --help type=bool
2757+
FLAG fizzy user export-create --ids-only type=bool
2758+
FLAG fizzy user export-create --jq type=string
2759+
FLAG fizzy user export-create --json type=bool
2760+
FLAG fizzy user export-create --limit type=int
2761+
FLAG fizzy user export-create --markdown type=bool
2762+
FLAG fizzy user export-create --profile type=string
2763+
FLAG fizzy user export-create --quiet type=bool
2764+
FLAG fizzy user export-create --styled type=bool
2765+
FLAG fizzy user export-create --token type=string
2766+
FLAG fizzy user export-create --verbose type=bool
2767+
FLAG fizzy user export-show --agent type=bool
2768+
FLAG fizzy user export-show --api-url type=string
2769+
FLAG fizzy user export-show --count type=bool
2770+
FLAG fizzy user export-show --help type=bool
2771+
FLAG fizzy user export-show --ids-only type=bool
2772+
FLAG fizzy user export-show --jq type=string
2773+
FLAG fizzy user export-show --json type=bool
2774+
FLAG fizzy user export-show --limit type=int
2775+
FLAG fizzy user export-show --markdown type=bool
2776+
FLAG fizzy user export-show --profile type=string
2777+
FLAG fizzy user export-show --quiet type=bool
2778+
FLAG fizzy user export-show --styled type=bool
2779+
FLAG fizzy user export-show --token type=string
2780+
FLAG fizzy user export-show --verbose type=bool
27332781
FLAG fizzy user help --agent type=bool
27342782
FLAG fizzy user help --api-url type=string
27352783
FLAG fizzy user help --count type=bool
@@ -2929,6 +2977,23 @@ FLAG fizzy webhook delete --quiet type=bool
29292977
FLAG fizzy webhook delete --styled type=bool
29302978
FLAG fizzy webhook delete --token type=string
29312979
FLAG fizzy webhook delete --verbose type=bool
2980+
FLAG fizzy webhook deliveries --agent type=bool
2981+
FLAG fizzy webhook deliveries --all type=bool
2982+
FLAG fizzy webhook deliveries --api-url type=string
2983+
FLAG fizzy webhook deliveries --board type=string
2984+
FLAG fizzy webhook deliveries --count type=bool
2985+
FLAG fizzy webhook deliveries --help type=bool
2986+
FLAG fizzy webhook deliveries --ids-only type=bool
2987+
FLAG fizzy webhook deliveries --jq type=string
2988+
FLAG fizzy webhook deliveries --json type=bool
2989+
FLAG fizzy webhook deliveries --limit type=int
2990+
FLAG fizzy webhook deliveries --markdown type=bool
2991+
FLAG fizzy webhook deliveries --page type=int
2992+
FLAG fizzy webhook deliveries --profile type=string
2993+
FLAG fizzy webhook deliveries --quiet type=bool
2994+
FLAG fizzy webhook deliveries --styled type=bool
2995+
FLAG fizzy webhook deliveries --token type=string
2996+
FLAG fizzy webhook deliveries --verbose type=bool
29322997
FLAG fizzy webhook help --agent type=bool
29332998
FLAG fizzy webhook help --api-url type=string
29342999
FLAG fizzy webhook help --count type=bool
@@ -3074,6 +3139,7 @@ SUB fizzy auth ls
30743139
SUB fizzy auth status
30753140
SUB fizzy auth switch
30763141
SUB fizzy board
3142+
SUB fizzy board accesses
30773143
SUB fizzy board closed
30783144
SUB fizzy board create
30793145
SUB fizzy board delete
@@ -3221,6 +3287,8 @@ SUB fizzy upload help
32213287
SUB fizzy user
32223288
SUB fizzy user avatar-remove
32233289
SUB fizzy user deactivate
3290+
SUB fizzy user export-create
3291+
SUB fizzy user export-show
32243292
SUB fizzy user help
32253293
SUB fizzy user list
32263294
SUB fizzy user ls
@@ -3234,6 +3302,7 @@ SUB fizzy version
32343302
SUB fizzy webhook
32353303
SUB fizzy webhook create
32363304
SUB fizzy webhook delete
3305+
SUB fizzy webhook deliveries
32373306
SUB fizzy webhook help
32383307
SUB fizzy webhook list
32393308
SUB fizzy webhook ls

internal/commands/board.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,50 @@ var boardEntropyCmd = &cobra.Command{
415415
},
416416
}
417417

418+
// Board accesses flags
419+
var boardAccessesBoard string
420+
var boardAccessesPage int
421+
422+
var boardAccessesCmd = &cobra.Command{
423+
Use: "accesses",
424+
Short: "Show board accesses",
425+
Long: "Shows access settings and users for a board.",
426+
RunE: func(cmd *cobra.Command, args []string) error {
427+
if err := requireAuthAndAccount(); err != nil {
428+
return err
429+
}
430+
431+
boardID, err := requireBoard(boardAccessesBoard)
432+
if err != nil {
433+
return err
434+
}
435+
436+
var page *int64
437+
if boardAccessesPage > 0 {
438+
pageVal := int64(boardAccessesPage)
439+
page = &pageVal
440+
}
441+
442+
data, _, err := getSDK().Boards().ListBoardAccesses(cmd.Context(), boardID, page)
443+
if err != nil {
444+
return convertSDKError(err)
445+
}
446+
447+
summary := "Board accesses"
448+
if boardAccessesPage > 0 {
449+
summary = fmt.Sprintf("Board accesses (page %d)", boardAccessesPage)
450+
}
451+
452+
breadcrumbs := []Breadcrumb{
453+
breadcrumb("board", fmt.Sprintf("fizzy board show %s", boardID), "View board"),
454+
breadcrumb("cards", fmt.Sprintf("fizzy card list --board %s", boardID), "List cards"),
455+
}
456+
457+
printDetail(normalizeAny(data), summary, breadcrumbs)
458+
return nil
459+
},
460+
}
461+
418462
// Board closed flags
419463
var boardClosedBoard string
420464
var boardClosedPage int
@@ -705,6 +749,11 @@ func init() {
705749
boardEntropyCmd.Flags().IntVar(&boardEntropyAutoPostponePeriodInDays, "auto_postpone_period_in_days", 0, "Auto postpone period in days ("+validAutoPostponePeriodsHelp+")")
706750
boardCmd.AddCommand(boardEntropyCmd)
707751

752+
// Accesses
753+
boardAccessesCmd.Flags().StringVar(&boardAccessesBoard, "board", "", "Board ID (required)")
754+
boardAccessesCmd.Flags().IntVar(&boardAccessesPage, "page", 0, "Page number")
755+
boardCmd.AddCommand(boardAccessesCmd)
756+
708757
// Closed cards
709758
boardClosedCmd.Flags().StringVar(&boardClosedBoard, "board", "", "Board ID (required)")
710759
boardClosedCmd.Flags().IntVar(&boardClosedPage, "page", 0, "Page number")

internal/commands/board_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,69 @@ func TestBoardEntropy(t *testing.T) {
664664
})
665665
}
666666

667+
func TestBoardAccesses(t *testing.T) {
668+
t.Run("shows board accesses", func(t *testing.T) {
669+
mock := NewMockClient()
670+
mock.GetResponse = &client.APIResponse{
671+
StatusCode: 200,
672+
Data: map[string]any{
673+
"board_id": "123",
674+
"all_access": true,
675+
"users": []any{
676+
map[string]any{"id": "user-1", "name": "User 1", "has_access": true},
677+
},
678+
},
679+
}
680+
681+
SetTestModeWithSDK(mock)
682+
SetTestConfig("token", "account", "https://api.example.com")
683+
defer resetTest()
684+
685+
boardAccessesBoard = "123"
686+
err := boardAccessesCmd.RunE(boardAccessesCmd, []string{})
687+
boardAccessesBoard = ""
688+
boardAccessesPage = 0
689+
690+
assertExitCode(t, err, 0)
691+
if mock.GetCalls[0].Path != "/boards/123/accesses.json" {
692+
t.Errorf("expected path '/boards/123/accesses.json', got '%s'", mock.GetCalls[0].Path)
693+
}
694+
})
695+
696+
t.Run("passes page", func(t *testing.T) {
697+
mock := NewMockClient()
698+
mock.GetResponse = &client.APIResponse{
699+
StatusCode: 200,
700+
Data: map[string]any{"board_id": "123", "all_access": false, "users": []any{}},
701+
}
702+
703+
SetTestModeWithSDK(mock)
704+
SetTestConfig("token", "account", "https://api.example.com")
705+
defer resetTest()
706+
707+
boardAccessesBoard = "123"
708+
boardAccessesPage = 2
709+
err := boardAccessesCmd.RunE(boardAccessesCmd, []string{})
710+
boardAccessesBoard = ""
711+
boardAccessesPage = 0
712+
713+
assertExitCode(t, err, 0)
714+
if mock.GetCalls[0].Path != "/boards/123/accesses.json?page=2" {
715+
t.Errorf("expected path '/boards/123/accesses.json?page=2', got '%s'", mock.GetCalls[0].Path)
716+
}
717+
})
718+
719+
t.Run("requires board", func(t *testing.T) {
720+
mock := NewMockClient()
721+
SetTestModeWithSDK(mock)
722+
SetTestConfig("token", "account", "https://api.example.com")
723+
defer resetTest()
724+
725+
err := boardAccessesCmd.RunE(boardAccessesCmd, []string{})
726+
assertExitCode(t, err, errors.ExitInvalidArgs)
727+
})
728+
}
729+
667730
func TestBoardClosed(t *testing.T) {
668731
t.Run("lists closed cards", func(t *testing.T) {
669732
mock := NewMockClient()

internal/commands/columns.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,11 @@ var (
7777
{Header: "URL", Field: "payload_url"},
7878
{Header: "Active", Field: "active"},
7979
}
80+
81+
webhookDeliveryColumns = render.Columns{
82+
{Header: "ID", Field: "id"},
83+
{Header: "State", Field: "state"},
84+
{Header: "Created", Field: "created_at"},
85+
{Header: "Updated", Field: "updated_at"},
86+
}
8087
)

internal/commands/user.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,72 @@ var userAvatarRemoveCmd = &cobra.Command{
272272
},
273273
}
274274

275+
var userExportCreateCmd = &cobra.Command{
276+
Use: "export-create USER_ID",
277+
Short: "Create a user export",
278+
Long: "Creates a new user data export.",
279+
Args: cobra.ExactArgs(1),
280+
RunE: func(cmd *cobra.Command, args []string) error {
281+
if err := requireAuthAndAccount(); err != nil {
282+
return err
283+
}
284+
285+
userID := args[0]
286+
287+
data, _, err := getSDK().Users().CreateUserDataExport(cmd.Context(), userID)
288+
if err != nil {
289+
return convertSDKError(err)
290+
}
291+
292+
items := normalizeAny(data)
293+
exportID := ""
294+
if export, ok := items.(map[string]any); ok {
295+
if id, ok := export["id"]; ok {
296+
exportID = fmt.Sprintf("%v", id)
297+
}
298+
}
299+
300+
var breadcrumbs []Breadcrumb
301+
if exportID != "" {
302+
breadcrumbs = []Breadcrumb{
303+
breadcrumb("show", fmt.Sprintf("fizzy user export-show %s %s", userID, exportID), "View export status"),
304+
breadcrumb("user", fmt.Sprintf("fizzy user show %s", userID), "View user"),
305+
}
306+
}
307+
308+
printMutation(items, "", breadcrumbs)
309+
return nil
310+
},
311+
}
312+
313+
var userExportShowCmd = &cobra.Command{
314+
Use: "export-show USER_ID EXPORT_ID",
315+
Short: "Show a user export",
316+
Long: "Shows the status of a user data export.",
317+
Args: cobra.ExactArgs(2),
318+
RunE: func(cmd *cobra.Command, args []string) error {
319+
if err := requireAuthAndAccount(); err != nil {
320+
return err
321+
}
322+
323+
userID := args[0]
324+
exportID := args[1]
325+
326+
data, _, err := getSDK().Users().GetUserDataExport(cmd.Context(), userID, exportID)
327+
if err != nil {
328+
return convertSDKError(err)
329+
}
330+
331+
breadcrumbs := []Breadcrumb{
332+
breadcrumb("user", fmt.Sprintf("fizzy user show %s", userID), "View user"),
333+
breadcrumb("export-create", fmt.Sprintf("fizzy user export-create %s", userID), "Create another export"),
334+
}
335+
336+
printDetail(normalizeAny(data), "", breadcrumbs)
337+
return nil
338+
},
339+
}
340+
275341
// Push subscription create flags
276342
var pushSubCreateUser string
277343
var pushSubCreateEndpoint string
@@ -377,6 +443,10 @@ func init() {
377443
// Avatar remove
378444
userCmd.AddCommand(userAvatarRemoveCmd)
379445

446+
// Exports
447+
userCmd.AddCommand(userExportCreateCmd)
448+
userCmd.AddCommand(userExportShowCmd)
449+
380450
// Push subscriptions
381451
userPushSubscriptionCreateCmd.Flags().StringVar(&pushSubCreateUser, "user", "", "User ID (required)")
382452
userPushSubscriptionCreateCmd.Flags().StringVar(&pushSubCreateEndpoint, "endpoint", "", "Push endpoint URL (required)")

0 commit comments

Comments
 (0)