diff --git a/API_SERVICE.md b/API_SERVICE.md new file mode 100644 index 0000000..b98b6fe --- /dev/null +++ b/API_SERVICE.md @@ -0,0 +1,97 @@ +# Signature Validation API Service + +This is a lightweight Python service that provides signature validation for the PHP application. + +## Why a separate service? + +The `bibapi` library is Python-only and provides access to your library catalog. Rather than rewriting this in PHP, we keep a small Python service running just for signature validation. + +## Running the Service + +### Option 1: Direct Python +```bash +python api_service.py +``` + +### Option 2: With uvicorn +```bash +uvicorn api_service:app --host 0.0.0.0 --port 8001 +``` + +### Option 3: Docker (if you can run containers internally) +```dockerfile +FROM python:3.13-slim +WORKDIR /app +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt +COPY api_service.py . +EXPOSE 8001 +CMD ["uvicorn", "api_service:app", "--host", "0.0.0.0", "--port", "8001"] +``` + +```bash +docker build -t signature-api . +docker run -d -p 8001:8001 signature-api +``` + +## Configuration + +Set the API endpoint in your PHP config. Update `php/config.php`: + +```php +// Signature validation API endpoint (optional) +define('SIGNATURE_API_URL', getenv('SIGNATURE_API_URL') ?: 'http://localhost:8001'); +``` + +## Testing + +```bash +# Health check +curl http://localhost:8001/health + +# Validate a signature +curl "http://localhost:8001/api/validate-signature?signature=ABC123" +``` + +## Production Deployment + +1. **Same server**: Run on a different port (8001) alongside your PHP application +2. **Separate server**: Run on internal network, update `SIGNATURE_API_URL` in PHP config +3. **Systemd service** (Linux): + +Create `/etc/systemd/system/signature-api.service`: +```ini +[Unit] +Description=Signature Validation API +After=network.target + +[Service] +Type=simple +User=www-data +WorkingDirectory=/var/www/signature-api +Environment="PATH=/var/www/signature-api/.venv/bin" +ExecStart=/var/www/signature-api/.venv/bin/uvicorn api_service:app --host 0.0.0.0 --port 8001 +Restart=always + +[Install] +WantedBy=multi-user.target +``` + +Then: +```bash +sudo systemctl enable signature-api +sudo systemctl start signature-api +``` + +## Security + +- In production, update CORS `allow_origins` to only your PHP server domain +- Consider adding API key authentication if exposed to public network +- Run behind reverse proxy (nginx/Apache) with SSL + +## Notes + +- The service is stateless and lightweight +- No data persistence required +- Can be scaled horizontally if needed +- Falls back gracefully if unavailable (ELSA form fields just won't have validation hints) diff --git a/api_service.py b/api_service.py new file mode 100644 index 0000000..543fcb7 --- /dev/null +++ b/api_service.py @@ -0,0 +1,67 @@ +""" +Lightweight Python API service for signature validation +This can run independently to support the PHP application +""" +from fastapi import FastAPI, Query +from fastapi.responses import JSONResponse +from fastapi.middleware.cors import CORSMiddleware +from bibapi import catalogue +import re +import os + +app = FastAPI(title="Signature Validation API") + +# Allow PHP application to call this API +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], # In production, restrict to your PHP server domain + allow_credentials=True, + allow_methods=["GET"], + allow_headers=["*"], +) + +# Initialize catalogue for signature validation +cat = catalogue.Catalogue() + +@app.get("/api/validate-signature") +async def validate_signature(signature: str = Query(...)): + """Validate a book signature and return total pages""" + try: + book_result = cat.get_book_with_data(signature) + if book_result and hasattr(book_result, "pages") and book_result.pages: + # Try to extract numeric page count + pages_str = str(book_result.pages) + # Extract first number from pages string (e.g., "245 S." -> 245) + match = re.search(r"(\d+)", pages_str) + if match: + total_pages = int(match.group(1)) + return JSONResponse( + {"valid": True, "total_pages": total_pages, "signature": signature} + ) + + return JSONResponse( + { + "valid": False, + "error": "Signatur nicht gefunden oder keine Seitenzahl verfügbar", + "signature": signature, + } + ) + except Exception as e: + return JSONResponse( + { + "valid": False, + "error": f"Fehler bei der Validierung: {str(e)}", + "signature": signature, + }, + status_code=500 + ) + +@app.get("/health") +async def health_check(): + """Health check endpoint""" + return {"status": "ok", "service": "signature-validation"} + +if __name__ == "__main__": + import uvicorn + port = int(os.getenv("API_PORT", "8001")) + uvicorn.run(app, host="0.0.0.0", port=port) diff --git a/php/config.php b/php/config.php index 56db04c..4db6933 100644 --- a/php/config.php +++ b/php/config.php @@ -24,5 +24,8 @@ define('MAIL_TO', getenv('MAIL_TO') ?: 'semesterapparate@ph-freiburg.de'); define('BASE_PATH', __DIR__); define('STATIC_PATH', '/static'); +// Signature validation API (optional Python service) +define('SIGNATURE_API_URL', getenv('SIGNATURE_API_URL') ?: 'http://localhost:8001'); + // Email regex pattern define('EMAIL_REGEX', '/^[^@\s]+@[^@\s]+\.[^@\s]+$/'); diff --git a/php/elsa.php b/php/elsa.php index 9be4905..b70b41b 100644 --- a/php/elsa.php +++ b/php/elsa.php @@ -34,7 +34,7 @@
-