Skip to content

Commit 072b3e4

Browse files
committed
feat: Allow filter to accept objects of multiple types
1 parent 5a081eb commit 072b3e4

File tree

2 files changed

+17
-20
lines changed

2 files changed

+17
-20
lines changed

coderd/rbac/authz.go

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,34 @@ type PreparedAuthorized interface {
1919
}
2020

2121
// Filter takes in a list of objects, and will filter the list removing all
22-
// the elements the subject does not have permission for. All objects must be
23-
// of the same type.
22+
// the elements the subject does not have permission for. This function slows
23+
// down if the list contains objects of multiple types. Attempt to only
24+
// filter objects of the same type for faster performance.
2425
func Filter[O Objecter](ctx context.Context, auth Authorizer, subjID string, subjRoles []string, action Action, objects []O) ([]O, error) {
2526
if len(objects) == 0 {
2627
// Nothing to filter
2728
return objects, nil
2829
}
29-
objectType := objects[0].RBACObject().Type
3030

3131
filtered := make([]O, 0)
32-
prepared, err := auth.PrepareByRoleName(ctx, subjID, subjRoles, action, objectType)
33-
if err != nil {
34-
return nil, xerrors.Errorf("prepare: %w", err)
35-
}
32+
prepared := make(map[string]PreparedAuthorized)
3633

3734
for i := range objects {
3835
object := objects[i]
39-
rbacObj := object.RBACObject()
40-
if rbacObj.Type != objectType {
41-
return nil, xerrors.Errorf("object types must be uniform across the set (%s), found %s", objectType, object.RBACObject().Type)
36+
objectType := object.RBACObject().Type
37+
// objectAuth is the prepared authorization for the object type.
38+
objectAuth, ok := prepared[object.RBACObject().Type]
39+
if !ok {
40+
var err error
41+
objectAuth, err = auth.PrepareByRoleName(ctx, subjID, subjRoles, action, objectType)
42+
if err != nil {
43+
return nil, xerrors.Errorf("prepare: %w", err)
44+
}
45+
prepared[objectType] = objectAuth
4246
}
43-
err := prepared.Authorize(ctx, rbacObj)
47+
48+
rbacObj := object.RBACObject()
49+
err := objectAuth.Authorize(ctx, rbacObj)
4450
if err == nil {
4551
filtered = append(filtered, object)
4652
}

coderd/rbac/authz_internal_test.go

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,6 @@ func (w fakeObject) RBACObject() Object {
3737
}
3838
}
3939

40-
func TestFilterError(t *testing.T) {
41-
t.Parallel()
42-
auth, err := NewAuthorizer()
43-
require.NoError(t, err)
44-
45-
_, err = Filter(context.Background(), auth, uuid.NewString(), []string{}, ActionRead, []Object{ResourceUser, ResourceWorkspace})
46-
require.ErrorContains(t, err, "object types must be uniform")
47-
}
48-
4940
// TestFilter ensures the filter acts the same as an individual authorize.
5041
// It generates a random set of objects, then runs the Filter batch function
5142
// against the singular ByRoleName function.

0 commit comments

Comments
 (0)