neris-api-client 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.1
2
2
  Name: neris_api_client
3
- Version: 0.0.1
3
+ Version: 0.1.0
4
4
  Summary: NERIS API Client
5
5
  Author-email: Ben Coleman <ben.coleman@ul.org>
6
6
  Project-URL: Homepage, https://github.com/ulfsri/neris
@@ -30,6 +30,9 @@ from neris_api_client import NerisApiClient
30
30
 
31
31
  client = NerisApiClient(username="neris.user", password="*******", env="dev")
32
32
 
33
- # Get an organization
34
- org = client.get_org("FD24027240")
33
+ # Get an entity
34
+ entity = client.get_entity("FD24027240")
35
35
  ```
36
+
37
+ API auth tokens are cached locally in `./.token_cache`. If there are auth issues first try instantiating the client with `use_cache=False`
38
+ keyword argument or deleting the token cache.
@@ -11,6 +11,9 @@ from neris_api_client import NerisApiClient
11
11
 
12
12
  client = NerisApiClient(username="neris.user", password="*******", env="dev")
13
13
 
14
- # Get an organization
15
- org = client.get_org("FD24027240")
14
+ # Get an entity
15
+ entity = client.get_entity("FD24027240")
16
16
  ```
17
+
18
+ API auth tokens are cached locally in `./.token_cache`. If there are auth issues first try instantiating the client with `use_cache=False`
19
+ keyword argument or deleting the token cache.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "neris_api_client"
7
- version = "0.0.1"
7
+ version = "0.1.0"
8
8
  authors = [
9
9
  { name="Ben Coleman", email="ben.coleman@ul.org" },
10
10
  ]
@@ -2,7 +2,7 @@ import jwt
2
2
  import json
3
3
  from enum import Enum
4
4
  from uuid import UUID
5
- from typing import Optional, Dict, Any, Callable
5
+ from typing import List, Optional, Dict, Any, Callable
6
6
  from pathlib import Path
7
7
  from datetime import datetime, timedelta
8
8
 
@@ -11,6 +11,7 @@ import requests
11
11
  from pydantic import BaseModel
12
12
 
