Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GET /organization/:orgId/roles support #392

Merged
merged 2 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
33 changes: 33 additions & 0 deletions tests/test_organizations.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import pytest
from tests.types.test_auto_pagination_function import TestAutoPaginationFunction
from tests.utils.fixtures.mock_organization import MockOrganization
from tests.utils.fixtures.mock_role import MockRole
from tests.utils.list_resource import list_response_of
from tests.utils.syncify import syncify
from workos.organizations import AsyncOrganizations, Organizations
Expand Down Expand Up @@ -67,6 +68,13 @@ def mock_organizations_multiple_data_pages(self):
]
return list_response_of(data=organizations_list)

@pytest.fixture
def mock_organization_roles(self):
return {
"data": [MockRole(id=str(i)).dict() for i in range(10)],
"object": "list",
}

def test_list_organizations(
self, mock_organizations, capture_and_mock_http_client_request
):
Expand Down Expand Up @@ -227,3 +235,28 @@ def test_list_organizations_auto_pagination_for_multiple_pages(
list_function=self.organizations.list_organizations,
expected_all_page_data=mock_organizations_multiple_data_pages["data"],
)

def test_list_organization_roles(
self, mock_organization_roles, capture_and_mock_http_client_request
):
request_kwargs = capture_and_mock_http_client_request(
self.http_client, mock_organization_roles, 200
)

organization_roles_response = syncify(
self.organizations.list_organization_roles(
organization_id="org_01EHT88Z8J8795GZNQ4ZP1J81T"
)
)

def to_dict(x):
return x.dict()

assert request_kwargs["method"] == "get"
assert request_kwargs["url"].endswith(
"/organizations/org_01EHT88Z8J8795GZNQ4ZP1J81T/roles"
)
assert (
list(map(to_dict, organization_roles_response.data))
== mock_organization_roles["data"]
)
18 changes: 18 additions & 0 deletions tests/utils/fixtures/mock_role.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import datetime

from workos.types.roles.role import Role


class MockRole(Role):
def __init__(self, id):
now = datetime.datetime.now().isoformat()
super().__init__(
object="role",
id=id,
name="Member",
slug="member",
description="The default member role",
type="EnvironmentRole",
created_at=now,
updated_at=now,
)
17 changes: 17 additions & 0 deletions workos/organizations.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from workos.types.organizations.domain_data_input import DomainDataInput
from workos.types.organizations.list_filters import OrganizationListFilters
from workos.types.roles.role import RoleList
from workos.typing.sync_or_async import SyncOrAsync
from workos.utils.http_client import AsyncHTTPClient, SyncHTTPClient
from workos.utils.pagination_order import PaginationOrder
Expand Down Expand Up @@ -223,6 +224,14 @@ def delete_organization(self, organization_id: str) -> None:
method=REQUEST_METHOD_DELETE,
)

def list_organization_roles(self, organization_id: str) -> RoleList:
response = self._http_client.request(
f"organizations/{organization_id}/roles",
method=REQUEST_METHOD_GET,
)

return RoleList.model_validate(response)


class AsyncOrganizations(OrganizationsModule):

Expand Down Expand Up @@ -324,3 +333,11 @@ async def delete_organization(self, organization_id: str) -> None:
f"organizations/{organization_id}",
method=REQUEST_METHOD_DELETE,
)

async def list_organization_roles(self, organization_id: str) -> RoleList:
response = await self._http_client.request(
f"organizations/{organization_id}/roles",
method=REQUEST_METHOD_GET,
)

