@@ -106,6 +106,7 @@ func RegisterPermissionCmd(rootCmd *cobra.Command) *cobra.Command {
106106 lookupSubjectsCmd .Flags ().Bool ("json" , false , "output as JSON" )
107107 lookupSubjectsCmd .Flags ().String ("revision" , "" , "optional revision at which to check" )
108108 lookupSubjectsCmd .Flags ().String ("caveat-context" , "" , "the caveat context to send along with the lookup, in JSON form" )
109+ lookupSubjectsCmd .Flags ().Uint32 ("page-limit" , 100 , "limit of subject returned per page" )
109110 registerConsistencyFlags (lookupSubjectsCmd .Flags ())
110111
111112 return permissionCmd
@@ -188,7 +189,7 @@ func checkCmdFunc(cmd *cobra.Command, args []string) error {
188189 return err
189190 }
190191
191- client , err := client .NewClient (cmd )
192+ c , err := client .NewClient (cmd )
192193 if err != nil {
193194 return err
194195 }
@@ -218,7 +219,7 @@ func checkCmdFunc(cmd *cobra.Command, args []string) error {
218219 }
219220
220221 var trailerMD metadata.MD
221- resp , err := client .CheckPermission (ctx , request , grpc .Trailer (& trailerMD ))
222+ resp , err := c .CheckPermission (ctx , request , grpc .Trailer (& trailerMD ))
222223 if err != nil {
223224 var debugInfo * v1.DebugInformation
224225 if resp != nil {
@@ -370,7 +371,7 @@ func expandCmdFunc(cmd *cobra.Command, args []string) error {
370371 return err
371372 }
372373
373- client , err := client .NewClient (cmd )
374+ c , err := client .NewClient (cmd )
374375 if err != nil {
375376 return err
376377 }
@@ -385,7 +386,7 @@ func expandCmdFunc(cmd *cobra.Command, args []string) error {
385386 }
386387 log .Trace ().Interface ("request" , request ).Send ()
387388
388- resp , err := client .ExpandPermissionTree (cmd .Context (), request )
389+ resp , err := c .ExpandPermissionTree (cmd .Context (), request )
389390 if err != nil {
390391 return err
391392 }
@@ -425,7 +426,7 @@ func lookupResourcesCmdFunc(cmd *cobra.Command, args []string) error {
425426 return err
426427 }
427428
428- client , err := client .NewClient (cmd )
429+ c , err := client .NewClient (cmd )
429430 if err != nil {
430431 return err
431432 }
@@ -444,7 +445,7 @@ func lookupResourcesCmdFunc(cmd *cobra.Command, args []string) error {
444445 }
445446 log .Trace ().Interface ("request" , request ).Send ()
446447
447- respStream , err := client .LookupResources (cmd .Context (), request )
448+ respStream , err := c .LookupResources (cmd .Context (), request )
448449 if err != nil {
449450 return err
450451 }
@@ -492,7 +493,7 @@ func lookupSubjectsCmdFunc(cmd *cobra.Command, args []string) error {
492493 return err
493494 }
494495
495- client , err := client .NewClient (cmd )
496+ c , err := client .NewClient (cmd )
496497 if err != nil {
497498 return err
498499 }
@@ -507,21 +508,37 @@ func lookupSubjectsCmdFunc(cmd *cobra.Command, args []string) error {
507508 Context : caveatContext ,
508509 Consistency : consistency ,
509510 }
510- log .Trace ().Interface ("request" , request ).Send ()
511-
512- respStream , err := client .LookupSubjects (cmd .Context (), request )
513- if err != nil {
514- return err
515- }
516511
512+ limit := cobrautil .MustGetUint32 (cmd , "page-limit" )
513+ request .OptionalConcreteLimit = limit
514+ log .Trace ().Interface ("request" , request ).Send ()
515+ lastCursor := request .OptionalCursor
517516 for {
518- resp , err := respStream .Recv ()
519- switch {
520- case errors .Is (err , io .EOF ):
521- return nil
522- case err != nil :
517+ request .OptionalCursor = lastCursor
518+ respStream , err := c .LookupSubjects (cmd .Context (), request )
519+ if err != nil {
523520 return err
524- default :
521+ }
522+
523+ var cursorToken string
524+ if lastCursor != nil {
525+ cursorToken = lastCursor .Token
526+ }
527+
528+ log .Trace ().Interface ("request" , request ).Str ("cursor" , cursorToken ).Msg ("reading subjects page" )
529+ var relCount uint32
530+ for {
531+ resp , err := respStream .Recv ()
532+ if errors .Is (err , io .EOF ) {
533+ break
534+ }
535+ if err != nil {
536+ return err
537+ }
538+
539+ lastCursor = resp .AfterResultCursor
540+ relCount ++
541+
525542 if cobrautil .MustGetBool (cmd , "json" ) {
526543 prettyProto , err := PrettyProto (resp )
527544 if err != nil {
@@ -533,8 +550,16 @@ func lookupSubjectsCmdFunc(cmd *cobra.Command, args []string) error {
533550 console .Printf ("%s:%s%s\n " ,
534551 subjectType ,
535552 prettyLookupPermissionship (resp .Subject .SubjectObjectId , resp .Subject .Permissionship , resp .Subject .PartialCaveatInfo ),
536- excludedSubjectsString (resp .ExcludedSubjects ),
537- )
553+ excludedSubjectsString (resp .ExcludedSubjects ))
554+ }
555+
556+ if relCount < limit || limit == 0 {
557+ return nil
558+ }
559+
560+ if relCount > limit {
561+ log .Warn ().Uint32 ("limit-specified" , limit ).Uint32 ("relationships-received" , relCount ).Msg ("page limit ignored, pagination may not be supported by the server, consider updating SpiceDB" )
562+ return nil
538563 }
539564 }
540565}
0 commit comments