Skip to content

Commit a0192c7

Browse files
committed
Add support for list organization feature flags endpoint
1 parent e2a2a05 commit a0192c7

File tree

7 files changed

+158
-0
lines changed

7 files changed

+158
-0
lines changed

tests/test_organizations.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from typing import Union
33
import pytest
44
from tests.types.test_auto_pagination_function import TestAutoPaginationFunction
5+
from tests.utils.fixtures.mock_feature_flag import MockFeatureFlag
56
from tests.utils.fixtures.mock_organization import MockOrganization
67
from tests.utils.fixtures.mock_role import MockRole
78
from tests.utils.list_resource import list_response_of
@@ -77,6 +78,14 @@ def mock_organization_roles(self):
7778
"object": "list",
7879
}
7980

81+
@pytest.fixture
82+
def mock_feature_flags(self):
83+
return {
84+
"data": [MockFeatureFlag(id=f"flag_{str(i)}").dict() for i in range(2)],
85+
"object": "list",
86+
"list_metadata": {"before": None, "after": None},
87+
}
88+
8089
def test_list_organizations(
8190
self, mock_organizations, capture_and_mock_http_client_request
8291
):
@@ -264,3 +273,28 @@ def to_dict(x):
264273
list(map(to_dict, organization_roles_response.data))
265274
== mock_organization_roles["data"]
266275
)
276+
277+
def test_list_feature_flags(
278+
self, mock_feature_flags, capture_and_mock_http_client_request
279+
):
280+
request_kwargs = capture_and_mock_http_client_request(
281+
self.http_client, mock_feature_flags, 200
282+
)
283+
284+
feature_flags_response = syncify(
285+
self.organizations.list_feature_flags(
286+
organization_id="org_01EHT88Z8J8795GZNQ4ZP1J81T"
287+
)
288+
)
289+
290+
def to_dict(x):
291+
return x.dict()
292+
293+
assert request_kwargs["method"] == "get"
294+
assert request_kwargs["url"].endswith(
295+
"/organizations/org_01EHT88Z8J8795GZNQ4ZP1J81T/feature-flags"
296+
)
297+
assert (
298+
list(map(to_dict, feature_flags_response.data))
299+
== mock_feature_flags["data"]
300+
)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import datetime
2+
3+
from workos.types.feature_flags.feature_flag import FeatureFlag
4+
5+
6+
class MockFeatureFlag(FeatureFlag):
7+
def __init__(self, id):
8+
now = datetime.datetime.now().isoformat()
9+
super().__init__(
10+
object="feature_flag",
11+
id=id,
12+
slug="test-feature",
13+
name="Test Feature",
14+
description="A test feature flag",
15+
created_at=now,
16+
updated_at=now,
17+
)

workos/organizations.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from typing import Optional, Protocol, Sequence
22

3+
from workos.types.feature_flags import FeatureFlag
4+
from workos.types.feature_flags.list_filters import FeatureFlagListFilters
35
from workos.types.metadata import Metadata
46
from workos.types.organizations.domain_data_input import DomainDataInput
57
from workos.types.organizations.list_filters import OrganizationListFilters
@@ -24,6 +26,10 @@
2426
Organization, OrganizationListFilters, ListMetadata
2527
]
2628

29+
FeatureFlagsListResource = WorkOSListResource[
30+
FeatureFlag, FeatureFlagListFilters, ListMetadata
31+
]
32+
2733

