Merge branch 'simpleauth'
This commit is contained in:
commit
54881f9b8b
|
@ -1,3 +1,10 @@
|
||||||
|
# secret passwords and so
|
||||||
|
/secrets.json
|
||||||
|
/staticfiles
|
||||||
|
/eva/settings.py
|
||||||
|
/nohup.out
|
||||||
|
/logfile
|
||||||
|
|
||||||
*~
|
*~
|
||||||
|
|
||||||
# ---> Python
|
# ---> Python
|
||||||
|
|
27
README.md
27
README.md
|
@ -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 &
|
||||||
|
|
|
@ -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',
|
|
@ -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/'
|
|
@ -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):
|
||||||
|
|
|
@ -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),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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)'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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)'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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',
|
||||||
|
),
|
||||||
|
]
|
|
@ -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'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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',
|
||||||
|
),
|
||||||
|
]
|
|
@ -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'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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)'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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
|
||||||
|
|
|
@ -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': [
|
||||||
|
'laptop', 'os', 'comment', 'email', 'landline', 'lists', 'mobile',
|
||||||
|
'department', 'accounts', 'language', 'screen', 'remote', 'desk',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
'OFFICE': {
|
'OFFICE': {
|
||||||
'MAIL': 'office@wikimedia.de',
|
'MAIL': 'office@wikimedia.de',
|
||||||
'DATA': ['transponder',],
|
'DATA': [
|
||||||
|
'transponder', 'special', 'post_office_box', 'sim', 'sim2',
|
||||||
|
'remote', 'desk',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
'ACCOUNTING': {'MAIL': 'accounting@wikimedia.de',
|
'KOMM': {
|
||||||
'DATA': ['rebu2go',],
|
'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',
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 %}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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 %}
|
||||||
|
{% if datatable == True %}
|
||||||
|
<button type="submit" value="{% trans "Weiter" %}">Abschicken</button>
|
||||||
|
{% else %}
|
||||||
<button type="submit" value="{% trans "Weiter" %}">Weiter</button>
|
<button type="submit" value="{% trans "Weiter" %}">Weiter</button>
|
||||||
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
<p>
|
<p>
|
||||||
</center>
|
</center>
|
||||||
|
|
|
@ -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 %}
|
|
@ -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')
|
||||||
|
if settings.MAILTEST:
|
||||||
send_mail(
|
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
|
||||||
|
|
Loading…
Reference in New Issue