middleware: add per-tenant timezone system (#88093)
gitea/hobo/pipeline/head There was a failure building this commit Details

This commit is contained in:
Thomas NOËL 2024-03-15 12:13:13 +01:00
parent 159f93a783
commit 668dc1693c
10 changed files with 161 additions and 0 deletions

View File

@ -257,6 +257,7 @@ if 'MIDDLEWARE' not in globals():
MIDDLEWARE = (
'hobo.middleware.VersionMiddleware', # /__version__
'hobo.middleware.cors.CORSMiddleware',
'hobo.middleware.timezone.TimezoneMiddleware',
'hobo.middleware.maintenance.MaintenanceMiddleware',
) + MIDDLEWARE

View File

@ -0,0 +1,38 @@
# hobo - portal to configure and deploy applications
# Copyright (C) 2015-2024 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pytz
from django.conf import settings
from django.utils import timezone
class TimezoneMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
time_zone = getattr(settings, 'TENANT_TIME_ZONE', None)
tz = None
if time_zone:
try:
tz = pytz.timezone(time_zone)
except pytz.exceptions.UnknownTimeZoneError:
pass
if tz:
timezone.activate(tz)
else:
timezone.deactivate()
return self.get_response(request)

View File

@ -57,6 +57,7 @@ INSTALLED_APPS = (
'hobo.emails',
'hobo.deploy',
'hobo.sms',
'hobo.timezone',
)
MIDDLEWARE = (

View File

@ -113,6 +113,7 @@
<a class="button button-paragraph" href="{% url 'sms-home' %}">{% trans 'SMS' %}</a>
<a class="button button-paragraph" href="{% url 'matomo-home' %}">{% trans 'User tracking' %}</a>
<a class="button button-paragraph" href="{% url 'seo-home' %}">{% trans 'Indexing' %}</a>
<a class="button button-paragraph" href="{% url 'timezone-home' %}">{% trans 'Timezone' %}</a>
<a class="button button-paragraph" href="{% url 'environment-home' %}">{% trans 'Services' %}</a>
<a class="button button-paragraph" href="{% url 'environment-variables' %}">{% trans 'Variables' %}</a>
<a class="button button-paragraph" href="{% url 'debug-home' %}">{% trans 'Debugging' %}</a>

View File

27
hobo/timezone/forms.py Normal file
View File

@ -0,0 +1,27 @@
# hobo - portal to configure and deploy applications
# Copyright (C) 2015-2024 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pytz
from django import forms
from django.utils.translation import gettext_lazy as _
class TimezoneForm(forms.Form):
timezone = forms.ChoiceField(
label=_('Time zone'),
required=False,
choices=[('', _('None'))] + [(tz, tz) for tz in pytz.all_timezones],
)

View File

@ -0,0 +1,21 @@
{% extends "hobo/base.html" %}
{% load i18n %}
{% block breadcrumb %}
{{ block.super }}
<a href="{% url 'timezone-home' %}">{% trans "Timezone" %}</a>
{% endblock %}
{% block appbar %}
<h2>{% trans 'Timezone' %}</h2>
{% endblock %}
{% block content %}
<form action="." method="post">
{% csrf_token %}
{{ form.as_p }}
<div class="buttons">
<button>{% trans "Submit" %}</button>
</div>
</form>
{% endblock %}

23
hobo/timezone/urls.py Normal file
View File

@ -0,0 +1,23 @@
# hobo - portal to configure and deploy applications
# Copyright (C) 2015-2024 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='timezone-home'),
]

47
hobo/timezone/views.py Normal file
View File

@ -0,0 +1,47 @@
# hobo - portal to configure and deploy applications
# Copyright (C) 2015-2024 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.conf import settings
from django.urls import reverse_lazy
from django.utils.functional import cached_property
from django.views.generic import FormView
from hobo.environment.utils import get_setting_variable
from .forms import TimezoneForm
class HomeView(FormView):
template_name = 'hobo/timezone/home.html'
form_class = TimezoneForm
success_url = reverse_lazy('timezone-home')
@cached_property
def timezone_variable(self):
return get_setting_variable('TENANT_TIME_ZONE')
def get_initial(self):
initial = super().get_initial()
initial['timezone'] = self.timezone_variable.value
return initial
def form_valid(self, form):
self.timezone_variable.value = form.cleaned_data['timezone']
self.timezone_variable.save()
return super().form_valid(form)
home = HomeView.as_view()

View File

@ -27,6 +27,7 @@ from .profile.urls import urlpatterns as profile_urls
from .seo.urls import urlpatterns as seo_urls
from .sms.urls import urlpatterns as sms_urls
from .theme.urls import urlpatterns as theme_urls
from .timezone.urls import urlpatterns as timezone_urls
from .urls_utils import decorated_includes
from .views import admin_required, health_json, hobo, home, login, login_local, logout, menu_json
@ -42,6 +43,7 @@ urlpatterns = [
re_path(r'^debug/', decorated_includes(admin_required, include(debug_urls))),
re_path(r'^applications/', decorated_includes(admin_required, include(applications_urls))),
re_path(r'^maintenance/', decorated_includes(admin_required, include(maintenance_urls))),
re_path(r'^timezone/', decorated_includes(admin_required, include(timezone_urls))),
path('api/health/', health_json, name='health-json'),
re_path(r'^menu.json$', menu_json, name='menu_json'),
re_path(r'^hobos.json$', hobo),