vortex-python-sdk 0.0.3__py3-none-any.whl → 0.0.5__py3-none-any.whl
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.
- {vortex_python_sdk-0.0.3.dist-info → vortex_python_sdk-0.0.5.dist-info}/METADATA +1 -1
- vortex_python_sdk-0.0.5.dist-info/RECORD +9 -0
- vortex_sdk/__init__.py +10 -10
- vortex_sdk/types.py +21 -12
- vortex_sdk/vortex.py +121 -118
- vortex_python_sdk-0.0.3.dist-info/RECORD +0 -9
- {vortex_python_sdk-0.0.3.dist-info → vortex_python_sdk-0.0.5.dist-info}/WHEEL +0 -0
- {vortex_python_sdk-0.0.3.dist-info → vortex_python_sdk-0.0.5.dist-info}/licenses/LICENSE +0 -0
- {vortex_python_sdk-0.0.3.dist-info → vortex_python_sdk-0.0.5.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
vortex_python_sdk-0.0.5.dist-info/licenses/LICENSE,sha256=VndlWxbL4-w3YDf2yE5gJscj4zVXF0qlSq0LDtay3lo,1074
|
|
2
|
+
vortex_sdk/__init__.py,sha256=_39nOXzridOgUJS7MrGv6jt097egE44yVCm6ZkDbFMs,711
|
|
3
|
+
vortex_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
vortex_sdk/types.py,sha256=2YAqEjR5ttZjB1_JfOQWJuPekbc0F-vGlqu8t-jIeho,3344
|
|
5
|
+
vortex_sdk/vortex.py,sha256=qvKWMcd1ISePtV3q8N8-BwBxRdbLQ7sG34nCnLtbpKc,15033
|
|
6
|
+
vortex_python_sdk-0.0.5.dist-info/METADATA,sha256=k_glnwxag_W43RzWI6BJ6wU8NhpjR8GsLcXaK48wutk,6237
|
|
7
|
+
vortex_python_sdk-0.0.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
8
|
+
vortex_python_sdk-0.0.5.dist-info/top_level.txt,sha256=xFDlEcXIIi_sBhkse0YfMnSdg2IlaYUd0oP2UCDc_Y0,11
|
|
9
|
+
vortex_python_sdk-0.0.5.dist-info/RECORD,,
|
vortex_sdk/__init__.py
CHANGED
|
@@ -4,21 +4,21 @@ Vortex Python SDK
|
|
|
4
4
|
A Python SDK for Vortex invitation management and JWT generation.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from .vortex import Vortex
|
|
8
7
|
from .types import (
|
|
8
|
+
AcceptInvitationsRequest,
|
|
9
|
+
ApiResponse,
|
|
9
10
|
AuthenticatedUser,
|
|
10
|
-
|
|
11
|
-
IdentifierInput,
|
|
11
|
+
CreateInvitationRequest,
|
|
12
12
|
GroupInput,
|
|
13
|
-
|
|
13
|
+
IdentifierInput,
|
|
14
14
|
Invitation,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
VortexApiError
|
|
15
|
+
InvitationTarget,
|
|
16
|
+
JwtPayload,
|
|
17
|
+
VortexApiError,
|
|
19
18
|
)
|
|
19
|
+
from .vortex import Vortex
|
|
20
20
|
|
|
21
|
-
__version__ = "0.0.
|
|
21
|
+
__version__ = "0.0.5"
|
|
22
22
|
__author__ = "TeamVortexSoftware"
|
|
23
23
|
__email__ = "support@vortexsoftware.com"
|
|
24
24
|
|
|
@@ -34,4 +34,4 @@ __all__ = [
|
|
|
34
34
|
"AcceptInvitationsRequest",
|
|
35
35
|
"ApiResponse",
|
|
36
36
|
"VortexApiError",
|
|
37
|
-
]
|
|
37
|
+
]
|
vortex_sdk/types.py
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
|
-
from typing import Dict, List, Optional, Union
|
|
1
|
+
from typing import Any, Dict, List, Literal, Optional, Union
|
|
2
|
+
|
|
2
3
|
from pydantic import BaseModel, Field
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
class IdentifierInput(BaseModel):
|
|
6
7
|
"""Identifier structure for JWT generation"""
|
|
8
|
+
|
|
7
9
|
type: Literal["email", "sms"]
|
|
8
10
|
value: str
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
class GroupInput(BaseModel):
|
|
12
14
|
"""Group structure for JWT generation (input)"""
|
|
15
|
+
|
|
13
16
|
type: str
|
|
14
17
|
id: Optional[str] = None # Legacy field (deprecated, use groupId)
|
|
15
|
-
groupId: Optional[str] = Field(
|
|
18
|
+
groupId: Optional[str] = Field(
|
|
19
|
+
None, alias="group_id", serialization_alias="groupId"
|
|
20
|
+
) # Preferred: Customer's group ID
|
|
16
21
|
name: str
|
|
17
22
|
|
|
18
23
|
class Config:
|
|
@@ -24,12 +29,13 @@ class InvitationGroup(BaseModel):
|
|
|
24
29
|
Invitation group from API responses
|
|
25
30
|
This matches the MemberGroups table structure from the API
|
|
26
31
|
"""
|
|
32
|
+
|
|
27
33
|
id: str # Vortex internal UUID
|
|
28
|
-
account_id: str # Vortex account ID
|
|
29
|
-
group_id: str # Customer's group ID
|
|
34
|
+
account_id: str = Field(alias="accountId") # Vortex account ID
|
|
35
|
+
group_id: str = Field(alias="groupId") # Customer's group ID
|
|
30
36
|
type: str # Group type (e.g., "workspace", "team")
|
|
31
37
|
name: str # Group name
|
|
32
|
-
created_at: str # ISO 8601 timestamp
|
|
38
|
+
created_at: str = Field(alias="createdAt") # ISO 8601 timestamp
|
|
33
39
|
|
|
34
40
|
class Config:
|
|
35
41
|
# Allow both snake_case (Python) and camelCase (JSON) field names
|
|
@@ -41,7 +47,7 @@ class InvitationGroup(BaseModel):
|
|
|
41
47
|
"groupId": "workspace-123",
|
|
42
48
|
"type": "workspace",
|
|
43
49
|
"name": "My Workspace",
|
|
44
|
-
"createdAt": "2025-01-27T12:00:00.000Z"
|
|
50
|
+
"createdAt": "2025-01-27T12:00:00.000Z",
|
|
45
51
|
}
|
|
46
52
|
}
|
|
47
53
|
|
|
@@ -68,14 +74,17 @@ class InvitationTarget(BaseModel):
|
|
|
68
74
|
|
|
69
75
|
class Invitation(BaseModel):
|
|
70
76
|
id: str
|
|
71
|
-
target: InvitationTarget
|
|
72
|
-
groups: Optional[List[InvitationGroup]] = None # Full group information
|
|
77
|
+
target: Union[InvitationTarget, List[InvitationTarget]] # API returns list or single
|
|
78
|
+
groups: Optional[List[Optional[InvitationGroup]]] = None # Full group information, can contain None
|
|
73
79
|
status: str
|
|
74
|
-
created_at: str
|
|
75
|
-
updated_at: Optional[str] = None
|
|
76
|
-
expires_at: Optional[str] = None
|
|
80
|
+
created_at: Optional[str] = Field(None, alias="createdAt") # API uses camelCase
|
|
81
|
+
updated_at: Optional[str] = Field(None, alias="updatedAt")
|
|
82
|
+
expires_at: Optional[str] = Field(None, alias="expiresAt")
|
|
77
83
|
metadata: Optional[Dict[str, Union[str, int, bool]]] = None
|
|
78
84
|
|
|
85
|
+
class Config:
|
|
86
|
+
populate_by_name = True
|
|
87
|
+
|
|
79
88
|
|
|
80
89
|
class CreateInvitationRequest(BaseModel):
|
|
81
90
|
target: InvitationTarget
|
|
@@ -100,4 +109,4 @@ class VortexApiError(Exception):
|
|
|
100
109
|
def __init__(self, message: str, status_code: int = 500):
|
|
101
110
|
self.message = message
|
|
102
111
|
self.status_code = status_code
|
|
103
|
-
super().__init__(message)
|
|
112
|
+
super().__init__(message)
|
vortex_sdk/vortex.py
CHANGED
|
@@ -1,34 +1,44 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import hmac
|
|
3
|
-
import hashlib
|
|
4
1
|
import base64
|
|
2
|
+
import hashlib
|
|
3
|
+
import hmac
|
|
4
|
+
import json
|
|
5
5
|
import time
|
|
6
6
|
import uuid
|
|
7
|
-
from typing import Dict, List, Optional, Union
|
|
7
|
+
from typing import Dict, List, Literal, Optional, Union
|
|
8
8
|
from urllib.parse import urlencode
|
|
9
|
+
|
|
9
10
|
import httpx
|
|
11
|
+
|
|
10
12
|
from .types import (
|
|
11
|
-
JwtPayload,
|
|
12
|
-
InvitationTarget,
|
|
13
|
-
Invitation,
|
|
14
|
-
CreateInvitationRequest,
|
|
15
13
|
AcceptInvitationsRequest,
|
|
16
14
|
ApiResponse,
|
|
17
|
-
|
|
15
|
+
CreateInvitationRequest,
|
|
16
|
+
Invitation,
|
|
17
|
+
InvitationTarget,
|
|
18
|
+
JwtPayload,
|
|
19
|
+
VortexApiError,
|
|
18
20
|
)
|
|
19
21
|
|
|
20
22
|
|
|
23
|
+
def _get_version():
|
|
24
|
+
"""Lazy import of version to avoid circular import"""
|
|
25
|
+
from . import __version__
|
|
26
|
+
return __version__
|
|
27
|
+
|
|
28
|
+
|
|
21
29
|
class Vortex:
|
|
22
|
-
def __init__(
|
|
30
|
+
def __init__(
|
|
31
|
+
self, api_key: str, base_url: str = "https://api.vortexsoftware.com/api/v1"
|
|
32
|
+
):
|
|
23
33
|
"""
|
|
24
34
|
Initialize Vortex client
|
|
25
35
|
|
|
26
36
|
Args:
|
|
27
37
|
api_key: Your Vortex API key
|
|
28
|
-
base_url: Base URL for Vortex API (default: https://api.vortexsoftware.com)
|
|
38
|
+
base_url: Base URL for Vortex API (default: https://api.vortexsoftware.com/api/v1)
|
|
29
39
|
"""
|
|
30
40
|
self.api_key = api_key
|
|
31
|
-
self.base_url = base_url.rstrip(
|
|
41
|
+
self.base_url = base_url.rstrip("/")
|
|
32
42
|
self._client = httpx.AsyncClient()
|
|
33
43
|
self._sync_client = httpx.Client()
|
|
34
44
|
|
|
@@ -49,20 +59,20 @@ class Vortex:
|
|
|
49
59
|
payload = JwtPayload(**payload)
|
|
50
60
|
|
|
51
61
|
# Parse API key (format: VRTX.base64url(uuid).key)
|
|
52
|
-
parts = self.api_key.split(
|
|
62
|
+
parts = self.api_key.split(".")
|
|
53
63
|
if len(parts) != 3:
|
|
54
|
-
raise ValueError(
|
|
64
|
+
raise ValueError("Invalid API key format. Expected: VRTX.{encodedId}.{key}")
|
|
55
65
|
|
|
56
66
|
prefix, encoded_id, key = parts
|
|
57
67
|
|
|
58
|
-
if prefix !=
|
|
59
|
-
raise ValueError(
|
|
68
|
+
if prefix != "VRTX":
|
|
69
|
+
raise ValueError("Invalid API key prefix. Expected: VRTX")
|
|
60
70
|
|
|
61
71
|
# Decode UUID from base64url
|
|
62
72
|
# Add padding if needed
|
|
63
73
|
padding = 4 - len(encoded_id) % 4
|
|
64
74
|
if padding != 4:
|
|
65
|
-
encoded_id_padded = encoded_id + (
|
|
75
|
+
encoded_id_padded = encoded_id + ("=" * padding)
|
|
66
76
|
else:
|
|
67
77
|
encoded_id_padded = encoded_id
|
|
68
78
|
|
|
@@ -70,75 +80,76 @@ class Vortex:
|
|
|
70
80
|
uuid_bytes = base64.urlsafe_b64decode(encoded_id_padded)
|
|
71
81
|
kid = str(uuid.UUID(bytes=uuid_bytes))
|
|
72
82
|
except Exception as e:
|
|
73
|
-
raise ValueError(f
|
|
83
|
+
raise ValueError(f"Invalid UUID in API key: {e}")
|
|
74
84
|
|
|
75
85
|
# Generate timestamps
|
|
76
86
|
iat = int(time.time())
|
|
77
87
|
expires = iat + 3600
|
|
78
88
|
|
|
79
89
|
# Step 1: Derive signing key from API key + UUID
|
|
80
|
-
signing_key = hmac.new(
|
|
81
|
-
key.encode(),
|
|
82
|
-
kid.encode(),
|
|
83
|
-
hashlib.sha256
|
|
84
|
-
).digest()
|
|
90
|
+
signing_key = hmac.new(key.encode(), kid.encode(), hashlib.sha256).digest()
|
|
85
91
|
|
|
86
92
|
# Step 2: Build header + payload
|
|
87
93
|
header = {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
94
|
+
"iat": iat,
|
|
95
|
+
"alg": "HS256",
|
|
96
|
+
"typ": "JWT",
|
|
97
|
+
"kid": kid,
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
# Serialize identifiers
|
|
95
|
-
identifiers_list = [
|
|
101
|
+
identifiers_list = [
|
|
102
|
+
{"type": id.type, "value": id.value} for id in payload.identifiers
|
|
103
|
+
]
|
|
96
104
|
|
|
97
105
|
# Serialize groups
|
|
98
106
|
groups_list = None
|
|
99
107
|
if payload.groups is not None:
|
|
100
108
|
groups_list = [
|
|
101
|
-
{
|
|
109
|
+
{
|
|
110
|
+
k: v
|
|
111
|
+
for k, v in group.model_dump(
|
|
112
|
+
by_alias=True, exclude_none=True
|
|
113
|
+
).items()
|
|
114
|
+
}
|
|
102
115
|
for group in payload.groups
|
|
103
116
|
]
|
|
104
117
|
|
|
105
118
|
jwt_payload = {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
119
|
+
"userId": payload.user_id,
|
|
120
|
+
"groups": groups_list,
|
|
121
|
+
"role": payload.role,
|
|
122
|
+
"expires": expires,
|
|
123
|
+
"identifiers": identifiers_list,
|
|
111
124
|
}
|
|
112
125
|
|
|
113
126
|
# Add attributes if provided
|
|
114
|
-
if hasattr(payload,
|
|
115
|
-
jwt_payload[
|
|
127
|
+
if hasattr(payload, "attributes") and payload.attributes:
|
|
128
|
+
jwt_payload["attributes"] = payload.attributes
|
|
116
129
|
|
|
117
130
|
# Step 3: Base64URL encode (without padding)
|
|
118
|
-
header_json = json.dumps(header, separators=(
|
|
119
|
-
payload_json = json.dumps(jwt_payload, separators=(
|
|
131
|
+
header_json = json.dumps(header, separators=(",", ":"))
|
|
132
|
+
payload_json = json.dumps(jwt_payload, separators=(",", ":"))
|
|
120
133
|
|
|
121
|
-
header_b64 = base64.urlsafe_b64encode(header_json.encode()).decode().rstrip(
|
|
122
|
-
payload_b64 =
|
|
134
|
+
header_b64 = base64.urlsafe_b64encode(header_json.encode()).decode().rstrip("=")
|
|
135
|
+
payload_b64 = (
|
|
136
|
+
base64.urlsafe_b64encode(payload_json.encode()).decode().rstrip("=")
|
|
137
|
+
)
|
|
123
138
|
|
|
124
139
|
# Step 4: Sign
|
|
125
|
-
to_sign = f
|
|
126
|
-
signature = hmac.new(
|
|
127
|
-
signing_key,
|
|
128
|
-
to_sign.encode(),
|
|
129
|
-
hashlib.sha256
|
|
130
|
-
).digest()
|
|
140
|
+
to_sign = f"{header_b64}.{payload_b64}"
|
|
141
|
+
signature = hmac.new(signing_key, to_sign.encode(), hashlib.sha256).digest()
|
|
131
142
|
|
|
132
|
-
signature_b64 = base64.urlsafe_b64encode(signature).decode().rstrip(
|
|
143
|
+
signature_b64 = base64.urlsafe_b64encode(signature).decode().rstrip("=")
|
|
133
144
|
|
|
134
|
-
return f
|
|
145
|
+
return f"{to_sign}.{signature_b64}"
|
|
135
146
|
|
|
136
147
|
async def _vortex_api_request(
|
|
137
148
|
self,
|
|
138
149
|
method: str,
|
|
139
150
|
endpoint: str,
|
|
140
151
|
data: Optional[Dict] = None,
|
|
141
|
-
params: Optional[Dict] = None
|
|
152
|
+
params: Optional[Dict] = None,
|
|
142
153
|
) -> Dict:
|
|
143
154
|
"""
|
|
144
155
|
Make an API request to Vortex
|
|
@@ -157,26 +168,27 @@ class Vortex:
|
|
|
157
168
|
"""
|
|
158
169
|
url = f"{self.base_url}{endpoint}"
|
|
159
170
|
headers = {
|
|
160
|
-
"
|
|
171
|
+
"x-api-key": f"{self.api_key}",
|
|
161
172
|
"Content-Type": "application/json",
|
|
162
|
-
"User-Agent": "vortex-python-sdk/
|
|
173
|
+
"User-Agent": f"vortex-python-sdk/{_get_version()}",
|
|
163
174
|
}
|
|
164
175
|
|
|
165
176
|
try:
|
|
166
177
|
response = await self._client.request(
|
|
167
|
-
method=method,
|
|
168
|
-
url=url,
|
|
169
|
-
json=data,
|
|
170
|
-
params=params,
|
|
171
|
-
headers=headers
|
|
178
|
+
method=method, url=url, json=data, params=params, headers=headers
|
|
172
179
|
)
|
|
173
180
|
|
|
174
181
|
if response.status_code >= 400:
|
|
175
182
|
try:
|
|
176
183
|
error_data = response.json()
|
|
177
|
-
error_message = error_data.get(
|
|
184
|
+
error_message = error_data.get(
|
|
185
|
+
"error",
|
|
186
|
+
f"API request failed with status {response.status_code}",
|
|
187
|
+
)
|
|
178
188
|
except:
|
|
179
|
-
error_message =
|
|
189
|
+
error_message = (
|
|
190
|
+
f"API request failed with status {response.status_code}"
|
|
191
|
+
)
|
|
180
192
|
|
|
181
193
|
raise VortexApiError(error_message, response.status_code)
|
|
182
194
|
|
|
@@ -190,7 +202,7 @@ class Vortex:
|
|
|
190
202
|
method: str,
|
|
191
203
|
endpoint: str,
|
|
192
204
|
data: Optional[Dict] = None,
|
|
193
|
-
params: Optional[Dict] = None
|
|
205
|
+
params: Optional[Dict] = None,
|
|
194
206
|
) -> Dict:
|
|
195
207
|
"""
|
|
196
208
|
Make a synchronous API request to Vortex
|
|
@@ -209,26 +221,27 @@ class Vortex:
|
|
|
209
221
|
"""
|
|
210
222
|
url = f"{self.base_url}{endpoint}"
|
|
211
223
|
headers = {
|
|
212
|
-
"
|
|
224
|
+
"x-api-key": f"{self.api_key}",
|
|
213
225
|
"Content-Type": "application/json",
|
|
214
|
-
"User-Agent": "vortex-python-sdk/
|
|
226
|
+
"User-Agent": f"vortex-python-sdk/{_get_version()}",
|
|
215
227
|
}
|
|
216
228
|
|
|
217
229
|
try:
|
|
218
230
|
response = self._sync_client.request(
|
|
219
|
-
method=method,
|
|
220
|
-
url=url,
|
|
221
|
-
json=data,
|
|
222
|
-
params=params,
|
|
223
|
-
headers=headers
|
|
231
|
+
method=method, url=url, json=data, params=params, headers=headers
|
|
224
232
|
)
|
|
225
233
|
|
|
226
234
|
if response.status_code >= 400:
|
|
227
235
|
try:
|
|
228
236
|
error_data = response.json()
|
|
229
|
-
error_message = error_data.get(
|
|
237
|
+
error_message = error_data.get(
|
|
238
|
+
"error",
|
|
239
|
+
f"API request failed with status {response.status_code}",
|
|
240
|
+
)
|
|
230
241
|
except:
|
|
231
|
-
error_message =
|
|
242
|
+
error_message = (
|
|
243
|
+
f"API request failed with status {response.status_code}"
|
|
244
|
+
)
|
|
232
245
|
|
|
233
246
|
raise VortexApiError(error_message, response.status_code)
|
|
234
247
|
|
|
@@ -240,7 +253,7 @@ class Vortex:
|
|
|
240
253
|
async def get_invitations_by_target(
|
|
241
254
|
self,
|
|
242
255
|
target_type: Literal["email", "username", "phoneNumber"],
|
|
243
|
-
target_value: str
|
|
256
|
+
target_value: str,
|
|
244
257
|
) -> List[Invitation]:
|
|
245
258
|
"""
|
|
246
259
|
Get invitations for a specific target
|
|
@@ -252,18 +265,17 @@ class Vortex:
|
|
|
252
265
|
Returns:
|
|
253
266
|
List of invitations
|
|
254
267
|
"""
|
|
255
|
-
params = {
|
|
256
|
-
"targetType": target_type,
|
|
257
|
-
"targetValue": target_value
|
|
258
|
-
}
|
|
268
|
+
params = {"targetType": target_type, "targetValue": target_value}
|
|
259
269
|
|
|
260
|
-
response = await self._vortex_api_request(
|
|
270
|
+
response = await self._vortex_api_request(
|
|
271
|
+
"GET", "/invitations/by-target", params=params
|
|
272
|
+
)
|
|
261
273
|
return [Invitation(**inv) for inv in response.get("invitations", [])]
|
|
262
274
|
|
|
263
275
|
def get_invitations_by_target_sync(
|
|
264
276
|
self,
|
|
265
277
|
target_type: Literal["email", "username", "phoneNumber"],
|
|
266
|
-
target_value: str
|
|
278
|
+
target_value: str,
|
|
267
279
|
) -> List[Invitation]:
|
|
268
280
|
"""
|
|
269
281
|
Get invitations for a specific target (synchronous)
|
|
@@ -275,12 +287,11 @@ class Vortex:
|
|
|
275
287
|
Returns:
|
|
276
288
|
List of invitations
|
|
277
289
|
"""
|
|
278
|
-
params = {
|
|
279
|
-
"targetType": target_type,
|
|
280
|
-
"targetValue": target_value
|
|
281
|
-
}
|
|
290
|
+
params = {"targetType": target_type, "targetValue": target_value}
|
|
282
291
|
|
|
283
|
-
response = self._vortex_api_request_sync(
|
|
292
|
+
response = self._vortex_api_request_sync(
|
|
293
|
+
"GET", "/invitations/by-target", params=params
|
|
294
|
+
)
|
|
284
295
|
return [Invitation(**inv) for inv in response.get("invitations", [])]
|
|
285
296
|
|
|
286
297
|
async def get_invitation(self, invitation_id: str) -> Invitation:
|
|
@@ -293,7 +304,9 @@ class Vortex:
|
|
|
293
304
|
Returns:
|
|
294
305
|
Invitation object
|
|
295
306
|
"""
|
|
296
|
-
response = await self._vortex_api_request(
|
|
307
|
+
response = await self._vortex_api_request(
|
|
308
|
+
"GET", f"/invitations/{invitation_id}"
|
|
309
|
+
)
|
|
297
310
|
return Invitation(**response)
|
|
298
311
|
|
|
299
312
|
def get_invitation_sync(self, invitation_id: str) -> Invitation:
|
|
@@ -310,9 +323,7 @@ class Vortex:
|
|
|
310
323
|
return Invitation(**response)
|
|
311
324
|
|
|
312
325
|
async def accept_invitations(
|
|
313
|
-
self,
|
|
314
|
-
invitation_ids: List[str],
|
|
315
|
-
target: Union[InvitationTarget, Dict[str, str]]
|
|
326
|
+
self, invitation_ids: List[str], target: Union[InvitationTarget, Dict[str, str]]
|
|
316
327
|
) -> Dict:
|
|
317
328
|
"""
|
|
318
329
|
Accept multiple invitations
|
|
@@ -327,17 +338,12 @@ class Vortex:
|
|
|
327
338
|
if isinstance(target, dict):
|
|
328
339
|
target = InvitationTarget(**target)
|
|
329
340
|
|
|
330
|
-
data = {
|
|
331
|
-
"invitationIds": invitation_ids,
|
|
332
|
-
"target": target.model_dump()
|
|
333
|
-
}
|
|
341
|
+
data = {"invitationIds": invitation_ids, "target": target.model_dump()}
|
|
334
342
|
|
|
335
343
|
return await self._vortex_api_request("POST", "/invitations/accept", data=data)
|
|
336
344
|
|
|
337
345
|
def accept_invitations_sync(
|
|
338
|
-
self,
|
|
339
|
-
invitation_ids: List[str],
|
|
340
|
-
target: Union[InvitationTarget, Dict[str, str]]
|
|
346
|
+
self, invitation_ids: List[str], target: Union[InvitationTarget, Dict[str, str]]
|
|
341
347
|
) -> Dict:
|
|
342
348
|
"""
|
|
343
349
|
Accept multiple invitations (synchronous)
|
|
@@ -352,10 +358,7 @@ class Vortex:
|
|
|
352
358
|
if isinstance(target, dict):
|
|
353
359
|
target = InvitationTarget(**target)
|
|
354
360
|
|
|
355
|
-
data = {
|
|
356
|
-
"invitationIds": invitation_ids,
|
|
357
|
-
"target": target.model_dump()
|
|
358
|
-
}
|
|
361
|
+
data = {"invitationIds": invitation_ids, "target": target.model_dump()}
|
|
359
362
|
|
|
360
363
|
return self._vortex_api_request_sync("POST", "/invitations/accept", data=data)
|
|
361
364
|
|
|
@@ -384,9 +387,7 @@ class Vortex:
|
|
|
384
387
|
return self._vortex_api_request_sync("DELETE", f"/invitations/{invitation_id}")
|
|
385
388
|
|
|
386
389
|
async def get_invitations_by_group(
|
|
387
|
-
self,
|
|
388
|
-
group_type: str,
|
|
389
|
-
group_id: str
|
|
390
|
+
self, group_type: str, group_id: str
|
|
390
391
|
) -> List[Invitation]:
|
|
391
392
|
"""
|
|
392
393
|
Get invitations for a specific group
|
|
@@ -398,13 +399,13 @@ class Vortex:
|
|
|
398
399
|
Returns:
|
|
399
400
|
List of invitations
|
|
400
401
|
"""
|
|
401
|
-
response = await self._vortex_api_request(
|
|
402
|
+
response = await self._vortex_api_request(
|
|
403
|
+
"GET", f"/invitations/by-group/{group_type}/{group_id}"
|
|
404
|
+
)
|
|
402
405
|
return [Invitation(**inv) for inv in response.get("invitations", [])]
|
|
403
406
|
|
|
404
407
|
def get_invitations_by_group_sync(
|
|
405
|
-
self,
|
|
406
|
-
group_type: str,
|
|
407
|
-
group_id: str
|
|
408
|
+
self, group_type: str, group_id: str
|
|
408
409
|
) -> List[Invitation]:
|
|
409
410
|
"""
|
|
410
411
|
Get invitations for a specific group (synchronous)
|
|
@@ -416,14 +417,12 @@ class Vortex:
|
|
|
416
417
|
Returns:
|
|
417
418
|
List of invitations
|
|
418
419
|
"""
|
|
419
|
-
response = self._vortex_api_request_sync(
|
|
420
|
+
response = self._vortex_api_request_sync(
|
|
421
|
+
"GET", f"/invitations/by-group/{group_type}/{group_id}"
|
|
422
|
+
)
|
|
420
423
|
return [Invitation(**inv) for inv in response.get("invitations", [])]
|
|
421
424
|
|
|
422
|
-
async def delete_invitations_by_group(
|
|
423
|
-
self,
|
|
424
|
-
group_type: str,
|
|
425
|
-
group_id: str
|
|
426
|
-
) -> Dict:
|
|
425
|
+
async def delete_invitations_by_group(self, group_type: str, group_id: str) -> Dict:
|
|
427
426
|
"""
|
|
428
427
|
Delete all invitations for a specific group
|
|
429
428
|
|
|
@@ -434,13 +433,11 @@ class Vortex:
|
|
|
434
433
|
Returns:
|
|
435
434
|
API response
|
|
436
435
|
"""
|
|
437
|
-
return await self._vortex_api_request(
|
|
436
|
+
return await self._vortex_api_request(
|
|
437
|
+
"DELETE", f"/invitations/by-group/{group_type}/{group_id}"
|
|
438
|
+
)
|
|
438
439
|
|
|
439
|
-
def delete_invitations_by_group_sync(
|
|
440
|
-
self,
|
|
441
|
-
group_type: str,
|
|
442
|
-
group_id: str
|
|
443
|
-
) -> Dict:
|
|
440
|
+
def delete_invitations_by_group_sync(self, group_type: str, group_id: str) -> Dict:
|
|
444
441
|
"""
|
|
445
442
|
Delete all invitations for a specific group (synchronous)
|
|
446
443
|
|
|
@@ -451,7 +448,9 @@ class Vortex:
|
|
|
451
448
|
Returns:
|
|
452
449
|
API response
|
|
453
450
|
"""
|
|
454
|
-
return self._vortex_api_request_sync(
|
|
451
|
+
return self._vortex_api_request_sync(
|
|
452
|
+
"DELETE", f"/invitations/by-group/{group_type}/{group_id}"
|
|
453
|
+
)
|
|
455
454
|
|
|
456
455
|
async def reinvite(self, invitation_id: str) -> Invitation:
|
|
457
456
|
"""
|
|
@@ -463,7 +462,9 @@ class Vortex:
|
|
|
463
462
|
Returns:
|
|
464
463
|
Updated invitation object
|
|
465
464
|
"""
|
|
466
|
-
response = await self._vortex_api_request(
|
|
465
|
+
response = await self._vortex_api_request(
|
|
466
|
+
"POST", f"/invitations/{invitation_id}/reinvite"
|
|
467
|
+
)
|
|
467
468
|
return Invitation(**response)
|
|
468
469
|
|
|
469
470
|
def reinvite_sync(self, invitation_id: str) -> Invitation:
|
|
@@ -476,7 +477,9 @@ class Vortex:
|
|
|
476
477
|
Returns:
|
|
477
478
|
Updated invitation object
|
|
478
479
|
"""
|
|
479
|
-
response = self._vortex_api_request_sync(
|
|
480
|
+
response = self._vortex_api_request_sync(
|
|
481
|
+
"POST", f"/invitations/{invitation_id}/reinvite"
|
|
482
|
+
)
|
|
480
483
|
return Invitation(**response)
|
|
481
484
|
|
|
482
485
|
async def close(self):
|
|
@@ -501,4 +504,4 @@ class Vortex:
|
|
|
501
504
|
|
|
502
505
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
503
506
|
"""Context manager exit"""
|
|
504
|
-
self.close_sync()
|
|
507
|
+
self.close_sync()
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
vortex_python_sdk-0.0.3.dist-info/licenses/LICENSE,sha256=VndlWxbL4-w3YDf2yE5gJscj4zVXF0qlSq0LDtay3lo,1074
|
|
2
|
-
vortex_sdk/__init__.py,sha256=0Q9cyxYBvCQtLsKWJJu-lAjPFp5HCXnIYKtp6xYAYFA,709
|
|
3
|
-
vortex_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
vortex_sdk/types.py,sha256=Si5fXbf2gkcK3FoirJURNBBPLOJM090P5uhlHx6kXZQ,3079
|
|
5
|
-
vortex_sdk/vortex.py,sha256=B7XAT8CAEJLEH5kxYF3KpMo4kAO_LwCBs8-VEBgC3cw,14754
|
|
6
|
-
vortex_python_sdk-0.0.3.dist-info/METADATA,sha256=bACa6c5OMHoIwGBKC2oH8uNKVIdHmlIzzrHYnftqr5w,6237
|
|
7
|
-
vortex_python_sdk-0.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
8
|
-
vortex_python_sdk-0.0.3.dist-info/top_level.txt,sha256=xFDlEcXIIi_sBhkse0YfMnSdg2IlaYUd0oP2UCDc_Y0,11
|
|
9
|
-
vortex_python_sdk-0.0.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|