Skip to content
Snippets Groups Projects
README.md 3.99 KiB
Newer Older
Ivan Procaccini's avatar
Ivan Procaccini committed
# Flask Template

This repository contains a Flask web application template to aid the development of DoC web applications.

## How to use this template

It's easy:
1. Fork it
2. Explore the code
3. Code a new app!

## Preparation

For environment setup and troubleshooting, consult the [docs](https://gitlab.doc.ic.ac.uk/edtech/docs/-/tree/master).

## Overview

The template offers a standard Flask application structure, which should hopefully me mostly self-explanatory.
A quick overview of the application's organisation is given below:

| Package | Content Description |
|---------|--------------------------|
| `auth/` | LDAP authentication wrapper and utilities. |
| `database/` | The app database object. |
| `models/` | The app data models. |
| `forms/` | Form classes for input validation. |
| `mocks/` | Fake implementation of third-party modules (like LDAP). |
| `messages/` | Library to build and encode HTML messages. |
| `static/`, `templates/` | Standard Flask application folders for static content and HTML templates. |
| `views/` | Application [blueprints](http://flask.pocoo.org/docs/1.0/tutorial/views/). |

### Configuration

The application's configuration (in `config.py`) is object-based. Many preconfigured configurations
are provided, one per standard deployment environment. The available
configurations are *development*, *staging* and *production*.
Any configuration other than *development* (selected by default) can be enabled
by setting the `ENV` environment variable to the desired configuration name
(e.g. `export ENV=production` to enable the *production* configuration).
The default *development* configuration sets up the application to
run in isolation by replacing any external service provider (like LDAP) with its fake counterpart (in `mocks/`).

The application's instantiation is performed through the `create_app()` method in the main `__init__.py`
(in compliance with the **factory pattern**). The method accepts a dictionary configuration for
testing purposes, which -when provided- overrides the object-based
configuration.

## Running the Application
Before running the application, its dependencies must be available.
To download all the required dependencies:
- **create a virtual environment** by running `python3.8 -m venv venv`
- **activate the environment** by running `source venv/bin/activate`
- **install the dependencies** by executing `pip install --upgrade pip && pip install -r requirements.txt`

In a local development environment, the app can then be run directly with flask (by default on localhost, port 5000).
To do so, run:
```
(venv) $ export FLASK_ENV=development
(venv) $ export FLASK_APP=flask_template
(venv) $ flask create_all
(venv) $ flask run
```

In a staging/production environment, the app is run "behind" a gunicorn web-server. The code to start (and *re*start)
the web-server, executed during the deployment stage of the pipeline defined in `.gitlab-ci.yml`, is in `scripts/restart`.

### Logging in with the default configuration
As already mentioned, the default configuration runs with a fake instance of the LDAP service (to make things easier
locally). The users recognised by this fake service must be defined in `fake_ldap_base/users.json`. You are provided
with one user, *Logan Howlett* (sounds familiar?). To log into the application, enter the user name *logan* and any
character you wish as password (the actual value is ignored by the fake LDAP).

## Testing
No tests are provided by default, but if they were, they'd sit under `tests/`.
The interesting bit there is in `conftest.py`, where fixtures for a dummy application
instance, database and authentication handler are defined.
To run the tests, from the top directory of the project run `pytest`.

## Continuous Integration
For your benefit, you are provided with a simple GitLabCI script in `txt` format. To use it for your project,
change the extension to `yml` and push it to your remote repository.
Note that you need to have a [GitLab Runner](https://docs.gitlab.com/runner/) spinning somewhere for the pipeline to be executed.