Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Mathias Lundteigen Mohus committed Feb 25, 2025
0 parents commit dae90e6
Show file tree
Hide file tree
Showing 103 changed files with 26,803 additions and 0 deletions.
18 changes: 18 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
GROUP_ID=00
DOMAIN=localhost
URL_PREFIX=http://
PORT_PREFIX=2
DEV_POSTFIX=1
STAG_POSTFIX=2
PROD_POSTFIX=3
DEV_PORT_PREFIX=${PORT_PREFIX}${GROUP_ID}${DEV_POSTFIX}
STAG_PORT_PREFIX=${PORT_PREFIX}${GROUP_ID}${STAG_POSTFIX}
PROD_PORT_PREFIX=${PORT_PREFIX}${GROUP_ID}${PROD_POSTFIX}

BACKEND_POSTFIX=4
FRONTEND_POSTFIX=5
GATEWAY_POSTFIX=6

DJANGO_SUPERUSER_PASSWORD=Password
DJANGO_SUPERUSER_USERNAME=admin
DJANGO_SUPERUSER_EMAIL=admin@mail.com
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.pack filter=lfs diff=lfs merge=lfs -text
43 changes: 43 additions & 0 deletions .github/workflows/deploy_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Deploy to TDT4242 server development

on:
workflow_dispatch:
inputs:
config:
description: "Which compose config file to deploy"
required: true
default: "docker-compose.dev.yml"
type: choice
options:
- "docker-compose.dev.yml"
- "docker-compose.stag.yml"
- "docker-compose.yml"

jobs:
deploy:
runs-on: self-hosted
env:
REPO_NAME: ${{ github.event.repository.name }}
COMPOSE_FILE: ${{ github.event.inputs.config }}

steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Dotenv Action
uses: falti/dotenv-action@v1.1.4
with:
export-variables: true
keys-case: bypass

- name: Check status of config file
run: |
env
docker compose version
cd $GITHUB_WORKSPACE
docker compose -f $COMPOSE_FILE --verbose config && printf "OK\n" || exit 1
- name: Build and run docker image
run: docker compose -f $COMPOSE_FILE up --force-recreate --build -d

- name: Verify that gateway is available
run: docker ps
31 changes: 31 additions & 0 deletions .github/workflows/update_primary_nginx.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: UNFINISHED - setup nginx from the configuration file

on:
workflow_dispatch:

jobs:
deploy:
runs-on: self-hosted

steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Dotenv Action
uses: falti/dotenv-action@v1.1.4
with:
export-variables: true
keys-case: bypass

- name: Check environment variables
run: env

#Doesn't work properly, envsubst replaces all instances of $variable and ${variable}, but we want to keep e.g., $host as nginx variables
#- name: Create temporary nginx config file
# run: envsubst < ./nginx_template.txt > temp_default.conf
# Maybe look at https://www.baeldung.com/linux/envsubst-command to get an idea

- name: Copy temporary file to correct place
run: cp temp_default.conf /etc/nginx/conf.d/default.conf

- name: Show nginx file
run: cat /etc/nginx/conf.d/default.conf
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.idea/
.vscode/
backend/secfit/.vscode/
backend/secfit/*/migrations/__pycache__/
backend/secfit/*/__pycache__/
backend/secfit/db.sqlite3
173 changes: 173 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# SecFit

SecFit (Secure Fitness) is a hybrid mobile application for fitness logging.

## Port mapping shenanigans

The port mapping in this application is a bit strange to enable hosting multiple stages (development/staging/production) with multiple containers for each, without needing to handle multiple DNSs.

We use static variables combine these to create unique ports for each container:

`PREFIX` is always defined as 2 and is found in the [.env](.env) file as `PORT_PREFIX=2`. This is needed in order for the full port to be on the form 2XXXX, to avoid crashing with established ports.

`GROUP_ID` is defined by your group number on BlackBoard, found in the [.env](.env) file as `GROUP_ID=XX`. This is always 2 numbers, so groups 1-9 have leading zeros, i.e., group 3 has `GROUP_ID=03`.


`STAGE` is defined as:
- development: 1
- staging: 2
- production: 3

The related variables can be found in the [.env](.env) file as `DEV_POSTFIX=1`, `STAG_POSTFIX=2`, and `PROD_POSTFIX=3`.

`CONTAINER_ID` is defined as:
- backend: 4
- frontend: 5
- gateway: 6

The related variables can be found in the [.env](.env) file as `BACKEND_POSTFIX=4`, `FRONTEND_POSTFIX=5`, and `GATEWAY_POSTFIX=6`.


The *ports* section of each compose file ([docker-compose.dev.yml](docker-compose.dev.yml), [docker-compose.stag.yml](docker-compose.stag.yml), and [docker-compose.yml](docker-compose.yml)) define which images are accessible from outside the isolated Docker network. Currently, all images are available in development and staging, while only the gateway is available in production.

