github.com/openfga/openfga@v1.5.4-rc1/pkg/server/commands/listusers/list_users.go (about)

     1  package listusers
     2  
     3  import (
     4  	"maps"
     5  	"sync/atomic"
     6  
     7  	openfgav1 "github.com/openfga/api/proto/openfga/v1"
     8  	"google.golang.org/protobuf/types/known/structpb"
     9  )
    10  
    11  type listUsersRequest interface {
    12  	GetStoreId() string
    13  	GetAuthorizationModelId() string
    14  	GetObject() *openfgav1.Object
    15  	GetRelation() string
    16  	GetUserFilters() []*openfgav1.UserTypeFilter
    17  	GetContextualTuples() []*openfgav1.TupleKey
    18  	GetContext() *structpb.Struct
    19  }
    20  
    21  type internalListUsersRequest struct {
    22  	*openfgav1.ListUsersRequest
    23  
    24  	// visitedUsersetsMap keeps track of the "path" we've made so far.
    25  	// It prevents stack overflows by preventing visiting the same userset twice.
    26  	visitedUsersetsMap map[string]struct{}
    27  
    28  	// depth is the current depths of the traversal expressed as a positive, incrementing integer.
    29  	// When expansion of list users recursively traverses one level, we increment by one. If this
    30  	// counter hits the limit, we throw ErrResolutionDepthExceeded. This protects against a potentially deep
    31  	// or endless cycle of recursion.
    32  	depth uint32
    33  
    34  	datastoreQueryCount *atomic.Uint32
    35  }
    36  
    37  var _ listUsersRequest = (*internalListUsersRequest)(nil)
    38  
    39  // nolint // it should be GetStoreID, but we want to satisfy the interface listUsersRequest
    40  func (r *internalListUsersRequest) GetStoreId() string {
    41  	if r == nil {
    42  		return ""
    43  	}
    44  	return r.StoreId
    45  }
    46  
    47  // nolint // it should be GetAuthorizationModelID, but we want to satisfy the interface listUsersRequest
    48  func (r *internalListUsersRequest) GetAuthorizationModelId() string {
    49  	if r == nil {
    50  		return ""
    51  	}
    52  	return r.AuthorizationModelId
    53  }
    54  
    55  func (r *internalListUsersRequest) GetObject() *openfgav1.Object {
    56  	if r == nil {
    57  		return nil
    58  	}
    59  	return r.Object
    60  }
    61  
    62  func (r *internalListUsersRequest) GetRelation() string {
    63  	if r == nil {
    64  		return ""
    65  	}
    66  	return r.Relation
    67  }
    68  
    69  func (r *internalListUsersRequest) GetUserFilters() []*openfgav1.UserTypeFilter {
    70  	if r == nil {
    71  		return nil
    72  	}
    73  	return r.UserFilters
    74  }
    75  
    76  func (r *internalListUsersRequest) GetContextualTuples() []*openfgav1.TupleKey {
    77  	if r == nil {
    78  		return nil
    79  	}
    80  	return r.ContextualTuples
    81  }
    82  
    83  func (r *internalListUsersRequest) GetDatastoreQueryCount() uint32 {
    84  	if r == nil {
    85  		return uint32(0)
    86  	}
    87  	return r.datastoreQueryCount.Load()
    88  }
    89  
    90  func (r *internalListUsersRequest) GetContext() *structpb.Struct {
    91  	if r == nil {
    92  		return nil
    93  	}
    94  	return r.Context
    95  }
    96  
    97  type listUsersResponse struct {
    98  	Users    []*openfgav1.User
    99  	Metadata listUsersResponseMetadata
   100  }
   101  
   102  type listUsersResponseMetadata struct {
   103  	DatastoreQueryCount uint32
   104  }
   105  
   106  func (r *listUsersResponse) GetUsers() []*openfgav1.User {
   107  	if r == nil {
   108  		return []*openfgav1.User{}
   109  	}
   110  	return r.Users
   111  }
   112  
   113  func (r *listUsersResponse) GetMetadata() listUsersResponseMetadata {
   114  	if r == nil {
   115  		return listUsersResponseMetadata{}
   116  	}
   117  	return r.Metadata
   118  }
   119  
   120  func fromListUsersRequest(o listUsersRequest, datastoreQueryCount *atomic.Uint32) *internalListUsersRequest {
   121  	if datastoreQueryCount == nil {
   122  		datastoreQueryCount = new(atomic.Uint32)
   123  	}
   124  	return &internalListUsersRequest{
   125  		ListUsersRequest: &openfgav1.ListUsersRequest{
   126  			StoreId:              o.GetStoreId(),
   127  			AuthorizationModelId: o.GetAuthorizationModelId(),
   128  			Object:               o.GetObject(),
   129  			Relation:             o.GetRelation(),
   130  			UserFilters:          o.GetUserFilters(),
   131  			ContextualTuples:     o.GetContextualTuples(),
   132  			Context:              o.GetContext(),
   133  		},
   134  		visitedUsersetsMap:  make(map[string]struct{}),
   135  		depth:               0,
   136  		datastoreQueryCount: datastoreQueryCount,
   137  	}
   138  }
   139  
   140  // clone creates a copy of the request. Note that some fields are not deep-cloned.
   141  func (r *internalListUsersRequest) clone() *internalListUsersRequest {
   142  	v := fromListUsersRequest(r, r.datastoreQueryCount)
   143  	v.visitedUsersetsMap = maps.Clone(r.visitedUsersetsMap)
   144  	v.depth = r.depth
   145  	return v
   146  }