Compare commits
2 Commits
4af1996fb4
...
e6e8cf0e42
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6e8cf0e42 | ||
|
|
ce868e1807 |
15
.env.dist
Normal file
15
.env.dist
Normal file
@@ -0,0 +1,15 @@
|
||||
BASIC_AUTH_PASSWORD="your_password_here"
|
||||
BASIC_AUTH_USER="your_username_here"
|
||||
COLLECTION_NAME="ingress"
|
||||
DB_NAME="ingress"
|
||||
ENDPOINT_URL="http://web:7000/plexts"
|
||||
INGRESS_COOKIE="csrftoken=...; sessionid=...; ingress.intelmap.zoom=10; ingress.intelmap.lat=45.80534988266492; ingress.intelmap.lng=12.471542358398438"
|
||||
MAX_LAT="46422713"
|
||||
MAX_LNG="14201202"
|
||||
MIN_LAT="45181069"
|
||||
MIN_LNG="10741882"
|
||||
MONGO_URI="mongodb://user:password@mongodb:27017/?authSource=admin"
|
||||
PORT=7000
|
||||
PYTHONUNBUFFERED=1
|
||||
TZ="Europe/Rome"
|
||||
V="412c0ac7e784d6df783fc507bca30e23b3c58c55"
|
||||
152
app.py
152
app.py
@@ -2,9 +2,12 @@ import os
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from zoneinfo import ZoneInfo
|
||||
from flask import Flask, request, jsonify
|
||||
from functools import wraps
|
||||
from flask import Flask, request, jsonify, Response
|
||||
from ingress import IngressAPI
|
||||
from models import EventType, Plext
|
||||
from pymongo import MongoClient
|
||||
from pymongo.errors import PyMongoError
|
||||
|
||||
# Timezone configuration
|
||||
TIMEZONE = ZoneInfo("Europe/Rome")
|
||||
@@ -18,6 +21,51 @@ logger = logging.getLogger(__name__)
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
def check_basic_auth(username: str, password: str) -> bool:
|
||||
"""
|
||||
Check if the provided username and password match the configured credentials.
|
||||
|
||||
Args:
|
||||
username: Username from the request
|
||||
password: Password from the request
|
||||
|
||||
Returns:
|
||||
True if credentials match, False otherwise
|
||||
"""
|
||||
expected_username = os.getenv("BASIC_AUTH_USER")
|
||||
expected_password = os.getenv("BASIC_AUTH_PASSWORD")
|
||||
|
||||
if not expected_username or not expected_password:
|
||||
logger.warning("BASIC_AUTH_USER or BASIC_AUTH_PASSWORD not configured")
|
||||
return False
|
||||
|
||||
return username == expected_username and password == expected_password
|
||||
|
||||
|
||||
def basic_auth_required(f):
|
||||
"""
|
||||
Decorator to require basic authentication for an endpoint.
|
||||
|
||||
Returns:
|
||||
401 Unauthorized if authentication fails or is missing
|
||||
"""
|
||||
@wraps(f)
|
||||
def decorated(*args, **kwargs):
|
||||
auth = request.authorization
|
||||
|
||||
if not auth or not check_basic_auth(auth.username, auth.password):
|
||||
return Response(
|
||||
"Could not verify your access level for that URL.\n"
|
||||
"You have to login with proper credentials",
|
||||
401,
|
||||
{"WWW-Authenticate": 'Basic realm="Login Required"'}
|
||||
)
|
||||
|
||||
return f(*args, **kwargs)
|
||||
|
||||
return decorated
|
||||
|
||||
|
||||
def parse_timestamp(value: str) -> int:
|
||||
"""
|
||||
Parse timestamp from either milliseconds (int) or ISO 8601 string.
|
||||
@@ -102,9 +150,93 @@ def plext_to_dict(plext: Plext) -> dict:
|
||||
],
|
||||
}
|
||||
|
||||
@app.route("/plexts/from-db", methods=["GET"])
|
||||
@basic_auth_required
|
||||
def get_plexts_from_db():
|
||||
"""
|
||||
Get plexts from MongoDB with optional filters.
|
||||
|
||||
@app.route("/plexts", methods=["GET"])
|
||||
def get_plexts():
|
||||
Query Parameters:
|
||||
player_name: Filter by player name (optional)
|
||||
timestamp_from: Minimum timestamp in milliseconds (optional)
|
||||
timestamp_to: Maximum timestamp in milliseconds (optional)
|
||||
|
||||
Returns:
|
||||
JSON response with list of plexts (without _id field)
|
||||
"""
|
||||
try:
|
||||
# Parse query parameters
|
||||
player_name = request.args.get("player_name")
|
||||
timestamp_from = request.args.get("timestamp_from")
|
||||
timestamp_to = request.args.get("timestamp_to")
|
||||
|
||||
# Validate and convert timestamp parameters to integers if provided
|
||||
if timestamp_from is not None:
|
||||
try:
|
||||
timestamp_from = int(timestamp_from)
|
||||
except ValueError:
|
||||
return jsonify({"error": "timestamp_from must be an integer"}), 400
|
||||
|
||||
if timestamp_to is not None:
|
||||
try:
|
||||
timestamp_to = int(timestamp_to)
|
||||
except ValueError:
|
||||
return jsonify({"error": "timestamp_to must be an integer"}), 400
|
||||
|
||||
# Build MongoDB filter query
|
||||
filter_query = {}
|
||||
|
||||
if player_name:
|
||||
filter_query["player_name"] = player_name
|
||||
|
||||
if timestamp_from is not None:
|
||||
filter_query["timestamp"] = filter_query.get("timestamp", {})
|
||||
filter_query["timestamp"]["$gte"] = timestamp_from
|
||||
|
||||
if timestamp_to is not None:
|
||||
filter_query["timestamp"] = filter_query.get("timestamp", {})
|
||||
filter_query["timestamp"]["$lte"] = timestamp_to
|
||||
|
||||
# Connect to MongoDB
|
||||
mongo_uri = os.getenv("MONGO_URI")
|
||||
db_name = os.getenv("DB_NAME")
|
||||
collection_name = os.getenv("COLLECTION_NAME")
|
||||
|
||||
client = MongoClient(mongo_uri)
|
||||
db = client[db_name]
|
||||
collection = db[collection_name]
|
||||
|
||||
try:
|
||||
# Projection to exclude _id field
|
||||
projection = {"_id": 0}
|
||||
|
||||
# Execute query with sorting (timestamp DESC - most recent first)
|
||||
cursor = collection.find(
|
||||
filter=filter_query,
|
||||
projection=projection
|
||||
).sort("timestamp", -1)
|
||||
|
||||
# Convert cursor to list
|
||||
plexts = list(cursor)
|
||||
|
||||
return jsonify({
|
||||
"count": len(plexts),
|
||||
"plexts": plexts
|
||||
})
|
||||
|
||||
except PyMongoError as e:
|
||||
logger.error(f"MongoDB error: {e}")
|
||||
return jsonify({"error": "Database error"}), 500
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
except Exception as e:
|
||||
logger.exception("Unexpected error in get_plexts_from_db")
|
||||
return jsonify({"error": "An error occurred"}), 500
|
||||
|
||||
@app.route("/plexts/from-api", methods=["GET"])
|
||||
@basic_auth_required
|
||||
def get_plexts_from_api():
|
||||
"""
|
||||
Get plexts from the Ingress API.
|
||||
|
||||
@@ -199,7 +331,7 @@ def index():
|
||||
"name": "Ingress Intel API",
|
||||
"version": "1.0.0",
|
||||
"endpoints": {
|
||||
"/plexts": {
|
||||
"/plexts/from-api": {
|
||||
"method": "GET",
|
||||
"description": "Get plexts from the Ingress API",
|
||||
"parameters": {
|
||||
@@ -213,7 +345,17 @@ def index():
|
||||
"max_timestamp": "Maximum timestamp (milliseconds or ISO 8601 format, default: -1)",
|
||||
},
|
||||
"event_types": [e.name for e in EventType],
|
||||
}
|
||||
},
|
||||
"/plexts/from-db": {
|
||||
"method": "GET",
|
||||
"description": "Get plexts from MongoDB with optional filters",
|
||||
"parameters": {
|
||||
"player_name": "Filter by player name (optional)",
|
||||
"timestamp_from": "Minimum timestamp in milliseconds (optional)",
|
||||
"timestamp_to": "Maximum timestamp in milliseconds (optional)",
|
||||
},
|
||||
"authentication": "Basic Auth required",
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user