From 7941e8fa60140373b09cb88a79c7190cb8dc93fb Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Fri, 7 Sep 2018 22:12:39 +0200 Subject: [PATCH] Add a readonly mode Activable with UMAP_READONLY=True --- docs/changelog.md | 6 ++++++ umap/middleware.py | 17 +++++++++++++++++ umap/settings/base.py | 2 ++ umap/settings/local.py.sample | 6 +++++- umap/tests/test_datalayer_views.py | 8 ++++++++ umap/tests/test_map_views.py | 9 +++++++++ 6 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 umap/middleware.py diff --git a/docs/changelog.md b/docs/changelog.md index 104d8427..0dd18f53 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -49,6 +49,12 @@ COMMIT; umap compress +## dev + +- added a readonly mode (`UMAP_READONLY=True`), useful to disallow update while + migrating from one server to an other, for example + + ## 1.0.0.rc-2 - allow to cache proxied remote data requests (#513 #510 #160) diff --git a/umap/middleware.py b/umap/middleware.py new file mode 100644 index 00000000..6e031769 --- /dev/null +++ b/umap/middleware.py @@ -0,0 +1,17 @@ +from django.conf import settings +from django.core.exceptions import MiddlewareNotUsed +from django.http import HttpResponseForbidden + + +def readonly_middleware(get_response): + + if not settings.UMAP_READONLY: + raise MiddlewareNotUsed + + def middleware(request): + if request.method not in ['GET', 'OPTIONS']: + return HttpResponseForbidden('Site is readonly') + + return get_response(request) + + return middleware diff --git a/umap/settings/base.py b/umap/settings/base.py index 3d5d592d..093b3fde 100644 --- a/umap/settings/base.py +++ b/umap/settings/base.py @@ -149,6 +149,7 @@ MIDDLEWARE = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.locale.LocaleMiddleware', 'django.middleware.common.CommonMiddleware', + 'umap.middleware.readonly_middleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', @@ -185,6 +186,7 @@ DATABASES = { 'NAME': 'umap', } } +UMAP_READONLY = False # ============================================================================= # Third party app settings diff --git a/umap/settings/local.py.sample b/umap/settings/local.py.sample index 6404bf80..204b8575 100644 --- a/umap/settings/local.py.sample +++ b/umap/settings/local.py.sample @@ -55,7 +55,7 @@ SOCIAL_AUTH_TWITTER_KEY = "xxx" SOCIAL_AUTH_TWITTER_SECRET = "xxx" SOCIAL_AUTH_OPENSTREETMAP_KEY = 'xxx' SOCIAL_AUTH_OPENSTREETMAP_SECRET = 'xxx' -MIDDLEWARE_CLASSES += ( +MIDDLEWARE += ( 'social_django.middleware.SocialAuthExceptionMiddleware', ) SOCIAL_AUTH_RAISE_EXCEPTIONS = False @@ -98,6 +98,10 @@ EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' # CREATE EXTENSION unaccent; UMAP_USE_UNACCENT = False +# Put the site in readonly mode (useful for migration or any maintenance) +UMAP_READONLY = False + + # For static deployment STATIC_ROOT = '/home/srv/var/static' diff --git a/umap/tests/test_datalayer_views.py b/umap/tests/test_datalayer_views.py index b3689115..d88bdd69 100644 --- a/umap/tests/test_datalayer_views.py +++ b/umap/tests/test_datalayer_views.py @@ -160,3 +160,11 @@ def test_version_should_return_one_version_geojson(client, datalayer, map): datalayer.geojson.storage.save('%s/%s' % (root, name), ContentFile("{}")) url = reverse('datalayer_version', args=(datalayer.pk, name)) assert client.get(url).content.decode() == "{}" + + +def test_update_readonly(client, datalayer, map, post_data, settings): + settings.UMAP_READONLY = True + url = reverse('datalayer_update', args=(map.pk, datalayer.pk)) + client.login(username=map.owner.username, password="123123") + response = client.post(url, post_data, follow=True) + assert response.status_code == 403 diff --git a/umap/tests/test_map_views.py b/umap/tests/test_map_views.py index 9069f3e6..bddbf9cb 100644 --- a/umap/tests/test_map_views.py +++ b/umap/tests/test_map_views.py @@ -472,3 +472,12 @@ def test_map_attach_owner_anonymous_not_allowed(cookieclient, anonymap, user): # client.login(username=user.username, password="123123") # response = client.post(url, {}) # assert response.status_code == 403 + + +def test_create_readonly(client, user, post_data, settings): + settings.UMAP_READONLY = True + url = reverse('map_create') + client.login(username=user.username, password="123123") + response = client.post(url, post_data) + assert response.status_code == 403 + assert response.content == b'Site is readonly'