Fix bugs and update ACL of flights API

This commit is contained in:
Santiago Lo Coco 2023-10-27 15:10:44 -03:00
parent 3e7515b9b1
commit a538c5f74c
12 changed files with 53 additions and 23 deletions

1
.gitignore vendored
View File

@ -7,3 +7,4 @@ node_modules
*.xml *.xml
notification-domain/ notification-domain/
TODO.txt TODO.txt
*.sh

View File

@ -17,6 +17,7 @@ def recreate_db():
@cli.command("seed_db") @cli.command("seed_db")
def seed_db(): def seed_db():
db.session.add(User(username="lufthansa", email="info@lufthansa.com", password="password1234", airline=True)) db.session.add(User(username="lufthansa", email="info@lufthansa.com", password="password1234", airline=True))
db.session.add(User(username="ryanair", email="info@ryanair.com", password="password1234", airline=True))
db.session.add(User(username="messi", email="messi@gmail.com", password="password1234")) db.session.add(User(username="messi", email="messi@gmail.com", password="password1234"))
db.session.commit() db.session.commit()

View File

@ -21,6 +21,7 @@ services:
condition: service_healthy condition: service_healthy
networks: networks:
- flights - flights
- subscriptions
flights-api-db: flights-api-db:
container_name: fids_flights_db container_name: fids_flights_db
@ -42,5 +43,8 @@ services:
- flights - flights
networks: networks:
subscriptions:
name: subscription-domain_subscriptions
external: true
flights: flights:
driver: bridge driver: bridge

View File

@ -3,4 +3,5 @@ fastapi[all]==0.103.2
psycopg2-binary==2.9.5 psycopg2-binary==2.9.5
pyjwt==2.6.0 pyjwt==2.6.0
gunicorn==20.1.0 gunicorn==20.1.0
sqlalchemy==2.0.22 sqlalchemy==2.0.22
asyncreq==0.0.4

View File

@ -0,0 +1 @@
API_MESSAGES = "http://fids_subscriptions_api:5000/messages"

View File

@ -22,6 +22,7 @@ def create_flight(db: Session, flight: FlightPydantic):
departure_time=flight.departure_time, departure_time=flight.departure_time,
arrival_time=flight.arrival_time, arrival_time=flight.arrival_time,
gate=flight.gate, gate=flight.gate,
user_id=flight.user_id,
) )
db.add(db_flight) db.add(db_flight)
db.commit() db.commit()
@ -33,8 +34,10 @@ def update_flight_status(db: Session, status, id):
db_flight = db.query(Flight).filter(Flight.id == id).first() db_flight = db.query(Flight).filter(Flight.id == id).first()
if db_flight is None: if db_flight is None:
raise KeyError raise KeyError
if db_flight.user_id != status.user_id:
raise PermissionError
setattr(db_flight, "status", status) setattr(db_flight, "status", status.status)
setattr(db_flight, "last_updated", func.now()) setattr(db_flight, "last_updated", func.now())
db.commit() db.commit()
db.refresh(db_flight) db.refresh(db_flight)

View File

@ -16,6 +16,7 @@ class Flight(Base):
arrival_time = Column(DateTime, nullable=False) arrival_time = Column(DateTime, nullable=False)
gate = Column(String, nullable=True) gate = Column(String, nullable=True)
last_updated = Column(DateTime, default=func.now(), nullable=False) last_updated = Column(DateTime, default=func.now(), nullable=False)
user_id = Column(Integer, nullable=False)
# def get_departure_time(self, format="%Y-%m-%d %I:%M %p"): # def get_departure_time(self, format="%Y-%m-%d %I:%M %p"):
# return self.departure_time.strftime(format) # return self.departure_time.strftime(format)

View File

