merged settings & use .env files to configure differences

This commit is contained in:
Oliver Zander 2025-08-19 09:45:14 +02:00 committed by Tobias Herre
parent e5cea49673
commit eb44094639
29 changed files with 361 additions and 1066 deletions

5
.env.develop.example Normal file
View File

@ -0,0 +1,5 @@
ENVIRONMENT = develop
DEBUG = yes
SECRET_KEY = not-a-secret-key
DATABASE_ENGINE = sqlite3
EMAIL_BACKEND = console

13
.env.production.example Normal file
View File

@ -0,0 +1,13 @@
ENVIRONMENT = production
DEBUG = no
SECRET_KEY = <enter a secret key>
HOST = https://foerderung.wikimedia.de
DATABASE_ENGINE = mysql
DATABASE_PASSWORD = <enter a database password>
EMAIL_BACKEND = smtp
EMAIL_HOST_USER = <enter an email host user>
EMAIL_HOST_PASSWORD = <enter an email host password>
OAUTH_ENABLED = yes
OAUTH_CLIENT_NAME = <enter a client name>
OAUTH_CLIENT_ID = <enter a client id>
OAUTH_CLIENT_SECRET = <enter a client secret>

1
.gitignore vendored
View File

@ -1,7 +1,6 @@
# secret passwords and so # secret passwords and so
/secrets.json /secrets.json
/staticfiles /staticfiles
foerderbarometer/settings.py
/nohup.out /nohup.out
/logfile /logfile
*~ *~

View File

@ -4,7 +4,10 @@ purpose: gather data from intern(WMDE) and extern(volunteers) forms to create a
## installation and development setup ## installation and development setup
ln -sr foerderbarometer/settings_development.py foerderbarometer/settings.py cp .env.develop.example .env
To use a MariaDB change `DATABASE_ENGINE` in .env to `mysql` and amend `DATABASE_*` variables according to your setup.
For further information see the production setup below.
build the database with build the database with
@ -65,16 +68,26 @@ run some tests with
## production setup ## production setup
ln -sr foerderbarometer/settings_production.py foerderbarometer/settings.py cp .env.production.example .env
edit /secrets.json to contain something similar to edit .env and fill in the missing secrets
{ SECRET_KEY
"DATABASE_PASSWORD": "THIS IS TOP SECRET!", DATABASE_PASSWORD
"SECRET_KEY": "THIS IS ANOTHER SECRET!" EMAIL_HOST_USER
} EMAIL_HOST_PASSWORD
OAUTH_CLIENT_NAME
OAUTH_CLIENT_ID
OAUTH_CLIENT_SECRET
edit foerderbarometer/settings_production.py according to your database setup (tested with MariaDB 10.0.36) amend database variables to .env according to your database setup (tested with MariaDB 10.0.36), e.g.
DATABASE_NAME
DATABASE_USER
DATABASE_HOST
DATABASE_PORT
for a full set of all possible env vars have a look at foerderbarometer/settings.py
run the following commands: run the following commands:

View File

