Skip to content

Commit 1d935d6

Browse files
authored
Add support for list user feature flags endpoint (#502)
* Add support for list user feature flags endpoint * Use FeatureFlagsListResource alias
1 parent e6a51c5 commit 1d935d6

File tree

2 files changed

+120
-0
lines changed

2 files changed

+120
-0
lines changed

tests/test_user_management.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from tests.utils.fixtures.mock_auth_factor_totp import MockAuthenticationFactorTotp
88
from tests.utils.fixtures.mock_email_verification import MockEmailVerification
9+
from tests.utils.fixtures.mock_feature_flag import MockFeatureFlag
910
from tests.utils.fixtures.mock_invitation import MockInvitation
1011
from tests.utils.fixtures.mock_magic_auth import MockMagicAuth
1112
from tests.utils.fixtures.mock_organization_membership import MockOrganizationMembership
@@ -146,6 +147,14 @@ def mock_invitations_multiple_pages(self):
146147
invitations_list = [MockInvitation(id=str(i)).dict() for i in range(40)]
147148
return list_response_of(data=invitations_list)
148149

150+
@pytest.fixture
151+
def mock_feature_flags(self):
152+
return {
153+
"data": [MockFeatureFlag(id=f"flag_{str(i)}").dict() for i in range(2)],
154+
"object": "list",
155+
"list_metadata": {"before": None, "after": None},
156+
}
157+
149158

150159
class TestUserManagementBase(UserManagementFixtures):
151160
@pytest.fixture(autouse=True)
@@ -1250,3 +1259,28 @@ def test_resend_invitation_accepted(self, capture_and_mock_http_client_request):
12501259

12511260
with pytest.raises(Exception):
12521261
syncify(self.user_management.resend_invitation("invitation_accepted"))
1262+
1263+
def test_list_feature_flags(
1264+
self, mock_feature_flags, capture_and_mock_http_client_request
1265+
):
1266+
request_kwargs = capture_and_mock_http_client_request(
1267+
self.http_client, mock_feature_flags, 200
1268+
)
1269+
1270+
feature_flags_response = syncify(
1271+
self.user_management.list_feature_flags(
1272+
user_id="user_01H7ZGXFP5C6BBQY6Z7277ZCT0"
1273+
)
1274+
)
1275+
1276+
def to_dict(x):
1277+
return x.dict()
1278+
1279+
assert request_kwargs["method"] == "get"
1280+
assert request_kwargs["url"].endswith(
1281+
"/user_management/users/user_01H7ZGXFP5C6BBQY6Z7277ZCT0/feature-flags"
1282+
)
1283+
assert (
1284+
list(map(to_dict, feature_flags_response.data))
1285+
== mock_feature_flags["data"]
1286+
)

workos/user_management.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
from urllib.parse import urlencode
33
from workos._client_configuration import ClientConfiguration
44
from workos.session import AsyncSession, Session
5+
from workos.types.feature_flags import FeatureFlag
6+
from workos.types.feature_flags.list_filters import FeatureFlagListFilters
57
from workos.types.list_resource import (
68
ListArgs,
79
ListMetadata,
@@ -97,6 +99,7 @@
9799
INVITATION_RESEND_PATH = "user_management/invitations/{0}/resend"
98100
PASSWORD_RESET_PATH = "user_management/password_reset"
99101
PASSWORD_RESET_DETAIL_PATH = "user_management/password_reset/{0}"
102+
USER_FEATURE_FLAGS_PATH = "user_management/users/{0}/feature-flags"
100103

101104

102105
UsersListResource = WorkOSListResource[User, UsersListFilters, ListMetadata]
@@ -113,6 +116,10 @@
113116
Invitation, InvitationsListFilters, ListMetadata
114117
]
115118

119+
FeatureFlagsListResource = WorkOSListResource[
120+
FeatureFlag, FeatureFlagListFilters, ListMetadata
121+
]
122+
116123
from workos.types.user_management.list_filters import SessionsListFilters
117124

118125
SessionsListResource = WorkOSListResource[
@@ -908,6 +915,29 @@ def resend_invitation(self, invitation_id: str) -> SyncOrAsync[Invitation]:
908915
"""
909916
...
910917

918+
def list_feature_flags(
919+
self,
920+
user_id: str,
921+
*,
922+
limit: int = DEFAULT_LIST_RESPONSE_LIMIT,
923+
before: Optional[str] = None,
924+
after: Optional[str] = None,
925+
order: PaginationOrder = "desc",
926+
) -> SyncOrAsync[FeatureFlagsListResource]:
927+
"""Retrieve a list of feature flags for a user
928+
929+
Args:
930+
user_id (str): User's unique identifier
931+
limit (int): Maximum number of records to return. (Optional)
932+
before (str): Pagination cursor to receive records before a provided Feature Flag ID. (Optional)
933+
after (str): Pagination cursor to receive records after a provided Feature Flag ID. (Optional)
934+
order (Literal["asc","desc"]): Sort records in either ascending or descending (default) order by created_at timestamp. (Optional)
935+
936+
Returns:
937+
FeatureFlagsListResource: Feature flags list response from WorkOS.
938+
"""
939+
...
940+
911941

912942
class UserManagement(UserManagementModule):
913943
_http_client: SyncHTTPClient
@@ -1603,6 +1633,34 @@ def resend_invitation(self, invitation_id: str) -> Invitation:
16031633

16041634
return Invitation.model_validate(response)
16051635

1636+
def list_feature_flags(
1637+
self,
1638+
user_id: str,
1639+
*,
1640+
limit: int = DEFAULT_LIST_RESPONSE_LIMIT,
1641+
before: Optional[str] = None,
1642+
after: Optional[str] = None,
1643+
order: PaginationOrder = "desc",
1644+
) -> FeatureFlagsListResource:
1645+
list_params: FeatureFlagListFilters = {
1646+
"limit": limit,
1647+
"before": before,
1648+
"after": after,
1649+
"order": order,
1650+
}
1651+
1652+
response = self._http_client.request(
1653+
USER_FEATURE_FLAGS_PATH.format(user_id),
1654+
method=REQUEST_METHOD_GET,
1655+
params=list_params,
1656+
)
1657+
1658+
return FeatureFlagsListResource(
1659+
list_method=self.list_feature_flags,
1660+
list_args=list_params,
1661+
**ListPage[FeatureFlag](**response).model_dump(),
1662+
)
1663+
16061664

16071665
class AsyncUserManagement(UserManagementModule):
16081666
_http_client: AsyncHTTPClient
@@ -2312,3 +2370,31 @@ async def resend_invitation(self, invitation_id: str) -> Invitation:
23122370
)
23132371

23142372
return Invitation.model_validate(response)
2373+
2374+
async def list_feature_flags(
2375+
self,
2376+
user_id: str,
2377+
*,
2378+
limit: int = DEFAULT_LIST_RESPONSE_LIMIT,
2379+
before: Optional[str] = None,
2380+
after: Optional[str] = None,
2381+
order: PaginationOrder = "desc",
2382+
) -> FeatureFlagsListResource:
2383+
list_params: FeatureFlagListFilters = {
2384+
"limit": limit,
2385+
"before": before,
2386+
"after": after,
2387+
"order": order,
2388+
}
2389+
2390+
response = await self._http_client.request(
2391+
USER_FEATURE_FLAGS_PATH.format(user_id),
2392+
method=REQUEST_METHOD_GET,
2393+
params=list_params,
2394+
)
2395+
2396+
return FeatureFlagsListResource(
2397+
list_method=self.list_feature_flags,
2398+
list_args=list_params,
2399+
**ListPage[FeatureFlag](**response).model_dump(),
2400+
)

0 commit comments

Comments
 (0)