13
13
  from .models import (
14
+ IncidentPayload,
14
15
  CreateDepartmentPayload,
15
16
  DepartmentPayload,
16
17
  CreateUserPayload,
@@ -24,15 +25,17 @@ class Environment(str, Enum):
24
25
  DEV = "dev"
25
26
  PROD = "prod"
26
27
  LOCAL = "local"
28
+ TEST = "test"
27
29
 
28
30
 
29
31
  BASE_URLS = {
30
32
  Environment.LOCAL: "http://localhost:8000",
31
33
  Environment.DEV: "https://api-dev.neris.fsri.org/v1",
32
34
  Environment.PROD: "https://api.neris.fsri.org/v1",
35
+ Environment.TEST: "https://api-test.neris.fsri.org/v1",
33
36
  }
34
37
 
35
- COGNTIO_CLIENT_CONFIG_URL = (
38
+ COGNITO_CLIENT_CONFIG_URL = (
36
39
  "https://neris-{env}-public.s3.us-east-2.amazonaws.com/cognito_config.json"
37
40
  )
38
41
 
@@ -40,14 +43,16 @@ COGNTIO_CLIENT_CONFIG_URL = (
40
43
  class _NerisApiClient:
41
44
  def __init__(
42
45
  self,
43
- env: Environment = Environment.LOCAL,
44
46
  username: str = "",
45
47
  password: str = "",
48
+ env: Environment = Environment.LOCAL,
49
+ use_cache: bool = True,
46
50
  ):
47
51
  self._username = username
48
52
  self._password = password
49
53
  self._base_url = BASE_URLS[env]
50
54
  self._env = env
55
+ self._use_cache = use_cache
51
56
 
52
57
  self._access_token: str = None
53
58
  self._access_token_exp: datetime = None
@@ -60,6 +65,7 @@ class _NerisApiClient:
60
65
  # Don't mess with auth on localhost
61
66
  if env == Environment.LOCAL:
62
67
  # Non-existent auth token never expires
68
+ self._use_cache = False
63
69
  self._access_token_exp = datetime.now() + timedelta(weeks=52)
64
70
  return
65
71
 
@@ -71,7 +77,8 @@ class _NerisApiClient:
71
77
  self._id_token_cache_path = self._token_cache_path / "id_token"
72
78
  self._cognito_config_cache_path = self._token_cache_path / "cognito_config.json"
73
79
 
74
- self._read_token_cache()
80
+ if self._use_cache:
81
+ self._read_token_cache()
75
82
 
76
83
  if self._access_token:
77
84
  self._set_token_exp()
@@ -83,7 +90,7 @@ class _NerisApiClient:
83
90
  def fetch_cognito_config(self):
84
91
  if self._cognito_config is None:
85
92
  self._cognito_config = requests.get(
86
- COGNTIO_CLIENT_CONFIG_URL.format(env=self._env)
93
+ COGNITO_CLIENT_CONFIG_URL.format(env=self._env)
87
94
  ).json()
88
95
  return f(self)
89
96
 
@@ -103,14 +110,15 @@ class _NerisApiClient:
103
110
 
104
111
  self._set_token_exp()
105
112
 
106
- self._write_token_cache()
113
+ if self._use_cache:
114
+ self._write_token_cache()
107
115
 
108
116
  @_fetch_cognito_config
109
117
  def _refresh_auth(self) -> None:
110
118
  res = self._cognito.initiate_auth(
111
119
  AuthFlow="REFRESH_TOKEN_AUTH",
112
120
  AuthParameters={"REFRESH_TOKEN": self._refresh_token},
113
- ClientId=self._cogntio_config["client_id"],
121
+ ClientId=self._cognito_config["client_id"],
114
122
  )
115
123
 
116
124
  self._access_token = res["AuthenticationResult"]["AccessToken"]
@@ -156,6 +164,7 @@ class _NerisApiClient:
156
164
  method: str,
157
165
  path: str,
158
166
  data: Optional[str | Dict[str, Any]] = None,
167
+ params: Optional[Dict[str, Any]] = None,
159
168
  model: Optional[BaseModel] = None,
160
169
  ):
161
170
  if self._access_token_exp - datetime.now() <= timedelta(seconds=0):
@@ -171,11 +180,15 @@ class _NerisApiClient:
171
180
 
172
181
  if model:
173
182
  if isinstance(data, str):
174
- data = model.model_validate_json(data).model_dump(mode="json")
183
+ data = model.model_validate_json(data).model_dump(
184
+ mode="json", by_alias=True
185
+ )
175
186
  if isinstance(data, dict):
176
- data = model.model_validate(data).model_dump(mode="json")
187
+ data = model.model_validate(data).model_dump(mode="json", by_alias=True)
177
188
 
178
- res = getattr(self._session, method)(f"{self._base_url}{path}", json=data)
189
+ res = getattr(self._session, method)(
190
+ f"{self._base_url}{path}", json=data, params=params
191
+ )
179
192
 
180
193
  try:
181
194
  res.raise_for_status()
@@ -194,14 +207,16 @@ class NerisApiClient(_NerisApiClient):
194
207
  def health(self):
195
208
  return self._call("get", "/health")
196
209
 
197
- def get_org(self, neris_id: str) -> Dict[str, Any]:
198
- return self._call("get", f"/org/{neris_id}")
210
+ def get_entity(self, neris_id: str) -> Dict[str, Any]:
211
+ return self._call("get", f"/entity/{neris_id}")
199
212
 
200
- def create_org(self, body: str | Dict[str, Any]) -> Dict[str, Any]:
201
- return self._call("post", "/org/", body, model=CreateDepartmentPayload)
213
+ def create_entity(self, body: str | Dict[str, Any]) -> Dict[str, Any]:
214
+ return self._call("post", "/entity/", body, model=CreateDepartmentPayload)
202
215
 
203
- def update_org(self, neris_id: str, body: str | Dict[str, Any]) -> Dict[str, Any]:
204
- return self._call("put", f"/org/{neris_id}", body, model=DepartmentPayload)
216
+ def update_entity(
217
+ self, neris_id: str, body: str | Dict[str, Any]
218
+ ) -> Dict[str, Any]:
219
+ return self._call("put", f"/entity/{neris_id}", body, model=DepartmentPayload)
205
220
 
206
221
  def get_user(self, sub: str | UUID) -> Dict[str, Any]:
207
222
  return self._call("get", f"/user/{sub}")
@@ -213,3 +228,31 @@ class NerisApiClient(_NerisApiClient):
213
228
  self, sub: str | UUID, body: str | Dict[str, Any]
214
229
  ) -> Dict[str, Any]:
215
230
  return self._call("put", f"/user/{sub}", body, model=UpdateUserPayload)
231
+
232
+ def delete_user(self, sub: str | UUID) -> None:
233
+ self._call("delete", f"/user/{sub}")
234
+
235
+ def create_user_entity_membership(self, sub: str | UUID, neris_id: str) -> None:
236
+ self._call("post", f"/user/{sub}/user_entity_membership/{neris_id}")
237
+
238
+ def delete_user_entity_membership(self, sub: str | UUID, neris_id: str) -> None:
239
+ self._call("delete", f"/user/{sub}/user_entity_membership/{neris_id}")
240
+
241
+ def update_user_entity_activation(
242
+ self, sub: str | UUID, neris_id: str, active: bool
243
+ ) -> None:
244
+ self._call(
245
+ "put",
246
+ f"/user/{sub}/user_entity_activation/{neris_id}",
247
+ data={"active": active},
248
+ )
249
+
250
+ def list_user_entity_memberships(self, sub: str | UUID) -> List[Dict[str, Any]]:
251
+ return self._call("get", f"/user/{sub}/user_entity_membership")
252
+
253
+ def create_incident(
254
+ self, neris_id: str, body: str | Dict[str, Any]
255
+ ) -> Dict[str, Any]:
256
+ return self._call(
257
+ "post", f"/incident/{neris_id}", data=body, model=IncidentPayload
258
+ )