added activity view
This commit is contained in:
121
FitnessSync/backend/src/api/config_routes.py
Normal file
121
FitnessSync/backend/src/api/config_routes.py
Normal file
@@ -0,0 +1,121 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
import logging
|
||||
import requests
|
||||
import base64
|
||||
import json
|
||||
|
||||
from ..services.postgresql_manager import PostgreSQLManager
|
||||
from ..utils.config import config
|
||||
|
||||
router = APIRouter()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def get_db():
|
||||
db_manager = PostgreSQLManager(config.DATABASE_URL)
|
||||
with db_manager.get_db_session() as session:
|
||||
yield session
|
||||
|
||||
@router.post("/setup/load-consul-config")
|
||||
def load_consul_config(db: Session = Depends(get_db)):
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.info("Attempting to load configuration from Consul...")
|
||||
try:
|
||||
# User defined Consul URL
|
||||
consul_host = "consul.service.dc1.consul"
|
||||
consul_port = "8500"
|
||||
app_prefix = "fitbit-garmin-sync/"
|
||||
consul_url = f"http://{consul_host}:{consul_port}/v1/kv/{app_prefix}?recurse=true"
|
||||
|
||||
logger.debug(f"Connecting to Consul at: {consul_url}")
|
||||
|
||||
response = requests.get(consul_url, timeout=5)
|
||||
if response.status_code == 404:
|
||||
logger.warning(f"No configuration found in Consul under '{app_prefix}'")
|
||||
raise HTTPException(status_code=404, detail="No configuration found in Consul")
|
||||
response.raise_for_status()
|
||||
|
||||
data = response.json()
|
||||
|
||||
config_map = {}
|
||||
|
||||
# Helper to decode Consul values
|
||||
def decode_consul_value(val):
|
||||
if not val: return None
|
||||
try:
|
||||
return base64.b64decode(val).decode('utf-8')
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to decode value: {e}")
|
||||
return None
|
||||
|
||||
# Pass 1: Load all raw keys
|
||||
for item in data:
|
||||
key = item['Key'].replace(app_prefix, '')
|
||||
value = decode_consul_value(item.get('Value'))
|
||||
if value:
|
||||
config_map[key] = value
|
||||
|
||||
# Pass 2: Check for special 'config' key (JSON blob)
|
||||
if 'config' in config_map:
|
||||
try:
|
||||
json_config = json.loads(config_map['config'])
|
||||
logger.debug("Found 'config' key with JSON content, merging...")
|
||||
config_map.update(json_config)
|
||||
except json.JSONDecodeError:
|
||||
logger.warning("'config' key found but is not valid JSON, ignoring as blob.")
|
||||
|
||||
logger.debug(f"Resolved configuration keys: {list(config_map.keys())}")
|
||||
|
||||
# Look for standard keys
|
||||
username = config_map.get('garmin_username') or config_map.get('USERNAME')
|
||||
password = config_map.get('garmin_password') or config_map.get('PASSWORD')
|
||||
is_china = str(config_map.get('is_china', 'false')).lower() == 'true'
|
||||
|
||||
if not username and isinstance(config_map.get('garmin'), dict):
|
||||
logger.debug("Found nested 'garmin' config object.")
|
||||
garmin_conf = config_map['garmin']
|
||||
username = garmin_conf.get('username')
|
||||
password = garmin_conf.get('password')
|
||||
if 'is_china' in garmin_conf:
|
||||
is_china = str(garmin_conf.get('is_china')).lower() == 'true'
|
||||
|
||||
if not username or not password:
|
||||
logger.error("Consul config resolved but missing 'garmin_username' or 'garmin_password'")
|
||||
raise HTTPException(status_code=400, detail="Consul config missing credentials")
|
||||
|
||||
# Extract Fitbit credentials
|
||||
fitbit_client_id = config_map.get('fitbit_client_id')
|
||||
fitbit_client_secret = config_map.get('fitbit_client_secret')
|
||||
fitbit_redirect_uri = config_map.get('fitbit_redirect_uri')
|
||||
|
||||
if isinstance(config_map.get('fitbit'), dict):
|
||||
logger.debug("Found nested 'fitbit' config object.")
|
||||
fitbit_conf = config_map['fitbit']
|
||||
fitbit_client_id = fitbit_conf.get('client_id')
|
||||
fitbit_client_secret = fitbit_conf.get('client_secret')
|
||||
|
||||
logger.info("Consul config loaded successfully. Returning to frontend.")
|
||||
|
||||
return {
|
||||
"status": "success",
|
||||
"message": "Configuration loaded from Consul",
|
||||
"garmin": {
|
||||
"username": username,
|
||||
"password": password,
|
||||
"is_china": is_china
|
||||
},
|
||||
"fitbit": {
|
||||
"client_id": fitbit_client_id,
|
||||
"client_secret": fitbit_client_secret,
|
||||
"redirect_uri": fitbit_redirect_uri
|
||||
}
|
||||
}
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"Failed to connect to Consul: {e}")
|
||||
raise HTTPException(status_code=502, detail=f"Failed to connect to Consul: {str(e)}")
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Error loading from Consul: {e}", exc_info=True)
|
||||
raise HTTPException(status_code=500, detail=f"Internal error loading config: {str(e)}")
|
||||
Reference in New Issue
Block a user