aboutsummaryrefslogtreecommitdiff
path: root/jb/managers
diff options
context:
space:
mode:
authorstuppie2026-09-01 14:17:10 -0600
committerstuppie2026-09-01 14:17:10 -0600
commit81261e52931d055df5830e29b9bf5ef81ba9134e (patch)
tree9ce5817cdb0953080f78950ea42c869683ed5643 /jb/managers
parentf5a1882de073ea6859c226395daefeb566e9e802 (diff)
downloadamt-jb-81261e52931d055df5830e29b9bf5ef81ba9134e.tar.gz
amt-jb-81261e52931d055df5830e29b9bf5ef81ba9134e.zip
add a magic token flow specifically for amt account link. gr api manager add more logging and error handling
Diffstat (limited to 'jb/managers')
-rw-r--r--jb/managers/gr_api.py59
1 files changed, 54 insertions, 5 deletions
diff --git a/jb/managers/gr_api.py b/jb/managers/gr_api.py
index 8ffeaf0..a31f7da 100644
--- a/jb/managers/gr_api.py
+++ b/jb/managers/gr_api.py
@@ -1,16 +1,23 @@
"""Client for General Research's product-user API."""
+import logging
from typing import Any
import requests
from jb.models.auth import User
+logger = logging.getLogger(__name__)
+
class GRApiError(RuntimeError):
"""The General Research API could not satisfy a request."""
+class GRApiNotFoundError(GRApiError):
+ """The requested General Research API resource does not exist."""
+
+
class GRApiManager:
def __init__(
self,
@@ -40,6 +47,14 @@ class GRApiManager:
response = self.session.request(method, url, timeout=self.timeout, **kwargs)
response.raise_for_status()
return response
+ except requests.HTTPError as exc:
+ if exc.response is not None and exc.response.status_code == 404:
+ raise GRApiNotFoundError(
+ f"General Research API resource not found: {method} {url}"
+ ) from exc
+ raise GRApiError(
+ f"General Research API request failed: {method} {url}"
+ ) from exc
except requests.RequestException as exc:
raise GRApiError(
f"General Research API request failed: {method} {url}"
@@ -101,12 +116,46 @@ class GRApiManager:
).json()
return self.get_user(user.product_user_id)
- def transition_product_user_id(self, user: User, amt_worker_id: str) -> User:
+ def transition_user_from_amt(self, user: User, amt_worker_id: str) -> User:
"""This should only be called once upon transition from an
AMT account to a General Research account."""
url = f"{self.base_url}/{self.product_id}/user/{amt_worker_id}/"
- res = self._request(
- "PATCH", url, json={"product_user_id": user.product_user_id}
- )
+ try:
+ self._request(
+ "PATCH", url, json={"product_user_id": user.product_user_id}
+ )
+ except GRApiNotFoundError as exc:
+ raise ValueError(f"User {amt_worker_id} does not exist") from exc
+ except GRApiError as exc:
+ http_error = exc.__cause__
+ response = (
+ http_error.response
+ if isinstance(http_error, requests.HTTPError)
+ else None
+ )
+ if response is not None and response.status_code == 400:
+ try:
+ detail = response.json().get("detail")
+ except (ValueError, AttributeError):
+ detail = None
+ if detail == "Unable to update User":
+ raise ValueError(
+ "unable to update user, probably another user already "
+ "exists with this email"
+ ) from exc
+ raise
self.set_user_email(user)
- return self.get_user(user.product_user_id)
+ transitioned_user = self.get_user(user.product_user_id)
+ logger.warning(
+ "Transitioned product user from AMT worker %s to %s with email %s",
+ amt_worker_id,
+ transitioned_user.product_user_id,
+ transitioned_user.email,
+ extra={
+ "event": "transition_user_from_amt",
+ "amt_worker_id": amt_worker_id,
+ "product_user_id": transitioned_user.product_user_id,
+ "email": str(transitioned_user.email),
+ },
+ )
+ return transitioned_user