To make ports available from outside the server, you'll need to either modify firewall/routing on the server or (as we have elected to do for this project) use a backward proxy. This is defined through the [./nginx_template.txt](./nginx_template.txt) file, which, when used with the ```$ envsubst < nginx_template.txt``` command, replaces the variables with the environment variables set by the [.env](.env) file (how to do this properly is left as part of task 1 in exercise 2).

The default setup to make the application available from the outside is to listen on ports `PREFIX + GROUP_ID + STAGE + 7` (and port 80 for production), mapping to their related gateways `PREFIX + GROUP_ID + STAGE + 6`.

One note on this is to make sure the ```proxy_set_header Host $http_host;``` is set with `$http_host` and not `$host` (as it normally is) in order to forward the port being used (otherwise, it assumes port 80 based on the default HTTP protocol).


### Port examples

| **Group Number** | **Stage** | **Image** | **Port** |
| :---: | :---: | :---: | :---: |
| 04 | development | backend | 20414 |
| 21 | staging | gateway | 22126 |
| 00 | production | frontend | NA (not available) |


## Deploy with Docker

### Prerequisites:

Docker

Git

Windows hosts must use Education or more advanced versions to run Docker \
Download: [https://innsida.ntnu.no/wiki/-/wiki/English/Microsoft+Windows+10](https://innsida.ntnu.no/wiki/-/wiki/English/Microsoft+Windows+10)

### Install:

```console
$ git clone https://git.ntnu.no/mathialm/secfit
$ cd secfit
```

### Run:

```console
$ docker-compose -f <compose_file> up --build -d
```

## Using GitHub actions
Managing GitHub actions is done from your repository's `Actions` tab.

From here, you can add, modify, and read the logs from all workflows.

The workflow files are stored in the [.github/workflows/](.github/workflows/) folder.

Documentation and tutorials for GitHub Actions can be found at [https://docs.github.com/en/actions](https://docs.github.com/en/actions)


## Technology
- **deployment** - Docker/Docker Compose/GitHub actions
- **web** - Nginx
- **database** - SQLite 3
- **backend** - Django 4 with Django REST framework
- **frontend** - HTML5/CSS/JS, React 4
- **authentication** - JWT


## Backend code and structure

- **secfit/** django project folder containing the project modules
- **<application_name>/** - generic structure of a Django application
- **migrations/** - directory containing django migrations enabling _mostly_ automatic modifications to your data models, see [https://docs.djangoproject.com/en/5.1/topics/migrations/](https://docs.djangoproject.com/en/5.1/topics/migrations/)
- **admin.py** - file containing definitions to connect models to the Django admin panel
- **apps.py** - defined the application for this directory
- **forms.py** - definitions of forms. Used to render html forms and verify user input
- **models.py** - contains data models
- **parsers.py** - contains custom parsers for parsing the body of HTTP requests
- **permissions.py** - contains custom permissions that govern access
- **settings.py** - Contains important settings at the application and/or project level
- **serializers.py** - contains serializer definitions for sending data between backend and frontend
- **tests/** - contains tests for the module. See [https://docs.djangoproject.com/en/2.1/topics/testing/](https://docs.djangoproject.com/en/2.1/topics/testing/) for more
- **urls.py** - contains the mapping between URLs and views
- **views.py** - Controller in MVC. Methods for rendering and accepting user data
- **media/** - directory for file uploads
- **comments/** - application handling user comments and reactions
- **secfit/** - The projects main module containing project-level settings
- **tests/** - Container Docker config for test and test_template
- **users/** - application handling users and requests
- **workouts/** - application handling exercises and workouts
- **db.sqlite3** - SQLite database file
- **manage.py** - entry point for running the project.
- **requirements.txt** - Python requirements


## Local setup
It's recommended to have a look at: https://www.djangoproject.com/start/
Just as important is the Django REST guide: https://www.django-rest-framework.org/

Create a virtualenv https://docs.python-guide.org/dev/virtualenvs/


### Django

Installation with examples for Ubuntu. Windows and OSX is mostly the same

Fork the project and clone it to your machine.

#### Setup and activation of virtualenv (env that prevents python packages from being installed globally on the machine)
Navigate into the project folder, and create your own virtual environment


#### Install python requirements

```console
$ pip install -r requirements.txt
```

#### Migrate database

```console
$ python manage.py migrate
```

#### Create superuser

Create a local admin user by entering the following command:

```console
$ python manage.py createsuperuser
```

Only username and password is required


#### Start the app

```console
$ python manage.py runserver
```


#### Add initial data

You can add initial data by going to the URL the app runs on locally and adding `/admin` to the URL.

Add some categories and you should be all set.

## Assumptions
The file .env would normally not be uploaded together with the code since that is bad practice allowing for sensitive data exposure. The file is however essential to run the application, and needs to stay where it is. If any other secret values needs to be stored 'outside' the code repository, this is where it should be put. If you use a different file, it should still be added to the repository, but you should state it here as an assumption.
Loading

0 comments on commit dae90e6

Please sign in to comment.