-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathpermit.py
More file actions
156 lines (124 loc) · 4.78 KB
/
permit.py
File metadata and controls
156 lines (124 loc) · 4.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import json
from typing import Optional
from loguru import logger
from .api.api_client import PermitApiClient
from .api.elements import ElementsApi
from .config import PermitConfig
from .enforcement.enforcer import Action, CheckQuery, Enforcer, Resource, User
from .logger import configure_logger
from .pdp_api.pdp_api import PdpApi
from .utils.context import Context
class Permit:
def __init__(self, config: Optional[PermitConfig] = None, **options):
self._config: PermitConfig = (
config if config is not None else PermitConfig(**options)
)
configure_logger(self._config)
self._enforcer = Enforcer(self._config)
self._api = PermitApiClient(self._config)
self._elements = ElementsApi(self._config)
self._pdp_api = PdpApi(self._config)
logger.debug(
"Permit SDK initialized with config:\n${}",
json.dumps(self._config.dict(exclude={"api_context"})),
)
@property
def config(self):
"""
Access the SDK configuration using this property.
Once the SDK is initialized, the configuration is read-only.
Usage example:
permit = Permit(config)
pdp_url = permit.config.pdp
"""
return self._config.copy()
@property
def api(self) -> PermitApiClient:
"""
Access the Permit REST API using this property.
Usage example:
permit = Permit(token="<YOUR_API_KEY>")
await permit.api.roles.create(...)
"""
return self._api
@property
def elements(self) -> ElementsApi:
"""
Access the Permit Elements API using this property.
Usage example:
permit = Permit(token="<YOUR_API_KEY>")
await permit.elements.loginAs(user, tenant)
"""
return self._elements
@property
def pdp(self) -> PdpApi:
"""
Access the Permit PDP API using this property.
Usage example:
permit = Permit(token
await permit.pdp.list_role_assignments()
"""
return self._pdp_api
async def bulk_check(
self,
checks: list[CheckQuery],
context: Context = {},
) -> list[bool]:
"""
Checks if a user is authorized to perform an action on a list of resources within the specified context.
Args:
checks: A list of check queries, each query contain user, action, and resource.
context: The context object representing the context in which the action is performed. Defaults to None.
Returns:
list[bool]: A list of booleans indicating whether the user is authorized for each resource.
Raises:
PermitConnectionError: If an error occurs while sending the authorization request to the PDP.
Examples:
# Bulk query of multiple check conventions
await permit.bulk_check([
{
"user": user,
"action": "close",
"resource": {type: "issue", key: "1234"},
},
{
"user": {key: "user"},
"action": "close",
"resource": "issue:1235",
},
{
"user": "user_a",
"action": "close",
"resource": "issue",
},
])
"""
return await self._enforcer.bulk_check(checks, context)
async def check(
self,
user: User,
action: Action,
resource: Resource,
context: Context = {},
) -> bool:
"""
Checks if a user is authorized to perform an action on a resource within the specified context.
Args:
user: The user object representing the user.
action: The action to be performed on the resource.
resource: The resource object representing the resource.
context: The context object representing the context in which the action is performed. Defaults to None.
Returns:
bool: True if the user is authorized, False otherwise.
Raises:
PermitConnectionError: If an error occurs while sending the authorization request to the PDP.
Examples:
# can the user close any issue?
await permit.check(user, 'close', 'issue')
# can the user close any issue who's id is 1234?
await permit.check(user, 'close', 'issue:1234')
# can the user close (any) issues belonging to the 't1' tenant?
# (in a multi tenant application)
await permit.check(user, 'close', {'type': 'issue', 'tenant': 't1'})
"""
return await self._enforcer.check(user, action, resource, context)