@ -0,0 +1,164 @@
import os
from pathlib import Path
from dotenv import load_dotenv
from input.utils.settings import env, password_validators
BASE_DIR = Path(__file__).parents[1]
load_dotenv(BASE_DIR / '.env')
DEBUG = env('DEBUG', False)
SECRET_KEY = env('SECRET_KEY')
ALLOWED_HOSTS = ['*']
HOST = env('HOST', 'http://localhost:8000')
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',
]
ROOT_URLCONF = 'foerderbarometer.urls'
DJANGO_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',
],
},
}
TEMPLATES = [DJANGO_TEMPLATES]
WSGI_APPLICATION = 'foerderbarometer.wsgi.application'
DATABASE_ENGINE = env('DATABASE_ENGINE', 'mysql')
DATABASE_SQLITE = {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
DATABASE_MYSQL = {
'ENGINE': 'django.db.backends.mysql',
'NAME': env('DATABASE_NAME', 'fdb'),
'USER': env('DATABASE_USER', 'fdb'),
'PASSWORD': env('DATABASE_PASSWORD'),
'HOST': env('DATABASE_HOST', 'localhost'),
'PORT': env('DATABASE_PORT', 3306),
'OPTIONS': {
'charset' : 'utf8',
'use_unicode' : True,
'init_command': 'SET '
'storage_engine=INNODB,'
'character_set_connection=utf8,'
'collation_connection=utf8_bin'
},
'TEST_CHARSET': 'utf8',
'TEST_COLLATION': 'utf8_general_ci',
}
if DATABASE_ENGINE == 'mysql':
DATABASE_DEFAULT = DATABASE_MYSQL
else:
DATABASE_DEFAULT = DATABASE_SQLITE
DATABASES = {
'default': DATABASE_DEFAULT,
}
EMAIL_BACKEND = env('EMAIL_BACKEND', 'console')
if EMAIL_BACKEND == 'smtp':
EMAIL_HOST = env('EMAIL_HOST', 'email.wikimedia.de')
EMAIL_PORT = env('EMAIL_PORT', 587)
EMAIL_USE_TLS = env('EMAIL_USE_TLS', True)
EMAIL_HOST_USER = env('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = env('EMAIL_HOST_PASSWORD')
EMAIL_BACKEND = f'django.core.mail.backends.{EMAIL_BACKEND}.EmailBackend'
EMAIL_URL_PREFIX = env('EMAIL_URL_PREFIX', HOST)
AUTH_PASSWORD_VALIDATORS = password_validators(
'UserAttributeSimilarityValidator',
'MinimumLengthValidator',
'CommonPasswordValidator',
'NumericPasswordValidator',
)
USE_I18N = True
USE_L10N = True
LANGUAGE_CODE = env('LANGUAGE_CODE', 'en-us')
USE_TZ = True
TIME_ZONE = env('TIME_ZONE', 'UTC')
STATIC_ROOT = BASE_DIR / 'staticfiles'
STATIC_URL = '/static/'
if OAUTH_ENABLED := env('OAUTH_ENABLED', not DEBUG):
MIDDLEWARE += ['input.middleware.oauth.OAuthMiddleware']
OAUTH_CLIENT_NAME = env('OAUTH_CLIENT_NAME')
OAUTH_CLIENT = {
'client_id': env('OAUTH_CLIENT_ID'),
'client_secret': env('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': env('OAUTH_REDIRECT_URI', f'{HOST}/oauth/callback'),
'client_kwargs': {
'scope': 'basic',
'token_placement': 'header'
},
'userinfo_endpoint': 'resource/profile',
}
OAUTH_URL_WHITELISTS = ['/admin']
OAUTH_COOKIE_SESSION_ID = 'sso_session_id'
IF_EMAIL = env('IF_EMAIL', 'community@wikimedia.de')
SURVEY_EMAIL = env('SURVEY_EMAIL', 'sandro.halank@wikimedia.de')
SURVEY_PREFIX = env('SURVEY_PREFIX', 'https://wikimedia.sslsurvey.de/Foerderbarometer/?')
DATAPROTECTION = 'https://www.wikimedia.de/datenschutz/#datenerfassung'
FOERDERRICHTLINIEN = 'https://de.wikipedia.org/wiki/Wikipedia:Wikimedia_Deutschland/Richtlinie_zur_Förderung_der_Communitys'
NUTZUNGSBEDINGUNGEN = 'static/input/nutzungsbedingungen.html'
NUTZUNGSBEDINGUNGEN_EMAIL_SERVICE = 'static/input/nutzungsbedingungen-mail.pdf'
NUTZUNGSBEDINGUNGEN_MAILINGLISTEN = 'static/input/nutzungsbedingungen-mailinglisten.pdf'
NUTZUNGSBEDINGUNGEN_LITERATURSTIPENDIUM = 'static/input/nutzungsbedingungen-literaturstipendium.pdf'
NUTZUNGSBEDINGUNGEN_OTRS = 'static/input/2025_Nutzungsvereinbarung_OTRS.docx.pdf'
NUTZUNGSBEDINGUNGEN_VISITENKARTEN = 'static/input/nutzungsbedingungen-visitenkarten.pdf'

View File

@ -1,203 +0,0 @@
"""
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'
CSRF_TRUSTED_ORIGINS = ['https://fdb-devel.wikimedia.de']
# EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'xemail.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.mysql',
'NAME': 'fdbdevel',
'USER': 'fdbdevel',
'PASSWORD': get_secret('DATABASE_PASSWORD'),
'HOST': '10.0.6.224', # Or an IP Address that your database is hosted on
# 'PORT': '3306',
#optional:
'OPTIONS': {
'charset' : 'utf8',
'use_unicode' : True,
'init_command': 'SET '
'storage_engine=INNODB,'
'character_set_connection=utf8,'
'collation_connection=utf8_bin'
#'sql_mode=STRICT_TRANS_TABLES,' # see note below
#'SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED',
},
'TEST_CHARSET': 'utf8',
'TEST_COLLATION': 'utf8_general_ci',
}
}
# 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

@ -1,151 +0,0 @@
"""
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 = 'http://localhost:8000'
# mails in development go to stdout
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# 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 = '*&7p9#_n$@^%0z49s+7jpy@+j1rw_hqh05knyd6y2*!0)r&b6h'
# 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',
]
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'

View File

@ -1,158 +0,0 @@
"""
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 = 'http://localhost:8000'
# mails in development go to stdout
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'email.wikimedia.de'
EMAIL_PORT = '587'
EMAIL_USE_TLS = True
EMAIL_HOST_USER = '636ea784dd6ec43'
EMAIL_HOST_PASSWORD = 'wsgqp4ZaVRZZEpRJ'
# 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 = '*&7p9#_n$@^%0z49s+7jpy@+j1rw_hqh05knyd6y2*!0)r&b6h'
# 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',
]
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'

View File

@ -1,175 +0,0 @@
"""
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 = 'http://localhost:8000'
# mails in development go to stdout
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# 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 = '*&7p9#_n$@^%0z49s+7jpy@+j1rw_hqh05knyd6y2*!0)r&b6h'
# 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',
]
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')
# }
# }
#
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'fdb',
'USER': 'fdb',
'PASSWORD': get_secret('DATABASE_PASSWORD'),
'HOST': 'localhost', # Or an IP Address that your database is hosted on
# 'PORT': '3306',
#optional:
'OPTIONS': {
'charset' : 'utf8',
'use_unicode' : True,
'init_command': 'SET '
'storage_engine=INNODB,'
'character_set_connection=utf8,'
'collation_connection=utf8_bin'
#'sql_mode=STRICT_TRANS_TABLES,' # see note below
#'SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED',
},
'TEST_CHARSET': 'utf8',
'TEST_COLLATION': 'utf8_general_ci',
}
}
# 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'

View File

