diff --git a/umap/forms.py b/umap/forms.py index a6afade7..e982799e 100644 --- a/umap/forms.py +++ b/umap/forms.py @@ -40,16 +40,12 @@ class UpdateMapPermissionsForm(forms.ModelForm): class AnonymousMapPermissionsForm(forms.ModelForm): - STATUS = ( - (Map.OWNER, _("Only editable with secret edit link")), - (Map.ANONYMOUS, _("Everyone can edit")), - ) - - edit_status = forms.ChoiceField(choices=STATUS) + edit_status = forms.ChoiceField(choices=Map.ANONYMOUS_EDIT_STATUS) + share_status = forms.ChoiceField(choices=Map.ANONYMOUS_SHARE_STATUS) class Meta: model = Map - fields = ("edit_status",) + fields = ("edit_status", "share_status") class DataLayerForm(forms.ModelForm): @@ -65,13 +61,7 @@ class DataLayerPermissionsForm(forms.ModelForm): class AnonymousDataLayerPermissionsForm(forms.ModelForm): - STATUS = ( - (DataLayer.INHERIT, _("Inherit")), - (DataLayer.OWNER, _("Only editable with secret edit link")), - (DataLayer.ANONYMOUS, _("Everyone can edit")), - ) - - edit_status = forms.ChoiceField(choices=STATUS) + edit_status = forms.ChoiceField(choices=DataLayer.ANONYMOUS_EDIT_STATUS) class Meta: model = DataLayer diff --git a/umap/models.py b/umap/models.py index c7e1d388..93c315d8 100644 --- a/umap/models.py +++ b/umap/models.py @@ -38,13 +38,22 @@ def get_user_stars_url(self): return reverse("user_stars", kwargs={"identifier": identifier}) +def get_user_metadata(self): + return { + "id": self.pk, + "name": str(self), + "url": self.get_url(), + } + + User.add_to_class("__str__", display_name) User.add_to_class("get_url", get_user_url) User.add_to_class("get_stars_url", get_user_stars_url) +User.add_to_class("get_metadata", get_user_metadata) def get_default_share_status(): - return settings.UMAP_DEFAULT_SHARE_STATUS or Map.PUBLIC + return settings.UMAP_DEFAULT_SHARE_STATUS or Map.DRAFT def get_default_edit_status(): @@ -161,20 +170,30 @@ class Map(NamedModel): ANONYMOUS = 1 COLLABORATORS = 2 OWNER = 3 + DRAFT = 0 PUBLIC = 1 OPEN = 2 PRIVATE = 3 BLOCKED = 9 + DELETED = 99 + ANONYMOUS_EDIT_STATUS = ( + (OWNER, _("Only editable with secret edit link")), + (ANONYMOUS, _("Everyone can edit")), + ) EDIT_STATUS = ( (ANONYMOUS, _("Everyone")), (COLLABORATORS, _("Editors and team only")), (OWNER, _("Owner only")), ) - SHARE_STATUS = ( + ANONYMOUS_SHARE_STATUS = ( + (DRAFT, _("Draft (private)")), (PUBLIC, _("Everyone (public)")), + ) + SHARE_STATUS = ANONYMOUS_SHARE_STATUS + ( (OPEN, _("Anyone with link")), (PRIVATE, _("Editors and team only")), (BLOCKED, _("Blocked")), + (DELETED, _("Deleted")), ) slug = models.SlugField(db_index=True) center = models.PointField(geography=True, verbose_name=_("center")) @@ -352,19 +371,20 @@ class Map(NamedModel): return can def can_view(self, request): - if self.share_status == self.BLOCKED: + if self.share_status in [Map.BLOCKED, Map.DELETED]: can = False + elif self.share_status in [Map.PUBLIC, Map.OPEN]: + can = True elif self.owner is None: - can = True - elif self.share_status in [self.PUBLIC, self.OPEN]: - can = True + can = settings.UMAP_ALLOW_ANONYMOUS and self.is_anonymous_owner(request) elif not request.user.is_authenticated: can = False elif request.user == self.owner: can = True else: + restricted = self.share_status in [Map.PRIVATE, Map.DRAFT] can = not ( - self.share_status == self.PRIVATE + restricted and request.user not in self.editors.all() and self.team not in request.user.teams.all() ) @@ -444,6 +464,11 @@ class DataLayer(NamedModel): (COLLABORATORS, _("Editors and team only")), (OWNER, _("Owner only")), ) + ANONYMOUS_EDIT_STATUS = ( + (INHERIT, _("Inherit")), + (OWNER, _("Only editable with secret edit link")), + (ANONYMOUS, _("Everyone can edit")), + ) uuid = models.UUIDField(unique=True, primary_key=True, editable=False) old_id = models.IntegerField(null=True, blank=True) map = models.ForeignKey(Map, on_delete=models.CASCADE) diff --git a/umap/static/umap/js/modules/permissions.js b/umap/static/umap/js/modules/permissions.js index 17552afd..b2c7650f 100644 --- a/umap/static/umap/js/modules/permissions.js +++ b/umap/static/umap/js/modules/permissions.js @@ -50,6 +50,14 @@ export class MapPermissions extends ServerStored { selectOptions: this._umap.properties.edit_statuses, }, ]) + fields.push([ + 'properties.share_status', + { + handler: 'IntSelect', + label: translate('Who can view'), + selectOptions: this._umap.properties.share_statuses, + }, + ]) const builder = new U.FormBuilder(this, fields) const form = builder.build() container.appendChild(form) @@ -184,11 +192,11 @@ export class MapPermissions extends ServerStored { } if (this.isOwner() || this.isAnonymousMap()) { formData.append('edit_status', this.properties.edit_status) + formData.append('share_status', this.properties.share_status) } if (this.isOwner()) { formData.append('owner', this.properties.owner?.id) formData.append('team', this.properties.team?.id || '') - formData.append('share_status', this.properties.share_status) } const [data, response, error] = await this._umap.server.post( this.getUrl(), @@ -228,6 +236,10 @@ export class MapPermissions extends ServerStored { ] } } + + isDraft() { + return this.properties.share_status === 0 + } } export class DataLayerPermissions extends ServerStored { diff --git a/umap/static/umap/js/modules/ui/bar.js b/umap/static/umap/js/modules/ui/bar.js index 87e70e8e..22209a48 100644 --- a/umap/static/umap/js/modules/ui/bar.js +++ b/umap/static/umap/js/modules/ui/bar.js @@ -31,7 +31,8 @@ const TOP_BAR_TEMPLATE = ` ` @@ -145,6 +146,8 @@ export class TopBar extends WithTemplate { redraw() { this.elements.peers.hidden = !this._umap.getProperty('syncEnabled') + this.elements.saveLabel.hidden = this._umap.permissions.isDraft() + this.elements.saveDraftLabel.hidden = !this._umap.permissions.isDraft() } } diff --git a/umap/static/umap/js/modules/umap.js b/umap/static/umap/js/modules/umap.js index 56199b08..1f6827b0 100644 --- a/umap/static/umap/js/modules/umap.js +++ b/umap/static/umap/js/modules/umap.js @@ -1321,6 +1321,7 @@ export default class Umap extends ServerStored { }) }) } + this.topBar.redraw() }, numberOfConnectedPeers: () => { Utils.eachElement('.connected-peers span', (el) => { diff --git a/umap/tests/base.py b/umap/tests/base.py index 81aaac3c..c1bb44e2 100644 --- a/umap/tests/base.py +++ b/umap/tests/base.py @@ -102,6 +102,7 @@ class MapFactory(factory.django.DjangoModelFactory): licence = factory.SubFactory(LicenceFactory) owner = factory.SubFactory(UserFactory) + share_status = Map.PUBLIC @classmethod def _adjust_kwargs(cls, **kwargs): diff --git a/umap/tests/integration/test_anonymous_owned_map.py b/umap/tests/integration/test_anonymous_owned_map.py index 69d7e1b5..5b964883 100644 --- a/umap/tests/integration/test_anonymous_owned_map.py +++ b/umap/tests/integration/test_anonymous_owned_map.py @@ -76,8 +76,6 @@ def test_owner_permissions_form(map, datalayer, live_server, owner_session): edit_permissions = owner_session.get_by_title("Update permissions and editors") expect(edit_permissions).to_be_visible() edit_permissions.click() - select = owner_session.locator(".umap-field-share_status select") - expect(select).to_be_hidden() owner_field = owner_session.locator(".umap-field-owner") expect(owner_field).to_be_hidden() editors_field = owner_session.locator(".umap-field-editors input") @@ -92,8 +90,15 @@ def test_owner_permissions_form(map, datalayer, live_server, owner_session): ".datalayer-permissions select[name='edit_status'] option:checked" ) expect(option).to_have_text("Inherit") - # Those fields should not be present in anonymous maps - expect(owner_session.locator(".umap-field-share_status select")).to_be_hidden() + expect(owner_session.locator(".umap-field-share_status select")).to_be_visible() + options = [ + int(option.get_attribute("value")) + for option in owner_session.locator( + ".umap-field-share_status select option" + ).all() + ] + assert options == [Map.DRAFT, Map.PUBLIC] + # This field should not be present in anonymous maps expect(owner_session.locator(".umap-field-owner")).to_be_hidden() @@ -135,15 +140,15 @@ def test_can_change_perms_after_create(tilelayer, live_server, page): page.get_by_title("Manage layers").click() page.get_by_title("Add a layer").click() page.locator("input[name=name]").fill("Layer 1") - save = page.get_by_role("button", name="Save") - expect(save).to_be_visible() + expect( + page.get_by_role("button", name="Visibility: Draft (private)") + ).to_be_visible() + expect(page.get_by_role("button", name="Save", exact=True)).to_be_hidden() with page.expect_response(re.compile(r".*/datalayer/create/.*")): - save.click() + page.get_by_role("button", name="Save draft", exact=True).click() edit_permissions = page.get_by_title("Update permissions and editors") expect(edit_permissions).to_be_visible() edit_permissions.click() - select = page.locator(".umap-field-share_status select") - expect(select).to_be_hidden() owner_field = page.locator(".umap-field-owner") expect(owner_field).to_be_hidden() editors_field = page.locator(".umap-field-editors input") @@ -157,6 +162,9 @@ def test_can_change_perms_after_create(tilelayer, live_server, page): ) expect(option).to_have_text("Inherit") expect(page.get_by_label("Secret edit link:")).to_be_visible() + page.locator('select[name="share_status"]').select_option("1") + expect(page.get_by_role("button", name="Save draft", exact=True)).to_be_hidden() + expect(page.get_by_role("button", name="Save", exact=True)).to_be_visible() def test_alert_message_after_create( diff --git a/umap/tests/integration/test_owned_map.py b/umap/tests/integration/test_owned_map.py index 34222650..2e87dda0 100644 --- a/umap/tests/integration/test_owned_map.py +++ b/umap/tests/integration/test_owned_map.py @@ -61,8 +61,12 @@ def test_owner_permissions_form(map, datalayer, live_server, login): edit_permissions = page.get_by_title("Update permissions and editors") expect(edit_permissions).to_be_visible() edit_permissions.click() - select = page.locator(".umap-field-share_status select") - expect(select).to_be_visible() + expect(page.locator(".umap-field-share_status select")).to_be_visible() + options = [ + int(option.get_attribute("value")) + for option in page.locator(".umap-field-share_status select option").all() + ] + assert options == [Map.DRAFT, Map.PUBLIC, Map.OPEN, Map.PRIVATE] # expect(select).to_have_value(Map.PUBLIC) # Does not work owner_field = page.locator(".umap-field-owner") expect(owner_field).to_be_visible() @@ -181,29 +185,31 @@ def test_can_change_perms_after_create(tilelayer, live_server, login, user): page.get_by_title("Manage layers").click() page.get_by_title("Add a layer").click() page.locator("input[name=name]").fill("Layer 1") - save = page.get_by_role("button", name="Save") - expect(save).to_be_visible() + expect( + page.get_by_role("button", name="Visibility: Draft (private)") + ).to_be_visible() + expect(page.get_by_role("button", name="Save", exact=True)).to_be_hidden() with page.expect_response(re.compile(r".*/map/create/")): - save.click() + page.get_by_role("button", name="Save draft", exact=True).click() edit_permissions = page.get_by_title("Update permissions and editors") expect(edit_permissions).to_be_visible() edit_permissions.click() - select = page.locator(".umap-field-share_status select") - expect(select).to_be_visible() - option = page.locator("select[name='share_status'] option:checked") - expect(option).to_have_text("Everyone (public)") - owner_field = page.locator(".umap-field-owner") - expect(owner_field).to_be_visible() - editors_field = page.locator(".umap-field-editors input") - expect(editors_field).to_be_visible() - datalayer_label = page.get_by_text('Who can edit "Layer 1"') - expect(datalayer_label).to_be_visible() + expect(page.locator(".umap-field-share_status select")).to_be_visible() + expect(page.locator("select[name='share_status'] option:checked")).to_have_text( + "Draft (private)" + ) + expect(page.locator(".umap-field-owner")).to_be_visible() + expect(page.locator(".umap-field-editors input")).to_be_visible() + expect(page.get_by_text('Who can edit "Layer 1"')).to_be_visible() options = page.locator(".datalayer-permissions select[name='edit_status'] option") expect(options).to_have_count(4) option = page.locator( ".datalayer-permissions select[name='edit_status'] option:checked" ) expect(option).to_have_text("Inherit") + page.locator('select[name="share_status"]').select_option("1") + expect(page.get_by_role("button", name="Save draft", exact=True)).to_be_hidden() + expect(page.get_by_role("button", name="Save", exact=True)).to_be_visible() def test_can_change_owner(map, live_server, login, user): diff --git a/umap/tests/test_map.py b/umap/tests/test_map.py index 07af12be..d9c60dac 100644 --- a/umap/tests/test_map.py +++ b/umap/tests/test_map.py @@ -2,6 +2,7 @@ import pytest from django.contrib.auth.models import AnonymousUser from django.urls import reverse +from umap.forms import DEFAULT_CENTER from umap.models import Map from .base import MapFactory @@ -160,8 +161,9 @@ def test_can_change_default_edit_status(user, settings): def test_can_change_default_share_status(user, settings): + map = Map.objects.create(owner=user, center=DEFAULT_CENTER) + assert map.share_status == Map.DRAFT + settings.UMAP_DEFAULT_SHARE_STATUS = Map.PUBLIC + map = Map.objects.create(owner=user, center=DEFAULT_CENTER) map = MapFactory(owner=user) assert map.share_status == Map.PUBLIC - settings.UMAP_DEFAULT_SHARE_STATUS = Map.PRIVATE - map = MapFactory(owner=user) - assert map.share_status == Map.PRIVATE diff --git a/umap/tests/test_map_views.py b/umap/tests/test_map_views.py index 5f63d3ea..c1b0e7b4 100644 --- a/umap/tests/test_map_views.py +++ b/umap/tests/test_map_views.py @@ -42,7 +42,7 @@ def test_create(client, user, post_data): assert created_map.center.y == 48.94415123418794 assert j["permissions"] == { "edit_status": 3, - "share_status": 1, + "share_status": 0, "owner": {"id": user.pk, "name": "Joe", "url": "/en/user/Joe/"}, "editors": [], } @@ -241,42 +241,46 @@ def test_map_creation_should_allow_unicode_names(client, map, post_data): assert created_map.slug == "map" -def test_anonymous_can_access_map_with_share_status_public(client, map): +@pytest.mark.parametrize("share_status", [Map.PUBLIC, Map.OPEN]) +def test_anonymous_can_access_map_with_share_status_accessible( + client, map, share_status +): url = reverse("map", args=(map.slug, map.pk)) - map.share_status = map.PUBLIC + map.share_status = share_status map.save() response = client.get(url) assert response.status_code == 200 -def test_anonymous_can_access_map_with_share_status_open(client, map): +@pytest.mark.parametrize( + "share_status", [Map.PRIVATE, Map.DRAFT, Map.BLOCKED, Map.DELETED] +) +def test_anonymous_cannot_access_map_with_share_status_restricted( + client, map, share_status +): url = reverse("map", args=(map.slug, map.pk)) - map.share_status = map.OPEN - map.save() - response = client.get(url) - assert response.status_code == 200 - - -def test_anonymous_cannot_access_map_with_share_status_private(client, map): - url = reverse("map", args=(map.slug, map.pk)) - map.share_status = map.PRIVATE + map.share_status = share_status map.save() response = client.get(url) assert response.status_code == 403 -def test_owner_can_access_map_with_share_status_private(client, map): +@pytest.mark.parametrize("share_status", [Map.PRIVATE, Map.DRAFT]) +def test_owner_can_access_map_with_share_status_restricted(client, map, share_status): url = reverse("map", args=(map.slug, map.pk)) - map.share_status = map.PRIVATE + map.share_status = share_status map.save() client.login(username=map.owner.username, password="123123") response = client.get(url) assert response.status_code == 200 -def test_editors_can_access_map_with_share_status_private(client, map, user): +@pytest.mark.parametrize("share_status", [Map.PRIVATE, Map.DRAFT]) +def test_editors_can_access_map_with_share_status_resricted( + client, map, user, share_status +): url = reverse("map", args=(map.slug, map.pk)) - map.share_status = map.PRIVATE + map.share_status = share_status map.editors.add(user) map.save() client.login(username=user.username, password="123123") @@ -284,10 +288,11 @@ def test_editors_can_access_map_with_share_status_private(client, map, user): assert response.status_code == 200 -def test_anonymous_cannot_access_map_with_share_status_blocked(client, map): +def test_owner_cannot_access_map_with_share_status_deleted(client, map): url = reverse("map", args=(map.slug, map.pk)) - map.share_status = map.BLOCKED + map.share_status = map.DELETED map.save() + client.login(username=map.owner.username, password="123123") response = client.get(url) assert response.status_code == 403 @@ -408,7 +413,7 @@ def test_anonymous_delete(cookieclient, anonymap): @pytest.mark.usefixtures("allow_anonymous") -def test_no_cookie_cant_delete(client, anonymap): +def test_no_cookie_cannot_delete(client, anonymap): url = reverse("map_delete", args=(anonymap.pk,)) response = client.post( url, headers={"X-Requested-With": "XMLHttpRequest"}, follow=True @@ -416,6 +421,24 @@ def test_no_cookie_cant_delete(client, anonymap): assert response.status_code == 403 +@pytest.mark.usefixtures("allow_anonymous") +def test_no_cookie_cannot_view_anonymous_owned_map_in_draft(client, anonymap): + anonymap.share_status = Map.DRAFT + anonymap.save() + url = reverse("map", kwargs={"map_id": anonymap.pk, "slug": anonymap.slug}) + response = client.get(url) + assert response.status_code == 403 + + +@pytest.mark.usefixtures("allow_anonymous") +def test_owner_can_view_anonymous_owned_map_in_draft(cookieclient, anonymap): + anonymap.share_status = Map.DRAFT + anonymap.save() + url = reverse("map", kwargs={"map_id": anonymap.pk, "slug": anonymap.slug}) + response = cookieclient.get(url) + assert response.status_code == 200 + + @pytest.mark.usefixtures("allow_anonymous") def test_anonymous_edit_url(cookieclient, anonymap): url = anonymap.get_anonymous_edit_url() @@ -557,16 +580,6 @@ def test_create_readonly(client, user, post_data, settings): assert response.content == b"Site is readonly for maintenance" -def test_search(client, map): - # Very basic search, that do not deal with accent nor case. - # See install.md for how to have a smarter dict + index. - map.name = "Blé dur" - map.save() - url = reverse("search") - response = client.get(url + "?q=Blé") - assert "Blé dur" in response.content.decode() - - def test_authenticated_user_can_star_map(client, map, user): url = reverse("map_star", args=(map.pk,)) client.login(username=user.username, password="123123") @@ -748,7 +761,9 @@ def test_download_multiple_maps_editor(client, map, datalayer): assert f.infolist()[1].filename == f"umap_backup_test-map_{map.id}.umap" -@pytest.mark.parametrize("share_status", [Map.PRIVATE, Map.BLOCKED]) +@pytest.mark.parametrize( + "share_status", [Map.PRIVATE, Map.BLOCKED, Map.DRAFT, Map.DELETED] +) def test_download_shared_status_map(client, map, datalayer, share_status): map.share_status = share_status map.save() @@ -757,8 +772,9 @@ def test_download_shared_status_map(client, map, datalayer, share_status): assert response.status_code == 403 -def test_download_my_map(client, map, datalayer): - map.share_status = Map.PRIVATE +@pytest.mark.parametrize("share_status", [Map.PRIVATE, Map.DRAFT]) +def test_download_my_map(client, map, datalayer, share_status): + map.share_status = share_status map.save() client.login(username=map.owner.username, password="123123") url = reverse("map_download", args=(map.pk,)) @@ -769,7 +785,19 @@ def test_download_my_map(client, map, datalayer): assert j["type"] == "umap" -@pytest.mark.parametrize("share_status", [Map.PRIVATE, Map.BLOCKED, Map.OPEN]) +@pytest.mark.parametrize("share_status", [Map.BLOCKED, Map.DELETED]) +def test_download_my_map_blocked_or_deleted(client, map, datalayer, share_status): + map.share_status = share_status + map.save() + client.login(username=map.owner.username, password="123123") + url = reverse("map_download", args=(map.pk,)) + response = client.get(url) + assert response.status_code == 403 + + +@pytest.mark.parametrize( + "share_status", [Map.PRIVATE, Map.BLOCKED, Map.OPEN, Map.DRAFT] +) def test_oembed_shared_status_map(client, map, datalayer, share_status): map.share_status = share_status map.save() diff --git a/umap/tests/test_views.py b/umap/tests/test_views.py index c6a6dbc3..420fe16e 100644 --- a/umap/tests/test_views.py +++ b/umap/tests/test_views.py @@ -288,6 +288,28 @@ def test_user_dashboard_display_user_maps(client, map): assert "Owner only" in body +@pytest.mark.django_db +def test_user_dashboard_do_not_display_blocked_user_maps(client, map): + map.share_status = Map.BLOCKED + map.save() + client.login(username=map.owner.username, password="123123") + response = client.get(reverse("user_dashboard")) + assert response.status_code == 200 + body = response.content.decode() + assert map.name not in body + + +@pytest.mark.django_db +def test_user_dashboard_do_not_display_deleted_user_maps(client, map): + map.share_status = Map.DELETED + map.save() + client.login(username=map.owner.username, password="123123") + response = client.get(reverse("user_dashboard")) + assert response.status_code == 200 + body = response.content.decode() + assert map.name not in body + + @pytest.mark.django_db def test_user_dashboard_display_user_team_maps(client, map, team, user): user.teams.add(team) @@ -497,3 +519,34 @@ def test_websocket_token_is_generated_for_editors(client, user, user2, map): resp = client.get(token_url) token = resp.json().get("token") assert TimestampSigner().unsign_object(token, max_age=30) + + +@pytest.mark.django_db +def test_search(client, map): + # Very basic search, that do not deal with accent nor case. + # See install.md for how to have a smarter dict + index. + map.name = "Blé dur" + map.save() + url = reverse("search") + response = client.get(url + "?q=Blé") + assert "Blé dur" in response.content.decode() + + +@pytest.mark.django_db +def test_cannot_search_blocked_map(client, map): + map.name = "Blé dur" + map.share_status = Map.BLOCKED + map.save() + url = reverse("search") + response = client.get(url + "?q=Blé") + assert "Blé dur" not in response.content.decode() + + +@pytest.mark.django_db +def test_cannot_search_deleted_map(client, map): + map.name = "Blé dur" + map.share_status = Map.DELETED + map.save() + url = reverse("search") + response = client.get(url + "?q=Blé") + assert "Blé dur" not in response.content.decode() diff --git a/umap/views.py b/umap/views.py index e56d0200..fcc1db33 100644 --- a/umap/views.py +++ b/umap/views.py @@ -373,6 +373,7 @@ class UserDashboard(PaginatorMixin, DetailView, SearchMixin): def get_maps(self): qs = self.get_search_queryset() or Map.objects.all() + qs = qs.exclude(share_status__in=[Map.DELETED, Map.BLOCKED]) teams = self.object.teams.all() qs = ( qs.filter(owner=self.object) @@ -601,9 +602,6 @@ class MapDetailMixin(SessionMixin): "id": self.get_id(), "starred": self.is_starred(), "licences": dict((l.name, l.json) for l in Licence.objects.all()), - "share_statuses": [ - (i, str(label)) for i, label in Map.SHARE_STATUS if i != Map.BLOCKED - ], "umap_version": VERSION, "featuresHaveOwner": settings.UMAP_DEFAULT_FEATURES_HAVE_OWNERS, "websocketEnabled": settings.WEBSOCKET_ENABLED, @@ -613,15 +611,22 @@ class MapDetailMixin(SessionMixin): } created = bool(getattr(self, "object", None)) if (created and self.object.owner) or (not created and not user.is_anonymous): - map_statuses = Map.EDIT_STATUS + edit_statuses = Map.EDIT_STATUS datalayer_statuses = DataLayer.EDIT_STATUS + share_statuses = Map.SHARE_STATUS else: - map_statuses = AnonymousMapPermissionsForm.STATUS - datalayer_statuses = AnonymousDataLayerPermissionsForm.STATUS - properties["edit_statuses"] = [(i, str(label)) for i, label in map_statuses] + edit_statuses = Map.ANONYMOUS_EDIT_STATUS + datalayer_statuses = DataLayer.ANONYMOUS_EDIT_STATUS + share_statuses = Map.ANONYMOUS_SHARE_STATUS + properties["edit_statuses"] = [(i, str(label)) for i, label in edit_statuses] properties["datalayer_edit_statuses"] = [ (i, str(label)) for i, label in datalayer_statuses ] + properties["share_statuses"] = [ + (i, str(label)) + for i, label in share_statuses + if i not in [Map.BLOCKED, Map.DELETED] + ] if self.get_short_url(): properties["shortUrl"] = self.get_short_url() @@ -684,14 +689,9 @@ class PermissionsMixin: permissions["edit_status"] = self.object.edit_status permissions["share_status"] = self.object.share_status if self.object.owner: - permissions["owner"] = { - "id": self.object.owner.pk, - "name": str(self.object.owner), - "url": self.object.owner.get_url(), - } + permissions["owner"] = self.object.owner.get_metadata() permissions["editors"] = [ - {"id": editor.pk, "name": str(editor)} - for editor in self.object.editors.all() + editor.get_metadata() for editor in self.object.editors.all() ] if self.object.team: permissions["team"] = self.object.team.get_metadata() @@ -847,6 +847,17 @@ class MapViewGeoJSON(MapView): class MapNew(MapDetailMixin, TemplateView): template_name = "umap/map_detail.html" + def get_map_properties(self): + properties = super().get_map_properties() + properties["permissions"] = { + "edit_status": Map.edit_status.field.default(), + "share_status": Map.share_status.field.default(), + } + if self.request.user.is_authenticated: + user = self.request.user + properties["permissions"]["owner"] = user.get_metadata() + return properties + class MapPreview(MapDetailMixin, TemplateView): template_name = "umap/map_detail.html"