diff --git a/Dockerfile b/Dockerfile
index 2aa1e077..9653a995 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -41,6 +41,7 @@ RUN npm install --quiet -g webpack@4.16.5 && npm install --quiet -g webpack-cli
RUN echo "UTC" > /etc/timezone
RUN python manage.py collectstatic --noinput
RUN bash app/scripts/plugin_cleanup.sh && echo "from app.plugins import build_plugins;build_plugins()" | python manage.py shell
+RUN bash translate.sh build
# Cleanup
RUN apt-get remove -y g++ python3-dev libpq-dev && apt-get autoremove -y
diff --git a/app/templates/app/dev_tools.html b/app/templates/app/dev_tools.html
new file mode 100644
index 00000000..fa316ed2
--- /dev/null
+++ b/app/templates/app/dev_tools.html
@@ -0,0 +1,14 @@
+{% extends "app/logged_in_base.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
{% trans 'Developer Tools' %}
+
+
+
+ // TODO
+ // https://hosted.weblate.org/download/webodm/?format=zip
+
+
+{% endblock %}
diff --git a/app/templates/app/logged_in_base.html b/app/templates/app/logged_in_base.html
index ed1762d2..c4d18f5c 100644
--- a/app/templates/app/logged_in_base.html
+++ b/app/templates/app/logged_in_base.html
@@ -103,6 +103,13 @@
{% endif %}
+
+ {% is_dev_mode as dev_mode %}
+ {% if dev_mode and user.is_superuser %}
+
+ {% trans 'Developer Tools' %}
+
+ {% endif %}
diff --git a/app/templatetags/settings.py b/app/templatetags/settings.py
index a530264f..c640860d 100644
--- a/app/templatetags/settings.py
+++ b/app/templatetags/settings.py
@@ -11,6 +11,10 @@ logger = logging.getLogger('app.logger')
def is_single_user_mode():
return settings.SINGLE_USER_MODE
+@register.simple_tag
+def is_dev_mode():
+ return settings.DEV
+
@register.simple_tag(takes_context=True)
def settings_image_url(context, image):
try:
diff --git a/app/tests/test_app.py b/app/tests/test_app.py
index 5a6da3bb..a0d9560a 100644
--- a/app/tests/test_app.py
+++ b/app/tests/test_app.py
@@ -5,6 +5,7 @@ from rest_framework import status
from app.models import Project, Task
from app.models import Setting
from app.models import Theme
+from webodm import settings
from .classes import BootTestCase
from django.core.exceptions import ValidationError
@@ -167,10 +168,22 @@ class TestApp(BootTestCase):
res = c.get(url)
self.assertEqual(res.status_code, status.HTTP_200_OK)
+ # Cannot access dev tools (not in dev mode)
+ settings.DEV = False
+ self.assertEqual(c.get('/dev-tools/').status_code, status.HTTP_404_NOT_FOUND)
+ settings.DEV = True
+
+ # Can access in dev mode
+ self.assertEqual(c.get('/dev-tools/').status_code, status.HTTP_200_OK)
+
# Cannot access admin views as normal user
c.logout()
c.login(username='testuser', password='test1234')
+ # Can never access dev tools as user, even in dev mode
+ self.assertRedirects(c.get('/dev-tools/', follow=True), '/login/?next=/dev-tools/')
+ settings.DEV = False
+
for url in admin_menu_items:
res = c.get(url, follow=True)
self.assertRedirects(res, '/admin/login/?next={}'.format(url))
diff --git a/app/urls.py b/app/urls.py
index e8881c4f..36dd8143 100644
--- a/app/urls.py
+++ b/app/urls.py
@@ -40,6 +40,8 @@ urlpatterns = [
url(r'^plugins/(?P[^/.]+)/(.*)$', app_view_handler),
url(r'^about/$', app_views.about, name='about'),
+ url(r'^dev-tools/$', app_views.dev_tools, name='dev_tools'),
+
# TODO: add caching: https://docs.djangoproject.com/en/3.1/topics/i18n/translation/#note-on-performance
url(r'^jsi18n/', JavaScriptCatalog.as_view(packages=['app']), name='javascript-catalog'),
]
diff --git a/app/views/app.py b/app/views/app.py
index 112a0f2c..5737347d 100644
--- a/app/views/app.py
+++ b/app/views/app.py
@@ -6,6 +6,7 @@ from django.contrib.auth.models import User
from django.http import Http404
from django.shortcuts import render, redirect, get_object_or_404
from guardian.shortcuts import get_objects_for_user
+from django.contrib.auth.decorators import user_passes_test
from nodeodm.models import ProcessingNode
from app.models import Project, Task
@@ -110,11 +111,20 @@ def processing_node(request, processing_node_id):
return render(request, 'app/processing_node.html',
{
- 'title': 'Processing Node',
+ 'title': _('Processing Node'),
'processing_node': pn,
'available_options_json': pn.get_available_options_json(pretty=True)
})
+@user_passes_test(lambda u: u.is_superuser)
+def dev_tools(request):
+ if not settings.DEV:
+ raise Http404()
+
+ return render(request, 'app/dev_tools.html', {
+ 'title': _('Developer Tools')
+ })
+
class FirstUserForm(forms.ModelForm):
class Meta:
model = User