Skip to content

Commit

Permalink
Addition of Prefix Path (tethysplatform#974)
Browse files Browse the repository at this point in the history
* adding prefix path to the tethys platform through a new portal_config setting called: PREFIX_TO_PATH

* edited test to handle the new path

* adding one test to cover the new settings

* test to check that the prefix was entered

* resolving comments in soruce code, still needs tests

* changes to 4/11 tests still needs some work

* test_url passing for tethys_portal

* test_setting for tethys_portal passing

* tes_urls for gizmos with prefix

* needs some test still

* added url test for apps with prefix

* handsoff test

* test daks needs probably tests in the portal_url

* removed uncessary tests

* removed unnecessary tests

* removing extra tests

* change in static to be in templates rather than in the .less files with hardcoded paths

Co-authored-by: Nathan Swain <[email protected]>

* fixed paths related problem with jobs tables, etc

* changes for the pull requests

* black formatting

* black formatting

* removed of extra parenthesis

* added comments to the .less and .html files regarding moving part of the style to the tempaltes to render the staticfiles dynamically

* added support to websockets and http_handlers

* mistake for the base.html

* mistake arcgis per hs-icon

* black formatting

* added the tests for the web sockets and https handlers

* needed to reaload the tethys_portal.asgi and also tethys_apps.urls

---------

Co-authored-by: romer8 <[email protected]>
  • Loading branch information
swainn and romer8 authored Aug 2, 2023
1 parent 4db7cb2 commit 6f940b0
Show file tree
Hide file tree
Showing 30 changed files with 1,047 additions and 69 deletions.
29 changes: 28 additions & 1 deletion tests/unit_tests/test_tethys_apps/test_base/test_handoff.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from types import FunctionType
from unittest import mock
from tethys_sdk.testing import TethysTestCase
from django.test import override_settings


def test_function(*args):
Expand Down Expand Up @@ -274,17 +275,43 @@ def test_with_app(self, mock_ta):


class TestTestAppHandoff(TethysTestCase):
import sys
from importlib import reload, import_module
from django.conf import settings
from django.urls import clear_url_caches

@classmethod
def reload_urlconf(self, urlconf=None):
self.clear_url_caches()
if urlconf is None:
urlconf = self.settings.ROOT_URLCONF
if urlconf in self.sys.modules:
self.reload(self.sys.modules[urlconf])
else:
self.import_module(urlconf)

def set_up(self):
self.c = self.get_test_client()
self.user = self.create_test_user(
username="joe", password="secret", email="joe@some_site.com"
)
self.c.force_login(self.user)

@override_settings(PREFIX_URL="/")
def tear_down(self):
self.user.delete()
self.reload_urlconf()

@override_settings(PREFIX_URL="/")
def test_test_app_handoff(self):
response = self.c.get('/handoff/test-app/test_name/?csv_url=""')
self.reload_urlconf()
response = self.c.get(f'/handoff/test-app/test_name/?csv_url=""')

self.assertEqual(302, response.status_code)

@override_settings(PREFIX_URL="test/prefix")
def test_test_app_handoff_with_prefix(self):
self.reload_urlconf()
response = self.c.get(f'/test/prefix/handoff/test-app/test_name/?csv_url=""')

self.assertEqual(302, response.status_code)
195 changes: 194 additions & 1 deletion tests/unit_tests/test_tethys_apps/test_decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from unittest import mock

from django.contrib.auth.models import AnonymousUser
from django.test import RequestFactory
from django.test import RequestFactory, TestCase
from django.test.utils import override_settings
from django.http import HttpResponseRedirect

Expand Down Expand Up @@ -33,6 +33,7 @@ def create_projects(request, *args, **kwargs):
self.assertEqual("expected_result", ret)

@override_settings(ENABLE_OPEN_PORTAL=False)
@override_settings(LOGIN_URL="/accounts/login/")
def test_login_required_open_portal_False_Fail(self):
request = self.request_factory.get("/apps/test-app")
request.user = AnonymousUser()
Expand Down Expand Up @@ -207,3 +208,195 @@ def method(self, request, *args, **kwargs):
f = Foo()

self.assertEqual(f.method(request), "expected_result")


@override_settings(PREFIX_URL="test/prefix")
@override_settings(LOGIN_URL="/test/prefix/test/login/")
class DecoratorsWithPrefixTest(TestCase):
import sys
from importlib import reload, import_module
from django.conf import settings
from django.urls import clear_url_caches

@classmethod
def reload_urlconf(self, urlconf=None):
self.clear_url_caches()
if urlconf is None:
urlconf = self.settings.ROOT_URLCONF
if urlconf in self.sys.modules:
self.reload(self.sys.modules[urlconf])
else:
self.import_module(urlconf)

def setUp(self):
self.request_factory = RequestFactory()
self.user = UserFactory()
self.reload_urlconf()

@override_settings(PREFIX_URL="/")
def tearDown(self):
self.reload_urlconf()
pass

@mock.patch("tethys_apps.decorators.messages")
@mock.patch("tethys_apps.decorators.has_permission", return_value=False)
def test_permission_required_message(self, _, mock_messages):
request = self.request_factory.get("/apps/test-app")
request.user = self.user
msg = "A different message."

@permission_required("create_projects", message=msg)
def create_projects(request, *args, **kwargs):
return "expected_result"

ret = create_projects(request)

mock_messages.add_message.assert_called_with(
request, mock_messages.WARNING, msg
)
self.assertIsInstance(ret, HttpResponseRedirect)
self.assertEqual("/test/prefix/apps/", ret.url)

@override_settings(ENABLE_OPEN_PORTAL=False)
def test_login_required_open_portal_False_Fail(self):
request = self.request_factory.get("/apps/test-app")
request.user = AnonymousUser()

@login_required()
def create_projects(request, *args, **kwargs):
return "expected_result"

ret = create_projects(request)

self.assertIsInstance(ret, HttpResponseRedirect)
self.assertIn("test/prefix/test/login/", ret.url)

@mock.patch("tethys_apps.decorators.messages")
@mock.patch("tethys_apps.decorators.has_permission", return_value=False)
def test_permission_required_no_pass_authenticated(self, _, mock_messages):
request = self.request_factory.get("/apps/test-app")
request.user = self.user

@permission_required("create_projects")
def create_projects(request, *args, **kwargs):
return "expected_result"

ret = create_projects(request)

mock_messages.add_message.assert_called()
self.assertIsInstance(ret, HttpResponseRedirect)
self.assertEqual("/test/prefix/apps/", ret.url)

@mock.patch("tethys_apps.decorators.messages")
@mock.patch("tethys_apps.decorators.has_permission", return_value=False)
def test_permission_required_no_pass_authenticated_with_referrer(
self, _, mock_messages
):
request = self.request_factory.get("/apps/test-app")
request.user = self.user
request.META["HTTP_REFERER"] = "http://testserver/foo/bar"

@permission_required("create_projects")
def create_projects(request, *args, **kwargs):
return "expected_result"

ret = create_projects(request)

mock_messages.add_message.assert_called()
self.assertIsInstance(ret, HttpResponseRedirect)
self.assertEqual("/foo/bar", ret.url)

def test_blank_permissions(self):
self.assertRaises(ValueError, permission_required)

@mock.patch("tethys_apps.decorators.has_permission", return_value=True)
def test_multiple_permissions(self, mock_has_permission):
request = self.request_factory.get("/apps/test-app")
request.user = self.user

@permission_required("create_projects", "delete_projects")
def multiple_permissions(request, *args, **kwargs):
return "expected_result"

ret = multiple_permissions(request)
self.assertEqual(ret, "expected_result")
hp_call_args = mock_has_permission.call_args_list
self.assertEqual(2, len(hp_call_args))
self.assertEqual("create_projects", hp_call_args[0][0][1])
self.assertEqual("delete_projects", hp_call_args[1][0][1])

@mock.patch("tethys_apps.decorators.has_permission", return_value=True)
def test_multiple_permissions_OR(self, _):
request = self.request_factory.get("/apps/test-app")
request.user = self.user

@permission_required("create_projects", "delete_projects", use_or=True)
def multiple_permissions_or(request, *args, **kwargs):
return "expected_result"

self.assertEqual(multiple_permissions_or(request), "expected_result")

@mock.patch("tethys_apps.decorators.tethys_portal_error", return_value=False)
@mock.patch("tethys_apps.decorators.has_permission", return_value=False)
@override_settings(DEBUG=True)
def test_permission_required_exception_403(self, _, mock_tp_error):
request = self.request_factory.get("/apps/test-app")
request.user = self.user

@permission_required("create_projects", raise_exception=True)
def exception_403(request, *args, **kwargs):
return "expected_result"

exception_403(request)
mock_tp_error.handler_403.assert_called_with(request)

@mock.patch("tethys_apps.decorators.tethys_portal_error", return_value=False)
@mock.patch("tethys_apps.decorators.has_permission", return_value=False)
@override_settings(DEBUG=False)
def test_permission_required_exception_404(self, _, mock_tp_error):
request = self.request_factory.get("/apps/test-app")
request.user = self.user

@permission_required("create_projects", raise_exception=True)
def exception_404(request, *args, **kwargs):
return "expected_result"

exception_404(request)
mock_tp_error.handler_404.assert_called_with(request)

def test_permission_required_no_request(self):
@permission_required("create_projects")
def no_request(request, *args, **kwargs):
return "expected_result"

self.assertRaises(ValueError, no_request)

@mock.patch("tethys_apps.decorators.has_permission", return_value=True)
def test_multiple_permissions_class_method(self, _):
request = self.request_factory.get("/apps/test-app")
request.user = self.user

class Foo:
@permission_required("create_projects")
def method(self, request, *args, **kwargs):
return "expected_result"

f = Foo()

self.assertEqual(f.method(request), "expected_result")

@mock.patch("tethys_apps.decorators.messages")
@mock.patch("tethys_apps.decorators.has_permission", return_value=False)
def test_permission_required_no_pass_not_authenticated(self, _, mock_messages):
request = self.request_factory.get("/apps/test-app")
request.user = AnonymousUser()

@permission_required("create_projects")
def create_projects(request, *args, **kwargs):
return "expected_result"

ret = create_projects(request)

mock_messages.add_message.assert_called()
self.assertIsInstance(ret, HttpResponseRedirect)
self.assertIn("/test/prefix/accounts/login/", ret.url)
65 changes: 65 additions & 0 deletions tests/unit_tests/test_tethys_apps/test_urls.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.urls import reverse, resolve
from tethys_sdk.testing import TethysTestCase
from django.test import override_settings


class TestUrls(TethysTestCase):
Expand Down Expand Up @@ -44,3 +45,67 @@ def test_urls(self):
self.assertEqual(
"tethysext.test_extension.controllers", resolver.func.__module__
)


# probably need to test for extensions manually
@override_settings(PREFIX_URL="test/prefix")
class TestUrlsWithPrefix(TethysTestCase):
import sys
from importlib import reload, import_module
from django.conf import settings
from django.urls import clear_url_caches

@classmethod
def reload_urlconf(self, urlconf=None):
self.clear_url_caches()
if urlconf is None:
urlconf = self.settings.ROOT_URLCONF
if urlconf in self.sys.modules:
self.reload(self.sys.modules[urlconf])
else:
self.import_module(urlconf)

def set_up(self):
self.reload_urlconf()
pass

@override_settings(PREFIX_URL="/")
def tearDown(self):
self.reload_urlconf()
pass

def test_urls(self):
# This executes the code at the module level
url = reverse("app_library")
resolver = resolve(url)
self.assertEqual("/test/prefix/apps/", url)
self.assertEqual("library", resolver.func.__name__)
self.assertEqual("tethys_apps.views", resolver.func.__module__)

url = reverse("send_beta_feedback")
resolver = resolve(url)
self.assertEqual("/test/prefix/apps/send-beta-feedback/", url)
self.assertEqual("send_beta_feedback_email", resolver.func.__name__)
self.assertEqual("tethys_apps.views", resolver.func.__module__)

url = reverse("test_app:home")
resolver = resolve(url)
self.assertEqual("/test/prefix/apps/test-app/", url)
self.assertEqual("home", resolver.func.__name__)
self.assertEqual("tethysapp.test_app.controllers", resolver.func.__module__)

url = reverse("test_extension:home", kwargs={"var1": "foo", "var2": "bar"})
resolver = resolve(url)
self.assertEqual("/test/prefix/extensions/test-extension/foo/bar/", url)
self.assertEqual("home", resolver.func.__name__)
self.assertEqual(
"tethysext.test_extension.controllers", resolver.func.__module__
)

url = reverse("test_extension:home", args=["foo", "bar"])
resolver = resolve(url)
self.assertEqual("/test/prefix/extensions/test-extension/foo/bar/", url)
self.assertEqual("home", resolver.func.__name__)
self.assertEqual(
"tethysext.test_extension.controllers", resolver.func.__module__
)
Loading

0 comments on commit 6f940b0

Please sign in to comment.