diff --git a/alpinebits.log b/alpinebits.log index 4734a81..364764c 100644 --- a/alpinebits.log +++ b/alpinebits.log @@ -10,3 +10,30 @@ 2025-10-09 14:28:51 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured 2025-10-09 14:28:51 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured 2025-10-09 14:28:51 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-09 16:54:04 - root - INFO - Logging to file: alpinebits.log +2025-10-09 16:54:04 - root - INFO - Logging configured at INFO level +2025-10-09 16:54:04 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-09 16:54:04 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-09 16:54:04 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-09 16:54:04 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-09 16:54:04 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-09 16:54:04 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-09 16:54:04 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-09 16:54:04 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-09 16:54:04 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-09 16:54:04 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-09 16:54:48 - root - INFO - Logging to file: alpinebits.log +2025-10-09 16:54:48 - root - INFO - Logging configured at INFO level +2025-10-09 16:54:48 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-09 16:54:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-09 16:54:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-09 16:54:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-09 16:54:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-09 16:54:48 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-09 16:54:48 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-09 16:54:48 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-09 16:54:48 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-09 16:54:48 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-09 16:54:50 - alpine_bits_python.api - INFO - AlpineBits authentication successful for user: sebastian (from config) +2025-10-09 16:54:50 - alpine_bits_python.api - INFO - Created directory: logs/conversions_import +2025-10-09 16:54:50 - alpine_bits_python.api - INFO - XML file saved to logs/conversions_import/file_sebastian_20251009_165450.xml by user sebastian (original: file.xml) diff --git a/src/alpine_bits_python/api.py b/src/alpine_bits_python/api.py index 8fd584d..3c31881 100644 --- a/src/alpine_bits_python/api.py +++ b/src/alpine_bits_python/api.py @@ -580,6 +580,7 @@ async def handle_xml_upload( credentials_tupel: tuple = Depends(validate_basic_auth), ): """Endpoint for receiving XML files for conversion processing via PUT. + Requires basic authentication and saves XML files to log directory. Supports gzip compression via Content-Encoding header. diff --git a/src/alpine_bits_python/auth.py b/src/alpine_bits_python/auth.py index 8e56717..83e6f66 100644 --- a/src/alpine_bits_python/auth.py +++ b/src/alpine_bits_python/auth.py @@ -9,7 +9,7 @@ from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer # Load environment variables from .env file load_dotenv() -from alpine_bits_python.logging_config import get_logger +from .logging_config import get_logger logger = get_logger(__name__) @@ -31,12 +31,12 @@ if os.getenv("ADMIN_API_KEY"): def generate_unique_id() -> str: - """Generate a unique ID with max length 35 characters""" - return secrets.token_urlsafe(26)[:35] # 26 bytes -> 35 chars in base64url + """Generate a unique ID with max length 32 characters.""" + return secrets.token_urlsafe(26)[:32] # 26 bytes -> 32 chars in base64url def generate_api_key() -> str: - """Generate a secure API key""" + """Generate a secure API key.""" return f"sk_live_{secrets.token_urlsafe(32)}" @@ -44,6 +44,7 @@ def validate_api_key( credentials: HTTPAuthorizationCredentials = Security(security), ) -> str: """Validate API key from Authorization header. + Expected format: Authorization: Bearer your_api_key_here """ token = credentials.credentials @@ -64,6 +65,7 @@ def validate_api_key( def validate_wix_signature(payload: bytes, signature: str, secret: str) -> bool: """Validate Wix webhook signature for additional security. + Wix signs their webhooks with HMAC-SHA256. """ if not signature or not secret: diff --git a/src/alpine_bits_python/main.py b/src/alpine_bits_python/main.py index 38a303c..d62223c 100644 --- a/src/alpine_bits_python/main.py +++ b/src/alpine_bits_python/main.py @@ -20,16 +20,9 @@ from .alpine_bits_helpers import ( from .config_loader import load_config # DB and config -from .db import ( - Base, - get_database_url, -) -from .db import ( - Customer as DBCustomer, -) -from .db import ( - Reservation as DBReservation, -) +from .db import Base, get_database_url +from .db import Customer as DBCustomer +from .db import Reservation as DBReservation from .generated import alpinebits as ab # Configure logging @@ -124,13 +117,13 @@ async def main(): num_children = int(data.get("field:anzahl_kinder") or 0) children_ages = [] if num_children > 0: - for k in data.keys(): + for k in data: if k.startswith("field:alter_kind_"): try: age = int(data[k]) children_ages.append(age) except ValueError: - logging.warning(f"Invalid age value for {k}: {data[k]}") + _LOGGER.warning("Invalid age value for %s: %s", k, data[k]) # UTM and offer utm_fields = [ @@ -208,6 +201,7 @@ async def main(): def create_xml_from_db(customer: DBCustomer, reservation: DBReservation): + """Generate AlpineBits XML from DB customer and reservation data.""" # Prepare data for XML phone_numbers = [(customer.phone, PhoneTechType.MOBILE)] if customer.phone else [] customer_data = CustomerData(