return RoleList.model_validate(response)
9 changes: 4 additions & 5 deletions workos/types/events/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
)
from workos.types.events.directory_payload import DirectoryPayload
from workos.types.events.directory_payload_with_legacy_fields import (
DirectoryPayloadWithLegacyFields,
DirectoryPayloadWithLegacyFieldsForEventsApi,
)
from workos.types.events.directory_user_with_previous_attributes import (
Expand All @@ -40,7 +39,7 @@
from workos.types.events.session_created_payload import SessionCreatedPayload
from workos.types.organizations.organization_common import OrganizationCommon
from workos.types.organizations.organization_domain import OrganizationDomain
from workos.types.roles.role import Role
from workos.types.roles.role import EventRole
from workos.types.sso.connection import Connection
from workos.types.user_management.email_verification import (
EmailVerificationCommon,
Expand Down Expand Up @@ -210,15 +209,15 @@ class PasswordResetCreatedEvent(EventModel[PasswordResetCommon]):
event: Literal["password_reset.created"]


class RoleCreatedEvent(EventModel[Role]):
class RoleCreatedEvent(EventModel[EventRole]):
event: Literal["role.created"]


class RoleDeletedEvent(EventModel[Role]):
class RoleDeletedEvent(EventModel[EventRole]):
event: Literal["role.deleted"]


class RoleUpdatedEvent(EventModel[Role]):
class RoleUpdatedEvent(EventModel[EventRole]):
event: Literal["role.updated"]


Expand Down
4 changes: 2 additions & 2 deletions workos/types/events/event_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
from workos.types.events.session_created_payload import SessionCreatedPayload
from workos.types.organizations.organization_common import OrganizationCommon
from workos.types.organizations.organization_domain import OrganizationDomain
from workos.types.roles.role import Role
from workos.types.roles.role import EventRole
from workos.types.sso.connection import Connection
from workos.types.user_management.email_verification import (
EmailVerificationCommon,
Expand Down Expand Up @@ -72,14 +72,14 @@
DirectoryUserWithPreviousAttributes,
DirectoryGroupMembershipPayload,
EmailVerificationCommon,
EventRole,
InvitationCommon,
MagicAuthCommon,
OrganizationCommon,
OrganizationDomain,
OrganizationDomainVerificationFailedPayload,
OrganizationMembership,
PasswordResetCommon,
Role,
SessionCreatedPayload,
User,
)
Expand Down
21 changes: 20 additions & 1 deletion workos/types/roles/role.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,27 @@
from typing import Literal, Optional, Sequence
from workos.types.workos_model import WorkOSModel

RoleType = Literal["EnvironmentRole", "OrganizationRole"]

class Role(WorkOSModel):

class RoleCommon(WorkOSModel):
object: Literal["role"]
slug: str


class EventRole(RoleCommon):
permissions: Optional[Sequence[str]] = None


class Role(RoleCommon):
id: str
name: str
description: Optional[str] = None
type: RoleType
created_at: str
updated_at: str


class RoleList(WorkOSModel):
object: Literal["list"]
data: Sequence[Role]
8 changes: 4 additions & 4 deletions workos/types/webhooks/webhook.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
from workos.types.events.session_created_payload import SessionCreatedPayload
from workos.types.organizations.organization_common import OrganizationCommon
from workos.types.organizations.organization_domain import OrganizationDomain
from workos.types.roles.role import Role
from workos.types.roles.role import EventRole
from workos.types.sso.connection import Connection
from workos.types.user_management.email_verification import (
EmailVerificationCommon,
Expand Down Expand Up @@ -213,15 +213,15 @@ class PasswordResetCreatedWebhook(WebhookModel[PasswordResetCommon]):
event: Literal["password_reset.created"]


class RoleCreatedWebhook(WebhookModel[Role]):
class RoleCreatedWebhook(WebhookModel[EventRole]):
event: Literal["role.created"]


class RoleDeletedWebhook(WebhookModel[Role]):
class RoleDeletedWebhook(WebhookModel[EventRole]):
event: Literal["role.deleted"]


class RoleUpdatedWebhook(WebhookModel[Role]):
class RoleUpdatedWebhook(WebhookModel[EventRole]):
event: Literal["role.updated"]


Expand Down
Loading