From e7db753444d86916b20327d25df7b3e464f810b3 Mon Sep 17 00:00:00 2001 From: Felix Rindt Date: Thu, 26 Dec 2024 13:46:54 +0100 Subject: [PATCH 1/7] add dynamic_settings --- ephios/core/dynamic.py | 25 +++++++++++++++++++ ephios/core/ical.py | 4 +-- .../core/migrations/0022_identityprovider.py | 2 +- ephios/core/services/files.py | 10 +++++--- ephios/core/services/notifications/types.py | 4 +-- ephios/core/services/password_reset.py | 5 ++-- ephios/core/signals.py | 8 ++++++ ephios/core/templatetags/settings_extras.py | 6 ++--- ephios/core/views/auth.py | 6 ++--- ephios/extra/auth.py | 4 +-- ephios/extra/templatetags/rich_text.py | 5 ++-- ephios/plugins/federation/forms.py | 4 +-- ephios/plugins/federation/models.py | 4 +-- ephios/plugins/federation/serializers.py | 4 +-- ephios/plugins/federation/views/api.py | 5 ++-- ephios/settings.py | 14 +++-------- tests/settings.py | 4 +-- 17 files changed, 70 insertions(+), 44 deletions(-) create mode 100644 ephios/core/dynamic.py diff --git a/ephios/core/dynamic.py b/ephios/core/dynamic.py new file mode 100644 index 000000000..b0b8f8e6e --- /dev/null +++ b/ephios/core/dynamic.py @@ -0,0 +1,25 @@ +class DynamicSettingsProxy: + """ + Proxy access to django settings but first check if any receiver overwrites it with a dynamic value. + """ + + NONE = object() + + def __init__(self): + from django.conf import settings + + self._django_settings = settings + + def __getattr__(self, name): + from ephios.core.signals import provide_dynamic_settings + + for _, result in provide_dynamic_settings.send(None, name=name): + if result is not None: + if result is DynamicSettingsProxy.NONE: + return None + return result + # default to django settings + return getattr(self._django_settings, f"DEFAULT_{name}") + + +dynamic_settings = DynamicSettingsProxy() diff --git a/ephios/core/ical.py b/ephios/core/ical.py index cca742932..a90fc019b 100644 --- a/ephios/core/ical.py +++ b/ephios/core/ical.py @@ -1,4 +1,3 @@ -from django.conf import settings from django.contrib.auth import get_user_model from django.db.models import Prefetch from django.shortcuts import get_object_or_404 @@ -6,6 +5,7 @@ from guardian.shortcuts import get_users_with_perms from icalendar import vCalAddress +from ephios.core.dynamic import dynamic_settings from ephios.core.models import AbstractParticipation, Shift @@ -38,7 +38,7 @@ def item_location(self, item): return item.event.location def item_guid(self, item): - return f"{item.pk}@{settings.GET_SITE_URL()}" + return f"{item.pk}@{dynamic_settings.SITE_URL}" def item_organizer(self, item): user = get_users_with_perms(item.event, only_with_perms_in=["change_event"]).first() diff --git a/ephios/core/migrations/0022_identityprovider.py b/ephios/core/migrations/0022_identityprovider.py index 57e9b9a3b..c9f934aa6 100644 --- a/ephios/core/migrations/0022_identityprovider.py +++ b/ephios/core/migrations/0022_identityprovider.py @@ -4,7 +4,7 @@ def migrate_oidc_provider(apps, schema_editor): - from ephios import settings + from django.conf import settings try: if settings.env.bool("ENABLE_OIDC_CLIENT"): diff --git a/ephios/core/services/files.py b/ephios/core/services/files.py index e1069d7cd..4ef38ccf0 100644 --- a/ephios/core/services/files.py +++ b/ephios/core/services/files.py @@ -11,6 +11,8 @@ from django.urls import reverse from django.views import View +from ephios.core.dynamic import dynamic_settings + class UserContentView(View): """ @@ -22,7 +24,7 @@ class UserContentView(View): def dispatch(self, request, *args, **kwargs): # If media files are served from a different domain and # the user requests media files from the app domain via this view --> 404 - if (loc := urlsplit(settings.GET_USERCONTENT_URL()).netloc) and request.get_host() != loc: + if (loc := urlsplit(dynamic_settings.USERCONTENT_URL).netloc) and request.get_host() != loc: raise PermissionDenied() return super().dispatch(request, *args, **kwargs) @@ -64,7 +66,7 @@ def redirect_to_file_download(field_file): """ Shortcut for redirecting to the ticketed media file download view. """ - if loc := urlsplit(settings.GET_USERCONTENT_URL()).netloc: + if loc := urlsplit(dynamic_settings.USERCONTENT_URL).netloc: ticket = file_ticket(field_file) path = reverse("core:file_ticket", kwargs={"ticket": ticket}) return redirect(urlunsplit(("http" if settings.DEBUG else "https", loc, path, "", ""))) @@ -81,9 +83,9 @@ def __call__(self, request): response = self.get_response(request) if ( # if the usercontent URL does not contain a domain, the request host will be checked against `None` --> no redirect loop - request.get_host() == urlsplit(settings.GET_USERCONTENT_URL()).netloc + request.get_host() == urlsplit(dynamic_settings.USERCONTENT_URL).netloc and request.resolver_match and not getattr(request.resolver_match.func.view_class, "is_usercontent_view", False) ): - return redirect(urljoin(settings.GET_SITE_URL(), request.path)) + return redirect(urljoin(dynamic_settings.SITE_URL, request.path)) return response diff --git a/ephios/core/services/notifications/types.py b/ephios/core/services/notifications/types.py index 2cd8271b6..b8bddcee3 100644 --- a/ephios/core/services/notifications/types.py +++ b/ephios/core/services/notifications/types.py @@ -1,7 +1,6 @@ from typing import List from urllib.parse import urlparse -from django.conf import settings from django.contrib.auth.tokens import default_token_generator from django.template.loader import render_to_string from django.urls import reverse @@ -13,6 +12,7 @@ from guardian.shortcuts import get_users_with_perms from requests import PreparedRequest +from ephios.core.dynamic import dynamic_settings from ephios.core.models import AbstractParticipation, Event, LocalParticipation, UserProfile from ephios.core.models.users import Consequence, Notification from ephios.core.signals import register_notification_types @@ -98,7 +98,7 @@ def get_actions_with_referrer(cls, notification): """ actions = [] for label, url in cls.get_actions(notification): - if urlparse(url).netloc in settings.GET_SITE_URL(): + if urlparse(url).netloc in dynamic_settings.SITE_URL: req = PreparedRequest() req.prepare_url(url, {NOTIFICATION_READ_PARAM_NAME: notification.pk}) url = req.url diff --git a/ephios/core/services/password_reset.py b/ephios/core/services/password_reset.py index 8490867c2..c7d90465f 100644 --- a/ephios/core/services/password_reset.py +++ b/ephios/core/services/password_reset.py @@ -1,11 +1,12 @@ import logging -from django.conf import settings from django.contrib.auth.password_validation import MinimumLengthValidator from django.core.mail import EmailMultiAlternatives from django.template.loader import render_to_string from django.utils.translation import gettext as _ +from ephios.core.dynamic import dynamic_settings + logger = logging.getLogger(__name__) @@ -19,7 +20,7 @@ def password_changed(self, password, user): # send notification to user text_content = _( "Your password for {site} has been changed. If you didn't request this change, contact an administrator immediately." - ).format(site=settings.GET_SITE_URL()) + ).format(site=dynamic_settings.SITE_URL) html_content = render_to_string( "core/mails/base.html", { diff --git a/ephios/core/signals.py b/ephios/core/signals.py index a78ecf903..bfe784de3 100644 --- a/ephios/core/signals.py +++ b/ephios/core/signals.py @@ -185,6 +185,14 @@ """ +provide_dynamic_settings = PluginSignal() +""" +Use this signal to overwrite the defaults of django settings accessed +using ``ephios.core.signals.DynamicSettingsProxy``. +Receivers receive a ``name`` keyword argument naming the setting. +""" + + @receiver( register_consequence_handlers, dispatch_uid="ephios.core.signals.register_base_consequence_handlers", diff --git a/ephios/core/templatetags/settings_extras.py b/ephios/core/templatetags/settings_extras.py index 8d329578e..6816a3cf1 100644 --- a/ephios/core/templatetags/settings_extras.py +++ b/ephios/core/templatetags/settings_extras.py @@ -1,9 +1,9 @@ from urllib.parse import urljoin from django import template -from django.conf import settings from dynamic_preferences.registries import global_preferences_registry +from ephios.core.dynamic import dynamic_settings from ephios.core.models.users import IdentityProvider register = template.Library() @@ -23,7 +23,7 @@ def identity_providers(): @register.simple_tag def site_url(): - return settings.GET_SITE_URL() + return dynamic_settings.SITE_URL @register.simple_tag @@ -33,7 +33,7 @@ def organization_name(): @register.filter def make_absolute(location): - return urljoin(settings.GET_SITE_URL(), location) + return urljoin(dynamic_settings.SITE_URL, location) @register.simple_tag(takes_context=True) diff --git a/ephios/core/views/auth.py b/ephios/core/views/auth.py index bab95dfb0..7e37611bc 100644 --- a/ephios/core/views/auth.py +++ b/ephios/core/views/auth.py @@ -1,7 +1,6 @@ from urllib.parse import urljoin import requests -from django.conf import settings from django.contrib import auth, messages from django.contrib.auth.views import LoginView from django.contrib.messages.views import SuccessMessageMixin @@ -23,6 +22,7 @@ from requests import PreparedRequest, RequestException from requests_oauthlib import OAuth2Session +from ephios.core.dynamic import dynamic_settings from ephios.core.dynamic_preferences_registry import LoginRedirectToSoleIndentityProvider from ephios.core.forms.auth import OIDCLoginForm from ephios.core.forms.users import IdentityProviderForm, OIDCDiscoveryForm @@ -38,7 +38,7 @@ def get_redirect_url(self, *args, **kwargs): oauth_client = WebApplicationClient(client_id=provider.client_id) oauth = OAuth2Session( client=oauth_client, - redirect_uri=urljoin(settings.GET_SITE_URL(), reverse("core:oidc_callback")), + redirect_uri=urljoin(dynamic_settings.SITE_URL, reverse("core:oidc_callback")), scope=provider.scopes, ) @@ -93,7 +93,7 @@ def get_redirect_url(self, *args, **kwargs): {} if auto_provider_redirect else { - "post_logout_redirect_uri": settings.GET_SITE_URL(), + "post_logout_redirect_uri": dynamic_settings.SITE_URL, "client_id": provider.client_id, } ), diff --git a/ephios/extra/auth.py b/ephios/extra/auth.py index 3e455d67a..00198e19f 100644 --- a/ephios/extra/auth.py +++ b/ephios/extra/auth.py @@ -4,7 +4,6 @@ from urllib.parse import urljoin import jwt -from django.conf import settings from django.contrib.auth import get_user_model from django.contrib.auth.backends import ModelBackend from django.contrib.auth.models import Group @@ -16,6 +15,7 @@ from requests_oauthlib import OAuth2Session from urllib3.exceptions import RequestError +from ephios.core.dynamic import dynamic_settings from ephios.core.models import Qualification from ephios.core.models.users import IdentityProvider, QualificationGrant from ephios.core.signals import oidc_update_user @@ -99,7 +99,7 @@ def authenticate(self, request, username=None, password=None, **kwargs): self.provider = IdentityProvider.objects.get(id=request.session["oidc_provider"]) oauth = OAuth2Session( client=WebApplicationClient(client_id=self.provider.client_id), - redirect_uri=urljoin(settings.GET_SITE_URL(), reverse("core:oidc_callback")), + redirect_uri=urljoin(dynamic_settings.SITE_URL, reverse("core:oidc_callback")), ) token = oauth.fetch_token( self.provider.token_endpoint, diff --git a/ephios/extra/templatetags/rich_text.py b/ephios/extra/templatetags/rich_text.py index 12777981b..f889bf2d9 100644 --- a/ephios/extra/templatetags/rich_text.py +++ b/ephios/extra/templatetags/rich_text.py @@ -4,10 +4,11 @@ import markdown from bleach.linkifier import DEFAULT_CALLBACKS from django import template -from django.conf import settings from django.utils.http import url_has_allowed_host_and_scheme from django.utils.safestring import mark_safe +from ephios.core.dynamic import dynamic_settings + register = template.Library() ALLOWED_TAGS = { @@ -80,7 +81,7 @@ def safelink_callback(attrs, new=False): if not url_has_allowed_host_and_scheme( url, allowed_hosts=[ - urlparse(settings.GET_SITE_URL()).netloc, + urlparse(dynamic_settings.SITE_URL).netloc, ], ): attrs[None, "target"] = "_blank" diff --git a/ephios/plugins/federation/forms.py b/ephios/plugins/federation/forms.py index b04520b17..a9c0289eb 100644 --- a/ephios/plugins/federation/forms.py +++ b/ephios/plugins/federation/forms.py @@ -5,11 +5,11 @@ from urllib.parse import urlparse from django import forms -from django.conf import settings from django.core.exceptions import ValidationError from django.forms import CheckboxSelectMultiple from django.utils.translation import gettext as _ +from ephios.core.dynamic import dynamic_settings from ephios.core.forms.events import BasePluginFormMixin from ephios.plugins.federation.models import FederatedEventShare, FederatedGuest, InviteCode @@ -66,7 +66,7 @@ class RedeemInviteCodeForm(forms.Form): def clean_code(self): try: data = json.loads(base64.b64decode(self.cleaned_data["code"].encode()).decode()) - if settings.GET_SITE_URL() != data["guest_url"]: + if dynamic_settings.SITE_URL != data["guest_url"]: raise ValidationError(_("This invite code is not issued for this instance.")) except (binascii.Error, JSONDecodeError, KeyError) as exc: raise ValidationError(_("Invalid code")) from exc diff --git a/ephios/plugins/federation/models.py b/ephios/plugins/federation/models.py index 95c105ee2..b5d53e80e 100644 --- a/ephios/plugins/federation/models.py +++ b/ephios/plugins/federation/models.py @@ -4,7 +4,6 @@ import json from secrets import token_hex -from django.conf import settings from django.db import models from django.urls import reverse from django.utils import timezone @@ -12,6 +11,7 @@ from django.utils.translation import gettext_lazy as _ from ephios.api.models import AccessToken, Application +from ephios.core.dynamic import dynamic_settings from ephios.core.models import AbstractParticipation, Event, Qualification from ephios.core.models.events import PARTICIPATION_LOG_CONFIG from ephios.core.signup.participants import AbstractParticipant @@ -93,7 +93,7 @@ def is_expired(self): def get_share_string(self): return base64.b64encode( json.dumps( - {"guest_url": self.url, "code": self.code, "host_url": settings.GET_SITE_URL()} + {"guest_url": self.url, "code": self.code, "host_url": dynamic_settings.SITE_URL} ).encode() ).decode() diff --git a/ephios/plugins/federation/serializers.py b/ephios/plugins/federation/serializers.py index 8b69d77a0..22a5ed991 100644 --- a/ephios/plugins/federation/serializers.py +++ b/ephios/plugins/federation/serializers.py @@ -1,13 +1,13 @@ import secrets from urllib.parse import urljoin -from django.conf import settings from django.urls import reverse from dynamic_preferences.registries import global_preferences_registry from rest_framework import serializers from ephios.api.models import AccessToken from ephios.api.serializers import EventSerializer +from ephios.core.dynamic import dynamic_settings from ephios.core.models import Event from ephios.plugins.federation.models import FederatedGuest, InviteCode @@ -71,7 +71,7 @@ class Meta: def get_signup_url(self, obj): return urljoin( - settings.GET_SITE_URL(), + dynamic_settings.SITE_URL, reverse( "federation:event_detail", kwargs={"pk": obj.pk, "guest": self.context["federated_guest"].pk}, diff --git a/ephios/plugins/federation/views/api.py b/ephios/plugins/federation/views/api.py index 71630440d..c0eb438a5 100644 --- a/ephios/plugins/federation/views/api.py +++ b/ephios/plugins/federation/views/api.py @@ -2,7 +2,6 @@ import django_filters import requests -from django.conf import settings from django.core.exceptions import MultipleObjectsReturned from django.db.models import Max, Min from django.shortcuts import redirect @@ -126,7 +125,7 @@ def _get_authorization_url(self): oauth_client = WebApplicationClient(client_id=self.guest.client_id) oauth = OAuth2Session( client=oauth_client, - redirect_uri=urljoin(settings.GET_SITE_URL(), reverse("federation:oauth_callback")), + redirect_uri=urljoin(dynamic_settings.SITE_URL, reverse("federation:oauth_callback")), scope=["ME_READ"], ) verifier = oauth_client.create_code_verifier(64) @@ -148,7 +147,7 @@ def _oauth_callback(self): oauth = OAuth2Session(client=oauth_client) token = oauth.fetch_token( urljoin(self.guest.url, "api/oauth/token/"), - authorization_response=urljoin(settings.GET_SITE_URL(), self.request.get_full_path()), + authorization_response=urljoin(dynamic_settings.SITE_URL, self.request.get_full_path()), client_secret=self.guest.client_secret, code_verifier=self.request.session["code_verifier"], ) diff --git a/ephios/settings.py b/ephios/settings.py index afb6ac624..7f410815a 100644 --- a/ephios/settings.py +++ b/ephios/settings.py @@ -234,6 +234,9 @@ MEDIA_URL = env.str("MEDIA_URL", default="/usercontent/") FALLBACK_MEDIA_SERVING = env.bool("FALLBACK_MEDIA_SERVING", default=DEBUG) +DEFAULT_SITE_URL = env.str("SITE_URL").rstrip("/") +DEFAULT_USERCONTENT_URL = MEDIA_URL + STATICFILES_DIRS = (os.path.join(BASE_DIR, "ephios/static"),) STATICFILES_FINDERS = [ "django.contrib.staticfiles.finders.FileSystemFinder", @@ -318,17 +321,6 @@ } -def GET_SITE_URL(): - site_url = env.str("SITE_URL") - if site_url.endswith("/"): - site_url = site_url[:-1] - return site_url - - -def GET_USERCONTENT_URL(): - return MEDIA_URL - - def GET_USERCONTENT_QUOTA(): """Returns a tuple (used, free) of the user content quota in bytes""" used = sum(p.stat().st_size for p in Path(MEDIA_ROOT).rglob("*")) diff --git a/tests/settings.py b/tests/settings.py index 8f13c9b94..a4bc453f0 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -3,6 +3,4 @@ LANGUAGE_CODE = "en" os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1" - -def GET_SITE_URL(): - return "http://localhost:8000" +DEFAULT_SITE_URL = "http://localhost:8000" From b60cf7b91bc336089484ae58b7bf9f0f71435d73 Mon Sep 17 00:00:00 2001 From: Felix Rindt Date: Sun, 5 Jan 2025 16:37:32 +0100 Subject: [PATCH 2/7] introduce PLATFORM_NAME setting --- .../api/templates/api/access_token_list.html | 6 +- .../oauth2_provider/application_list.html | 6 +- ephios/core/context.py | 2 + ephios/core/forms/users.py | 7 +- ephios/core/services/notifications/types.py | 24 +- ephios/core/services/password_reset.py | 4 +- ephios/core/templates/core/group_form.html | 4 +- .../core/templates/core/userprofile_form.html | 4 +- ephios/core/views/pwa.py | 10 +- ephios/core/views/settings.py | 2 +- ephios/locale/de/LC_MESSAGES/django.po | 282 +++++++++--------- ephios/settings.py | 2 + ephios/templates/500.html | 2 +- ephios/templates/base.html | 2 +- 14 files changed, 193 insertions(+), 164 deletions(-) diff --git a/ephios/api/templates/api/access_token_list.html b/ephios/api/templates/api/access_token_list.html index 28ee8cf0d..22cf78301 100644 --- a/ephios/api/templates/api/access_token_list.html +++ b/ephios/api/templates/api/access_token_list.html @@ -6,9 +6,9 @@

