Add API support for get_document_by_id
This commit is contained in:
parent
c25252ceda
commit
378ae41b39
5
.gitignore
vendored
5
.gitignore
vendored
@ -1 +1,6 @@
|
||||
.venv/
|
||||
*__pycache__*
|
||||
.vscode
|
||||
/deploy/.*
|
||||
*.log
|
||||
*.pyc
|
||||
@ -1,5 +1,5 @@
|
||||
# Dockerfile for Python Service
|
||||
FROM python:3.11-slim
|
||||
FROM python:3.10-slim
|
||||
|
||||
# Set the working directory inside the container
|
||||
WORKDIR /app
|
||||
@ -16,4 +16,4 @@ EXPOSE 8005
|
||||
|
||||
|
||||
# Run the application using the start script
|
||||
CMD ["uvicorn", "webapi.main:app", "--reload", "--port=8003", "--host=0.0.0.0"]
|
||||
CMD ["uvicorn", "app.central_storage.webapi.main:app", "--reload", "--port=8005", "--host=0.0.0.0"]
|
||||
|
||||
@ -92,6 +92,9 @@ class AzureBlobManager:
|
||||
app_settings.AZURE_STORAGE_DOCUMENT_API_ENDPOINT,
|
||||
credential=app_settings.AZURE_STORAGE_DOCUMENT_API_KEY,
|
||||
) as blob_service_client:
|
||||
# user_delegation_key = await blob_service_client.get_user_delegation_key(
|
||||
# key_start_time=key_start_time, key_expiry_time=key_expiry_time
|
||||
# )
|
||||
blob_client = blob_service_client.get_blob_client(
|
||||
container=container_name, blob=file_name
|
||||
)
|
||||
|
||||
@ -1,3 +1,13 @@
|
||||
fastapi==0.114.0
|
||||
fastapi-jwt==0.2.0
|
||||
pika==1.3.2
|
||||
fastapi
|
||||
uvicorn
|
||||
pydantic==2.9.2
|
||||
loguru==0.7.2
|
||||
uvicorn==0.23.2
|
||||
beanie==1.21.0
|
||||
aio-pika
|
||||
pydantic-settings
|
||||
python-jose
|
||||
azure-storage-blob==12.22.0
|
||||
azure-identity
|
||||
azure-core[aio]
|
||||
@ -2,12 +2,12 @@ import logging
|
||||
from fastapi import FastAPI
|
||||
from fastapi.openapi.utils import get_openapi
|
||||
|
||||
from webapi.providers import common
|
||||
from webapi.providers import logger
|
||||
from webapi.providers import router
|
||||
from webapi.providers import database
|
||||
from webapi.providers import scheduler
|
||||
from webapi.providers import exception_handler
|
||||
from app.central_storage.webapi.providers import common
|
||||
from app.central_storage.webapi.providers import logger
|
||||
from app.central_storage.webapi.providers import router
|
||||
from app.central_storage.webapi.providers import database
|
||||
from app.central_storage.webapi.providers import scheduler
|
||||
from app.central_storage.webapi.providers import exception_handler
|
||||
from .freeleaps_app import FreeleapsApp
|
||||
|
||||
|
||||
@ -49,11 +49,7 @@ def customize_openapi_security(app: FastAPI) -> None:
|
||||
|
||||
# Add security scheme to components
|
||||
openapi_schema["components"]["securitySchemes"] = {
|
||||
"bearerAuth": {
|
||||
"type": "http",
|
||||
"scheme": "bearer",
|
||||
"bearerFormat": "JWT"
|
||||
}
|
||||
"bearerAuth": {"type": "http", "scheme": "bearer", "bearerFormat": "JWT"}
|
||||
}
|
||||
|
||||
# Add security requirement globally
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
from webapi.bootstrap.application import create_app
|
||||
from webapi.config.site_settings import site_settings
|
||||
from app.central_storage.webapi.bootstrap.application import create_app
|
||||
from app.central_storage.webapi.config.site_settings import site_settings
|
||||
from fastapi.responses import RedirectResponse
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from strawberry.fastapi import GraphQLRouter
|
||||
from strawberry.fastapi.handlers import GraphQLTransportWSHandler, GraphQLWSHandler
|
||||
import uvicorn
|
||||
from typing import Any
|
||||
|
||||
|
||||
app = create_app()
|
||||
|
||||
|
||||
@app.get("/", status_code=301)
|
||||
async def root():
|
||||
"""
|
||||
@ -19,12 +18,16 @@ async def root():
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
uvicorn.run(app="main:app", host=site_settings.SERVER_HOST, port=site_settings.SERVER_PORT)
|
||||
uvicorn.run(
|
||||
app="main:app", host=site_settings.SERVER_HOST, port=site_settings.SERVER_PORT
|
||||
)
|
||||
|
||||
|
||||
def get_context() -> Any:
|
||||
# Define your context function. This is where you can set up authentication, database connections, etc.
|
||||
return {}
|
||||
|
||||
|
||||
def get_root_value() -> Any:
|
||||
# Define your root value function. This can be used to customize the root value for GraphQL operations.
|
||||
return {}
|
||||
return {}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from webapi.config.site_settings import site_settings
|
||||
from app.central_storage.webapi.config.site_settings import site_settings
|
||||
|
||||
|
||||
def register(app):
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
from webapi.config.site_settings import site_settings
|
||||
from infra.config.app_settings import app_settings
|
||||
from beanie import init_beanie
|
||||
from motor.motor_asyncio import AsyncIOMotorClient
|
||||
from app.central_storage.backend.models.models import DocumentDoc
|
||||
|
||||
|
||||
def register(app):
|
||||
app.debug = site_settings.DEBUG
|
||||
app.title = site_settings.NAME
|
||||
app.debug = "mongo_debug"
|
||||
app.title = "mongo_name"
|
||||
|
||||
@app.on_event("startup")
|
||||
async def start_database():
|
||||
@ -13,5 +14,12 @@ def register(app):
|
||||
|
||||
|
||||
async def initiate_database():
|
||||
#init your database here
|
||||
pass
|
||||
client = AsyncIOMotorClient(
|
||||
app_settings.MONGODB_URI,
|
||||
serverSelectionTimeoutMS=60000,
|
||||
minPoolSize=5, # Minimum number of connections in the pool
|
||||
maxPoolSize=20, # Maximum number of connections in the pool
|
||||
)
|
||||
await init_beanie(
|
||||
database=client[app_settings.MONGODB_NAME], document_models=[DocumentDoc]
|
||||
)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import logging
|
||||
import sys
|
||||
from loguru import logger
|
||||
from common.config.log_settings import log_settings
|
||||
from app.central_storage.common.config.log_settings import log_settings
|
||||
|
||||
|
||||
def register(app=None):
|
||||
@ -21,15 +21,8 @@ def register(app=None):
|
||||
logging.getLogger(name).propagate = True
|
||||
|
||||
# configure loguru
|
||||
logger.add(
|
||||
sink=sys.stdout
|
||||
)
|
||||
logger.add(
|
||||
sink=file_path,
|
||||
level=level,
|
||||
retention=retention,
|
||||
rotation=rotation
|
||||
)
|
||||
logger.add(sink=sys.stdout)
|
||||
logger.add(sink=file_path, level=level, retention=retention, rotation=rotation)
|
||||
|
||||
logger.disable("pika.adapters")
|
||||
logger.disable("pika.connection")
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
from webapi.routes import api_router
|
||||
from app.central_storage.webapi.routes import api_router
|
||||
|
||||
from starlette import routing
|
||||
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
from fastapi import APIRouter
|
||||
from .get_document_by_id import router as doc_router
|
||||
|
||||
api_router = APIRouter()
|
||||
api_router.include_router(doc_router, tags=["attachment"])
|
||||
|
||||
websocket_router = APIRouter()
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
from fastapi import APIRouter, Security, HTTPException
|
||||
from fastapi import APIRouter, HTTPException, Request
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi_jwt import JwtAuthorizationCredentials
|
||||
from backend.infra.authentication.auth import access_security
|
||||
from infra.token.token_manager import TokenManager
|
||||
from app.central_storage.backend.application.document_app import DocumentHub
|
||||
|
||||
router = APIRouter()
|
||||
token_manager = TokenManager()
|
||||
|
||||
|
||||
# Web API
|
||||
@ -19,9 +19,32 @@ router = APIRouter()
|
||||
)
|
||||
async def get_document_by_id(
|
||||
document_id: str,
|
||||
credentials: JwtAuthorizationCredentials = Security(access_security),
|
||||
request: Request,
|
||||
):
|
||||
user_id = credentials["id"]
|
||||
# Extract the Authorization header
|
||||
auth_header = request.headers.get("Authorization")
|
||||
|
||||
if not auth_header:
|
||||
raise HTTPException(status_code=401, detail="Authorization header missing")
|
||||
|
||||
# Ensure the header starts with 'Bearer'
|
||||
if not auth_header.startswith("Bearer "):
|
||||
raise HTTPException(status_code=401, detail="Invalid authorization header")
|
||||
|
||||
token = auth_header.split(" ")[1]
|
||||
|
||||
try:
|
||||
# Decode the token using the TokenManager
|
||||
credentials = token_manager.decode_token(token)
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=401, detail=f"Invalid or expired token: {str(e)}"
|
||||
)
|
||||
|
||||
# Get the user_id from the decoded token
|
||||
user_id = credentials.get("id")
|
||||
if not user_id:
|
||||
raise HTTPException(status_code=401, detail="Invalid token payload")
|
||||
|
||||
# Fetch the document using DocumentHub
|
||||
document = await DocumentHub(user_id).get_document_by_id(document_id)
|
||||
|
||||
@ -1,15 +1,18 @@
|
||||
import os
|
||||
from pydantic_settings import BaseSettings
|
||||
|
||||
class AppSettings():
|
||||
NAME: str = "myapp"
|
||||
|
||||
class AppSettings(BaseSettings):
|
||||
JWT_SECRET_KEY: str = ""
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
|
||||
REFRESH_TOKEN_EXPIRE_DAYS: int = 30
|
||||
MONGODB_NAME: str = "freeleaps2"
|
||||
MONGODB_URI: str = (
|
||||
"mongodb+srv://freeadmin:0eMV0bt8oyaknA0m@freeleaps2.zmsmpos.mongodb.net/?retryWrites=true&w=majority"
|
||||
)
|
||||
|
||||
class Config:
|
||||
env_file = ".myapp.env"
|
||||
env_file_encoding = "utf-8"
|
||||
|
||||
APPLICATION_ACTIVITY_LOG: str = "myapp-application-activity"
|
||||
USER_ACTIVITY_LOG: str = "myapp-user-activity"
|
||||
BUSINESS_METRIC_LOG: str = "myapp-business-metrics"
|
||||
|
||||
app_settings = AppSettings()
|
||||
|
||||
59
infra/token/token_manager.py
Normal file
59
infra/token/token_manager.py
Normal file
@ -0,0 +1,59 @@
|
||||
# application/auth/token/token_manager.py
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Dict
|
||||
from jose import jwt
|
||||
from infra.config.app_settings import app_settings
|
||||
|
||||
|
||||
class TokenManager:
|
||||
def __init__(self):
|
||||
self.secret_key = app_settings.JWT_SECRET_KEY
|
||||
self.algorithm = "HS256"
|
||||
self.access_token_expire_minutes = app_settings.ACCESS_TOKEN_EXPIRE_MINUTES
|
||||
self.refresh_token_expire_days = app_settings.REFRESH_TOKEN_EXPIRE_DAYS
|
||||
|
||||
def create_access_token(self, subject: Dict[str, str]) -> str:
|
||||
"""
|
||||
Generates an access token with a short expiration time.
|
||||
Args:
|
||||
subject (Dict[str, str]): A dictionary containing user information like 'id' and 'role'.
|
||||
|
||||
Returns:
|
||||
str: Encoded JWT access token.
|
||||
"""
|
||||
expire = datetime.now(timezone.utc) + timedelta(
|
||||
minutes=self.access_token_expire_minutes
|
||||
)
|
||||
to_encode = subject.copy()
|
||||
to_encode.update({"exp": expire})
|
||||
return jwt.encode(to_encode, self.secret_key, algorithm=self.algorithm)
|
||||
|
||||
def create_refresh_token(self, subject: Dict[str, str]) -> str:
|
||||
"""
|
||||
Generates a refresh token with a longer expiration time.
|
||||
Args:
|
||||
subject (Dict[str, str]): A dictionary containing user information like 'id' and 'role'.
|
||||
|
||||
Returns:
|
||||
str: Encoded JWT refresh token.
|
||||
"""
|
||||
expire = datetime.now(timezone.utc) + timedelta(
|
||||
days=self.refresh_token_expire_days
|
||||
)
|
||||
to_encode = subject.copy()
|
||||
to_encode.update({"exp": expire})
|
||||
return jwt.encode(to_encode, self.secret_key, algorithm=self.algorithm)
|
||||
|
||||
def decode_token(self, token: str) -> Dict:
|
||||
"""
|
||||
Decodes a JWT token and returns the payload.
|
||||
Args:
|
||||
token (str): Encoded JWT token.
|
||||
|
||||
Returns:
|
||||
Dict: Decoded token payload.
|
||||
|
||||
Raises:
|
||||
JWTError: If the token is invalid or expired.
|
||||
"""
|
||||
return jwt.decode(token, self.secret_key, algorithms=[self.algorithm])
|
||||
Loading…
Reference in New Issue
Block a user