2834
class OrganizationsModule(Protocol):
2935
"""Offers methods through the WorkOS Organizations service."""
@@ -128,6 +134,29 @@ def delete_organization(self, organization_id: str) -> SyncOrAsync[None]:
128134
"""
129135
...
130136

137+
def list_feature_flags(
138+
self,
139+
organization_id: str,
140+
*,
141+
limit: int = DEFAULT_LIST_RESPONSE_LIMIT,
142+
before: Optional[str] = None,
143+
after: Optional[str] = None,
144+
order: PaginationOrder = "desc",
145+
) -> SyncOrAsync[FeatureFlagsListResource]:
146+
"""Retrieve a list of feature flags for an organization
147+
148+
Args:
149+
organization_id (str): Organization's unique identifier
150+
limit (int): Maximum number of records to return. (Optional)
151+
before (str): Pagination cursor to receive records before a provided Feature Flag ID. (Optional)
152+
after (str): Pagination cursor to receive records after a provided Feature Flag ID. (Optional)
153+
order (Literal["asc","desc"]): Sort records in either ascending or descending (default) order by created_at timestamp. (Optional)
154+
155+
Returns:
156+
FeatureFlagsListResource: Feature flags list response from WorkOS.
157+
"""
158+
...
159+
131160

132161
class Organizations(OrganizationsModule):
133162
_http_client: SyncHTTPClient
@@ -247,6 +276,34 @@ def list_organization_roles(self, organization_id: str) -> RoleList:
247276

248277
return RoleList.model_validate(response)
249278

279+
def list_feature_flags(
280+
self,
281+
organization_id: str,
282+
*,
283+
limit: int = DEFAULT_LIST_RESPONSE_LIMIT,
284+
before: Optional[str] = None,
285+
after: Optional[str] = None,
286+
order: PaginationOrder = "desc",
287+
) -> FeatureFlagsListResource:
288+
list_params: FeatureFlagListFilters = {
289+
"limit": limit,
290+
"before": before,
291+
"after": after,
292+
"order": order,
293+
}
294+
295+
response = self._http_client.request(
296+
f"organizations/{organization_id}/feature-flags",
297+
method=REQUEST_METHOD_GET,
298+
params=list_params,
299+
)
300+
301+
return WorkOSListResource[FeatureFlag, FeatureFlagListFilters, ListMetadata](
302+
list_method=self.list_feature_flags,
303+
list_args=list_params,
304+
**ListPage[FeatureFlag](**response).model_dump(),
305+
)
306+
250307

251308
class AsyncOrganizations(OrganizationsModule):
252309
_http_client: AsyncHTTPClient
@@ -365,3 +422,31 @@ async def list_organization_roles(self, organization_id: str) -> RoleList:
365422
)
366423

367424
return RoleList.model_validate(response)
425+
426+
async def list_feature_flags(
427+
self,
428+
organization_id: str,
429+
*,
430+
limit: int = DEFAULT_LIST_RESPONSE_LIMIT,
431+
before: Optional[str] = None,
432+
after: Optional[str] = None,
433+
order: PaginationOrder = "desc",
434+
) -> FeatureFlagsListResource:
435+
list_params: FeatureFlagListFilters = {
436+
"limit": limit,
437+
"before": before,
438+
"after": after,
439+
"order": order,
440+
}
441+
442+
response = await self._http_client.request(
443+
f"organizations/{organization_id}/feature-flags",
444+
method=REQUEST_METHOD_GET,
445+
params=list_params,
446+
)
447+
448+
return WorkOSListResource[FeatureFlag, FeatureFlagListFilters, ListMetadata](
449+
list_method=self.list_feature_flags,
450+
list_args=list_params,
451+
**ListPage[FeatureFlag](**response).model_dump(),
452+
)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from workos.types.feature_flags.feature_flag import FeatureFlag
2+
3+
__all__ = ["FeatureFlag"]
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from typing import Literal, Optional
2+
from workos.types.workos_model import WorkOSModel
3+
4+
5+
class FeatureFlag(WorkOSModel):
6+
id: str
7+
object: Literal["feature_flag"]
8+
slug: str
9+
name: str
10+
description: Optional[str]
11+
created_at: str
12+
updated_at: str
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from workos.types.list_resource import ListArgs
2+
3+
4+
class FeatureFlagListFilters(ListArgs, total=False):
5+
pass

workos/types/list_resource.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
DirectoryUserWithGroups,
2424
)
2525
from workos.types.events import Event
26+
from workos.types.feature_flags import FeatureFlag
2627
from workos.types.fga import (
2728
Warrant,
2829
AuthorizationResource,
@@ -46,6 +47,7 @@
4647
DirectoryGroup,
4748
DirectoryUserWithGroups,
4849
Event,
50+
FeatureFlag,
4951
Invitation,
5052
Organization,
5153
OrganizationMembership,

0 commit comments

Comments
 (0)