Commit 7e2a4a7b authored by Lars Kruse's avatar Lars Kruse
Browse files

refactor(settings): centralize evaluation of grouprise settings

Previously the various settings were accessed in the places, where they
are used.  This also included the specification of default values.
Now all settings and their defaults are evaluated in a single location
(grouprise.core.settings).

Most users of grouprise settings should use the following pattern:

  from grouprise.core.settings import FOO

If test-related mocking of settings is relevant, then the module should
be imported instead (in order to allow dynamic attribute overrides):

  import grouprise.core.settings as grouprise_settings

See #648
parent b9083ffa
from django.conf import settings as django_settings
from django.contrib.sites.models import Site
from django.templatetags.static import static
import grouprise.core.settings as grouprise_settings
def settings(request):
gr_settings = django_settings.GROUPRISE
return {
'GROUPRISE_CLAIMS': gr_settings.get('CLAIMS', []),
'GROUPRISE_SITE_NAME': Site.objects.get_current().name,
'GROUPRISE_THEME_COLOR': gr_settings.get('BRANDING_THEME_COLOR', '#2a62ac'),
'GROUPRISE_LOGO_TEXT': gr_settings.get(
'BRANDING_LOGO_TEXT', static('core/logos/logo-text.svg')),
'GROUPRISE_LOGO_BACKDROP': gr_settings.get(
'BRANDING_LOGO_BACKDROP', static('core/logos/logo-backdrop.svg')),
'GROUPRISE_LOGO_SQUARE': gr_settings.get(
'BRANDING_LOGO_SQUARE', static('core/logos/logo-square.svg')),
'GROUPRISE_LOGO_FAVICON': gr_settings.get(
'BRANDING_LOGO_FAVICON', static('core/logos/logo-square.png')),
"GROUPRISE_CLAIMS": grouprise_settings.CLAIMS,
"GROUPRISE_SITE_NAME": Site.objects.get_current().name,
"GROUPRISE_THEME_COLOR": grouprise_settings.THEME_COLOR,
"GROUPRISE_LOGO_TEXT": grouprise_settings.LOGO_TEXT,
"GROUPRISE_LOGO_BACKDROP": grouprise_settings.LOGO_BACKDROP,
"GROUPRISE_LOGO_SQUARE": grouprise_settings.LOGO_SQUARE,
"GROUPRISE_LOGO_FAVICON": grouprise_settings.LOGO_FAVICON,
}
......@@ -6,6 +6,8 @@ import subprocess
from django.core.management.base import BaseCommand, CommandError
from django.conf import settings
from grouprise.core.settings import BACKUP_PATH
def create_filename(directory, prefix, filename=None, suffix=''):
return os.path.abspath(os.path.join(directory, '{prefix}{filename}{suffix}'.format(**{
......@@ -49,8 +51,7 @@ class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument('--prefix', default='', help='prefix for the filename')
parser.add_argument('--output-dir', default=settings.GROUPRISE.get("BACKUP_PATH", "."),
help='backup storage dir')
parser.add_argument('--output-dir', default=BACKUP_PATH, help='backup storage dir')
parser.add_argument('--output-file', default=None, help='backup filename')
def handle(self, *args, **options):
......
import itertools
import django.contrib.contenttypes.models
from django.conf import settings
from django.contrib.contenttypes import models as contenttypes_models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
......@@ -9,19 +8,20 @@ from django.db import models
from django.utils import crypto
import django.utils.timezone
MAX_FILE_SIZE = settings.GROUPRISE.get('UPLOAD_MAX_FILE_SIZE', 10)
from grouprise.core.settings import UPLOAD_MAX_FILE_SIZE as UPLOAD_MAX_FILE_SIZE_MB
IMAGE_FIELD_HELP_TEXT = (
'Mögliche Formate sind JPEG, PNG und viele weitere. Nicht unterstützt werden PDF- '
'oder SVG-Dateien. Die maximal erlaubte Dateigröße beträgt {} MB.'.format(
MAX_FILE_SIZE))
UPLOAD_MAX_FILE_SIZE_MB))
PERMISSION_TOKEN_LENGTH = 15
def validate_file_size(f):
try:
if f._size > MAX_FILE_SIZE * 1024 * 1024:
if f._size > UPLOAD_MAX_FILE_SIZE_MB * 1024 * 1024:
raise django.forms.ValidationError('Die Datei ist zu groß.')
except AttributeError:
pass
......
......@@ -11,20 +11,18 @@ from django.core import mail
from django.template import loader
from grouprise.core.models import PermissionToken
import grouprise.core.settings as grouprise_settings
from grouprise.core.templatetags.defaultfilters import full_url as build_absolute_uri
logger = logging.getLogger(__name__)
DEFAULT_REPLY_TO_EMAIL = settings.GROUPRISE.get(
'DEFAULT_REPLY_TO_EMAIL', 'reply+{reply_key}@localhost')
class Notification:
@classmethod
def send_all(cls, instance, force=False, **extra_kwargs):
for recipient, kwargs in cls.get_recipients(instance).items():
if (force or not recipient.is_email_blocker) and (
recipient.id != settings.GROUPRISE.get('FEED_IMPORTER_GESTALT_ID')):
recipient.id != grouprise_settings.FEED_IMPORTER_GESTALT_ID):
kwargs.update(extra_kwargs)
cls(instance).send(recipient, **kwargs)
......@@ -65,16 +63,14 @@ class Notification:
return '{} <{}>'.format(self.recipient, self.recipient.user.email)
def get_formatted_reply_address(self, token):
return '<{}>'.format(DEFAULT_REPLY_TO_EMAIL.format(
return '<{}>'.format(grouprise_settings.DEFAULT_REPLY_TO_EMAIL.format(
reply_key=token.secret_key))
def get_formatted_sender(self):
sender = self.get_sender()
name = '{} via '.format(sender) if sender else ''
if sender:
email = settings.GROUPRISE \
.get('DEFAULT_DISTINCT_FROM_EMAIL', 'noreply+{slug}@localhost') \
.format(slug=sender.slug)
email = grouprise_settings.DEFAULT_DISTINCT_FROM_EMAIL.format(slug=sender.slug)
else:
email = settings.DEFAULT_FROM_EMAIL
from_email = '{name}{site} <{email}>'.format(
......
import os
from django.conf import settings
from django.templatetags.static import static
_GR = settings.GROUPRISE
# branding
CLAIMS = _GR.get("CLAIMS", [])
LOGO_BACKDROP = _GR.get(
"BRANDING_LOGO_BACKDROP", static("core/logos/logo-backdrop.svg")
)
LOGO_FAVICON = _GR.get("BRANDING_LOGO_FAVICON", static("core/logos/logo-square.png"))
LOGO_SQUARE = _GR.get("BRANDING_LOGO_SQUARE", static("core/logos/logo-square.svg"))
LOGO_TEXT = _GR.get("BRANDING_LOGO_TEXT", static("core/logos/logo-text.svg"))
THEME_COLOR = _GR.get("BRANDING_THEME_COLOR", "#2a62ac")
# mail handling
COLLECTOR_MAILBOX_ADDRESS = _GR.get("COLLECTOR_MAILBOX_ADDRESS", None)
DEFAULT_DISTINCT_FROM_EMAIL = _GR.get(
"DEFAULT_DISTINCT_FROM_EMAIL", "noreply+{slug}@localhost"
)
DEFAULT_REPLY_TO_EMAIL = _GR.get(
"DEFAULT_REPLY_TO_EMAIL", "reply+{reply_key}@localhost"
)
MAILINGLIST_ENABLED = _GR.get("MAILINGLIST_ENABLED", False)
POSTMASTER_EMAIL = _GR.get("POSTMASTER_EMAIL", "postmaster@localhost")
# content import
FEED_IMPORTER_GESTALT_ID = _GR.get("FEED_IMPORTER_GESTALT_ID", None)
OPERATOR_GROUP_ID = _GR.get("OPERATOR_GROUP_ID", 1)
UNKNOWN_GESTALT_ID = _GR.get("UNKNOWN_GESTALT_ID", 1)
# local administration
BACKUP_PATH = _GR.get("BACKUP_PATH", os.getcwd())
HOOK_SCRIPT_PATHS = _GR.get("HOOK_SCRIPT_PATHS", [])
# miscellaneous
ENTITY_SLUG_BLACKLIST = _GR.get(
"ENTITY_SLUG_BLACKLIST",
[
"all",
"grouprise",
"info",
"mail",
"noreply",
"postmaster",
"reply",
"stadt",
"webmaster",
"www",
],
)
SCORE_CONTENT_AGE = _GR.get("SCORE_CONTENT_AGE", 100)
UPLOAD_MAX_FILE_SIZE = _GR.get("UPLOAD_MAX_FILE_SIZE", 10)
import contextlib
import logging
from django.conf import settings
import django.urls
from django import test, urls
from django.contrib import auth
......@@ -9,6 +8,8 @@ from django.contrib.sites import models as sites_models
from django.core import mail
from simplemathcaptcha.utils import hash_answer
import grouprise.core.settings as grouprise_settings
HTTP_GET = 'get'
HTTP_POST = 'post'
......@@ -24,20 +25,26 @@ def get_url(url, *args):
@contextlib.contextmanager
def temporary_settings_override(key, value):
""" provide a context for temporarily changing a setting in the GROUPRISE dictionary """
""" provide a context for temporarily changing a setting in the GROUPRISE dictionary
This override only works, if the setting is accessed as an attributes of the
grouprise.core.settings module.
Thus direct imports of the values (e.g. "from grouprise.core.settings import FOO") are not
affected by such overrides.
"""
try:
original_value = settings.GROUPRISE[key]
original_value = getattr(grouprise_settings, key)
is_missing = False
except KeyError:
except AttributeError:
is_missing = True
settings.GROUPRISE[key] = value
setattr(grouprise_settings, key, value)
try:
yield
finally:
if is_missing:
del settings.GROUPRISE[key]
delattr(grouprise_settings, key)
else:
settings.GROUPRISE[key] = original_value
setattr(grouprise_settings, key, original_value)
def with_captcha(data, answer=10, field_name='captcha'):
......
......@@ -2,7 +2,7 @@ import os
from django import forms
from grouprise.core.models import MAX_FILE_SIZE
from grouprise.core.settings import UPLOAD_MAX_FILE_SIZE
from grouprise.features.content import forms as content
......@@ -10,7 +10,7 @@ class Create(content.Create):
text = forms.CharField(label='Beschreibung', widget=forms.Textarea({'rows': 2}))
file = forms.FileField(
label='Datei', help_text='Die maximal erlaubte Dateigröße beträgt {} MB.'.format(
MAX_FILE_SIZE))
UPLOAD_MAX_FILE_SIZE))
def save(self, commit=True):
association = super().save(False)
......@@ -27,7 +27,7 @@ class Update(content.Update):
text = forms.CharField(label='Beschreibung', widget=forms.Textarea({'rows': 2}))
file = forms.FileField(
label='Datei', help_text='Die maximal erlaubte Dateigröße beträgt {} MB.'.format(
MAX_FILE_SIZE))
UPLOAD_MAX_FILE_SIZE))
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
......
......@@ -9,6 +9,7 @@ from imagekit.models import ImageSpecField
from imagekit.processors import SmartResize, Transpose
import grouprise.core
from grouprise.core.settings import UNKNOWN_GESTALT_ID
from grouprise.core.utils import get_random_color
......@@ -81,7 +82,7 @@ class Gestalt(grouprise.core.models.Model):
def delete(self, *args, **kwargs):
data = self.get_data()
unknown_gestalt = Gestalt.objects.get(id=settings.GROUPRISE.get('UNKNOWN_GESTALT_ID', 1))
unknown_gestalt = Gestalt.objects.get(id=UNKNOWN_GESTALT_ID)
data['associations'].update(entity_id=unknown_gestalt.id)
data['contributions'].update(author=unknown_gestalt)
data['images'].update(creator=unknown_gestalt)
......
......@@ -2,7 +2,6 @@ import datetime
import django
from django import urls
from django.conf import settings
from django.contrib.contenttypes.fields import GenericRelation
from django.db import models
from django.utils.translation import gettext as _
......@@ -11,6 +10,7 @@ from imagekit.processors import ResizeToFit, Transpose
from taggit.managers import TaggableManager
import grouprise.core.models
from grouprise.core.settings import OPERATOR_GROUP_ID
from grouprise.core.utils import get_random_color
from grouprise.features.gestalten.models import Gestalt
from grouprise.features.stadt.models import EntitySlugField
......@@ -18,8 +18,7 @@ from grouprise.features.stadt.models import EntitySlugField
class GroupManager(models.Manager):
def operator_group(self):
operator_group_id = settings.GROUPRISE.get('OPERATOR_GROUP_ID', 1)
return self.get_queryset().filter(id=operator_group_id).first()
return self.get_queryset().filter(id=OPERATOR_GROUP_ID).first()
class Group(grouprise.core.models.Model):
......
......@@ -3,11 +3,11 @@ import logging
import shlex
import subprocess
from django.conf import settings
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from huey.contrib.djhuey import db_task
from grouprise.core.settings import HOOK_SCRIPT_PATHS
from grouprise.core.utils import slugify
from grouprise.features.gestalten import models as gestalten
from grouprise.features.stadt.forms import ENTITY_SLUG_BLACKLIST
......@@ -26,8 +26,7 @@ def call_hook_script(event_type: str, group: Group, timeout=300):
"objectData": {"id": group.id, "slug": group.slug},
}
)
hook_script_names = settings.GROUPRISE.get("HOOK_SCRIPT_PATHS", [])
for script_name in hook_script_names:
for script_name in HOOK_SCRIPT_PATHS:
try:
subprocess.run(
[script_name, hook_event_info_json],
......
import re
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.messages.views import SuccessMessageMixin
from django.contrib.sites.models import Site
......@@ -14,6 +13,7 @@ from django.views.generic.edit import FormView
from django.views.generic.list import MultipleObjectMixin
from django_filters.views import FilterView
from grouprise.core.settings import MAILINGLIST_ENABLED
from grouprise.core.views import PermissionMixin, TemplateFilterMixin
from grouprise.features.associations import models as associations
from grouprise.features.content.filters import ContentFilterSet
......@@ -52,11 +52,10 @@ class Detail(PermissionMixin, TemplateFilterMixin, MultipleObjectMixin, DetailVi
intro_gallery = intro_associations.filter_galleries().filter(public=True).first()
if intro_gallery:
intro_associations = intro_associations.exclude(pk=intro_gallery.pk)
mailinglist_conf = settings.GROUPRISE.get('MAILINGLIST_ENABLED', False)
kwargs['feed_url'] = self.request.build_absolute_uri(
reverse('group-feed', args=(self.object.pk,)))
return super().get_context_data(
GROUPRISE_MAILINGLIST_ENABLED=mailinglist_conf,
GROUPRISE_MAILINGLIST_ENABLED=MAILINGLIST_ENABLED,
associations=associations,
intro_associations=intro_associations,
intro_gallery=intro_gallery,
......
......@@ -5,11 +5,11 @@ import time
import urllib.request
import django
from django.conf import settings
import feedparser
import grouprise.core
from grouprise.core.signals import post_create
from grouprise.core.settings import FEED_IMPORTER_GESTALT_ID
from grouprise.core.templatetags.defaultfilters import html2text
from grouprise.core.utils import slugify
from grouprise.features.associations import models as associations
......@@ -85,9 +85,8 @@ def import_from_feed(feed_url, submitter, target_group):
def run_feed_import_for_groups():
processed_feeds = []
feed_importer_id = settings.GROUPRISE.get("FEED_IMPORTER_GESTALT_ID")
if feed_importer_id is not None:
author = gestalten.Gestalt.objects.get(id=feed_importer_id)
if FEED_IMPORTER_GESTALT_ID is not None:
author = gestalten.Gestalt.objects.get(id=FEED_IMPORTER_GESTALT_ID)
for group in groups.Group.objects.filter(url_import_feed=True):
if group.url:
request = urllib.request.Request(
......
......@@ -9,7 +9,7 @@ import django.utils.timezone
import html2text
import grouprise.core.models
from grouprise.core.notifications import DEFAULT_REPLY_TO_EMAIL
from grouprise.core.settings import DEFAULT_REPLY_TO_EMAIL
from grouprise.core.signals import post_create
from grouprise.features.associations import models as associations
from grouprise.features.content.models import Content
......
......@@ -5,9 +5,9 @@ import os
import re
import sys
from django.conf import settings
from django.core.management.base import BaseCommand
from grouprise.core.settings import COLLECTOR_MAILBOX_ADDRESS
from grouprise.features.imports.mails import (
ContributionMailProcessor,
MailProcessingFailure,
......@@ -25,9 +25,6 @@ The content of the line could be:
Delivered-To: Alice <foo@example.org>
"""
DTLINE_REGEX = re.compile(r"^Delivered-To:\s*(.+)$", flags=re.IGNORECASE)
# Email address used in Delivered-To header in case of mailbox delivery (all incoming mails being
# delivered to a single mailbox).
COLLECTOR_MAILBOX_ADDRESS = settings.GROUPRISE.get("COLLECTOR_MAILBOX_ADDRESS")
EXITCODE_TEMPORARY_FAILURE = 1
EXITCODE_PERMANENT_FAILURE = 70
EXITCODE_DELIVERY_SUCCESS = 99
......
......@@ -14,18 +14,14 @@ from aiosmtplib.errors import SMTPRecipientsRefused, SMTPResponseException
from aiosmtplib.smtp import SMTP
import django
import django.db
from django.conf import settings
from grouprise.core.settings import POSTMASTER_EMAIL as POSTMASTER_ADDRESS
from grouprise.features.imports.mails import (
ContributionMailProcessor, MailProcessingFailure, ParsedMailMessage)
logger = logging.getLogger(__name__)
# internal error mails are sent to the postmaster
POSTMASTER_ADDRESS = settings.GROUPRISE.get('POSTMASTER_EMAIL', 'postmaster@localhost')
class Command(django.core.management.base.BaseCommand):
def add_arguments(self, parser):
parser.add_argument('host')
......
......@@ -11,7 +11,7 @@ from django.core import mail
from django.urls import reverse
from grouprise.core import tests
from grouprise.core.notifications import DEFAULT_REPLY_TO_EMAIL
from grouprise.core.settings import DEFAULT_REPLY_TO_EMAIL
from grouprise.features.associations import models as associations
from grouprise.features.contributions import models
from grouprise.features.imports.management.commands.run_lmtpd import (
......
from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.validators import validate_slug
DEFAULT_ENTITY_SLUG_BLACKLIST = [
'all', 'grouprise', 'info', 'mail', 'noreply', 'postmaster', 'reply', 'stadt',
'webmaster', 'www']
ENTITY_SLUG_BLACKLIST = settings.GROUPRISE.get(
'ENTITY_SLUG_BLACKLIST', DEFAULT_ENTITY_SLUG_BLACKLIST)
from grouprise.core.settings import ENTITY_SLUG_BLACKLIST
def validate_entity_slug(slug, entity=None):
......
......@@ -3,7 +3,8 @@ from math import log
import django.conf
import django.utils.timezone
from django.conf import settings
from grouprise.core.settings import SCORE_CONTENT_AGE as MAX_SCORE_CONTENT_AGE_DAYS
from grouprise.features.content import models as content
from grouprise.features.contributions import models as contributions
......@@ -12,9 +13,6 @@ from grouprise.features.groups import models as groups
from grouprise.features.subscriptions import models as subscriptions
MAX_SCORE_CONTENT_AGE_DAYS = settings.GROUPRISE.get('SCORE_CONTENT_AGE', 100)
class Gestalt:
@classmethod
def score(cls, instance):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment