in places where we check for inverse relations it might be useful to use the ListUsers API
this is only available from version x.y.z of OpenFGA so that needs to be taken into account
this can potentially be swapped in places like this or this
sample code would be the following
func (c *Client) ListUsers(ctx context.Context, userFilter, relation, objectType string) ([]string, error) {
ctx, span := c.tracer.Start(ctx, "openfga.Client.ListObjects")
defer span.End()
var filter *openfga.UserTypeFilter
if userFilter == "" {
return nil, fmt.Errorf("userFilter cannot be empty")
}
f := strings.Split(userFilter, "#")
filter = openfga.NewUserTypeFilter(f[0])
if len(f) == 2 {
filter.SetRelation(f[1])
}
r := c.c.ListUsers(ctx)
body := client.ClientListUserRequest{
UserFilter: []openfga.UserTypeFilter{*filter},
Relation: relation,
Type: objectType,
}
r = r.Body(body)
usersResponse, err := c.c.ListUsersExecute(r)
if err != nil {
c.logger.Errorf("issues performing list operation: %s", err)
return nil, err
}
allowedObjs := make([]string, len(usersResponse.GetUsers()))
// TODO @shipperizer evaluate if this needs removing
for i, u := range usersResponse.GetUsers() {
// only use the id of the tuple
if o, ok := u.GetObjectOk(); ok {
allowedObjs[i] = o.Id
}
if us, ok := u.GetUsersetOk(); ok {
allowedObjs[i] = us.Id
}
if _, ok := u.GetWildcardOk(); ok {
allowedObjs[i] = "*"
}
}
return allowedObjs, nil
}
in places where we check for inverse relations it might be useful to use the
ListUsers
APIthis is only available from version
x.y.z
of OpenFGA so that needs to be taken into accountthis can potentially be swapped in places like this or this
sample code would be the following
with the following set of tuples
where the 3 groups are interconnected
ListUsers
performs the expand, whereas theReadTuples
does notthe result from
ListUsers
expands to linked groups providing a better result