diff --git a/umap/static/umap/js/umap.js b/umap/static/umap/js/umap.js index 394a04b9..5f82b885 100644 --- a/umap/static/umap/js/umap.js +++ b/umap/static/umap/js/umap.js @@ -1074,6 +1074,11 @@ L.U.Map.include({ if (!this.options.umap_id) { duration = 100000; // we want a longer message at map creation (TODO UGLY) this.options.umap_id = data.id; + this.permissions.setOptions(data.permissions) + } else if (!this.permissions.isDirty) { + // Do not override local changes to permissions, + // but update in case some other editors changed them in the meantime. + this.permissions.setOptions(data.permissions) } // Update URL in case the name has changed. if (history && history.pushState) history.pushState({}, this.options.name, data.url); diff --git a/umap/static/umap/js/umap.permissions.js b/umap/static/umap/js/umap.permissions.js index 2242dd0d..d23dd1a8 100644 --- a/umap/static/umap/js/umap.permissions.js +++ b/umap/static/umap/js/umap.permissions.js @@ -10,7 +10,7 @@ L.U.MapPermissions = L.Class.extend({ }, initialize: function (map) { - this.options = map.options.permissions || {}; + this.setOptions(map.options.permissions); this.map = map; var isDirty = false, self = this; @@ -31,6 +31,10 @@ L.U.MapPermissions = L.Class.extend({ }, + setOptions: function (options) { + this.options = L.Util.setOptions(this, options); + }, + isOwner: function () { return this.map.options.user && this.options.owner && this.map.options.user.id == this.options.owner.id; }, @@ -49,8 +53,8 @@ L.U.MapPermissions = L.Class.extend({ fields = [], title = L.DomUtil.create('h4', '', container); if (this.isAnonymousMap()) { - if (this.map.options.anonymous_edit_url) { - var helpText = L._('Secret edit link is:
{link}', {link: this.map.options.anonymous_edit_url}); + if (this.options.anonymous_edit_url) { + var helpText = L._('Secret edit link is:
{link}', {link: this.options.anonymous_edit_url}); fields.push(['options.edit_status', {handler: 'IntSelect', label: L._('Who can edit'), selectOptions: this.map.options.anonymous_edit_statuses, helpText: helpText}]); } } else { diff --git a/umap/static/umap/test/Permissions.js b/umap/static/umap/test/Permissions.js index f214dcd9..7ead6bc7 100644 --- a/umap/static/umap/test/Permissions.js +++ b/umap/static/umap/test/Permissions.js @@ -33,7 +33,7 @@ describe('L.Permissions', function () { var button; it('should only allow edit_status', function () { - this.map.options.anonymous_edit_url = 'http://anonymous.url' + this.map.permissions.options.anonymous_edit_url = 'http://anonymous.url'; button = qs('a.update-map-permissions'); happen.click(button); expect(qs('select[name="edit_status"]')).to.be.ok; diff --git a/umap/tests/test_map_views.py b/umap/tests/test_map_views.py index b00b8c67..c14ee14d 100644 --- a/umap/tests/test_map_views.py +++ b/umap/tests/test_map_views.py @@ -35,6 +35,18 @@ def test_create(client, user, post_data): assert created_map.name == name assert created_map.center.x == 13.447265624999998 assert created_map.center.y == 48.94415123418794 + assert j['permissions'] == { + 'edit_status': 3, + 'share_status': 1, + 'owner': { + 'id': user.pk, + 'name': 'Joe', + 'url': '/en/user/Joe/' + }, + 'editors': [], + 'anonymous_edit_url': ('http://umap.org' + + created_map.get_anonymous_edit_url()) + } def test_map_create_permissions(client, settings): @@ -315,6 +327,8 @@ def test_anonymous_create(cookieclient, post_data): j = json.loads(response.content.decode()) created_map = Map.objects.latest('pk') assert j['id'] == created_map.pk + assert (created_map.get_anonymous_edit_url() + in j['permissions']['anonymous_edit_url']) assert created_map.name == name key, value = created_map.signed_cookie_elements assert key in cookieclient.cookies diff --git a/umap/views.py b/umap/views.py index 35688583..4ff93a1b 100644 --- a/umap/views.py +++ b/umap/views.py @@ -382,6 +382,14 @@ class MapDetailMixin: locale = to_locale(locale) properties['locale'] = locale context['locale'] = locale + user = self.request.user + if not user.is_anonymous: + properties['user'] = { + 'id': user.pk, + 'name': user.get_username(), + 'url': reverse(settings.USER_MAPS_URL, + args=(user.get_username(), )) + } map_settings = self.get_geojson() if "properties" not in map_settings: map_settings['properties'] = {} @@ -416,7 +424,34 @@ class MapDetailMixin: return None -class MapView(MapDetailMixin, DetailView): +class PermissionsMixin: + + def get_permissions(self): + permissions = {} + 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': self.object.owner.get_username(), + 'url': reverse(settings.USER_MAPS_URL, + args=(self.object.owner.get_username(), )) + } + permissions['editors'] = [{ + 'id': editor.pk, + 'name': editor.get_username(), + } for editor in self.object.editors.all()] + if (not self.object.owner + and self.object.is_anonymous_owner(self.request)): + permissions['anonymous_edit_url'] = self.get_anonymous_edit_url() + return permissions + + def get_anonymous_edit_url(self): + anonymous_url = self.object.get_anonymous_edit_url() + return f'{settings.SITE_URL}{anonymous_url}' + + +class MapView(MapDetailMixin, PermissionsMixin, DetailView): def get(self, request, *args, **kwargs): self.object = self.get_object() @@ -455,36 +490,7 @@ class MapView(MapDetailMixin, DetailView): if "properties" not in map_settings: map_settings['properties'] = {} map_settings['properties']['name'] = self.object.name - permissions = {} - 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': self.object.owner.get_username(), - 'url': reverse(settings.USER_MAPS_URL, - args=(self.object.owner.get_username(), )) - } - permissions['editors'] = [{ - 'id': editor.pk, - 'name': editor.get_username(), - } for editor in self.object.editors.all()] - map_settings['properties']['permissions'] = permissions - user = self.request.user - if not user.is_anonymous: - map_settings['properties']['user'] = { - 'id': user.pk, - 'name': user.get_username(), - 'url': reverse(settings.USER_MAPS_URL, - args=(user.get_username(), )) - } - if (not self.object.owner - and self.object.is_anonymous_owner(self.request)): - anonymous_url = "%s%s" % ( - settings.SITE_URL, - self.object.get_anonymous_edit_url() - ) - map_settings['properties']['anonymous_edit_url'] = anonymous_url + map_settings['properties']['permissions'] = self.get_permissions() return map_settings @@ -502,7 +508,7 @@ class MapNew(MapDetailMixin, TemplateView): template_name = "umap/map_detail.html" -class MapCreate(FormLessEditMixin, CreateView): +class MapCreate(FormLessEditMixin, PermissionsMixin, CreateView): model = Map form_class = MapSettingsForm @@ -510,11 +516,8 @@ class MapCreate(FormLessEditMixin, CreateView): if self.request.user.is_authenticated: form.instance.owner = self.request.user self.object = form.save() + anonymous_url = self.get_anonymous_edit_url() if not self.request.user.is_authenticated: - anonymous_url = "%s%s" % ( - settings.SITE_URL, - self.object.get_anonymous_edit_url() - ) msg = _( "Your map has been created! If you want to edit this map from " "another computer, please use this link: %(anonymous_url)s" @@ -522,9 +525,13 @@ class MapCreate(FormLessEditMixin, CreateView): ) else: msg = _("Congratulations, your map has been created!") + permissions = self.get_permissions() + # User does not have the cookie yet. + permissions['anonymous_edit_url'] = anonymous_url response = simple_json_response( id=self.object.pk, url=self.object.get_absolute_url(), + permissions=permissions, info=msg ) if not self.request.user.is_authenticated: @@ -537,7 +544,7 @@ class MapCreate(FormLessEditMixin, CreateView): return response -class MapUpdate(FormLessEditMixin, UpdateView): +class MapUpdate(FormLessEditMixin, PermissionsMixin, UpdateView): model = Map form_class = MapSettingsForm pk_url_kwarg = 'map_id' @@ -548,7 +555,8 @@ class MapUpdate(FormLessEditMixin, UpdateView): return simple_json_response( id=self.object.pk, url=self.object.get_absolute_url(), - info=_("Map has been updated!") + permissions=self.get_permissions(), + info=_("Map has been updated!"), ) @@ -607,7 +615,7 @@ class MapDelete(DeleteView): return simple_json_response(redirect="/") -class MapClone(View): +class MapClone(PermissionsMixin, View): def post(self, *args, **kwargs): if not getattr(settings, "UMAP_ALLOW_ANONYMOUS", False) \ @@ -623,14 +631,10 @@ class MapClone(View): value=value, max_age=ANONYMOUS_COOKIE_MAX_AGE ) - anonymous_url = "%s%s" % ( - settings.SITE_URL, - self.object.get_anonymous_edit_url() - ) msg = _( "Your map has been cloned! If you want to edit this map from " "another computer, please use this link: %(anonymous_url)s" - % {"anonymous_url": anonymous_url} + % {"anonymous_url": self.get_anonymous_edit_url()} ) else: msg = _("Congratulations, your map has been cloned!")