keyrunes-python-sdk 0.0.1__tar.gz → 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: keyrunes-python-sdk
3
- Version: 0.0.1
3
+ Version: 0.1.0
4
4
  Summary: Python SDK for Keyrunes Authorization System
5
5
  License: AGPL
6
6
  Keywords: keyrunes,authorization,rbac,abac,security,authentication,permissions
@@ -1,5 +1,6 @@
1
1
  """Keyrunes API Client."""
2
2
 
3
+ import os
3
4
  from typing import Any, Dict, List, Optional
4
5
  from urllib.parse import urljoin
5
6
 
@@ -38,6 +39,8 @@ class KeyrunesClient:
38
39
  base_url: Base URL of the Keyrunes API
39
40
  (e.g., "https://keyrunes.example.com")
40
41
  api_key: Optional API key for authentication
42
+ organization_key: Optional Organization Key (required for v0.2.0+)
43
+ If not provided, looks for KEYRUNES_ORG_KEY env var
41
44
  timeout: Request timeout in seconds (default: 30)
42
45
 
43
46
  Example:
@@ -50,11 +53,16 @@ class KeyrunesClient:
50
53
  self,
51
54
  base_url: str,
52
55
  api_key: Optional[str] = None,
56
+ organization_key: Optional[str] = None,
53
57
  timeout: int = 30,
54
58
  ) -> None:
55
59
  """Initialize Keyrunes client."""
56
60
  self.base_url = base_url.rstrip("/")
57
61
  self.api_key = api_key
62
+ # Prioritize explicit argument, then env var
63
+ self.organization_key = organization_key or os.getenv(
64
+ "KEYRUNES_ORG_KEY"
65
+ )
58
66
  self.timeout = timeout
59
67
  self._token: Optional[str] = None
60
68
  self._token_data: Optional[Dict[str, Any]] = None
@@ -63,6 +71,11 @@ class KeyrunesClient:
63
71
  if api_key:
64
72
  self._client.headers.update({"X-API-Key": api_key})
65
73
 
74
+ if self.organization_key:
75
+ self._client.headers.update(
76
+ {"X-Organization-Key": self.organization_key}
77
+ )
78
+
66
79
  def _make_request(
67
80
  self,
68
81
  method: str,
@@ -190,13 +203,16 @@ class KeyrunesClient:
190
203
  user=user_model,
191
204
  )
192
205
 
193
- def login(self, username: str, password: str) -> Token:
206
+ def login(
207
+ self, username: str, password: str, namespace: str = "public"
208
+ ) -> Token:
194
209
  """
195
210
  Authenticate user and obtain access token.
196
211
 
197
212
  Args:
198
213
  username: Username or email
199
214
  password: User password
215
+ namespace: User namespace (default: "public")
200
216
 
201
217
  Returns:
202
218
  Token object containing access token and user info
@@ -206,10 +222,14 @@ class KeyrunesClient:
206
222
 
207
223
  Example:
208
224
  >>> client = KeyrunesClient("https://keyrunes.example.com")
209
- >>> token = client.login("user@example.com", "password123")
225
+ >>> token = client.login(
226
+ ... "user@example.com", "password123", namespace="public"
227
+ ... )
210
228
  >>> client.set_token(token.access_token)
211
229
  """
212
- credentials = LoginCredentials(identity=username, password=password)
230
+ credentials = LoginCredentials(
231
+ identity=username, password=password, namespace=namespace
232
+ )
213
233
  response = self._make_request(
214
234
  "POST",
215
235
  "/api/login",
@@ -228,7 +248,12 @@ class KeyrunesClient:
228
248
  return token
229
249
 
230
250
  def register_user(
231
- self, username: str, email: str, password: str, **attributes: Any
251
+ self,
252
+ username: str,
253
+ email: str,
254
+ password: str,
255
+ namespace: str = "public",
256
+ **attributes: Any,
232
257
  ) -> User:
233
258
  """
234
259
  Register a new user.
@@ -237,6 +262,7 @@ class KeyrunesClient:
237
262
  username: Username (3-50 characters)
238
263
  email: User email address
239
264
  password: Password (minimum 8 characters)
265
+ namespace: User namespace (default: "public")
240
266
  **attributes: Additional user attributes
241
267
 
242
268
  Returns:
@@ -251,6 +277,7 @@ class KeyrunesClient:
251
277
  ... username="newuser",
252
278
  ... email="newuser@example.com",
253
279
  ... password="securepass123",
280
+ ... namespace="my-app",
254
281
  ... department="Engineering"
255
282
  ... )
256
283
  """
@@ -258,6 +285,7 @@ class KeyrunesClient:
258
285
  username=username,
259
286
  email=email,
260
287
  password=password,
288
+ namespace=namespace,
261
289
  attributes=attributes,
262
290
  )
263
291
  response = self._make_request(
@@ -283,6 +311,7 @@ class KeyrunesClient:
283
311
  email: str,
284
312
  password: str,
285
313
  admin_key: str,
314
+ namespace: str = "public",
286
315
  **attributes: Any,
287
316
  ) -> User:
