135 lines
5.8 KiB
Python
135 lines
5.8 KiB
Python
import os
|
|
import requests
|
|
from dotenv import load_dotenv
|
|
import logging
|
|
|
|
# Set up basic logging
|
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class AuthHandler:
|
|
def __init__(self):
|
|
load_dotenv(override=True)
|
|
self.client_id = os.getenv("SO_CLIENT_ID") or os.getenv("SO_SOD")
|
|
self.client_secret = os.getenv("SO_CLIENT_SECRET")
|
|
self.refresh_token = os.getenv("SO_REFRESH_TOKEN")
|
|
self.redirect_uri = os.getenv("SO_REDIRECT_URI", "http://localhost")
|
|
self.env = os.getenv("SO_ENVIRONMENT", "sod")
|
|
self.cust_id = os.getenv("SO_CONTEXT_IDENTIFIER", "Cust55774")
|
|
|
|
if not all([self.client_id, self.client_secret, self.refresh_token]):
|
|
raise ValueError("SuperOffice credentials missing in .env file.")
|
|
|
|
logger.info("AuthHandler initialized with environment variables.")
|
|
|
|
def get_access_token(self):
|
|
# This method would typically handle caching and refreshing
|
|
# For this health check, we'll directly call _refresh_access_token
|
|
return self._refresh_access_token()
|
|
|
|
def _refresh_access_token(self):
|
|
# OAuth token endpoint is ALWAYS online.superoffice.com for production,
|
|
# or sod.superoffice.com for sandbox.
|
|
token_domain = "online.superoffice.com" if "online" in self.env.lower() else "sod.superoffice.com"
|
|
url = f"https://{token_domain}/login/common/oauth/tokens"
|
|
|
|
data = {
|
|
"grant_type": "refresh_token",
|
|
"client_id": self.client_id,
|
|
"client_secret": self.client_secret,
|
|
"refresh_token": self.refresh_token,
|
|
"redirect_uri": self.redirect_uri
|
|
}
|
|
try:
|
|
resp = requests.post(url, data=data)
|
|
if resp.status_code != 200:
|
|
logger.error(f"❌ Token Refresh Failed (Status {resp.status_code}): {resp.text}")
|
|
return None
|
|
|
|
logger.info("Access token refreshed successfully.")
|
|
return resp.json().get("access_token")
|
|
except Exception as e:
|
|
logger.error(f"❌ Connection Error during token refresh: {e}")
|
|
return None
|
|
|
|
class SuperOfficeClient:
|
|
def __init__(self, auth_handler):
|
|
self.auth_handler = auth_handler
|
|
self.env = os.getenv("SO_ENVIRONMENT", "sod")
|
|
self.cust_id = os.getenv("SO_CONTEXT_IDENTIFIER", "Cust55774")
|
|
# API base URL: online3.superoffice.com is valid here
|
|
self.base_url = f"https://{self.env}.superoffice.com/{self.cust_id}/api/v1"
|
|
self.access_token = self.auth_handler.get_access_token()
|
|
if not self.access_token:
|
|
raise Exception("Failed to obtain access token during SuperOfficeClient initialization.")
|
|
|
|
self.headers = {
|
|
"Authorization": f"Bearer {self.access_token}",
|
|
"Content-Type": "application/json",
|
|
"Accept": "application/json"
|
|
}
|
|
logger.info("✅ SuperOffice Client initialized and authenticated.")
|
|
|
|
def _get(self, endpoint):
|
|
try:
|
|
resp = requests.get(f"{self.base_url}/{endpoint}", headers=self.headers)
|
|
resp.raise_for_status()
|
|
return resp.json()
|
|
except requests.exceptions.HTTPError as e:
|
|
logger.error(f"❌ API GET Error for {endpoint} (Status: {e.response.status_code}): {e.response.text}")
|
|
return None
|
|
except Exception as e:
|
|
logger.error(f"❌ Connection Error for {endpoint}: {e}")
|
|
return None
|
|
|
|
def perform_health_check():
|
|
logger.info("Starting SuperOffice API health check...")
|
|
try:
|
|
auth_handler = AuthHandler()
|
|
so_client = SuperOfficeClient(auth_handler)
|
|
|
|
# Test 1: Associate/Me
|
|
logger.info("\n--- Test 1: Fetching current user details (/Associate/Me) ---")
|
|
user_details = so_client._get("Associate/Me")
|
|
if user_details:
|
|
logger.info(f"✅ Associate/Me successful! Connected as: {user_details.get('Name')} (Associate ID: {user_details.get('AssociateId')})")
|
|
else:
|
|
logger.error("❌ Associate/Me failed.")
|
|
|
|
# Test 2: Get Person by ID (e.g., ID 1)
|
|
logger.info("\n--- Test 2: Fetching Person with ID 1 (/Person/1) ---")
|
|
person = so_client._get("Person/1")
|
|
if person:
|
|
logger.info(f"✅ Person/1 successful! Name: {person.get('Firstname')} {person.get('Lastname')}")
|
|
else:
|
|
logger.error("❌ Person/1 failed. (Could be that Person ID 1 does not exist or insufficient permissions)")
|
|
|
|
# Test 3: Get Contact by ID (e.g., ID 1)
|
|
logger.info("\n--- Test 3: Fetching Contact with ID 1 (/Contact/1) ---")
|
|
contact = so_client._get("Contact/1")
|
|
if contact:
|
|
logger.info(f"✅ Contact/1 successful! Name: {contact.get('Name')}")
|
|
else:
|
|
logger.error("❌ Contact/1 failed. (Could be that Contact ID 1 does not exist or insufficient permissions)")
|
|
|
|
# Overall check - if at least one read operation was successful
|
|
if user_details or person or contact:
|
|
logger.info("\n✅ SuperOffice API Connector seems partially operational (at least one read test passed).")
|
|
return True
|
|
else:
|
|
logger.error("\n❌ SuperOffice API Connector is NOT operational (all read tests failed).")
|
|
return False
|
|
|
|
except ValueError as ve:
|
|
logger.error(f"❌ Configuration error: {ve}")
|
|
return False
|
|
except Exception as e:
|
|
logger.error(f"❌ An unexpected error occurred during health check: {e}", exc_info=True)
|
|
return False
|
|
|
|
if __name__ == "__main__":
|
|
if perform_health_check():
|
|
logger.info("\nOverall SuperOffice API Health Check: PASSED (partially operational is still a pass for now).")
|
|
else:
|
|
logger.error("\nOverall SuperOffice API Health Check: FAILED.")
|