From 8a87a78449834c29b0f4e9612154908b42fd58fc Mon Sep 17 00:00:00 2001 From: matthewexe Date: Sat, 2 Aug 2025 01:52:25 +0200 Subject: [PATCH] geo-access --- backend/docker-compose.yaml | 8 ++--- backend/endpoints/__init__.py | 0 backend/endpoints/geo_access.py | 33 ++++++++++++++++++ backend/geo_access.py | 60 +++++++++++++++++++++++++++++++++ backend/main.py | 15 ++++++++- backend/routes.py | 7 +++- 6 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 backend/endpoints/__init__.py create mode 100644 backend/endpoints/geo_access.py create mode 100644 backend/geo_access.py diff --git a/backend/docker-compose.yaml b/backend/docker-compose.yaml index 8347b75..f569bbc 100644 --- a/backend/docker-compose.yaml +++ b/backend/docker-compose.yaml @@ -7,8 +7,8 @@ services: ports: - "27017:27017" environment: - MONGO_INITDB_ROOT_USERNAME: admin - MONGO_INITDB_ROOT_PASSWORD: password + MONGO_INITDB_ROOT_USERNAME: ${ME_CONFIG_MONGODB_ADMIN_USERNAME} + MONGO_INITDB_ROOT_PASSWORD: ${ME_CONFIG_MONGODB_ADMIN_PASSWORD} volumes: - mongodb_data:/data/db restart: unless-stopped @@ -19,8 +19,8 @@ services: ports: - "8081:8081" environment: - ME_CONFIG_MONGODB_ADMINUSERNAME: admin - ME_CONFIG_MONGODB_ADMINPASSWORD: password + ME_CONFIG_MONGODB_ADMINUSERNAME: ${ME_CONFIG_MONGODB_ADMIN_USERNAME} + ME_CONFIG_MONGODB_ADMINPASSWORD: ${ME_CONFIG_MONGODB_ADMIN_PASSWORD} ME_CONFIG_MONGODB_URL: mongodb://admin:password@mongodb:27017/ depends_on: - mongodb diff --git a/backend/endpoints/__init__.py b/backend/endpoints/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/endpoints/geo_access.py b/backend/endpoints/geo_access.py new file mode 100644 index 0000000..e669371 --- /dev/null +++ b/backend/endpoints/geo_access.py @@ -0,0 +1,33 @@ +from dataclasses import dataclass +from typing import Literal, TypedDict + +from fastapi import APIRouter + +from geo_access import lido_circle_checker + +geo_access_router = APIRouter(prefix="/geo-access") + +@dataclass +class GeoAccessRequest: + """ + Request model for geo access. + """ + coords: tuple[float, float] + type: Literal["circle", "polygon"] | None = "circle" + + +type_checker = { + "circle": lido_circle_checker, + # "polygon": lido_polygon_checker +} + + +@geo_access_router.post("/") +async def get_geo_access(request: GeoAccessRequest): + with open("test.json", "w") as f: + f.write(repr(request)) + + # return { + # "success": type_checker.get(request.type, "circle").is_inside(request.coords) + # } + return {"success": True} diff --git a/backend/geo_access.py b/backend/geo_access.py new file mode 100644 index 0000000..eb19a12 --- /dev/null +++ b/backend/geo_access.py @@ -0,0 +1,60 @@ +from math import radians, sin, cos, sqrt, atan2 +from shapely import Polygon + + +# class PolygonChecker: +# """ +# A class to check if a point is inside a polygon defined by its vertices. +# The polygon is defined by a list of points (latitude, longitude). +# +# """ +# def __init__(self, *points): +# self.coords = points[:] if points else [] +# self.polygon = Polygon(self.coords) +# +# def is_inside(self, point) -> bool: +# return self.polygon.contains(point) + +class CircleChecker: + """ + A class to check if a point is inside a circle defined by its center and radius. + The circle is defined by a center point (latitude, longitude) and a radius in meters + """ + def __init__(self, center, radius_meters): + self.center = center + self.radius_meters = radius_meters + + def is_inside(self, point) -> bool: + return is_inside_circle(self.center, point, self.radius_meters) + + +def is_inside_circle(center, point, radius_meters): + R = 6371000 # Earth radius in meters + lat1, lon1 = center + lat2, lon2 = point + + dlat = radians(lat2 - lat1) + dlon = radians(lon2 - lon1) + + a = sin(dlat / 2) ** 2 + cos(radians(lat1)) * cos(radians(lat2)) * sin(dlon / 2) ** 2 + c = 2 * atan2(sqrt(a), sqrt(1 - a)) + distance = R * c + + return distance <= radius_meters + + +# Default CircleChecker with a radius of 1000 meters +lido_circle_checker = CircleChecker((46.6770371, 11.1860135), 160) # Center + +# Default PolygonChecker with a predefined polygon +# polygon_coords = [ +# (46.677168, 11.185606), +# (46.676910, 11.185692), +# (46.676673, 11.186094), +# (46.676691, 11.186630), +# (46.676673, 11.187094), +# (46.677309, 11.187242), +# (46.677280, 11.185606) +# ] +# +# lido_polygon_checker = PolygonChecker(polygon_coords) \ No newline at end of file diff --git a/backend/main.py b/backend/main.py index e2744c8..b44d4ae 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1,7 +1,12 @@ +from dotenv import load_dotenv from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware + +from endpoints.geo_access import geo_access_router from routes import router +load_dotenv() + app = FastAPI(title="Simple Fullstack API") # CORS per permettere richieste dal frontend @@ -15,8 +20,16 @@ app.add_middleware( # Includi le route app.include_router(router) +app.include_router(geo_access_router) + + +@app.post("/auth") +def auth(): + pass + if __name__ == "__main__": import uvicorn + print("🚀 Avvio server FastAPI...") - uvicorn.run(app, host="0.0.0.0", port=8000) \ No newline at end of file + uvicorn.run(app, host="0.0.0.0", port=8000) diff --git a/backend/routes.py b/backend/routes.py index 4621b8b..eb66c31 100644 --- a/backend/routes.py +++ b/backend/routes.py @@ -1,3 +1,5 @@ +import os + from fastapi import APIRouter, HTTPException from pymongo import MongoClient from datetime import datetime @@ -6,7 +8,10 @@ from datetime import datetime router = APIRouter() # Connessione MongoDB -client = MongoClient("mongodb://localhost:27017/") +username = os.getenv("ME_CONFIG_MONGODB_ADMIN_USERNAME") +password = os.getenv("ME_CONFIG_MONGODB_ADMIN_PASSWORD") + +client = MongoClient(f"mongodb://admin:password@localhost:27017/") db = client["simple_db"] collection = db["items"]