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 pdp api and list role assignment api from pdp #63

Closed
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
Empty file added permit/pdp_api/__init__.py
Empty file.
67 changes: 67 additions & 0 deletions permit/pdp_api/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from typing import Callable, TypeVar

from permit import PermitConfig, PYDANTIC_VERSION

from permit.api.base import SimpleHttpClient


if PYDANTIC_VERSION < (2, 0):
from pydantic import BaseModel, Extra, Field, parse_obj_as
else:
from pydantic.v1 import BaseModel, Extra, Field, parse_obj_as # type: ignore




T = TypeVar("T", bound=Callable)
TModel = TypeVar("TModel", bound=BaseModel)
TData = TypeVar("TData", bound=BaseModel)




def pagination_params(page: int, per_page: int) -> dict:
return {"page": page, "per_page": per_page}


class ClientConfig(BaseModel):
class Config:
extra = Extra.allow

base_url: str = Field(
...,
description="base url that will prefix the url fragment sent via the client",
)
headers: dict = Field(..., description="http headers sent to the API server")




class BasePdpPermitApi:
"""
The base class for Permit APIs.
"""

def __init__(self, config: PermitConfig):
"""
Initialize a BasePermitApi.

Args:
config: The Permit SDK configuration.
"""
self.config = config

def _build_http_client(self, endpoint_url: str = "", **kwargs):
client_config = ClientConfig(
base_url=f"{self.config.pdp}",
headers={
"Content-Type": "application/json",
"Authorization": f"bearer {self.config.token}",
},
)
client_config_dict = client_config.dict()
client_config_dict.update(kwargs)
return SimpleHttpClient(
client_config_dict,
base_url=endpoint_url,
)
29 changes: 29 additions & 0 deletions permit/pdp_api/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# generated by datamodel-codegen:
# filename: open.json (local PDP)
# timestamp: 2024-04-09T15:36:45+00:00

from __future__ import annotations

from typing import Optional

from ..utils.pydantic_version import PYDANTIC_VERSION

if PYDANTIC_VERSION < (2, 0):
from pydantic import BaseModel, Field
else:
from pydantic.v1 import BaseModel, Field # type: ignore



class RoleAssignment(BaseModel):
user: str = Field(..., description='the user the role is assigned to', title='User')
role: str = Field(..., description='the role that is assigned', title='Role')
tenant: str = Field(
..., description='the tenant the role is associated with', title='Tenant'
)
resource_instance: Optional[str] = Field(
None,
description='the resource instance the role is associated with',
title='Resource Instance',
)

40 changes: 40 additions & 0 deletions permit/pdp_api/pdp_api_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from ..config import PermitConfig
from .condition_set_rules import ConditionSetRulesApi
from .condition_sets import ConditionSetsApi
from .deprecated import DeprecatedApi
from .environments import EnvironmentsApi
from .projects import ProjectsApi
from .relationship_tuples import RelationshipTuplesApi
from .resource_action_groups import ResourceActionGroupsApi
from .resource_actions import ResourceActionsApi
from .resource_attributes import ResourceAttributesApi
from .resource_instances import ResourceInstancesApi
from .resource_relations import ResourceRelationsApi
from .resource_roles import ResourceRolesApi
from .resources import ResourcesApi
from .role_assignments import RoleAssignmentsApi
from .roles import RolesApi
from .tenants import TenantsApi
from .users import UsersApi


class PermitApiClient(DeprecatedApi):
def __init__(self, config: PermitConfig):
"""
Constructs a new instance of the PdpApiClient class with the specified SDK configuration.

Args:
config: The configuration for the Permit SDK.
"""
self._config = config
self._headers = {
"Content-Type": "application/json",
"Authorization": f"bearer {self._config.token}",
}
self._base_url = self._config.pdp

self._role_assignments = RoleAssignmentsApi(config)

@property
def role_assignments(self) -> RoleAssignmentsApi:
return self._role_assignments
70 changes: 70 additions & 0 deletions permit/pdp_api/role_assignments.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from typing import List, Optional

from permit.api.base import SimpleHttpClient

from permit import PYDANTIC_VERSION
from permit.pdp_api.base import BasePdpPermitApi, pagination_params
from permit.pdp_api.models import RoleAssignment

if PYDANTIC_VERSION < (2, 0):
from pydantic import validate_arguments
else:
from pydantic.v1 import validate_arguments # type: ignore




class RoleAssignmentsApi(BasePdpPermitApi):
@property
def __role_assignments(self) -> SimpleHttpClient:
return self._build_http_client(
"/local/role_assignments"
)


@validate_arguments
async def list(
self,
user_key: Optional[str] = None,
role_key: Optional[str] = None,
tenant_key: Optional[str] = None,
resource_key: Optional[str] = None,
resource_instance_key: Optional[str] = None,
page: int = 1,
per_page: int = 100,
) -> List[RoleAssignment]:
"""
Retrieves a list of role assignments based on the specified filters.

Args:
user_key: optional user filter, will only return role assignments granted to this user.
role_key: optional role filter, will only return role assignments granting this role.
tenant_key: optional tenant filter, will only return role assignments granted in that tenant.
resource_key: optional resource type filter, will only return role assignments granted on that resource type.
resource_instance_key: optional resource instance filter, will only return role assignments granted on that resource instance.
page: The page number to fetch (default: 1).
per_page: How many items to fetch per page (default: 100).

Returns:
an array of role assignments.

Raises:
PermitApiError: If the API returns an error HTTP status code.
PermitContextError: If the configured ApiContext does not match the required endpoint context.
"""
params = pagination_params(page, per_page)
if user_key is not None:
params.update(dict(user=user_key))
if role_key is not None:
params.update(dict(role=role_key))
if tenant_key is not None:
params.update(dict(tenant=tenant_key))
if resource_key is not None:
params.update(dict(resource=resource_key))
if resource_instance_key is not None:
params.update(dict(resource_instance=resource_instance_key))
return await self.__role_assignments.get(
"",
model=List[RoleAssignment],
params=params,
)
3 changes: 2 additions & 1 deletion permit/permit.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from .config import PermitConfig
from .enforcement.enforcer import Action, CheckQuery, Enforcer, Resource, User
from .logger import configure_logger
from .pdp_api.base import BasePdpPermitApi
from .utils.context import Context


Expand All @@ -21,7 +22,7 @@ def __init__(self, config: Optional[PermitConfig] = None, **options):
self._enforcer = Enforcer(self._config)
self._api = PermitApiClient(self._config)
self._elements = ElementsApi(self._config)

self. _pdp_api = BasePdpPermitApi(self._config)
logger.debug(
"Permit SDK initialized with config:\n${}",
json.dumps(self._config.dict(exclude={"api_context"})),
Expand Down
Loading