Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions api-server/app/auth/get_token_claims.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import jwt
import os
import time

from app.singletons.logs_manager import LogsManager

from .models.token_claims import TokenClaims

logger = LogsManager().get_logger()

JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY")
if not JWT_SECRET_KEY:
raise ValueError("JWT_SECRET_KEY environment variable is not set or is empty.")
JWT_ALGORITHM = "HS256"


async def get_token_claims(token: str, x_exosphere_request_id: str):
try:
claims = TokenClaims(**jwt.decode(token, JWT_SECRET_KEY, algorithms=[JWT_ALGORITHM]))
logger.info("Token claims decoded", x_exosphere_request_id=x_exosphere_request_id, user_id=claims.user_id)

if claims.exp < time.time():
logger.error("Token expired", x_exosphere_request_id=x_exosphere_request_id, user_id=claims.user_id)
return None

return claims

except Exception as e:
logger.error("Error decoding token", error=e, x_exosphere_request_id=x_exosphere_request_id)
return None

43 changes: 0 additions & 43 deletions api-server/app/auth/middlewares/get_token_claims.py

This file was deleted.

17 changes: 17 additions & 0 deletions api-server/app/auth/routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from fastapi import APIRouter, status, Request

from .controllers.create_token import create_token
from .models.token_request import TokenRequest
from .models.token_response import TokenResponse

router = APIRouter(prefix="/v0/auth", tags=["auth"])

@router.post(
"/token",
response_model=TokenResponse,
status_code=status.HTTP_200_OK,
response_description="Token created successfully"
)
async def create_token_route(body: TokenRequest, request: Request):
x_exosphere_request_id = getattr(request.state, "x_exosphere_request_id", None)
return await create_token(body, x_exosphere_request_id)
9 changes: 4 additions & 5 deletions api-server/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@
UnhandledExceptionsMiddleware,
)
from .middlewares.request_id_middleware import RequestIdMiddleware
from .auth.middlewares.get_token_claims import GetTokenClaimsMiddleware

# injecting databases
from .user.models.user_database_model import User
from .project.models.project_database_model import Project

# injecting routers
from .user.routes import router as user_router
from .auth.router import router as auth_router

from .auth.routes import router as auth_router
from .project.routes import router as project_router

load_dotenv()


Expand Down Expand Up @@ -54,8 +54,6 @@ async def lifespan(app: FastAPI):
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="auth/token")

# this middleware should be the first one
app.add_middleware(GetTokenClaimsMiddleware)

app.add_middleware(RequestIdMiddleware)

app.add_middleware(UnhandledExceptionsMiddleware)
Expand All @@ -69,3 +67,4 @@ def health() -> dict:
# injecting routers
app.include_router(user_router)
app.include_router(auth_router)
app.include_router(project_router)
36 changes: 36 additions & 0 deletions api-server/app/project/controllers/create_project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from beanie import Link
from bson import ObjectId

from ..models.create_project_request import CreateProjectRequest
from ..models.create_project_response import CreateProjectResponse
from ..models.project_database_model import Project

from app.singletons.logs_manager import LogsManager
from app.auth.models.token_claims import TokenClaims
from app.user.models.user_database_model import User

logger = LogsManager().get_logger()


async def create_project(request: CreateProjectRequest, claims: TokenClaims, x_exosphere_request_id: str) -> CreateProjectResponse:
try:
logger.info("Creating new project", x_exosphere_request_id=x_exosphere_request_id, user_id=claims.user_id)
project = Project(
name=request.name,
super_admin=Link(ObjectId(claims.user_id), User)
)
await project.save()
print(project)
return CreateProjectResponse(
id=str(project.id),
name=project.name,
status=project.status,
billing_account=project.billing_account,
super_admin=claims.user_id,
created_at=project.created_at,
updated_at=project.updated_at
)

except Exception as e:
logger.error("Error creating new project", x_exosphere_request_id=x_exosphere_request_id, error=e)
raise e
3 changes: 2 additions & 1 deletion api-server/app/project/models/billing_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@


class TaxInformationTypeEnum(str, Enum):
NOT_DEFINED = "NOT_DEFINED"
GST = "GST"
VAT = "VAT"
EIN = "EIN"
Expand All @@ -15,7 +16,7 @@ class BillingAccount(BaseModel):

billing_address: str = Field(default="", description="Billing address of the company")

tax_number_type: TaxInformationTypeEnum = Field(default="", description="Type of tax information")
tax_number_type: TaxInformationTypeEnum = Field(default=TaxInformationTypeEnum.NOT_DEFINED, description="Type of tax information")

tax_number: str = Field(default="", description="Tax information of the company")

Expand Down
4 changes: 4 additions & 0 deletions api-server/app/project/models/create_project_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from pydantic import BaseModel

class CreateProjectRequest(BaseModel):
name: str
14 changes: 14 additions & 0 deletions api-server/app/project/models/create_project_response.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from pydantic import BaseModel
from .billing_account import BillingAccount
from .project_status_enum import ProjectStatusEnum
from datetime import datetime


class CreateProjectResponse(BaseModel):
id: str
name: str
status: ProjectStatusEnum
billing_account: BillingAccount
super_admin: str
created_at: datetime
updated_at: datetime
27 changes: 27 additions & 0 deletions api-server/app/project/routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from fastapi import APIRouter, status, Request, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from typing import Annotated
from starlette.responses import JSONResponse

from .controllers.create_project import create_project
from .models.create_project_request import CreateProjectRequest
from .models.create_project_response import CreateProjectResponse

from app.auth.get_token_claims import get_token_claims

router = APIRouter(prefix="/v0/project", tags=["project"])

@router.post(
"/",
response_model=CreateProjectResponse,
status_code=status.HTTP_201_CREATED,
response_description="Project created successfully"
)
async def create_project_route(body: CreateProjectRequest, request: Request, token: Annotated[HTTPAuthorizationCredentials, Depends(HTTPBearer())]):
x_exosphere_request_id = getattr(request.state, "x_exosphere_request_id", None)
claims = await get_token_claims(token.credentials, x_exosphere_request_id)

if claims is None:
return JSONResponse(status_code=401, content={"message": "Invalid token", "success": False})

return await create_project(body, claims, x_exosphere_request_id)
6 changes: 3 additions & 3 deletions api-server/app/user/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
from .controllers.create_user import create_user
from .models.create_user_request import CreateUserRequest
from .models.create_user_response import CreateUserResponse

router = APIRouter(prefix="/user", tags=["user"])
router = APIRouter(prefix="/v0/user", tags=["user"])

@router.post(
"/create",
"/",
response_model=CreateUserResponse,
status_code=status.HTTP_201_CREATED,
response_description="User created successfully"
Expand Down