umap-project 2.7.3__py3-none-any.whl → 2.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- umap/__init__.py +1 -1
- umap/forms.py +4 -14
- umap/locale/am_ET/LC_MESSAGES/django.mo +0 -0
- umap/locale/am_ET/LC_MESSAGES/django.po +278 -151
- umap/locale/ar/LC_MESSAGES/django.mo +0 -0
- umap/locale/ar/LC_MESSAGES/django.po +335 -141
- umap/locale/bg/LC_MESSAGES/django.mo +0 -0
- umap/locale/bg/LC_MESSAGES/django.po +279 -152
- umap/locale/br/LC_MESSAGES/django.mo +0 -0
- umap/locale/br/LC_MESSAGES/django.po +95 -79
- umap/locale/ca/LC_MESSAGES/django.mo +0 -0
- umap/locale/ca/LC_MESSAGES/django.po +85 -68
- umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
- umap/locale/cs_CZ/LC_MESSAGES/django.po +78 -66
- umap/locale/da/LC_MESSAGES/django.mo +0 -0
- umap/locale/da/LC_MESSAGES/django.po +280 -153
- umap/locale/de/LC_MESSAGES/django.mo +0 -0
- umap/locale/de/LC_MESSAGES/django.po +80 -64
- umap/locale/el/LC_MESSAGES/django.mo +0 -0
- umap/locale/el/LC_MESSAGES/django.po +82 -66
- umap/locale/en/LC_MESSAGES/django.po +73 -61
- umap/locale/es/LC_MESSAGES/django.mo +0 -0
- umap/locale/es/LC_MESSAGES/django.po +75 -63
- umap/locale/et/LC_MESSAGES/django.mo +0 -0
- umap/locale/et/LC_MESSAGES/django.po +280 -153
- umap/locale/eu/LC_MESSAGES/django.mo +0 -0
- umap/locale/eu/LC_MESSAGES/django.po +82 -66
- umap/locale/fa_IR/LC_MESSAGES/django.mo +0 -0
- umap/locale/fa_IR/LC_MESSAGES/django.po +80 -64
- umap/locale/fi/LC_MESSAGES/django.mo +0 -0
- umap/locale/fi/LC_MESSAGES/django.po +278 -151
- umap/locale/fr/LC_MESSAGES/django.mo +0 -0
- umap/locale/fr/LC_MESSAGES/django.po +75 -63
- umap/locale/gl/LC_MESSAGES/django.mo +0 -0
- umap/locale/gl/LC_MESSAGES/django.po +280 -153
- umap/locale/he/LC_MESSAGES/django.mo +0 -0
- umap/locale/he/LC_MESSAGES/django.po +281 -154
- umap/locale/hu/LC_MESSAGES/django.mo +0 -0
- umap/locale/hu/LC_MESSAGES/django.po +80 -64
- umap/locale/is/LC_MESSAGES/django.mo +0 -0
- umap/locale/is/LC_MESSAGES/django.po +280 -153
- umap/locale/it/LC_MESSAGES/django.mo +0 -0
- umap/locale/it/LC_MESSAGES/django.po +82 -66
- umap/locale/ja/LC_MESSAGES/django.mo +0 -0
- umap/locale/ja/LC_MESSAGES/django.po +280 -153
- umap/locale/ko/LC_MESSAGES/django.mo +0 -0
- umap/locale/ko/LC_MESSAGES/django.po +280 -153
- umap/locale/lt/LC_MESSAGES/django.mo +0 -0
- umap/locale/lt/LC_MESSAGES/django.po +280 -153
- umap/locale/ms/LC_MESSAGES/django.mo +0 -0
- umap/locale/ms/LC_MESSAGES/django.po +82 -66
- umap/locale/nl/LC_MESSAGES/django.mo +0 -0
- umap/locale/nl/LC_MESSAGES/django.po +280 -153
- umap/locale/pl/LC_MESSAGES/django.mo +0 -0
- umap/locale/pl/LC_MESSAGES/django.po +82 -66
- umap/locale/pt/LC_MESSAGES/django.mo +0 -0
- umap/locale/pt/LC_MESSAGES/django.po +75 -63
- umap/locale/pt_BR/LC_MESSAGES/django.mo +0 -0
- umap/locale/pt_BR/LC_MESSAGES/django.po +280 -153
- umap/locale/pt_PT/LC_MESSAGES/django.mo +0 -0
- umap/locale/pt_PT/LC_MESSAGES/django.po +280 -153
- umap/locale/ru/LC_MESSAGES/django.mo +0 -0
- umap/locale/ru/LC_MESSAGES/django.po +280 -153
- umap/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
- umap/locale/sk_SK/LC_MESSAGES/django.po +280 -153
- umap/locale/sl/LC_MESSAGES/django.mo +0 -0
- umap/locale/sl/LC_MESSAGES/django.po +280 -153
- umap/locale/sr/LC_MESSAGES/django.mo +0 -0
- umap/locale/sr/LC_MESSAGES/django.po +280 -153
- umap/locale/sv/LC_MESSAGES/django.mo +0 -0
- umap/locale/sv/LC_MESSAGES/django.po +81 -65
- umap/locale/th_TH/LC_MESSAGES/django.mo +0 -0
- umap/locale/th_TH/LC_MESSAGES/django.po +257 -185
- umap/locale/tr/LC_MESSAGES/django.mo +0 -0
- umap/locale/tr/LC_MESSAGES/django.po +280 -153
- umap/locale/uk_UA/LC_MESSAGES/django.mo +0 -0
- umap/locale/uk_UA/LC_MESSAGES/django.po +280 -153
- umap/locale/vi/LC_MESSAGES/django.mo +0 -0
- umap/locale/vi/LC_MESSAGES/django.po +278 -151
- umap/locale/zh/LC_MESSAGES/django.mo +0 -0
- umap/locale/zh/LC_MESSAGES/django.po +278 -151
- umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
- umap/locale/zh_TW/LC_MESSAGES/django.po +97 -81
- umap/management/commands/empty_trash.py +35 -0
- umap/management/commands/migrate_to_S3.py +29 -0
- umap/migrations/0023_alter_datalayer_uuid.py +19 -0
- umap/migrations/0024_alter_map_share_status.py +30 -0
- umap/migrations/0025_alter_datalayer_geojson.py +24 -0
- umap/models.py +68 -116
- umap/settings/base.py +23 -3
- umap/settings/local_s3.py +45 -0
- umap/static/umap/base.css +3 -603
- umap/static/umap/content.css +5 -3
- umap/static/umap/css/bar.css +202 -0
- umap/static/umap/css/form.css +620 -0
- umap/static/umap/css/icon.css +21 -1
- umap/static/umap/css/popup.css +125 -0
- umap/static/umap/img/16-white.svg +16 -4
- umap/static/umap/img/16.svg +1 -1
- umap/static/umap/img/source/16-white.svg +46 -45
- umap/static/umap/img/source/16.svg +1 -753
- umap/static/umap/js/components/fragment.js +3 -1
- umap/static/umap/js/modules/browser.js +20 -19
- umap/static/umap/js/modules/caption.js +21 -22
- umap/static/umap/js/modules/data/features.js +120 -78
- umap/static/umap/js/modules/data/layer.js +195 -153
- umap/static/umap/js/modules/facets.js +9 -9
- umap/static/umap/js/modules/formatter.js +5 -5
- umap/static/umap/js/modules/global.js +4 -52
- umap/static/umap/js/modules/help.js +18 -21
- umap/static/umap/js/modules/importer.js +133 -56
- umap/static/umap/js/modules/importers/cadastrefr.js +4 -0
- umap/static/umap/js/modules/importers/geodatamine.js +3 -3
- umap/static/umap/js/modules/importers/overpass.js +5 -0
- umap/static/umap/js/modules/permissions.js +85 -87
- umap/static/umap/js/modules/rendering/icon.js +2 -1
- umap/static/umap/js/modules/rendering/layers/base.js +15 -15
- umap/static/umap/js/modules/rendering/layers/classified.js +1 -1
- umap/static/umap/js/modules/rendering/layers/cluster.js +1 -1
- umap/static/umap/js/modules/rendering/layers/heat.js +1 -1
- umap/static/umap/js/modules/rendering/map.js +390 -0
- umap/static/umap/js/modules/rendering/popup.js +19 -19
- umap/static/umap/js/modules/rendering/template.js +88 -21
- umap/static/umap/js/modules/rendering/ui.js +63 -14
- umap/static/umap/js/modules/request.js +2 -2
- umap/static/umap/js/modules/rules.js +22 -25
- umap/static/umap/js/modules/saving.js +47 -0
- umap/static/umap/js/modules/schema.js +6 -0
- umap/static/umap/js/modules/share.js +21 -24
- umap/static/umap/js/modules/slideshow.js +24 -20
- umap/static/umap/js/modules/sync/updaters.js +7 -9
- umap/static/umap/js/modules/tableeditor.js +20 -19
- umap/static/umap/js/modules/ui/bar.js +196 -0
- umap/static/umap/js/modules/ui/dialog.js +5 -0
- umap/static/umap/js/modules/ui/panel.js +10 -9
- umap/static/umap/js/modules/umap.js +1691 -0
- umap/static/umap/js/modules/urls.js +2 -2
- umap/static/umap/js/modules/utils.js +22 -6
- umap/static/umap/js/umap.controls.js +81 -305
- umap/static/umap/js/umap.core.js +29 -50
- umap/static/umap/js/umap.forms.js +78 -27
- umap/static/umap/keycloak.png +0 -0
- umap/static/umap/locale/am_ET.js +26 -10
- umap/static/umap/locale/am_ET.json +26 -10
- umap/static/umap/locale/ar.js +26 -10
- umap/static/umap/locale/ar.json +26 -10
- umap/static/umap/locale/ast.js +26 -10
- umap/static/umap/locale/ast.json +26 -10
- umap/static/umap/locale/bg.js +26 -10
- umap/static/umap/locale/bg.json +26 -10
- umap/static/umap/locale/br.js +27 -20
- umap/static/umap/locale/br.json +27 -20
- umap/static/umap/locale/ca.js +32 -29
- umap/static/umap/locale/ca.json +32 -29
- umap/static/umap/locale/cs_CZ.js +24 -17
- umap/static/umap/locale/cs_CZ.json +24 -17
- umap/static/umap/locale/da.js +26 -10
- umap/static/umap/locale/da.json +26 -10
- umap/static/umap/locale/de.js +21 -14
- umap/static/umap/locale/de.json +21 -14
- umap/static/umap/locale/el.js +28 -12
- umap/static/umap/locale/el.json +28 -12
- umap/static/umap/locale/en.js +14 -9
- umap/static/umap/locale/en.json +14 -9
- umap/static/umap/locale/en_US.json +26 -10
- umap/static/umap/locale/es.js +16 -13
- umap/static/umap/locale/es.json +16 -13
- umap/static/umap/locale/et.js +26 -10
- umap/static/umap/locale/et.json +26 -10
- umap/static/umap/locale/eu.js +16 -9
- umap/static/umap/locale/eu.json +16 -9
- umap/static/umap/locale/fa_IR.js +16 -9
- umap/static/umap/locale/fa_IR.json +16 -9
- umap/static/umap/locale/fi.js +26 -10
- umap/static/umap/locale/fi.json +26 -10
- umap/static/umap/locale/fr.js +14 -9
- umap/static/umap/locale/fr.json +14 -9
- umap/static/umap/locale/gl.js +26 -10
- umap/static/umap/locale/gl.json +26 -10
- umap/static/umap/locale/he.js +26 -10
- umap/static/umap/locale/he.json +26 -10
- umap/static/umap/locale/hr.js +26 -10
- umap/static/umap/locale/hr.json +26 -10
- umap/static/umap/locale/hu.js +16 -9
- umap/static/umap/locale/hu.json +16 -9
- umap/static/umap/locale/id.js +26 -10
- umap/static/umap/locale/id.json +26 -10
- umap/static/umap/locale/is.js +26 -10
- umap/static/umap/locale/is.json +26 -10
- umap/static/umap/locale/it.js +26 -10
- umap/static/umap/locale/it.json +26 -10
- umap/static/umap/locale/ja.js +26 -10
- umap/static/umap/locale/ja.json +26 -10
- umap/static/umap/locale/ko.js +26 -10
- umap/static/umap/locale/ko.json +26 -10
- umap/static/umap/locale/lt.js +26 -10
- umap/static/umap/locale/lt.json +26 -10
- umap/static/umap/locale/ms.js +28 -12
- umap/static/umap/locale/ms.json +28 -12
- umap/static/umap/locale/nl.js +28 -12
- umap/static/umap/locale/nl.json +28 -12
- umap/static/umap/locale/no.js +26 -10
- umap/static/umap/locale/no.json +26 -10
- umap/static/umap/locale/pl.js +28 -12
- umap/static/umap/locale/pl.json +28 -12
- umap/static/umap/locale/pl_PL.json +26 -10
- umap/static/umap/locale/pt.js +16 -9
- umap/static/umap/locale/pt.json +16 -9
- umap/static/umap/locale/pt_BR.js +26 -10
- umap/static/umap/locale/pt_BR.json +26 -10
- umap/static/umap/locale/pt_PT.js +16 -9
- umap/static/umap/locale/pt_PT.json +16 -9
- umap/static/umap/locale/ro.js +26 -10
- umap/static/umap/locale/ro.json +26 -10
- umap/static/umap/locale/ru.js +26 -10
- umap/static/umap/locale/ru.json +26 -10
- umap/static/umap/locale/si.js +7 -7
- umap/static/umap/locale/si.json +7 -7
- umap/static/umap/locale/sk_SK.js +26 -10
- umap/static/umap/locale/sk_SK.json +26 -10
- umap/static/umap/locale/sl.js +26 -10
- umap/static/umap/locale/sl.json +26 -10
- umap/static/umap/locale/sr.js +26 -10
- umap/static/umap/locale/sr.json +26 -10
- umap/static/umap/locale/sv.js +27 -11
- umap/static/umap/locale/sv.json +27 -11
- umap/static/umap/locale/th_TH.js +28 -12
- umap/static/umap/locale/th_TH.json +28 -12
- umap/static/umap/locale/tr.js +26 -10
- umap/static/umap/locale/tr.json +26 -10
- umap/static/umap/locale/uk_UA.js +26 -10
- umap/static/umap/locale/uk_UA.json +26 -10
- umap/static/umap/locale/vi.js +26 -10
- umap/static/umap/locale/vi.json +26 -10
- umap/static/umap/locale/vi_VN.json +26 -10
- umap/static/umap/locale/zh.js +26 -10
- umap/static/umap/locale/zh.json +26 -10
- umap/static/umap/locale/zh_CN.json +26 -10
- umap/static/umap/locale/zh_TW.Big5.json +26 -10
- umap/static/umap/locale/zh_TW.js +34 -27
- umap/static/umap/locale/zh_TW.json +34 -27
- umap/static/umap/map.css +39 -530
- umap/static/umap/unittests/URLs.js +15 -15
- umap/static/umap/unittests/utils.js +23 -1
- umap/static/umap/vars.css +2 -1
- umap/static/umap/vendors/formbuilder/Leaflet.FormBuilder.js +5 -1
- umap/storage/__init__.py +3 -0
- umap/storage/fs.py +101 -0
- umap/storage/s3.py +61 -0
- umap/templates/base.html +2 -0
- umap/templates/registration/login.html +7 -6
- umap/templates/umap/components/alerts/alert.html +4 -0
- umap/templates/umap/css.html +6 -0
- umap/templates/umap/js.html +3 -2
- umap/templates/umap/map_init.html +6 -5
- umap/templates/umap/user_dashboard.html +20 -19
- umap/tests/base.py +5 -1
- umap/tests/fixtures/test_upload_simple_marker.json +19 -0
- umap/tests/integration/conftest.py +2 -1
- umap/tests/integration/test_anonymous_owned_map.py +18 -10
- umap/tests/integration/test_browser.py +16 -1
- umap/tests/integration/test_dashboard.py +1 -1
- umap/tests/integration/test_edit_datalayer.py +29 -7
- umap/tests/integration/test_import.py +28 -6
- umap/tests/integration/test_optimistic_merge.py +31 -8
- umap/tests/integration/test_owned_map.py +22 -16
- umap/tests/integration/test_popup.py +44 -0
- umap/tests/integration/test_save.py +35 -0
- umap/tests/integration/test_view_marker.py +12 -0
- umap/tests/integration/test_view_polyline.py +257 -0
- umap/tests/integration/test_websocket_sync.py +81 -9
- umap/tests/test_dashboard.py +82 -0
- umap/tests/test_datalayer.py +6 -7
- umap/tests/test_datalayer_s3.py +135 -0
- umap/tests/test_datalayer_views.py +28 -10
- umap/tests/test_empty_trash.py +34 -0
- umap/tests/test_map.py +12 -3
- umap/tests/test_map_views.py +69 -37
- umap/tests/test_statics.py +1 -1
- umap/tests/test_team_views.py +35 -1
- umap/tests/test_views.py +31 -52
- umap/urls.py +3 -3
- umap/views.py +126 -90
- {umap_project-2.7.3.dist-info → umap_project-2.8.0.dist-info}/METADATA +16 -13
- {umap_project-2.7.3.dist-info → umap_project-2.8.0.dist-info}/RECORD +289 -269
- umap/management/commands/purge_purgatory.py +0 -28
- umap/static/umap/js/umap.js +0 -1903
- umap/tests/test_purge_purgatory.py +0 -25
- /umap/{storage.py → storage/staticfiles.py} +0 -0
- {umap_project-2.7.3.dist-info → umap_project-2.8.0.dist-info}/WHEEL +0 -0
- {umap_project-2.7.3.dist-info → umap_project-2.8.0.dist-info}/entry_points.txt +0 -0
- {umap_project-2.7.3.dist-info → umap_project-2.8.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from copy import deepcopy
|
|
3
3
|
from pathlib import Path
|
|
4
|
+
from uuid import uuid4
|
|
4
5
|
|
|
5
6
|
import pytest
|
|
6
7
|
from django.core.files.base import ContentFile
|
|
@@ -105,6 +106,21 @@ def test_gzip_should_be_created_if_accepted(client, datalayer, map, post_data):
|
|
|
105
106
|
assert Path(flat).stat().st_mtime_ns == Path(gzipped).stat().st_mtime_ns
|
|
106
107
|
|
|
107
108
|
|
|
109
|
+
def test_create_datalayer(client, map, post_data):
|
|
110
|
+
uuid = str(uuid4())
|
|
111
|
+
url = reverse("datalayer_create", args=(map.pk, uuid))
|
|
112
|
+
client.login(username=map.owner.username, password="123123")
|
|
113
|
+
response = client.post(url, post_data, follow=True)
|
|
114
|
+
assert response.status_code == 200
|
|
115
|
+
new_datalayer = DataLayer.objects.get(pk=uuid)
|
|
116
|
+
assert new_datalayer.name == "name"
|
|
117
|
+
assert new_datalayer.rank == 0
|
|
118
|
+
# Test response is a json
|
|
119
|
+
data = json.loads(response.content.decode())
|
|
120
|
+
assert "id" in data
|
|
121
|
+
assert data["id"] == uuid
|
|
122
|
+
|
|
123
|
+
|
|
108
124
|
def test_update(client, datalayer, map, post_data):
|
|
109
125
|
url = reverse("datalayer_update", args=(map.pk, datalayer.pk))
|
|
110
126
|
client.login(username=map.owner.username, password="123123")
|
|
@@ -215,7 +231,7 @@ def test_optimistic_concurrency_control_with_empty_version(
|
|
|
215
231
|
def test_versions_should_return_versions(client, datalayer, map, settings):
|
|
216
232
|
map.share_status = Map.PUBLIC
|
|
217
233
|
map.save()
|
|
218
|
-
root = datalayer.
|
|
234
|
+
root = datalayer.geojson.storage._base_path(datalayer)
|
|
219
235
|
datalayer.geojson.storage.save(
|
|
220
236
|
"%s/%s_1440924889.geojson" % (root, datalayer.pk), ContentFile("{}")
|
|
221
237
|
)
|
|
@@ -232,6 +248,7 @@ def test_versions_should_return_versions(client, datalayer, map, settings):
|
|
|
232
248
|
"name": "%s_1440918637.geojson" % datalayer.pk,
|
|
233
249
|
"size": 2,
|
|
234
250
|
"at": "1440918637",
|
|
251
|
+
"ref": "1440918637",
|
|
235
252
|
}
|
|
236
253
|
assert version in versions["versions"]
|
|
237
254
|
|
|
@@ -239,7 +256,7 @@ def test_versions_should_return_versions(client, datalayer, map, settings):
|
|
|
239
256
|
def test_versions_can_return_old_format(client, datalayer, map, settings):
|
|
240
257
|
map.share_status = Map.PUBLIC
|
|
241
258
|
map.save()
|
|
242
|
-
root = datalayer.
|
|
259
|
+
root = datalayer.geojson.storage._base_path(datalayer)
|
|
243
260
|
datalayer.old_id = 123 # old datalayer id (now replaced by uuid)
|
|
244
261
|
datalayer.save()
|
|
245
262
|
|
|
@@ -263,31 +280,32 @@ def test_versions_can_return_old_format(client, datalayer, map, settings):
|
|
|
263
280
|
"name": old_format_version,
|
|
264
281
|
"size": 2,
|
|
265
282
|
"at": "1440918637",
|
|
283
|
+
"ref": "1440918637",
|
|
266
284
|
}
|
|
267
285
|
assert version in versions["versions"]
|
|
268
286
|
|
|
269
|
-
client.get(
|
|
270
|
-
reverse("datalayer_version", args=(map.pk, datalayer.pk, old_format_version))
|
|
271
|
-
)
|
|
287
|
+
client.get(reverse("datalayer_version", args=(map.pk, datalayer.pk, "1440918637")))
|
|
272
288
|
|
|
273
289
|
|
|
274
290
|
def test_version_should_return_one_version_geojson(client, datalayer, map):
|
|
275
291
|
map.share_status = Map.PUBLIC
|
|
276
292
|
map.save()
|
|
277
|
-
root = datalayer.
|
|
293
|
+
root = datalayer.geojson.storage._base_path(datalayer)
|
|
278
294
|
name = "%s_1440924889.geojson" % datalayer.pk
|
|
279
295
|
datalayer.geojson.storage.save("%s/%s" % (root, name), ContentFile("{}"))
|
|
280
|
-
url = reverse("datalayer_version", args=(map.pk, datalayer.pk,
|
|
281
|
-
|
|
296
|
+
url = reverse("datalayer_version", args=(map.pk, datalayer.pk, "1440924889"))
|
|
297
|
+
resp = client.get(url)
|
|
298
|
+
assert resp.status_code == 200
|
|
299
|
+
assert resp.content.decode() == "{}"
|
|
282
300
|
|
|
283
301
|
|
|
284
302
|
def test_version_should_return_403_if_not_allowed(client, datalayer, map):
|
|
285
303
|
map.share_status = Map.PRIVATE
|
|
286
304
|
map.save()
|
|
287
|
-
root = datalayer.
|
|
305
|
+
root = datalayer.geojson.storage._base_path(datalayer)
|
|
288
306
|
name = "%s_1440924889.geojson" % datalayer.pk
|
|
289
307
|
datalayer.geojson.storage.save("%s/%s" % (root, name), ContentFile("{}"))
|
|
290
|
-
url = reverse("datalayer_version", args=(map.pk, datalayer.pk,
|
|
308
|
+
url = reverse("datalayer_version", args=(map.pk, datalayer.pk, "1440924889"))
|
|
291
309
|
assert client.get(url).status_code == 403
|
|
292
310
|
|
|
293
311
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from datetime import datetime, timedelta
|
|
2
|
+
from unittest import mock
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
from django.core.management import call_command
|
|
6
|
+
|
|
7
|
+
from umap.models import Map
|
|
8
|
+
|
|
9
|
+
from .base import MapFactory
|
|
10
|
+
|
|
11
|
+
pytestmark = pytest.mark.django_db
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_empty_trash(user):
|
|
15
|
+
recent = MapFactory(owner=user)
|
|
16
|
+
recent_deleted = MapFactory(owner=user)
|
|
17
|
+
recent_deleted.move_to_trash()
|
|
18
|
+
recent_deleted.save()
|
|
19
|
+
with mock.patch("django.utils.timezone.now") as mocked:
|
|
20
|
+
mocked.return_value = datetime.utcnow() - timedelta(days=8)
|
|
21
|
+
old_deleted = MapFactory(owner=user)
|
|
22
|
+
old_deleted.move_to_trash()
|
|
23
|
+
old_deleted.save()
|
|
24
|
+
old = MapFactory(owner=user)
|
|
25
|
+
assert Map.objects.count() == 4
|
|
26
|
+
call_command("empty_trash", "--days=7", "--dry-run")
|
|
27
|
+
assert Map.objects.count() == 4
|
|
28
|
+
call_command("empty_trash", "--days=9")
|
|
29
|
+
assert Map.objects.count() == 4
|
|
30
|
+
call_command("empty_trash", "--days=7")
|
|
31
|
+
assert not Map.objects.filter(pk=old_deleted.pk)
|
|
32
|
+
assert Map.objects.filter(pk=old.pk)
|
|
33
|
+
assert Map.objects.filter(pk=recent.pk)
|
|
34
|
+
assert Map.objects.filter(pk=recent_deleted.pk)
|
umap/tests/test_map.py
CHANGED
|
@@ -2,6 +2,7 @@ import pytest
|
|
|
2
2
|
from django.contrib.auth.models import AnonymousUser
|
|
3
3
|
from django.urls import reverse
|
|
4
4
|
|
|
5
|
+
from umap.forms import DEFAULT_CENTER
|
|
5
6
|
from umap.models import Map
|
|
6
7
|
|
|
7
8
|
from .base import MapFactory
|
|
@@ -160,8 +161,16 @@ def test_can_change_default_edit_status(user, settings):
|
|
|
160
161
|
|
|
161
162
|
|
|
162
163
|
def test_can_change_default_share_status(user, settings):
|
|
164
|
+
map = Map.objects.create(owner=user, center=DEFAULT_CENTER)
|
|
165
|
+
assert map.share_status == Map.DRAFT
|
|
166
|
+
settings.UMAP_DEFAULT_SHARE_STATUS = Map.PUBLIC
|
|
167
|
+
map = Map.objects.create(owner=user, center=DEFAULT_CENTER)
|
|
163
168
|
map = MapFactory(owner=user)
|
|
164
169
|
assert map.share_status == Map.PUBLIC
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def test_move_to_trash(user, map):
|
|
173
|
+
map.move_to_trash()
|
|
174
|
+
map.save()
|
|
175
|
+
reloaded = Map.objects.get(pk=map.pk)
|
|
176
|
+
assert reloaded.share_status == Map.DELETED
|
umap/tests/test_map_views.py
CHANGED
|
@@ -42,7 +42,7 @@ def test_create(client, user, post_data):
|
|
|
42
42
|
assert created_map.center.y == 48.94415123418794
|
|
43
43
|
assert j["permissions"] == {
|
|
44
44
|
"edit_status": 3,
|
|
45
|
-
"share_status":
|
|
45
|
+
"share_status": 0,
|
|
46
46
|
"owner": {"id": user.pk, "name": "Joe", "url": "/en/user/Joe/"},
|
|
47
47
|
"editors": [],
|
|
48
48
|
}
|
|
@@ -114,8 +114,10 @@ def test_delete(client, map, datalayer):
|
|
|
114
114
|
url, headers={"X-Requested-With": "XMLHttpRequest"}, follow=True
|
|
115
115
|
)
|
|
116
116
|
assert response.status_code == 200
|
|
117
|
-
assert
|
|
118
|
-
assert
|
|
117
|
+
assert Map.objects.filter(pk=map.pk).exists()
|
|
118
|
+
assert DataLayer.objects.filter(pk=datalayer.pk).exists()
|
|
119
|
+
reloaded = Map.objects.get(pk=map.pk)
|
|
120
|
+
assert reloaded.share_status == Map.DELETED
|
|
119
121
|
# Check that user has not been impacted
|
|
120
122
|
assert User.objects.filter(pk=map.owner.pk).exists()
|
|
121
123
|
# Test response is a json
|
|
@@ -241,42 +243,46 @@ def test_map_creation_should_allow_unicode_names(client, map, post_data):
|
|
|
241
243
|
assert created_map.slug == "map"
|
|
242
244
|
|
|
243
245
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
map
|
|
247
|
-
|
|
248
|
-
response = client.get(url)
|
|
249
|
-
assert response.status_code == 200
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
def test_anonymous_can_access_map_with_share_status_open(client, map):
|
|
246
|
+
@pytest.mark.parametrize("share_status", [Map.PUBLIC, Map.OPEN])
|
|
247
|
+
def test_anonymous_can_access_map_with_share_status_accessible(
|
|
248
|
+
client, map, share_status
|
|
249
|
+
):
|
|
253
250
|
url = reverse("map", args=(map.slug, map.pk))
|
|
254
|
-
map.share_status =
|
|
251
|
+
map.share_status = share_status
|
|
255
252
|
map.save()
|
|
256
253
|
response = client.get(url)
|
|
257
254
|
assert response.status_code == 200
|
|
258
255
|
|
|
259
256
|
|
|
260
|
-
|
|
257
|
+
@pytest.mark.parametrize(
|
|
258
|
+
"share_status", [Map.PRIVATE, Map.DRAFT, Map.BLOCKED, Map.DELETED]
|
|
259
|
+
)
|
|
260
|
+
def test_anonymous_cannot_access_map_with_share_status_restricted(
|
|
261
|
+
client, map, share_status
|
|
262
|
+
):
|
|
261
263
|
url = reverse("map", args=(map.slug, map.pk))
|
|
262
|
-
map.share_status =
|
|
264
|
+
map.share_status = share_status
|
|
263
265
|
map.save()
|
|
264
266
|
response = client.get(url)
|
|
265
267
|
assert response.status_code == 403
|
|
266
268
|
|
|
267
269
|
|
|
268
|
-
|
|
270
|
+
@pytest.mark.parametrize("share_status", [Map.PRIVATE, Map.DRAFT])
|
|
271
|
+
def test_owner_can_access_map_with_share_status_restricted(client, map, share_status):
|
|
269
272
|
url = reverse("map", args=(map.slug, map.pk))
|
|
270
|
-
map.share_status =
|
|
273
|
+
map.share_status = share_status
|
|
271
274
|
map.save()
|
|
272
275
|
client.login(username=map.owner.username, password="123123")
|
|
273
276
|
response = client.get(url)
|
|
274
277
|
assert response.status_code == 200
|
|
275
278
|
|
|
276
279
|
|
|
277
|
-
|
|
280
|
+
@pytest.mark.parametrize("share_status", [Map.PRIVATE, Map.DRAFT])
|
|
281
|
+
def test_editors_can_access_map_with_share_status_resricted(
|
|
282
|
+
client, map, user, share_status
|
|
283
|
+
):
|
|
278
284
|
url = reverse("map", args=(map.slug, map.pk))
|
|
279
|
-
map.share_status =
|
|
285
|
+
map.share_status = share_status
|
|
280
286
|
map.editors.add(user)
|
|
281
287
|
map.save()
|
|
282
288
|
client.login(username=user.username, password="123123")
|
|
@@ -284,10 +290,11 @@ def test_editors_can_access_map_with_share_status_private(client, map, user):
|
|
|
284
290
|
assert response.status_code == 200
|
|
285
291
|
|
|
286
292
|
|
|
287
|
-
def
|
|
293
|
+
def test_owner_cannot_access_map_with_share_status_deleted(client, map):
|
|
288
294
|
url = reverse("map", args=(map.slug, map.pk))
|
|
289
|
-
map.share_status = map.
|
|
295
|
+
map.share_status = map.DELETED
|
|
290
296
|
map.save()
|
|
297
|
+
client.login(username=map.owner.username, password="123123")
|
|
291
298
|
response = client.get(url)
|
|
292
299
|
assert response.status_code == 403
|
|
293
300
|
|
|
@@ -401,14 +408,16 @@ def test_anonymous_delete(cookieclient, anonymap):
|
|
|
401
408
|
url, headers={"X-Requested-With": "XMLHttpRequest"}, follow=True
|
|
402
409
|
)
|
|
403
410
|
assert response.status_code == 200
|
|
404
|
-
assert
|
|
411
|
+
assert Map.objects.filter(pk=anonymap.pk).exists()
|
|
412
|
+
reloaded = Map.objects.get(pk=anonymap.pk)
|
|
413
|
+
assert reloaded.share_status == Map.DELETED
|
|
405
414
|
# Test response is a json
|
|
406
415
|
j = json.loads(response.content.decode())
|
|
407
416
|
assert "redirect" in j
|
|
408
417
|
|
|
409
418
|
|
|
410
419
|
@pytest.mark.usefixtures("allow_anonymous")
|
|
411
|
-
def
|
|
420
|
+
def test_no_cookie_cannot_delete(client, anonymap):
|
|
412
421
|
url = reverse("map_delete", args=(anonymap.pk,))
|
|
413
422
|
response = client.post(
|
|
414
423
|
url, headers={"X-Requested-With": "XMLHttpRequest"}, follow=True
|
|
@@ -416,6 +425,24 @@ def test_no_cookie_cant_delete(client, anonymap):
|
|
|
416
425
|
assert response.status_code == 403
|
|
417
426
|
|
|
418
427
|
|
|
428
|
+
@pytest.mark.usefixtures("allow_anonymous")
|
|
429
|
+
def test_no_cookie_cannot_view_anonymous_owned_map_in_draft(client, anonymap):
|
|
430
|
+
anonymap.share_status = Map.DRAFT
|
|
431
|
+
anonymap.save()
|
|
432
|
+
url = reverse("map", kwargs={"map_id": anonymap.pk, "slug": anonymap.slug})
|
|
433
|
+
response = client.get(url)
|
|
434
|
+
assert response.status_code == 403
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
@pytest.mark.usefixtures("allow_anonymous")
|
|
438
|
+
def test_owner_can_view_anonymous_owned_map_in_draft(cookieclient, anonymap):
|
|
439
|
+
anonymap.share_status = Map.DRAFT
|
|
440
|
+
anonymap.save()
|
|
441
|
+
url = reverse("map", kwargs={"map_id": anonymap.pk, "slug": anonymap.slug})
|
|
442
|
+
response = cookieclient.get(url)
|
|
443
|
+
assert response.status_code == 200
|
|
444
|
+
|
|
445
|
+
|
|
419
446
|
@pytest.mark.usefixtures("allow_anonymous")
|
|
420
447
|
def test_anonymous_edit_url(cookieclient, anonymap):
|
|
421
448
|
url = anonymap.get_anonymous_edit_url()
|
|
@@ -557,16 +584,6 @@ def test_create_readonly(client, user, post_data, settings):
|
|
|
557
584
|
assert response.content == b"Site is readonly for maintenance"
|
|
558
585
|
|
|
559
586
|
|
|
560
|
-
def test_search(client, map):
|
|
561
|
-
# Very basic search, that do not deal with accent nor case.
|
|
562
|
-
# See install.md for how to have a smarter dict + index.
|
|
563
|
-
map.name = "Blé dur"
|
|
564
|
-
map.save()
|
|
565
|
-
url = reverse("search")
|
|
566
|
-
response = client.get(url + "?q=Blé")
|
|
567
|
-
assert "Blé dur" in response.content.decode()
|
|
568
|
-
|
|
569
|
-
|
|
570
587
|
def test_authenticated_user_can_star_map(client, map, user):
|
|
571
588
|
url = reverse("map_star", args=(map.pk,))
|
|
572
589
|
client.login(username=user.username, password="123123")
|
|
@@ -748,7 +765,9 @@ def test_download_multiple_maps_editor(client, map, datalayer):
|
|
|
748
765
|
assert f.infolist()[1].filename == f"umap_backup_test-map_{map.id}.umap"
|
|
749
766
|
|
|
750
767
|
|
|
751
|
-
@pytest.mark.parametrize(
|
|
768
|
+
@pytest.mark.parametrize(
|
|
769
|
+
"share_status", [Map.PRIVATE, Map.BLOCKED, Map.DRAFT, Map.DELETED]
|
|
770
|
+
)
|
|
752
771
|
def test_download_shared_status_map(client, map, datalayer, share_status):
|
|
753
772
|
map.share_status = share_status
|
|
754
773
|
map.save()
|
|
@@ -757,8 +776,9 @@ def test_download_shared_status_map(client, map, datalayer, share_status):
|
|
|
757
776
|
assert response.status_code == 403
|
|
758
777
|
|
|
759
778
|
|
|
760
|
-
|
|
761
|
-
|
|
779
|
+
@pytest.mark.parametrize("share_status", [Map.PRIVATE, Map.DRAFT])
|
|
780
|
+
def test_download_my_map(client, map, datalayer, share_status):
|
|
781
|
+
map.share_status = share_status
|
|
762
782
|
map.save()
|
|
763
783
|
client.login(username=map.owner.username, password="123123")
|
|
764
784
|
url = reverse("map_download", args=(map.pk,))
|
|
@@ -769,7 +789,19 @@ def test_download_my_map(client, map, datalayer):
|
|
|
769
789
|
assert j["type"] == "umap"
|
|
770
790
|
|
|
771
791
|
|
|
772
|
-
@pytest.mark.parametrize("share_status", [Map.
|
|
792
|
+
@pytest.mark.parametrize("share_status", [Map.BLOCKED, Map.DELETED])
|
|
793
|
+
def test_download_my_map_blocked_or_deleted(client, map, datalayer, share_status):
|
|
794
|
+
map.share_status = share_status
|
|
795
|
+
map.save()
|
|
796
|
+
client.login(username=map.owner.username, password="123123")
|
|
797
|
+
url = reverse("map_download", args=(map.pk,))
|
|
798
|
+
response = client.get(url)
|
|
799
|
+
assert response.status_code == 403
|
|
800
|
+
|
|
801
|
+
|
|
802
|
+
@pytest.mark.parametrize(
|
|
803
|
+
"share_status", [Map.PRIVATE, Map.BLOCKED, Map.OPEN, Map.DRAFT]
|
|
804
|
+
)
|
|
773
805
|
def test_oembed_shared_status_map(client, map, datalayer, share_status):
|
|
774
806
|
map.share_status = share_status
|
|
775
807
|
map.save()
|
umap/tests/test_statics.py
CHANGED
|
@@ -15,7 +15,7 @@ def staticfiles(settings):
|
|
|
15
15
|
# Make sure settings are properly reset after the test
|
|
16
16
|
settings.STORAGES = deepcopy(settings.STORAGES)
|
|
17
17
|
settings.STORAGES["staticfiles"]["BACKEND"] = (
|
|
18
|
-
"umap.storage.UmapManifestStaticFilesStorage"
|
|
18
|
+
"umap.storage.staticfiles.UmapManifestStaticFilesStorage"
|
|
19
19
|
)
|
|
20
20
|
try:
|
|
21
21
|
call_command("collectstatic", "--noinput")
|
umap/tests/test_team_views.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
from django.urls import reverse
|
|
3
3
|
|
|
4
|
-
from umap.models import Team
|
|
4
|
+
from umap.models import Map, Team
|
|
5
5
|
|
|
6
6
|
pytestmark = pytest.mark.django_db
|
|
7
7
|
|
|
@@ -15,6 +15,40 @@ def test_can_see_team_maps(client, map, team):
|
|
|
15
15
|
assert map.name in response.content.decode()
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
@pytest.mark.parametrize("share_status", [Map.PRIVATE, Map.DRAFT])
|
|
19
|
+
def test_others_cannot_see_team_private_maps_in_team_page(
|
|
20
|
+
client, map, team, user, share_status
|
|
21
|
+
):
|
|
22
|
+
map.team = team
|
|
23
|
+
map.share_status = share_status
|
|
24
|
+
map.save()
|
|
25
|
+
url = reverse("team_maps", args=(team.pk,))
|
|
26
|
+
response = client.get(url)
|
|
27
|
+
assert response.status_code == 200
|
|
28
|
+
assert map.name not in response.content.decode()
|
|
29
|
+
# User is not in team
|
|
30
|
+
client.login(username=user.username, password="123123")
|
|
31
|
+
response = client.get(url)
|
|
32
|
+
assert response.status_code == 200
|
|
33
|
+
assert map.name not in response.content.decode()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@pytest.mark.parametrize("share_status", [Map.PRIVATE, Map.DRAFT])
|
|
37
|
+
def test_members_can_see_private_maps_in_team_page(
|
|
38
|
+
client, map, team, user, share_status
|
|
39
|
+
):
|
|
40
|
+
map.team = team
|
|
41
|
+
map.share_status = share_status
|
|
42
|
+
map.save()
|
|
43
|
+
user.teams.add(team)
|
|
44
|
+
user.save()
|
|
45
|
+
url = reverse("team_maps", args=(team.pk,))
|
|
46
|
+
client.login(username=user.username, password="123123")
|
|
47
|
+
response = client.get(url)
|
|
48
|
+
assert response.status_code == 200
|
|
49
|
+
assert map.name in response.content.decode()
|
|
50
|
+
|
|
51
|
+
|
|
18
52
|
def test_user_can_see_their_teams(client, team, user):
|
|
19
53
|
user.teams.add(team)
|
|
20
54
|
user.save()
|
umap/tests/test_views.py
CHANGED
|
@@ -267,58 +267,6 @@ def test_change_user_slug(client, user, settings):
|
|
|
267
267
|
assert f"/en/user/{user.pk}/" in response.content.decode()
|
|
268
268
|
|
|
269
269
|
|
|
270
|
-
@pytest.mark.django_db
|
|
271
|
-
def test_user_dashboard_is_restricted_to_logged_in(client):
|
|
272
|
-
response = client.get(reverse("user_dashboard"))
|
|
273
|
-
assert response.status_code == 302
|
|
274
|
-
assert response["Location"] == "/en/login/?next=/en/me"
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
@pytest.mark.django_db
|
|
278
|
-
def test_user_dashboard_display_user_maps(client, map):
|
|
279
|
-
client.login(username=map.owner.username, password="123123")
|
|
280
|
-
response = client.get(reverse("user_dashboard"))
|
|
281
|
-
assert response.status_code == 200
|
|
282
|
-
body = response.content.decode()
|
|
283
|
-
assert map.name in body
|
|
284
|
-
assert f"{map.get_absolute_url()}?edit" in body
|
|
285
|
-
assert f"{map.get_absolute_url()}?share" in body
|
|
286
|
-
assert f"/map/{map.pk}/download" in body
|
|
287
|
-
assert "Everyone (public)" in body
|
|
288
|
-
assert "Owner only" in body
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
@pytest.mark.django_db
|
|
292
|
-
def test_user_dashboard_display_user_team_maps(client, map, team, user):
|
|
293
|
-
user.teams.add(team)
|
|
294
|
-
user.save()
|
|
295
|
-
map.team = team
|
|
296
|
-
map.save()
|
|
297
|
-
client.login(username=user.username, password="123123")
|
|
298
|
-
response = client.get(reverse("user_dashboard"))
|
|
299
|
-
assert response.status_code == 200
|
|
300
|
-
body = response.content.decode()
|
|
301
|
-
assert map.name in body
|
|
302
|
-
assert map.get_absolute_url() in body
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
@pytest.mark.django_db
|
|
306
|
-
def test_user_dashboard_display_user_maps_distinct(client, map):
|
|
307
|
-
# cf https://github.com/umap-project/umap/issues/1325
|
|
308
|
-
anonymap = MapFactory(name="Map witout owner should not appear")
|
|
309
|
-
user1 = UserFactory(username="user1")
|
|
310
|
-
user2 = UserFactory(username="user2")
|
|
311
|
-
map.editors.add(user1)
|
|
312
|
-
map.editors.add(user2)
|
|
313
|
-
map.save()
|
|
314
|
-
client.login(username=map.owner.username, password="123123")
|
|
315
|
-
response = client.get(reverse("user_dashboard"))
|
|
316
|
-
assert response.status_code == 200
|
|
317
|
-
body = response.content.decode()
|
|
318
|
-
assert body.count(f'<a href="/en/map/test-map_{map.pk}">test map</a>') == 1
|
|
319
|
-
assert body.count(anonymap.name) == 0
|
|
320
|
-
|
|
321
|
-
|
|
322
270
|
@pytest.mark.django_db
|
|
323
271
|
def test_logout_should_return_redirect(client, user, settings):
|
|
324
272
|
client.login(username=user.username, password="123123")
|
|
@@ -497,3 +445,34 @@ def test_websocket_token_is_generated_for_editors(client, user, user2, map):
|
|
|
497
445
|
resp = client.get(token_url)
|
|
498
446
|
token = resp.json().get("token")
|
|
499
447
|
assert TimestampSigner().unsign_object(token, max_age=30)
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
@pytest.mark.django_db
|
|
451
|
+
def test_search(client, map):
|
|
452
|
+
# Very basic search, that do not deal with accent nor case.
|
|
453
|
+
# See install.md for how to have a smarter dict + index.
|
|
454
|
+
map.name = "Blé dur"
|
|
455
|
+
map.save()
|
|
456
|
+
url = reverse("search")
|
|
457
|
+
response = client.get(url + "?q=Blé")
|
|
458
|
+
assert "Blé dur" in response.content.decode()
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
@pytest.mark.django_db
|
|
462
|
+
def test_cannot_search_blocked_map(client, map):
|
|
463
|
+
map.name = "Blé dur"
|
|
464
|
+
map.share_status = Map.BLOCKED
|
|
465
|
+
map.save()
|
|
466
|
+
url = reverse("search")
|
|
467
|
+
response = client.get(url + "?q=Blé")
|
|
468
|
+
assert "Blé dur" not in response.content.decode()
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
@pytest.mark.django_db
|
|
472
|
+
def test_cannot_search_deleted_map(client, map):
|
|
473
|
+
map.name = "Blé dur"
|
|
474
|
+
map.share_status = Map.DELETED
|
|
475
|
+
map.save()
|
|
476
|
+
url = reverse("search")
|
|
477
|
+
response = client.get(url + "?q=Blé")
|
|
478
|
+
assert "Blé dur" not in response.content.decode()
|
umap/urls.py
CHANGED
|
@@ -87,7 +87,7 @@ i18n_urls += decorated_patterns(
|
|
|
87
87
|
name="datalayer_versions",
|
|
88
88
|
),
|
|
89
89
|
path(
|
|
90
|
-
"datalayer/<int:map_id>/<uuid:pk>/<str:
|
|
90
|
+
"datalayer/<int:map_id>/<uuid:pk>/<str:ref>",
|
|
91
91
|
views.DataLayerVersion.as_view(),
|
|
92
92
|
name="datalayer_version",
|
|
93
93
|
),
|
|
@@ -155,8 +155,8 @@ map_urls = [
|
|
|
155
155
|
views.MapClone.as_view(),
|
|
156
156
|
name="map_clone",
|
|
157
157
|
),
|
|
158
|
-
|
|
159
|
-
|
|
158
|
+
path(
|
|
159
|
+
"map/<int:map_id>/datalayer/create/<uuid:pk>/",
|
|
160
160
|
views.DataLayerCreate.as_view(),
|
|
161
161
|
name="datalayer_create",
|
|
162
162
|
),
|