diff --git a/alembic/versions/20250418_140631_85c18764_update_routingapi.py b/alembic/versions/20250418_140631_85c18764_update_routingapi.py new file mode 100644 index 0000000..e1e1234 --- /dev/null +++ b/alembic/versions/20250418_140631_85c18764_update_routingapi.py @@ -0,0 +1,32 @@ +"""create table for routing_apis +Revision ID: 2d7a3b8c4e7b +Revises: 0001 +Create Date: 2023-05-10 12:34:56.789012 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.sql import func +import uuid + +# revision identifiers, used by Alembic. +revision = '2d7a3b8c4e7b' +down_revision = '0001' +branch_labels = None +depends_on = None + +def upgrade(): + op.create_table( + 'routing_apis', + sa.Column('id', sa.String(36), primary_key=True, default=lambda: str(uuid.uuid4())), + sa.Column('name', sa.String(), nullable=False, unique=True), + sa.Column('description', sa.String(), nullable=True), + sa.Column('api_key', sa.String(), nullable=False, unique=True), + sa.Column('max_requests', sa.Integer(), nullable=False, server_default='1000'), + sa.Column('created_at', sa.DateTime(), server_default=func.now()), + sa.Column('updated_at', sa.DateTime(), server_default=func.now(), onupdate=func.now()), + sa.Index('ix_routing_apis_name', 'name') + ) + +def downgrade(): + op.drop_table('routing_apis') \ No newline at end of file diff --git a/endpoints/Route.get.py b/endpoints/Route.get.py index e69de29..3dbce09 100644 --- a/endpoints/Route.get.py +++ b/endpoints/Route.get.py @@ -0,0 +1,16 @@ +from fastapi import APIRouter, Depends +from typing import List +from sqlalchemy.orm import Session +from core.database import get_db +from schemas.routing_api import RoutingAPISchema +from helpers.routing_api_helpers import get_all_routing_apis, get_routing_api_schema + +router = APIRouter() + +@router.get("/Route", status_code=200, response_model=List[RoutingAPISchema]) +async def get_routes( + db: Session = Depends(get_db) +): + routing_apis = get_all_routing_apis(db) + routing_api_schemas = [get_routing_api_schema(routing_api) for routing_api in routing_apis] + return routing_api_schemas \ No newline at end of file diff --git a/helpers/routing_api_helpers.py b/helpers/routing_api_helpers.py new file mode 100644 index 0000000..a16202f --- /dev/null +++ b/helpers/routing_api_helpers.py @@ -0,0 +1,142 @@ +from typing import List, Optional +from sqlalchemy.orm import Session +import uuid +from models.routing_api import RoutingAPI +from schemas.routing_api import RoutingAPICreate, RoutingAPIUpdate, RoutingAPISchema + +def get_routing_api_by_id(db: Session, routing_api_id: uuid.UUID) -> Optional[RoutingAPI]: + """ + Retrieves a routing API by its ID. + + Args: + db (Session): The database session. + routing_api_id (UUID): The ID of the routing API to retrieve. + + Returns: + Optional[RoutingAPI]: The routing API object if found, otherwise None. + """ + return db.query(RoutingAPI).filter(RoutingAPI.id == routing_api_id).first() + +def get_all_routing_apis(db: Session) -> List[RoutingAPI]: + """ + Retrieves all routing APIs from the database. + + Args: + db (Session): The database session. + + Returns: + List[RoutingAPI]: A list of all routing API objects. + """ + return db.query(RoutingAPI).all() + +def create_routing_api(db: Session, routing_api_data: RoutingAPICreate) -> RoutingAPI: + """ + Creates a new routing API in the database. + + Args: + db (Session): The database session. + routing_api_data (RoutingAPICreate): The data for the routing API to create. + + Returns: + RoutingAPI: The newly created routing API object. + """ + db_routing_api = RoutingAPI(**routing_api_data.dict()) + db.add(db_routing_api) + db.commit() + db.refresh(db_routing_api) + return db_routing_api + +def update_routing_api(db: Session, routing_api_id: uuid.UUID, routing_api_data: RoutingAPIUpdate) -> RoutingAPI: + """ + Updates an existing routing API in the database. + + Args: + db (Session): The database session. + routing_api_id (UUID): The ID of the routing API to update. + routing_api_data (RoutingAPIUpdate): The updated data for the routing API. + + Returns: + RoutingAPI: The updated routing API object. + """ + db_routing_api = db.query(RoutingAPI).filter(RoutingAPI.id == routing_api_id).first() + if not db_routing_api: + raise ValueError(f"Routing API with ID {routing_api_id} not found") + + update_data = routing_api_data.dict(exclude_unset=True) + for key, value in update_data.items(): + setattr(db_routing_api, key, value) + + db.commit() + db.refresh(db_routing_api) + return db_routing_api + +def delete_routing_api(db: Session, routing_api_id: uuid.UUID) -> bool: + """ + Deletes a routing API from the database. + + Args: + db (Session): The database session. + routing_api_id (UUID): The ID of the routing API to delete. + + Returns: + bool: True if the routing API was deleted, False otherwise. + """ + db_routing_api = db.query(RoutingAPI).filter(RoutingAPI.id == routing_api_id).first() + if not db_routing_api: + return False + + db.delete(db_routing_api) + db.commit() + return True + +def generate_api_key(db: Session, routing_api: RoutingAPI) -> str: + """ + Generates a unique API key for a routing API. + + Args: + db (Session): The database session. + routing_api (RoutingAPI): The routing API object. + + Returns: + str: The generated API key. + """ + existing_keys = db.query(RoutingAPI.api_key).all() + existing_keys = [key[0] for key in existing_keys] + + api_key = str(uuid.uuid4()) + while api_key in existing_keys: + api_key = str(uuid.uuid4()) + + routing_api.api_key = api_key + db.commit() + db.refresh(routing_api) + return api_key + +def get_routing_api_schema(db_routing_api: RoutingAPI) -> RoutingAPISchema: + """ + Converts a RoutingAPI model object to a RoutingAPISchema object. + + Args: + db_routing_api (RoutingAPI): The RoutingAPI model object. + + Returns: + RoutingAPISchema: The corresponding RoutingAPISchema object. + """ + return RoutingAPISchema.from_orm(db_routing_api) + +def get_routing_api_requests_count(db: Session, routing_api_id: uuid.UUID) -> int: + """ + Retrieves the number of requests made to a routing API. + + Args: + db (Session): The database session. + routing_api_id (UUID): The ID of the routing API. + + Returns: + int: The number of requests made to the routing API. + """ + routing_api = db.query(RoutingAPI).filter(RoutingAPI.id == routing_api_id).first() + if not routing_api: + raise ValueError(f"Routing API with ID {routing_api_id} not found") + + return len(routing_api.routes) \ No newline at end of file diff --git a/models/routing_api.py b/models/routing_api.py new file mode 100644 index 0000000..c6646d4 --- /dev/null +++ b/models/routing_api.py @@ -0,0 +1,19 @@ +from sqlalchemy import Column, String, Integer, DateTime +from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy.orm import relationship +from sqlalchemy.sql import func +from core.database import Base +import uuid + +class RoutingAPI(Base): + __tablename__ = "routing_apis" + + id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) + name = Column(String, nullable=False, unique=True, index=True) + description = Column(String, nullable=True) + api_key = Column(String, nullable=False, unique=True) + max_requests = Column(Integer, nullable=False, default=1000) + created_at = Column(DateTime, default=func.now()) + updated_at = Column(DateTime, default=func.now(), onupdate=func.now()) + + routes = relationship("Route", back_populates="routing_api") \ No newline at end of file diff --git a/schemas/routing_api.py b/schemas/routing_api.py new file mode 100644 index 0000000..8041dac --- /dev/null +++ b/schemas/routing_api.py @@ -0,0 +1,27 @@ +from pydantic import BaseModel, Field +from typing import Optional +from datetime import datetime +import uuid + +class RoutingAPIBase(BaseModel): + name: str = Field(..., description="Name of the routing API") + description: Optional[str] = Field(None, description="Description of the routing API") + api_key: str = Field(..., description="API key for the routing API") + max_requests: int = Field(..., description="Maximum number of requests allowed for the routing API") + +class RoutingAPICreate(RoutingAPIBase): + pass + +class RoutingAPIUpdate(RoutingAPIBase): + name: Optional[str] = Field(None, description="Name of the routing API") + description: Optional[str] = Field(None, description="Description of the routing API") + api_key: Optional[str] = Field(None, description="API key for the routing API") + max_requests: Optional[int] = Field(None, description="Maximum number of requests allowed for the routing API") + +class RoutingAPISchema(RoutingAPIBase): + id: uuid.UUID + created_at: datetime + updated_at: datetime + + class Config: + orm_mode = True \ No newline at end of file