add debug application (#29240)

This commit is contained in:
Benjamin Dauvergne 2019-03-08 02:41:26 +01:00
parent 09588c0de6
commit b36e054cb0
9 changed files with 225 additions and 0 deletions

0
hobo/debug/__init__.py Normal file
View File

57
hobo/debug/forms.py Normal file
View File

@ -0,0 +1,57 @@
# hobo - portal to configure and deploy applications
# Copyright (C) 2015-2019 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 import forms
from django.core.validators import validate_ipv46_address
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
def validate_space_separated_ips(value):
errors = []
for ip in value:
try:
validate_ipv46_address(ip)
except ValidationError as e:
errors.append(e)
if errors:
raise ValidationError(errors)
class MultipleIPAddressField(forms.CharField):
default_validators = [validate_space_separated_ips]
def to_python(self, value):
if value in self.empty_values:
return []
return value.split()
def prepare_value(self, value):
if not value:
return ''
if not isinstance(value, list):
return value
return ' '.join(value)
class SettingsForm(forms.Form):
debug_log = forms.BooleanField(
required=False,
label=_('Debug log'))
debug_ips = MultipleIPAddressField(
label=_('Internal IP adresses'),
required=False,
help_text=_('List of IP adresses for which to enable debugging'))

View File

@ -0,0 +1,26 @@
{% extends "hobo/base.html" %}
{% load i18n %}
{% block breadcrumb %}
{{ block.super }}
<a href="{% url 'debug-home' %}">{% trans "Debugging" %}</a>
{% endblock %}
{% block appbar %}
<h2>{% trans 'Debugging' %}</h2>
{% endblock %}
{% block content %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<div class="buttons">
<button class="submit-button">{% trans "Save" %}</button>
<button class="submit-button"
name="toggle-current-ip">{% if current_ip_debug %}{% trans "Remove current IP" %}{% else %}{% trans "Add current IP" %}{% endif %} - {{ view.current_ip }}</button>
</div>
</form>
{% endblock %}

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

@ -0,0 +1,23 @@
# hobo - portal to configure and deploy applications
# Copyright (C) 2015-2019 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.urls import url
from . import views
urlpatterns = [
url(r'^$', views.home, name='debug-home'),
]

72
hobo/debug/views.py Normal file
View File

@ -0,0 +1,72 @@
# hobo - portal to configure and deploy applications
# Copyright (C) 2015-2019 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.core.urlresolvers import reverse_lazy
from django.views.generic import FormView
from django.utils.functional import cached_property
from hobo.environment.utils import get_setting_variable
from .forms import SettingsForm
class HomeView(FormView):
template_name = 'hobo/debug_home.html'
form_class = SettingsForm
success_url = reverse_lazy('debug-home')
@cached_property
def debug_log_variable(self):
return get_setting_variable('DEBUG_LOG')
@cached_property
def debug_ips_variable(self):
return get_setting_variable('INTERNAL_IPS')
def get_initial(self):
initial = super(HomeView, self).get_initial()
initial['debug_log'] = bool(self.debug_log_variable.json)
initial['debug_ips'] = self.debug_ips_variable.json
return initial
@property
def current_ip(self):
return self.request.META.get('REMOTE_ADDR') or None
def get_context_data(self, **kwargs):
ctx = super(HomeView, self).get_context_data(**kwargs)
ctx['current_ip_debug'] = self.current_ip in self.debug_ips_variable.json
return ctx
def toggle_value(self, l, value):
if value in l:
return [x for x in l if x != value]
else:
return l + [value]
def form_valid(self, form):
debug_log = form.cleaned_data['debug_log']
self.debug_log_variable.json = debug_log
self.debug_log_variable.save()
debug_ips = form.cleaned_data['debug_ips']
if 'toggle-current-ip' in self.request.POST:
debug_ips = self.toggle_value(debug_ips, self.current_ip)
self.debug_ips_variable.json = debug_ips
self.debug_ips_variable.save()
return super(HomeView, self).form_valid(form)
home = HomeView.as_view()

View File

@ -41,6 +41,7 @@ INSTALLED_APPS = (
'rest_framework',
'mellon',
'gadjo',
'hobo.debug',
'hobo.environment',
'hobo.franceconnect',
'hobo.matomo',

View File

@ -17,6 +17,7 @@
<li><a href="{% url 'matomo-home' %}">{% trans 'User tracking' %}</a></li>
<li><a href="{% url 'environment-home' %}">{% trans 'Services' %}</a></li>
<li><a href="{% url 'environment-variables' %}">{% trans 'Variables' %}</a></li>
<li><a href="{% url 'debug-home' %}">{% trans 'Debugging' %}</a></li>
</ul>
</span>
{% endblock %}

View File

@ -27,6 +27,7 @@ from .matomo.urls import urlpatterns as matomo_urls
from .profile.urls import urlpatterns as profile_urls
from .theme.urls import urlpatterns as theme_urls
from .emails.urls import urlpatterns as emails_urls
from .debug.urls import urlpatterns as debug_urls
admin.autodiscover()
@ -38,6 +39,7 @@ urlpatterns = [
url(r'^matomo/', decorated_includes(admin_required, include(matomo_urls))),
url(r'^theme/', decorated_includes(admin_required, include(theme_urls))),
url(r'^emails/', decorated_includes(admin_required, include(emails_urls))),
url(r'^debug/', decorated_includes(admin_required, include(debug_urls))),
url(r'^api/health/$', health_json, name='health-json'),
url(r'^menu.json$', menu_json, name='menu_json'),
url(r'^hobos.json$', hobo),

View File

@ -88,3 +88,46 @@ def test_add_attribute(logged_app, admin_user, kind):
def test_attribute_kind_not_restricted_at_model_level(db):
assert models.AttributeDefinition.objects.create(label='test', kind='somestring')
def test_debug_home(logged_app):
from hobo.environment.utils import get_setting_variable, get_installed_services_dict
IPS = '99.99.99.99 77.77.77.77'
IP_LIST = ['99.99.99.99', '77.77.77.77']
page = logged_app.get('/debug/')
page.form['debug_log'] = True
page.form['debug_ips'] = IPS
page = page.form.submit().follow()
assert get_setting_variable('DEBUG_LOG').json is True
assert get_setting_variable('INTERNAL_IPS').json == IP_LIST
hobo_json = get_installed_services_dict()
assert hobo_json['variables']['SETTING_DEBUG_LOG'] is True
assert hobo_json['variables']['SETTING_INTERNAL_IPS'] == IP_LIST
page.form['debug_log'] = False
page.form['debug_ips'] = ''
page = page.form.submit().follow()
assert get_setting_variable('DEBUG_LOG').json is False
assert get_setting_variable('INTERNAL_IPS').json == []
hobo_json = get_installed_services_dict()
assert hobo_json['variables']['SETTING_DEBUG_LOG'] is False
assert hobo_json['variables']['SETTING_INTERNAL_IPS'] == []
# toggle-current-ip button
page = logged_app.get('/debug/')
page.form['debug_ips'] = IPS
page = page.form.submit(name='toggle-current-ip').follow() # click
assert get_setting_variable('INTERNAL_IPS').json == IP_LIST + ['127.0.0.1']
page = page.form.submit(name='toggle-current-ip').follow() # click again
assert get_setting_variable('INTERNAL_IPS').json == IP_LIST
# wrong ips are not returned as a list
page = logged_app.get('/debug/')
page.form['debug_ips'] = 'not_an_IP'
page = page.form.submit()
assert 'Enter a valid IPv4 or IPv6 address' in page.content
assert page.form['debug_ips']._value == 'not_an_IP' # get 'n o t _ a n _ I P'