@ -1,171 +0,0 @@
"""
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
# mails in development go to stdout
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'email.wikimedia.de'
EMAIL_PORT = '587'
EMAIL_USE_TLS = True
EMAIL_HOST_USER = '636ea784dd6ec43'
EMAIL_HOST_PASSWORD = 'wsgqp4ZaVRZZEpRJ'
# prefix for urls in mails
URLPREFIX = 'http://foerderung.wikimedia.de'
# 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
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',
]
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.mysql',
'NAME': 'fdbdevel',
'USER': 'fdbdevel',
'PASSWORD': get_secret('DATABASE_PASSWORD'),
'HOST': '10.0.6.7', # Or an IP Address that your database is hosted on
# 'PORT': '3306',
#optional:
'OPTIONS': {
'charset' : 'utf8',
'use_unicode' : True,
'init_command': 'SET '
'storage_engine=INNODB,'
'character_set_connection=utf8,'
'collation_connection=utf8_bin'
#'sql_mode=STRICT_TRANS_TABLES,' # see note below
#'SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED',
},
'TEST_CHARSET': 'utf8',
'TEST_COLLATION': 'utf8_general_ci',
}
}
# 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

@ -1,16 +0,0 @@
"""
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

@ -1,4 +1,4 @@
from django.db import models from django.conf import settings
from django.forms import ModelForm, DateField, ChoiceField, RadioSelect, BooleanField from django.forms import ModelForm, DateField, ChoiceField, RadioSelect, BooleanField
from django.contrib.admin.widgets import AdminDateWidget from django.contrib.admin.widgets import AdminDateWidget
from django.utils.html import format_html from django.utils.html import format_html
@ -6,9 +6,6 @@ from django.utils.html import format_html
from .models import Project, Volunteer, ConcreteVolunteer, Extern, ConcreteExtern, IFG, Library, TYPE_CHOICES,\ from .models import Project, Volunteer, ConcreteVolunteer, Extern, ConcreteExtern, IFG, Library, TYPE_CHOICES,\
HonoraryCertificate, Travel, Email, Literature, List,\ HonoraryCertificate, Travel, Email, Literature, List,\
BusinessCard BusinessCard
from .settings import DATAPROTECTION, FOERDERRICHTLINIEN, NUTZUNGSBEDINGUNGEN
from . import settings
@ -39,7 +36,7 @@ class ExternForm(FdbForm):
check = BooleanField(required=True, check = BooleanField(required=True,
label=format_html("Ich stimme den <a href='{}' target='_blank' rel='noopener'>Datenschutzbestimmungen</a> und der<br> <a href='{}' target='_blank' rel='noopener'>Richtlinie zur Förderung der Communitys</a> zu", label=format_html("Ich stimme den <a href='{}' target='_blank' rel='noopener'>Datenschutzbestimmungen</a> und der<br> <a href='{}' target='_blank' rel='noopener'>Richtlinie zur Förderung der Communitys</a> zu",
DATAPROTECTION, FOERDERRICHTLINIEN)) settings.DATAPROTECTION, settings.FOERDERRICHTLINIEN))
class Meta: class Meta:
model = ConcreteExtern model = ConcreteExtern
@ -116,7 +113,7 @@ class IFGForm(FdbForm):
class CheckForm(FdbForm): class CheckForm(FdbForm):
termstoaccept = NUTZUNGSBEDINGUNGEN termstoaccept = settings.NUTZUNGSBEDINGUNGEN
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)

View File

