Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 30 additions & 7 deletions docs/api-reference/apidocs.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -2057,6 +2057,19 @@
},
"description": "EntityFilter is used to filter entities based on the type and ids."
},
"EntityIds": {
"type": "object",
"properties": {
"ids": {
"type": "array",
"items": {
"type": "string"
},
"title": "entitiy Ids"
}
},
"description": "EntityIds is a helper message used within PermissionLookupEntityResponse to encapsulate a list of entity."
},
"Entry": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -2271,8 +2284,11 @@
"type": "string",
"description": "Type of the entity to lookup, required, must start with a letter and can include alphanumeric and underscore, max 64 bytes."
},
"permission": {
"type": "string",
"permissions": {
"type": "array",
"items": {
"type": "string"
},
"description": "Name of the permission to check, required, must start with a letter and can include alphanumeric and underscore, max 64 bytes."
},
"subject": {
Expand Down Expand Up @@ -2306,8 +2322,11 @@
"type": "string",
"description": "Type of the entity to lookup, required, must start with a letter and can include alphanumeric and underscore, max 64 bytes."
},
"permission": {
"type": "string",
"permissions": {
"type": "array",
"items": {
"type": "string"
},
"description": "Name of the permission to check, required, must start with a letter and can include alphanumeric and underscore, max 64 bytes."
},
"subject": {
Expand Down Expand Up @@ -2598,9 +2617,9 @@
"type": "object",
"properties": {
"entity_ids": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/EntityIds"
},
"description": "List of identifiers for entities that match the lookup."
},
Expand All @@ -2618,6 +2637,10 @@
"type": "string",
"description": "Identifier for an entity that matches the lookup."
},
"permission": {
"type": "string",
"description": "The name of the permission for which the specified entity_id has access."
},
"continuous_token": {
"type": "string",
"description": "continuous_token is a string that can be used to paginate and retrieve the next set of results."
Expand Down
37 changes: 30 additions & 7 deletions docs/api-reference/openapiv2/apidocs.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -2049,6 +2049,19 @@
},
"description": "EntityFilter is used to filter entities based on the type and ids."
},
"EntityIds": {
"type": "object",
"properties": {
"ids": {
"type": "array",
"items": {
"type": "string"
},
"title": "entitiy Ids"
}
},
"description": "EntityIds is a helper message used within PermissionLookupEntityResponse to encapsulate a list of entity."
},
"Entry": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -2261,8 +2274,11 @@
"type": "string",
"description": "Type of the entity to lookup, required, must start with a letter and can include alphanumeric and underscore, max 64 bytes."
},
"permission": {
"type": "string",
"permissions": {
"type": "array",
"items": {
"type": "string"
},
Comment on lines +2365 to +2369
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update API clients to use an array of permission names.

Changing the permission property to an array is a good enhancement to allow checking multiple permissions in a single request.

Please ensure that all API clients are updated to provide an array of permission names when calling the LookupEntity API.

"description": "Name of the permission to check, required, must start with a letter and can include alphanumeric and underscore, max 64 bytes."
},
"subject": {
Expand Down Expand Up @@ -2296,8 +2312,11 @@
"type": "string",
"description": "Type of the entity to lookup, required, must start with a letter and can include alphanumeric and underscore, max 64 bytes."
},
"permission": {
"type": "string",
"permissions": {
"type": "array",
"items": {
"type": "string"
},
Comment on lines +2410 to +2414
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update streaming API clients to handle multiple permissions per entity ID.

Changing the permission property to an array is a good enhancement to allow checking multiple permissions in a single streaming request.

Please ensure that all streaming API clients are updated to handle multiple permissions associated with each entity ID in the response stream.

"description": "Name of the permission to check, required, must start with a letter and can include alphanumeric and underscore, max 64 bytes."
},
"subject": {
Expand Down Expand Up @@ -2584,9 +2603,9 @@
"type": "object",
"properties": {
"entity_ids": {
"type": "array",
"items": {
"type": "string"
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/EntityIds"
},
"description": "List of identifiers for entities that match the lookup."
},
Expand All @@ -2604,6 +2623,10 @@
"type": "string",
"description": "Identifier for an entity that matches the lookup."
},
"permission": {
"type": "string",
"description": "The name of the permission for which the specified entity_id has access."
},
"continuous_token": {
"type": "string",
"description": "continuous_token is a string that can be used to paginate and retrieve the next set of results."
Expand Down
12 changes: 8 additions & 4 deletions integration-test/usecases/facebook_groups_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,17 @@ var _ = Describe("facebook-groups-test", func() {
Context: &base.Context{
Tuples: contextTuples,
},
EntityType: filter.EntityType,
Permission: permission,
Subject: subject,
EntityType: filter.EntityType,
Permissions: []string{permission},
Subject: subject,
})

Expect(err).ShouldNot(HaveOccurred())
Expect(IsSameArray(res.GetEntityIds(), expected)).Should(Equal(true))
var responseIdsForPermission []string
if res, ok := res.GetEntityIds()[permission]; ok {
responseIdsForPermission = res.Ids
}
Expect(IsSameArray(responseIdsForPermission, expected)).Should(Equal(true))
}
}
}
Expand Down
12 changes: 8 additions & 4 deletions integration-test/usecases/google_docs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,17 @@ var _ = Describe("google-docs-test", func() {
Context: &base.Context{
Tuples: contextTuples,
},
EntityType: filter.EntityType,
Permission: permission,
Subject: subject,
EntityType: filter.EntityType,
Permissions: []string{permission},
Subject: subject,
})

Expect(err).ShouldNot(HaveOccurred())
Expect(IsSameArray(res.GetEntityIds(), expected)).Should(Equal(true))
var responseIdsForPermission []string
if res, ok := res.GetEntityIds()[permission]; ok {
responseIdsForPermission = res.Ids
}
Expect(IsSameArray(responseIdsForPermission, expected)).Should(Equal(true))
}
}
}
Expand Down
12 changes: 8 additions & 4 deletions integration-test/usecases/notion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,17 @@ var _ = Describe("notion-test", func() {
Context: &base.Context{
Tuples: contextTuples,
},
EntityType: filter.EntityType,
Permission: permission,
Subject: subject,
EntityType: filter.EntityType,
Permissions: []string{permission},
Subject: subject,
})

