canonical / identity-platform-admin-ui

Admin UI for the Canonical identity broker and identity provider solution
Other
6 stars 4 forks source link

inspect usage of `ListUsers` API #385

Open shipperizer opened 3 months ago

shipperizer commented 3 months ago

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
}

with the following set of tuples

### test
- object: role:test1
  user: user:test1
  relation: assignee
- object: role:test2
  user: group:test1#member
  relation: assignee
- object: group:test2
  user: user:test2
  relation: member
- object: role:test3
  user: group:test2#member
  relation: assignee
- object: group:test2
  user: user:test1
  relation: member
- object: group:test2
  user: group:test3#member
  relation: member
- object: group:test1
  user: group:test2#member
  relation: member

where the 3 groups are interconnected ListUsers performs the expand, whereas the ReadTuples does not

the result from ListUsers expands to linked groups providing a better result

image

image

syncronize-issues-to-jira[bot] commented 3 months ago

Thank you for reporting us your feedback!

The internal ticket has been created: https://warthogs.atlassian.net/browse/IAM-1007.

This message was autogenerated