Skip to content

Project rewrite #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 19, 2021
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
3 changes: 2 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
MONGO_DETAILS=mongodb://mongourl:port
MONGO_DETAILS=mongodb://mongodb:27017
secret=guiyfgc837tgf3iw87-012389764
9 changes: 5 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
FROM python:3.8
WORKDIR /app

ADD requirements.txt /requirements.txt
ADD requirements.txt /app/requirements.txt

RUN pip install -r requirements.txt
RUN pip install --upgrade -r requirements.txt

EXPOSE 80

COPY ./app /app
COPY ./ /app

CMD ["uvicorn", "app.server.app:app", "--host", "0.0.0.0", "--port", "80"]
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8080"]
58 changes: 3 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,71 +33,19 @@ python app/main.py

You also need to start your mongodb instance.

The starter listens on port 8000 on address [0.0.0.0](0.0.0.0).
The starter listens on port 8000 on address [0.0.0.0](0.0.0.0:8080).

![FastAPI-MongoDB starter](https://res.cloudinary.com/adeshina/image/upload/v1600180509/fopab9idhrjqeqds4izk.png)

## Deploying to Vercel
## Deployment

> Currently, the vercel build fails when running requests to MongoDB through the async driver. The next section shows how to deploy to Heroku.
[![Develop on Okteto](https://okteto.com/develop-okteto.svg)](https://cloud.okteto.com/deploy?repository=https://github.com/Youngestdev/fastapi-mongo)

To deploy to [vercel](https://vercel.com), make sure the `vercel` CLI tool is installed and run the command in the base directory:

```console
vercel
```

The above deploys to development, to deploy it into production, run:

```console
vercel --prod
```

Ensure you add the environment variable `MONGO_DETAILS` in vercel.

## Deploying to Heroku

To deploy to Heroku, connect your repository to the Heroku application and deploy the branch master. This template has been deployed to Heroku and you can view it here: [FastAPI Mongo](https://fastapi-mongo.herokuapp.com/)

Ensure you add the environment variable `MONGO_DETAILS` in your application's settings.

## Dockerising

To build a docker image for this boilerplate, create a duplicate `.env` file but with name `env`. Next, build an image:

```console
docker build -t fastapi-mongo .
```

The command above builds an image that can be deployed. To run the image in a container:

```console
docker run --env-file env -d --name fastapi-mongo -p 80:80 fastapi-mongo:latest
```

## Contributing ?

Fork the repo, make changes and send a PR. We'll review it together!

## TODOS

- [ ] Add a simple bash script file that runs the installation process.

- [x] Fix the `UPDATE` part of the CRUD operation

- [x] Add Authentication

- [x] Add Dockerfile

- [x] Vercel configuration file

- [x] Deploying to Heroku

- [ ] Write a concise README

- [x] Format code. I'm new to FastAPI so I'll be working towards best practices.


## License

This project is licensed under the terms of MIT license.
File renamed without changes.
8 changes: 4 additions & 4 deletions app/server/app.py → app.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
from fastapi import FastAPI, Depends

from .auth.jwt_bearer import JWTBearer
from .routes.student import router as StudentRouter
from .routes.admin import router as AdminRouter
from auth.jwt_bearer import JWTBearer
from routes.student import router as StudentRouter
from routes.admin import router as AdminRouter

app = FastAPI()

token_listener = JWTBearer()

@app.get("/", tags=["Root"])
async def read_root():
return {"message": "Welcome to this fantastic app, sighs."}
return {"message": "Welcome to this fantastic app."}


app.include_router(AdminRouter, tags=["Administrator"], prefix="/admin")
Expand Down
4 changes: 0 additions & 4 deletions app/main.py

This file was deleted.

2 changes: 1 addition & 1 deletion app/server/auth/admin.py → auth/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from fastapi.security import HTTPBasicCredentials, HTTPBasic
from passlib.context import CryptContext

from app.server.database.database import admin_collection
from database.database import admin_collection

security = HTTPBasic()
hash_helper = CryptContext(schemes=["bcrypt"])
Expand Down
4 changes: 0 additions & 4 deletions app/server/auth/jwt_bearer.py → auth/jwt_bearer.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
# Code copied from github.com/overrideveloper/HowAreYouApi*
from fastapi import Request, HTTPException
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials

from .jwt_handler import decodeJWT
# from models.Database import Database


class JWTBearer(HTTPBearer):
# db: Database = None

def __init__(self, auto_error: bool = True):
super(JWTBearer, self).__init__(auto_error=auto_error)
# self.db = db

async def __call__(self, request: Request):
credentials: HTTPAuthorizationCredentials = await super(JWTBearer, self).__call__(request)
Expand Down
2 changes: 1 addition & 1 deletion app/server/auth/jwt_handler.py → auth/jwt_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ def decodeJWT(token: str) -> dict:
decoded_token = jwt.decode(token.encode(), JWT_SECRET, algorithms=["HS256"])
return decoded_token if decoded_token['expires'] >= time.time() else None
except:
return None
return {}
2 changes: 1 addition & 1 deletion app/server/database/database.py → database/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from bson import ObjectId
from decouple import config

from app.server.database.database_helper import student_helper, admin_helper
from .database_helper import student_helper, admin_helper

MONGO_DETAILS = config('MONGO_DETAILS')

Expand Down
File renamed without changes.
20 changes: 20 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
version: "3"

services:
web:
build: .
ports:
- 8080:8080
env_file:
- .env

mongodb:
image: bitnami/mongodb:latest
ports:
- 27017
volumes:
- data:/bitnami/mongodb


volumes:
data:
4 changes: 4 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import uvicorn

if __name__ == '__main__':
uvicorn.run('app:app', host="0.0.0.0", port=8000, reload=True)
File renamed without changes.
File renamed without changes.
29 changes: 22 additions & 7 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
bcrypt==3.2.0
cffi==1.14.2
click==7.1.2
dnspython==2.0.0
email-validator==1.1.1
fastapi==0.61.1
pydantic==1.6.1
uvicorn==0.11.8
h11==0.9.0
httptools==0.1.1
idna==2.10
motor==2.2.0
pydantic[email]
python-decouple
email-validator
nanodb==0.4.3
nanodb-driver==0.0.3
passlib==1.7.2
pycparser==2.20
pydantic==1.6.1
PyJWT==1.7.1
passlib
bcrypt
pymongo==3.11.0
python-decouple==3.3
PyYAML==3.11
pyzmq==22.0.3
six==1.15.0
starlette==0.13.6
uvicorn==0.11.8
uvloop==0.14.0
websockets==8.1
17 changes: 4 additions & 13 deletions app/server/routes/admin.py → routes/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
from fastapi.security import HTTPBasicCredentials
from passlib.context import CryptContext

from server.database.database import admin_collection
#from app.server.auth.admin import validate_login
from server.auth.jwt_handler import signJWT
from server.database.database import add_admin
from server.models.admin import AdminModel
from database.database import admin_collection
from auth.jwt_handler import signJWT
from database.database import add_admin
from models.admin import AdminModel

router = APIRouter()

Expand All @@ -27,14 +26,6 @@ async def admin_login(admin_credentials: HTTPBasicCredentials = Body(...)):

return "Incorrect email or password"

# OLD CODE
# if validate_login(admin):
# return {
# "email": admin.username,
# "access_token": signJWT(admin.username)
# }
# return "Invalid Login Details!"

@router.post("/")
async def admin_signup(admin: AdminModel = Body(...)):
admin_exists = await admin_collection.find_one({"email": admin.email}, {"_id": 0})
Expand Down
6 changes: 3 additions & 3 deletions app/server/routes/student.py → routes/student.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from fastapi import APIRouter, Body
from fastapi.encoders import jsonable_encoder

from app.server.database.database import *
from app.server.models.student import *
from database.database import *
from models.student import *

router = APIRouter()

Expand All @@ -21,7 +21,7 @@ async def get_student_data(id):
student = await retrieve_student(id)
return ResponseModel(student, "Student data retrieved successfully") \
if student \
else ErrorResponseModel("An error occured.", 404, "Student doesn'exist.")
else ErrorResponseModel("An error occured.", 404, "Student doesn't exist.")


@router.post("/", response_description="Student data added into the database")
Expand Down
8 changes: 0 additions & 8 deletions vercel.json

This file was deleted.