2
1
Fork 0

Merge branch 'oauth_with_fix'

This commit is contained in:
Tobias Herre 2025-02-18 15:16:30 +00:00
commit c44891e7a8
16 changed files with 558 additions and 42 deletions

4
.gitignore vendored
View File

@ -2,8 +2,8 @@
/secrets.json /secrets.json
/staticfiles /staticfiles
# /foerderbarometer/settings.py # /foerderbarometer/settings.py
/foerderbarometer/*settings* # /foerderbarometer/*settings*
/foerderbarometer/input/settings.py /input/settings.py
/nohup.out /nohup.out
/logfile /logfile
*~ *~

View File

@ -35,11 +35,27 @@ entries to a csv file
## versions used in development ## versions used in development
python 3.8.2 asgiref==3.2.10
django 3.1.x (does not work with django 3.2 in the moment!) Django==3.1.2
django-formtools 2.2 django-formtools==2.4
whitenoise 5.2.0 gunicorn==20.0.4
gunicorn 20.0.4 mysqlclient==2.1.1
sqlparse==0.4.3
whitenoise==6.2.0
asgiref==3.2.10
Authlib==1.2.1
certifi==2023.7.22
cffi==1.16.0
chardet==5.2.0
charset-normalizer==3.3.0
cryptography==41.0.4
idna==3.4
pycparser==2.21
pytz==2023.3.post1
requests==2.31.0
six==1.16.0
typing_extensions==4.8.0
urllib3==2.0.6
## testing ## testing

186
foerderbarometer/settings.py Executable file
View File

@ -0,0 +1,186 @@
"""
Django settings for foerderbarometer project.
Generated by 'django-admin startproject' using Django 3.1.1.
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
# prefix for urls in mails
URLPREFIX = 'https://fdb-devel.wikimedia.de'
# mails in development go to stdout
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
#EMAIL_HOST = 'email.wikimedia.de'
#EMAIL_PORT = '587'
#EMAIL_USE_TLS = True
#EMAIL_HOST_USER = get_secret('EMAIL_HOST_USER')
#EMAIL_HOST_PASSWORD = get_secret('EMAIL_HOST_PASSWORD')
# 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 = True
STATIC_ROOT = BASE_DIR / 'staticfiles'
ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
'input.apps.InputConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'formtools',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'input.middleware.oauth.OAuthMiddleware'
]
ROOT_URLCONF = 'foerderbarometer.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 = 'foerderbarometer.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': get_secret('DATABASE_PASSWORD')
}
}
# 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/'
# needed since django 3.2
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
# OAuth Settings
OAUTH_URL_WHITELISTS = ['/admin']
OAUTH_CLIENT_NAME = '<name-of-the-configured-wikimedia-app>'
OAUTH_CLIENT_NAME = get_secret('OAUTH_CLIENT_NAME')
OAUTH_CLIENT = {
'client_id': get_secret('OAUTH_CLIENT_ID'),
'client_secret': get_secret('OAUTH_CLIENT_SECRET'),
'access_token_url': 'https://meta.wikimedia.org/w/rest.php/oauth2/access_token',
'authorize_url': 'https://meta.wikimedia.org/w/rest.php/oauth2/authorize',
'api_base_url': 'https://meta.wikimedia.org/w/rest.php/oauth2/resource',
'redirect_uri': 'https://fdb-devel.wikimedia.de/oauth/callback',
'client_kwargs': {
'scope': 'basic',
'token_placement': 'header'
},
'userinfo_endpoint': 'resource/profile',
}
OAUTH_COOKIE_SESSION_ID = 'sso_session_id'

View File

@ -36,6 +36,11 @@ class ProjectAdmin(admin.ModelAdmin):
date_hierarchy = 'end' date_hierarchy = 'end'
readonly_fields = ('end_quartal', 'project_of_year', 'pid', 'finance_id') readonly_fields = ('end_quartal', 'project_of_year', 'pid', 'finance_id')
class Media:
js = ('dropdown/js/otrs_link.js',)
@admin.register(BusinessCard) @admin.register(BusinessCard)
class BusinessCardAdmin(admin.ModelAdmin): class BusinessCardAdmin(admin.ModelAdmin):
save_as = True save_as = True

16
input/asgi.py Normal file
View File

@ -0,0 +1,16 @@
"""
ASGI config for oauth_demo project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'oauth_demo.settings')
application = get_asgi_application()

View File

@ -26,6 +26,9 @@ class ProjectForm(FdbForm):
widgets = {'start': AdminDateWidget(), widgets = {'start': AdminDateWidget(),
'end': AdminDateWidget(),} 'end': AdminDateWidget(),}
class Media:
js = ('dropdown/js/otrs_link.js',)
class ExternForm(FdbForm): class ExternForm(FdbForm):
@ -38,7 +41,7 @@ class ExternForm(FdbForm):
class Meta: class Meta:
model = ConcreteExtern model = ConcreteExtern
exclude = ('granted', 'granted_date', 'survey_mail_send', 'service_id', 'survey_mail_date', 'mail_state') exclude = ('username', 'granted', 'granted_date', 'survey_mail_send', 'service_id', 'survey_mail_date', 'mail_state')
INTERN_CHOICES = {'PRO': 'Projektsteckbrief', INTERN_CHOICES = {'PRO': 'Projektsteckbrief',

View File

87
input/middleware/oauth.py Normal file
View File

@ -0,0 +1,87 @@
from authlib.integrations.base_client import OAuthError
from authlib.integrations.django_client import OAuth
from authlib.oauth2.rfc6749 import OAuth2Token
from django.shortcuts import redirect
from django.utils.deprecation import MiddlewareMixin
from foerderbarometer import settings
from input import views
from input import models
class OAuthMiddleware(MiddlewareMixin):
def __init__(self, get_response=None):
super().__init__(get_response)
self.oauth = OAuth()
def process_request(self, request):
# added this if clause to get the landing page before oauth
if request.path == '/':
return self.get_response(request)
if settings.OAUTH_URL_WHITELISTS is not None:
for w in settings.OAUTH_URL_WHITELISTS:
if request.path.startswith(w):
return self.get_response(request)
def update_token(token, refresh_token, access_token):
request.session['token'] = token
print('oioi')
print('oi token', token)
return None
sso_client = self.oauth.register(
settings.OAUTH_CLIENT_NAME, overwrite=True, **settings.OAUTH_CLIENT, update_token=update_token
)
if request.path.startswith('/oauth/callback'):
print('oi')
self.clear_session(request)
request.session['token'] = sso_client.authorize_access_token(request)
# print('blub', request.session['token'])
models.Extern.username = self.get_current_user(sso_client, request)['username']
if self.get_current_user(sso_client, request) is not None:
redirect_uri = request.session.pop('redirect_uri', None)
if redirect_uri is not None:
return redirect(redirect_uri)
return redirect(views.ExternView)
if request.session.get('token', None) is not None:
current_user = self.get_current_user(sso_client, request)
if current_user is not None:
return self.get_response(request)
# remember redirect URI for redirecting to the original URL.
request.session['redirect_uri'] = request.path
return sso_client.authorize_redirect(request, settings.OAUTH_CLIENT['redirect_uri'])
# fetch current login user info
# 1. check if it's in cache
# 2. fetch from remote API when it's not in cache
@staticmethod
def get_current_user(sso_client, request):
token = request.session.get('token', None)
if token is None or 'access_token' not in token:
return None
if not OAuth2Token.from_dict(token).is_expired() and 'user' in request.session:
return request.session['user']
try:
res = sso_client.get(settings.OAUTH_CLIENT['userinfo_endpoint'], token=OAuth2Token(token))
print('json oi oi' , res.json())
if res.ok:
request.session['user'] = res.json()
return res.json()
except OAuthError as e:
print(e)
return None
@staticmethod
def clear_session(request):
try:
del request.session['user']
del request.session['token']
except KeyError:
pass
def __del__(self):
print('destroyed')

View File

@ -13,11 +13,12 @@ EMAIL_STATES = {'NONE': 'noch keine Mail versendet',
class Volunteer(models.Model): class Volunteer(models.Model):
realname = models.CharField(max_length=200, null=True, verbose_name="Realname", realname = models.CharField(max_length=200, null=True, verbose_name="Realname",
help_text="Bitte gib deinen Vornamen und deinen Nachnamen ein.") help_text="Bitte gib deinen Vornamen und deinen Nachnamen ein.", default='')
email = models.EmailField(max_length=200, null=True, verbose_name='E-Mail-Adresse', email = models.EmailField(max_length=200, null=True, verbose_name='E-Mail-Adresse',
help_text=format_html('Bitte gib deine E-Mail-Adresse ein, damit dich<br>Wikimedia Deutschland bei Rückfragen oder für<br>die Zusage kontaktieren kann.')) help_text=format_html('Bitte gib deine E-Mail-Adresse ein, damit dich<br>Wikimedia Deutschland bei Rückfragen oder für<br>die Zusage kontaktieren kann.'))
# the following Fields are not supposed to be edited by users # the following Fields are not supposed to be edited by users
granted = models.BooleanField(null=True, verbose_name='bewilligt') granted = models.BooleanField(null=True, verbose_name='bewilligt')
granted_date = models.DateField(null=True, verbose_name='bewilligt am') granted_date = models.DateField(null=True, verbose_name='bewilligt am')
survey_mail_date = models.DateField(verbose_name='Umfragemail wurde verschickt am', null=True, blank=True) survey_mail_date = models.DateField(verbose_name='Umfragemail wurde verschickt am', null=True, blank=True)
@ -36,10 +37,12 @@ class Volunteer(models.Model):
abstract = True abstract = True
class Extern(Volunteer): class Extern(Volunteer):
''' abstract basis class for all data entered by extern volunteers ''' ''' abstract basis class for all data entered by extern volunteers '''
username = models.CharField(max_length=200, null=True, verbose_name='Benutzer_innenname', username = models.CharField(max_length=200, null=True, verbose_name='Benutzer_innenname',
help_text=format_html("Bitte gib den Namen ein, mit dem du dich<br>in den Wikimedia-Projekten registriert hast.")) help_text=format_html("Wikimedia Benutzer_innenname"))
# the following Fields are not supposed to be edited by users # the following Fields are not supposed to be edited by users
service_id = models.CharField(max_length=15, null=True, blank=True) service_id = models.CharField(max_length=15, null=True, blank=True)
@ -97,13 +100,60 @@ class Project(Volunteer):
project_of_year = models.IntegerField(default=0) project_of_year = models.IntegerField(default=0)
end_quartal = models.CharField(max_length=15, null=True, blank=True, verbose_name="Quartal Projekt Ende") end_quartal = models.CharField(max_length=15, null=True, blank=True, verbose_name="Quartal Projekt Ende")
def save(self,*args,**kwargs): def save(self,*args,**kwargs):
generate_finance_id=False
'''we generate the autogenerated fields here''' '''we generate the autogenerated fields here'''
# we don't call save with args/kwargs to avoid UNIQUE CONSTRAINT errors # we don't call save with args/kwargs to avoid UNIQUE CONSTRAINT errors
# but maybe there is a better solution? # but maybe there is a better solution?
super().save()
self.pid = str(self.start.year) + '-' + str(self.account.code) + str(self.pk).zfill(3) if not self.pk:
# self.pid = str(self.account.code) + str(self.pk).zfill(3) print ("NO PK THERE");
generate_finance_id=True
super().save()
else:
orig = type(self).objects.get(pk=self.pk) # Originaldaten aus der DB abrufen
if orig.start.year != self.start.year:
generate_finance_id=True
if orig.account.code != self.account.code:
if str(self.account.code) == '21111':
generate_finance_id=True
else:
self.finance_id = str(self.account.code)
if generate_finance_id:
print ("MUST GENERATE FINANCE ID")
year = self.start.year
projects = Project.objects.filter(start__year=year)
if not projects:
self.project_of_year = 1
#self.pid = str(self.start.year) + '-' + str(self.account.code) + str(self.project_of_year).zfill(3)
else:
# get the project of year number of latest entry
projects = projects.order_by("-project_of_year")[0]
# add one to value of latest entry
self.project_of_year = int(projects.project_of_year) + 1
# self.pid = str(self.start.year) + '-' + str(self.account.code) + str(self.project_of_year).zfill(3)
if str(self.account.code) == '21111':
self.finance_id = str(self.account.code) + '-' + str(self.project_of_year).zfill(3)
else:
self.finance_id = str(self.account.code)
# print (("Current PID",self.pid))
if not self.pid:
self.pid = str(self.account.code) + str(self.pk).zfill(8)
# self.pid = str(self.account.code) + str(self.pk).zfill(3)
print (("Hallo Leute! Ich save jetzt mal MIT PID DANN!!!",self.pid))
# generation of field quartals # generation of field quartals
if self.end.month in [1, 2, 3]: if self.end.month in [1, 2, 3]:
@ -115,34 +165,9 @@ class Project(Volunteer):
if self.end.month in [10, 11, 12]: if self.end.month in [10, 11, 12]:
self.end_quartal = 'Q4' self.end_quartal = 'Q4'
# generation of pid and financeID
if not self.project_of_year:
#print('AAA')
# we need to determine if this is a new year with its first new project...
year = self.start.year
#print(year)
projects = Project.objects.filter(start__year=year)
if not projects:
#print('BBB')
self.project_of_year = 1
self.pid = str(self.start.year) + '-' + str(self.account.code) + str(self.project_of_year).zfill(3)
else:
#print('CCC')
# get the project of year number of latest entry
projects = projects.order_by("-project_of_year")[0]
# add one to value of latest entry
self.project_of_year = int(projects.project_of_year) + 1
self.pid = str(self.start.year) + '-' + str(self.account.code) + str(self.project_of_year).zfill(3)
if str(self.account.code) == '21111':
self.finance_id = str(self.account.code) + str(self.project_of_year).zfill(3)
else:
self.finance_id = str(self.account.code)
super().save() super().save()
def __str__(self): def __str__(self):
return f"{self.pid} {self.name}" return f"{self.pid} {self.name}"

View File

@ -39,3 +39,33 @@ ACCOUNTS ={ # "21103": '21103 Willkommen',
"21140": '21140 Wikipedia-Kampagne', "21140": '21140 Wikipedia-Kampagne',
"21141": '21141 Wikipedia-Onboarding', "21141": '21141 Wikipedia-Onboarding',
"21150": '21150 Fürsorge und Online-Kommunikationskultur',} "21150": '21150 Fürsorge und Online-Kommunikationskultur',}
# teken from working oauth prototype as additional settings
WSGI_APPLICATION = 'oauth_demo.wsgi.application'
# OAuth Settings
OAUTH_URL_WHITELISTS = []
OAUTH_CLIENT_NAME = '<name-of-the-configured-wikimedia-app>'
OAUTH_CLIENT = {
'client_id': '<client-application-key-of-wikimedia-app>',
'client_secret': '<client-application-secret-of-wikimedia-app>',
'access_token_url': 'https://meta.wikimedia.org/w/rest.php/oauth2/access_token',
'authorize_url': 'https://meta.wikimedia.org/w/rest.php/oauth2/authorize',
'api_base_url': 'https://meta.wikimedia.org/w/rest.php/oauth2/resource',
'redirect_uri': 'http://localhost:8000/oauth/callback',
'client_kwargs': {
'scope': 'basic',
'token_placement': 'header'
},
'userinfo_endpoint': 'resource/profile',
}
OAUTH_COOKIE_SESSION_ID = 'sso_session_id'

41
input/settings.py.old Executable file
View File

@ -0,0 +1,41 @@
# mail for IF-OTRS
IF_EMAIL = 'community@wikimedia.de'
#IF_EMAIL = 'test-luca-ext@wikimedia.de'
#SURVEY_EMAIL = 'christof.pins@wikimedia.de'
#SURVEY_EMAIL = 'luca.wulf@cannabinieri.de'
SURVEY_EMAIL = 'sandro.halank@wikimedia.de'
# prefix for urls
SURVEYPREFIX = 'https://wikimedia.sslsurvey.de/Foerderbarometer/?'
# some links
DATAPROTECTION = "https://www.wikimedia.de/datenschutz/#datenerfassung"
FOERDERRICHTLINIEN = "https://de.wikipedia.org/wiki/Wikipedia:Wikimedia_Deutschland/F%C3%B6rderrichtlinien"
NUTZUNGSBEDINGUNGEN = 'static/input/nutzungsbedingungen.html'
LANGUAGE_CODE = 'de'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
ACCOUNTS ={ # "21103": '21103 Willkommen',
"DEF": 'DEFAULT VALUE, you hould not see this!',
"21111": '21111 Förderung (reaktiv)',
"21112": '21112 WikiCon',
# "21113": '21113 Wikimania/Unterstützung Ehrenamtliche',
"21115": '21115 Lokale Räume, Berlin',
"21116": '21116 Lokale Räume, Hamburg',
"21117": '21117 Lokale Räume, Hannover',
"21118": '21118 Lokale Räume, Köln',
"21119": '21119 Lokale Räume, München',
"21120": '21120 Lokale Räume, Fürth',
"21125": '21125 Lokale Räume, allgemein',
"21130": '21130 GLAM-Förderung',
"21131": '21131 Initiative Förderung',
# "21134": '21134 Größe',
# "21137": '21137 Beitragen',
# "21138": '21138 Vermittlung',
"21140": '21140 Wikipedia-Kampagne',
"21141": '21141 Wikipedia-Onboarding',
"21150": '21150 Fürsorge und Online-Kommunikationskultur',}

View File

@ -0,0 +1,19 @@
window.addEventListener("load", function() {
(function($) {
$(function() {
let otrs_link = document.querySelector(".field-otrs > div > p.url > a").href;
console.log(otrs_link);
alert(otrs_link);
let otrs_link_pret = otrs_link.replace(/%3B/g, ";");
let otrs_link_pretty = otrs_link_pret.replace(/%3D/g, "=");
console.log(otrs_link_pretty);
document.querySelector(".field-otrs > div > p.url > a").href = otrs_link_pretty;
});
})(django.jQuery);
});

View File

@ -0,0 +1,69 @@
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/base.css' %}" />
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/widgets.css' %}" />
{% load i18n %}
{% csrf_token %}
<center>
<style>
ul > li {
list-style-type: none;
}
ul {
padding-left: 10;
}
label.required::after {
content: ' *';
color: red;
}
.div15 {
height: 15%;
}
.div5 {
height: 5%;
}
.button1 {
width: 40vw;
height: 6vh;
display: flex;
justify-content: center;
align-items: center;
font-weight: bold;
font-size: 4vh;
}
</style>
<div class="div5"></div>
<p>
Herzlich willkommen im Förderanfrageportal von Wikimedia Deutschland!
</p>
<div class="div5"></div>
<!-- <a href="http://fdb-devel.wikimedia.de/extern"style="float:right;padding-right:10%;">OAUTH</a>
<a href="http://fdb-devel.wikimedia.de/extern" style="float:left;padding-left:10%;">OAUTH</a> -->
<p>
<img src="https://upload.wikimedia.org/wikipedia/commons/c/c4/Figuren_klein.jpg"><p>
Um eine Unterstützungsleistung im Rahmen der Förderangebote anfragen zu können, verifiziere dich bitte mit deinem Wikimedia-Konto.
<br>Weitere Informationen und Hintergründe findest du unter
<a href="https://de.wikipedia.org/wiki/Wikipedia:Förderung/Förderangebote">
Förderportal</a> in der deutschsprachigen Wikipedia.
<p>
<div class="div5"></div>
<div class="button button1"><a href="/extern"><div class="button1_text">Anmelden</div></a></div>
<div class="div5"></div>
<div class="div5"></div>
<br>Für alle Fragen wende dich gern an das <a href="https://de.wikipedia.org/wiki/Wikipedia:Förderung/Wikimedia_Deutschland">Team Communitys und Engagement</a>.
<br>Für interessierte Hacker gibts auch den <a href="https://srcsrv.wikimedia.de/beba/foerderbarometer">Sourcecode</a> zum Formular und was damit passiert.
<p>
<a href="https://www.wikimedia.de/impressum/">Impressum</a>
<p>
</center>

View File

@ -1,10 +1,12 @@
from django.urls import path from django.urls import path
from .views import ExternView, done, authorize, deny, InternView, export from .views import ExternView, index, done, authorize, deny, InternView, export
from django.contrib import admin
urlpatterns = [ urlpatterns = [
path('', ExternView.as_view(), name='extern'), path('', index, name='index'),
path('extern', ExternView.as_view(), name='extern'),
# path('intern', InternView.as_view(), name='intern'), # path('intern', InternView.as_view(), name='intern'),
path('admin/', admin.site.urls),
path('saved', done, name='done'), path('saved', done, name='done'),
path('export', export, name='export'), path('export', export, name='export'),
path('authorize/<str:choice>/<int:pk>', authorize, name='authorize'), path('authorize/<str:choice>/<int:pk>', authorize, name='authorize'),

View File

@ -70,6 +70,8 @@ def deny(request, choice, pk):
def done(request): def done(request):
return HttpResponse("Deine Anfrage wurde gesendet. Du erhältst in Kürze eine E-Mail-Benachrichtigung mit deinen Angaben. Für alle Fragen kontaktiere bitte das Team Communitys und Engagement unter community@wikimedia.de.") return HttpResponse("Deine Anfrage wurde gesendet. Du erhältst in Kürze eine E-Mail-Benachrichtigung mit deinen Angaben. Für alle Fragen kontaktiere bitte das Team Communitys und Engagement unter community@wikimedia.de.")
def index(request):
return render(request, 'input/index.html')
class InternView(LoginRequiredMixin, CookieWizardView): class InternView(LoginRequiredMixin, CookieWizardView):
'''This View is for WMDE-employees only''' '''This View is for WMDE-employees only'''
@ -216,6 +218,8 @@ class ExternView(CookieWizardView):
data = {} data = {}
for form in form_list: for form in form_list:
data = {**data, **form.cleaned_data} data = {**data, **form.cleaned_data}
data['username'] = self.request.session['user']['username']
if data['choice'] == 'LIT': if data['choice'] == 'LIT':
if data['selfbuy'] == 'TRUE': if data['selfbuy'] == 'TRUE':

View File

@ -1,7 +1,20 @@
asgiref==3.2.10 asgiref==3.2.10
Authlib==1.2.1
certifi==2023.7.22
cffi==1.16.0
chardet==5.2.0
charset-normalizer==3.3.0
cryptography==41.0.4
Django==3.1.2 Django==3.1.2
django-formtools==2.4 django-formtools==2.4
gunicorn==20.0.4 gunicorn==20.0.4
idna==3.4
mysqlclient==2.1.1 mysqlclient==2.1.1
pycparser==2.21
pytz==2023.3.post1
requests==2.31.0
six==1.16.0
sqlparse==0.4.3 sqlparse==0.4.3
typing_extensions==4.8.0
urllib3==2.0.6
whitenoise==6.2.0 whitenoise==6.2.0