Merge branch 'simpleauth'

This commit is contained in:
Benni Bärmann 2021-05-06 16:19:58 +02:00
commit 54881f9b8b
24 changed files with 591 additions and 59 deletions

7
.gitignore vendored
View File

@ -1,3 +1,10 @@
# secret passwords and so
/secrets.json
/staticfiles
/eva/settings.py
/nohup.out
/logfile
*~ *~
# ---> Python # ---> Python

View File

@ -23,3 +23,30 @@ environment managing tool
- start your development server with - start your development server with
python manage.py runserver python manage.py runserver
# production
- you can use gunicorn as server for example instead of the django development server.
- we use whitenoise for serving static files
- we still use the development SQLITE database from django
do the following in the project main directory:
ln -sr eva/settings_production.py eva/settings.py
edit /secrets.json to contain something similar to
{
"SECRET_KEY": "THIS IS ANOTHER SECRET!"
}
run the following commands:
python3 manage.py migrate
python3 manage.py collectstatic
server starts with
nohup gunicorn --forwarded-allow-ips="*" -b '0:8000' eva.wsgi 2&> logfile &

3
TODO
View File

@ -1,3 +0,0 @@
known bugs:
html problem in mails: 14" -> 14"

View File

@ -27,6 +27,9 @@ SECRET_KEY = 'g%+i6+gkwt3zz@+k-5x1dtstuw4)&qd$lxd^bt2oswy5e1#dul'
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True DEBUG = True
# send mails only to debug mode adress even if in production
MAILTEST = True
STATIC_ROOT = BASE_DIR / 'staticfiles' STATIC_ROOT = BASE_DIR / 'staticfiles'
ALLOWED_HOSTS = ['*'] ALLOWED_HOSTS = ['*']
@ -54,6 +57,7 @@ INSTALLED_APPS = [
MIDDLEWARE = [ MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfViewMiddleware',

159
eva/settings_production.py Normal file
View File

@ -0,0 +1,159 @@
"""
Django settings for eva project.
Generated by 'django-admin startproject' using Django 3.1.4.
For more information on this file, see
https://docs.djangoproject.com/en/3.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.1/ref/settings/
"""
import json
import os
from pathlib import Path
from django.core.exceptions import ImproperlyConfigured
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# mails in production goes to mailserver
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = '10.0.6.25'
EMAIL_PORT = '25'
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# get secrets
with open(os.path.join(BASE_DIR, 'secrets.json')) as secrets_file:
secrets = json.load(secrets_file)
def get_secret(setting, secrets=secrets):
"""Get secret setting or fail with ImproperlyConfigured"""
try:
return secrets[setting]
except KeyError:
raise ImproperlyConfigured("Set the {} setting".format(setting))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = get_secret('SECRET_KEY')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
# send mails only to debug mode adress even if in production
MAILTEST = True
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
# SECRET_KEY = 'g%+i6+gkwt3zz@+k-5x1dtstuw4)&qd$lxd^bt2oswy5e1#dul'
STATIC_ROOT = BASE_DIR / 'staticfiles'
ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
'evapp.apps.EvappConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'multiselectfield',
'formtools',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'eva.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'eva.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/
STATIC_URL = '/static/'

View File

@ -29,7 +29,7 @@ class PersonalForm(EvaForm):
class Meta: class Meta:
model = Employee model = Employee
fields = ['firstname', 'lastname', 'intern', 'email', 'department', 'team', ] fields = ['usermail', 'firstname', 'lastname', 'intern', 'department', 'team', ]
class WorkingForm(EvaForm): class WorkingForm(EvaForm):
@ -50,7 +50,7 @@ class ITForm(EvaForm):
class Meta: class Meta:
model = Employee model = Employee
fields = [ fields = [
'laptop', 'vendor', 'os', 'screen', 'mobile', 'landline', 'comment', 'vendor', 'os', 'keyboard', 'screen', 'mobile', 'sim', 'comment',
'language', 'accounts', 'lists', 'rebu2go' ] 'language', 'accounts', 'lists', 'rebu2go' ]
class OfficeForm(EvaForm): class OfficeForm(EvaForm):

View File

@ -0,0 +1,28 @@
# Generated by Django 3.1.4 on 2021-03-15 14:08
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evapp', '0008_auto_20210301_1053'),
]
operations = [
migrations.AddField(
model_name='employee',
name='usermail',
field=models.EmailField(default='bestechefin@wikimedia.de', max_length=50, verbose_name='Deine Mailadresse'),
),
migrations.AlterField(
model_name='employee',
name='email',
field=models.EmailField(max_length=50, verbose_name='E-Mail-Adresse ders Mitarbeitenden'),
),
migrations.AlterField(
model_name='employee',
name='laptop',
field=models.CharField(choices=[('14', '14", Unser Standardgerät'), ('12', '12,5", Geeignet für Vielreisende')], default='14', max_length=2),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.1.4 on 2021-03-25 08:13
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evapp', '0009_auto_20210315_1408'),
]
operations = [
migrations.AlterField(
model_name='employee',
name='jobdescription_german',
field=models.CharField(max_length=100, null=True, verbose_name='Stellenbezeichnung(deutsch)'),
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 3.1.4 on 2021-03-29 12:54
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evapp', '0010_auto_20210325_0813'),
]
operations = [
migrations.AddField(
model_name='employee',
name='sim',
field=models.BooleanField(default=False, verbose_name='Mobilfunkvertrag'),
),
migrations.AddField(
model_name='employee',
name='sim2',
field=models.BooleanField(default=False, verbose_name='Zweite Sim (für Laptop zB)'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.1.4 on 2021-03-30 08:25
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evapp', '0011_auto_20210329_1254'),
]
operations = [
migrations.AddField(
model_name='employee',
name='bvg',
field=models.BooleanField(default=True, verbose_name='Bekommt eine BVG-Karte, weil in Berlin tätig'),
),
]

View File

@ -0,0 +1,17 @@
# Generated by Django 3.1.4 on 2021-04-01 08:30
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('evapp', '0012_employee_bvg'),
]
operations = [
migrations.RemoveField(
model_name='employee',
name='bvg',
),
]

View File

@ -0,0 +1,38 @@
# Generated by Django 3.1.4 on 2021-05-04 08:42
from django.db import migrations, models
import multiselectfield.db.fields
class Migration(migrations.Migration):
dependencies = [
('evapp', '0013_remove_employee_bvg'),
]
operations = [
migrations.RemoveField(
model_name='employee',
name='sim2',
),
migrations.AlterField(
model_name='employee',
name='accounts',
field=multiselectfield.db.fields.MultiSelectField(blank=True, choices=[('OTRSWMDE', 'OTRS Ticketsystem'), ('CIVIC1', 'Civic CRM (allgemein)'), ('CIVIC2', 'Civic CRM (Mailings, impliziert allgemein)'), ('WEB', 'www.wikimedia.de (edit)'), ('BLOG', 'blog.wikimedia.de (edit)'), ('FORUM', 'forum.wikimedia.de')], max_length=37, null=True, verbose_name='Zusätzliche Accounts'),
),
migrations.AlterField(
model_name='employee',
name='lists',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Zusätzliche Mailinglisten'),
),
migrations.AlterField(
model_name='employee',
name='mobile',
field=models.BooleanField(default=False, max_length=6, verbose_name='Handy benötigt?'),
),
migrations.AlterField(
model_name='employee',
name='vendor',
field=models.CharField(choices=[('STANDARD', 'Dell Latitude'), ('LENOVO', 'Lenovo Thinkpad'), ('MAC', 'Mac (nur in Ausnahmefällen)')], default='STANDARD', max_length=8, verbose_name='Hersteller'),
),
]

View File

@ -0,0 +1,17 @@
# Generated by Django 3.1.4 on 2021-05-04 09:43
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('evapp', '0014_auto_20210504_0842'),
]
operations = [
migrations.RemoveField(
model_name='employee',
name='email',
),
]

View File

@ -0,0 +1,27 @@
# Generated by Django 3.1.4 on 2021-05-04 10:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evapp', '0015_remove_employee_email'),
]
operations = [
migrations.RemoveField(
model_name='employee',
name='landline',
),
migrations.AddField(
model_name='employee',
name='keyboard',
field=models.CharField(choices=[('DE', 'Deutsch'), ('US', 'USA'), ('OT', 'Anderes (Bitte unten angeben)')], default='DE', max_length=2, verbose_name='Tastaturlayout'),
),
migrations.AlterField(
model_name='employee',
name='department',
field=models.CharField(choices=[('PROG', 'Programme'), ('SOFT', 'Softwareentwicklung'), ('CENT', 'Central'), ('VOR', 'Vorstand')], max_length=5, verbose_name='Bereich'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.1.4 on 2021-05-04 12:24
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evapp', '0016_auto_20210504_1040'),
]
operations = [
migrations.AlterField(
model_name='employee',
name='os',
field=models.CharField(choices=[('UBU', 'Ubuntu (Standard)'), ('WIN', 'Windows (bitte Begründung angeben)')], default='UBU', max_length=3, verbose_name='Betriebssystem'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.1.4 on 2021-05-04 12:51
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evapp', '0017_auto_20210504_1224'),
]
operations = [
migrations.AlterField(
model_name='employee',
name='usermail',
field=models.EmailField(default='bestechefin@wikimedia.de', max_length=50, verbose_name='Deine Mailadresse (Ansprechpartner_in)'),
),
]

View File

@ -0,0 +1,22 @@
# Generated by Django 3.1.4 on 2021-05-04 13:33
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evapp', '0018_auto_20210504_1251'),
]
operations = [
migrations.RemoveField(
model_name='employee',
name='laptop',
),
migrations.AlterField(
model_name='employee',
name='vendor',
field=models.CharField(choices=[('STANDARD', 'Dell Latitude'), ('LENOVO', 'Lenovo Thinkpad'), ('MAC', 'Mac (nur für Grafiker_innen)')], default='STANDARD', max_length=8, verbose_name='Hersteller'),
),
]

View File

@ -11,28 +11,24 @@ DEPARTMENT_CHOICES = {'PROG': 'Programme',
'CENT': 'Central', 'CENT': 'Central',
'VOR': 'Vorstand',} 'VOR': 'Vorstand',}
LAPTOP_CHOICES = {'14': '14", Unser Standardgerät',
'12': '12,5", Geeignet für Vielreisende',}
VENDOR_CHOICES = {'STANDARD': 'Dell Latitude', VENDOR_CHOICES = {'STANDARD': 'Dell Latitude',
'LENOVO': 'Lenovo Thinkpad', 'LENOVO': 'Lenovo Thinkpad',
'MAC': 'Mac (nur in Ausnahmefällen)'} 'MAC': 'Mac (nur für Grafiker_innen)'}
OS_CHOICES = {'UBU': 'Ubuntu (Standard)', OS_CHOICES = {'UBU': 'Ubuntu (Standard)',
'WIN': 'Windows (bitte Begründung angeben)',} 'WIN': 'Windows (bitte Begründung angeben)',}
MOBILE_CHOICES = {'NO': 'Kein Mobiltelefon',
'SIMPLE': 'Einfaches Gerät für Erreichbarkeit',
'SINGLE': 'Smartphone, Single SIM',
'DUAL': 'Smartphone, Dual SIM',}
LANG_CHOICES = {'GER': 'Deutsch', LANG_CHOICES = {'GER': 'Deutsch',
'ENG': 'English',} 'ENG': 'English',}
KEYBOARD_CHOICES = {'DE': 'Deutsch',
'US': 'USA',
'OT': 'Anderes (Bitte unten angeben)'}
ACCOUNT_CHOICES = {'OTRSWMDE': 'OTRS Ticketsystem', ACCOUNT_CHOICES = {'OTRSWMDE': 'OTRS Ticketsystem',
'CIVIC1': 'Civic CRM (allgemein)', 'CIVIC1': 'Civic CRM (allgemein)',
'CIVIC2': "Civic CRM (Mailings, impliziert allgemein)", 'CIVIC2': "Civic CRM (Mailings, impliziert allgemein)",
'ZEDA': "Zeda Nextcloud",
'WEB': 'www.wikimedia.de (edit)', 'WEB': 'www.wikimedia.de (edit)',
'BLOG': 'blog.wikimedia.de (edit)', 'BLOG': 'blog.wikimedia.de (edit)',
'FORUM': 'forum.wikimedia.de', 'FORUM': 'forum.wikimedia.de',
@ -43,33 +39,36 @@ TRANSPONDER_CHOICES = {'NORM': 'Allgemeiner Transponder',
'NOTRANS': 'Kein Transponder',} 'NOTRANS': 'Kein Transponder',}
class Employee(models.Model): class Employee(models.Model):
# email adress of user. should not be necessary if we use openauth one day
usermail = models.EmailField(max_length=50, verbose_name="Deine Mailadresse (Ansprechpartner_in)", default='bestechefin@wikimedia.de')
# personal data # personal data
firstname = models.CharField(max_length=50, verbose_name="Vorname") firstname = models.CharField(max_length=50, verbose_name="Vorname")
lastname = models.CharField(max_length=50, verbose_name="Nachname") lastname = models.CharField(max_length=50, verbose_name="Nachname")
intern = models.BooleanField(verbose_name='Interne_r Mitarbeiter_in?', default=True) intern = models.BooleanField(verbose_name='Interne_r Mitarbeiter_in?', default=True)
email = models.EmailField(max_length=50, verbose_name="E-Mail-Adresse") department = models.CharField(max_length=5, choices=DEPARTMENT_CHOICES.items(), verbose_name='Bereich')
department = models.CharField(max_length=5, choices=DEPARTMENT_CHOICES.items()) team = models.CharField(max_length=20, null=True, blank=True) # TODO? better with choices?
team = models.CharField(max_length=20, null=True, blank=True) # TODO? besser als choices?
# general work related stuff # general work related stuff
firstdate_employment = models.DateField(null=True, verbose_name="Erster Arbeitstag") firstdate_employment = models.DateField(null=True, verbose_name="Erster Arbeitstag")
firstdate_presence = models.DateField(null=True, verbose_name="Erster Tag der Anwesenheit in der Geschäftsstelle") firstdate_presence = models.DateField(null=True, verbose_name="Erster Tag der Anwesenheit in der Geschäftsstelle")
jobdescription_german = models.CharField(null=True, max_length=100, verbose_name="Stellenbeschreibung(deutsch)") jobdescription_german = models.CharField(null=True, max_length=100, verbose_name="Stellenbezeichnung(deutsch)")
jobdescription_english = models.CharField(null=True, max_length=100, verbose_name="Job description(english)") jobdescription_english = models.CharField(null=True, max_length=100, verbose_name="Job description(english)")
remote = models.BooleanField(verbose_name='Braucht keinen Arbeitsplatz weil Home-Office', default=False) remote = models.BooleanField(verbose_name='Braucht keinen Arbeitsplatz weil Home-Office', default=False)
desk = models.CharField(max_length=100, null=True, blank=True, verbose_name="Wo soll der Arbeitsplatz sein?") desk = models.CharField(max_length=100, null=True, blank=True, verbose_name="Wo soll der Arbeitsplatz sein?")
# IT related stuff # IT related stuff
laptop = models.CharField(max_length=2, choices=LAPTOP_CHOICES.items(), default='14') vendor = models.CharField(max_length=8, choices=VENDOR_CHOICES.items(), default='STANDARD', verbose_name='Hersteller')
vendor = models.CharField(max_length=8, choices=VENDOR_CHOICES.items(), default='STANDARD') os = models.CharField(max_length=3, choices=OS_CHOICES.items(), default='UBU', verbose_name='Betriebssystem')
os = models.CharField(max_length=3, choices=OS_CHOICES.items(), default='UBU')
screen = models.BooleanField(default=False, verbose_name='Zusätzlicher Monitor? Einer ist standard.') screen = models.BooleanField(default=False, verbose_name='Zusätzlicher Monitor? Einer ist standard.')
mobile = models.CharField(max_length=6, default='NO') mobile = models.BooleanField(max_length=6, default=False, verbose_name='Handy benötigt?')
landline = models.BooleanField(default=True, verbose_name="Festnetztelefon") sim = models.BooleanField(default=False, verbose_name="Mobilfunkvertrag")
keyboard = models.CharField(max_length=2, choices=KEYBOARD_CHOICES.items(), default='DE', verbose_name="Tastaturlayout")
comment = models.TextField(max_length=500, null=True, blank=True, verbose_name="zusätzliche IT-Anforderungen") comment = models.TextField(max_length=500, null=True, blank=True, verbose_name="zusätzliche IT-Anforderungen")
language = models.CharField(max_length=3, choices=LANG_CHOICES.items(), default="GER") language = models.CharField(max_length=3, choices=LANG_CHOICES.items(), default="GER")
accounts = MultiSelectField(choices=ACCOUNT_CHOICES.items(), null=True) accounts = MultiSelectField(choices=ACCOUNT_CHOICES.items(), null=True, blank=True, verbose_name="Zusätzliche Accounts")
lists = models.CharField(max_length=100, null=True) lists = models.CharField(max_length=100, null=True, blank=True, verbose_name="Zusätzliche Mailinglisten")
rebu2go = models.BooleanField(verbose_name="Rebu2Go-Zugang benötigt?", default=False) rebu2go = models.BooleanField(verbose_name="Rebu2Go-Zugang benötigt?", default=False)
# office related stuff # office related stuff

View File

@ -1,22 +1,52 @@
# temporary setting while change and exit is not yet fully implemented # temporary setting while change and exit is not yet fully implemented
ONLY_ONBOARDING = True ONLY_ONBOARDING = True
# sender mail adress # sender mail adress also used for MAILTEST mode
EVA_MAIL = 'benni.baermann@wikimedia.de' EVA_MAIL = 'benni.baermann@wikimedia.de'
# these Fields should be included in every mail # these Fields should be included in every mail
BASIC_DATA = ['firstname', 'lastname'] BASIC_DATA = ['usermail', 'firstname', 'lastname', 'firstdate_employment', 'firstdate_presence',]
# for every department: 'MAIL' => mail adress, 'DATA': additional fields to include # for every department: 'MAIL' => mail adress, 'DATA': additional fields to include
MAILS = {'IT': { MAILS = {
'MAIL': 'it@wikimedia.de', 'IT': {
'DATA': ['laptop', 'os', 'email'], 'MAIL': 'wmde-it@wikimedia.de',
}, 'DATA': [
'OFFICE': { 'laptop', 'os', 'comment', 'email', 'landline', 'lists', 'mobile',
'MAIL': 'office@wikimedia.de', 'department', 'accounts', 'language', 'screen', 'remote', 'desk',
'DATA': ['transponder',], ],
}, },
'ACCOUNTING': {'MAIL': 'accounting@wikimedia.de', 'OFFICE': {
'DATA': ['rebu2go',], 'MAIL': 'office@wikimedia.de',
} 'DATA': [
'transponder', 'special', 'post_office_box', 'sim', 'sim2',
'remote', 'desk',
],
},
'KOMM': {
'MAIL': 'presse@wikimedia.de',
'DATA': [
'department', 'team',
'jobdescription_german', 'jobdescription_english',
],
},
'CENTRAL': {
'MAIL': 'eileen.miedtank@wikimedia.de',
'DATA': [
'department', 'team', 'language', 'sim', 'sim2', 'rebu2go'
],
},
'HR': {
'MAIL': 'personal@wikimedia.de, eileen.miedtank@wikimedia.de',
'DATA': [
'department', 'team', 'language',
]
},
'DIRECTORAT': {
'MAIL': 'ricarda.busse@wikimedia.de',
'DATA': [
'team', 'department', 'language',
]
}
} }

View File

@ -1,5 +1,4 @@
{% autoescape off %} {% autoescape off %}
{% for key, value in data.items %} {% for key, value in data.items %}{% if key == 'laptop' %} {{ key }}: {{ value | safe}}{% else %}
{{ key }}: {{ value }} {{ key }}: {{ value }}{% endif %}{% endfor %}
{% endfor %}
{% endautoescape %} {% endautoescape %}

View File

@ -1,6 +1,6 @@
Hallo! Hallo!
Es gibt einen Neuzugang bei Wikimedia! Hier (<insertlink>) kannst Du nachsehen, Es gibt einen Neuzugang bei Wikimedia! Hier ( https://wiki.wikimedia.de/wiki/Onboarding ) kannst Du nachsehen,
welche Schritte jetzt für Deine Abteilung nötig werden. Im Folgenden alle Daten, welche Schritte jetzt für Deine Abteilung nötig werden. Im Folgenden alle Daten,
die Du dafür brauchst: die Du dafür brauchst:

View File

@ -30,7 +30,7 @@
<img src="{% static 'evapp/logo.png' %}" /> <img src="{% static 'evapp/logo.png' %}" />
<h1> <h1>
E V A - Eintritt, Veränderung, Austritt E (V A) - Eintritt, (Veränderung, Austritt)<p>
</h1> </h1>
<h2> <h2>
<p>Schritt {{ wizard.steps.step1 }} von {{ wizard.steps.count }}</p> <p>Schritt {{ wizard.steps.step1 }} von {{ wizard.steps.count }}</p>
@ -55,9 +55,11 @@
</p> </p>
</h2> </h2>
{% if datatable == True %} {% if datatable == True %}
<table>
{% for key, value in data.items %} {% for key, value in data.items %}
{{ key }}: {{ value }}<p> <tr><th>{{ key }}</th><th>{{ value }}</th></tr>
{% endfor %} {% endfor %}
</table>
{% endif %} {% endif %}
<form action="" method="post"> <form action="" method="post">
{% csrf_token %} {% csrf_token %}
@ -84,7 +86,11 @@
{% if wizard.steps.prev %} {% if wizard.steps.prev %}
<button formnovalidate="formnovalidate" name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">Zurück</button> <button formnovalidate="formnovalidate" name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">Zurück</button>
{% endif %} {% endif %}
<button type="submit" value="{% trans "Weiter" %}">Weiter</button> {% if datatable == True %}
<button type="submit" value="{% trans "Weiter" %}">Abschicken</button>
{% else %}
<button type="submit" value="{% trans "Weiter" %}">Weiter</button>
{% endif %}
</form> </form>
<p> <p>
</center> </center>

View File

@ -0,0 +1,35 @@
{% block content %}
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
{% if next %}
{% if user.is_authenticated %}
<p>Your account doesn't have access to this page. To proceed,
please login with an account that has access.</p>
{% else %}
<p>Please login to see this page.</p>
{% endif %}
{% endif %}
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<table>
<tr>
<td>{{ form.username.label_tag }}</td>
<td>{{ form.username }}</td>
</tr>
<tr>
<td>{{ form.password.label_tag }}</td>
<td>{{ form.password }}</td>
</tr>
</table>
<input type="submit" value="login" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
{# Assumes you setup the password_reset view in your URLconf #}
<p><a href="{% url 'password_reset' %}">Lost password?</a></p>
{% endblock %}

View File

@ -9,9 +9,10 @@ from django.template.loader import get_template
from formtools.wizard.views import CookieWizardView from formtools.wizard.views import CookieWizardView
from django.shortcuts import render from django.shortcuts import render
from django.conf import settings from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import Employee, DEPARTMENT_CHOICES, LAPTOP_CHOICES, OS_CHOICES, VENDOR_CHOICES, \ from .models import Employee, DEPARTMENT_CHOICES, OS_CHOICES, VENDOR_CHOICES, \
MOBILE_CHOICES, LANG_CHOICES, ACCOUNT_CHOICES, TRANSPONDER_CHOICES LANG_CHOICES, ACCOUNT_CHOICES, TRANSPONDER_CHOICES, KEYBOARD_CHOICES
from .forms import PersonalForm, WorkingForm, ITForm, OfficeForm, DummyForm,\ from .forms import PersonalForm, WorkingForm, ITForm, OfficeForm, DummyForm,\
ChangeForm, TYPE_CHOICES ChangeForm, TYPE_CHOICES
from .settings import MAILS, EVA_MAIL, BASIC_DATA, ONLY_ONBOARDING from .settings import MAILS, EVA_MAIL, BASIC_DATA, ONLY_ONBOARDING
@ -43,7 +44,7 @@ def change_process(wizard):
return not long_process(wizard) return not long_process(wizard)
class EvaFormView(CookieWizardView): class EvaFormView(LoginRequiredMixin, CookieWizardView):
template_name = 'evapp/employee_form.html' template_name = 'evapp/employee_form.html'
form_list = [PersonalForm, WorkingForm, ITForm, OfficeForm, ChangeForm, DummyForm] form_list = [PersonalForm, WorkingForm, ITForm, OfficeForm, ChangeForm, DummyForm]
instance = None instance = None
@ -54,17 +55,22 @@ class EvaFormView(CookieWizardView):
def set_choice(self, c): def set_choice(self, c):
self.choice = c self.choice = c
def generate_email(self, data):
(first, *_) = data['firstname'].split(maxsplit=1)
(last, *_) = data['lastname'].split(maxsplit=1)
name = first + '.' + last
if not data['intern']:
mail = name + '_ext@wikimedia.de'
else:
mail = name + '@wikimedia.de'
data['email'] = mail
def get_all_cleaned_data(self): def get_all_cleaned_data(self):
'''this method deletes data which is only used temporary and is not in the modell, '''this method deletes data which is only used temporary and is not in the modell,
it also changes the mail adress of the employee in some circumstances''' it also changes the mail adress of the employee in some circumstances'''
data = super().get_all_cleaned_data() data = super().get_all_cleaned_data()
if not data['intern']: self.generate_email(data)
print("intern employee detected")
if not data['email'].endswith('_ext'):
print('added "_ext" to mail adress')
data['email'] += '_ext'
print("delete CHOICE FROM DATA") print("delete CHOICE FROM DATA")
if 'choice' in data: if 'choice' in data:
@ -129,11 +135,19 @@ class EvaFormView(CookieWizardView):
try: try:
mail_template = get_template(f'evapp/department_mail.txt') mail_template = get_template(f'evapp/department_mail.txt')
send_mail( if settings.MAILTEST:
send_mail(
'EVA: Neuzugang', 'EVA: Neuzugang',
mail_template.render(context), mail_template.render(context),
EVA_MAIL, EVA_MAIL,
[MAILS[department]['MAIL']], [EVA_MAIL, self.instance.usermail],
fail_silently=False)
else:
send_mail(
'EVA: Neuzugang',
mail_template.render(context),
EVA_MAIL,
[MAILS[department]['MAIL'], self.instance.usermail],
fail_silently=False) fail_silently=False)
except BadHeaderError: except BadHeaderError:
self.instance.delete() self.instance.delete()
@ -150,11 +164,9 @@ class EvaFormView(CookieWizardView):
# #
''' '''
# print("BEAUTIFY")
# update values in data dictionary with keys from *_CHOICES if present there # update values in data dictionary with keys from *_CHOICES if present there
choices = {**DEPARTMENT_CHOICES, **LAPTOP_CHOICES, **TRANSPONDER_CHOICES, choices = {**DEPARTMENT_CHOICES, **TRANSPONDER_CHOICES,
**OS_CHOICES, **MOBILE_CHOICES, **LANG_CHOICES, **VENDOR_CHOICES} **OS_CHOICES, **LANG_CHOICES, **VENDOR_CHOICES, **KEYBOARD_CHOICES}
data.update({k:choices[v] for k,v in data.items() \ data.update({k:choices[v] for k,v in data.items() \
if isinstance(v,collections.abc.Hashable) \ if isinstance(v,collections.abc.Hashable) \
and v in choices}) and v in choices})
@ -164,6 +176,19 @@ class EvaFormView(CookieWizardView):
data['accounts'] = [ACCOUNT_CHOICES[c] for c in data['accounts']] data['accounts'] = [ACCOUNT_CHOICES[c] for c in data['accounts']]
# replace keys in data dictionary with verbose_name # replace keys in data dictionary with verbose_name
# a bit ugly workaround here: we need to store 'email' away, because it es not in the modell
mail = ''
if 'email' in data:
mail = data.pop('email')
newdata = {self.instance._meta.get_field(k).verbose_name.title() : v for k,v in data.items()} newdata = {self.instance._meta.get_field(k).verbose_name.title() : v for k,v in data.items()}
if mail:
newdata['Email'] = mail
# translate booleans
newdata.update({k:'Ja' for k,v in newdata.items() if isinstance(v,bool) and v == True})
newdata.update({k:'Nein' for k,v in newdata.items() if isinstance(v,bool) and v == False})
# handle some special data types
newdata.update({k:'' for k,v in newdata.items() if v == None})
newdata.update({k:'' for k,v in newdata.items() if v == []})
return newdata return newdata