From 5777dcd2546c8ebd508c201bbd4ba8acbb9f2034 Mon Sep 17 00:00:00 2001 From: Nick Misasi Date: Tue, 25 Nov 2025 14:04:14 -0500 Subject: [PATCH] Fix issues with access_control_policies/search endpoint functionality and docs (#34564) * Fix issues with access_control_policies/search endpoint functionality and docs * Undo --- api/v4/source/definitions.yaml | 38 +++++++++++++++---- .../sqlstore/access_control_policy_store.go | 9 +++-- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/api/v4/source/definitions.yaml b/api/v4/source/definitions.yaml index bbebb7b3eba..d62cc296c43 100644 --- a/api/v4/source/definitions.yaml +++ b/api/v4/source/definitions.yaml @@ -4324,16 +4324,34 @@ components: term: type: string description: The search term to match against policy names or display names. - is_active: + type: + type: string + description: The type of policy (e.g., 'parent' or 'channel'). + parent_id: + type: string + description: The ID of the parent policy to search within. + ids: + type: array + items: + type: string + description: List of policy IDs to filter by. + active: type: boolean description: Filter policies by active status. - page: + include_children: + type: boolean + description: Whether to include child policies in the result. + cursor: + $ref: "#/components/schemas/AccessControlPolicyCursor" + limit: type: integer - description: The page number to return. - per_page: - type: integer - description: The number of policies to return per page. - # Add other potential search/filter fields like sort_by, sort_direction + description: The maximum number of policies to return. + AccessControlPolicyCursor: + type: object + properties: + id: + type: string + description: The ID of the policy to start searching after. AccessControlPolicyTestResponse: type: object properties: @@ -4407,12 +4425,18 @@ components: after: type: string description: The ID of the user to start the test after (for pagination). + channelId: + type: string + description: The channel ID to contextually test the expression against (required for channel admins). CELExpression: type: object properties: expression: type: string description: The CEL expression to visualize. + channelId: + type: string + description: The channel ID to contextually test the expression against (required for channel admins). VisualExpression: type: object properties: diff --git a/server/channels/store/sqlstore/access_control_policy_store.go b/server/channels/store/sqlstore/access_control_policy_store.go index 9e9828b8726..06121074c80 100644 --- a/server/channels/store/sqlstore/access_control_policy_store.go +++ b/server/channels/store/sqlstore/access_control_policy_store.go @@ -19,6 +19,7 @@ import ( ) const MaxPerPage = 1000 +const DefaultPerPage = 10 // Usually rules are how we define the policy, hence the versioning. For v0.1, we also // have the imports field which is used to link with the parent policy. @@ -561,7 +562,7 @@ func (s *SqlAccessControlPolicyStore) GetAll(_ request.CTX, opts model.GetAccess limit := uint64(opts.Limit) if limit < 1 { - limit = 1 + limit = DefaultPerPage } else if limit > MaxPerPage { limit = MaxPerPage } @@ -598,9 +599,9 @@ func (s *SqlAccessControlPolicyStore) SearchPolicies(rctx request.CTX, opts mode var query sq.SelectBuilder if opts.IncludeChildren && opts.ParentID == "" { columns := accessControlPolicySliceColumns("p") - childIDs := `COALESCE((SELECT JSON_AGG(c.ID) + childIDs := `COALESCE((SELECT JSON_AGG(c.ID) FROM AccessControlPolicies c - WHERE c.Type != 'parent' + WHERE c.Type != 'parent' AND c.Data->'imports' @> JSONB_BUILD_ARRAY(p.ID)), '[]'::json) AS ChildIDs` columns = append(columns, childIDs) query = s.getQueryBuilder().Select(columns...).From("AccessControlPolicies p") @@ -647,7 +648,7 @@ func (s *SqlAccessControlPolicyStore) SearchPolicies(rctx request.CTX, opts mode limit := uint64(opts.Limit) if limit < 1 { - limit = 1 + limit = DefaultPerPage } else if limit > MaxPerPage { limit = MaxPerPage }