@ -9,7 +9,6 @@ from django.conf import settings
from input.models import Project, Library, HonoraryCertificate, Travel, Email,\ from input.models import Project, Library, HonoraryCertificate, Travel, Email,\
BusinessCard, List, IFG, Literature BusinessCard, List, IFG, Literature
from input.settings import IF_EMAIL, SURVEYPREFIX, SURVEY_EMAIL
class Command(BaseCommand): class Command(BaseCommand):
''' mails will be send here: ''' mails will be send here:
@ -34,14 +33,14 @@ class Command(BaseCommand):
'type': type, 'type': type,
'name': name, 'name': name,
'pid': pid, 'pid': pid,
'SURVEYPREFIX': SURVEYPREFIX, } 'SURVEY_PREFIX': settings.SURVEY_PREFIX, }
txt_mail_template = get_template('input/survey_mail.txt') txt_mail_template = get_template('input/survey_mail.txt')
html_mail_template = get_template('input/survey_mail.html') html_mail_template = get_template('input/survey_mail.html')
try: try:
subject, from_email, to = 'Dein Feedback zur Förderung durch Wikimedia Deutschland', IF_EMAIL, email subject, from_email, to = 'Dein Feedback zur Förderung durch Wikimedia Deutschland', settings.IF_EMAIL, email
text_content = txt_mail_template.render(context) text_content = txt_mail_template.render(context)
html_content = html_mail_template.render(context) html_content = html_mail_template.render(context)
msg = EmailMultiAlternatives(subject, text_content, from_email, [to], bcc=[SURVEY_EMAIL]) msg = EmailMultiAlternatives(subject, text_content, from_email, [to], bcc=[settings.SURVEY_EMAIL])
msg.attach_alternative(html_content, "text/html") msg.attach_alternative(html_content, "text/html")
msg.send() msg.send()
#print('survey mail would have been send') #print('survey mail would have been send')
@ -77,10 +76,10 @@ class Command(BaseCommand):
for project in old: for project in old:
context = {'project': project} context = {'project': project}
context['URLPREFIX'] = settings.URLPREFIX context['URL_PREFIX'] = settings.EMAIL_URL_PREFIX
try: try:
subject, from_email, to = 'Projektende erreicht', IF_EMAIL, IF_EMAIL subject, from_email, to = 'Projektende erreicht', settings.IF_EMAIL, settings.IF_EMAIL
text_content = txt_mail_template.render(context) text_content = txt_mail_template.render(context)
html_content = html_mail_template.render(context) html_content = html_mail_template.render(context)
msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
@ -120,11 +119,11 @@ class Command(BaseCommand):
for project in approved_end: for project in approved_end:
context = {'project': project} context = {'project': project}
context['URLPREFIX'] = settings.URLPREFIX context['URL_PREFIX'] = settings.EMAIL_URL_PREFIX
try: try:
subject, from_email, to = 'Projektende erreicht', IF_EMAIL, project.email subject, from_email, to = 'Projektende erreicht', settings.IF_EMAIL, project.email
text_content = txt_mail_template.render(context) text_content = txt_mail_template.render(context)
html_content = html_mail_template.render(context) html_content = html_mail_template.render(context)
msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
@ -132,7 +131,7 @@ class Command(BaseCommand):
msg.send() msg.send()
#print('if and of project approved mail would have been sent') #print('if and of project approved mail would have been sent')
inform_subject, inform_from_email, inform_to = 'Projektorganisator*in wurde informiert', IF_EMAIL, IF_EMAIL inform_subject, inform_from_email, inform_to = 'Projektorganisator*in wurde informiert', settings.IF_EMAIL, settings.IF_EMAIL
inform_text_content = txt_informMail_template.render(context) inform_text_content = txt_informMail_template.render(context)
inform_html_content = html_informMail_template.render(context) inform_html_content = html_informMail_template.render(context)
inform_msg = EmailMultiAlternatives(inform_subject, inform_text_content, inform_from_email, [inform_to]) inform_msg = EmailMultiAlternatives(inform_subject, inform_text_content, inform_from_email, [inform_to])
@ -178,9 +177,9 @@ class Command(BaseCommand):
for project in approved_notHappened: for project in approved_notHappened:
context = {'project': project} context = {'project': project}
context['URLPREFIX'] = settings.URLPREFIX context['URL_PREFIX'] = settings.EMAIL_URL_PREFIX
try: try:
subject, from_email, to = 'Projektende erreicht', IF_EMAIL, project.email subject, from_email, to = 'Projektende erreicht', settings.IF_EMAIL, project.email
text_content = txt_mail_template.render(context) text_content = txt_mail_template.render(context)
html_content = html_mail_template.render(context) html_content = html_mail_template.render(context)
msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
@ -195,7 +194,7 @@ class Command(BaseCommand):
# [project.email], # [project.email],
# fail_silently=False) # fail_silently=False)
inform_subject, inform_from_email, inform_to = 'Projektorganisator*in wurde informiert', IF_EMAIL, IF_EMAIL inform_subject, inform_from_email, inform_to = 'Projektorganisator*in wurde informiert', settings.IF_EMAIL, settings.IF_EMAIL
inform_text_content = txt_informMail_template.render(context) inform_text_content = txt_informMail_template.render(context)
inform_html_content = html_informMail_template.render(context) inform_html_content = html_informMail_template.render(context)
inform_msg = EmailMultiAlternatives(inform_subject, inform_text_content, inform_from_email, [inform_to]) inform_msg = EmailMultiAlternatives(inform_subject, inform_text_content, inform_from_email, [inform_to])

View File

@ -1,11 +1,14 @@
from authlib.integrations.base_client import OAuthError from authlib.integrations.base_client import OAuthError
from authlib.integrations.django_client import OAuth from authlib.integrations.django_client import OAuth
from authlib.oauth2.rfc6749 import OAuth2Token from authlib.oauth2.rfc6749 import OAuth2Token
from django.shortcuts import redirect from django.shortcuts import redirect
from django.utils.deprecation import MiddlewareMixin from django.utils.deprecation import MiddlewareMixin
from foerderbarometer import settings from django.conf import settings
from input import views
from input import models from input.models import Extern
from input.views import ExternView
class OAuthMiddleware(MiddlewareMixin): class OAuthMiddleware(MiddlewareMixin):
@ -14,7 +17,7 @@ class OAuthMiddleware(MiddlewareMixin):
self.oauth = OAuth() self.oauth = OAuth()
def process_request(self, request): def process_request(self, request):
# added this if clause to get the landing page before oauth # added this if-clause to get the landing page before oauth
if request.path == '/': if request.path == '/':
return self.get_response(request) return self.get_response(request)
if settings.OAUTH_URL_WHITELISTS is not None: if settings.OAUTH_URL_WHITELISTS is not None:
@ -37,12 +40,12 @@ class OAuthMiddleware(MiddlewareMixin):
self.clear_session(request) self.clear_session(request)
request.session['token'] = sso_client.authorize_access_token(request) request.session['token'] = sso_client.authorize_access_token(request)
# print('blub', request.session['token']) # print('blub', request.session['token'])
models.Extern.username = self.get_current_user(sso_client, request)['username'] Extern.username = self.get_current_user(sso_client, request)['username']
if self.get_current_user(sso_client, request) is not None: if self.get_current_user(sso_client, request) is not None:
redirect_uri = request.session.pop('redirect_uri', None) redirect_uri = request.session.pop('redirect_uri', None)
if redirect_uri is not None: if redirect_uri is not None:
return redirect(redirect_uri) return redirect(redirect_uri)
return redirect(views.ExternView) return redirect(ExternView)
if request.session.get('token', None) is not None: if request.session.get('token', None) is not None:
current_user = self.get_current_user(sso_client, request) current_user = self.get_current_user(sso_client, request)

