Major project restructure and setup

This commit is contained in:
Khalim Conn-Kowlessar 2023-07-06 11:33:13 +01:00
parent 737ebc115b
commit f7fe90b185
10 changed files with 111 additions and 30 deletions

1
backend/.env.example Normal file
View file

@ -0,0 +1 @@
API_KEY = example-api-key

View file

@ -4,14 +4,65 @@ learning and data modelling services.
# Usage
## Local
## Prerequisites
Python 3.8+
Poetry for managing project dependencies and virtual environment.
For running the serice locally, natigate to the backend directory and run the following command:
## Installation and setup
1. Clone this directory and navigate into the project directory.
```bash
uvicorn main:app --reload
```commandline
git clone https://github.com/Hestia-Homes/Model.git
cd backend
```
2. For environment management, I'm using conda with pycharm which is a convenient setup for development
on a mac M1 however using tools such as poetry or pipenv is also fine.
For example, to install conda and create a virtual environment for this project, run the following commands:
```commandline
conda create -n backend python=3.10
conda activate backend
```
then enter the virtual environment and install the dependencies using conda.
```commandline
conda install --file requirements/base.txt
```
3. Duplicate .env.example and rename it to .env
```commandline
cp .env.example .env
```
4. Open .env and fill in the required environment variables.
## Running the Application
from within the application you can run with the following command:
```commandline
uvicorn app.main:app --reload
```
You application will be available at the designated url
## API Documentation
FastAPI automatically generates interactive API documentation for your application. To access the docs, start your
server and visit <yourlocalurl>/docs in your browser. Alternatively, you can go to
<yourlocalurl>/redoc to view the documentation in the ReDoc format.
## Testing
To run tests, run the following command from the root of the project directory:
```commandline
pytest
```
### Thoughts for authenticating the frontend with the backend
To provide secure communication between your frontend Next.js application and your backend FastAPI service, you have several options. Here are a few popular approaches:

0
backend/app/__init__.py Normal file
View file

15
backend/app/config.py Normal file
View file

@ -0,0 +1,15 @@
from functools import lru_cache
from pydantic import BaseSettings
class Settings(BaseSettings):
API_KEY: str
API_KEY_NAME: str = "X-API-KEY"
class Config:
env_file = ".env"
@lru_cache()
def get_settings():
return Settings()

View file

@ -0,0 +1,14 @@
from fastapi import Depends, HTTPException, status
from fastapi.security import APIKeyHeader
from app.config import get_settings
api_key_header = APIKeyHeader(name=get_settings().API_KEY_NAME, auto_error=False)
async def validate_api_key(api_key_header: str = Depends(api_key_header)):
if api_key_header != get_settings().API_KEY:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN, detail="Could not validate credentials"
)
return api_key_header

8
backend/app/main.py Normal file
View file

@ -0,0 +1,8 @@
from fastapi import FastAPI
from app.portfolio import router as portfolio_router
app = FastAPI()
app.include_router(portfolio_router.router)

View file

View file

@ -0,0 +1,18 @@
from fastapi import APIRouter, Depends
from app.dependencies import validate_api_key
router = APIRouter(
prefix="/portfolio",
dependencies=[Depends(validate_api_key)],
tags=["portfolio"],
responses={404: {"description": "Not found"}}
)
@router.get("/{portfolio_id}")
async def get_portfolio(portfolio_id: int):
return {
"portfolio_id": portfolio_id,
"name": "My Portfolio",
"description": "This is my portfolio",
}

View file

@ -1,26 +0,0 @@
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import APIKeyHeader
API_KEY = "example-api-key"
API_KEY_NAME = "X-API-KEY"
api_key_header = APIKeyHeader(name=API_KEY_NAME, auto_error=False)
app = FastAPI()
async def validate_api_key(api_key_header: str = Depends(api_key_header)):
if api_key_header != API_KEY:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN, detail="Could not validate credentials"
)
return api_key_header
@app.get("/portfolio/{portfolio_id}", dependencies=[Depends(validate_api_key)])
async def get_portfolio(portfolio_id: int):
return {
"portfolio_id": portfolio_id,
"name": "My Portfolio",
"description": "This is my portfolio",
}