@ -1,12 +1,17 @@
from typing import Optional from typing import Optional
from fastapi import APIRouter, Depends, HTTPException from asyncreq import request
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from src.api.config import API_MESSAGES
from src.api.cruds import flight as flight_crud from src.api.cruds import flight as flight_crud
from src.api.db import get_db from src.api.db import get_db
from src.api.schemas.flight import Flight, FlightCreate, FlightStatusUpdate from src.api.schemas.flight import Flight, FlightCreate, FlightStatusUpdate
# from copy import copy
router = APIRouter() router = APIRouter()
@ -24,9 +29,25 @@ def create_flight(flight: FlightCreate, db: Session = Depends(get_db)):
@router.patch("/{id}", response_model=Flight) @router.patch("/{id}", response_model=Flight)
def update_flight(id: int, status: FlightStatusUpdate, db: Session = Depends(get_db)): async def update_flight(
db_flight = flight_crud.update_flight_status(db=db, id=id, status=status.status) id: int,
# push to queue with BackgroundTasks status: FlightStatusUpdate,
background_tasks: BackgroundTasks,
db: Session = Depends(get_db),
):
try:
db_flight = flight_crud.update_flight_status(db=db, id=id, status=status)
except PermissionError:
raise HTTPException(status_code=401, detail="Unauthorized")
except KeyError:
raise HTTPException(status_code=404, detail="Flight not found")
msg = status.model_dump()
msg["id"] = id
msg["flight_code"] = db_flight.flight_code
msg["origin"] = db_flight.origin
msg["destination"] = db_flight.destination
background_tasks.add_task(request, API_MESSAGES, "POST", json=msg)
return db_flight return db_flight

View File

@ -12,6 +12,7 @@ class Flight(BaseModel):
departure_time: str departure_time: str
arrival_time: str arrival_time: str
gate: str = None gate: str = None
user_id: int
# last_updated: str # last_updated: str
# @validator("departure_time", "arrival_time", "last_updated", pre=True, always=True) # @validator("departure_time", "arrival_time", "last_updated", pre=True, always=True)
@ -30,7 +31,9 @@ class FlightCreate(BaseModel):
departure_time: str departure_time: str
arrival_time: str arrival_time: str
gate: str = None gate: str = None
user_id: int
class FlightStatusUpdate(BaseModel): class FlightStatusUpdate(BaseModel):
status: str status: str
user_id: int

View File

@ -22,9 +22,11 @@ async def get_flight_by_id(id: int):
async def create_flight( async def create_flight(
flight: FlightCreate, authorization: Annotated[str | None, Header()] = None flight: FlightCreate, authorization: Annotated[str | None, Header()] = None
): ):
await checkAuth(authorization) auth = await checkAuth(authorization)
flight_data = flight.model_dump()
flight_data["user_id"] = auth["id"]
(response, status, _) = await request( (response, status, _) = await request(
f"{API_FLIGHTS}", "POST", json=flight.model_dump() f"{API_FLIGHTS}", "POST", json=flight_data
) )
if status < 200 or status > 204: if status < 200 or status > 204:
raise HTTPException(status_code=status, detail=response) raise HTTPException(status_code=status, detail=response)
@ -37,17 +39,11 @@ async def update_flight(
status_update: FlightStatusUpdate, status_update: FlightStatusUpdate,
authorization: Annotated[str | None, Header()] = None, authorization: Annotated[str | None, Header()] = None,
): ):
await checkAuth(authorization) auth = await checkAuth(authorization)
status = status_update.model_dump()
status["user_id"] = auth["id"]
(response, status, _) = await request( (response, status, _) = await request(
f"{API_FLIGHTS}/{id}", "PATCH", json=status_update.model_dump() f"{API_FLIGHTS}/{id}", "PATCH", json=status
)
if status < 200 or status > 204:
raise HTTPException(status_code=status, detail=response)
# TODO: move to flights-domain
msg = response
msg["id"] = id
(response, status, _) = await request(
f"{API_MESSAGES}", "POST", json=msg
) )
if status < 200 or status > 204: if status < 200 or status > 204:
raise HTTPException(status_code=status, detail=response) raise HTTPException(status_code=status, detail=response)

View File

@ -1,7 +1,6 @@
from fastapi import APIRouter, Header, HTTPException from fastapi import APIRouter, HTTPException
from src.api.config import (API_FLIGHTS, API_NOTIFICATIONS, API_SUBSCRIPTIONS, from src.api.config import API_NOTIFICATIONS
API_USERS)
from src.api.schemas.notification import Update as Message from src.api.schemas.notification import Update as Message
from src.api.utils.network import request from src.api.utils.network import request

View File

@ -2,8 +2,7 @@ from typing import Annotated
from fastapi import APIRouter, Header, HTTPException from fastapi import APIRouter, Header, HTTPException
from src.api.config import (API_FLIGHTS, API_NOTIFICATIONS, API_SUBSCRIPTIONS, from src.api.config import API_SUBSCRIPTIONS
API_USERS)
from src.api.routes.auth import status as checkAuth from src.api.routes.auth import status as checkAuth
from src.api.schemas.subscriptions import Subscription from src.api.schemas.subscriptions import Subscription
from src.api.utils.network import request from src.api.utils.network import request