{% translate "Integrations" %}

- {% blocktranslate trimmed %} - Other applications can integrate with ephios by asking you for access to your data. - You can also create personal API tokens to access ephios from other applications. + {% blocktranslate trimmed with platform=platform_name %} + Other applications can integrate with {{ platform }} by asking you for access to your data. + You can also create personal API tokens to access {{ platform }} from other applications. If you are unsure about the origins of a token or the security of the third party application please revoke access. {% endblocktranslate %} diff --git a/ephios/api/templates/oauth2_provider/application_list.html b/ephios/api/templates/oauth2_provider/application_list.html index 39780926d..a21057090 100644 --- a/ephios/api/templates/oauth2_provider/application_list.html +++ b/ephios/api/templates/oauth2_provider/application_list.html @@ -5,9 +5,9 @@

{% translate "App integrations" %}

- {% blocktranslate trimmed %} - On this page you can configure other apps and programs to work with ephios as an authentication provider - using the OAuth2-standard. Other ways to integrate with ephios include the plugin system and the API. + {% blocktranslate trimmed with platform=platform_name %} + On this page you can configure other apps and programs to work with {{ platform }} as an authentication provider + using the OAuth2-standard. Other ways to integrate with {{ platform }} include the plugin system and the API. More detailed information can be found in the documentation. {% endblocktranslate %}

