Skip to content
This repository was archived by the owner on Nov 14, 2022. It is now read-only.

Commit 718cb4a

Browse files
authored
Refactor backend and frontend (#7)
* ⬆️ Upgrade backend dependencies in Dockerfiles * 📝 Update generated docs to use latest integrated /start-reload.sh * 🔧 Add scripts for project generator development * ➕ Add backend development dependencies * 🔥 Remove scripts provided by base image * 🔊 Add logs to starting scripts * 🏗️ Upgrade backend structure, names, dependencies * 🎨 Upgrade linting script to include dead code detection * ⬆️ Upgrade frontend dependencies * 🏗️ Upgrade vuex integration and standardize layout * 🐛 Fix backend logic to update users * 🎨 Format frontend code
1 parent cfebb50 commit 718cb4a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+743
-686
lines changed

dev-fsfcb-back.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#! /usr/bin/env bash
2+
3+
# Run this script from outside the project, to integrate a dev-fsfcb project with changes and review modifications
4+
5+
# Exit in case of error
6+
set -e
7+
8+
if [ $(uname -s) = "Linux" ]; then
9+
echo "Remove __pycache__ files"
10+
sudo find ./dev-fsfcb/ -type d -name __pycache__ -exec rm -r {} \+
11+
fi
12+
13+
rm -rf ./full-stack-fastapi-couchbase/\{\{cookiecutter.project_slug\}\}/*
14+
15+
rsync -a --exclude=node_modules ./dev-fsfcb/* ./full-stack-fastapi-couchbase/\{\{cookiecutter.project_slug\}\}/
16+
17+
rsync -a ./dev-fsfcb/{.env,.gitignore,.gitlab-ci.yml} ./full-stack-fastapi-couchbase/\{\{cookiecutter.project_slug\}\}/

dev-fsfcb-config.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
default_context:
2+
"project_name": "Dev FSFCB"

dev-fsfcb.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#! /usr/bin/env bash
2+
3+
# Run this script from outside the project, to generate a dev-fsfcb project
4+
5+
# Exit in case of error
6+
set -e
7+
8+
rm -rf ./dev-fsfcb
9+
10+
cookiecutter --config-file ./full-stack-fastapi-couchbase/dev-fsfcb-config.yml --no-input -f ./full-stack-fastapi-couchbase

{{cookiecutter.project_slug}}/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ The changes to those files only affect the local development environment, not th
8181

8282
For example, the directory with the backend code is mounted as a Docker "host volume" (in the file `docker-compose.dev.volumes.yml`), mapping the code you change live to the directory inside the container. That allows you to test your changes right away, without having to build the Docker image again. It should only be done during development, for production, you should build the Docker image with a recent version of the backend code. But during development, it allows you to iterate very fast.
8383

84-
There is also a commented out `command` override (in the file `docker-compose.dev.command.yml`), if you want to enable it, uncomment it. It makes the backend container run a process that does "nothing", but keeps the process running. That allows you to get inside your living container and run commands inside, for example a Python interpreter to test installed dependencies, or start the development server that reloads when it detectes changes.
84+
There is also a commented out `command` override (in the file `docker-compose.dev.command.yml`), if you want to enable it, uncomment it. It makes the backend container run a process that does "nothing", but keeps the process running. That allows you to get inside your living container and run commands inside, for example a Python interpreter to test installed dependencies, or start the development server that reloads when it detects changes.
8585

8686
To get inside the container with a `bash` session you can start the stack with:
8787

@@ -103,16 +103,16 @@ root@7f2607af31c3:/app#
103103

104104
that means that you are in a `bash` session inside your container, as a `root` user, under the `/app` directory.
105105

106-
There is also a script `backend-live.sh` to run the debug live reloading server. You can run that script from inside the container with:
106+
There is also a script `/start-reload.sh` to run the debug live reloading server. You can run that script from inside the container with:
107107

108108
```bash
109-
bash ./backend-live.sh
109+
bash /start-reload.sh
110110
```
111111

112112
...it will look like:
113113

114114
```bash
115-
root@7f2607af31c3:/app# bash ./backend-live.sh
115+
root@7f2607af31c3:/app# bash /start-reload.sh
116116
```
117117

118118
and then hit enter. That runs the debugging server that auto reloads when it detects code changes.

{{cookiecutter.project_slug}}/backend/app/Pipfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ isort = "*"
1111
autoflake = "*"
1212
flake8 = "*"
1313
pytest = "*"
14+
vulture = "*"
1415

1516
[packages]
1617
fastapi = "*"
@@ -26,6 +27,7 @@ pydantic = "*"
2627
couchbase = "*"
2728
emails = "*"
2829
raven = "*"
30+
jinja2 = "*"
2931

3032
[requires]
3133
python_version = "3.6"
Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
from fastapi import APIRouter
22

3-
from app.api.api_v1.endpoints.role import router as roles_router
4-
from app.api.api_v1.endpoints.token import router as token_router
5-
from app.api.api_v1.endpoints.user import router as user_router
6-
from app.api.api_v1.endpoints.utils import router as utils_router
3+
from app.api.api_v1.endpoints import role, token, user, utils
74

85
api_router = APIRouter()
9-
api_router.include_router(roles_router)
10-
api_router.include_router(token_router)
11-
api_router.include_router(user_router)
12-
api_router.include_router(utils_router)
6+
api_router.include_router(role.router)
7+
api_router.include_router(token.router)
8+
api_router.include_router(user.router)
9+
api_router.include_router(utils.router)
Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,17 @@
11
from fastapi import APIRouter, Depends
2-
from starlette.exceptions import HTTPException
32

4-
from app.core.jwt import get_current_user
5-
from app.crud.user import check_if_user_is_active, check_if_user_is_superuser
6-
from app.crud.utils import ensure_enums_to_strs
3+
from app import crud
4+
from app.api.utils.security import get_current_active_superuser
75
from app.models.role import RoleEnum, Roles
86
from app.models.user import UserInDB
97

108
router = APIRouter()
119

1210

1311
@router.get("/roles/", response_model=Roles)
14-
def route_roles_get(current_user: UserInDB = Depends(get_current_user)):
12+
def read_roles(current_user: UserInDB = Depends(get_current_active_superuser)):
1513
"""
1614
Retrieve roles
1715
"""
18-
if not check_if_user_is_active(current_user):
19-
raise HTTPException(status_code=400, detail="Inactive user")
20-
elif not (check_if_user_is_superuser(current_user)):
21-
raise HTTPException(
22-
status_code=400, detail="The current user does not have enogh privileges"
23-
)
24-
roles = ensure_enums_to_strs(RoleEnum)
16+
roles = crud.utils.ensure_enums_to_strs(RoleEnum)
2517
return {"roles": roles}
Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
11
from datetime import timedelta
22

3-
from fastapi import APIRouter, Depends
3+
from fastapi import APIRouter, Depends, HTTPException
44
from fastapi.security import OAuth2PasswordRequestForm
5-
from starlette.exceptions import HTTPException
65

6+
from app import crud
7+
from app.api.utils.security import get_current_user
78
from app.core import config
8-
from app.core.jwt import create_access_token, get_current_user
9-
from app.crud.user import (
10-
authenticate_user,
11-
check_if_user_is_active,
12-
check_if_user_is_superuser,
13-
get_user,
14-
update_user,
15-
)
9+
from app.core.jwt import create_access_token
1610
from app.db.database import get_default_bucket
1711
from app.models.msg import Msg
1812
from app.models.token import Token
@@ -27,70 +21,72 @@
2721

2822

2923
@router.post("/login/access-token", response_model=Token, tags=["login"])
30-
def route_login_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
24+
def login(form_data: OAuth2PasswordRequestForm = Depends()):
3125
"""
3226
OAuth2 compatible token login, get an access token for future requests
3327
"""
3428
bucket = get_default_bucket()
35-
user = authenticate_user(bucket, form_data.username, form_data.password)
29+
user = crud.user.authenticate(
30+
bucket, username=form_data.username, password=form_data.password
31+
)
3632
if not user:
3733
raise HTTPException(status_code=400, detail="Incorrect email or password")
38-
elif not check_if_user_is_active(user):
34+
elif not crud.user.is_active(user):
3935
raise HTTPException(status_code=400, detail="Inactive user")
4036
access_token_expires = timedelta(minutes=config.ACCESS_TOKEN_EXPIRE_MINUTES)
4137
return {
4238
"access_token": create_access_token(
43-
data={"username": form_data.username}, expires_delta=access_token_expires
39+
data={"username": user.username}, expires_delta=access_token_expires
4440
),
4541
"token_type": "bearer",
4642
}
4743

4844

4945
@router.post("/login/test-token", tags=["login"], response_model=User)
50-
def route_test_token(current_user: UserInDB = Depends(get_current_user)):
46+
def test_token(current_user: UserInDB = Depends(get_current_user)):
5147
"""
5248
Test access token
5349
"""
5450
return current_user
5551

5652

5753
@router.post("/password-recovery/{username}", tags=["login"], response_model=Msg)
58-
def route_recover_password(username: str):
54+
def recover_password(username: str):
5955
"""
6056
Password Recovery
6157
"""
6258
bucket = get_default_bucket()
63-
user = get_user(bucket, username)
59+
user = crud.user.get(bucket, username=username)
6460

6561
if not user:
6662
raise HTTPException(
6763
status_code=404,
6864
detail="The user with this username does not exist in the system.",
6965
)
70-
password_reset_token = generate_password_reset_token(username)
66+
password_reset_token = generate_password_reset_token(username=username)
7167
send_reset_password_email(
7268
email_to=user.email, username=username, token=password_reset_token
7369
)
7470
return {"msg": "Password recovery email sent"}
7571

7672

7773
@router.post("/reset-password/", tags=["login"], response_model=Msg)
78-
def route_reset_password(token: str, new_password: str):
74+
def reset_password(token: str, new_password: str):
7975
"""
8076
Reset password
8177
"""
8278
username = verify_password_reset_token(token)
8379
if not username:
8480
raise HTTPException(status_code=400, detail="Invalid token")
8581
bucket = get_default_bucket()
86-
user = get_user(bucket, username)
82+
user = crud.user.get(bucket, username=username)
8783
if not user:
8884
raise HTTPException(
8985
status_code=404,
9086
detail="The user with this username does not exist in the system.",
9187
)
92-
elif not check_if_user_is_active(user):
88+
elif not crud.user.is_active(user):
9389
raise HTTPException(status_code=400, detail="Inactive user")
9490
user_in = UserInUpdate(name=username, password=new_password)
95-
user = update_user(bucket, user_in)
91+
user = crud.user.update(bucket, username=username, user_in=user_in)
9692
return {"msg": "Password updated successfully"}

0 commit comments

Comments
 (0)