From 2d8ecb367ae894fb7d776f99ec154bb40f7779a1 Mon Sep 17 00:00:00 2001
From: Antoine Gaudron-desjardins <antoine.gaudrondesjardins@student-cs.fr>
Date: Wed, 20 Jul 2022 16:04:27 +0200
Subject: [PATCH] protect OpenAPI interface

---
 backend/db/crud.py    |  2 ++
 backend/db/models.py  |  3 ++-
 backend/db/schemas.py |  1 +
 backend/main.py       | 26 +++++++++++++++++++++++---
 4 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/backend/db/crud.py b/backend/db/crud.py
index 97bb655..9b7e645 100644
--- a/backend/db/crud.py
+++ b/backend/db/crud.py
@@ -382,6 +382,7 @@ def update_user(user: schemas.User, user_info: dict, db: Session):
     if existing_user:
         existing_user.cookie = user.cookie
         existing_user.expiration_date = expiration_date
+        existing_user.admin = "admin eatfast" in user_info["roles"]
         db.delete(user)
         db.add(existing_user)
         db.commit()
@@ -390,6 +391,7 @@ def update_user(user: schemas.User, user_info: dict, db: Session):
     else:
         user.username = full_name
         user.expiration_date = expiration_date
+        user.admin = "admin eatfast" in user_info["roles"]
         db.add(user)
         db.commit()
         db.refresh(user)
diff --git a/backend/db/models.py b/backend/db/models.py
index 753b570..2f719cd 100644
--- a/backend/db/models.py
+++ b/backend/db/models.py
@@ -1,7 +1,7 @@
 """
 Models of the database for magasin app
 """
-from sqlalchemy import Column, ForeignKey, Integer, DateTime, Float, Interval, String, Text, Time
+from sqlalchemy import Boolean, Column, ForeignKey, Integer, DateTime, Float, Interval, String, Text, Time
 from sqlalchemy.orm import relationship
 
 from db.database import Base
@@ -82,5 +82,6 @@ class Users(Base):
     username = Column(String(50))
     cookie = Column(String(50))
     expiration_date = Column(DateTime)
+    admin = Column(Boolean)
     comments = relationship("Comments")
     comments = relationship("CollaborativeRecords")
diff --git a/backend/db/schemas.py b/backend/db/schemas.py
index 0777b3a..f47c7c0 100644
--- a/backend/db/schemas.py
+++ b/backend/db/schemas.py
@@ -138,3 +138,4 @@ class User(BaseModel):
     username: str
     cookie: str
     expiration_date: datetime
+    admin: Optional[bool] = Field(default=False, title="Set to true to allow access to the admin interface")
diff --git a/backend/main.py b/backend/main.py
index d6c986a..8a5b832 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -1,14 +1,19 @@
-from fastapi import FastAPI
+from fastapi import Cookie, Depends, FastAPI
 from fastapi.middleware.cors import CORSMiddleware
+from fastapi.responses import JSONResponse
+from fastapi.openapi.docs import get_swagger_ui_html
+from fastapi.openapi.utils import get_openapi
+from sqlalchemy.orm import Session
 from dotenv import load_dotenv
 from threading import Thread
 import os
 
-from db import database, models
+from db import database, models, crud
+from db.database import get_db
 from routers import *
 from video_capture import handle_cameras
 
-app = FastAPI(docs_url="/api/docs", openapi_url="/api/openapi.json")
+app = FastAPI(docs_url=None, redoc_url=None, openapi_url=None)
 
 # load environment variables
 load_dotenv()
@@ -34,6 +39,21 @@ async def on_startup():
     t.start()
 
 
+# Docs OpenAPI
+@app.get("/api/openapi.json")
+async def get_open_api_endpoint(connect_id: str = Cookie(...), db: Session = Depends(get_db)):
+    user = crud.get_user(connect_id, db)
+    if user.admin:
+        return JSONResponse(get_openapi(title="FastAPI", version=1, routes=app.routes))
+
+
+@app.get("/api/docs")
+async def get_documentation(connect_id: str = Cookie(...), db: Session = Depends(get_db)):
+    user = crud.get_user(connect_id, db)
+    if user.admin:
+        return get_swagger_ui_html(openapi_url="/openapi.json", title="docs")
+
+
 # Integration of routers
 app.include_router(infos.router)
 app.include_router(records.router)
-- 
GitLab