diff --git a/ephios/core/context.py b/ephios/core/context.py index 844b08808..a06b227a0 100644 --- a/ephios/core/context.py +++ b/ephios/core/context.py @@ -4,6 +4,7 @@ from django.utils.translation import get_language from dynamic_preferences.registries import global_preferences_registry +from ephios.core.dynamic import dynamic_settings from ephios.core.models import AbstractParticipation from ephios.core.signals import footer_link, html_head, nav_link, navbar_html @@ -61,4 +62,5 @@ def ephios_base_context(request): "PWA_APP_ICONS": settings.PWA_APP_ICONS, "DEBUG": settings.DEBUG, "organization_name": global_preferences_registry.manager()["general__organization_name"], + "platform_name": dynamic_settings.PLATFORM_NAME, } diff --git a/ephios/core/forms/users.py b/ephios/core/forms/users.py index c1ad0a704..760e35cd8 100644 --- a/ephios/core/forms/users.py +++ b/ephios/core/forms/users.py @@ -20,6 +20,7 @@ from guardian.shortcuts import assign_perm, get_objects_for_group, remove_perm from ephios.core.consequences import WorkingHoursConsequenceHandler +from ephios.core.dynamic import dynamic_settings from ephios.core.models import QualificationGrant, UserProfile, WorkingHours from ephios.core.models.users import IdentityProvider from ephios.core.services.notifications.backends import enabled_notification_backends @@ -132,7 +133,6 @@ class GroupForm(PermissionFormMixin, ModelForm): required=False, ) is_management_group = PermissionField( - label=_("Can change permissions and manage ephios"), help_text=_( "If checked, users in this group can edit all users, change groups, their permissions and memberships " "as well as define eventtypes and qualifications." @@ -171,6 +171,9 @@ def __init__(self, **kwargs): for field_name, field in extra_fields: self.base_fields[field_name] = field super().__init__(**kwargs) + self.fields["is_management_group"].label = _( + "Can change permissions and manage {platform}" + ).format(platform=dynamic_settings.PLATFORM_NAME) self.helper = FormHelper() self.helper.layout = Layout( Field("name"), @@ -252,7 +255,7 @@ class UserProfileForm(PermissionFormMixin, ModelForm): is_staff = PermissionField( label=_("Administrator"), help_text=_( - "If checked, this user can change technical ephios settings as well as edit all user profiles, " + "If checked, this user can change technical settings as well as edit all user profiles, " "groups, qualifications, events and event types." ), permissions=MANAGEMENT_PERMISSIONS, diff --git a/ephios/core/services/notifications/types.py b/ephios/core/services/notifications/types.py index b8bddcee3..5f45969a2 100644 --- a/ephios/core/services/notifications/types.py +++ b/ephios/core/services/notifications/types.py @@ -116,13 +116,18 @@ def send(cls, user: UserProfile, **kwargs): @classmethod def get_subject(cls, notification): - return _("ephios account updated") + return _("{platform} account updated").format(platform=dynamic_settings.PLATFORM_NAME) @classmethod def get_body(cls, notification): + org_name = global_preferences_registry.manager().get("general__organization_name") return _( - "You're receiving this email because your account at ephios has been updated." - ).format(url=cls._get_personal_data_url(notification), email=notification.user.email) + "You're receiving this email because your {platform} account ({email} at {org_name}) has been updated." + ).format( + platform=dynamic_settings.PLATFORM_NAME, + org_name=org_name, + email=notification.user.email, + ) @classmethod def get_actions(cls, notification): @@ -149,16 +154,21 @@ def send(cls, user: UserProfile, **kwargs): @classmethod def get_subject(cls, notification): - org_name = global_preferences_registry.manager().get("general__organization_name") - return _("Welcome to {}!").format(org_name) + return _("Welcome to {}!").format(dynamic_settings.PLATFORM_NAME) @classmethod def get_body(cls, notification): + org_name = global_preferences_registry.manager().get("general__organization_name") return _( - "You're receiving this email because a new account has been created for you at ephios.\n" + "You're receiving this email because a new account has been created for you at {platform} ({org_name}).\n" "Please go to the following page and choose a password: {url} \n" "Your username is your email address: {email}" - ).format(url=cls._get_reset_url(notification), email=notification.user.email) + ).format( + url=cls._get_reset_url(notification), + email=notification.user.email, + platform_name=dynamic_settings.PLATFORM_NAME, + org_name=org_name, + ) @classmethod def get_actions(cls, notification): diff --git a/ephios/core/services/password_reset.py b/ephios/core/services/password_reset.py index c7d90465f..4c14d12f2 100644 --- a/ephios/core/services/password_reset.py +++ b/ephios/core/services/password_reset.py @@ -24,7 +24,9 @@ def password_changed(self, password, user): html_content = render_to_string( "core/mails/base.html", { - "subject": _("Your ephios password has been changed"), + "subject": _("Your {platform} password has been changed").format( + platform=dynamic_settings.PLATFORM_NAME + ), "body": text_content, }, ) diff --git a/ephios/core/templates/core/group_form.html b/ephios/core/templates/core/group_form.html index d39f6be34..563893957 100644 --- a/ephios/core/templates/core/group_form.html +++ b/ephios/core/templates/core/group_form.html @@ -21,8 +21,8 @@

{% translate "Create new group" %}

{% if oidc_group_claims %} {% endif %} diff --git a/ephios/core/templates/core/userprofile_form.html b/ephios/core/templates/core/userprofile_form.html index 0be702a96..d5ef9f6cd 100644 --- a/ephios/core/templates/core/userprofile_form.html +++ b/ephios/core/templates/core/userprofile_form.html @@ -25,8 +25,8 @@

{% translate "Add new user" %}

{% if oidc_group_claims %}