Expect(err).ShouldNot(HaveOccurred())
Expect(IsSameArray(res.GetEntityIds(), expected)).Should(Equal(true))
var responseIdsForPermission []string
if res, ok := res.GetEntityIds()[permission]; ok {
responseIdsForPermission = res.Ids
}
Expect(IsSameArray(responseIdsForPermission, expected)).Should(Equal(true))
}
}
}
Expand Down
35 changes: 20 additions & 15 deletions internal/engines/bulk.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ type BulkChecker struct {

// callback is a function that handles the result of each permission check.
// It is called with the entity ID and the result of the permission check (e.g., allowed or denied).
callback func(entityID, ct string)
callback func(entityID, permission string, ct string)

// sortedList is a slice that stores BulkCheckerRequest objects.
// This list is maintained in a sorted order based on some criteria, such as the entity ID.
Expand All @@ -76,7 +76,7 @@ type BulkChecker struct {
// engine: the CheckEngine to use for permission checks
// callback: a callback function that handles the result of each permission check
// concurrencyLimit: the maximum number of concurrent permission checks
func NewBulkChecker(ctx context.Context, checker invoke.Check, typ BulkCheckerType, callback func(entityID, ct string), concurrencyLimit int) *BulkChecker {
func NewBulkChecker(ctx context.Context, checker invoke.Check, typ BulkCheckerType, callback func(entityID, permission string, ct string), concurrencyLimit int) *BulkChecker {
bc := &BulkChecker{
RequestChan: make(chan BulkCheckerRequest),
checker: checker,
Expand Down Expand Up @@ -220,9 +220,9 @@ func (bc *BulkChecker) ExecuteRequests(size uint32) error {
}
// Depending on the type of check (entity or subject), call the appropriate callback
if bc.typ == BULK_ENTITY {
bc.callback(listCopy[processedIndex].Request.GetEntity().GetId(), ct)
bc.callback(listCopy[processedIndex].Request.GetEntity().GetId(), req.Request.GetPermission(), ct)
} else if bc.typ == BULK_SUBJECT {
bc.callback(listCopy[processedIndex].Request.GetSubject().GetId(), ct)
bc.callback(listCopy[processedIndex].Request.GetSubject().GetId(), req.Request.GetPermission(), ct)
}
}
}
Expand Down Expand Up @@ -261,17 +261,22 @@ func NewBulkEntityPublisher(ctx context.Context, request *base.PermissionLookupE
}

// Publish publishes a permission check request to the BulkChecker.
func (s *BulkEntityPublisher) Publish(entity *base.Entity, metadata *base.PermissionCheckRequestMetadata, context *base.Context, result base.CheckResult) {
s.bulkChecker.RequestChan <- BulkCheckerRequest{
Request: &base.PermissionCheckRequest{
TenantId: s.request.GetTenantId(),
Metadata: metadata,
Entity: entity,
Permission: s.request.GetPermission(),
Subject: s.request.GetSubject(),
Context: context,
},
Result: result,
func (s *BulkEntityPublisher) Publish(entity *base.Entity, metadata *base.PermissionCheckRequestMetadata, context *base.Context, result base.CheckResult, permissionChecks *ERMap) {
for _, permission := range s.request.GetPermissions() {
if !permissionChecks.Add(entity, permission) {
continue
}
s.bulkChecker.RequestChan <- BulkCheckerRequest{
Request: &base.PermissionCheckRequest{
TenantId: s.request.GetTenantId(),
Metadata: metadata,
Entity: entity,
Permission: permission,
Subject: s.request.GetSubject(),
Context: context,
},
Result: result,
}
}
}

Expand Down
Loading
Loading