Source code for pinecone.models.admin.role_binding

"""Role binding models for the Admin API."""

from __future__ import annotations

from collections.abc import Iterator
from enum import Enum
from typing import Any

from msgspec import Struct

from pinecone._internal.validation import require_one_of
from pinecone.errors.exceptions import ValidationError
from pinecone.models._mixin import StructDictMixin, _struct_to_dict_recursive
from pinecone.models.admin.pagination import PaginationResponse


[docs] class PrincipalType(str, Enum): """The kind of principal that receives permissions from a role binding. Possible values: ``user``, ``service_account``, ``api_key``, ``invite``. Examples: >>> from pinecone.models.admin.role_binding import PrincipalType >>> PrincipalType.SERVICE_ACCOUNT == "service_account" True """ USER = "user" SERVICE_ACCOUNT = "service_account" API_KEY = "api_key" INVITE = "invite"
[docs] class ResourceType(str, Enum): """The kind of resource scope a role binding applies to. Possible values: ``organization``, ``project``. Examples: >>> from pinecone.models.admin.role_binding import ResourceType >>> ResourceType.PROJECT == "project" True """ ORGANIZATION = "organization" PROJECT = "project"
[docs] class RoleName(str, Enum): """A role that can be assigned to a principal at a resource scope. Organization-scoped roles: ``OrgOwner``, ``OrgManager``, ``OrgMember``, ``OrgBillingAdmin``. Project-scoped roles: ``ProjectOwner``, ``ProjectManager``, ``ProjectMember``, ``ProjectEditor``, ``ProjectViewer``, ``ControlPlaneEditor``, ``ControlPlaneViewer``, ``DataPlaneEditor``, ``DataPlaneViewer``. Examples: >>> from pinecone.models.admin.role_binding import RoleName >>> RoleName.DATA_PLANE_EDITOR == "DataPlaneEditor" True """ ORG_OWNER = "OrgOwner" ORG_MANAGER = "OrgManager" ORG_MEMBER = "OrgMember" ORG_BILLING_ADMIN = "OrgBillingAdmin" PROJECT_OWNER = "ProjectOwner" PROJECT_MANAGER = "ProjectManager" PROJECT_MEMBER = "ProjectMember" PROJECT_EDITOR = "ProjectEditor" PROJECT_VIEWER = "ProjectViewer" CONTROL_PLANE_EDITOR = "ControlPlaneEditor" CONTROL_PLANE_VIEWER = "ControlPlaneViewer" DATA_PLANE_EDITOR = "DataPlaneEditor" DATA_PLANE_VIEWER = "DataPlaneViewer"
_VALID_RESOURCE_TYPES = [r.value for r in ResourceType] _VALID_ROLE_NAMES = [r.value for r in RoleName] def _as_str(value: str) -> str: return value.value if isinstance(value, Enum) else value
[docs] class RoleBindingModel(StructDictMixin, Struct, kw_only=True): """Response model for a role binding: a ``role`` granted to a principal at a scope. ``principal_type``, ``resource_type``, and ``role`` are typed as :class:`str` rather than as enums so values the server adds after this SDK release surface as their raw strings instead of raising. Compare against :class:`PrincipalType`, :class:`ResourceType`, and :class:`RoleName` directly — they are ``str`` values. Attributes: id (str): Unique identifier (UUID) for the role binding. principal_type (str): One of the :class:`PrincipalType` values. principal_id (str): The principal's UUID. resource_type (str): One of the :class:`ResourceType` values. resource_id (str): The organization or project the binding is scoped to. role (str): One of the :class:`RoleName` values. created_at (str): RFC 3339 timestamp for when the binding was created. Examples: >>> from pinecone.models.admin.role_binding import RoleBindingModel, RoleName >>> binding = RoleBindingModel( ... id="9a8e3528-b9c0-4358-84ce-84c28e91b566", ... principal_type="service_account", ... principal_id="f8a3b2c1-4d5e-6f7a-8b9c-0d1e2f3a4b5c", ... resource_type="project", ... resource_id="a2f7dddb-1597-4eff-9f71-535fde243f58", ... role="DataPlaneEditor", ... created_at="2026-04-10T15:23:00Z", ... ) >>> binding.role == RoleName.DATA_PLANE_EDITOR True """ id: str principal_type: str principal_id: str resource_type: str resource_id: str role: str created_at: str
[docs] class RoleBindingInput(StructDictMixin, Struct, kw_only=True, omit_defaults=True): """A role to grant when creating an invite or a service account. Unlike the response models, this is an input the SDK sends, so ``resource_type`` and ``role`` are validated on construction against the values this SDK release knows about. ``resource_type`` selects the binding scope. For ``organization`` scope, omit ``resource_id`` — the binding applies to the organization inferred from the request context. For ``project`` scope, ``resource_id`` is required and must be the project UUID. Attributes: resource_type (str): One of the :class:`ResourceType` values. role (str): One of the :class:`RoleName` values. resource_id (str | None): The project UUID for ``project`` scope; leave unset for ``organization`` scope. Raises: :exc:`~pinecone.errors.PineconeValueError`: If ``resource_type`` or ``role`` is not a recognized value, or if ``resource_type`` is ``project`` and ``resource_id`` is missing or empty. Examples: >>> from pinecone.models.admin.role_binding import ( ... ResourceType, ... RoleBindingInput, ... RoleName, ... ) >>> RoleBindingInput( ... resource_type=ResourceType.ORGANIZATION, role=RoleName.ORG_MEMBER ... ).to_dict() {'resource_type': 'organization', 'role': 'OrgMember', 'resource_id': None} Project-scoped bindings need the project UUID: >>> RoleBindingInput( ... resource_type="project", ... role="ProjectViewer", ... resource_id="a2f7dddb-1597-4eff-9f71-535fde243f58", ... ).resource_id 'a2f7dddb-1597-4eff-9f71-535fde243f58' """ resource_type: str role: str resource_id: str | None = None def __post_init__(self) -> None: self.resource_type = _as_str(self.resource_type) self.role = _as_str(self.role) require_one_of("resource_type", self.resource_type, _VALID_RESOURCE_TYPES) require_one_of("role", self.role, _VALID_ROLE_NAMES) if self.resource_type == ResourceType.PROJECT.value and not self.resource_id: raise ValidationError( "resource_id is required when resource_type is 'project' " "(it must be the project UUID)" )
[docs] class RoleBindingList(Struct, kw_only=True): """A page of role bindings, plus the cursor for the next page. Attributes: data (list[RoleBindingModel]): The role bindings on this page. pagination (PaginationResponse | None): Cursor envelope for the next page, or ``None`` on the final page. Examples: >>> from pinecone.models.admin.role_binding import RoleBindingList, RoleBindingModel >>> bindings = RoleBindingList( ... data=[ ... RoleBindingModel( ... id="rb1", ... principal_type="user", ... principal_id="u1", ... resource_type="organization", ... resource_id="org-1", ... role="OrgMember", ... created_at="2026-04-10T15:23:00Z", ... ) ... ] ... ) >>> bindings.roles() ['OrgMember'] """ data: list[RoleBindingModel] = [] pagination: PaginationResponse | None = None def __iter__(self) -> Iterator[RoleBindingModel]: return iter(self.data) def __len__(self) -> int: return len(self.data) def __getitem__(self, index: int) -> RoleBindingModel: return self.data[index] @property def pagination_token(self) -> str | None: """Opaque cursor for the next page, or ``None`` if this is the last page.""" return self.pagination.next if self.pagination is not None else None @property def has_more(self) -> bool: """``True`` when the server supplied a cursor for a further page.""" return self.pagination_token is not None
[docs] def roles(self) -> list[str]: """Return the role names on this page, in order.""" return [binding.role for binding in self.data]
[docs] def to_dict(self) -> dict[str, Any]: """Return this page as a serializable dict with ``data`` and ``pagination`` keys.""" return { "data": [_struct_to_dict_recursive(binding) for binding in self.data], "pagination": _struct_to_dict_recursive(self.pagination), }
def __repr__(self) -> str: summaries = ", ".join( f"<principal_type={b.principal_type!r}, principal_id={b.principal_id!r}, " f"role={b.role!r}>" for b in self.data ) return f"RoleBindingList([{summaries}], has_more={self.has_more!r})"