Skip to content

Commit ef3c072

Browse files
authored
7 improve user management (#8)
* Refactor user management to enable SSO with google. Refactor docker config * Update user_profile backend route to disable setting is_superuser for oneself * Update backend dependencies * update frontend deps * Fix dependencies with audit * revert version change for eslint-plugin-react * add missing jsdom dep * Fix typescript errors * Add build workflow
1 parent 8b748fd commit ef3c072

Some content is hidden

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

50 files changed

+2864
-3183
lines changed

.env

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,37 @@
11
DOMAIN=localhost
2-
# DOMAIN=local.dockertoolbox.tiangolo.com
3-
# DOMAIN=localhost.tiangolo.com
4-
# DOMAIN=dev.farm-docker.com
52

63
STACK_NAME=farm-docker
74

85
TRAEFIK_PUBLIC_NETWORK=traefik-public
96
TRAEFIK_TAG=farm-docker
107
TRAEFIK_PUBLIC_TAG=traefik-public
8+
TRAEFIK_PUBLIC_NETWORK_IS_EXTERNAL=false
9+
TRAEFIK_TLS_EMAIL=[email protected]
1110

12-
DOCKER_IMAGE_BACKEND=backend
13-
DOCKER_IMAGE_FRONTEND=frontend
11+
DOCKER_IMAGE_BACKEND=farmd-backend
12+
DOCKER_IMAGE_FRONTEND=farmd-frontend
13+
DOCKER_PACKAGE_REPOSITORY=ghcr.io/jonasrenault
1414

1515
# Backend
16-
BACKEND_CORS_ORIGINS=["http://localhost", "http://localhost:5173", "http://localhost:3000", "http://localhost:8080", "https://localhost", "https://localhost:5173", "https://localhost:3000", "https://localhost:8080", "http://dev.farm-docker.com", "https://stag.farm-docker.com", "https://farm-docker.com", "http://local.dockertoolbox.tiangolo.com", "http://localhost.tiangolo.com"]
16+
BACKEND_CORS_ORIGINS=["http://localhost", "http://localhost:5173", "http://localhost:3000", "http://localhost:8080", "https://localhost", "https://localhost:5173", "https://localhost:3000", "https://localhost:8080", "http://dev.farm-docker.com", "https://stag.farm-docker.com", "https://farm-docker.com"]
1717
PROJECT_NAME=farm-docker
1818
SECRET_KEY=98153798f1616ba9e65c2cbcdb3fd3e3a6297b2002f6936b72823fd21ce609d9
1919
FIRST_SUPERUSER=[email protected]
2020
FIRST_SUPERUSER_PASSWORD=admin
2121

22-
USERS_OPEN_REGISTRATION=False
22+
GOOGLE_CLIENT_ID=
23+
GOOGLE_CLIENT_SECRET=
24+
FACEBOOK_CLIENT_ID=
25+
FACEBOOK_CLIENT_SECRET=
26+
# HOSTNAME used to build google redirect uri. Should point to backend
27+
SSO_CALLBACK_HOSTNAME=http://localhost
28+
# Callback URL we redirect to after google login. Should point to frontend/sso-login-callback
29+
SSO_LOGIN_CALLBACK_URL=http://localhost/sso-login-callback
2330

2431
# Frontend
2532
VITE_BACKEND_API_URL=http://localhost/api/v1/
33+
VITE_PWD_SIGNUP_ENABLED=true
34+
VITE_GA_TRACKING_ID=
2635

2736
# MongoDB
2837
MONGO_HOST=db

.github/workflows/build.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: Build and deploy
2+
3+
on:
4+
# Trigger the workflow on push to main branch
5+
push:
6+
branches:
7+
- main
8+
9+
workflow_run:
10+
workflows: ["Run tests"]
11+
branches: [main]
12+
types:
13+
- completed
14+
15+
env:
16+
REGISTRY: ghcr.io
17+
18+
jobs:
19+
# Build docker images with docker compose and push to github registry
20+
build-push-to-registry:
21+
name: Docker compose build and push to ghcr
22+
runs-on: ubuntu-latest
23+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
24+
environment:
25+
name: prod
26+
27+
steps:
28+
- name: Git checkout
29+
uses: actions/checkout@v3
30+
31+
- name: Log in to the Container registry
32+
uses: docker/login-action@v2
33+
with:
34+
registry: ${{ env.REGISTRY }}
35+
username: ${{ github.repository_owner }}
36+
password: ${{ secrets.GITHUB_TOKEN }}
37+
38+
- name: Create env file
39+
run: |
40+
touch .env
41+
echo "${{ secrets.SERVER_ENV_PROD }}" > .env
42+
43+
- name: Build images
44+
run: docker compose -f docker-compose.prod.yml build
45+
46+
- name: Push image to container registry
47+
run: docker compose -f docker-compose.prod.yml push

.github/workflows/lint.yml

Lines changed: 0 additions & 55 deletions
This file was deleted.

.github/workflows/test.yml

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Run tests
1+
name: Run tests and linting
22

33
on:
44
# Trigger the workflow on push or pull request,
@@ -18,9 +18,46 @@ env: # environment variables (available in any part of the action)
1818
MONGODB_VERSION: 6.0
1919

2020
jobs:
21+
run-js-linters:
22+
name: Run JS linters
23+
runs-on: ubuntu-latest
24+
defaults:
25+
run:
26+
working-directory: ./frontend
27+
28+
steps:
29+
- name: Check out Git repository
30+
uses: actions/checkout@v3
31+
32+
- name: Set up Node.js
33+
uses: actions/setup-node@v3
34+
with:
35+
node-version: ${{ env.NODE_VERSION }}
36+
37+
- name: Install Node.js dependencies
38+
run: npm ci
39+
40+
- name: Run eslint
41+
run: npm run lint
42+
43+
run-python-linters:
44+
name: Run Python linters
45+
runs-on: ubuntu-latest
46+
defaults:
47+
run:
48+
working-directory: ./backend
49+
50+
steps:
51+
- name: Check out Git repository
52+
uses: actions/checkout@v3
53+
54+
- name: Run black
55+
uses: psf/black@stable
56+
2157
test-backend:
2258
name: Run backend unit tests
2359
runs-on: ubuntu-latest
60+
needs: run-python-linters
2461
defaults:
2562
run:
2663
working-directory: ./backend
@@ -73,6 +110,7 @@ jobs:
73110
test-frontend:
74111
name: Run frontend unit tests
75112
runs-on: ubuntu-latest
113+
needs: run-js-linters
76114
defaults:
77115
run:
78116
working-directory: ./frontend

README.md

Lines changed: 25 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# Fastapi-React-Mongodb-Docker
22

3-
[![Linting](https://github.com/jonasrenault/fastapi-react-mongodb-docker/actions/workflows/lint.yml/badge.svg)](https://github.com/jonasrenault/fastapi-react-mongodb-docker/actions/workflows/lint.yml)
4-
53
[![Tests](https://github.com/jonasrenault/fastapi-react-mongodb-docker/actions/workflows/test.yml/badge.svg)](https://github.com/jonasrenault/fastapi-react-mongodb-docker/actions/workflows/test.yml)
64

75
This is a template application for a FARM stack. FARM stands for FastAPI, React, MongoDB.
@@ -15,20 +13,24 @@ The project is composed of :
1513

1614
## Running the application locally for development
1715

18-
To run the application manually in a terminal, see both the [backend](backend/README.md) and [frontend](frontend/README.md)'s READMEs.
16+
To run the application manually in a terminal, see both the [backend](backend/README.md) and [frontend](frontend/README.md)'s READMEs for instructions.
1917

2018
## Running the application with Docker
2119

22-
The project contains Docker configuration files to run the application through Docker. The Docker configuration is largely adapted from Tiangolo's [Full stack FastAPI cookiecutter](https://github.com/tiangolo/full-stack-fastapi-postgresql) project.
20+
The project contains Docker configuration files to run the application with Docker compose. Two docker-compose files are provided with configuration for `dev` and for `production` environments. The Docker configuration is largely adapted from Tiangolo's [Full stack FastAPI cookiecutter](https://github.com/tiangolo/full-stack-fastapi-postgresql) project.
2321

2422
### Local development with Docker
2523

24+
The local development file for docker is [docker-compose.yml](./docker-compose.yml).
25+
2626
Start the stack with Docker Compose:
2727

2828
```bash
29-
docker-compose up -d
29+
docker compose up -d --build
3030
```
3131

32+
The `--build` arg can be omitted after the images have been built at least once.
33+
3234
Now you can open your browser and interact with these URLs:
3335

3436
* Frontend, served with vite with hot reload of code: http://localhost
@@ -44,70 +46,56 @@ Now you can open your browser and interact with these URLs:
4446
Once the stack is up, to check the logs, run:
4547

4648
```bash
47-
docker-compose logs
49+
docker compose logs
4850
```
4951

5052
To check the logs of a specific service, add the name of the service, e.g.:
5153

5254
```bash
53-
docker-compose logs backend
55+
docker compose logs backend
5456
```
5557

56-
### Docker Compose Override
58+
### Docker Compose settings for development
5759

58-
During development, you can change Docker Compose settings that will only affect the local development environment, in the file `docker-compose.override.yml`.
59-
60-
The changes to that file only affect the local development environment, not the production environment. So, you can add *temporary* changes that help the development workflow.
61-
62-
For example, the directory with the backend code is mounted as a Docker "host volume", mapping the code you change live to the directory inside the container. Same for the frontend code. 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 and stable version of the code.
60+
When running the application with docker in development, both the frontend and backend directories are mounted as volumes to their corresponding docker containers to enable hot reload of code changes. This 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 and stable version of the code.
6361

6462
For the backend, there is a command override that runs `/start-reload.sh` (included in the base image) instead of the default `/start.sh` (also included in the base image). It starts a single server process (instead of multiple, as would be for production) and reloads the process whenever the code changes. Have in mind that if you have a syntax error and save the Python file, it will break and exit, and the container will stop. After that, you can restart the container by fixing the error and running the `docker-compose up -d` command again. The backend [Dockerfile](backend/Dockerfile) is in the backend directory.
6563

66-
For the frontend, a different Dockerfile is used in the `docker-compose.override.yml`. In development, the frontend docker container starts with the `npm run dev -- --host` command, while in production the frontend app is built and the app is served by an nginx server. The [nginx configuration file](frontend/nginx.conf) is in the frontend dir.
64+
For the frontend, when in development, the frontend docker container starts with the `npm run dev -- --host` command, while in production the frontend app is built into static files and the app is served by an nginx server. The [nginx configuration file](frontend/nginx.conf) is in the frontend dir.
6765

6866
### Accessing the containers
6967

7068
To get inside a container with a `bash` session you can start the stack with:
7169

7270
```console
73-
$ docker-compose up -d
71+
$ docker compose up -d
7472
```
7573

7674
and then `exec` inside the running container:
7775

7876
```console
79-
$ docker-compose exec backend bash
77+
$ docker compose exec backend bash
8078
```
8179

8280
This will give you access to a bash session in the `backend` container. Change the name of the container to the one you want to access.
8381

84-
## Deployment
85-
86-
Deployment to a Docker Swarm mode cluster should be possible, but it has not been tested. Refer to Tiangolo's [Full stack FastAPI cookiecutter](https://github.com/tiangolo/full-stack-fastapi-postgresql) project documentation for information on how to manage deployment and how to configure the Traefik proxy with constraints and such. The <a href="https://dockerswarm.rocks" target="_blank">DockerSwarm.rocks</a> tutorials are also a good place to look for info.
8782

88-
## Docker Compose files and env vars
83+
### Docker Compose settings for production
8984

90-
There is a main `docker-compose.yml` file with all the configurations that apply to the whole stack, it is used automatically by `docker-compose`.
85+
The [docker-compose-prod.yml](./docker-compose.prod.yml) file contains the configuration to run the application with docker in a production environment, on a host server. To run the application with this file, run
9186

92-
And there's also a `docker-compose.override.yml` with overrides for development, for example to mount the source code as a volume. It is used automatically by `docker-compose` to apply overrides on top of `docker-compose.yml`.
93-
94-
These Docker Compose files use the [.env](./.env) file containing configurations to be injected as environment variables in the containers.
95-
96-
They also use some additional configurations taken from environment variables set in the scripts before calling the `docker-compose` command.
97-
98-
It is all designed to support several "stages", like development, building, testing, and deployment. Also, allowing the deployment to different environments like staging and production.
99-
100-
They are designed to have the minimum repetition of code and configurations, so that if you need to change something, you have to change it in the minimum amount of places. That's why files use environment variables that get auto-expanded. That way, if for example, you want to use a different domain, you can call the `docker-compose` command with a different `DOMAIN` environment variable instead of having to change the domain in several places inside the Docker Compose files.
87+
```console
88+
docker compose -f docker-compose.prod.yml up -d
89+
```
10190

102-
Also, if you want to have another deployment environment, say `preprod`, you just have to change environment variables, but you can keep using the same Docker Compose files.
91+
**Note:** This will not work out of the box, mainly because the `docker-compose-prod.yml` configures a traefik proxy with ssl enabled that will try to fetch ssl certificates from Let's Encrypt, which will not work unless you specify a valid hostname accessible on the internet. However, to deploy the application in production on a server, you only need to set the required env variables in the [.env](./.env) file.
10392

104-
### The .env file
93+
### Docker Compose files and env vars
10594

106-
The [.env](./.env) file is the one that contains all your configurations, generated keys and passwords, etc.
95+
Both the [docker-compose.yml](./docker-compose.yml) and [docker-compose-prod.yml](./docker-compose.prod.yml) files use the [.env](./.env) file containing configurations to be injected as environment variables in the containers.
10796

108-
Depending on your workflow, you could want to exclude it from Git, for example if your project is public. In that case, you would have to make sure to set up a way for your CI tools to obtain it while building or deploying your project.
97+
The docker-compose files are designed to support several environments (i.e. development, building, testing, production) simply by setting the appropriate variable values in the `.env` file.
10998

110-
One way to do it could be to add each environment variable to your CI/CD system, and updating the `docker-compose.yml` file to read that specific env var instead of reading the `.env` file.
99+
The [.env](./.env) file contains all the configuration variables. The values set in the `.env` file will override those that are set in the frontend and backend `.env` files for local development. For exemple, the backend app also has a [.env.dev](backend/.env.dev) file which is read to populate the backend's [config](backend/app/config/config.py) module. When the application is run with docker though, the env variables in the projet root's [.env](./.env) file will override the env variables set in the backend and frontend's respective .env files. In order to be able to keep working both with docker and manually, you only have to make sure that the required variables are set both in the root `.env` file, and in the backend and frontend `.env` files.
111100

112-
**Note** that in order to have both the backend and frontend app be able to run locally without docker, those apps also expect to find env variables in their respective directory. For exemple, the backend app also has a [.env.dev](backend/.env.dev) file which is read to populate the backend's [config](backend/app/config/config.py) module. When the application is run with docker though, the env variables in the projet root's [.env](./.env) file will override the env variables set in the backend and frontend's respective .env files.
113-
In order to be able to keep working both with docker and manually, you only have to make sure that the required variables are set both in the root `.env` file, and in the backend and frontend `.env` files.
101+
The `.env` file that is commited to the github repository contains example values which are ok to use for testing and development, but which should be changed when running the application in production (admin passwords, secret keys, client ids, etc.). During deployment in production, the .env file is replaced with one containing the appropriate values.

backend/.env.dev

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,23 @@ PROJECT_NAME=farm-docker
33
SERVER_NAME=localhost
44
SERVER_HOST=http://localhost
55

6-
76
# MongoDB
87
MONGO_HOST=localhost
9-
MONGO_DB=farmdocker
8+
MONGO_DB=farmd
109
MONGO_PORT=27017
1110
MONGO_USER=
1211
MONGO_PASSWORD=
1312

1413
# Super User
1514
FIRST_SUPERUSER=[email protected]
1615
FIRST_SUPERUSER_PASSWORD=admin
16+
17+
# SSO config
18+
GOOGLE_CLIENT_ID=
19+
GOOGLE_CLIENT_SECRET=
20+
FACEBOOK_CLIENT_ID=
21+
FACEBOOK_CLIENT_SECRET=
22+
# HOSTNAME used to build google redirect uri
23+
SSO_CALLBACK_HOSTNAME=http://localhost:8000
24+
# Callback URL we redirect to after google login
25+
SSO_LOGIN_CALLBACK_URL=http://localhost:5173/sso-login-callback

backend/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ Navigate to `http://localhost:8000/api/v1/` to access the root API path.
3131
Navigate to `http://localhost:8000/docs` to access the API's documentation.
3232
Navigate to `http://localhost:8000/redoc` to access the API's alternative doc built with ReDoc.
3333

34+
## Running the tests
35+
36+
Run
37+
38+
```console
39+
pytest
40+
```
41+
42+
to run the unit test for the backend app.
43+
3444
## Configuration
3545

3646
The project uses Pydantic's settings management through FastAPI. Documentation on how the settings work is availabe [here](https://fastapi.tiangolo.com/advanced/settings/).

0 commit comments

Comments
 (0)