Merge branch 'develop' into 'master'
Update PG, Hackathon commits See merge request sahkoinsinoorikilta/vtmk/web2.0-backend!10
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
HOST=web.sik.party
|
||||
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
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
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
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
*.swp
|
||||
sikweb/settings.py
|
||||
.env
|
||||
*~
|
||||
*.pyc
|
||||
*.sqlite3
|
||||
@@ -10,7 +10,7 @@ members/logs/*
|
||||
logs/
|
||||
/media/
|
||||
node_modules/
|
||||
/.coverage
|
||||
.coverage
|
||||
db.sqlite3
|
||||
requirements_henu.txt
|
||||
/collected_static/
|
||||
|
||||
+6
-39
@@ -8,17 +8,16 @@ test:
|
||||
image: python:3.7
|
||||
stage: test
|
||||
services:
|
||||
- postgres:latest
|
||||
- postgres:12
|
||||
variables:
|
||||
POSTGRES_DB: ci
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB"
|
||||
DB_HOST: postgres
|
||||
script:
|
||||
- python -V
|
||||
- pip install -r requirements.txt
|
||||
- cp sikweb/settings-sample.py sikweb/default_settings.py
|
||||
- cp sikweb/.ci-settings.py sikweb/settings.py
|
||||
- python manage.py migrate --noinput
|
||||
- python manage.py createdefaultadmin
|
||||
- python manage.py test
|
||||
@@ -46,31 +45,18 @@ remark:
|
||||
script:
|
||||
- npm run remark
|
||||
|
||||
# TODO: remove
|
||||
publish_dev:
|
||||
stage: publish
|
||||
image: docker:stable
|
||||
services:
|
||||
- docker:stable-dind
|
||||
only:
|
||||
- develop
|
||||
script:
|
||||
- docker info
|
||||
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
|
||||
- docker build . -t "$IMAGE_NAME_DEV"
|
||||
- docker push "$IMAGE_NAME_DEV"
|
||||
|
||||
publish:
|
||||
stage: publish
|
||||
image: docker:stable
|
||||
services:
|
||||
- docker:stable-dind
|
||||
only:
|
||||
- develop
|
||||
- master
|
||||
script:
|
||||
- docker info
|
||||
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
|
||||
- docker build . -f Dockerfile.prod -t "$IMAGE_NAME"
|
||||
- docker build . -t "$IMAGE_NAME"
|
||||
- docker push "$IMAGE_NAME"
|
||||
|
||||
deploy_dev:
|
||||
@@ -91,29 +77,10 @@ deploy_dev:
|
||||
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
|
||||
script:
|
||||
- scp docker-compose.yml $DEV_SSH_USER@$DEV_SSH_HOST:~/deployment/docker-compose.yml
|
||||
- scp .env.dev $DEV_SSH_USER@$DEV_SSH_HOST:~/deployment/.env
|
||||
- scp .deploy_dev.sh $DEV_SSH_USER@$DEV_SSH_HOST:~/deployment/deploy_dev.sh
|
||||
- ssh $DEV_SSH_USER@$DEV_SSH_HOST "docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY"
|
||||
- ssh $DEV_SSH_USER@$DEV_SSH_HOST "bash ~/deployment/deploy_dev.sh \"$IMAGE_NAME_DEV\""
|
||||
|
||||
# deploy_production:
|
||||
# stage: deploy
|
||||
# image: alpine:latest
|
||||
# environment:
|
||||
# name: production
|
||||
# url: https://sika.sahkoinsinoorikilta.fi
|
||||
# when: manual
|
||||
# only:
|
||||
# - master
|
||||
# before_script:
|
||||
# - pwd
|
||||
# - apk add --update openssh
|
||||
# - ssh -V
|
||||
# - mkdir -p ~/.ssh
|
||||
# - echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
|
||||
# - chmod 600 ~/.ssh/id_rsa
|
||||
# - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config
|
||||
# script:
|
||||
# - ssh $PROD_SSH_USER@$PROD_SSH_HOST "zsh ~/deploy.sh"
|
||||
- ssh $DEV_SSH_USER@$DEV_SSH_HOST "bash ~/deployment/deploy_dev.sh \"$IMAGE_NAME\""
|
||||
|
||||
deploy_production:
|
||||
stage: deploy
|
||||
|
||||
+19
-7
@@ -1,8 +1,20 @@
|
||||
FROM python:3.7
|
||||
FROM python:3.7-alpine
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
ENV IS_DOCKER 1
|
||||
RUN mkdir /code
|
||||
WORKDIR /code
|
||||
ADD requirements.txt /code/
|
||||
RUN env
|
||||
ADD . /code/
|
||||
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
|
||||
|
||||
RUN python manage.py collectstatic --noinput
|
||||
|
||||
CMD ["sh", "-c", "./production_entrypoint.sh"]
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
FROM python:3.7-alpine
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
ENV IS_DOCKER 0
|
||||
WORKDIR /app
|
||||
COPY requirements.txt ./
|
||||
COPY requirements.production.txt ./
|
||||
COPY . ./
|
||||
COPY sikweb/settings-sample-prod.py sikweb/settings.py
|
||||
|
||||
# uWSGI, gunicorn etc.
|
||||
RUN apk add --no-cache --virtual .build-deps python3-dev build-base linux-headers pcre-dev openssl \
|
||||
# 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 \
|
||||
&& apk del .build-deps
|
||||
|
||||
RUN python manage.py collectstatic --noinput
|
||||
|
||||
# run migrate
|
||||
# python manage.py migrate --noinput
|
||||
|
||||
ENTRYPOINT ["sh", "-c", "./production_entrypoint.sh"]
|
||||
+12
-3
@@ -2,12 +2,21 @@ version: '3'
|
||||
|
||||
services:
|
||||
db:
|
||||
image: postgres
|
||||
image: postgres:12
|
||||
volumes:
|
||||
- dbdata:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "5432:5432"
|
||||
web:
|
||||
build: .
|
||||
image: registry.gitlab.com/sahkoinsinoorikilta/vtmk/web2.0-backend:dev
|
||||
command: ["bash", "-c", "cd /code && ./wait-for-it.sh db:5432 -- bash setup.sh --no-input --no-npm && python manage.py runserver 0.0.0.0:8000"]
|
||||
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:
|
||||
- "8000:8000"
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
volumes:
|
||||
dbdata:
|
||||
|
||||
Binary file not shown.
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-09-16 19:33+0300\n"
|
||||
"POT-Creation-Date: 2019-10-10 18:14+0300\n"
|
||||
"PO-Revision-Date: 2017-11-02 23:09+0200\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
@@ -37,7 +37,7 @@ msgstr "Sössö articles"
|
||||
msgid "Today's lunch"
|
||||
msgstr ""
|
||||
|
||||
#: infoscreen/models.py:212 webapp/models.py:74
|
||||
#: infoscreen/models.py:212 webapp/models.py:75
|
||||
msgid "Events"
|
||||
msgstr "Events"
|
||||
|
||||
@@ -113,7 +113,7 @@ msgid "Delete"
|
||||
msgstr "Delete"
|
||||
|
||||
#: infoscreen/templates/tabs/add_remove.html:23 kaehmy/models.py:56
|
||||
#: kaehmy/templates/list.html:36 webapp/models.py:125 webapp/models.py:154
|
||||
#: kaehmy/templates/list.html:36 webapp/models.py:126 webapp/models.py:155
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
@@ -263,7 +263,7 @@ msgstr ""
|
||||
msgid "Category"
|
||||
msgstr ""
|
||||
|
||||
#: kaehmy/models.py:39 webapp/models.py:136
|
||||
#: kaehmy/models.py:39 webapp/models.py:137
|
||||
msgid "Description"
|
||||
msgstr "Description"
|
||||
|
||||
@@ -311,7 +311,7 @@ msgstr "Kaehmy application"
|
||||
msgid "Kaehmylomakkeet"
|
||||
msgstr "Kaehmy applications"
|
||||
|
||||
#: kaehmy/models.py:98 webapp/models.py:189
|
||||
#: kaehmy/models.py:98 webapp/models.py:221
|
||||
msgid "Phone number"
|
||||
msgstr ""
|
||||
|
||||
@@ -327,7 +327,7 @@ msgstr ""
|
||||
msgid "Custom role name"
|
||||
msgstr ""
|
||||
|
||||
#: kaehmy/models.py:104 webapp/models.py:126
|
||||
#: kaehmy/models.py:104 webapp/models.py:127
|
||||
msgid "Board member"
|
||||
msgstr "Board member"
|
||||
|
||||
@@ -351,7 +351,7 @@ msgstr ""
|
||||
msgid "Telegram channels"
|
||||
msgstr ""
|
||||
|
||||
#: kaehmy/tables.py:13 webapp/models.py:173
|
||||
#: kaehmy/tables.py:13 webapp/models.py:174
|
||||
msgid "Roles"
|
||||
msgstr ""
|
||||
|
||||
@@ -392,7 +392,7 @@ msgid ""
|
||||
" Koska lista ei ole koskaan täydellinen, voit myös ehdottaa ihan "
|
||||
"uutta toimenkuvaa.\n"
|
||||
" Jos sinulla on kysyttävää mistä tahansa virasta, kannattaa "
|
||||
"konsultoida <a href=\"/static/other/kahmyopas.pdf\">kaehmyopasta</a> \n"
|
||||
"konsultoida <a href=\"/static/other/kahmyopas.pdf\">kaehmyopasta</a>\n"
|
||||
" tai olla yhteydessä kyseistä virkaa tänä vuonna toimittavaan "
|
||||
"henkilöön."
|
||||
msgstr ""
|
||||
@@ -406,7 +406,7 @@ msgstr ""
|
||||
|
||||
#: kaehmy/templates/kaehmy.html:23
|
||||
msgid ""
|
||||
"Muista, että kaehmyn lähettäminen on kiinnostuksen ilmaus \n"
|
||||
"Muista, että kaehmyn lähettäminen on kiinnostuksen ilmaus\n"
|
||||
" eikä siis missään nimessä sitova ilmoittautumien mihinkään "
|
||||
"tehtävään!"
|
||||
msgstr ""
|
||||
@@ -418,24 +418,27 @@ msgid "Päivämääriä & deadlineja"
|
||||
msgstr "Dates and deadlines"
|
||||
|
||||
#: kaehmy/templates/kaehmy.html:28
|
||||
msgid "Kiltailta"
|
||||
msgstr "Guild night"
|
||||
|
||||
#: kaehmy/templates/kaehmy.html:29
|
||||
msgid "Hallitustyrkkypaneeli (haku hallitukseen olisi hyvä tehdä ennen tätä!)"
|
||||
msgstr "Board panel discussion (applications to the board before this date!)"
|
||||
|
||||
#: kaehmy/templates/kaehmy.html:29
|
||||
#: kaehmy/templates/kaehmy.html:30
|
||||
msgid "Vaalikokous, osa 1 (puheenjohtajan valinta)"
|
||||
msgstr "Election meeting, part 1 (chairman election)"
|
||||
|
||||
#: kaehmy/templates/kaehmy.html:30
|
||||
msgid "Kiltailta"
|
||||
msgstr "Guild night"
|
||||
|
||||
#: kaehmy/templates/kaehmy.html:31
|
||||
msgid "Vaalikokous, osa 2 (hallituksen valinta)"
|
||||
msgstr "Election meeting, part 2 (board election)"
|
||||
|
||||
#: kaehmy/templates/kaehmy.html:32
|
||||
msgid "Haku toimariksi olisi hyvä tehdä ennen tätä!"
|
||||
msgstr "Deadline to apply as a non-board official!"
|
||||
msgid ""
|
||||
"Infoilta toimarihakijoille (haku toimariksi olisi hyvä tehdä ennen tätä)"
|
||||
msgstr ""
|
||||
"Information evening for applicants (applications to official roles before "
|
||||
"this date!)"
|
||||
|
||||
#: kaehmy/templates/kaehmy.html:33
|
||||
msgid "Vaalikokous, osa 3 (toimarien valinta)"
|
||||
@@ -524,11 +527,11 @@ msgstr "I'm a member of AYY"
|
||||
msgid "I want to receive a weekly newsletter"
|
||||
msgstr "I want to receive a weekly newsletter"
|
||||
|
||||
#: members/models.py:13
|
||||
#: members/models.py:13 webapp/models.py:218
|
||||
msgid "First name"
|
||||
msgstr "First name"
|
||||
|
||||
#: members/models.py:14
|
||||
#: members/models.py:14 webapp/models.py:219
|
||||
msgid "Last name"
|
||||
msgstr "Last name"
|
||||
|
||||
@@ -913,11 +916,11 @@ msgstr "Payments in register:"
|
||||
msgid "Language"
|
||||
msgstr "Language"
|
||||
|
||||
#: members/templates/settings.html:20 sikweb/base.py:255
|
||||
#: members/templates/settings.html:20 sikweb/base.py:256
|
||||
msgid "Finnish"
|
||||
msgstr "Finnish"
|
||||
|
||||
#: members/templates/settings.html:21 sikweb/base.py:256
|
||||
#: members/templates/settings.html:21 sikweb/base.py:257
|
||||
msgid "English"
|
||||
msgstr "English"
|
||||
|
||||
@@ -1098,7 +1101,7 @@ msgstr ""
|
||||
msgid "Challenge"
|
||||
msgstr "Challenge"
|
||||
|
||||
#: ohlhafv/views.py:43
|
||||
#: ohlhafv/views.py:44
|
||||
msgid "Sinut on haastettu Øhlhäfviin!"
|
||||
msgstr "You have been challenged at Ohlhafv!"
|
||||
|
||||
@@ -1111,114 +1114,134 @@ msgstr "Go"
|
||||
msgid "Aalto-yliopiston Sähköinsinöörikilta ry"
|
||||
msgstr "Aalto-yliopiston Sähköinsinöörikilta ry"
|
||||
|
||||
#: webapp/models.py:17
|
||||
#: webapp/models.py:18
|
||||
msgid "Webapp"
|
||||
msgstr "Webapp"
|
||||
|
||||
#: webapp/models.py:28
|
||||
#: webapp/models.py:29
|
||||
msgid "Tag"
|
||||
msgstr "Tag"
|
||||
|
||||
#: webapp/models.py:29
|
||||
#: webapp/models.py:30
|
||||
msgid "Tags"
|
||||
msgstr "Tags"
|
||||
|
||||
#: webapp/models.py:32
|
||||
#: webapp/models.py:33
|
||||
msgid "Tag: {}"
|
||||
msgstr "Tag: {}"
|
||||
|
||||
#: webapp/models.py:53
|
||||
#: webapp/models.py:54
|
||||
msgid "Feed: {}"
|
||||
msgstr "Feed: {}"
|
||||
|
||||
#: webapp/models.py:56
|
||||
#: webapp/models.py:57
|
||||
msgid "Feed"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:57
|
||||
#: webapp/models.py:58
|
||||
msgid "Feeds"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:70
|
||||
#: webapp/models.py:71
|
||||
msgid "Event: {}"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:73
|
||||
#: webapp/models.py:74
|
||||
msgid "Event"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:84
|
||||
#: webapp/models.py:85
|
||||
msgid "Template questions: {}"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:87
|
||||
#: webapp/models.py:88
|
||||
msgid "Template question"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:88
|
||||
#: webapp/models.py:89
|
||||
msgid "Template questions"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:102
|
||||
#: webapp/models.py:103
|
||||
msgid "#{} {}"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:105
|
||||
#: webapp/models.py:106
|
||||
msgid "Signup form"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:106
|
||||
#: webapp/models.py:107
|
||||
msgid "Signup forms"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:115
|
||||
#: webapp/models.py:116
|
||||
msgid "Sign-ups: {}"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:118
|
||||
#: webapp/models.py:119
|
||||
msgid "Sign-up"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:119
|
||||
#: webapp/models.py:120
|
||||
msgid "Sign-ups"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:130
|
||||
#: webapp/models.py:131
|
||||
msgid "board member"
|
||||
msgstr "board member"
|
||||
|
||||
#: webapp/models.py:148
|
||||
#: webapp/models.py:149
|
||||
msgid "Committee"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:149
|
||||
#: webapp/models.py:150
|
||||
msgid "Committees"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:152
|
||||
#: webapp/models.py:153
|
||||
msgid "Committee: {}"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:172
|
||||
#: webapp/models.py:173
|
||||
msgid "Role"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:175
|
||||
#: webapp/models.py:179
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:179
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:190
|
||||
msgid "Occupation"
|
||||
msgstr "Occupation"
|
||||
|
||||
#: webapp/models.py:191
|
||||
msgid "Occupations"
|
||||
msgstr "Occupations"
|
||||
|
||||
#: webapp/models.py:193
|
||||
msgid "Start date"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:176
|
||||
#: webapp/models.py:194
|
||||
msgid "End date"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:186
|
||||
#: webapp/models.py:213
|
||||
msgid "Official"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:187
|
||||
#: webapp/models.py:214
|
||||
msgid "Officials"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:220
|
||||
msgid "Email address"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/templates/contact.html:9 webapp/templates/navigation.html:20
|
||||
msgid "Contact"
|
||||
msgstr "Contact"
|
||||
@@ -1340,6 +1363,3 @@ msgstr "Corporate"
|
||||
|
||||
#~ msgid "Missing \"textfield\" POST request field"
|
||||
#~ msgstr "Missing \"textfield\" POST request field"
|
||||
|
||||
#~ msgid "Options"
|
||||
#~ msgstr "Options"
|
||||
|
||||
Binary file not shown.
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-09-16 19:33+0300\n"
|
||||
"POT-Creation-Date: 2019-10-10 18:14+0300\n"
|
||||
"PO-Revision-Date: 2017-11-02 23:04+0200\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
@@ -38,7 +38,7 @@ msgstr "Sössön artikkelit"
|
||||
msgid "Today's lunch"
|
||||
msgstr "Päivän lounas"
|
||||
|
||||
#: infoscreen/models.py:212 webapp/models.py:74
|
||||
#: infoscreen/models.py:212 webapp/models.py:75
|
||||
msgid "Events"
|
||||
msgstr "Tapahtumat"
|
||||
|
||||
@@ -114,7 +114,7 @@ msgid "Delete"
|
||||
msgstr "Poista"
|
||||
|
||||
#: infoscreen/templates/tabs/add_remove.html:23 kaehmy/models.py:56
|
||||
#: kaehmy/templates/list.html:36 webapp/models.py:125 webapp/models.py:154
|
||||
#: kaehmy/templates/list.html:36 webapp/models.py:126 webapp/models.py:155
|
||||
msgid "Name"
|
||||
msgstr "Nimi"
|
||||
|
||||
@@ -264,7 +264,7 @@ msgstr "Muut"
|
||||
msgid "Category"
|
||||
msgstr "Kategoria"
|
||||
|
||||
#: kaehmy/models.py:39 webapp/models.py:136
|
||||
#: kaehmy/models.py:39 webapp/models.py:137
|
||||
msgid "Description"
|
||||
msgstr "Kuvaus"
|
||||
|
||||
@@ -312,7 +312,7 @@ msgstr "Kaehmylomake"
|
||||
msgid "Kaehmylomakkeet"
|
||||
msgstr "Kaehmylomakkeet"
|
||||
|
||||
#: kaehmy/models.py:98 webapp/models.py:189
|
||||
#: kaehmy/models.py:98 webapp/models.py:221
|
||||
msgid "Phone number"
|
||||
msgstr "Puhelinnumero"
|
||||
|
||||
@@ -328,7 +328,7 @@ msgstr "Teksti"
|
||||
msgid "Custom role name"
|
||||
msgstr "Uusi virka"
|
||||
|
||||
#: kaehmy/models.py:104 webapp/models.py:126
|
||||
#: kaehmy/models.py:104 webapp/models.py:127
|
||||
msgid "Board member"
|
||||
msgstr "Hallituksen jäsen"
|
||||
|
||||
@@ -352,7 +352,7 @@ msgstr "Telegram-kanava"
|
||||
msgid "Telegram channels"
|
||||
msgstr "Telegram-kanavat"
|
||||
|
||||
#: kaehmy/tables.py:13 webapp/models.py:173
|
||||
#: kaehmy/tables.py:13 webapp/models.py:174
|
||||
msgid "Roles"
|
||||
msgstr "Roolit"
|
||||
|
||||
@@ -386,6 +386,17 @@ msgid "Copyright Aalto-yliopiston Sähköinsinöörikilta ry"
|
||||
msgstr "Copyright Aalto-yliopiston Sähköinsinöörikilta ry"
|
||||
|
||||
#: kaehmy/templates/kaehmy.html:16
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Kaehmykoneella voit ilmaista kiinnostuksesi toimia killassa ensi vuonna.\n"
|
||||
#| " Listassa on vastuualueittain sekä hallitus- että "
|
||||
#| "toimihenkilövirkoja.\n"
|
||||
#| " Koska lista ei ole koskaan täydellinen, voit myös ehdottaa "
|
||||
#| "ihan uutta toimenkuvaa.\n"
|
||||
#| " Jos sinulla on kysyttävää mistä tahansa virasta, kannattaa "
|
||||
#| "konsultoida <a href=\"/static/other/kahmyopas.pdf\">kaehmyopasta</a> \n"
|
||||
#| " tai olla yhteydessä kyseistä virkaa tänä vuonna toimittavaan "
|
||||
#| "henkilöön."
|
||||
msgid ""
|
||||
"Kaehmykoneella voit ilmaista kiinnostuksesi toimia killassa ensi vuonna.\n"
|
||||
" Listassa on vastuualueittain sekä hallitus- että "
|
||||
@@ -393,7 +404,7 @@ msgid ""
|
||||
" Koska lista ei ole koskaan täydellinen, voit myös ehdottaa ihan "
|
||||
"uutta toimenkuvaa.\n"
|
||||
" Jos sinulla on kysyttävää mistä tahansa virasta, kannattaa "
|
||||
"konsultoida <a href=\"/static/other/kahmyopas.pdf\">kaehmyopasta</a> \n"
|
||||
"konsultoida <a href=\"/static/other/kahmyopas.pdf\">kaehmyopasta</a>\n"
|
||||
" tai olla yhteydessä kyseistä virkaa tänä vuonna toimittavaan "
|
||||
"henkilöön."
|
||||
msgstr ""
|
||||
@@ -409,7 +420,7 @@ msgstr ""
|
||||
|
||||
#: kaehmy/templates/kaehmy.html:23
|
||||
msgid ""
|
||||
"Muista, että kaehmyn lähettäminen on kiinnostuksen ilmaus \n"
|
||||
"Muista, että kaehmyn lähettäminen on kiinnostuksen ilmaus\n"
|
||||
" eikä siis missään nimessä sitova ilmoittautumien mihinkään "
|
||||
"tehtävään!"
|
||||
msgstr ""
|
||||
@@ -422,23 +433,26 @@ msgid "Päivämääriä & deadlineja"
|
||||
msgstr "Päivämääriä & deadlineja"
|
||||
|
||||
#: kaehmy/templates/kaehmy.html:28
|
||||
msgid "Kiltailta"
|
||||
msgstr "Kiltailta"
|
||||
|
||||
#: kaehmy/templates/kaehmy.html:29
|
||||
msgid "Hallitustyrkkypaneeli (haku hallitukseen olisi hyvä tehdä ennen tätä!)"
|
||||
msgstr "Hallitustyrkkypaneeli (haku hallitukseen olisi hyvä tehdä ennen tätä!)"
|
||||
|
||||
#: kaehmy/templates/kaehmy.html:29
|
||||
#: kaehmy/templates/kaehmy.html:30
|
||||
msgid "Vaalikokous, osa 1 (puheenjohtajan valinta)"
|
||||
msgstr "Vaalikokous, osa 1 (puheenjohtajan valinta)"
|
||||
|
||||
#: kaehmy/templates/kaehmy.html:30
|
||||
msgid "Kiltailta"
|
||||
msgstr "Kiltailta"
|
||||
|
||||
#: kaehmy/templates/kaehmy.html:31
|
||||
msgid "Vaalikokous, osa 2 (hallituksen valinta)"
|
||||
msgstr "Vaalikokous, osa 2 (hallituksen valinta)"
|
||||
|
||||
#: kaehmy/templates/kaehmy.html:32
|
||||
msgid "Haku toimariksi olisi hyvä tehdä ennen tätä!"
|
||||
#, fuzzy
|
||||
#| msgid "Haku toimariksi olisi hyvä tehdä ennen tätä!"
|
||||
msgid ""
|
||||
"Infoilta toimarihakijoille (haku toimariksi olisi hyvä tehdä ennen tätä)"
|
||||
msgstr "Haku toimariksi olisi hyvä tehdä ennen tätä!"
|
||||
|
||||
#: kaehmy/templates/kaehmy.html:33
|
||||
@@ -522,11 +536,11 @@ msgstr "Olen AYY:n jäsen"
|
||||
msgid "I want to receive a weekly newsletter"
|
||||
msgstr "Haluan saada viikottaisen jäsentiedotteen"
|
||||
|
||||
#: members/models.py:13
|
||||
#: members/models.py:13 webapp/models.py:218
|
||||
msgid "First name"
|
||||
msgstr "Etunimi"
|
||||
|
||||
#: members/models.py:14
|
||||
#: members/models.py:14 webapp/models.py:219
|
||||
msgid "Last name"
|
||||
msgstr "Sukunimi"
|
||||
|
||||
@@ -767,10 +781,8 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: members/templates/email_application_submit.html:15
|
||||
#, fuzzy
|
||||
#| msgid "Muista myös maksaa jäsenmaksusi!"
|
||||
msgid "Muistathan maksaa jäsenmaksun! Alla maksutiedot"
|
||||
msgstr "Muista myös maksaa jäsenmaksusi!"
|
||||
msgstr "Muistathan maksaa jäsenmaksun! Alla maksutiedot"
|
||||
|
||||
#: members/templates/email_application_submit.html:17
|
||||
msgid "Saaja"
|
||||
@@ -903,11 +915,11 @@ msgstr "Maksutapahtumia:"
|
||||
msgid "Language"
|
||||
msgstr "Kieli"
|
||||
|
||||
#: members/templates/settings.html:20 sikweb/base.py:255
|
||||
#: members/templates/settings.html:20 sikweb/base.py:256
|
||||
msgid "Finnish"
|
||||
msgstr "suomi"
|
||||
|
||||
#: members/templates/settings.html:21 sikweb/base.py:256
|
||||
#: members/templates/settings.html:21 sikweb/base.py:257
|
||||
msgid "English"
|
||||
msgstr "englanti"
|
||||
|
||||
@@ -1088,7 +1100,7 @@ msgstr "Haasta kaverisi mittelöön!"
|
||||
msgid "Challenge"
|
||||
msgstr "Haasta"
|
||||
|
||||
#: ohlhafv/views.py:43
|
||||
#: ohlhafv/views.py:44
|
||||
msgid "Sinut on haastettu Øhlhäfviin!"
|
||||
msgstr ""
|
||||
|
||||
@@ -1101,114 +1113,134 @@ msgstr "Vaihda"
|
||||
msgid "Aalto-yliopiston Sähköinsinöörikilta ry"
|
||||
msgstr "Aalto-yliopiston Sähköinsinöörikilta ry"
|
||||
|
||||
#: webapp/models.py:17
|
||||
#: webapp/models.py:18
|
||||
msgid "Webapp"
|
||||
msgstr "Nettisivut"
|
||||
|
||||
#: webapp/models.py:28
|
||||
#: webapp/models.py:29
|
||||
msgid "Tag"
|
||||
msgstr "Tunniste"
|
||||
|
||||
#: webapp/models.py:29
|
||||
#: webapp/models.py:30
|
||||
msgid "Tags"
|
||||
msgstr "Tunnisteet"
|
||||
|
||||
#: webapp/models.py:32
|
||||
#: webapp/models.py:33
|
||||
msgid "Tag: {}"
|
||||
msgstr "Tunniste: {}"
|
||||
|
||||
#: webapp/models.py:53
|
||||
#: webapp/models.py:54
|
||||
msgid "Feed: {}"
|
||||
msgstr "Uutinen: {}"
|
||||
|
||||
#: webapp/models.py:56
|
||||
#: webapp/models.py:57
|
||||
msgid "Feed"
|
||||
msgstr "Uutinen"
|
||||
|
||||
#: webapp/models.py:57
|
||||
#: webapp/models.py:58
|
||||
msgid "Feeds"
|
||||
msgstr "Uutiset"
|
||||
|
||||
#: webapp/models.py:70
|
||||
#: webapp/models.py:71
|
||||
msgid "Event: {}"
|
||||
msgstr "Tapahtuma: {}"
|
||||
|
||||
#: webapp/models.py:73
|
||||
#: webapp/models.py:74
|
||||
msgid "Event"
|
||||
msgstr "Tapahtuma"
|
||||
|
||||
#: webapp/models.py:84
|
||||
#: webapp/models.py:85
|
||||
msgid "Template questions: {}"
|
||||
msgstr "Vakiokysymykset: {}"
|
||||
|
||||
#: webapp/models.py:87
|
||||
#: webapp/models.py:88
|
||||
msgid "Template question"
|
||||
msgstr "Vakiokysymys"
|
||||
|
||||
#: webapp/models.py:88
|
||||
#: webapp/models.py:89
|
||||
msgid "Template questions"
|
||||
msgstr "Vakiokysymykset"
|
||||
|
||||
#: webapp/models.py:102
|
||||
#: webapp/models.py:103
|
||||
msgid "#{} {}"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:105
|
||||
#: webapp/models.py:106
|
||||
msgid "Signup form"
|
||||
msgstr "Ilmoittautumislomake"
|
||||
|
||||
#: webapp/models.py:106
|
||||
#: webapp/models.py:107
|
||||
msgid "Signup forms"
|
||||
msgstr "Ilmoittautumislomakkeet"
|
||||
|
||||
#: webapp/models.py:115
|
||||
#: webapp/models.py:116
|
||||
msgid "Sign-ups: {}"
|
||||
msgstr "Ilmoittautumiset: {}"
|
||||
|
||||
#: webapp/models.py:118
|
||||
#: webapp/models.py:119
|
||||
msgid "Sign-up"
|
||||
msgstr "Ilmoittautuminen"
|
||||
|
||||
#: webapp/models.py:119
|
||||
#: webapp/models.py:120
|
||||
msgid "Sign-ups"
|
||||
msgstr "Ilmoittautumiset"
|
||||
|
||||
#: webapp/models.py:130
|
||||
#: webapp/models.py:131
|
||||
msgid "board member"
|
||||
msgstr "hallituksen jäsen"
|
||||
|
||||
#: webapp/models.py:148
|
||||
#: webapp/models.py:149
|
||||
msgid "Committee"
|
||||
msgstr "Toimikunta"
|
||||
|
||||
#: webapp/models.py:149
|
||||
#: webapp/models.py:150
|
||||
msgid "Committees"
|
||||
msgstr "Toimikunnat"
|
||||
|
||||
#: webapp/models.py:152
|
||||
#: webapp/models.py:153
|
||||
msgid "Committee: {}"
|
||||
msgstr "Toimikunta: {}"
|
||||
|
||||
#: webapp/models.py:172
|
||||
#: webapp/models.py:173
|
||||
msgid "Role"
|
||||
msgstr "Rooli"
|
||||
|
||||
#: webapp/models.py:175
|
||||
#: webapp/models.py:179
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:179
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/models.py:190
|
||||
msgid "Occupation"
|
||||
msgstr "Virka"
|
||||
|
||||
#: webapp/models.py:191
|
||||
msgid "Occupations"
|
||||
msgstr "Virat"
|
||||
|
||||
#: webapp/models.py:193
|
||||
msgid "Start date"
|
||||
msgstr "Alkupäivämäärä"
|
||||
|
||||
#: webapp/models.py:176
|
||||
#: webapp/models.py:194
|
||||
msgid "End date"
|
||||
msgstr "Loppupäivämäärä"
|
||||
|
||||
#: webapp/models.py:186
|
||||
#: webapp/models.py:213
|
||||
msgid "Official"
|
||||
msgstr "Toimihenkilö"
|
||||
|
||||
#: webapp/models.py:187
|
||||
#: webapp/models.py:214
|
||||
msgid "Officials"
|
||||
msgstr "Toimihenkilöt"
|
||||
|
||||
#: webapp/models.py:220
|
||||
msgid "Email address"
|
||||
msgstr ""
|
||||
|
||||
#: webapp/templates/contact.html:9 webapp/templates/navigation.html:20
|
||||
msgid "Contact"
|
||||
msgstr "Yhteystiedot"
|
||||
|
||||
@@ -35,5 +35,6 @@
|
||||
<body>
|
||||
{% block content %}
|
||||
{% endblock content %}
|
||||
{% include "webapp:footer.html" %}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Generated
+1121
-2622
File diff suppressed because it is too large
Load Diff
+3
-3
@@ -15,12 +15,12 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"eslint": "3.19.0",
|
||||
"remark-cli": "^4.0.0",
|
||||
"remark-preset-lint-recommended": "^3.0.1"
|
||||
"remark-cli": "7.0.0",
|
||||
"remark-preset-lint-recommended": "3.0.3"
|
||||
},
|
||||
"remarkConfig": {
|
||||
"plugins": [
|
||||
"remark-preset-lint-recommended"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
echo "SIK WEB 2.0"
|
||||
echo "This script will set up the environment for this project."
|
||||
echo "========================================================="
|
||||
echo "Dependencies: python>3.5"
|
||||
echo "Dependencies: python3.7"
|
||||
|
||||
INTERACTIVE="true"
|
||||
USE_NPM="true"
|
||||
@@ -36,14 +36,6 @@ then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
$INTERACTIVE && read -p "Copy settings from template? (recommended) [y/n]" -n 1 -r || REPLY="y"
|
||||
echo ""
|
||||
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]
|
||||
then
|
||||
cp "$PWD/sikweb/settings-sample.py" "$PWD/sikweb/settings.py"
|
||||
fi
|
||||
|
||||
$INTERACTIVE && read -p "Copy pre-push hook to .git/hooks? (recommended) [y/n]" -n 1 -r || REPLY="y"
|
||||
echo ""
|
||||
|
||||
@@ -65,6 +57,7 @@ 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
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
"""File containing CI settings."""
|
||||
|
||||
from sikweb.default_settings import *
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||
'NAME': 'ci',
|
||||
'USER': 'postgres',
|
||||
'PASSWORD': 'postgres',
|
||||
'HOST': 'postgres',
|
||||
'PORT': '5432',
|
||||
},
|
||||
}
|
||||
@@ -7,19 +7,12 @@ from django.utils.translation import ugettext_lazy as _
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
IS_DOCKER = bool(os.getenv('IS_DOCKER', None))
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
|
||||
|
||||
|
||||
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
|
||||
|
||||
if not IS_DOCKER:
|
||||
ALLOWED_HOSTS = []
|
||||
else:
|
||||
ALLOWED_HOSTS = ["*"]
|
||||
|
||||
# Logger level
|
||||
|
||||
LOGGERLEVEL = logging.DEBUG
|
||||
@@ -166,36 +159,6 @@ TEMPLATES = [
|
||||
|
||||
WSGI_APPLICATION = 'sikweb.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/1.9/ref/settings/#databases
|
||||
|
||||
if not IS_DOCKER:
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||
'NAME': 'sik',
|
||||
'USER': 'sik',
|
||||
'PASSWORD': 'password123',
|
||||
'HOST': 'localhost',
|
||||
'PORT': '5432',
|
||||
'TEST': {
|
||||
'NAME': 'sik_test',
|
||||
},
|
||||
},
|
||||
}
|
||||
else:
|
||||
logging.info('Using docker database configuration')
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||
'NAME': 'postgres',
|
||||
'USER': 'postgres',
|
||||
'PASSWORD': 'postgres',
|
||||
'HOST': 'db',
|
||||
'PORT': '5432',
|
||||
},
|
||||
}
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators
|
||||
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
|
||||
"""
|
||||
Django settings for sikweb project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 1.9.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.9/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/1.9/ref/settings/
|
||||
"""
|
||||
|
||||
from sikweb.base import *
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
# ALLOWED_HOSTS = ["*"]
|
||||
URL = "sika.sik.party"
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = '7p$85^4ibb^p4-=vs44b7!y0e-zemugze18@a#30&71=a8)dp('
|
||||
|
||||
# MQTT settings
|
||||
MQTT_SETTINGS = {
|
||||
'HOST': 'mqtt.sik.party',
|
||||
'PORT': 1883,
|
||||
'TOPICS': {
|
||||
'BREW_TIME': 'sik/kiltahuone/kahvivaaka/brewtime',
|
||||
'WEIGHT': 'sik/kiltahuone/kahvivaaka/weight',
|
||||
'BREWING': 'sik/kiltahuone/kahvivaaka/brewing',
|
||||
'CUPS': 'sik/kiltahuone/kahvivaaka/cups',
|
||||
}
|
||||
}
|
||||
|
||||
# ReCaptcha
|
||||
# http://www.yaconiello.com/blog/integrating-google-recaptcha-to-django/
|
||||
GOOGLE_RECAPTCHA_SITE_KEY = "YOUR-PUBLIC-KEY"
|
||||
GOOGLE_RECAPTCHA_SECRET_KEY = "YOUR-PRIVATE-KEY"
|
||||
|
||||
# Email settings (more settings in base.py)
|
||||
EMAIL_HOST_USER = '<gmailtunnarisi>@gmail.com'
|
||||
EMAIL_HOST_PASSWORD = '<gmail_passu>'
|
||||
DEFAULT_EMAIL_FROM = 'SIK Viestintä <sikviestinta@gmail.com>'
|
||||
ENABLE_AUTOMATIC_EMAILS = False
|
||||
|
||||
# Token for Telegram bot
|
||||
TELEGRAM_BOT_TOKEN = "<BOT_TOKEN>"
|
||||
|
||||
# Database settings
|
||||
# Only uncomment if default settings in base.py are not ok
|
||||
|
||||
# DATABASES = {
|
||||
# 'default': {
|
||||
# 'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||
# 'NAME': 'sik',
|
||||
# 'USER': 'sik',
|
||||
# 'PASSWORD': 'password123',
|
||||
# 'HOST': 'localhost',
|
||||
# 'PORT': '5432',
|
||||
# 'TEST': {
|
||||
# 'NAME': 'sik_test',
|
||||
# },
|
||||
# },
|
||||
# }
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': 'mydatabase',
|
||||
'TEST': {
|
||||
'NAME': 'sik_test',
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -14,27 +14,29 @@ https://docs.djangoproject.com/en/1.9/ref/settings/
|
||||
from sikweb.base import *
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = False
|
||||
DEBUG = os.getenv('DEBUG', False) == 'True'
|
||||
|
||||
ALLOWED_HOSTS = ["sika.sik.party"]
|
||||
URL = "sika.sik.party"
|
||||
URL = os.getenv("HOST", "sika.sik.party")
|
||||
ALLOWED_HOSTS = ["localhost", "127.0.0.1", URL]
|
||||
if DEBUG:
|
||||
ALLOWED_HOSTS = ["*"]
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = os.getenv('SECRET_KEY', '<your secret key>')
|
||||
|
||||
# ReCaptcha
|
||||
# http://www.yaconiello.com/blog/integrating-google-recaptcha-to-django/
|
||||
GOOGLE_RECAPTCHA_SITE_KEY = "YOUR-PUBLIC-KEY"
|
||||
GOOGLE_RECAPTCHA_SECRET_KEY = "YOUR-PRIVATE-KEY"
|
||||
GOOGLE_RECAPTCHA_SITE_KEY = os.getenv("GOOGLE_RECAPTCHA_SITE_KEY", "YOUR-PUBLIC-KEY")
|
||||
GOOGLE_RECAPTCHA_SECRET_KEY = os.getenv("GOOGLE_RECAPTCHA_SECRET_KEY", "YOUR-PRIVATE-KEY")
|
||||
|
||||
# Email settings (more settings in base.py)
|
||||
EMAIL_HOST_USER = 'sikviestinta@gmail.com'
|
||||
EMAIL_HOST_USER = os.getenv('EMAIL_HOST', 'sikviestinta@gmail.com')
|
||||
EMAIL_HOST_PASSWORD = os.getenv('EMAIL_PASSWD', '<gmail_passu>')
|
||||
DEFAULT_EMAIL_FROM = 'SIK Viestintä <sikviestinta@gmail.com>'
|
||||
ENABLE_AUTOMATIC_EMAILS = True
|
||||
|
||||
# Token for Telegram bot
|
||||
TELEGRAM_BOT_TOKEN = os.getenv('TG_BOT_TOKEN')
|
||||
TELEGRAM_BOT_TOKEN = os.getenv('TG_BOT_TOKEN', '<tg token>')
|
||||
|
||||
# Database settings
|
||||
# Only uncomment if default settings in base.py are not ok
|
||||
@@ -42,10 +44,10 @@ TELEGRAM_BOT_TOKEN = os.getenv('TG_BOT_TOKEN')
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||
'NAME': os.getenv('DB_USER', '<none>'),
|
||||
'USER': os.getenv('DB_USER', '<none>'),
|
||||
'PASSWORD': os.getenv('DB_PASSWD', '<none>'),
|
||||
'HOST': os.getenv('DB_HOST', '127.0.0.1'),
|
||||
'NAME': os.getenv('DB_USER', 'postgres'),
|
||||
'USER': os.getenv('DB_USER', 'postgres'),
|
||||
'PASSWORD': os.getenv('DB_PASSWD', 'postgres'),
|
||||
'HOST': os.getenv('DB_HOST', 'localhost'),
|
||||
'PORT': os.getenv('DB_PORT', 5432),
|
||||
}
|
||||
}
|
||||
+1
-3
@@ -1,13 +1,11 @@
|
||||
version: '3.4'
|
||||
services:
|
||||
db:
|
||||
image: postgres:10
|
||||
image: postgres:12
|
||||
deploy:
|
||||
replicas: 1
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
update_config:
|
||||
order: start-first
|
||||
|
||||
environment:
|
||||
- POSTGRES_USER_FILE=/run/secrets/DJANGO_DB_USER
|
||||
|
||||
-177
@@ -1,177 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Use this script to test if a given TCP host/port are available
|
||||
|
||||
cmdname=$(basename $0)
|
||||
|
||||
echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }
|
||||
|
||||
usage()
|
||||
{
|
||||
cat << USAGE >&2
|
||||
Usage:
|
||||
$cmdname host:port [-s] [-t timeout] [-- command args]
|
||||
-h HOST | --host=HOST Host or IP under test
|
||||
-p PORT | --port=PORT TCP port under test
|
||||
Alternatively, you specify the host and port as host:port
|
||||
-s | --strict Only execute subcommand if the test succeeds
|
||||
-q | --quiet Don't output any status messages
|
||||
-t TIMEOUT | --timeout=TIMEOUT
|
||||
Timeout in seconds, zero for no timeout
|
||||
-- COMMAND ARGS Execute command with args after the test finishes
|
||||
USAGE
|
||||
exit 1
|
||||
}
|
||||
|
||||
wait_for()
|
||||
{
|
||||
if [[ $TIMEOUT -gt 0 ]]; then
|
||||
echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT"
|
||||
else
|
||||
echoerr "$cmdname: waiting for $HOST:$PORT without a timeout"
|
||||
fi
|
||||
start_ts=$(date +%s)
|
||||
while :
|
||||
do
|
||||
if [[ $ISBUSY -eq 1 ]]; then
|
||||
nc -z $HOST $PORT
|
||||
result=$?
|
||||
else
|
||||
(echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1
|
||||
result=$?
|
||||
fi
|
||||
if [[ $result -eq 0 ]]; then
|
||||
end_ts=$(date +%s)
|
||||
echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds"
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
return $result
|
||||
}
|
||||
|
||||
wait_for_wrapper()
|
||||
{
|
||||
# In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
|
||||
if [[ $QUIET -eq 1 ]]; then
|
||||
timeout $BUSYTIMEFLAG $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT &
|
||||
else
|
||||
timeout $BUSYTIMEFLAG $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT &
|
||||
fi
|
||||
PID=$!
|
||||
trap "kill -INT -$PID" INT
|
||||
wait $PID
|
||||
RESULT=$?
|
||||
if [[ $RESULT -ne 0 ]]; then
|
||||
echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT"
|
||||
fi
|
||||
return $RESULT
|
||||
}
|
||||
|
||||
# process arguments
|
||||
while [[ $# -gt 0 ]]
|
||||
do
|
||||
case "$1" in
|
||||
*:* )
|
||||
hostport=(${1//:/ })
|
||||
HOST=${hostport[0]}
|
||||
PORT=${hostport[1]}
|
||||
shift 1
|
||||
;;
|
||||
--child)
|
||||
CHILD=1
|
||||
shift 1
|
||||
;;
|
||||
-q | --quiet)
|
||||
QUIET=1
|
||||
shift 1
|
||||
;;
|
||||
-s | --strict)
|
||||
STRICT=1
|
||||
shift 1
|
||||
;;
|
||||
-h)
|
||||
HOST="$2"
|
||||
if [[ $HOST == "" ]]; then break; fi
|
||||
shift 2
|
||||
;;
|
||||
--host=*)
|
||||
HOST="${1#*=}"
|
||||
shift 1
|
||||
;;
|
||||
-p)
|
||||
PORT="$2"
|
||||
if [[ $PORT == "" ]]; then break; fi
|
||||
shift 2
|
||||
;;
|
||||
--port=*)
|
||||
PORT="${1#*=}"
|
||||
shift 1
|
||||
;;
|
||||
-t)
|
||||
TIMEOUT="$2"
|
||||
if [[ $TIMEOUT == "" ]]; then break; fi
|
||||
shift 2
|
||||
;;
|
||||
--timeout=*)
|
||||
TIMEOUT="${1#*=}"
|
||||
shift 1
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
CLI=("$@")
|
||||
break
|
||||
;;
|
||||
--help)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
echoerr "Unknown argument: $1"
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ "$HOST" == "" || "$PORT" == "" ]]; then
|
||||
echoerr "Error: you need to provide a host and port to test."
|
||||
usage
|
||||
fi
|
||||
|
||||
TIMEOUT=${TIMEOUT:-15}
|
||||
STRICT=${STRICT:-0}
|
||||
CHILD=${CHILD:-0}
|
||||
QUIET=${QUIET:-0}
|
||||
|
||||
# check to see if timeout is from busybox?
|
||||
# check to see if timeout is from busybox?
|
||||
TIMEOUT_PATH=$(realpath $(which timeout))
|
||||
if [[ $TIMEOUT_PATH =~ "busybox" ]]; then
|
||||
ISBUSY=1
|
||||
BUSYTIMEFLAG="-t"
|
||||
else
|
||||
ISBUSY=0
|
||||
BUSYTIMEFLAG=""
|
||||
fi
|
||||
|
||||
if [[ $CHILD -gt 0 ]]; then
|
||||
wait_for
|
||||
RESULT=$?
|
||||
exit $RESULT
|
||||
else
|
||||
if [[ $TIMEOUT -gt 0 ]]; then
|
||||
wait_for_wrapper
|
||||
RESULT=$?
|
||||
else
|
||||
wait_for
|
||||
RESULT=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $CLI != "" ]]; then
|
||||
if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then
|
||||
echoerr "$cmdname: strict mode, refusing to execute subprocess"
|
||||
exit $RESULT
|
||||
fi
|
||||
exec "${CLI[@]}"
|
||||
else
|
||||
exit $RESULT
|
||||
fi
|
||||
+3
-2
@@ -1,7 +1,7 @@
|
||||
"""File containing webapp app admin registers."""
|
||||
|
||||
from django.contrib import admin
|
||||
from webapp.models import Official, Role, Committee
|
||||
from webapp.models import Official, Role, Committee, Occupation
|
||||
from webapp.models import Feed, Tag, BaseFeed, Event, Signup, SignupForm, TemplateQuestion
|
||||
from modeltranslation.admin import TranslationAdmin
|
||||
from django.contrib.auth.models import Permission
|
||||
@@ -16,6 +16,7 @@ admin.site.register(Event, TranslationAdmin)
|
||||
admin.site.register(SignupForm, TranslationAdmin)
|
||||
admin.site.register(Signup, TranslationAdmin)
|
||||
admin.site.register(TemplateQuestion, TranslationAdmin)
|
||||
admin.site.register(Committee, TranslationAdmin)
|
||||
admin.site.register(Official)
|
||||
admin.site.register(Occupation)
|
||||
admin.site.register(Role)
|
||||
admin.site.register(Committee)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 2.1.5 on 2019-09-26 17:48
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('webapp', '0054_auto_20190313_1642'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.DeleteModel(
|
||||
name='official'
|
||||
)
|
||||
]
|
||||
@@ -0,0 +1,58 @@
|
||||
# Generated by Django 2.1.5 on 2019-09-26 17:51
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import phonenumber_field.modelfields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('webapp', '0055_auto_20190926_2048'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Occupation',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('start_date', models.DateField(verbose_name='Start date')),
|
||||
('end_date', models.DateField(verbose_name='End date')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Occupation',
|
||||
'verbose_name_plural': 'Occupations',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Official',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('first_name', models.CharField(max_length=30, verbose_name='First name')),
|
||||
('last_name', models.CharField(max_length=150, verbose_name='Last name')),
|
||||
('email', models.EmailField(max_length=254, verbose_name='Email address')),
|
||||
('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, verbose_name='Phone number')),
|
||||
('role_history', models.ManyToManyField(blank=True, to='webapp.Occupation')),
|
||||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Official',
|
||||
'verbose_name_plural': 'Officials',
|
||||
},
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='role',
|
||||
name='end_date',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='role',
|
||||
name='start_date',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='occupation',
|
||||
name='role',
|
||||
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='webapp.Role'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 2.1.5 on 2019-09-26 18:02
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('webapp', '0056_auto_20190926_2051'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='occupation',
|
||||
name='role',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='webapp.Role'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 2.1.5 on 2019-10-10 15:37
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('webapp', '0057_auto_20190926_2102'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='official',
|
||||
name='role_history',
|
||||
field=models.ManyToManyField(blank=True, related_name='officials', to='webapp.Occupation'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 2.1.5 on 2019-10-10 16:00
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('webapp', '0058_auto_20191010_1837'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='committee',
|
||||
name='name_en',
|
||||
field=models.CharField(max_length=255, null=True, verbose_name='Name'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='committee',
|
||||
name='name_fi',
|
||||
field=models.CharField(max_length=255, null=True, verbose_name='Name'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 2.1.5 on 2019-10-10 16:05
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('webapp', '0059_auto_20191010_1900'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='official',
|
||||
name='image',
|
||||
field=models.ImageField(null=True, upload_to=''),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,29 @@
|
||||
# Generated by Django 2.1.5 on 2019-11-10 18:24
|
||||
|
||||
import django.contrib.postgres.fields.jsonb
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('webapp', '0060_official_image'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='official',
|
||||
name='image',
|
||||
field=models.ImageField(blank=True, null=True, upload_to=''),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='signup',
|
||||
name='answer',
|
||||
field=django.contrib.postgres.fields.jsonb.JSONField(),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='signupform',
|
||||
name='questions',
|
||||
field=django.contrib.postgres.fields.jsonb.JSONField(),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 2.1.5 on 2019-11-10 19:17
|
||||
|
||||
import django.contrib.postgres.fields.jsonb
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('webapp', '0061_auto_20191110_2024'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='templatequestion',
|
||||
name='question',
|
||||
field=django.contrib.postgres.fields.jsonb.JSONField(),
|
||||
),
|
||||
]
|
||||
+56
-12
@@ -4,12 +4,13 @@ from django.db import models
|
||||
from django.utils import timezone
|
||||
# from datetime import timedelta
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
from webapp.utils import month_from_now
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
# from django.contrib.auth.models import User
|
||||
from auditlog.registry import auditlog
|
||||
from phonenumber_field.modelfields import PhoneNumberField
|
||||
# from django.contrib.postgres.fields import JSONField
|
||||
from django.contrib.postgres.fields import JSONField
|
||||
|
||||
# import logging
|
||||
|
||||
@@ -76,9 +77,8 @@ class Event(BaseFeed):
|
||||
|
||||
class TemplateQuestion(models.Model):
|
||||
"""Stores template questions for signup forms as JSONB"""
|
||||
# question = JSONField()
|
||||
name = models.CharField(max_length=255)
|
||||
question = models.CharField(max_length=255)
|
||||
question = JSONField()
|
||||
|
||||
def __str__(self):
|
||||
return _('Template questions: {}').format(self.name)
|
||||
@@ -94,8 +94,7 @@ class SignupForm(models.Model):
|
||||
title = models.CharField(max_length=255)
|
||||
start_time = models.DateTimeField(default=timezone.now)
|
||||
end_time = models.DateTimeField(default=timezone.now)
|
||||
# question = JSONField()
|
||||
questions = models.TextField(default="[]")
|
||||
questions = JSONField()
|
||||
visible = models.BooleanField(default=True)
|
||||
|
||||
def __str__(self):
|
||||
@@ -109,7 +108,7 @@ class SignupForm(models.Model):
|
||||
class Signup(models.Model):
|
||||
signupForm = models.ForeignKey('SignupForm', on_delete=models.CASCADE)
|
||||
time = models.DateTimeField(default=timezone.now)
|
||||
answer = models.CharField(max_length=255)
|
||||
answer = JSONField()
|
||||
|
||||
def __str__(self):
|
||||
return _('Sign-ups: {}').format(self.signupForm)
|
||||
@@ -163,7 +162,7 @@ class Role(PresetRole):
|
||||
Model for Role.
|
||||
|
||||
Model representing an active or historical occupation
|
||||
in an official's history.
|
||||
in the guild.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
@@ -172,12 +171,38 @@ class Role(PresetRole):
|
||||
verbose_name = _('Role')
|
||||
verbose_name_plural = _('Roles')
|
||||
|
||||
start_date = models.DateField(_('Start date'))
|
||||
end_date = models.DateField(_('End date'))
|
||||
committee = models.ForeignKey('Committee', related_name='roles', on_delete=models.SET_NULL, null=True)
|
||||
|
||||
def __str__(self):
|
||||
return '{} (Hallitus: {}) ({})'.format(self.name, _("Yes") if self.is_board else _("No"), self.committee)
|
||||
|
||||
class Official(User):
|
||||
|
||||
class Occupation(models.Model):
|
||||
"""
|
||||
Model for a occupation in guild.
|
||||
|
||||
Model links Official into a role he/she has or has had in the guild.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Occupation')
|
||||
verbose_name_plural = _('Occupations')
|
||||
|
||||
start_date = models.DateField(_('Start date'))
|
||||
end_date = models.DateField(_('End date'))
|
||||
role = models.ForeignKey('Role', on_delete=models.SET_NULL, null=True)
|
||||
|
||||
@staticmethod
|
||||
def by_year(year):
|
||||
return Occupation.objects.filter(
|
||||
end_date__gte=timezone.datetime(year, 1, 1)).filter(
|
||||
start_date__lte=timezone.datetime(year, 12, 31))
|
||||
|
||||
def __str__(self):
|
||||
return '{}: {} - {}'.format(self.role.name, self.start_date, self.end_date)
|
||||
|
||||
|
||||
class Official(models.Model):
|
||||
"""Model representing a guild official."""
|
||||
|
||||
class Meta:
|
||||
@@ -186,13 +211,32 @@ class Official(User):
|
||||
verbose_name = _('Official')
|
||||
verbose_name_plural = _('Officials')
|
||||
|
||||
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
||||
|
||||
first_name = models.CharField(_('First name'), max_length=30)
|
||||
last_name = models.CharField(_('Last name'), max_length=150)
|
||||
email = models.EmailField(_('Email address'))
|
||||
phone_number = PhoneNumberField(_('Phone number'))
|
||||
role = models.ManyToManyField('Role', related_name='official')
|
||||
role_history = models.ManyToManyField('Occupation', 'officials', blank=True)
|
||||
image = models.ImageField(blank=True, null=True)
|
||||
|
||||
@staticmethod
|
||||
def by_year(year):
|
||||
return Official.objects.filter(
|
||||
role_history__in=Occupation.occupations_by_year(year)).distinct()
|
||||
|
||||
def __str__(self):
|
||||
return '{} {}'.format(self.first_name, self.last_name)
|
||||
|
||||
|
||||
@receiver(post_save, sender=Official)
|
||||
def save_user_official(sender, instance, **kwargs):
|
||||
instance.user.first_name = instance.first_name
|
||||
instance.user.last_name = instance.last_name
|
||||
instance.user.email = instance.email
|
||||
instance.user.save()
|
||||
|
||||
|
||||
auditlog.register(Tag)
|
||||
auditlog.register(Feed)
|
||||
auditlog.register(Event)
|
||||
|
||||
+42
-8
@@ -3,12 +3,14 @@ from webapp.models import *
|
||||
|
||||
|
||||
class SignupFormSerializer(serializers.HyperlinkedModelSerializer):
|
||||
questions = serializers.JSONField(binary=True)
|
||||
|
||||
class Meta:
|
||||
model = SignupForm
|
||||
fields = ('id', 'title', 'start_time', 'end_time', 'questions')
|
||||
|
||||
|
||||
class EventSerializer(serializers.HyperlinkedModelSerializer):
|
||||
class EventSerializer(serializers.ModelSerializer):
|
||||
signupForm = SignupFormSerializer(many=True, read_only=True, required=False)
|
||||
signup_id = serializers.PrimaryKeyRelatedField(
|
||||
many=True,
|
||||
@@ -23,8 +25,8 @@ class EventSerializer(serializers.HyperlinkedModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Event
|
||||
fields = ('id', 'tag_id', 'tags', 'visible', 'title', 'description',
|
||||
'content', 'start_time', 'end_time', 'location', 'signup_id', 'signupForm')
|
||||
fields = ('id', 'tag_id', 'tags', 'visible', 'title_fi', 'title_en', 'description_fi', 'description_en',
|
||||
'content_fi', 'content_en', 'start_time', 'end_time', 'location', 'signup_id', 'signupForm')
|
||||
depth = 1
|
||||
|
||||
def create(self, validated_data):
|
||||
@@ -49,9 +51,16 @@ class EventSerializer(serializers.HyperlinkedModelSerializer):
|
||||
|
||||
|
||||
class SignupSerializer(serializers.ModelSerializer):
|
||||
signupForm = SignupFormSerializer(read_only=True, required=False)
|
||||
signupForm_id = serializers.PrimaryKeyRelatedField(
|
||||
source="signupForm",
|
||||
queryset=SignupForm.objects.all()
|
||||
)
|
||||
answer = serializers.JSONField(binary=True)
|
||||
|
||||
class Meta:
|
||||
model = Signup
|
||||
fields = ('id', 'signupForm', 'answer')
|
||||
fields = ('id', 'signupForm', 'signupForm_id', 'answer')
|
||||
extra_kwargs = {
|
||||
'url': {
|
||||
'view_name': 'signup-detail',
|
||||
@@ -60,6 +69,8 @@ class SignupSerializer(serializers.ModelSerializer):
|
||||
|
||||
|
||||
class SavedQuestionsSerializer(serializers.ModelSerializer):
|
||||
question = serializers.JSONField(binary=True)
|
||||
|
||||
class Meta:
|
||||
model = TemplateQuestion
|
||||
fields = ('id', 'name', 'question')
|
||||
@@ -68,7 +79,7 @@ class SavedQuestionsSerializer(serializers.ModelSerializer):
|
||||
class TagSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Tag
|
||||
fields = ('id', 'slug', 'name', 'icon')
|
||||
fields = ('id', 'slug', 'name_fi', 'name_en', 'icon')
|
||||
|
||||
|
||||
class FeedSerializer(serializers.ModelSerializer):
|
||||
@@ -80,8 +91,8 @@ class FeedSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Feed
|
||||
fields = ('id', 'tags', 'tag_id', 'visible', 'title', 'description',
|
||||
'content', 'publish_time', 'autohide', 'autohide_enabled')
|
||||
fields = ('id', 'tags', 'tag_id', 'visible', 'title_fi', 'title_en', 'description_fi', 'description_en',
|
||||
'content_fi', 'content_en', 'publish_time', 'autohide', 'autohide_enabled')
|
||||
depth = 1
|
||||
|
||||
def create(self, validated_data):
|
||||
@@ -93,8 +104,31 @@ class FeedSerializer(serializers.ModelSerializer):
|
||||
return feed
|
||||
|
||||
|
||||
class CommitteeSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Committee
|
||||
fields = ['name_fi', 'name_en']
|
||||
|
||||
|
||||
class RoleSerializer(serializers.ModelSerializer):
|
||||
committee = CommitteeSerializer(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Role
|
||||
fields = ('name_fi', 'name_en', 'description_fi', 'description_en', 'committee', 'is_board')
|
||||
|
||||
|
||||
class ContactsSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Official
|
||||
fields = ('id', 'first_name', 'last_name', 'phone_number', 'role')
|
||||
fields = ('first_name', 'last_name', 'email', 'phone_number', 'image')
|
||||
depth = 2
|
||||
|
||||
|
||||
class OccupationSerializer(serializers.ModelSerializer):
|
||||
role = RoleSerializer(read_only=True)
|
||||
officials = ContactsSerializer(many=True, read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Occupation
|
||||
fields = ('role', 'start_date', 'end_date', 'officials')
|
||||
|
||||
-131
@@ -1,131 +0,0 @@
|
||||
"""Tests for webapp."""
|
||||
|
||||
from django.test import TestCase
|
||||
from django.core.files import File
|
||||
from django.contrib.auth.models import User
|
||||
from rest_framework.test import APITestCase
|
||||
from rest_framework import status
|
||||
from rest_framework.test import force_authenticate
|
||||
from webapp.models import Tag, Feed
|
||||
from webapp.serializers import TagSerializer, FeedSerializer
|
||||
|
||||
from collections import OrderedDict
|
||||
from itertools import islice
|
||||
import tempfile
|
||||
|
||||
|
||||
class TagsTestCase(APITestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.icon = tempfile.NamedTemporaryFile(suffix=".jpg").name
|
||||
Tag.objects.create(slug='Party', name='Bileet', icon=self.icon)
|
||||
|
||||
def test_get_single_tag(self):
|
||||
self.assertEqual(Tag.objects.count(), 1)
|
||||
response = self.client.get('/api/tags/', format='json')
|
||||
self.assertTrue(status.is_success(response.status_code))
|
||||
|
||||
# We dont care about icon, so response is sliced
|
||||
sliced_response = OrderedDict(islice(response.data['results'][0].items(), 3))
|
||||
tag1 = Tag.objects.get(slug="Party")
|
||||
self.assertEqual(sliced_response, {'id': tag1.id, 'slug': 'Party', 'name': 'Bileet'})
|
||||
|
||||
def test_get_single_tag_serializer(self):
|
||||
response = self.client.get('/api/tags/', format='json')
|
||||
self.assertTrue(status.is_success(response.status_code))
|
||||
|
||||
tags = Tag.objects.all()
|
||||
serializer = TagSerializer(tags, many=True)
|
||||
# Icon on serializer is returned without protocol and domain
|
||||
# Assert these individually
|
||||
resp_icon = response.data['results'][0].pop('icon')
|
||||
serial_icon = serializer.data[0].pop('icon')
|
||||
self.assertEqual(response.data['results'], serializer.data)
|
||||
self.assertEqual(resp_icon, "http://testserver" + serial_icon)
|
||||
|
||||
def test_get_multiple_tags(self):
|
||||
self.assertEqual(Tag.objects.count(), 1)
|
||||
Tag.objects.create(slug='Freshmen', name='Fuksit', icon=self.icon)
|
||||
Tag.objects.create(slug='International', name='Ulkkarit', icon=self.icon)
|
||||
self.assertEqual(Tag.objects.count(), 3)
|
||||
|
||||
response = self.client.get('/api/tags/', format='json')
|
||||
self.assertTrue(status.is_success(response.status_code))
|
||||
|
||||
# We dont care about icon, so response is sliced
|
||||
tag1 = Tag.objects.get(slug="Party")
|
||||
sliced_response = OrderedDict(islice(response.data['results'][0].items(), 3))
|
||||
self.assertEqual(sliced_response, {'id': tag1.id, 'slug': 'Party', 'name': 'Bileet'})
|
||||
sliced_response = OrderedDict(islice(response.data['results'][1].items(), 3))
|
||||
tag2 = Tag.objects.get(slug="Freshmen")
|
||||
self.assertEqual(sliced_response, {'id': tag2.id, 'slug': 'Freshmen', 'name': 'Fuksit'})
|
||||
sliced_response = OrderedDict(islice(response.data['results'][2].items(), 3))
|
||||
tag3 = Tag.objects.get(slug="International")
|
||||
self.assertEqual(sliced_response, {'id': tag3.id, 'slug': 'International', 'name': 'Ulkkarit'})
|
||||
|
||||
def test_create_tag(self):
|
||||
self.assertEqual(Tag.objects.count(), 1)
|
||||
response = self.client.post('/api/tags/', {'slug': 'Test', 'name': 'Testinimi', 'icon': self.icon}, format='multipart')
|
||||
self.assertFalse(status.is_success(response.status_code))
|
||||
self.assertEqual(Tag.objects.count(), 1)
|
||||
|
||||
def test_invalid_tag(self):
|
||||
self.assertEqual(Tag.objects.count(), 1)
|
||||
response = self.client.get('/api/tags/15', format='json', follow=True)
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
|
||||
|
||||
class FeedTestCase(APITestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.icon = tempfile.NamedTemporaryFile(suffix=".jpg").name
|
||||
Tag.objects.create(slug='testtag1', name='test1', icon=self.icon)
|
||||
tag1 = Tag.objects.get(slug="testtag1")
|
||||
Tag.objects.create(slug="testtag2", name='test2', icon=self.icon)
|
||||
tag2 = Tag.objects.get(slug="testtag2")
|
||||
self.assertEqual(Tag.objects.count(), 2)
|
||||
|
||||
Feed.objects.create(title="TestFeed", visible=True, description="diidadaapa", content="lorem ipsum")
|
||||
Feed.objects.get(title="TestFeed").tags.add(tag1)
|
||||
Feed.objects.get(title="TestFeed").tags.add(tag2)
|
||||
self.assertEqual(Feed.objects.count(), 1)
|
||||
self.assertEqual(Feed.objects.all()[0].tags.count(), 2)
|
||||
|
||||
username, password = 'test_admin', 'password123'
|
||||
self.authClient = User.objects.create_superuser(username, 'myemail@test.com', password)
|
||||
|
||||
def test_get_feed(self):
|
||||
response = self.client.get('/api/feed/', format='json')
|
||||
self.assertTrue(status.is_success(response.status_code))
|
||||
|
||||
feeds = Feed.objects.all()
|
||||
serializer = FeedSerializer(feeds, many=True)
|
||||
|
||||
# DRF extends path given by serializer with the protocol and domain for icon
|
||||
# Ignore tag on serializer and response. This is tested on TagTestCase.
|
||||
# Note that we assume the length here to be 1
|
||||
response.data['results'][0].pop('tags')
|
||||
serializer.data[0].pop('tags')
|
||||
self.assertEqual(response.data['results'], serializer.data)
|
||||
|
||||
def test_post_feed(self):
|
||||
Tag.objects.create(slug="test1", name="testsds")
|
||||
Tag.objects.create(slug="test2", name="testsdsd")
|
||||
tag1_id = Tag.objects.get(slug="test1").id
|
||||
tag2_id = Tag.objects.get(slug="test2").id
|
||||
|
||||
data = {'tags': [tag1_id, tag2_id], 'title': 'testtitle', 'visible': 'True', 'description': 'liirumlaarum', 'content': 'lorem ipsum'}
|
||||
# Try post without authentication
|
||||
response = self.client.post('/api/feed/', data, format='multipart')
|
||||
self.assertTrue(status.is_client_error(response.status_code))
|
||||
self.assertEqual(Feed.objects.count(), 1)
|
||||
# Authenticate
|
||||
self.client.force_authenticate(user=self.authClient)
|
||||
response = self.client.post('/api/feed/', data, format='multipart')
|
||||
# Return success and check object was created
|
||||
self.assertTrue(status.is_success(response.status_code))
|
||||
self.assertEqual(Feed.objects.count(), 2)
|
||||
|
||||
created = Feed.objects.get(title="testtitle")
|
||||
print(created.tags)
|
||||
# self.assertEqual(created.tags.count(), 2)
|
||||
@@ -0,0 +1,36 @@
|
||||
from django.utils import timezone
|
||||
from webapp.models import Event
|
||||
from webapp.utils import month_from_now
|
||||
|
||||
|
||||
def createEventObject(name="Testitapahtuma1", visible=True, start_time=timezone.now(), end_time=month_from_now(), tag_id=[], signup_id=[]):
|
||||
return Event.objects.create(
|
||||
title_fi=name,
|
||||
title_en=f"title_en {name}",
|
||||
visible=visible,
|
||||
description_fi=f"desc_fi {name}",
|
||||
description_en=f"desc_en {name}",
|
||||
content_fi=f"content_fi {name}",
|
||||
content_en=f"content_en {name}",
|
||||
start_time=start_time,
|
||||
end_time=end_time,
|
||||
location=f"loc {name}"
|
||||
)
|
||||
|
||||
|
||||
def createEventJSON(name="POST1", visible=True, start_time=timezone.now(), end_time=month_from_now(), tag_id=[], signup_id=[]):
|
||||
return {
|
||||
"tags": tag_id,
|
||||
"tag_id": tag_id,
|
||||
"visible": visible,
|
||||
"title_fi": f"title_fi {name}",
|
||||
"title_en": f"title_en {name}",
|
||||
"description_fi": f"desc_fi {name}",
|
||||
"description_en": f"desc_en {name}",
|
||||
"content_fi": f"content_fi {name}",
|
||||
"content_en": f"content_en {name}",
|
||||
"start_time": start_time,
|
||||
"end_time": end_time,
|
||||
"signup_id": signup_id,
|
||||
"location": f"loc {name}"
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
from webapp.models import Signup, SignupForm
|
||||
from django.utils import timezone
|
||||
from webapp.utils import month_from_now
|
||||
|
||||
import json
|
||||
|
||||
ALL_QUESTION_TYPES = [
|
||||
{"id": "j5CeRZDvl", "name": "Asd", "type": "text", "options": []},
|
||||
{"id": "RHJhSoaLD", "name": "Asd2", "type": "radiobutton", "options": ["Yes", "no", "maybe"]},
|
||||
{"id": "i10d426d5", "name": "Asd3", "type": "checkbox", "options": ["A", "B", "C"]}
|
||||
]
|
||||
|
||||
ALL_QUESTION_TYPES_ANSWER = {"j5CeRZDvl": "Testi", "RHJhSoaLD": "maybe", "i10d426d5": ["B"]}
|
||||
|
||||
|
||||
def createSignupForm(name="Form1", start_time=timezone.now(), end_time=month_from_now(), questions=ALL_QUESTION_TYPES, visible=True):
|
||||
return SignupForm.objects.create(
|
||||
title=name,
|
||||
start_time=start_time,
|
||||
end_time=end_time,
|
||||
questions=questions,
|
||||
visible=visible
|
||||
)
|
||||
|
||||
|
||||
def createSignupObject(form, answer):
|
||||
return Signup.objects.create(
|
||||
signupForm=form,
|
||||
answer=answer
|
||||
)
|
||||
|
||||
|
||||
def createSignupJSON(form_id, answer):
|
||||
return {
|
||||
"signupForm_id": form_id,
|
||||
"answer": json.dumps(answer)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
from webapp.models import Tag
|
||||
import tempfile
|
||||
|
||||
|
||||
def createTagIcon():
|
||||
return tempfile.NamedTemporaryFile(suffix=".jpg").name
|
||||
|
||||
|
||||
def tagBuilder(slug="Tag1", icon=createTagIcon()):
|
||||
return Tag.objects.create(
|
||||
slug=slug,
|
||||
name_fi=slug + " name_fi",
|
||||
name_en=slug + " name_en",
|
||||
icon=icon
|
||||
)
|
||||
@@ -0,0 +1,96 @@
|
||||
from django.test import TestCase
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils import timezone
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from webapp.models import Official, Role, Occupation, Committee
|
||||
from webapp.serializers import OccupationSerializer
|
||||
|
||||
|
||||
URL = "/api/contacts/"
|
||||
COMMITTEE = Committee.objects.create(
|
||||
name_fi="Viestintä",
|
||||
name_en="Communications"
|
||||
)
|
||||
|
||||
|
||||
def createRoleBoard():
|
||||
return Role.objects.create(
|
||||
name_fi="Metsuri",
|
||||
name_en="The lumberjack",
|
||||
is_board=True,
|
||||
description_fi="Toimikunta PJ",
|
||||
description_en="Committee Chair"
|
||||
)
|
||||
|
||||
|
||||
def createRoleNoBoard():
|
||||
return Role.objects.create(
|
||||
name_fi="Toimari",
|
||||
name_en="Official",
|
||||
is_board=False,
|
||||
description_fi="Toimikunta jäbä",
|
||||
description_en="Committee dude(tte)",
|
||||
committee=COMMITTEE
|
||||
)
|
||||
|
||||
|
||||
def createOccupation(year, role=createRoleNoBoard(), dummydata=1):
|
||||
occupation = Occupation.objects.create(
|
||||
start_date=timezone.datetime(year, 1, 1),
|
||||
end_date=timezone.datetime(year, 12, 31),
|
||||
role=role
|
||||
)
|
||||
|
||||
occupation.officials.add(
|
||||
createPerson(dummydata)
|
||||
)
|
||||
|
||||
return occupation
|
||||
|
||||
|
||||
def createPerson(name):
|
||||
return Official.objects.create(
|
||||
user=User.objects.create_user(f"testi{name}", "test@test.tld", "password123"),
|
||||
first_name=f"first{name}",
|
||||
last_name=f"last{name}",
|
||||
email="test@test.tld",
|
||||
phone_number="+358501234567",
|
||||
image=""
|
||||
)
|
||||
|
||||
|
||||
class ContactsTestCase(APITestCase):
|
||||
|
||||
def setUp(self):
|
||||
createOccupation(timezone.now().year, role=createRoleBoard(), dummydata=1)
|
||||
createOccupation(timezone.now().year, dummydata=2)
|
||||
createOccupation(1970, role=createRoleBoard(), dummydata=3)
|
||||
createOccupation(1970, dummydata=4)
|
||||
|
||||
def test_get(self):
|
||||
response = self.client.get(f"{URL}", format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
serializer = OccupationSerializer(
|
||||
Occupation.by_year(2019),
|
||||
many=True
|
||||
)
|
||||
self.assertEqual(response.data["results"], serializer.data)
|
||||
|
||||
def test_get_by_year(self):
|
||||
response = self.client.get(f"{URL}?year=1970", format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
serializer = OccupationSerializer(
|
||||
Occupation.by_year(1970),
|
||||
many=True
|
||||
)
|
||||
|
||||
self.assertEqual(response.data["results"], serializer.data)
|
||||
|
||||
def test_by_year_empty(self):
|
||||
response = self.client.get(f"{URL}?year=1971")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data["results"], [])
|
||||
@@ -0,0 +1,159 @@
|
||||
from django.test import TestCase
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils import timezone
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase, APIRequestFactory, force_authenticate
|
||||
|
||||
from webapp.models import Event
|
||||
from webapp.serializers import EventSerializer
|
||||
from webapp.tests.tag_fixture import tagBuilder, createTagIcon
|
||||
from webapp.tests.event_fixture import createEventObject, createEventJSON
|
||||
from webapp.tests.signup_fixture import createSignupForm
|
||||
|
||||
URL = "/api/events/"
|
||||
|
||||
|
||||
class EventTestCase(APITestCase):
|
||||
|
||||
def setUp(self):
|
||||
# Visible and relevant
|
||||
test1 = createEventObject(
|
||||
"Testitapahtuma1",
|
||||
start_time=timezone.datetime(2019, 11, 9, 12, 0, 0))
|
||||
# Invisible but relevant
|
||||
createEventObject(
|
||||
"Testitapahtuma2",
|
||||
visible=False,
|
||||
start_time=timezone.datetime(2018, 11, 9, 12, 0, 0))
|
||||
# Visible but unrelevant
|
||||
test2 = createEventObject(
|
||||
"Testitapahtuma3",
|
||||
visible=True,
|
||||
start_time=timezone.datetime(2018, 12, 9, 12, 0, 0),
|
||||
end_time=timezone.datetime(2018, 12, 9, 13, 0, 0))
|
||||
# Visible and relevant
|
||||
createEventObject(
|
||||
"Testitapahtuma4",
|
||||
visible=True,
|
||||
start_time=timezone.datetime(2018, 12, 9, 12, 0, 0))
|
||||
# Add some tags
|
||||
tag1 = tagBuilder()
|
||||
tag2 = tagBuilder("testtag2")
|
||||
self.testTagId = tag1.id
|
||||
test1.tags.add(tag1)
|
||||
test2.tags.add(tag2)
|
||||
self.testEventId = test1.id
|
||||
self.assertEqual(Event.objects.count(), 4)
|
||||
|
||||
self.signupFormId = createSignupForm().id
|
||||
|
||||
username, password = "test_admin", "password123"
|
||||
self.authClient = User.objects.create_superuser(username, "myemail@test.com", password)
|
||||
|
||||
def test_get_current_events(self):
|
||||
# Get from API
|
||||
response = self.client.get(URL, format="json")
|
||||
# Response 200
|
||||
self.assertTrue(response.status_code, status.HTTP_200_OK)
|
||||
# Response should not have old events and invisible
|
||||
self.assertEqual(len(response.data["results"]), 2)
|
||||
# Check that serialized data is equal to received response
|
||||
expected_events = EventSerializer(
|
||||
Event.objects.filter(title_fi__in=("Testitapahtuma1", "Testitapahtuma4")).order_by("start_time"),
|
||||
many=True,
|
||||
context={
|
||||
"request": APIRequestFactory().get(r"http://testserver/api/events/")
|
||||
}
|
||||
)
|
||||
self.assertEqual(response.data["results"], expected_events.data)
|
||||
|
||||
def test_get_events_since(self):
|
||||
response = self.client.get(f"{URL}?since=2018-01-01", format="json")
|
||||
self.assertTrue(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(len(response.data["results"]), 3)
|
||||
|
||||
expected_events = EventSerializer(
|
||||
Event.objects.filter(title_fi__in=("Testitapahtuma1", "Testitapahtuma3", "Testitapahtuma4")).order_by("start_time"),
|
||||
many=True,
|
||||
context={
|
||||
"request": APIRequestFactory().get(r"http://testserver/api/events/")
|
||||
}
|
||||
)
|
||||
self.assertEqual(response.data["results"], expected_events.data)
|
||||
|
||||
def test_get_single_event(self):
|
||||
response = self.client.get(f"{URL}{self.testEventId}/", format="json")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
serializer = EventSerializer(
|
||||
Event.objects.get(title_fi="Testitapahtuma1"),
|
||||
context={
|
||||
"request": APIRequestFactory().get(r"http://testserver/api/events/")
|
||||
}
|
||||
)
|
||||
self.assertEqual(response.data, serializer.data)
|
||||
|
||||
def test_get_invalid_event(self):
|
||||
response = self.client.get(f"{URL}200/", format="json")
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
|
||||
def test_post_event(self):
|
||||
# Authenticate
|
||||
self.client.force_authenticate(user=self.authClient)
|
||||
response = self.client.post(
|
||||
URL,
|
||||
createEventJSON(tag_id=[self.testTagId], signup_id=[self.signupFormId]),
|
||||
format="json"
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(Event.objects.count(), 5)
|
||||
|
||||
def test_post_event_unauth(self):
|
||||
response = self.client.post(
|
||||
URL,
|
||||
createEventJSON(tag_id=[self.testTagId], signup_id=[self.signupFormId]),
|
||||
format="json"
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
self.assertEqual(Event.objects.count(), 4)
|
||||
|
||||
def test_update_event(self):
|
||||
# Authenticate
|
||||
self.client.force_authenticate(user=self.authClient)
|
||||
event = Event.objects.get(id=self.testEventId)
|
||||
new = createEventJSON(name="Update1", signup_id=[self.signupFormId])
|
||||
response = self.client.put(
|
||||
f"{URL}{self.testEventId}/",
|
||||
new,
|
||||
format="json"
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
event = Event.objects.get(id=self.testEventId)
|
||||
self.assertEqual(event.title_fi, "title_fi Update1")
|
||||
self.assertEqual(Event.objects.count(), 4)
|
||||
|
||||
def test_update_event_unauth(self):
|
||||
response = self.client.put(
|
||||
f"{URL}{self.testEventId}/",
|
||||
createEventJSON(name="Update1"),
|
||||
format="json"
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
event = Event.objects.get(id=self.testEventId)
|
||||
self.assertEqual(event.title_fi, "Testitapahtuma1")
|
||||
self.assertEqual(Event.objects.count(), 4)
|
||||
|
||||
def test_delete_event(self):
|
||||
response = self.client.delete(f"{URL}{self.testEventId}/",)
|
||||
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
self.assertEqual(Event.objects.count(), 4)
|
||||
|
||||
# Authenticate
|
||||
self.client.force_authenticate(user=self.authClient)
|
||||
response = self.client.delete(f"{URL}{self.testEventId}/")
|
||||
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
||||
self.assertEqual(Event.objects.count(), 3)
|
||||
@@ -0,0 +1,64 @@
|
||||
from django.test import TestCase
|
||||
from django.contrib.auth.models import User
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase, APIRequestFactory, force_authenticate
|
||||
|
||||
from webapp.models import Feed
|
||||
from webapp.serializers import FeedSerializer
|
||||
from webapp.tests.tag_fixture import tagBuilder
|
||||
|
||||
|
||||
class FeedTestCase(APITestCase):
|
||||
|
||||
def setUp(self):
|
||||
tag1 = tagBuilder()
|
||||
tag2 = tagBuilder("testtag2")
|
||||
|
||||
feed = Feed.objects.create(title="TestFeed", visible=True, description="diidadaapa", content="lorem ipsum")
|
||||
feed.tags.add(tag1)
|
||||
feed.tags.add(tag2)
|
||||
self.assertEqual(Feed.objects.count(), 1)
|
||||
self.assertEqual(Feed.objects.all()[0].tags.count(), 2)
|
||||
|
||||
username, password = "test_admin", "password123"
|
||||
self.authClient = User.objects.create_superuser(username, "myemail@test.com", password)
|
||||
|
||||
def test_get_feed(self):
|
||||
response = self.client.get("/api/feed/", format="json")
|
||||
self.assertTrue(status.is_success(response.status_code))
|
||||
|
||||
feeds = Feed.objects.all()
|
||||
serializer = FeedSerializer(
|
||||
feeds, many=True,
|
||||
context={
|
||||
"request": APIRequestFactory().get(r"http://testserver/api/events/")
|
||||
})
|
||||
self.assertEqual(response.data["results"], serializer.data)
|
||||
|
||||
def test_post_feed(self):
|
||||
tag1_id = tagBuilder("test1").id
|
||||
tag2_id = tagBuilder("test2").id
|
||||
|
||||
data = {
|
||||
"tag_id": [tag1_id, tag2_id],
|
||||
"title_fi": "testtitle",
|
||||
"title_en": "testtitle",
|
||||
"visible": "True",
|
||||
"description_fi": "liirumlaarum",
|
||||
"description_en": "liirumlaarum",
|
||||
"content_fi": "lorem ipsum",
|
||||
"content_en": "lorem ipsum"
|
||||
}
|
||||
# Try post without authentication
|
||||
response = self.client.post("/api/feed/", data, format="json")
|
||||
self.assertTrue(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
self.assertEqual(Feed.objects.count(), 1)
|
||||
# Authenticate
|
||||
self.client.force_authenticate(user=self.authClient)
|
||||
response = self.client.post("/api/feed/", data, format="json")
|
||||
# Return success and check object was created
|
||||
self.assertTrue(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(Feed.objects.count(), 2)
|
||||
|
||||
created = Feed.objects.get(title_fi="testtitle")
|
||||
self.assertEqual(created.tags.count(), 2)
|
||||
@@ -0,0 +1,93 @@
|
||||
from django.test import TestCase
|
||||
from unittest import skip
|
||||
from django.contrib.auth.models import User
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase, force_authenticate
|
||||
|
||||
from webapp.serializers import SignupSerializer, SignupFormSerializer
|
||||
from webapp.models import Signup
|
||||
from webapp.tests.event_fixture import createEventObject
|
||||
from webapp.tests.signup_fixture import createSignupForm, createSignupObject, createSignupJSON, ALL_QUESTION_TYPES, ALL_QUESTION_TYPES_ANSWER
|
||||
|
||||
|
||||
URL = "/api/signup/"
|
||||
|
||||
|
||||
class SignupTestCase(APITestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.signupForm = createSignupForm()
|
||||
self.hiddenForm = createSignupForm(visible=False)
|
||||
|
||||
self.signup1 = createSignupObject(self.signupForm, ALL_QUESTION_TYPES)
|
||||
self.signup2 = createSignupObject(self.signupForm, [])
|
||||
|
||||
username, password = "test_admin", "password123"
|
||||
self.authClient = User.objects.create_superuser(username, "myemail@test.com", password)
|
||||
|
||||
def test_get_signups(self):
|
||||
expected = SignupSerializer(
|
||||
self.signupForm.signup_set.all(),
|
||||
many=True
|
||||
)
|
||||
|
||||
# Unauthorized
|
||||
response = self.client.get(URL, format="json")
|
||||
self.assertTrue(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
# Authenticate
|
||||
self.client.force_authenticate(user=self.authClient)
|
||||
response = self.client.get(URL, format="json")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data["results"], expected.data)
|
||||
|
||||
def test_get_single_signup(self):
|
||||
id = self.signup1.id
|
||||
expected = SignupSerializer(
|
||||
Signup.objects.get(id=id)
|
||||
)
|
||||
|
||||
# Unauthorized
|
||||
response = self.client.get(f"{URL}{id}/", format="json")
|
||||
self.assertTrue(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
# Authenticate
|
||||
self.client.force_authenticate(user=self.authClient)
|
||||
response = self.client.get(f"{URL}{id}/", format="json")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data, expected.data)
|
||||
|
||||
def test_create_signup(self):
|
||||
new = createSignupJSON(self.signupForm.id, ALL_QUESTION_TYPES_ANSWER)
|
||||
response = self.client.post(URL, new, format="json")
|
||||
print(response.data)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(Signup.objects.count(), 3)
|
||||
|
||||
def test_create_signup_404_or_hidden(self):
|
||||
new = createSignupJSON(3001, ALL_QUESTION_TYPES_ANSWER)
|
||||
response = self.client.post(URL, new, format="json")
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertEqual(Signup.objects.count(), 2)
|
||||
|
||||
new = createSignupJSON(self.hiddenForm.id, ALL_QUESTION_TYPES_ANSWER)
|
||||
response = self.client.post(URL, new, format="json")
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertEqual(Signup.objects.count(), 2)
|
||||
|
||||
@skip("NotImplemented")
|
||||
def test_get_hidden_forms_admin(self):
|
||||
pass
|
||||
|
||||
@skip("NotImplemented")
|
||||
def test_create_malformed_answer(self):
|
||||
response = self.client.post(URL, createSignupJSON(self.signupForm.id, []), format="json")
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
# Update and Delete are available for super admin (Django Admin)
|
||||
# and to the user that signed up (uid token)
|
||||
@skip("NotImplemented")
|
||||
def test_update_signup_token(self):
|
||||
pass
|
||||
|
||||
@skip("NotImplemented")
|
||||
def test_delete_signup_token(self):
|
||||
pass
|
||||
@@ -0,0 +1,79 @@
|
||||
from django.test import TestCase
|
||||
from django.contrib.auth.models import User
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase, APIRequestFactory, force_authenticate
|
||||
|
||||
from webapp.models import Tag
|
||||
from webapp.serializers import TagSerializer
|
||||
|
||||
|
||||
from webapp.tests.tag_fixture import tagBuilder, createTagIcon
|
||||
|
||||
|
||||
class TagsTestCase(APITestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.icon = createTagIcon()
|
||||
tag = tagBuilder("Party", icon=self.icon)
|
||||
self.tag_id = tag.id
|
||||
|
||||
tagBuilder("Off")
|
||||
self.assertEqual(Tag.objects.count(), 2)
|
||||
|
||||
username, password = 'test_admin', 'password123'
|
||||
self.authClient = User.objects.create_superuser(username, 'myemail@test.com', password)
|
||||
|
||||
def test_get_multiple_tags(self):
|
||||
tagBuilder("Fuksi")
|
||||
tagBuilder("Inter")
|
||||
|
||||
expected = TagSerializer(
|
||||
Tag.objects.all(), many=True,
|
||||
context={
|
||||
"request": APIRequestFactory().get(r"http://testserver/api/events/")
|
||||
}).data
|
||||
|
||||
response = self.client.get('/api/tags/', format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(len(response.data['results']), 4)
|
||||
|
||||
self.assertEqual(
|
||||
response.data['results'],
|
||||
expected
|
||||
)
|
||||
|
||||
def test_get_single_tag(self):
|
||||
response = self.client.get(f"/api/tags/{self.tag_id}/", format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
serializer = TagSerializer(
|
||||
Tag.objects.get(id=self.tag_id),
|
||||
context={
|
||||
"request": APIRequestFactory().get(r"http://testserver/api/events/")
|
||||
})
|
||||
self.assertEqual(response.data, serializer.data)
|
||||
|
||||
def test_get_invalid_tag(self):
|
||||
response = self.client.get('/api/tags/15/', format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
|
||||
# READ ONLY API! Modify result code and count
|
||||
def test_create_tag(self):
|
||||
# Authenticate
|
||||
self.client.force_authenticate(user=self.authClient)
|
||||
response = self.client.post(
|
||||
"/api/tags/",
|
||||
{
|
||||
"slug": "Test",
|
||||
"name": "Testinimi",
|
||||
"name_fi": "Testinimi",
|
||||
"name_en": "Test name",
|
||||
"icon": self.icon
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
|
||||
# Method Not allowed!
|
||||
self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)
|
||||
# Not created
|
||||
self.assertEqual(Tag.objects.count(), 2)
|
||||
@@ -0,0 +1,80 @@
|
||||
from django.test import TestCase
|
||||
from django.contrib.auth.models import User
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase, force_authenticate
|
||||
|
||||
from webapp.models import TemplateQuestion
|
||||
from webapp.serializers import SavedQuestionsSerializer
|
||||
from webapp.tests.signup_fixture import ALL_QUESTION_TYPES
|
||||
import json
|
||||
|
||||
|
||||
class TemplateQuestionCase(APITestCase):
|
||||
def setUp(self):
|
||||
self.questions = [
|
||||
TemplateQuestion.objects.create(
|
||||
name="Testi1",
|
||||
question=ALL_QUESTION_TYPES
|
||||
),
|
||||
TemplateQuestion.objects.create(
|
||||
name="Testi2",
|
||||
question=ALL_QUESTION_TYPES
|
||||
)
|
||||
]
|
||||
|
||||
username, password = "test_admin", "password123"
|
||||
self.authClient = User.objects.create_superuser(username, "myemail@test.com", password)
|
||||
|
||||
def test_get(self):
|
||||
response = self.client.get("/api/questions/", format="json")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data["results"], SavedQuestionsSerializer(self.questions, many=True).data)
|
||||
response = self.client.get(f"/api/questions/{self.questions[0].id}/", format="json")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data, SavedQuestionsSerializer(self.questions[0]).data)
|
||||
|
||||
def test_post(self):
|
||||
new = {
|
||||
"name": "testi3",
|
||||
"question": json.dumps(ALL_QUESTION_TYPES)
|
||||
}
|
||||
response = self.client.post("/api/questions/", new, format="json")
|
||||
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
self.assertEqual(TemplateQuestion.objects.count(), 2)
|
||||
|
||||
# Authenticate
|
||||
self.client.force_authenticate(user=self.authClient)
|
||||
response = self.client.post("/api/questions/", new, format="json")
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(TemplateQuestion.objects.count(), 3)
|
||||
|
||||
def test_update(self):
|
||||
new = {
|
||||
"name": "uusi testi2",
|
||||
"question": json.dumps({})
|
||||
}
|
||||
response = self.client.put(f"/api/questions/{self.questions[0].id}/", new, format="json")
|
||||
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
self.assertEqual(TemplateQuestion.objects.count(), 2)
|
||||
|
||||
# Authenticate
|
||||
self.client.force_authenticate(user=self.authClient)
|
||||
response = self.client.put(f"/api/questions/{self.questions[0].id}/", new, format="json")
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(TemplateQuestion.objects.count(), 2)
|
||||
self.assertEqual(
|
||||
TemplateQuestion.objects.get(id=self.questions[0].id).name,
|
||||
"uusi testi2"
|
||||
)
|
||||
|
||||
def test_delete(self):
|
||||
response = self.client.delete(f"/api/questions/{self.questions[0].id}/", format="json")
|
||||
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
self.assertEqual(TemplateQuestion.objects.count(), 2)
|
||||
|
||||
# Authenticate
|
||||
self.client.force_authenticate(user=self.authClient)
|
||||
response = self.client.delete(f"/api/questions/{self.questions[0].id}/", format="json")
|
||||
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
||||
self.assertEqual(TemplateQuestion.objects.count(), 1)
|
||||
@@ -1,8 +1,7 @@
|
||||
"""Translation classes."""
|
||||
|
||||
from modeltranslation.translator import register, TranslationOptions
|
||||
from webapp.models import BaseFeed, Feed, Tag, Event, Signup, SignupForm, TemplateQuestion
|
||||
from webapp.models import PresetRole, BaseRole
|
||||
from webapp.models import *
|
||||
|
||||
|
||||
@register(BaseFeed)
|
||||
@@ -66,3 +65,10 @@ class PresetRoleTranslationOptions(TranslationOptions):
|
||||
"""Class for PresetRole translation options."""
|
||||
|
||||
fields = ('description',)
|
||||
|
||||
|
||||
@register(Committee)
|
||||
class CommitteeTranslationOptions(TranslationOptions):
|
||||
"""Class for PresetRole translation options."""
|
||||
|
||||
fields = ('name',)
|
||||
|
||||
+4
-55
@@ -3,25 +3,10 @@
|
||||
from django.conf.urls import url, include
|
||||
from rest_framework import routers
|
||||
from rest_framework_jwt.views import obtain_jwt_token, verify_jwt_token
|
||||
from webapp.views import about_view, nginx_jwt_resp
|
||||
|
||||
# from rest_framework.urlpatterns import format_suffix_patterns
|
||||
# from django.conf import settings
|
||||
# from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
# from webapp.views import main_index
|
||||
# from webapp.views import login_view
|
||||
# from webapp.views import logout_view
|
||||
from webapp.views import about_view
|
||||
# from webapp.views import guild_view
|
||||
# from webapp.views import freshmen_view
|
||||
# from webapp.views import jobs_view
|
||||
# from webapp.views import event_calendar_view
|
||||
# from webapp.views import international_view
|
||||
# from webapp.views import sosso_view
|
||||
# from webapp.views import contact_view
|
||||
|
||||
from webapp.views import EventViewSet, SignupFormViewSet, SignupViewSet,\
|
||||
FeedViewSet, ContactsViewSet, SavedQuestionsViewSet, RootView, TagsViewSet
|
||||
from webapp.views import *
|
||||
|
||||
|
||||
class APIRouter(routers.DefaultRouter):
|
||||
@@ -34,6 +19,7 @@ router.register(r'signupForm', SignupFormViewSet)
|
||||
router.register(r'signup', SignupViewSet)
|
||||
router.register(r'feed', FeedViewSet)
|
||||
router.register(r'contacts', ContactsViewSet)
|
||||
router.register(r'committees', CommitteeViewSet)
|
||||
router.register(r'questions', SavedQuestionsViewSet)
|
||||
router.register(r'tags', TagsViewSet)
|
||||
|
||||
@@ -41,44 +27,7 @@ urlpatterns = [
|
||||
url(r'^api/', include(router.urls)),
|
||||
url(r'^api/api-token-auth/', obtain_jwt_token),
|
||||
url(r'^api/api-token-verify/', verify_jwt_token),
|
||||
|
||||
# login stuff
|
||||
# url(r'^login$', login_view),
|
||||
# url(r'^logout$', logout_view),
|
||||
|
||||
# git revision
|
||||
url(r'^about', about_view),
|
||||
url(r'^jwt_nginx', nginx_jwt_resp),
|
||||
]
|
||||
# urlpatterns = [
|
||||
# # main
|
||||
# url(r'^$', main_index),
|
||||
# url(r'^api/events/$', EventList.as_view(), name='event-list'),
|
||||
# url(r'^api/events/(?P<pk>[0-9]+)/$', EventDetail.as_view(), name='event-detail'),
|
||||
# url(r'^api/signup/$', SignupFormList.as_view(), name='signupform-list'),
|
||||
# url(r'^api/signup/(?P<pk>[0-9]+)/$', SignupFormDetail.as_view(), name='signup-detail'),
|
||||
|
||||
# url(r'^api/signup/create$', SignupFormCreate.as_view(), name='signupform-create'),
|
||||
|
||||
# # url(r'^signupform/$', SignupFormList.as_view(), name='signupform-list'),
|
||||
# # url(r'^signupform/(?P<pk>[0-9]+)/$', SignupFormDetail.as_view(), name='signupform-detail'),
|
||||
|
||||
# # login stuff
|
||||
# url(r'^login$', login_view),
|
||||
# url(r'^logout$', logout_view),
|
||||
|
||||
# # pages
|
||||
# url(r'^guild', guild_view),
|
||||
# url(r'^freshmen', freshmen_view),
|
||||
# url(r'^event_calendar', event_calendar_view),
|
||||
# url(r'^international', international_view),
|
||||
# url(r'^sosso', sosso_view),
|
||||
# url(r'^contact', contact_view),
|
||||
|
||||
# # corporate
|
||||
# url(r'^jobs', jobs_view),
|
||||
# ]
|
||||
|
||||
|
||||
# if settings.DEBUG:
|
||||
# from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
||||
# urlpatterns += staticfiles_urlpatterns()
|
||||
|
||||
+69
-84
@@ -1,29 +1,24 @@
|
||||
"""Webapp views."""
|
||||
|
||||
# from django.db.models import Count
|
||||
from django.shortcuts import render, redirect
|
||||
from django.contrib.auth import login, logout, authenticate
|
||||
import jwt
|
||||
from django.utils import timezone
|
||||
from dealer.git import git
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import authenticate
|
||||
from django.http import HttpResponseBadRequest, HttpResponse
|
||||
from django.shortcuts import redirect, render
|
||||
from django.views.decorators.http import require_http_methods
|
||||
# from django.views.decorators.csrf import ensure_csrf_cookie
|
||||
# from django.http import HttpResponse, HttpResponseRedirect
|
||||
# from django.contrib.auth.decorators import permission_required, login_required
|
||||
# from django.conf import settings
|
||||
# from django.utils import timezone
|
||||
from rest_framework import viewsets, routers
|
||||
from django_filters import rest_framework as filters
|
||||
from rest_framework import permissions, routers, viewsets
|
||||
from rest_framework.filters import OrderingFilter, SearchFilter
|
||||
from rest_framework.permissions import IsAuthenticatedOrReadOnly
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.reverse import reverse
|
||||
from django_filters import rest_framework as filters
|
||||
from rest_framework.filters import SearchFilter, OrderingFilter
|
||||
from rest_framework import permissions
|
||||
# import logging
|
||||
# import requests
|
||||
from dealer.git import git
|
||||
|
||||
from webapp.models import Event, SignupForm, Signup, TemplateQuestion, Feed,\
|
||||
Committee, Official, Tag
|
||||
from webapp.serializers import *
|
||||
from members.views.utils import *
|
||||
from webapp.models import Event, SignupForm, Signup, TemplateQuestion, Feed, Committee, Occupation, Tag
|
||||
from webapp.serializers import (EventSerializer, SignupFormSerializer, SignupSerializer,
|
||||
SavedQuestionsSerializer, FeedSerializer, CommitteeSerializer,
|
||||
OccupationSerializer, TagSerializer)
|
||||
|
||||
|
||||
class IsPostOrIsAuthenticated(permissions.BasePermission):
|
||||
@@ -41,6 +36,7 @@ class RootView(routers.APIRootView):
|
||||
|
||||
class EventViewSet(viewsets.ModelViewSet):
|
||||
queryset = Event.objects.all()
|
||||
ordering = ["start_time"]
|
||||
serializer_class = EventSerializer
|
||||
permission_classes = [IsAuthenticatedOrReadOnly]
|
||||
filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter)
|
||||
@@ -48,22 +44,27 @@ class EventViewSet(viewsets.ModelViewSet):
|
||||
search_fields = '__all__'
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_authenticated:
|
||||
return Event.objects.all()
|
||||
|
||||
since = self.request.query_params.get('since', None)
|
||||
if since:
|
||||
return Event.objects.filter(visible=True, end_time__gt=since).order_by('start_time')
|
||||
|
||||
return Event.objects.filter(visible=True).order_by('start_time')
|
||||
return Event.objects.filter(visible=True, end_time__gt=timezone.now()).order_by('start_time')
|
||||
|
||||
|
||||
class SignupFormViewSet(viewsets.ModelViewSet):
|
||||
queryset = SignupForm.objects.all()
|
||||
serializer_class = SignupFormSerializer
|
||||
permission_classes = [IsAuthenticatedOrReadOnly]
|
||||
filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter)
|
||||
filter_fields = '__all__'
|
||||
search_fields = '__all__'
|
||||
# Throws errors with JSONFIeld. Modify __all__ to not use JSONField if filters are enadbled
|
||||
# filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter)
|
||||
# filter_fields = '__all__'
|
||||
# search_fields = '__all__'
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_authenticated:
|
||||
return SignupForm.objects.all().order_by('start_time')
|
||||
return SignupForm.objects.filter(visible=True, end_time__gt=timezone.now()).order_by('start_time')
|
||||
|
||||
|
||||
@@ -75,8 +76,18 @@ class SignupViewSet(viewsets.ModelViewSet):
|
||||
# filter_fields = '__all__'
|
||||
# search_fields = '__all__'
|
||||
|
||||
# def get_queryset(self):
|
||||
# return Signup.objects.filter(visible=True, end_time__gt=timezone.now()).order_by('start_time')
|
||||
def create(self, request, *args, **kwargs):
|
||||
try:
|
||||
form = SignupForm.objects.get(id=request.data["signupForm_id"])
|
||||
if (form.visible):
|
||||
return super().create(request, *args, **kwargs)
|
||||
except:
|
||||
return HttpResponseBadRequest()
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
return super().update(request, *args, **kwargs)
|
||||
|
||||
|
||||
class SavedQuestionsViewSet(viewsets.ModelViewSet):
|
||||
@@ -94,7 +105,10 @@ class FeedViewSet(viewsets.ModelViewSet):
|
||||
search_fields = '__all__'
|
||||
|
||||
def get_queryset(self):
|
||||
objs = Feed.objects.filter(visible=True).order_by('publish_time')
|
||||
if self.request.user.is_authenticated:
|
||||
return Feed.objects.all().order_by('publish_time')
|
||||
else:
|
||||
objs = Feed.objects.filter(visible=True).order_by('publish_time')
|
||||
|
||||
result_ids = []
|
||||
for obj in objs:
|
||||
@@ -108,8 +122,20 @@ class FeedViewSet(viewsets.ModelViewSet):
|
||||
|
||||
|
||||
class ContactsViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
queryset = Official.objects.all()
|
||||
serializer_class = ContactsSerializer
|
||||
queryset = Occupation.objects.all()
|
||||
serializer_class = OccupationSerializer
|
||||
permission_classes = [IsAuthenticatedOrReadOnly]
|
||||
|
||||
def get_queryset(self):
|
||||
year = self.request.query_params.get('year')
|
||||
if not year:
|
||||
return Occupation.by_year(timezone.now().year)
|
||||
return Occupation.by_year(int(year))
|
||||
|
||||
|
||||
class CommitteeViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
queryset = Committee.objects.all()
|
||||
serializer_class = CommitteeSerializer
|
||||
permission_classes = [IsAuthenticatedOrReadOnly]
|
||||
|
||||
|
||||
@@ -119,14 +145,6 @@ class TagsViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
permission_classes = [IsAuthenticatedOrReadOnly]
|
||||
|
||||
|
||||
# -- OLD CODEBASE -- #
|
||||
|
||||
@require_http_methods(["GET"])
|
||||
def main_index(request, *args, **kwargs):
|
||||
"""Render main page."""
|
||||
return render(request, "index.html", {})
|
||||
|
||||
|
||||
@require_http_methods(["GET"])
|
||||
def about_view(request, *args, **kwargs):
|
||||
"""Render about page."""
|
||||
@@ -138,8 +156,8 @@ def about_view(request, *args, **kwargs):
|
||||
latest_commit = repo.git("rev-parse HEAD").decode('utf-8')
|
||||
latest_date = repo.git("show -s --format=%ci " + latest_commit).decode('utf-8')
|
||||
latest_tag = repo.git("describe --tags " + repo.git("rev-list --tags --max-count=1").decode('utf-8')).decode('utf-8')
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
print(f"Git failed:\n{e}")
|
||||
|
||||
context = {
|
||||
'commit': latest_commit,
|
||||
@@ -150,48 +168,15 @@ def about_view(request, *args, **kwargs):
|
||||
|
||||
|
||||
@require_http_methods(["GET"])
|
||||
def guild_view(request, *args, **kwargs):
|
||||
"""Render "Guild" page."""
|
||||
return render(request, "guild.html", {})
|
||||
|
||||
|
||||
@require_http_methods(["GET"])
|
||||
def freshmen_view(request, *args, **kwargs):
|
||||
"""Render "Freshmen" page."""
|
||||
return render(request, "freshmen.html", {})
|
||||
|
||||
|
||||
@require_http_methods(["GET"])
|
||||
def jobs_view(request, *args, **kwargs):
|
||||
"""Render "Jobs" page."""
|
||||
return render(request, "jobs.html", {})
|
||||
|
||||
|
||||
@require_http_methods(["GET"])
|
||||
def event_calendar_view(request, *args, **kwargs):
|
||||
"""Render "Event calendar" page."""
|
||||
return render(request, "event_calendar.html", {})
|
||||
|
||||
|
||||
@require_http_methods(["GET"])
|
||||
def international_view(request, *args, **kwargs):
|
||||
"""Render "International" page."""
|
||||
return render(request, "international.html", {})
|
||||
|
||||
|
||||
@require_http_methods(["GET"])
|
||||
def sosso_view(request, *args, **kwargs):
|
||||
"""Render "Sössö" page."""
|
||||
return render(request, "sosso.html", {})
|
||||
|
||||
|
||||
@require_http_methods(["GET"])
|
||||
def contact_view(request, *args, **kwargs):
|
||||
"""Render "Contact" page."""
|
||||
committees = Committee.objects.order_by('name')
|
||||
|
||||
context = {
|
||||
"committees": committees
|
||||
}
|
||||
|
||||
return render(request, "contact.html", context)
|
||||
def nginx_jwt_resp(request, *args, **kwargs):
|
||||
cookie = request.COOKIES.get("jwt", None)
|
||||
if not cookie:
|
||||
return HttpResponse("", status=401)
|
||||
try:
|
||||
token = jwt.decode(cookie, settings.SECRET_KEY)
|
||||
except jwt.exceptions.InvalidSignatureError:
|
||||
return HttpResponse("", status=403)
|
||||
user = 'admin' if token.get('username', '') == 'admin' else 'moderator'
|
||||
resp = HttpResponse("", status=200)
|
||||
resp['X-FBrowser-User'] = user
|
||||
return resp
|
||||
|
||||
Reference in New Issue
Block a user