Merge branch 'develop' into 'master'
Prod deploy: Python 3.9, poetry & dependency updates, SendGrid, Managed DB See merge request sahkoinsinoorikilta/vtmk/web2.0-backend!41
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
[report]
|
||||
show_missing = True
|
||||
omit =
|
||||
*/migrations/*
|
||||
*/admin.py
|
||||
*/translation.py
|
||||
[run]
|
||||
omit =
|
||||
*/migrations/*
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "Deploying to development."
|
||||
set -e
|
||||
set -x
|
||||
|
||||
pushd deployment
|
||||
|
||||
docker-compose down
|
||||
docker pull "$1"
|
||||
docker-compose up -d
|
||||
|
||||
popd
|
||||
|
||||
set +x
|
||||
set +e
|
||||
@@ -2,9 +2,8 @@ HOST=api.dev.sahkoinsinoorikilta.fi
|
||||
DEBUG=True
|
||||
SECRET_KEY=7p$85^4ibb^p4-=vs44b7!y0e-zemugze18@a#30&71=a8)dp(
|
||||
TG_BOT_TOKEN=
|
||||
EMAIL_HOST=
|
||||
EMAIL_PASSWD=
|
||||
DB_USER=postgres
|
||||
DB_PASSWD=postgres
|
||||
DB_HOST=db
|
||||
DB_PORT=5432
|
||||
DB_PORT=5432
|
||||
EMAIL_API_KEY=
|
||||
|
||||
+2
-3
@@ -2,9 +2,8 @@ HOST=localhost
|
||||
DEBUG=True
|
||||
SECRET_KEY=7p$85^4ibb^p4-=vs44b7!y0e-zemugze18@a#30&71=a8)dp(
|
||||
TG_BOT_TOKEN=
|
||||
EMAIL_HOST=
|
||||
EMAIL_PASSWD=
|
||||
DB_USER=postgres
|
||||
DB_PASSWD=postgres
|
||||
DB_HOST=db
|
||||
DB_PORT=5432
|
||||
DB_PORT=5432
|
||||
EMAIL_API_KEY=
|
||||
|
||||
+7
-16
@@ -1,23 +1,14 @@
|
||||
*.swp
|
||||
.DS_Store
|
||||
.env
|
||||
*~
|
||||
*.pyc
|
||||
*.sqlite3
|
||||
uwsgi.ini
|
||||
uwsgi.log
|
||||
members/logs/*
|
||||
.idea/
|
||||
logs/
|
||||
/collected_static/
|
||||
/media/
|
||||
logs/
|
||||
members/logs/*
|
||||
node_modules/
|
||||
.coverage
|
||||
db.sqlite3
|
||||
requirements_henu.txt
|
||||
/collected_static/
|
||||
mydatabase
|
||||
settings.json
|
||||
.vscode/
|
||||
.DS_Store
|
||||
.idea/
|
||||
*.code-workspace
|
||||
sik_test
|
||||
venv/
|
||||
venv/
|
||||
.venv/
|
||||
|
||||
+18
-4
@@ -1,5 +1,6 @@
|
||||
stages:
|
||||
- setup
|
||||
- audit
|
||||
- lint
|
||||
- test
|
||||
- publish
|
||||
@@ -15,8 +16,19 @@ install:
|
||||
- node_modules
|
||||
expire_in: 1 week
|
||||
|
||||
audit:
|
||||
image: python:3.9
|
||||
stage: audit
|
||||
needs: []
|
||||
before_script:
|
||||
- pip install poetry==1.1.4
|
||||
- poetry config virtualenvs.create false
|
||||
- poetry install --no-interaction --no-ansi
|
||||
script:
|
||||
- safety check
|
||||
|
||||
test:
|
||||
image: python:3.7
|
||||
image: python:3.9
|
||||
stage: test
|
||||
needs: []
|
||||
services:
|
||||
@@ -27,15 +39,17 @@ test:
|
||||
POSTGRES_PASSWORD: postgres
|
||||
DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB"
|
||||
DB_HOST: postgres
|
||||
before_script:
|
||||
- pip install poetry==1.1.4
|
||||
- poetry config virtualenvs.create false
|
||||
- poetry install --no-interaction --no-ansi
|
||||
script:
|
||||
- python -V
|
||||
- pip install -r requirements.txt
|
||||
- python manage.py migrate --noinput
|
||||
- python manage.py createdefaultadmin
|
||||
- python manage.py test
|
||||
|
||||
lint:py:
|
||||
image: python:3.7
|
||||
image: python:3.9
|
||||
stage: lint
|
||||
needs: []
|
||||
script:
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
3.7.4
|
||||
3.9
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
global_static
|
||||
+22
-14
@@ -1,20 +1,28 @@
|
||||
FROM python:3.7-alpine
|
||||
FROM python:3.9-slim-buster as builder
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
WORKDIR /app
|
||||
COPY requirements.txt ./
|
||||
COPY requirements.production.txt ./
|
||||
COPY . ./
|
||||
|
||||
# uWSGI, gunicorn etc.
|
||||
RUN apk add --no-cache python3-dev build-base linux-headers pcre-dev openssl bash \
|
||||
# PSQL
|
||||
&& apk add --no-cache postgresql-dev \
|
||||
# Pillow
|
||||
&& apk add --no-cache jpeg-dev zlib-dev \
|
||||
&& pip install --upgrade pip \
|
||||
&& pip install -r requirements.txt \
|
||||
&& pip install -r requirements.production.txt
|
||||
ENV POETRY_VERSION=1.1.4
|
||||
|
||||
RUN pip install "poetry==$POETRY_VERSION"
|
||||
RUN poetry export > requirements.txt
|
||||
|
||||
FROM python:3.9-slim-buster as server
|
||||
|
||||
WORKDIR /app
|
||||
COPY . ./
|
||||
COPY --from=builder requirements.txt ./
|
||||
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
# prevents python creating .pyc files
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
# pip
|
||||
PIP_NO_CACHE_DIR=off \
|
||||
PIP_DISABLE_PIP_VERSION_CHECK=on \
|
||||
PIP_DEFAULT_TIMEOUT=100
|
||||
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y build-essential
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
RUN python manage.py collectstatic --noinput
|
||||
|
||||
CMD ["sh", "-c", "./production_entrypoint.sh"]
|
||||
|
||||
@@ -13,7 +13,6 @@ services:
|
||||
web:
|
||||
build: .
|
||||
image: registry.gitlab.com/sahkoinsinoorikilta/vtmk/web2.0-backend
|
||||
command: ["bash", "-c", "cd /app & bash setup.sh --no-input --no-npm && gunicorn -w 4 -b 0.0.0.0:8000 sikweb.wsgi"]
|
||||
env_file:
|
||||
- .env
|
||||
ports:
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from datetime import timedelta
|
||||
from webapp.utils import month_from_now
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from auditlog.registry import auditlog
|
||||
from phonenumber_field.modelfields import PhoneNumberField
|
||||
from webapp.models import BaseRole
|
||||
import logging
|
||||
|
||||
|
||||
# TODO: Move BaseRole to Kaehmt App; will fuck up the DB since table is removed, if no data migration is done before-hand.
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
# Linux/Mac installation instructions
|
||||
|
||||
## Install dependencies
|
||||
|
||||
### Dependency list
|
||||
|
||||
* Python >3.5
|
||||
* PostgreSQL >9.5
|
||||
* pip3
|
||||
* virtualenv
|
||||
* npm
|
||||
|
||||
Install with apt:
|
||||
|
||||
```bash
|
||||
sudo apt install python3
|
||||
sudo apt install python3-pip
|
||||
sudo apt install postgresql
|
||||
sudo pip3 install virtualenv
|
||||
sudo apt install npm
|
||||
```
|
||||
|
||||
More info about PostgreSQL at:
|
||||
[https://www.postgresql.org/](https://www.postgresql.org)
|
||||
|
||||
These packages might be needed on certain platforms:
|
||||
|
||||
* python3-dev
|
||||
* libffi-dev
|
||||
* python3-cffi
|
||||
* libssl-dev
|
||||
|
||||
## Create a virtual environment for python
|
||||
|
||||
Create a virtualenv in the parent directory.
|
||||
|
||||
```bash
|
||||
virtualenv -p python3 ../virtualenv.sikweb
|
||||
```
|
||||
|
||||
## Activate virtualenv
|
||||
|
||||
Assuming we are at the root of this repository and virtualenv is one level above.
|
||||
|
||||
```bash
|
||||
. ../virtualenv.sikweb/bin/activate
|
||||
```
|
||||
|
||||
## Run install wizard
|
||||
|
||||
Run the install wizard with
|
||||
|
||||
```bash
|
||||
bash setup.sh
|
||||
```
|
||||
|
||||
and follow the instructions.
|
||||
|
||||
## Done
|
||||
|
||||
## In case of error on macOS Mojave 10.14
|
||||
|
||||
If you get an error saying
|
||||
|
||||
```bash
|
||||
The headers or library files could not be found for zlib,
|
||||
a required dependency when compiling Pillow from source.
|
||||
```
|
||||
|
||||
run
|
||||
|
||||
```bash
|
||||
xcode-select --install
|
||||
sudo installer -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg -target /
|
||||
```
|
||||
@@ -640,10 +640,10 @@ msgstr "Amazing! Your membership application has been sent."
|
||||
|
||||
#: members/templates/application_success.html:9
|
||||
msgid ""
|
||||
"Vahvistusviesti on lähetetty sähköpostiisi. Ota yhteyttä sik-vtmk@list.ayy."
|
||||
"Vahvistusviesti on lähetetty sähköpostiisi. Ota yhteyttä admin@sahkoinsinoorikilta.fi."
|
||||
"fi jos viestiä ei näy."
|
||||
msgstr ""
|
||||
"Confirmation email is sent to given email address. Contact sik-vtmk@list.ayy."
|
||||
"Confirmation email is sent to given email address. Contact admin@sahkoinsinoorikilta.fi."
|
||||
"fi if you didn't receive it."
|
||||
|
||||
#: members/templates/application_success.html:10
|
||||
|
||||
@@ -453,9 +453,9 @@ msgstr "Vaalikokous, osa 3 (toimarien valinta)"
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" Hyväksyn <a href=\"https://sik.ayy.fi/files/official/"
|
||||
"Tietosuojaseloste%%20%%E2%%80%%93%%20Toimihenkil%%C3%%B6ksi%%20hakemisen"
|
||||
"%%20rekisteri.pdf\" target=\"_blank\">tietosuojaselosteen</a> ja tietojeni "
|
||||
" Hyväksyn <a href=\"https://static.sahkoinsinoorikilta.fi/GDPR/"
|
||||
"Tietosuojaseloste%20%23U2013%20Toimihenkil%23U00f6ksi%20hakemisen"
|
||||
"%20rekisteri.pdf\" target=\"_blank\">tietosuojaselosteen</a> ja tietojeni "
|
||||
"tallentamisen.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
@@ -637,7 +637,7 @@ msgstr "Hienoa! Jäsenhakemuksesi on nyt lähetetty."
|
||||
|
||||
#: members/templates/application_success.html:9
|
||||
msgid ""
|
||||
"Vahvistusviesti on lähetetty sähköpostiisi. Ota yhteyttä sik-vtmk@list.ayy."
|
||||
"Vahvistusviesti on lähetetty sähköpostiisi. Ota yhteyttä admin@sahkoinsinoorikilta.fi."
|
||||
"fi jos viestiä ei näy."
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
{% block content %}
|
||||
<link rel="stylesheet" href="{% static "css/application.css" %}">
|
||||
<h3>{% trans "Hienoa! Jäsenhakemuksesi on nyt lähetetty." %}</h3>
|
||||
<p>{% trans "Vahvistusviesti on lähetetty sähköpostiisi. Ota yhteyttä sik-vtmk@list.ayy.fi jos viestiä ei näy." %}</p>
|
||||
<p>{% trans "Vahvistusviesti on lähetetty sähköpostiisi. Ota yhteyttä admin@sahkoinsinoorikilta.fi jos viestiä ei näy." %}</p>
|
||||
<a href="/"><h4>{% trans "Takaisin Sähköinsinöörikillan web-sivuille" %}</h4></a>
|
||||
{% endblock content %}
|
||||
|
||||
Generated
+370
-541
File diff suppressed because it is too large
Load Diff
@@ -10,8 +10,8 @@ fi
|
||||
if test -f "$EMAIL_API_KEY_FILE"; then
|
||||
export EMAIL_API_KEY=$(cat $EMAIL_API_KEY_FILE)
|
||||
fi
|
||||
if test -f "$EMAIL_API_SECRET_FILE"; then
|
||||
export EMAIL_API_SECRET=$(cat $EMAIL_API_SECRET_FILE)
|
||||
# if test -f "$EMAIL_API_SECRET_FILE"; then
|
||||
# export EMAIL_API_SECRET=$(cat $EMAIL_API_SECRET_FILE)
|
||||
fi
|
||||
if test -f "$DB_USER_FILE"; then
|
||||
export DB_USER=$(cat $DB_USER_FILE)
|
||||
|
||||
+35
-47
@@ -1,59 +1,47 @@
|
||||
[tool.poetry]
|
||||
name = "web2.0-backend"
|
||||
version = "0.1.0"
|
||||
description = ""
|
||||
authors = ["Your Name <you@example.com>"]
|
||||
description = "Backend for sahkoinsinoorikilta.fi"
|
||||
authors = ["Aarni Halinen aarni.halinen@sahkoinsinoorikilta.fi"]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.9"
|
||||
decorator = "^4.0.9"
|
||||
Django = "^2.2.19"
|
||||
requests = "^2.11.1"
|
||||
django-cors-headers = "^3.7.0"
|
||||
djangorestframework = "^3.12.4"
|
||||
djangorestframework-jwt = "^1.11.0"
|
||||
django-nose = "^1.4.5"
|
||||
psycopg2-binary = "^2.8.4"
|
||||
django-bootstrap3 = "^11.1.0"
|
||||
django-tables2 = "^1.6.1"
|
||||
dealer = "^2.0.5"
|
||||
django-modeltranslation = "^0.13b1"
|
||||
django-auditlog = "^0.4.5"
|
||||
django-phonenumber-field = {version = "^4.0.0", extras = ["phonenumbers"]}
|
||||
django-autocomplete-light = "^3.4.1"
|
||||
six = "^1.12.0"
|
||||
django-suit = "^0.2.26"
|
||||
pyexcel = "^0.5.14"
|
||||
pyexcel-xlsx = "^0.5.8"
|
||||
django-import-export = "^0.7.0"
|
||||
openpyxl = "^2.6.4"
|
||||
django-app-namespace-template-loader = "^0.4.1"
|
||||
django-filter = "^2.0.0"
|
||||
whitenoise = "^4.1.4"
|
||||
jsonschema = "^3.2.0"
|
||||
Markdown = "^3.2.2"
|
||||
uWSGI = "^2.0.18"
|
||||
gunicorn = "^20.1.0"
|
||||
Pillow = "^8.1.2"
|
||||
"backports.shutil_get_terminal_size" = "1.0.0"
|
||||
decorator = "4.0.9"
|
||||
Django = "2.1.5"
|
||||
ipython = "4.2.0"
|
||||
ipython_genutils = "0.1.0"
|
||||
pexpect = "4.1.0"
|
||||
pickleshare = "0.7.2"
|
||||
ptyprocess = "0.5.1"
|
||||
pytz = "2016.4"
|
||||
simplegeneric = "0.8.1"
|
||||
traitlets = "4.2.1"
|
||||
requests = "2.11.1"
|
||||
django-nocaptcha-recaptcha = "0.0.19"
|
||||
django-cors-headers = "2.0.1"
|
||||
djangorestframework = "3.8.2"
|
||||
PyJWT = "1.6.4"
|
||||
djangorestframework-jwt = "1.11.0"
|
||||
coverage = "4.3.4"
|
||||
django-nose = "1.4.5"
|
||||
nose-exclude = "0.5.0"
|
||||
psycopg2-binary = "2.8.4"
|
||||
django-bootstrap3 = "11.1.0"
|
||||
django-tables2 = "1.6.1"
|
||||
pycodestyle = "2.6.0"
|
||||
dealer = "2.0.5"
|
||||
django-modeltranslation = "0.13b1"
|
||||
django-auditlog = "0.4.5"
|
||||
phonenumbers = "8.11.4"
|
||||
django-phonenumber-field = {version = "4.0.0", extras = ["phonenumbers"]}
|
||||
django-autocomplete-light = "3.4.1"
|
||||
six = "1.12.0"
|
||||
django-suit = "0.2.26"
|
||||
telepot = "12.3"
|
||||
pyexcel = "0.5.14"
|
||||
pyexcel-xlsx = "0.5.8"
|
||||
django-import-export = "0.7.0"
|
||||
openpyxl = "2.6.4"
|
||||
django-app-namespace-template-loader = "0.4.1"
|
||||
django-filter = "2.0.0"
|
||||
whitenoise = "4.1.4"
|
||||
jsonschema = "3.2.0"
|
||||
mailjet-rest = "1.3.3"
|
||||
Markdown = "3.2.2"
|
||||
uWSGI = "2.0.18"
|
||||
gunicorn = "19.9.0"
|
||||
sendgrid = "^6.7.0"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
coverage = "^5.5"
|
||||
nose-exclude = "^0.5.0"
|
||||
safety = "^1.10.3"
|
||||
pycodestyle = "^2.7.0"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
|
||||
+1
-1
@@ -12,5 +12,5 @@
|
||||
"reportMissingImports": true,
|
||||
"reportMissingTypeStubs": false,
|
||||
|
||||
"pythonVersion": "3.7.4"
|
||||
"pythonVersion": "3.9"
|
||||
}
|
||||
@@ -26,18 +26,39 @@ Set up your SSH key authentication in GitLab Profile Settings. Then clone the re
|
||||
git clone git@gitlab.com:sahkoinsinoorikilta/vtmk/web2.0-backend.git
|
||||
cd web2.0-backend
|
||||
git checkout develop
|
||||
cp scripts/git/pre-push .git/hooks/pre-push # install a script to test code before committing
|
||||
```
|
||||
|
||||
## Windows install instructions
|
||||
## Development
|
||||
|
||||
See [Windows install instructions](./windows_install.md)
|
||||
### Poetry
|
||||
|
||||
## Linux/Mac install instructions
|
||||
For depedencies and virtual environment, we use [poetry](https://python-poetry.org/). The easiest integration with VSCode is to have poetry install virtual environment in project folder, configured with
|
||||
|
||||
See [Linux/Mac install instructions](./linux_install.md)
|
||||
```bash
|
||||
poetry config virtualenvs.in-project true
|
||||
```
|
||||
|
||||
## Initializing data
|
||||
#### CMDs
|
||||
|
||||
Install dependencies
|
||||
|
||||
```bash
|
||||
poetry install
|
||||
```
|
||||
|
||||
Activate virtual environment in shell
|
||||
|
||||
```bash
|
||||
poetry shell
|
||||
```
|
||||
|
||||
### npm scripts
|
||||
|
||||
We use Node.js for few development tasks, like linting. Easiest way to install Node is [nvm](https://github.com/nvm-sh/nvm).
|
||||
|
||||
TODO: List scripts
|
||||
|
||||
### Initializing data
|
||||
|
||||
Run the following `manage.py` commands. Do not run these in production without thinking!
|
||||
|
||||
@@ -47,9 +68,7 @@ python manage.py initialize # creates user groups
|
||||
python manage.py createdummydata # creates dummy members to the member register
|
||||
```
|
||||
|
||||
## Running
|
||||
|
||||
### Use runserver command
|
||||
### Running
|
||||
|
||||
```bash
|
||||
python manage.py runserver 0.0.0.0:8000
|
||||
@@ -57,23 +76,11 @@ python manage.py runserver 0.0.0.0:8000
|
||||
|
||||
Using address `0.0.0.0` will bind to all IP addresses. Using `localhost` will only bind to your machine.
|
||||
|
||||
### Visit the page
|
||||
#### Visit the page
|
||||
|
||||
Visit [https://localhost:8000](https://localhost:8000) in your browser!
|
||||
|
||||
## Running in production
|
||||
|
||||
Run the project in production with gunicorn. Refer to [this page](https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-16-04) for instructions.
|
||||
|
||||
Install production dependencies.
|
||||
|
||||
```bash
|
||||
pip install -r requirements.production.txt
|
||||
```
|
||||
|
||||
## Development workflow
|
||||
|
||||
Do not use `rebase` when pulling or merging changes. Rebasing transforms the commit history and makes it appear more linear. This is a plus e.g. when working with a few people, but in this project traditional merging is recommended for clarity.
|
||||
### Development workflow
|
||||
|
||||
When you start working on a feature, create a feature branch for your changes. These feature branches should be prefixed with `feature`.
|
||||
|
||||
@@ -110,13 +117,17 @@ Use an editor with linting capabilities to write pretty code that passes linting
|
||||
Run unit tests with
|
||||
|
||||
```bash
|
||||
python manage.py test -v 2
|
||||
python manage.py test
|
||||
```
|
||||
|
||||
Due to the mostly static nature of the project, most elements are difficult to properly unit test. If you write code with actual logic, make sure to write at least one unit or integration test that tests your code's core functionality.
|
||||
|
||||
Tests are located in `tests.py` under every subproject.
|
||||
|
||||
### GitLab CI
|
||||
## Production
|
||||
|
||||
Project is run in production with Docker. See `Dockerfile` for details.
|
||||
|
||||
## GitLab CI
|
||||
|
||||
All pushed changes go through the GitLab Continuous Integration, which consists of automated unit testing and linting. Make sure your changes pass both before merging to `develop` or `master`.
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
uWSGI==2.0.18
|
||||
gunicorn==19.9.0
|
||||
@@ -1,44 +0,0 @@
|
||||
backports.shutil-get-terminal-size==1.0.0
|
||||
decorator==4.0.9
|
||||
Django==2.1.5
|
||||
ipython==4.2.0
|
||||
ipython-genutils==0.1.0
|
||||
pexpect==4.1.0
|
||||
pickleshare==0.7.2
|
||||
ptyprocess==0.5.1
|
||||
pytz==2016.4
|
||||
simplegeneric==0.8.1
|
||||
traitlets==4.2.1
|
||||
Pillow==7.2.0
|
||||
requests==2.11.1
|
||||
django-nocaptcha-recaptcha==0.0.19
|
||||
django-cors-headers==2.0.1
|
||||
djangorestframework==3.8.2
|
||||
PyJWT==1.6.4
|
||||
djangorestframework-jwt==1.11.0
|
||||
coverage==4.3.4
|
||||
django-nose==1.4.5
|
||||
nose-exclude==0.5.0
|
||||
psycopg2-binary==2.8.4
|
||||
django-bootstrap3==11.1.0
|
||||
django-tables2==1.6.1
|
||||
pycodestyle==2.6.0
|
||||
dealer==2.0.5
|
||||
django-modeltranslation==0.13b1
|
||||
django-auditlog==0.4.5
|
||||
phonenumbers==8.11.4
|
||||
django-phonenumber-field[phonenumbers]==4.0.0
|
||||
django-autocomplete-light==3.4.1
|
||||
six==1.12.0
|
||||
django-suit==0.2.26
|
||||
telepot==12.3
|
||||
pyexcel==0.5.14
|
||||
pyexcel-xlsx==0.5.8
|
||||
django-import-export==0.7.0
|
||||
openpyxl==2.6.4
|
||||
django-app-namespace-template-loader==0.4.1
|
||||
django-filter==2.0.0
|
||||
whitenoise==4.1.4
|
||||
jsonschema==3.2.0
|
||||
mailjet-rest==1.3.3
|
||||
markdown==3.2.2
|
||||
@@ -1,68 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "SIK WEB 2.0"
|
||||
echo "This script will set up the environment for this project."
|
||||
echo "========================================================="
|
||||
echo "Dependencies: python3.7"
|
||||
|
||||
INTERACTIVE="true"
|
||||
USE_NPM="true"
|
||||
if [[ $* == *--no-input* ]]
|
||||
then
|
||||
INTERACTIVE="false"
|
||||
fi
|
||||
if [[ $* == *--no-npm* ]]
|
||||
then
|
||||
USE_NPM="false"
|
||||
fi
|
||||
|
||||
$INTERACTIVE || (echo "Running in non-interactive mode." && env)
|
||||
|
||||
$INTERACTIVE && read -p "Are these programs installed? [y/n]" -n 1 -r || REPLY="y"
|
||||
echo ""
|
||||
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]
|
||||
then
|
||||
echo "Please install the dependencies. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
$INTERACTIVE && read -p "Is virtualenv activated? [y/n]" -n 1 -r || REPLY="y"
|
||||
echo ""
|
||||
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]
|
||||
then
|
||||
echo "Please activate virtualenv first. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
$INTERACTIVE && read -p "Copy pre-push hook to .git/hooks? (recommended) [y/n]" -n 1 -r || REPLY="y"
|
||||
echo ""
|
||||
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]
|
||||
then
|
||||
cp "$PWD/scripts/git/pre-push" "$PWD/.git/hooks/pre-push"
|
||||
fi
|
||||
|
||||
|
||||
$INTERACTIVE && read -p "Start setup? [y/n]" -n 1 -r || REPLY="y"
|
||||
echo ""
|
||||
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]
|
||||
then
|
||||
echo "Exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
set -e
|
||||
set -x
|
||||
pip install -r requirements.txt
|
||||
pip install -r requirements.production.txt
|
||||
$USE_NPM && npm install
|
||||
python manage.py migrate
|
||||
python manage.py createdefaultadmin
|
||||
set +e
|
||||
set +x
|
||||
|
||||
echo "Done."
|
||||
echo "Run 'python manage.py runserver 0.0.0.0:8000' to start the development server!"
|
||||
+4
-4
@@ -203,10 +203,10 @@ REST_FRAMEWORK = {
|
||||
}
|
||||
|
||||
# Email settings (tested working with gmail)
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
||||
EMAIL_USE_TLS = True
|
||||
EMAIL_HOST = 'smtp.gmail.com'
|
||||
EMAIL_PORT = 587
|
||||
# EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
||||
# EMAIL_USE_TLS = True
|
||||
# EMAIL_HOST = 'smtp.gmail.com'
|
||||
# EMAIL_PORT = 587
|
||||
|
||||
|
||||
# Internationalization
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ GOOGLE_RECAPTCHA_SECRET_KEY = os.getenv("GOOGLE_RECAPTCHA_SECRET_KEY", "YOUR-PRI
|
||||
|
||||
# Email settings (more settings in base.py)
|
||||
EMAIL_API_KEY = os.getenv('EMAIL_API_KEY', '')
|
||||
EMAIL_API_SECRET = os.getenv('EMAIL_API_SECRET', '')
|
||||
# EMAIL_API_SECRET = os.getenv('EMAIL_API_SECRET', '')
|
||||
DEFAULT_EMAIL_FROM = 'SIK'
|
||||
DEFAULT_EMAIL_FROM_ADDR = 'noreply@sahkoinsinoorikilta.fi'
|
||||
ENABLE_AUTOMATIC_EMAILS = True
|
||||
|
||||
@@ -23,10 +23,6 @@ from django.conf import settings
|
||||
from django.contrib.staticfiles import views as static_views
|
||||
from django.views.generic.base import RedirectView
|
||||
|
||||
import webapp.urls
|
||||
import infoscreen.urls
|
||||
import members.urls
|
||||
|
||||
favicon_view = RedirectView.as_view(
|
||||
url='static/img/favicon.png', permanent=True)
|
||||
|
||||
|
||||
@@ -27,19 +27,15 @@ services:
|
||||
- FRONTEND_URL=dev.sahkoinsinoorikilta.fi
|
||||
- DEBUG=True
|
||||
- EMAIL_API_KEY_FILE=/run/secrets/DJANGO_EMAIL_API_KEY
|
||||
- EMAIL_API_SECRET_FILE=/run/secrets/DJANGO_EMAIL_API_SECRET
|
||||
- DB_HOST=db
|
||||
- DB_PORT=5432
|
||||
|
||||
secrets:
|
||||
- DJANGO_EMAIL_API_KEY
|
||||
- DJANGO_EMAIL_API_SECRET
|
||||
|
||||
secrets:
|
||||
DJANGO_EMAIL_API_KEY:
|
||||
external: true
|
||||
DJANGO_EMAIL_API_SECRET:
|
||||
external: true
|
||||
|
||||
volumes:
|
||||
dbdata:
|
||||
|
||||
@@ -47,7 +47,6 @@ services:
|
||||
- DB_HOST=db
|
||||
- DB_PORT=5432
|
||||
- EMAIL_API_KEY_FILE=/run/secrets/BACKEND_EMAIL_API_KEY
|
||||
- EMAIL_API_SECRET_FILE=/run/secrets/BACKEND_EMAIL_API_SECRET
|
||||
|
||||
secrets:
|
||||
- BACKEND_SECRET_KEY
|
||||
@@ -55,7 +54,6 @@ services:
|
||||
- BACKEND_DB_USER
|
||||
- BACKEND_DB_PASSWD
|
||||
- BACKEND_EMAIL_API_KEY
|
||||
- BACKEND_EMAIL_API_SECRET
|
||||
secrets:
|
||||
BACKEND_SECRET_KEY:
|
||||
external: true
|
||||
@@ -69,8 +67,6 @@ secrets:
|
||||
external: true
|
||||
BACKEND_EMAIL_API_KEY:
|
||||
external: true
|
||||
BACKEND_EMAIL_API_SECRET:
|
||||
external: true
|
||||
|
||||
volumes:
|
||||
dbdata:
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
|
||||
<a href={{ url }}>{{url}}</a>
|
||||
|
||||
<p>Hädässä ota yhteyttä sik-vtmk@list.ayy.fi</p>
|
||||
<p>Hädässä ota yhteyttä admin@sahkoinsinoorikilta.fi</p>
|
||||
|
||||
@@ -83,7 +83,7 @@ class SignupTestCase(APITestCase):
|
||||
def test_delete_signup_token(self):
|
||||
pass
|
||||
|
||||
# TODO: Use some mocking library and check that mailjet is actually called
|
||||
# TODO: Use some mocking library and check that sendgrid is actually called
|
||||
def test_signupee_sendemail(self):
|
||||
form = self.signupForm
|
||||
emailURL = f"/api/signupForm/{form.id}/sendemail/"
|
||||
|
||||
+20
-35
@@ -1,18 +1,16 @@
|
||||
"""Webapp utils."""
|
||||
|
||||
from django.utils import timezone
|
||||
# from django.core.mail import send_mail
|
||||
import os
|
||||
from mailjet_rest import Client
|
||||
import sendgrid
|
||||
from sendgrid.helpers.mail import *
|
||||
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from django.conf import settings
|
||||
from django.template.loader import render_to_string
|
||||
from django.core.files.base import ContentFile
|
||||
import base64
|
||||
import uuid
|
||||
from sikweb.settings import FRONTEND_URL, URL, EMAIL_API_KEY, EMAIL_API_SECRET, DEFAULT_EMAIL_FROM, DEFAULT_EMAIL_FROM_ADDR, ENABLE_AUTOMATIC_EMAILS
|
||||
from sikweb.settings import FRONTEND_URL, EMAIL_API_KEY, DEFAULT_EMAIL_FROM_ADDR, ENABLE_AUTOMATIC_EMAILS
|
||||
import imghdr
|
||||
import markdown
|
||||
|
||||
@@ -60,37 +58,24 @@ def send_email(to, subject, body, html=False):
|
||||
logging.debug(f"subject: {subject}")
|
||||
logging.debug(f"body: {body}")
|
||||
return
|
||||
|
||||
from_email = Email(DEFAULT_EMAIL_FROM_ADDR)
|
||||
to_email = To(to)
|
||||
sub = Subject(subject)
|
||||
|
||||
if (html):
|
||||
content = HtmlContent(body)
|
||||
else:
|
||||
content = PlainTextContent(body)
|
||||
|
||||
mail = Mail(from_email, to_email, sub, content)
|
||||
|
||||
try:
|
||||
mailjet = Client(auth=(EMAIL_API_KEY, EMAIL_API_SECRET), version='v3.1')
|
||||
sg = sendgrid.SendGridAPIClient(EMAIL_API_KEY)
|
||||
response = sg.client.mail.send.post(request_body=mail.get())
|
||||
|
||||
data = {
|
||||
'Messages': [
|
||||
{
|
||||
"From": {
|
||||
"Email": DEFAULT_EMAIL_FROM_ADDR,
|
||||
"Name": DEFAULT_EMAIL_FROM
|
||||
},
|
||||
"To": [
|
||||
{
|
||||
"Email": to,
|
||||
"Name": "You"
|
||||
}
|
||||
],
|
||||
"Subject": subject
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
if (html):
|
||||
data["Messages"][0]["HTMLPart"] = body
|
||||
else:
|
||||
data["Messages"][0]["TextPart"] = body
|
||||
|
||||
success = mailjet.send.create(data=data)
|
||||
|
||||
# For some reason returns 200 OK instead of 201 Created...
|
||||
if success.status_code != 200:
|
||||
raise Exception(f'Failed to send email: {success.json()}')
|
||||
if response.status_code != 202:
|
||||
raise Exception(f'Failed to send email: {response.body}')
|
||||
|
||||
except Exception as ex:
|
||||
logging.exception('Failed to send email.')
|
||||
@@ -109,4 +94,4 @@ def send_signup_email(to, subject, id, uuid, content):
|
||||
|
||||
def admin_send_email_signupees(list, subject, content):
|
||||
for to in list:
|
||||
send_email(to, subject, markdown.markdown(content), True)
|
||||
send_email(to.email, subject, markdown.markdown(content), True)
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
# Windows installation instructions
|
||||
|
||||
## Install dependencies
|
||||
|
||||
### Install python3
|
||||
|
||||
Visit [The python website](https://www.python.org/downloads/windows/) to install the latest version of python3.
|
||||
|
||||
Make sure to add the python binary directory to PATH. For instructions how to do this, refer to [this Stackoverflow answer](https://superuser.com/questions/143119/how-to-add-python-to-the-windows-path).
|
||||
|
||||
### Install virtualenv with pip
|
||||
|
||||
Run the following command to install `virtualenv`.
|
||||
|
||||
```cmd
|
||||
python -m pip install virtualenv
|
||||
```
|
||||
|
||||
Setup a virtual python environment.
|
||||
|
||||
```cmd
|
||||
python -m virtualenv ../virtualenv.sikweb
|
||||
```
|
||||
|
||||
## Activate virtualenv and install requirements
|
||||
|
||||
Activate `virtualenv` (note that this has to be active at all times).
|
||||
|
||||
```cmd
|
||||
source ../virtualenv.sikweb/Scripts/activate
|
||||
```
|
||||
|
||||
Run the following command to install python packages.
|
||||
|
||||
```cmd
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## Run migrations
|
||||
|
||||
Run
|
||||
|
||||
```cmd
|
||||
python manage.py migrate
|
||||
```
|
||||
|
||||
## Install npm for linting javascript
|
||||
|
||||
Follow the instructions on [the npm website](https://www.npmjs.com/package/npm).
|
||||
|
||||
## Set up database
|
||||
|
||||
By default Django uses SQLite, which doesn't need any configuration. If you need PostgreSQL instead, refer to [their website](https://www.postgresql.org/download/windows/).
|
||||
|
||||
## Done
|
||||
Reference in New Issue
Block a user