diff --git a/.mock/definition/__package__.yml b/.mock/definition/__package__.yml index 3013a3914..ee7522fc3 100644 --- a/.mock/definition/__package__.yml +++ b/.mock/definition/__package__.yml @@ -1620,6 +1620,23 @@ types: docs: Last updated time source: openapi: openapi/openapi.yaml + ConfigurablePermissionOptionDefault: + discriminated: false + union: + - Role9E7Enum + - NullEnum + source: + openapi: openapi/openapi.yaml + inline: true + ConfigurablePermissionOption: + properties: + default: optional + label: optional + options: list + permission: string + tooltip: optional + source: + openapi: openapi/openapi.yaml ConvertedFormat: properties: export_type: @@ -2160,7 +2177,7 @@ types: occurs, contact the LEAP team for assistance with enabling custom scripts. default_role: - type: optional + type: optional docs: |- Default membership role for invited users @@ -2194,25 +2211,6 @@ types: quick view. source: openapi: openapi/openapi.yaml - DefaultRoleEnum: - enum: - - OW - - AD - - MA - - RE - - AN - - DI - - 'NO' - docs: |- - * `OW` - Owner - * `AD` - Administrator - * `MA` - Manager - * `RE` - Reviewer - * `AN` - Annotator - * `DI` - Deactivated - * `NO` - Not Activated - source: - openapi: openapi/openapi.yaml EditionEnum: enum: - Community @@ -3604,7 +3602,7 @@ types: * `MA` - Manager custom_scripts_enabled: string default_role: - type: optional + type: optional docs: |- Default membership role for invited users @@ -5698,6 +5696,35 @@ types: minLength: 1 source: openapi: openapi/openapi.yaml + OrganizationPermission: + properties: + default_role: string + id: integer + label: string + options: string + organization: integer + permission: + type: string + validation: + maxLength: 255 + roles: + type: optional> + docs: Explicit roles that have this permission within the organization. + tooltip: string + source: + openapi: openapi/openapi.yaml + OrganizationPermissionRequest: + properties: + permission: + type: string + validation: + minLength: 1 + maxLength: 255 + roles: + type: optional> + docs: Explicit roles that have this permission within the organization. + source: + openapi: openapi/openapi.yaml PaginatedAllRolesProjectListList: properties: count: integer diff --git a/.mock/definition/organizations.yml b/.mock/definition/organizations.yml index 59cba9e71..4c0156410 100644 --- a/.mock/definition/organizations.yml +++ b/.mock/definition/organizations.yml @@ -200,7 +200,7 @@ service: will be raised. If this occurs, contact the LEAP team for assistance with enabling custom scripts. default_role: - type: optional + type: optional docs: |- Default membership role for invited users diff --git a/.mock/definition/organizations/permissions.yml b/.mock/definition/organizations/permissions.yml new file mode 100644 index 000000000..aaf7f88ca --- /dev/null +++ b/.mock/definition/organizations/permissions.yml @@ -0,0 +1,267 @@ +imports: + root: ../__package__.yml +service: + auth: false + base-path: '' + endpoints: + list: + path: /api/organizations/{id}/permissions + method: GET + auth: true + docs: >- + List all organization-level permission overrides for a given + organization. + source: + openapi: openapi/openapi.yaml + path-parameters: + id: integer + display-name: List organization permission overrides + request: + name: PermissionsListRequest + query-parameters: + ordering: + type: optional + docs: Which field to use when ordering the results. + response: + docs: '' + type: list + examples: + - path-parameters: + id: 1 + response: + body: + - default_role: default_role + id: 1 + label: label + options: options + organization: 1 + permission: permission + roles: + - OW + tooltip: tooltip + audiences: + - public + create: + path: /api/organizations/{id}/permissions + method: POST + auth: true + docs: >- + Create a new organization-level permission override for a given + organization. + source: + openapi: openapi/openapi.yaml + path-parameters: + id: integer + display-name: Create organization permission override + request: + body: root.OrganizationPermissionRequest + content-type: application/json + response: + docs: '' + type: root.OrganizationPermission + errors: + - root.BadRequestError + - root.ForbiddenError + examples: + - path-parameters: + id: 1 + request: + permission: permission + response: + body: + default_role: default_role + id: 1 + label: label + options: options + organization: 1 + permission: permission + roles: + - OW + tooltip: tooltip + audiences: + - public + get_options: + path: /api/organizations/{id}/permissions/options + method: GET + auth: true + docs: >- + Retrieve the list of configurable permission options (label, tooltip, + default role and allowed roles). + source: + openapi: openapi/openapi.yaml + path-parameters: + id: integer + display-name: Get configurable permissions options + request: + name: PermissionsGetOptionsRequest + query-parameters: + ordering: + type: optional + docs: Which field to use when ordering the results. + response: + docs: '' + type: list + examples: + - path-parameters: + id: 1 + response: + body: + - default: OW + label: label + options: + - OW + permission: permission + tooltip: tooltip + audiences: + - public + get: + path: /api/organizations/{id}/permissions/{permission} + method: GET + auth: true + source: + openapi: openapi/openapi.yaml + path-parameters: + id: integer + permission: string + display-name: Retrieve organization permission override + response: + docs: '' + type: root.OrganizationPermission + errors: + - root.ForbiddenError + - root.NotFoundError + examples: + - path-parameters: + id: 1 + permission: permission + response: + body: + default_role: default_role + id: 1 + label: label + options: options + organization: 1 + permission: permission + roles: + - OW + tooltip: tooltip + audiences: + - public + replace: + path: /api/organizations/{id}/permissions/{permission} + method: PUT + auth: true + docs: >- + Replace the organization-level permission override for a given + permission key. + source: + openapi: openapi/openapi.yaml + path-parameters: + id: + type: integer + docs: A unique integer value identifying this organization. + permission: + type: string + docs: Permission key to update within the organization. + display-name: Replace organization permission override + request: + body: root.OrganizationPermissionRequest + content-type: application/json + response: + docs: '' + type: root.OrganizationPermission + errors: + - root.BadRequestError + - root.ForbiddenError + - root.NotFoundError + examples: + - path-parameters: + id: 1 + permission: permission + request: + permission: permission + response: + body: + default_role: default_role + id: 1 + label: label + options: options + organization: 1 + permission: permission + roles: + - OW + tooltip: tooltip + audiences: + - public + delete: + path: /api/organizations/{id}/permissions/{permission} + method: DELETE + auth: true + source: + openapi: openapi/openapi.yaml + path-parameters: + id: integer + permission: string + display-name: Delete organization permission override + errors: + - root.ForbiddenError + - root.NotFoundError + examples: + - path-parameters: + id: 1 + permission: permission + audiences: + - public + update: + path: /api/organizations/{id}/permissions/{permission} + method: PATCH + auth: true + docs: >- + Partially update the organization-level permission override for a given + permission key. + source: + openapi: openapi/openapi.yaml + path-parameters: + id: integer + permission: string + display-name: Update organization permission override + request: + name: PatchedOrganizationPermissionRequest + body: + properties: + permission: + type: optional + name: patchedOrganizationPermissionRequestPermission + roles: + type: optional> + docs: >- + Explicit roles that have this permission within the + organization. + content-type: application/json + response: + docs: '' + type: root.OrganizationPermission + errors: + - root.BadRequestError + - root.ForbiddenError + - root.NotFoundError + examples: + - path-parameters: + id: 1 + permission: permission + request: {} + response: + body: + default_role: default_role + id: 1 + label: label + options: options + organization: 1 + permission: permission + roles: + - OW + tooltip: tooltip + audiences: + - public + source: + openapi: openapi/openapi.yaml diff --git a/.mock/openapi/openapi.yaml b/.mock/openapi/openapi.yaml index 06d0222d8..d0d1b6b2d 100644 --- a/.mock/openapi/openapi.yaml +++ b/.mock/openapi/openapi.yaml @@ -5449,6 +5449,296 @@ paths: - organizations - members x-fern-sdk-method-name: get + /api/organizations/{id}/permissions: + get: + description: List all organization-level permission overrides for a given organization. + operationId: api_organizations_permissions_list + parameters: + - in: path + name: id + required: true + schema: + type: integer + - description: Which field to use when ordering the results. + in: query + name: ordering + required: false + schema: + type: string + responses: + '200': + content: + application/json: + schema: + items: + $ref: '#/components/schemas/OrganizationPermission' + type: array + description: '' + security: + - Token: [] + summary: List organization permission overrides + tags: + - Organizations + - Permissions + x-fern-audiences: + - public + x-fern-sdk-group-name: + - organizations + - permissions + x-fern-sdk-method-name: list + post: + description: Create a new organization-level permission override for a given organization. + operationId: api_organizations_permissions_create + parameters: + - in: path + name: id + required: true + schema: + type: integer + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/OrganizationPermissionRequest' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/OrganizationPermissionRequest' + multipart/form-data: + schema: + $ref: '#/components/schemas/OrganizationPermissionRequest' + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/OrganizationPermission' + description: '' + '400': + description: Bad Request + '403': + description: Permission Denied + security: + - Token: [] + summary: Create organization permission override + tags: + - Organizations + - Permissions + x-fern-audiences: + - public + x-fern-sdk-group-name: + - organizations + - permissions + x-fern-sdk-method-name: create + /api/organizations/{id}/permissions/options: + get: + description: Retrieve the list of configurable permission options (label, tooltip, default role and allowed roles). + operationId: api_organizations_permissions_options_list + parameters: + - in: path + name: id + required: true + schema: + type: integer + - description: Which field to use when ordering the results. + in: query + name: ordering + required: false + schema: + type: string + responses: + '200': + content: + application/json: + schema: + items: + $ref: '#/components/schemas/ConfigurablePermissionOption' + type: array + description: '' + security: + - Token: [] + summary: Get configurable permissions options + tags: + - Organizations + - Permissions + x-fern-audiences: + - public + x-fern-sdk-group-name: + - organizations + - permissions + x-fern-sdk-method-name: get_options + /api/organizations/{id}/permissions/{permission}: + delete: + operationId: api_organizations_permissions_destroy + parameters: + - in: path + name: id + required: true + schema: + type: integer + - in: path + name: permission + required: true + schema: + type: string + responses: + '204': + description: Deleted + '403': + description: Permission Denied + '404': + description: Permission not found for organization + security: + - Token: [] + summary: Delete organization permission override + tags: + - Organizations + - Permissions + x-fern-audiences: + - public + x-fern-sdk-group-name: + - organizations + - permissions + x-fern-sdk-method-name: delete + get: + operationId: api_organizations_permissions_retrieve + parameters: + - in: path + name: id + required: true + schema: + type: integer + - in: path + name: permission + required: true + schema: + type: string + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/OrganizationPermission' + description: '' + '403': + description: Permission Denied + '404': + description: Permission not found for organization + security: + - Token: [] + summary: Retrieve organization permission override + tags: + - Organizations + - Permissions + x-fern-audiences: + - public + x-fern-sdk-group-name: + - organizations + - permissions + x-fern-sdk-method-name: get + patch: + description: Partially update the organization-level permission override for a given permission key. + operationId: api_organizations_permissions_partial_update + parameters: + - in: path + name: id + required: true + schema: + type: integer + - in: path + name: permission + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedOrganizationPermissionRequest' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/PatchedOrganizationPermissionRequest' + multipart/form-data: + schema: + $ref: '#/components/schemas/PatchedOrganizationPermissionRequest' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/OrganizationPermission' + description: '' + '400': + description: Bad Request + '403': + description: Permission Denied + '404': + description: Permission not found for organization + security: + - Token: [] + summary: Update organization permission override + tags: + - Organizations + - Permissions + x-fern-audiences: + - public + x-fern-sdk-group-name: + - organizations + - permissions + x-fern-sdk-method-name: update + put: + description: Replace the organization-level permission override for a given permission key. + operationId: api_organizations_permissions_update + parameters: + - description: A unique integer value identifying this organization. + in: path + name: id + required: true + schema: + type: integer + - description: Permission key to update within the organization. + in: path + name: permission + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/OrganizationPermissionRequest' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/OrganizationPermissionRequest' + multipart/form-data: + schema: + $ref: '#/components/schemas/OrganizationPermissionRequest' + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/OrganizationPermission' + description: '' + '400': + description: Bad Request + '403': + description: Permission Denied + '404': + description: Permission not found for organization + security: + - Token: [] + summary: Replace organization permission override + tags: + - Organizations + - Permissions + x-fern-audiences: + - public + x-fern-sdk-group-name: + - organizations + - permissions + x-fern-sdk-method-name: replace /api/organizations/{id}/set-default-role: patch: description: Update the default role for members of a specific organization. @@ -19275,6 +19565,27 @@ components: - task - updated_at type: object + ConfigurablePermissionOption: + properties: + default: + nullable: true + oneOf: + - $ref: '#/components/schemas/Role9e7Enum' + - $ref: '#/components/schemas/NullEnum' + label: + type: string + options: + items: + $ref: '#/components/schemas/Role9e7Enum' + type: array + permission: + type: string + tooltip: + type: string + required: + - options + - permission + type: object ConvertedFormat: properties: export_type: @@ -19921,7 +20232,7 @@ components: type: string default_role: allOf: - - $ref: '#/components/schemas/DefaultRoleEnum' + - $ref: '#/components/schemas/Role9e7Enum' description: |- Default membership role for invited users @@ -19963,24 +20274,6 @@ components: required: - organization type: object - DefaultRoleEnum: - description: |- - * `OW` - Owner - * `AD` - Administrator - * `MA` - Manager - * `RE` - Reviewer - * `AN` - Annotator - * `DI` - Deactivated - * `NO` - Not Activated - enum: - - OW - - AD - - MA - - RE - - AN - - DI - - 'NO' - type: string EditionEnum: description: |- * `Community` - Community @@ -21800,7 +22093,7 @@ components: type: string default_role: allOf: - - $ref: '#/components/schemas/DefaultRoleEnum' + - $ref: '#/components/schemas/Role9e7Enum' description: |- Default membership role for invited users @@ -24893,6 +25186,57 @@ components: required: - role type: object + OrganizationPermission: + properties: + default_role: + readOnly: true + type: string + id: + readOnly: true + type: integer + label: + readOnly: true + type: string + options: + readOnly: true + type: string + organization: + readOnly: true + type: integer + permission: + maxLength: 255 + type: string + roles: + description: Explicit roles that have this permission within the organization. + items: + $ref: '#/components/schemas/Role9e7Enum' + type: array + tooltip: + readOnly: true + type: string + required: + - default_role + - id + - label + - options + - organization + - permission + - tooltip + type: object + OrganizationPermissionRequest: + properties: + permission: + maxLength: 255 + minLength: 1 + type: string + roles: + description: Explicit roles that have this permission within the organization. + items: + $ref: '#/components/schemas/Role9e7Enum' + type: array + required: + - permission + type: object PaginatedAllRolesProjectListList: properties: count: @@ -25774,7 +26118,7 @@ components: type: string default_role: allOf: - - $ref: '#/components/schemas/DefaultRoleEnum' + - $ref: '#/components/schemas/Role9e7Enum' description: |- Default membership role for invited users @@ -26749,6 +27093,18 @@ components: user_id: type: integer type: object + PatchedOrganizationPermissionRequest: + properties: + permission: + maxLength: 255 + minLength: 1 + type: string + roles: + description: Explicit roles that have this permission within the organization. + items: + $ref: '#/components/schemas/Role9e7Enum' + type: array + type: object PatchedPauseRequest: description: |- A ModelSerializer that takes additional arguments for diff --git a/reference.md b/reference.md index 3e8f32da5..3ef779234 100644 --- a/reference.md +++ b/reference.md @@ -4987,7 +4987,7 @@ Set the minimum user role that can edit custom scripts in the UI.
-**default_role:** `typing.Optional[DefaultRoleEnum]` +**default_role:** `typing.Optional[Role9E7Enum]` Default membership role for invited users @@ -26472,6 +26472,571 @@ client.organizations.members.delete(
+ + + + +## Organizations Permissions +
client.organizations.permissions.list(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +List all organization-level permission overrides for a given organization. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from label_studio_sdk import LabelStudio + +client = LabelStudio( + api_key="YOUR_API_KEY", +) +client.organizations.permissions.list( + id=1, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `int` + +
+
+ +
+
+ +**ordering:** `typing.Optional[str]` — Which field to use when ordering the results. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.organizations.permissions.create(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Create a new organization-level permission override for a given organization. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from label_studio_sdk import LabelStudio + +client = LabelStudio( + api_key="YOUR_API_KEY", +) +client.organizations.permissions.create( + id=1, + permission="permission", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `int` + +
+
+ +
+
+ +**permission:** `str` + +
+
+ +
+
+ +**roles:** `typing.Optional[typing.Sequence[Role9E7Enum]]` — Explicit roles that have this permission within the organization. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.organizations.permissions.get_options(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Retrieve the list of configurable permission options (label, tooltip, default role and allowed roles). +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from label_studio_sdk import LabelStudio + +client = LabelStudio( + api_key="YOUR_API_KEY", +) +client.organizations.permissions.get_options( + id=1, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `int` + +
+
+ +
+
+ +**ordering:** `typing.Optional[str]` — Which field to use when ordering the results. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.organizations.permissions.get(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from label_studio_sdk import LabelStudio + +client = LabelStudio( + api_key="YOUR_API_KEY", +) +client.organizations.permissions.get( + id=1, + permission="permission", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `int` + +
+
+ +
+
+ +**permission:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.organizations.permissions.replace(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Replace the organization-level permission override for a given permission key. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from label_studio_sdk import LabelStudio + +client = LabelStudio( + api_key="YOUR_API_KEY", +) +client.organizations.permissions.replace( + id=1, + permission_="permission", + permission="permission", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `int` — A unique integer value identifying this organization. + +
+
+ +
+
+ +**permission_:** `str` — Permission key to update within the organization. + +
+
+ +
+
+ +**permission:** `str` + +
+
+ +
+
+ +**roles:** `typing.Optional[typing.Sequence[Role9E7Enum]]` — Explicit roles that have this permission within the organization. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.organizations.permissions.delete(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from label_studio_sdk import LabelStudio + +client = LabelStudio( + api_key="YOUR_API_KEY", +) +client.organizations.permissions.delete( + id=1, + permission="permission", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `int` + +
+
+ +
+
+ +**permission:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.organizations.permissions.update(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Partially update the organization-level permission override for a given permission key. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from label_studio_sdk import LabelStudio + +client = LabelStudio( + api_key="YOUR_API_KEY", +) +client.organizations.permissions.update( + id=1, + permission="permission", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `int` + +
+
+ +
+
+ +**permission:** `str` + +
+
+ +
+
+ +**patched_organization_permission_request_permission:** `typing.Optional[str]` + +
+
+ +
+
+ +**roles:** `typing.Optional[typing.Sequence[Role9E7Enum]]` — Explicit roles that have this permission within the organization. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ +
diff --git a/src/label_studio_sdk/__init__.py b/src/label_studio_sdk/__init__.py index 85aebcb1c..4fe4748d8 100644 --- a/src/label_studio_sdk/__init__.py +++ b/src/label_studio_sdk/__init__.py @@ -42,13 +42,14 @@ Comment, CommentRequest, CommentSerializerWithExpandedUser, + ConfigurablePermissionOption, + ConfigurablePermissionOptionDefault, ConvertedFormat, ConvertedFormatRequest, CountLimit, CustomScriptsEditableByEnum, DefaultRole, DefaultRoleCustomScriptsEditableBy, - DefaultRoleEnum, EditionEnum, Export, FileUpload, @@ -138,6 +139,8 @@ OrganizationInvite, OrganizationMember, OrganizationMembership, + OrganizationPermission, + OrganizationPermissionRequest, PaginatedAllRolesProjectListList, PaginatedAnnotationHistoryList, PaginatedLseOrganizationMemberListList, @@ -399,13 +402,14 @@ "Comment", "CommentRequest", "CommentSerializerWithExpandedUser", + "ConfigurablePermissionOption", + "ConfigurablePermissionOptionDefault", "ConvertedFormat", "ConvertedFormatRequest", "CountLimit", "CustomScriptsEditableByEnum", "DefaultRole", "DefaultRoleCustomScriptsEditableBy", - "DefaultRoleEnum", "EditionEnum", "Export", "ExportStorageListTypesResponseItem", @@ -509,6 +513,8 @@ "OrganizationInvite", "OrganizationMember", "OrganizationMembership", + "OrganizationPermission", + "OrganizationPermissionRequest", "PaginatedAllRolesProjectListList", "PaginatedAnnotationHistoryList", "PaginatedLseOrganizationMemberListList", diff --git a/src/label_studio_sdk/organizations/__init__.py b/src/label_studio_sdk/organizations/__init__.py index faea629fa..8451c0fe6 100644 --- a/src/label_studio_sdk/organizations/__init__.py +++ b/src/label_studio_sdk/organizations/__init__.py @@ -1,6 +1,6 @@ # This file was auto-generated by Fern from our API Definition. from .types import PatchedDefaultRoleRequestCustomScriptsEditableBy -from . import invites, members +from . import invites, members, permissions -__all__ = ["PatchedDefaultRoleRequestCustomScriptsEditableBy", "invites", "members"] +__all__ = ["PatchedDefaultRoleRequestCustomScriptsEditableBy", "invites", "members", "permissions"] diff --git a/src/label_studio_sdk/organizations/client.py b/src/label_studio_sdk/organizations/client.py index eaebaacbc..8117bc87d 100644 --- a/src/label_studio_sdk/organizations/client.py +++ b/src/label_studio_sdk/organizations/client.py @@ -4,6 +4,7 @@ from ..core.client_wrapper import SyncClientWrapper from .invites.client import InvitesClient from .members.client import MembersClient +from .permissions.client import PermissionsClient from ..core.request_options import RequestOptions from ..types.organization_invite import OrganizationInvite from ..core.unchecked_base_model import construct_type @@ -19,12 +20,13 @@ from .types.patched_default_role_request_custom_scripts_editable_by import ( PatchedDefaultRoleRequestCustomScriptsEditableBy, ) -from ..types.default_role_enum import DefaultRoleEnum +from ..types.role9e7enum import Role9E7Enum from ..types.default_role import DefaultRole from ..core.serialization import convert_and_respect_annotation_metadata from ..core.client_wrapper import AsyncClientWrapper from .invites.client import AsyncInvitesClient from .members.client import AsyncMembersClient +from .permissions.client import AsyncPermissionsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -35,6 +37,7 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper self.invites = InvitesClient(client_wrapper=self._client_wrapper) self.members = MembersClient(client_wrapper=self._client_wrapper) + self.permissions = PermissionsClient(client_wrapper=self._client_wrapper) def reset_token(self, *, request_options: typing.Optional[RequestOptions] = None) -> OrganizationInvite: """ @@ -306,7 +309,7 @@ def update_default_role( annotator_reviewer_firewall_enabled_at: typing.Optional[dt.datetime] = OMIT, custom_scripts_editable_by: typing.Optional[PatchedDefaultRoleRequestCustomScriptsEditableBy] = OMIT, custom_scripts_enabled_at: typing.Optional[dt.datetime] = OMIT, - default_role: typing.Optional[DefaultRoleEnum] = OMIT, + default_role: typing.Optional[Role9E7Enum] = OMIT, email_notification_settings: typing.Optional[typing.Optional[typing.Any]] = OMIT, embed_domains: typing.Optional[typing.Optional[typing.Any]] = OMIT, embed_settings: typing.Optional[typing.Optional[typing.Any]] = OMIT, @@ -336,7 +339,7 @@ def update_default_role( custom_scripts_enabled_at : typing.Optional[dt.datetime] Set to current time to enabled custom scripts for this organization. Can only be enabled if no organization members are active members of any other organizations; otherwise an error will be raised. If this occurs, contact the LEAP team for assistance with enabling custom scripts. - default_role : typing.Optional[DefaultRoleEnum] + default_role : typing.Optional[Role9E7Enum] Default membership role for invited users * `OW` - Owner @@ -433,6 +436,7 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper self.invites = AsyncInvitesClient(client_wrapper=self._client_wrapper) self.members = AsyncMembersClient(client_wrapper=self._client_wrapper) + self.permissions = AsyncPermissionsClient(client_wrapper=self._client_wrapper) async def reset_token(self, *, request_options: typing.Optional[RequestOptions] = None) -> OrganizationInvite: """ @@ -736,7 +740,7 @@ async def update_default_role( annotator_reviewer_firewall_enabled_at: typing.Optional[dt.datetime] = OMIT, custom_scripts_editable_by: typing.Optional[PatchedDefaultRoleRequestCustomScriptsEditableBy] = OMIT, custom_scripts_enabled_at: typing.Optional[dt.datetime] = OMIT, - default_role: typing.Optional[DefaultRoleEnum] = OMIT, + default_role: typing.Optional[Role9E7Enum] = OMIT, email_notification_settings: typing.Optional[typing.Optional[typing.Any]] = OMIT, embed_domains: typing.Optional[typing.Optional[typing.Any]] = OMIT, embed_settings: typing.Optional[typing.Optional[typing.Any]] = OMIT, @@ -766,7 +770,7 @@ async def update_default_role( custom_scripts_enabled_at : typing.Optional[dt.datetime] Set to current time to enabled custom scripts for this organization. Can only be enabled if no organization members are active members of any other organizations; otherwise an error will be raised. If this occurs, contact the LEAP team for assistance with enabling custom scripts. - default_role : typing.Optional[DefaultRoleEnum] + default_role : typing.Optional[Role9E7Enum] Default membership role for invited users * `OW` - Owner diff --git a/src/label_studio_sdk/organizations/permissions/__init__.py b/src/label_studio_sdk/organizations/permissions/__init__.py new file mode 100644 index 000000000..f3ea2659b --- /dev/null +++ b/src/label_studio_sdk/organizations/permissions/__init__.py @@ -0,0 +1,2 @@ +# This file was auto-generated by Fern from our API Definition. + diff --git a/src/label_studio_sdk/organizations/permissions/client.py b/src/label_studio_sdk/organizations/permissions/client.py new file mode 100644 index 000000000..6a356d5bb --- /dev/null +++ b/src/label_studio_sdk/organizations/permissions/client.py @@ -0,0 +1,1129 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from ...core.client_wrapper import SyncClientWrapper +from ...core.request_options import RequestOptions +from ...types.organization_permission import OrganizationPermission +from ...core.jsonable_encoder import jsonable_encoder +from ...core.unchecked_base_model import construct_type +from json.decoder import JSONDecodeError +from ...core.api_error import ApiError +from ...types.role9e7enum import Role9E7Enum +from ...errors.bad_request_error import BadRequestError +from ...errors.forbidden_error import ForbiddenError +from ...types.configurable_permission_option import ConfigurablePermissionOption +from ...errors.not_found_error import NotFoundError +from ...core.client_wrapper import AsyncClientWrapper + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class PermissionsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, id: int, *, ordering: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None + ) -> typing.List[OrganizationPermission]: + """ + List all organization-level permission overrides for a given organization. + + Parameters + ---------- + id : int + + ordering : typing.Optional[str] + Which field to use when ordering the results. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[OrganizationPermission] + + + Examples + -------- + from label_studio_sdk import LabelStudio + + client = LabelStudio( + api_key="YOUR_API_KEY", + ) + client.organizations.permissions.list( + id=1, + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"api/organizations/{jsonable_encoder(id)}/permissions", + method="GET", + params={ + "ordering": ordering, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + typing.List[OrganizationPermission], + construct_type( + type_=typing.List[OrganizationPermission], # type: ignore + object_=_response.json(), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def create( + self, + id: int, + *, + permission: str, + roles: typing.Optional[typing.Sequence[Role9E7Enum]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> OrganizationPermission: + """ + Create a new organization-level permission override for a given organization. + + Parameters + ---------- + id : int + + permission : str + + roles : typing.Optional[typing.Sequence[Role9E7Enum]] + Explicit roles that have this permission within the organization. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + OrganizationPermission + + + Examples + -------- + from label_studio_sdk import LabelStudio + + client = LabelStudio( + api_key="YOUR_API_KEY", + ) + client.organizations.permissions.create( + id=1, + permission="permission", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"api/organizations/{jsonable_encoder(id)}/permissions", + method="POST", + json={ + "permission": permission, + "roles": roles, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + OrganizationPermission, + construct_type( + type_=OrganizationPermission, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_options( + self, id: int, *, ordering: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None + ) -> typing.List[ConfigurablePermissionOption]: + """ + Retrieve the list of configurable permission options (label, tooltip, default role and allowed roles). + + Parameters + ---------- + id : int + + ordering : typing.Optional[str] + Which field to use when ordering the results. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[ConfigurablePermissionOption] + + + Examples + -------- + from label_studio_sdk import LabelStudio + + client = LabelStudio( + api_key="YOUR_API_KEY", + ) + client.organizations.permissions.get_options( + id=1, + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"api/organizations/{jsonable_encoder(id)}/permissions/options", + method="GET", + params={ + "ordering": ordering, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + typing.List[ConfigurablePermissionOption], + construct_type( + type_=typing.List[ConfigurablePermissionOption], # type: ignore + object_=_response.json(), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get( + self, id: int, permission: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> OrganizationPermission: + """ + Parameters + ---------- + id : int + + permission : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + OrganizationPermission + + + Examples + -------- + from label_studio_sdk import LabelStudio + + client = LabelStudio( + api_key="YOUR_API_KEY", + ) + client.organizations.permissions.get( + id=1, + permission="permission", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"api/organizations/{jsonable_encoder(id)}/permissions/{jsonable_encoder(permission)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + OrganizationPermission, + construct_type( + type_=OrganizationPermission, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def replace( + self, + id: int, + permission_: str, + *, + permission: str, + roles: typing.Optional[typing.Sequence[Role9E7Enum]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> OrganizationPermission: + """ + Replace the organization-level permission override for a given permission key. + + Parameters + ---------- + id : int + A unique integer value identifying this organization. + + permission_ : str + Permission key to update within the organization. + + permission : str + + roles : typing.Optional[typing.Sequence[Role9E7Enum]] + Explicit roles that have this permission within the organization. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + OrganizationPermission + + + Examples + -------- + from label_studio_sdk import LabelStudio + + client = LabelStudio( + api_key="YOUR_API_KEY", + ) + client.organizations.permissions.replace( + id=1, + permission_="permission", + permission="permission", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"api/organizations/{jsonable_encoder(id)}/permissions/{jsonable_encoder(permission_)}", + method="PUT", + json={ + "permission": permission, + "roles": roles, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + OrganizationPermission, + construct_type( + type_=OrganizationPermission, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def delete(self, id: int, permission: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: + """ + Parameters + ---------- + id : int + + permission : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from label_studio_sdk import LabelStudio + + client = LabelStudio( + api_key="YOUR_API_KEY", + ) + client.organizations.permissions.delete( + id=1, + permission="permission", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"api/organizations/{jsonable_encoder(id)}/permissions/{jsonable_encoder(permission)}", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def update( + self, + id: int, + permission: str, + *, + patched_organization_permission_request_permission: typing.Optional[str] = OMIT, + roles: typing.Optional[typing.Sequence[Role9E7Enum]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> OrganizationPermission: + """ + Partially update the organization-level permission override for a given permission key. + + Parameters + ---------- + id : int + + permission : str + + patched_organization_permission_request_permission : typing.Optional[str] + + roles : typing.Optional[typing.Sequence[Role9E7Enum]] + Explicit roles that have this permission within the organization. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + OrganizationPermission + + + Examples + -------- + from label_studio_sdk import LabelStudio + + client = LabelStudio( + api_key="YOUR_API_KEY", + ) + client.organizations.permissions.update( + id=1, + permission="permission", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"api/organizations/{jsonable_encoder(id)}/permissions/{jsonable_encoder(permission)}", + method="PATCH", + json={ + "permission": patched_organization_permission_request_permission, + "roles": roles, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + OrganizationPermission, + construct_type( + type_=OrganizationPermission, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncPermissionsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, id: int, *, ordering: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None + ) -> typing.List[OrganizationPermission]: + """ + List all organization-level permission overrides for a given organization. + + Parameters + ---------- + id : int + + ordering : typing.Optional[str] + Which field to use when ordering the results. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[OrganizationPermission] + + + Examples + -------- + import asyncio + + from label_studio_sdk import AsyncLabelStudio + + client = AsyncLabelStudio( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.organizations.permissions.list( + id=1, + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"api/organizations/{jsonable_encoder(id)}/permissions", + method="GET", + params={ + "ordering": ordering, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + typing.List[OrganizationPermission], + construct_type( + type_=typing.List[OrganizationPermission], # type: ignore + object_=_response.json(), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def create( + self, + id: int, + *, + permission: str, + roles: typing.Optional[typing.Sequence[Role9E7Enum]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> OrganizationPermission: + """ + Create a new organization-level permission override for a given organization. + + Parameters + ---------- + id : int + + permission : str + + roles : typing.Optional[typing.Sequence[Role9E7Enum]] + Explicit roles that have this permission within the organization. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + OrganizationPermission + + + Examples + -------- + import asyncio + + from label_studio_sdk import AsyncLabelStudio + + client = AsyncLabelStudio( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.organizations.permissions.create( + id=1, + permission="permission", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"api/organizations/{jsonable_encoder(id)}/permissions", + method="POST", + json={ + "permission": permission, + "roles": roles, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + OrganizationPermission, + construct_type( + type_=OrganizationPermission, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_options( + self, id: int, *, ordering: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None + ) -> typing.List[ConfigurablePermissionOption]: + """ + Retrieve the list of configurable permission options (label, tooltip, default role and allowed roles). + + Parameters + ---------- + id : int + + ordering : typing.Optional[str] + Which field to use when ordering the results. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[ConfigurablePermissionOption] + + + Examples + -------- + import asyncio + + from label_studio_sdk import AsyncLabelStudio + + client = AsyncLabelStudio( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.organizations.permissions.get_options( + id=1, + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"api/organizations/{jsonable_encoder(id)}/permissions/options", + method="GET", + params={ + "ordering": ordering, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + typing.List[ConfigurablePermissionOption], + construct_type( + type_=typing.List[ConfigurablePermissionOption], # type: ignore + object_=_response.json(), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get( + self, id: int, permission: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> OrganizationPermission: + """ + Parameters + ---------- + id : int + + permission : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + OrganizationPermission + + + Examples + -------- + import asyncio + + from label_studio_sdk import AsyncLabelStudio + + client = AsyncLabelStudio( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.organizations.permissions.get( + id=1, + permission="permission", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"api/organizations/{jsonable_encoder(id)}/permissions/{jsonable_encoder(permission)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + OrganizationPermission, + construct_type( + type_=OrganizationPermission, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def replace( + self, + id: int, + permission_: str, + *, + permission: str, + roles: typing.Optional[typing.Sequence[Role9E7Enum]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> OrganizationPermission: + """ + Replace the organization-level permission override for a given permission key. + + Parameters + ---------- + id : int + A unique integer value identifying this organization. + + permission_ : str + Permission key to update within the organization. + + permission : str + + roles : typing.Optional[typing.Sequence[Role9E7Enum]] + Explicit roles that have this permission within the organization. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + OrganizationPermission + + + Examples + -------- + import asyncio + + from label_studio_sdk import AsyncLabelStudio + + client = AsyncLabelStudio( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.organizations.permissions.replace( + id=1, + permission_="permission", + permission="permission", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"api/organizations/{jsonable_encoder(id)}/permissions/{jsonable_encoder(permission_)}", + method="PUT", + json={ + "permission": permission, + "roles": roles, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + OrganizationPermission, + construct_type( + type_=OrganizationPermission, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def delete( + self, id: int, permission: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + Parameters + ---------- + id : int + + permission : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from label_studio_sdk import AsyncLabelStudio + + client = AsyncLabelStudio( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.organizations.permissions.delete( + id=1, + permission="permission", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"api/organizations/{jsonable_encoder(id)}/permissions/{jsonable_encoder(permission)}", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def update( + self, + id: int, + permission: str, + *, + patched_organization_permission_request_permission: typing.Optional[str] = OMIT, + roles: typing.Optional[typing.Sequence[Role9E7Enum]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> OrganizationPermission: + """ + Partially update the organization-level permission override for a given permission key. + + Parameters + ---------- + id : int + + permission : str + + patched_organization_permission_request_permission : typing.Optional[str] + + roles : typing.Optional[typing.Sequence[Role9E7Enum]] + Explicit roles that have this permission within the organization. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + OrganizationPermission + + + Examples + -------- + import asyncio + + from label_studio_sdk import AsyncLabelStudio + + client = AsyncLabelStudio( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.organizations.permissions.update( + id=1, + permission="permission", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"api/organizations/{jsonable_encoder(id)}/permissions/{jsonable_encoder(permission)}", + method="PATCH", + json={ + "permission": patched_organization_permission_request_permission, + "roles": roles, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + OrganizationPermission, + construct_type( + type_=OrganizationPermission, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + typing.Optional[typing.Any], + construct_type( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/label_studio_sdk/types/__init__.py b/src/label_studio_sdk/types/__init__.py index 916608b86..f539e9f73 100644 --- a/src/label_studio_sdk/types/__init__.py +++ b/src/label_studio_sdk/types/__init__.py @@ -43,13 +43,14 @@ from .comment import Comment from .comment_request import CommentRequest from .comment_serializer_with_expanded_user import CommentSerializerWithExpandedUser +from .configurable_permission_option import ConfigurablePermissionOption +from .configurable_permission_option_default import ConfigurablePermissionOptionDefault from .converted_format import ConvertedFormat from .converted_format_request import ConvertedFormatRequest from .count_limit import CountLimit from .custom_scripts_editable_by_enum import CustomScriptsEditableByEnum from .default_role import DefaultRole from .default_role_custom_scripts_editable_by import DefaultRoleCustomScriptsEditableBy -from .default_role_enum import DefaultRoleEnum from .edition_enum import EditionEnum from .export import Export from .file_upload import FileUpload @@ -139,6 +140,8 @@ from .organization_invite import OrganizationInvite from .organization_member import OrganizationMember from .organization_membership import OrganizationMembership +from .organization_permission import OrganizationPermission +from .organization_permission_request import OrganizationPermissionRequest from .paginated_all_roles_project_list_list import PaginatedAllRolesProjectListList from .paginated_annotation_history_list import PaginatedAnnotationHistoryList from .paginated_lse_organization_member_list_list import PaginatedLseOrganizationMemberListList @@ -265,13 +268,14 @@ "Comment", "CommentRequest", "CommentSerializerWithExpandedUser", + "ConfigurablePermissionOption", + "ConfigurablePermissionOptionDefault", "ConvertedFormat", "ConvertedFormatRequest", "CountLimit", "CustomScriptsEditableByEnum", "DefaultRole", "DefaultRoleCustomScriptsEditableBy", - "DefaultRoleEnum", "EditionEnum", "Export", "FileUpload", @@ -361,6 +365,8 @@ "OrganizationInvite", "OrganizationMember", "OrganizationMembership", + "OrganizationPermission", + "OrganizationPermissionRequest", "PaginatedAllRolesProjectListList", "PaginatedAnnotationHistoryList", "PaginatedLseOrganizationMemberListList", diff --git a/src/label_studio_sdk/types/configurable_permission_option.py b/src/label_studio_sdk/types/configurable_permission_option.py new file mode 100644 index 000000000..db9475f8e --- /dev/null +++ b/src/label_studio_sdk/types/configurable_permission_option.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.unchecked_base_model import UncheckedBaseModel +import typing +from .configurable_permission_option_default import ConfigurablePermissionOptionDefault +from .role9e7enum import Role9E7Enum +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class ConfigurablePermissionOption(UncheckedBaseModel): + default: typing.Optional[ConfigurablePermissionOptionDefault] = None + label: typing.Optional[str] = None + options: typing.List[Role9E7Enum] + permission: str + tooltip: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/label_studio_sdk/types/configurable_permission_option_default.py b/src/label_studio_sdk/types/configurable_permission_option_default.py new file mode 100644 index 000000000..ee182d47a --- /dev/null +++ b/src/label_studio_sdk/types/configurable_permission_option_default.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from .role9e7enum import Role9E7Enum +from .null_enum import NullEnum + +ConfigurablePermissionOptionDefault = typing.Union[Role9E7Enum, NullEnum] diff --git a/src/label_studio_sdk/types/default_role.py b/src/label_studio_sdk/types/default_role.py index fe031178a..0ad8ea3ac 100644 --- a/src/label_studio_sdk/types/default_role.py +++ b/src/label_studio_sdk/types/default_role.py @@ -5,7 +5,7 @@ import datetime as dt import pydantic from .default_role_custom_scripts_editable_by import DefaultRoleCustomScriptsEditableBy -from .default_role_enum import DefaultRoleEnum +from .role9e7enum import Role9E7Enum from ..core.pydantic_utilities import IS_PYDANTIC_V2 @@ -28,7 +28,7 @@ class DefaultRole(UncheckedBaseModel): Set to current time to enabled custom scripts for this organization. Can only be enabled if no organization members are active members of any other organizations; otherwise an error will be raised. If this occurs, contact the LEAP team for assistance with enabling custom scripts. """ - default_role: typing.Optional[DefaultRoleEnum] = pydantic.Field(default=None) + default_role: typing.Optional[Role9E7Enum] = pydantic.Field(default=None) """ Default membership role for invited users diff --git a/src/label_studio_sdk/types/default_role_enum.py b/src/label_studio_sdk/types/default_role_enum.py deleted file mode 100644 index 37e91a29c..000000000 --- a/src/label_studio_sdk/types/default_role_enum.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -DefaultRoleEnum = typing.Union[typing.Literal["OW", "AD", "MA", "RE", "AN", "DI", "NO"], typing.Any] diff --git a/src/label_studio_sdk/types/lse_organization.py b/src/label_studio_sdk/types/lse_organization.py index cfd182c7c..511a055e9 100644 --- a/src/label_studio_sdk/types/lse_organization.py +++ b/src/label_studio_sdk/types/lse_organization.py @@ -6,7 +6,7 @@ import typing from .lse_organization_custom_scripts_editable_by import LseOrganizationCustomScriptsEditableBy import pydantic -from .default_role_enum import DefaultRoleEnum +from .role9e7enum import Role9E7Enum from ..core.pydantic_utilities import IS_PYDANTIC_V2 @@ -22,7 +22,7 @@ class LseOrganization(UncheckedBaseModel): """ custom_scripts_enabled: str - default_role: typing.Optional[DefaultRoleEnum] = pydantic.Field(default=None) + default_role: typing.Optional[Role9E7Enum] = pydantic.Field(default=None) """ Default membership role for invited users diff --git a/src/label_studio_sdk/types/organization_permission.py b/src/label_studio_sdk/types/organization_permission.py new file mode 100644 index 000000000..e9ca4c416 --- /dev/null +++ b/src/label_studio_sdk/types/organization_permission.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.unchecked_base_model import UncheckedBaseModel +import typing +from .role9e7enum import Role9E7Enum +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class OrganizationPermission(UncheckedBaseModel): + default_role: str + id: int + label: str + options: str + organization: int + permission: str + roles: typing.Optional[typing.List[Role9E7Enum]] = pydantic.Field(default=None) + """ + Explicit roles that have this permission within the organization. + """ + + tooltip: str + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/label_studio_sdk/types/organization_permission_request.py b/src/label_studio_sdk/types/organization_permission_request.py new file mode 100644 index 000000000..6f333242a --- /dev/null +++ b/src/label_studio_sdk/types/organization_permission_request.py @@ -0,0 +1,24 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.unchecked_base_model import UncheckedBaseModel +import typing +from .role9e7enum import Role9E7Enum +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class OrganizationPermissionRequest(UncheckedBaseModel): + permission: str + roles: typing.Optional[typing.List[Role9E7Enum]] = pydantic.Field(default=None) + """ + Explicit roles that have this permission within the organization. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/tests/organizations/test_permissions.py b/tests/organizations/test_permissions.py new file mode 100644 index 000000000..813475542 --- /dev/null +++ b/tests/organizations/test_permissions.py @@ -0,0 +1,183 @@ +# This file was auto-generated by Fern from our API Definition. + +from label_studio_sdk import LabelStudio +from label_studio_sdk import AsyncLabelStudio +import typing +from ..utilities import validate_response + + +async def test_list_(client: LabelStudio, async_client: AsyncLabelStudio) -> None: + expected_response: typing.Any = [ + { + "default_role": "default_role", + "id": 1, + "label": "label", + "options": "options", + "organization": 1, + "permission": "permission", + "roles": ["OW"], + "tooltip": "tooltip", + } + ] + expected_types: typing.Tuple[typing.Any, typing.Any] = ( + "list", + { + 0: { + "default_role": None, + "id": "integer", + "label": None, + "options": None, + "organization": "integer", + "permission": None, + "roles": ("list", {0: None}), + "tooltip": None, + } + }, + ) + response = client.organizations.permissions.list(id=1) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.organizations.permissions.list(id=1) + validate_response(async_response, expected_response, expected_types) + + +async def test_create(client: LabelStudio, async_client: AsyncLabelStudio) -> None: + expected_response: typing.Any = { + "default_role": "default_role", + "id": 1, + "label": "label", + "options": "options", + "organization": 1, + "permission": "permission", + "roles": ["OW"], + "tooltip": "tooltip", + } + expected_types: typing.Any = { + "default_role": None, + "id": "integer", + "label": None, + "options": None, + "organization": "integer", + "permission": None, + "roles": ("list", {0: None}), + "tooltip": None, + } + response = client.organizations.permissions.create(id=1, permission="permission") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.organizations.permissions.create(id=1, permission="permission") + validate_response(async_response, expected_response, expected_types) + + +async def test_get_options(client: LabelStudio, async_client: AsyncLabelStudio) -> None: + expected_response: typing.Any = [ + {"default": "OW", "label": "label", "options": ["OW"], "permission": "permission", "tooltip": "tooltip"} + ] + expected_types: typing.Tuple[typing.Any, typing.Any] = ( + "list", + {0: {"default": None, "label": None, "options": ("list", {0: None}), "permission": None, "tooltip": None}}, + ) + response = client.organizations.permissions.get_options(id=1) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.organizations.permissions.get_options(id=1) + validate_response(async_response, expected_response, expected_types) + + +async def test_get(client: LabelStudio, async_client: AsyncLabelStudio) -> None: + expected_response: typing.Any = { + "default_role": "default_role", + "id": 1, + "label": "label", + "options": "options", + "organization": 1, + "permission": "permission", + "roles": ["OW"], + "tooltip": "tooltip", + } + expected_types: typing.Any = { + "default_role": None, + "id": "integer", + "label": None, + "options": None, + "organization": "integer", + "permission": None, + "roles": ("list", {0: None}), + "tooltip": None, + } + response = client.organizations.permissions.get(id=1, permission="permission") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.organizations.permissions.get(id=1, permission="permission") + validate_response(async_response, expected_response, expected_types) + + +async def test_replace(client: LabelStudio, async_client: AsyncLabelStudio) -> None: + expected_response: typing.Any = { + "default_role": "default_role", + "id": 1, + "label": "label", + "options": "options", + "organization": 1, + "permission": "permission", + "roles": ["OW"], + "tooltip": "tooltip", + } + expected_types: typing.Any = { + "default_role": None, + "id": "integer", + "label": None, + "options": None, + "organization": "integer", + "permission": None, + "roles": ("list", {0: None}), + "tooltip": None, + } + response = client.organizations.permissions.replace(id=1, permission_="permission", permission="permission") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.organizations.permissions.replace( + id=1, permission_="permission", permission="permission" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_delete(client: LabelStudio, async_client: AsyncLabelStudio) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.organizations.permissions.delete(id=1, permission="permission") # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.organizations.permissions.delete(id=1, permission="permission") # type: ignore[func-returns-value] + is None + ) + + +async def test_update(client: LabelStudio, async_client: AsyncLabelStudio) -> None: + expected_response: typing.Any = { + "default_role": "default_role", + "id": 1, + "label": "label", + "options": "options", + "organization": 1, + "permission": "permission", + "roles": ["OW"], + "tooltip": "tooltip", + } + expected_types: typing.Any = { + "default_role": None, + "id": "integer", + "label": None, + "options": None, + "organization": "integer", + "permission": None, + "roles": ("list", {0: None}), + "tooltip": None, + } + response = client.organizations.permissions.update(id=1, permission="permission") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.organizations.permissions.update(id=1, permission="permission") + validate_response(async_response, expected_response, expected_types)