Skip to content
Snippets Groups Projects
readme.md 7.8 KiB
Newer Older
Jacek Lebioda's avatar
Jacek Lebioda committed
# SMart SCHeduling

[![coverage report](https://git-r3lab.uni.lu/NCER-PD/scheduling-system/badges/master/coverage.svg)](https://git-r3lab.uni.lu/NCER-PD/scheduling-system/commits/master)
Piotr Gawron's avatar
Piotr Gawron committed
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)

## Docker version
If you'd like to try out the application without preparing the environment, you can use Docker (you must have _Docker_ and _docker-compose_ installed):

```
# Navigate to the project's directory
docker-compose build && docker-compose up
# To add a new user, type in the new terminal:
docker-compose exec web sh
python manage.py createsuperuser
```
Jacek Lebioda's avatar
Jacek Lebioda committed
## Required software (on ubuntu's OS family):
  - `sudo apt-get install libpq-dev python-dev postgresql postgresql-contrib python virtualenv python-virtualenv gcc python-lxml libxml2-dev libcurl4-openssl-dev libcurl4-gnutls-dev libgnutls28-dev`
Jacek Lebioda's avatar
Jacek Lebioda committed

## Postgres installation
  - If you don't have postgres installed, complete step seven from [https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-django-with-postgres-nginx-and-gunicorn](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-django-with-postgres-nginx-and-gunicorn) (remember to save all the credentials, they will be necessary to run the application).
Jacek Lebioda's avatar
Jacek Lebioda committed

## Developer project installation
  - `mkdir -p ~/dev/smash`
  - `cd ~/dev/smash`
Piotr Gawron's avatar
Piotr Gawron committed
  - `git clone ssh://git@git-r3lab-server.uni.lu:8022/NCER-PD/scheduling-system.git`
  - `cd scheduling-system`
  - `virtualenv env` to create new virtualenv (contains clean python working environment)
  - `. env/bin/activate` (to start using virtualenv)
  - `pip install --use-deprecated=legacy-resolver -r requirements.txt` to install project's dependencies
  - Create `local_settings.py` file in `(./scheduling-system)/smash/smash` directory by copying the template in `(./scheduling-system)/smash/smash/local_settings.template` and edit your local_setttings.py file to change your database connection data.
Piotr Gawron's avatar
Piotr Gawron committed
 - Update migration db scrpit from file structure (`./scheduling-system/smash/manage.py makemigrations`)
 - Create the database by applying migrations (`./scheduling-system/smash/manage.py migrate`)
 - Create the first, administrative, user-  (`./scheduling-system/smash/manage.py createsuperuser`)

## Development    
  - Remember, that before working you have to activate _virtualenv_, by: `devel@host ~/home/smash/scheduling-system $ . env/bin/activate`
  - In order to run development server, run: `devel@host ~/home/smash/scheduling-system/smash $ ./manage.py runserver` and go to `127.0.0.1:8000` in browser
Jacek Lebioda's avatar
Jacek Lebioda committed
  - For reference of HTML tempalte, see [https://almsaeedstudio.com/themes/AdminLTE/pages/widgets.html#](https://almsaeedstudio.com/themes/AdminLTE/pages/widgets.html#)
Valentin Groues's avatar
Valentin Groues committed
### Mac Developers

In case of problems with the openssl version installed on the system:

```
export PYCURL_SSL_LIBRARY=openssl
pip install pycurl --global-option=build_ext --global-option="-I/usr/local/Cellar/openssl/1.0.2k/include" --global-option="-L/usr/local/Cellar/openssl/1.0.2k/lib" --upgrade
pip install psycopg2 --global-option=build_ext --global-option="-I/usr/local/Cellar/openssl/1.0.2k/include" --global-option="-L/usr/local/Cellar/openssl/1.0.2k/lib" --upgrade
```

## Production deployment
  - git pull and other project installation should be performed in a dir where this django app should be installed, in this tutorial it's /var/www/scheduling-system/
  - install nginx: `apt-get install nginx`
Jacek Lebioda's avatar
Jacek Lebioda committed
  - create gunicorn service in systemd (http://docs.gunicorn.org/en/stable/deploy.html#systemd):
Jacek Lebioda's avatar
Jacek Lebioda committed
### /etc/systemd/system/gunicorn.service

```
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
PIDFile=/run/gunicorn/pid
User=www-data
Group=www-data
WorkingDirectory=/var/www/scheduling-system/smash

ExecStart=/var/www/scheduling-system/env/bin/gunicorn --pid /run/gunicorn/pid smash.wsgi --error-logfile /var/log/gunicorn.log --log-level DEBUG --capture-output --limit-request-line 8192
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target
```

Don't forget to change ownership of `/run/gunicorn/` folder and `/var/log/gunicorn.log` file.
```
chown -R www-data:www-data /run/gunicorn/
touch /var/log/gunicorn.log
chown www-data:www-data /var/log/gunicorn.log
```
### /etc/systemd/system/gunicorn.socket

```
[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn/socket
ListenStream=0.0.0.0:9000
ListenStream=[::]:8000

[Install]
WantedBy=sockets.target
   - modify nginx configuration

### /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
        worker_connections 768;
        # multi_accept on;
}
http {
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # SSL Settings
        ##

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        ##
        # Gzip Settings
        ##

        gzip on;
        gzip_disable "msie6";

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}
```

### /etc/nginx/sites-enabled/default

```
upstream app_server {
    # fail_timeout=0 means we always retry an upstream even if it failed
    # to return a good HTTP response

    # for UNIX domain socket setups
    server unix:/run/gunicorn/socket fail_timeout=0;

    # for a TCP configuration
    # server 192.168.0.7:8000 fail_timeout=0;
}

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        listen 443 ssl;


        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        server_name prc.parkinson.lu;

        ssl_certificate /etc/nginx/ssl/nginx.crt;
        ssl_certificate_key /etc/nginx/ssl/nginx.key;


        #configuration for static and media files hosted by nginx
        location /media/ {
                root /var/www/scheduling-system-files;
        }

        location /static/ {
                root /var/www/scheduling-system-files;
        }


        location / {
              # checks for static file, if not found proxy to app
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
              # enable this if and only if you use HTTPS
              # proxy_set_header X-Forwarded-Proto https;
              proxy_set_header Host $http_host;
              # we don't want nginx trying to do something clever with
              # redirects, we set the Host: header above already.
              proxy_redirect off;
              proxy_pass http://app_server;
    }

}
```
  - extract static files and make them available via nginx: `./manage.py collectstatic`
Jacek Lebioda's avatar
Jacek Lebioda committed
  - you start application by starting gunicorn and nginx: `service gunicorn start`, `service nginx start`
Piotr Gawron's avatar
Piotr Gawron committed
## Cron jobs (weekly emails)

If weekly emails are required then cron must be edited to fire periodically django function that send emails.

```
> crontab -e
SHELL=/bin/bash
*/30 * * * * source /var/www/scheduling-system/env/bin/activate && python /var/www/scheduling-system/smash/manage.py runcrons >> /var/log/django-cronjob.log 2>&1
Piotr Gawron's avatar
Piotr Gawron committed
```

### Disable two steps authentication for a specific user


```
./manage.py two_factor_disable ${USERNAME}
```

### Public holidays

to import public holidays run:

```
./manage.py holidays ${YEARS}
```

where ${YEARS} should be a space separated list of years for which the holidays will be imported.

example:

```
./manage.py holidays 2017 2018 2019