View File

@ -3,8 +3,6 @@ from datetime import date
from django.db import models from django.db import models
from django.utils.html import format_html from django.utils.html import format_html
from .settings import ACCOUNTS
EMAIL_STATES = {'NONE': 'noch keine Mail versendet', EMAIL_STATES = {'NONE': 'noch keine Mail versendet',
'INF': 'die Benachrichtigung zur Projektabschlussmail wurde versendet', 'INF': 'die Benachrichtigung zur Projektabschlussmail wurde versendet',

View File

@ -1,78 +0,0 @@
# 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"
FOERDERRICHTLINIEN = "https://de.wikipedia.org/wiki/Wikipedia:Wikimedia_Deutschland/Richtlinie_zur_Förderung_der_Communitys"
NUTZUNGSBEDINGUNGEN = 'static/input/nutzungsbedingungen.html'
NUTZUNGSBEDINGUNGEN_EMAIL_SERVICE = 'static/input/nutzungsbedingungen-mail.pdf'
NUTZUNGSBEDINGUNGEN_MAILINGLISTEN = 'static/input/nutzungsbedingungen-mailinglisten.pdf'
NUTZUNGSBEDINGUNGEN_LITERATURSTIPENDIUM = 'static/input/nutzungsbedingungen-literaturstipendium.pdf'
NUTZUNGSBEDINGUNGEN_OTRS = 'static/input/2025_Nutzungsvereinbarung_OTRS.docx.pdf'
NUTZUNGSBEDINGUNGEN_VISITENKARTEN = 'static/input/nutzungsbedingungen-visitenkarten.pdf'
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',}
# 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'

View File

@ -1,41 +0,0 @@
# 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

@ -8,7 +8,7 @@ Ende erreicht.<br><br>
Hier könnt ihr es in der Datenbank editieren: Hier könnt ihr es in der Datenbank editieren:
<br><br> <br><br>
<a href="{{URLPREFIX}}/admin/input/project/{{project.pk}}/change">{{URLPREFIX}}/admin/input/project/{{project.pk}}/change</a> <a href="{{URL_PREFIX}}/admin/input/project/{{project.pk}}/change">{{URL_PREFIX}}/admin/input/project/{{project.pk}}/change</a>
<br><br> <br><br>
mit freundlichen Grüßen, Eure Lieblingsdatenbank mit freundlichen Grüßen, Eure Lieblingsdatenbank

View File

@ -5,6 +5,6 @@ Ende erreicht.
Hier könnt ihr es in der Datenbank editieren: Hier könnt ihr es in der Datenbank editieren:
{{URLPREFIX}}/admin/input/project/{{project.pk}}/change {{URL_PREFIX}}/admin/input/project/{{project.pk}}/change
mit freundlichen Grüßen, Eure Lieblingsdatenbank mit freundlichen Grüßen, Eure Lieblingsdatenbank

View File

@ -8,7 +8,7 @@ Ende erreicht.
<br><br> <br><br>
Hier könnt ihr es in der Datenbank editieren: Hier könnt ihr es in der Datenbank editieren:
<br><br> <br><br>
<a href="{{URLPREFIX}}/admin/input/project/{{project.pk}}/change">{{URLPREFIX}}/admin/input/project/{{project.pk}}/change</a> <a href="{{URL_PREFIX}}/admin/input/project/{{project.pk}}/change">{{URL_PREFIX}}/admin/input/project/{{project.pk}}/change</a>
<br><br> <br><br>
Projektorganisator*in wurde über den Projektabschluss informiert. Projektorganisator*in wurde über den Projektabschluss informiert.

View File

@ -5,7 +5,7 @@ Ende erreicht.
Hier könnt ihr es in der Datenbank editieren: Hier könnt ihr es in der Datenbank editieren:
{{URLPREFIX}}/admin/input/project/{{project.pk}}/change {{URL_PREFIX}}/admin/input/project/{{project.pk}}/change
Projektorganisator*in wurde über den Projektabschluss informiert. Projektorganisator*in wurde über den Projektabschluss informiert.

View File

@ -28,29 +28,29 @@ Sendungsadrese: {{data.send_to}} <br> {% endif %}
Zum Eintrag in der Förderdatenbank: Zum Eintrag in der Förderdatenbank:
{% if data.choice == 'BIB' %} {% if data.choice == 'BIB' %}
<a href="{{data.urlprefix}}/admin/input/library/{{data.pk}}/change">{{data.urlprefix}}/admin/input/library/{{data.pk}}/change</a> <a href="{{data.url_prefix}}/admin/input/library/{{data.pk}}/change">{{data.url_prefix}}/admin/input/library/{{data.pk}}/change</a>
{% elif data.choice == 'ELIT'%} {% elif data.choice == 'ELIT'%}
<a href="{{data.urlprefix}}/admin/input/library/{{data.pk}}/change">{{data.urlprefix}}/admin/input/library/{{data.pk}}/change</a> <a href="{{data.url_prefix}}/admin/input/library/{{data.pk}}/change">{{data.url_prefix}}/admin/input/library/{{data.pk}}/change</a>
{% elif data.choice == 'LIT'%} {% elif data.choice == 'LIT'%}
<a href="{{data.urlprefix}}/admin/input/literature/{{data.pk}}/change">{{data.urlprefix}}/admin/input/literature/{{data.pk}}/change</a> <a href="{{data.url_prefix}}/admin/input/literature/{{data.pk}}/change">{{data.url_prefix}}/admin/input/literature/{{data.pk}}/change</a>
{% elif data.choice == 'MAIL'%} {% elif data.choice == 'MAIL'%}
<a href="{{data.urlprefix}}/admin/input/email/{{data.pk}}/change">{{data.urlprefix}}/admin/input/email/{{data.pk}}/change</a> <a href="{{data.url_prefix}}/admin/input/email/{{data.pk}}/change">{{data.url_prefix}}/admin/input/email/{{data.pk}}/change</a>
{% elif data.choice == 'IFG'%} {% elif data.choice == 'IFG'%}
<a href="{{data.urlprefix}}/admin/input/ifg/{{data.pk}}/change">{{data.urlprefix}}/admin/input/ifg/{{data.pk}}/change</a> <a href="{{data.url_prefix}}/admin/input/ifg/{{data.pk}}/change">{{data.url_prefix}}/admin/input/ifg/{{data.pk}}/change</a>
{% elif data.choice == 'LIST'%} {% elif data.choice == 'LIST'%}
<a href="{{data.urlprefix}}/admin/input/list/{{data.pk}}/change">{{data.urlprefix}}/admin/input/list/{{data.pk}}/change</a> <a href="{{data.url_prefix}}/admin/input/list/{{data.pk}}/change">{{data.url_prefix}}/admin/input/list/{{data.pk}}/change</a>
{% elif data.choice == 'TRAV'%} {% elif data.choice == 'TRAV'%}
<a href="{{data.urlprefix}}/admin/input/travel/{{data.pk}}/change">{{data.urlprefix}}/admin/input/travel/{{data.pk}}/change</a> <a href="{{data.url_prefix}}/admin/input/travel/{{data.pk}}/change">{{data.url_prefix}}/admin/input/travel/{{data.pk}}/change</a>
{% elif data.choice == 'SOFT'%} {% elif data.choice == 'SOFT'%}
<a href="{{data.urlprefix}}/admin/input/library/{{data.pk}}/change">{{data.urlprefix}}/admin/input/library/{{data.pk}}/change</a> <a href="{{data.url_prefix}}/admin/input/library/{{data.pk}}/change">{{data.url_prefix}}/admin/input/library/{{data.pk}}/change</a>
{% elif data.choice == 'VIS'%} {% elif data.choice == 'VIS'%}
<a href="{{data.urlprefix}}/admin/input/businesscard/{{data.pk}}/change">{{data.urlprefix}}/admin/input/businesscard/{{data.pk}}/change</a> <a href="{{data.url_prefix}}/admin/input/businesscard/{{data.pk}}/change">{{data.url_prefix}}/admin/input/businesscard/{{data.pk}}/change</a>
{% endif %} {% endif %}
<br><br> <br><br>
Zum Genehmigen hier klicken: <a href="{{data.urlprefix}}{% url 'authorize' data.choice data.pk %}">{{data.urlprefix}}{% url 'authorize' data.choice data.pk %}</a> Zum Genehmigen hier klicken: <a href="{{data.url_prefix}}{% url 'authorize' data.choice data.pk %}">{{data.url_prefix}}{% url 'authorize' data.choice data.pk %}</a>
<br><br> <br><br>
Zu Ablehnen hier klicken: <a href="{{data.urlprefix}}{% url 'deny' data.choice data.pk %}">{{data.urlprefix}}{% url 'deny' data.choice data.pk %}</a> Zu Ablehnen hier klicken: <a href="{{data.url_prefix}}{% url 'deny' data.choice data.pk %}">{{data.url_prefix}}{% url 'deny' data.choice data.pk %}</a>
<br><br> <br><br>
Stets zu Diensten, Deine Förderdatenbank Stets zu Diensten, Deine Förderdatenbank

View File

@ -25,28 +25,28 @@ Sendungsadrese: {{data.send_to}} {% endif %}
Zum Eintrag in der Förderdatenbank: Zum Eintrag in der Förderdatenbank:
{% if data.choice == 'BIB' %} {% if data.choice == 'BIB' %}
<a href="{{data.urlprefix}}/admin/input/library/{{data.pk}}/change">{{data.urlprefix}}/admin/input/library/{{data.pk}}/change</a> <a href="{{data.url_prefix}}/admin/input/library/{{data.pk}}/change">{{data.url_prefix}}/admin/input/library/{{data.pk}}/change</a>
{% elif data.choice == 'ELIT'%} {% elif data.choice == 'ELIT'%}
<a href="{{data.urlprefix}}/admin/input/library/{{data.pk}}/change">{{data.urlprefix}}/admin/input/library/{{data.pk}}/change</a> <a href="{{data.url_prefix}}/admin/input/library/{{data.pk}}/change">{{data.url_prefix}}/admin/input/library/{{data.pk}}/change</a>
{% elif data.choice == 'LIT'%} {% elif data.choice == 'LIT'%}
<a href="{{data.urlprefix}}/admin/input/literature/{{data.pk}}/change">{{data.urlprefix}}/admin/input/literature/{{data.pk}}/change</a> <a href="{{data.url_prefix}}/admin/input/literature/{{data.pk}}/change">{{data.url_prefix}}/admin/input/literature/{{data.pk}}/change</a>
{% elif data.choice == 'MAIL'%} {% elif data.choice == 'MAIL'%}
<a href="{{data.urlprefix}}/admin/input/email/{{data.pk}}/change">{{data.urlprefix}}/admin/input/email/{{data.pk}}/change</a> <a href="{{data.url_prefix}}/admin/input/email/{{data.pk}}/change">{{data.url_prefix}}/admin/input/email/{{data.pk}}/change</a>
{% elif data.choice == 'IFG'%} {% elif data.choice == 'IFG'%}
<a href="{{data.urlprefix}}/admin/input/ifg/{{data.pk}}/change">{{data.urlprefix}}/admin/input/ifg/{{data.pk}}/change</a> <a href="{{data.url_prefix}}/admin/input/ifg/{{data.pk}}/change">{{data.url_prefix}}/admin/input/ifg/{{data.pk}}/change</a>
{% elif data.choice == 'LIST'%} {% elif data.choice == 'LIST'%}
<a href="{{data.urlprefix}}/admin/input/list/{{data.pk}}/change">{{data.urlprefix}}/admin/input/list/{{data.pk}}/change</a> <a href="{{data.url_prefix}}/admin/input/list/{{data.pk}}/change">{{data.url_prefix}}/admin/input/list/{{data.pk}}/change</a>
{% elif data.choice == 'TRAV'%} {% elif data.choice == 'TRAV'%}
<a href="{{data.urlprefix}}/admin/input/travel/{{data.pk}}/change">{{data.urlprefix}}/admin/input/travel/{{data.pk}}/change</a> <a href="{{data.url_prefix}}/admin/input/travel/{{data.pk}}/change">{{data.url_prefix}}/admin/input/travel/{{data.pk}}/change</a>
{% elif data.choice == 'SOFT'%} {% elif data.choice == 'SOFT'%}
<a href="{{data.urlprefix}}/admin/input/library/{{data.pk}}/change">{{data.urlprefix}}/admin/input/library/{{data.pk}}/change</a> <a href="{{data.url_prefix}}/admin/input/library/{{data.pk}}/change">{{data.url_prefix}}/admin/input/library/{{data.pk}}/change</a>
{% elif data.choice == 'VIS'%} {% elif data.choice == 'VIS'%}
<a href="{{data.urlprefix}}/admin/input/businesscard/{{data.pk}}/change">{{data.urlprefix}}/admin/input/businesscard/{{data.pk}}/change</a> <a href="{{data.url_prefix}}/admin/input/businesscard/{{data.pk}}/change">{{data.url_prefix}}/admin/input/businesscard/{{data.pk}}/change</a>
{% endif %} {% endif %}
Zum Genehmigen hier klicken: {{data.urlprefix}}{% url 'authorize' data.choice data.pk %} Zum Genehmigen hier klicken: {{data.url_prefix}}{% url 'authorize' data.choice data.pk %}
Zu Ablehnen hier klicken: {{data.urlprefix}}{% url 'deny' data.choice data.pk %} Zu Ablehnen hier klicken: {{data.url_prefix}}{% url 'deny' data.choice data.pk %}
Stets zu Diensten, Deine Förderdatenbank Stets zu Diensten, Deine Förderdatenbank

View File

@ -34,7 +34,7 @@ Förderprogramme im Sinne der Communitys weiter zu verbessern. Wir freuen uns,
wenn du dir kurz die Zeit dafür nehmen würdest. Die Umfrage mit weiteren wenn du dir kurz die Zeit dafür nehmen würdest. Die Umfrage mit weiteren
Informationen findest du unter dem folgenden Link:<br> Informationen findest du unter dem folgenden Link:<br>
<a href="{{SURVEYPREFIX}}{% if type == 'PRO' %}O{% else %}I{% endif %}=1&{{pid}}=1">{{SURVEYPREFIX}}{% if type == 'PRO' %}O{% else %}I{% endif %}=1&{{pid}}=1</a><br><br> <a href="{{SURVEY_PREFIX}}{% if type == 'PRO' %}O{% else %}I{% endif %}=1&{{pid}}=1">{{SURVEY_PREFIX}}{% if type == 'PRO' %}O{% else %}I{% endif %}=1&{{pid}}=1</a><br><br>
Da dies eine automatisch erzeugte Nachricht ist, wende dich bei Rückfragen zur Umfrage bitte an <a href="mailto: community@wikimedia.de">community@wikimedia.de</a> Da dies eine automatisch erzeugte Nachricht ist, wende dich bei Rückfragen zur Umfrage bitte an <a href="mailto: community@wikimedia.de">community@wikimedia.de</a>

View File

@ -32,6 +32,6 @@ Förderprogramme im Sinne der Communitys weiter zu verbessern. Wir freuen uns,
wenn du dir kurz die Zeit dafür nehmen würdest. Die Umfrage mit weiteren wenn du dir kurz die Zeit dafür nehmen würdest. Die Umfrage mit weiteren
Informationen findest du unter dem folgenden Link: Informationen findest du unter dem folgenden Link:
{{SURVEYPREFIX}}{% if type == 'PRO' %}O{% else %}I{% endif %}=1&{{pid}}=1 {{SURVEY_PREFIX}}{% if type == 'PRO' %}O{% else %}I{% endif %}=1&{{pid}}=1
Da dies eine automatisch erzeugte Nachricht ist, wende dich bei Rückfragen zur Umfrage bitte an community@wikimedia.de Da dies eine automatisch erzeugte Nachricht ist, wende dich bei Rückfragen zur Umfrage bitte an community@wikimedia.de

View File

@ -0,0 +1,54 @@
YES_NO = {
'y': True,
'Y': True,
'yes': True,
'YES': True,
'n': False,
'N': False,
'no': False,
'NO': False,
}
ZERO_ONE = {
1: True,
'1': True,
0: False,
'0': False,
}
TRUE_FALSE = {
True: True,
'TRUE': True,
'True': True,
'true': True,
't': True,
False: False,
'FALSE': False,
'False': False,
'false': False,
'f': False,
None: False,
}
ON_OFF = {
'on': True,
'ON': True,
'off': False,
'OFF': False,
}
TRUTHY = {
**YES_NO,
**ZERO_ONE,
**TRUE_FALSE,
**ON_OFF,
}
def ask(question, default=False, truthy=None):
response = input(question).strip()
return (truthy or YES_NO).get(response, default)
confirm = ask

42
input/utils/settings.py Normal file
View File

@ -0,0 +1,42 @@
import os
from .confirmation import TRUTHY
def env(key, default=None, parser=None):
value = os.environ.get(key)
if value is None:
return default
if parser is None:
if default is None:
return value
else:
parser = type(default)
if parser is bool:
return truthy(value, default)
return parser(value)
def truthy(value, default=False):
return TRUTHY.get(value, default)
def password_validators(*validators):
return list(_parse_password_validators(validators))
def _parse_password_validators(validators):
for validator in validators:
if isinstance(validator, (tuple, list)):
validator, options = validator
else:
validator, options = validator, {}
if '.' not in validator:
validator = 'django.contrib.auth.password_validation.%s' % validator
yield dict(NAME=validator, OPTIONS=options)

View File

@ -9,6 +9,7 @@ from django.core.mail import send_mail, BadHeaderError, EmailMultiAlternatives
from django.conf import settings from django.conf import settings
from django.template.loader import get_template from django.template.loader import get_template
from django.template import Context from django.template import Context
from django.conf import settings
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.utils.html import format_html from django.utils.html import format_html
@ -18,7 +19,6 @@ from .forms import ProjectForm, ExternForm, LibraryForm, IFGForm, LiteratureForm
HonoraryCertificateForm, InternForm, TravelForm, EmailForm,\ HonoraryCertificateForm, InternForm, TravelForm, EmailForm,\
ListForm, BusinessCardForm, INTERN_CHOICES ListForm, BusinessCardForm, INTERN_CHOICES
from .models import Project, TYPE_CHOICES, Library, Literature, Travel, IFG, BusinessCard, Email, List from .models import Project, TYPE_CHOICES, Library, Literature, Travel, IFG, BusinessCard, Email, List
from .settings import IF_EMAIL
def auth_deny(choice,pk,auth): def auth_deny(choice,pk,auth):
if choice in ('BIB', 'ELIT', 'SOFT'): if choice in ('BIB', 'ELIT', 'SOFT'):
@ -244,7 +244,7 @@ class ExternView(CookieWizardView):
# add some data to context for mail templates # add some data to context for mail templates
data['pk'] = modell.pk data['pk'] = modell.pk
data['urlprefix'] = settings.URLPREFIX data['url_prefix'] = settings.EMAIL_URL_PREFIX
data['grant'] = ('LIT', 'SOFT', 'ELIT', 'BIB', 'IFG') data['grant'] = ('LIT', 'SOFT', 'ELIT', 'BIB', 'IFG')
data['DOMAIN'] = ('MAIL', 'LIST') data['DOMAIN'] = ('MAIL', 'LIST')
data['typestring'] = TYPE_CHOICES[data['choice']] data['typestring'] = TYPE_CHOICES[data['choice']]
@ -257,7 +257,7 @@ class ExternView(CookieWizardView):
txt_mail_template1 = get_template('input/ifg_volunteer_mail.txt') txt_mail_template1 = get_template('input/ifg_volunteer_mail.txt')
html_mail_template1 = get_template('input/ifg_volunteer_mail.html') html_mail_template1 = get_template('input/ifg_volunteer_mail.html')
subject1, from_email1, to1 = 'Formular ausgefüllt', IF_EMAIL, data['email'] subject1, from_email1, to1 = 'Formular ausgefüllt', settings.IF_EMAIL, data['email']
text_content1 = txt_mail_template1.render(context) text_content1 = txt_mail_template1.render(context)
html_content1 = html_mail_template1.render(context) html_content1 = html_mail_template1.render(context)
msg1 = EmailMultiAlternatives(subject1, text_content1, from_email1, [to1]) msg1 = EmailMultiAlternatives(subject1, text_content1, from_email1, [to1])
@ -275,7 +275,7 @@ class ExternView(CookieWizardView):
txt_mail_template = get_template('input/if_mail.txt') txt_mail_template = get_template('input/if_mail.txt')
html_mail_template = get_template('input/if_mail.html') html_mail_template = get_template('input/if_mail.html')
subject, from_email, to = 'Formular ausgefüllt', IF_EMAIL, IF_EMAIL subject, from_email, to = 'Formular ausgefüllt', settings.IF_EMAIL, settings.IF_EMAIL
text_content = txt_mail_template.render(context) text_content = txt_mail_template.render(context)
html_content = html_mail_template.render(context) html_content = html_mail_template.render(context)
msg2 = EmailMultiAlternatives(subject, text_content, from_email, [to]) msg2 = EmailMultiAlternatives(subject, text_content, from_email, [to])

View File

@ -11,6 +11,7 @@ gunicorn==20.0.4
idna==3.4 idna==3.4
mysqlclient==2.1.1 mysqlclient==2.1.1
pycparser==2.21 pycparser==2.21
python-dotenv==1.1.1
pytz==2023.3.post1 pytz==2023.3.post1
requests==2.31.0 requests==2.31.0
six==1.16.0 six==1.16.0