288
317
  """
@@ -293,6 +322,7 @@ class KeyrunesClient:
293
322
  email: Admin email address
294
323
  password: Password (minimum 8 characters)
295
324
  admin_key: Admin registration key
325
+ namespace: User namespace (default: "public")
296
326
  **attributes: Additional user attributes
297
327
 
298
328
  Returns:
@@ -316,6 +346,7 @@ class KeyrunesClient:
316
346
  email=email,
317
347
  password=password,
318
348
  admin_key=admin_key,
349
+ namespace=namespace,
319
350
  attributes=attributes,
320
351
  )
321
352
  response = self._make_request(
@@ -69,6 +69,7 @@ class _GlobalConfig:
69
69
  self,
70
70
  base_url: str,
71
71
  api_key: Optional[str] = None,
72
+ organization_key: Optional[str] = None,
72
73
  timeout: int = 30,
73
74
  ) -> KeyrunesClient:
74
75
  """
@@ -77,6 +78,7 @@ class _GlobalConfig:
77
78
  Args:
78
79
  base_url: Base URL of the Keyrunes API
79
80
  api_key: Optional API key for authentication
81
+ organization_key: Optional Organization Key (required for v0.2.0+)
80
82
  timeout: Request timeout in seconds (default: 30)
81
83
 
82
84
  Returns:
@@ -91,7 +93,10 @@ class _GlobalConfig:
91
93
  ... )
92
94
  """
93
95
  client = KeyrunesClient(
94
- base_url=base_url, api_key=api_key, timeout=timeout
96
+ base_url=base_url,
97
+ api_key=api_key,
98
+ organization_key=organization_key,
99
+ timeout=timeout,
95
100
  )
96
101
  self.set_client(client)
97
102
  return client
@@ -133,6 +138,7 @@ def get_config() -> _GlobalConfig:
133
138
  def configure(
134
139
  base_url: str,
135
140
  api_key: Optional[str] = None,
141
+ organization_key: Optional[str] = None,
136
142
  timeout: int = 30,
137
143
  ) -> KeyrunesClient:
138
144
  """
@@ -145,6 +151,7 @@ def configure(
145
151
  Args:
146
152
  base_url: Base URL of the Keyrunes API
147
153
  api_key: Optional API key for authentication
154
+ organization_key: Optional Organization Key (required for v0.2.0+)
148
155
  timeout: Request timeout in seconds (default: 30)
149
156
 
150
157
  Returns:
@@ -167,6 +174,7 @@ def configure(
167
174
  return _config.configure(
168
175
  base_url=base_url,
169
176
  api_key=api_key,
177
+ organization_key=organization_key,
170
178
  timeout=timeout,
171
179
  )
172
180
 
@@ -64,6 +64,7 @@ class UserRegistration(BaseModel):
64
64
  )
65
65
  email: EmailStr = Field(..., description="User email")
66
66
  password: str = Field(..., min_length=8, description="Password")
67
+ namespace: str = Field("default", description="User namespace")
67
68
  attributes: Dict[str, Any] = Field(
68
69
  default_factory=dict, description="Additional attributes"
69
70
  )
@@ -80,11 +81,14 @@ class LoginCredentials(BaseModel):
80
81
 
81
82
  identity: str = Field(..., description="Username or email")
82
83
  password: str = Field(..., description="Password")
84
+ namespace: str = Field("default", description="User namespace")
83
85
 
84
86
  @classmethod
85
- def from_username(cls, username: str, password: str) -> "LoginCredentials":
87
+ def from_username(
88
+ cls, username: str, password: str, namespace: str = "default"
89
+ ) -> "LoginCredentials":
86
90
  """Create from username parameter (for backward compatibility)."""
87
- return cls(identity=username, password=password)
91
+ return cls(identity=username, password=password, namespace=namespace)
88
92
 
89
93
 
90
94
  class GroupCheck(BaseModel):
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "keyrunes-python-sdk"
3
- version = "0.0.1"
3
+ version = "0.1.0"
4
4
  description = "Python SDK for Keyrunes Authorization System"
5
5
  authors = ["keyrunes <contact@singularjourney.host>"]
6
6
  maintainers = ["jonatasoli <contact@jonatasoli.dev>"]
@@ -40,12 +40,14 @@ pytest-cov = "^4.1.0"
40
40
  pytest-mock = "^3.11.1"
41
41
  factory-boy = "^3.3.0"
42
42
  faker = "^19.0.0"
43
- black = "^23.7.0"
43
+ black = "^25.12.0"
44
44
  isort = "^5.12.0"
45
45
  flake8 = "^6.1.0"
46
46
  mypy = "^1.5.0"
47
47
  taskipy = "^1.12.0"
48
48
  towncrier = "^25.8.0"
49
+ pre-commit = "^4.5.1"
50
+ safety = "^3.7.0"
49
51
 
50
52
  [build-system]
51
53
  requires = ["poetry-core>=1.0.0"]