mirror of
https://github.com/umap-project/umap.git
synced 2025-05-05 22:11:50 +02:00
parent
87814f0362
commit
6e9e46dbbd
14 changed files with 174 additions and 154 deletions
|
@ -33,6 +33,7 @@ classifiers = [
|
|||
]
|
||||
dependencies = [
|
||||
"Django>=4.1",
|
||||
"djangorestframework==3.14.0",
|
||||
"django-agnocomplete==2.2.0",
|
||||
"django-compressor==4.3.1",
|
||||
"django-environ==0.10.0",
|
||||
|
|
59
umap/api_views.py
Normal file
59
umap/api_views.py
Normal file
|
@ -0,0 +1,59 @@
|
|||
from rest_framework import generics, status
|
||||
from rest_framework.response import Response
|
||||
|
||||
from .models import Map
|
||||
from .serializers import MapSerializer
|
||||
from .views import ANONYMOUS_COOKIE_MAX_AGE
|
||||
|
||||
|
||||
class MapList(generics.ListCreateAPIView):
|
||||
queryset = Map.public.all().order_by("-modified_at")
|
||||
serializer_class = MapSerializer
|
||||
|
||||
def perform_create(self, serializer):
|
||||
if self.request.user.is_authenticated:
|
||||
serializer.save(owner=self.request.user)
|
||||
else:
|
||||
serializer.save()
|
||||
|
||||
def get_map_permissions(self, map_):
|
||||
permissions = {}
|
||||
permissions["edit_status"] = map_.edit_status
|
||||
permissions["share_status"] = map_.share_status
|
||||
if map_.owner:
|
||||
permissions["owner"] = {
|
||||
"id": map_.owner.pk,
|
||||
"name": str(map_.owner),
|
||||
"url": map_.owner.get_url(),
|
||||
}
|
||||
permissions["editors"] = [
|
||||
{"id": editor.pk, "name": str(editor)} for editor in map_.editors.all()
|
||||
]
|
||||
if not map_.owner and map_.is_anonymous_owner(self.request):
|
||||
permissions["anonymous_edit_url"] = map_.get_anonymous_edit_url()
|
||||
return permissions
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
self.perform_create(serializer)
|
||||
map_ = serializer.instance
|
||||
headers = self.get_success_headers(serializer.data)
|
||||
data = serializer.data
|
||||
permissions = self.get_map_permissions(map_)
|
||||
if not map_.owner:
|
||||
anonymous_url = map_.get_anonymous_edit_url()
|
||||
permissions["anonymous_edit_url"] = anonymous_url
|
||||
data["permissions"] = permissions
|
||||
response = Response(data, status=status.HTTP_201_CREATED, headers=headers)
|
||||
if not self.request.user.is_authenticated:
|
||||
key, value = map_.signed_cookie_elements
|
||||
response.set_signed_cookie(
|
||||
key=key, value=value, max_age=ANONYMOUS_COOKIE_MAX_AGE
|
||||
)
|
||||
return response
|
||||
|
||||
|
||||
class MapDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||
queryset = Map.public.all().order_by("-modified_at")
|
||||
serializer_class = MapSerializer
|
|
@ -33,7 +33,7 @@ def can_edit_map(view_func):
|
|||
|
||||
@wraps(view_func)
|
||||
def wrapper(request, *args, **kwargs):
|
||||
map_inst = get_object_or_404(Map, pk=kwargs["map_id"])
|
||||
map_inst = get_object_or_404(Map, pk=kwargs.get("map_id", kwargs.get("pk")))
|
||||
user = request.user
|
||||
kwargs["map_inst"] = map_inst # Avoid rerequesting the map in the view
|
||||
if map_inst.edit_status >= map_inst.EDITORS:
|
||||
|
@ -54,7 +54,7 @@ def can_view_map(view_func):
|
|||
|
||||
@wraps(view_func)
|
||||
def wrapper(request, *args, **kwargs):
|
||||
map_inst = get_object_or_404(Map, pk=kwargs["map_id"])
|
||||
map_inst = get_object_or_404(Map, pk=kwargs.get("map_id", kwargs.get("pk")))
|
||||
kwargs["map_inst"] = map_inst # Avoid rerequesting the map in the view
|
||||
if not map_inst.can_view(request):
|
||||
return HttpResponseForbidden()
|
||||
|
|
|
@ -2,7 +2,6 @@ from django import forms
|
|||
from django.contrib.gis.geos import Point
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.template.defaultfilters import slugify
|
||||
from django.conf import settings
|
||||
from django.forms.utils import ErrorList
|
||||
|
||||
|
@ -78,34 +77,6 @@ class AnonymousDataLayerPermissionsForm(forms.ModelForm):
|
|||
fields = ("edit_status",)
|
||||
|
||||
|
||||
class MapSettingsForm(forms.ModelForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(MapSettingsForm, self).__init__(*args, **kwargs)
|
||||
self.fields["slug"].required = False
|
||||
self.fields["center"].widget.map_srid = 4326
|
||||
|
||||
def clean_slug(self):
|
||||
slug = self.cleaned_data.get("slug", None)
|
||||
name = self.cleaned_data.get("name", None)
|
||||
if not slug and name:
|
||||
# If name is empty, don't do nothing, validation will raise
|
||||
# later on the process because name is required
|
||||
self.cleaned_data["slug"] = slugify(name) or "map"
|
||||
return self.cleaned_data["slug"][:50]
|
||||
else:
|
||||
return ""
|
||||
|
||||
def clean_center(self):
|
||||
if not self.cleaned_data["center"]:
|
||||
point = DEFAULT_CENTER
|
||||
self.cleaned_data["center"] = point
|
||||
return self.cleaned_data["center"]
|
||||
|
||||
class Meta:
|
||||
fields = ("settings", "name", "center", "slug")
|
||||
model = Map
|
||||
|
||||
|
||||
class UserProfileForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = User
|
||||
|
|
32
umap/serializers.py
Normal file
32
umap/serializers.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
from django.contrib.gis.geos import Point
|
||||
from django.template.defaultfilters import slugify
|
||||
from django.conf import settings
|
||||
from rest_framework import serializers
|
||||
|
||||
from .models import Map
|
||||
|
||||
DEFAULT_LATITUDE = (
|
||||
settings.LEAFLET_LATITUDE if hasattr(settings, "LEAFLET_LATITUDE") else 51
|
||||
)
|
||||
DEFAULT_LONGITUDE = (
|
||||
settings.LEAFLET_LONGITUDE if hasattr(settings, "LEAFLET_LONGITUDE") else 2
|
||||
)
|
||||
DEFAULT_CENTER = Point(DEFAULT_LONGITUDE, DEFAULT_LATITUDE)
|
||||
|
||||
|
||||
class MapSerializer(serializers.HyperlinkedModelSerializer):
|
||||
slug = serializers.CharField(required=False)
|
||||
|
||||
class Meta:
|
||||
model = Map
|
||||
fields = ["id", "name", "slug", "center", "settings"]
|
||||
|
||||
def validate(self, data):
|
||||
slug = data.get("slug")
|
||||
name = data.get("name")
|
||||
if not slug and name:
|
||||
data["slug"] = slugify(name)[:50] or "map"
|
||||
return data
|
||||
|
||||
def validate_center(self, value):
|
||||
return value or DEFAULT_CENTER
|
|
@ -122,6 +122,7 @@ INSTALLED_APPS = (
|
|||
"umap",
|
||||
"compressor",
|
||||
"social_django",
|
||||
"rest_framework",
|
||||
# See https://github.com/peopledoc/django-agnocomplete/commit/26eda2dfa4a2f8a805ca2ea19a0c504b9d773a1c
|
||||
# Django does not find the app config in the default place, so the app is not loaded
|
||||
# so the "autodiscover" is not run.
|
||||
|
@ -281,6 +282,11 @@ if SOCIAL_AUTH_OPENSTREETMAP_KEY and SOCIAL_AUTH_OPENSTREETMAP_SECRET:
|
|||
)
|
||||
|
||||
AUTHENTICATION_BACKENDS += ("django.contrib.auth.backends.ModelBackend",)
|
||||
REST_FRAMEWORK = {
|
||||
# Use Django's standard `django.contrib.auth` permissions,
|
||||
# or allow read-only access for unauthenticated users.
|
||||
"DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.AllowAny"]
|
||||
}
|
||||
|
||||
LOGGING = {
|
||||
"version": 1,
|
||||
|
|
|
@ -1102,7 +1102,8 @@ L.U.Map.include({
|
|||
formData.append('name', this.options.name)
|
||||
formData.append('center', JSON.stringify(this.geometry()))
|
||||
formData.append('settings', JSON.stringify(geojson))
|
||||
this.post(this.getSaveUrl(), {
|
||||
const method = this.options.umap_id ? this.put.bind(this) : this.post.bind(this)
|
||||
method(this.getSaveUrl(), {
|
||||
data: formData,
|
||||
context: this,
|
||||
callback: function (data) {
|
||||
|
@ -1192,13 +1193,13 @@ L.U.Map.include({
|
|||
},
|
||||
|
||||
getEditUrl: function () {
|
||||
return L.Util.template(this.options.urls.map_update, {
|
||||
map_id: this.options.umap_id,
|
||||
return L.Util.template(this.options.urls.map_detail, {
|
||||
pk: this.options.umap_id,
|
||||
})
|
||||
},
|
||||
|
||||
getCreateUrl: function () {
|
||||
return L.Util.template(this.options.urls.map_create)
|
||||
return L.Util.template(this.options.urls.map_list)
|
||||
},
|
||||
|
||||
getSaveUrl: function () {
|
||||
|
@ -1855,6 +1856,12 @@ L.U.Map.include({
|
|||
this.xhr.post(url, options)
|
||||
},
|
||||
|
||||
put: function (url, options) {
|
||||
options = options || {}
|
||||
options.listener = this
|
||||
this.xhr.put(url, options)
|
||||
},
|
||||
|
||||
get: function (url, options) {
|
||||
options = options || {}
|
||||
options.listener = this
|
||||
|
|
|
@ -60,7 +60,7 @@ L.U.Xhr = L.Evented.extend({
|
|||
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
if (xhr.status == 200) {
|
||||
if (xhr.status == 200 || xhr.status == 201) {
|
||||
settings.callback.call(settings.context || xhr, xhr.responseText, xhr)
|
||||
} else if (xhr.status === 403) {
|
||||
self.ui.alert({
|
||||
|
@ -130,7 +130,7 @@ L.U.Xhr = L.Evented.extend({
|
|||
}
|
||||
const settings = L.Util.extend({}, default_options, options)
|
||||
|
||||
if (verb === 'POST') {
|
||||
if (verb === 'POST' || verb === 'PUT') {
|
||||
// find a way not to make this django specific
|
||||
const token = document.cookie.replace(
|
||||
/(?:(?:^|.*;\s*)csrftoken\s*\=\s*([^;]*).*$)|^.*$/,
|
||||
|
@ -186,6 +186,10 @@ L.U.Xhr = L.Evented.extend({
|
|||
this._json('POST', uri, options)
|
||||
},
|
||||
|
||||
put: function (uri, options) {
|
||||
this._json('PUT', uri, options)
|
||||
},
|
||||
|
||||
submit_form: function (form_id, options) {
|
||||
if (typeof options === 'undefined') options = {}
|
||||
const form = L.DomUtil.get(form_id)
|
||||
|
|
|
@ -76,11 +76,7 @@ describe('L.U.DataLayer', function () {
|
|||
it('should call datalayer.save on save button click', function (done) {
|
||||
sinon.spy(this.datalayer, 'save')
|
||||
this.server.flush()
|
||||
this.server.respondWith(
|
||||
'POST',
|
||||
'/map/99/update/settings/',
|
||||
JSON.stringify({ id: 99 })
|
||||
)
|
||||
this.server.respondWith('PUT', '/map/99/', JSON.stringify({ id: 99 }))
|
||||
this.server.respondWith(
|
||||
'POST',
|
||||
'/map/99/datalayer/update/62/',
|
||||
|
@ -97,11 +93,7 @@ describe('L.U.DataLayer', function () {
|
|||
it('should show alert if server respond 412', function () {
|
||||
cleanAlert()
|
||||
this.server.flush()
|
||||
this.server.respondWith(
|
||||
'POST',
|
||||
'/map/99/update/settings/',
|
||||
JSON.stringify({ id: 99 })
|
||||
)
|
||||
this.server.respondWith('PUT', '/map/99/', JSON.stringify({ id: 99 }))
|
||||
this.server.respondWith('POST', '/map/99/datalayer/update/62/', [412, {}, ''])
|
||||
happen.click(editButton)
|
||||
input = qs('form.umap-form input[name="name"]')
|
||||
|
@ -178,11 +170,7 @@ describe('L.U.DataLayer', function () {
|
|||
it('should set umap_id on save callback', function () {
|
||||
assert.notOk(newDatalayer.umap_id)
|
||||
this.server.flush()
|
||||
this.server.respondWith(
|
||||
'POST',
|
||||
'/map/99/update/settings/',
|
||||
JSON.stringify({ id: 99 })
|
||||
)
|
||||
this.server.respondWith('PUT', '/map/99/', JSON.stringify({ id: 99 }))
|
||||
this.server.respondWith(
|
||||
'POST',
|
||||
'/map/99/datalayer/create/',
|
||||
|
@ -219,11 +207,7 @@ describe('L.U.DataLayer', function () {
|
|||
}
|
||||
var spy = sinon.spy(response)
|
||||
this.server.flush()
|
||||
this.server.respondWith(
|
||||
'POST',
|
||||
'/map/99/update/settings/',
|
||||
JSON.stringify({ id: 99 })
|
||||
)
|
||||
this.server.respondWith('PUT', '/map/99/', JSON.stringify({ id: 99 }))
|
||||
this.server.respondWith('POST', '/map/99/datalayer/update/63/', spy)
|
||||
clickSave()
|
||||
this.server.respond()
|
||||
|
@ -404,8 +388,7 @@ describe('L.U.DataLayer', function () {
|
|||
})
|
||||
})
|
||||
|
||||
describe("#displayOnLoad", function () {
|
||||
|
||||
describe('#displayOnLoad', function () {
|
||||
beforeEach(function () {
|
||||
this.server.respondWith(
|
||||
/\/datalayer\/64\/\?.*/,
|
||||
|
@ -415,27 +398,26 @@ describe('L.U.DataLayer', function () {
|
|||
// Force fetching the data, so to deal here with fake server
|
||||
this.datalayer.fetchData()
|
||||
this.server.respond()
|
||||
this.map.setZoom(10, {animate: false})
|
||||
});
|
||||
this.map.setZoom(10, { animate: false })
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
this.datalayer._delete()
|
||||
})
|
||||
|
||||
it("should not display layer at load", function () {
|
||||
it('should not display layer at load', function () {
|
||||
assert.notOk(qs('path[fill="AliceBlue"]'))
|
||||
})
|
||||
|
||||
it("should display on click", function () {
|
||||
it('should display on click', function () {
|
||||
happen.click(qs(`[data-id='${L.stamp(this.datalayer)}'] .layer-toggle`))
|
||||
assert.ok(qs('path[fill="AliceBlue"]'))
|
||||
})
|
||||
|
||||
it("should not display on zoom", function () {
|
||||
this.map.setZoom(9, {animate: false})
|
||||
it('should not display on zoom', function () {
|
||||
this.map.setZoom(9, { animate: false })
|
||||
assert.notOk(qs('path[fill="AliceBlue"]'))
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
describe('#facet-search()', function () {
|
||||
|
@ -474,22 +456,22 @@ describe('L.U.DataLayer', function () {
|
|||
})
|
||||
describe('#zoomEnd', function () {
|
||||
it('should honour the fromZoom option', function () {
|
||||
this.map.setZoom(6, {animate: false})
|
||||
this.map.setZoom(6, { animate: false })
|
||||
assert.ok(qs('path[fill="none"]'))
|
||||
this.datalayer.options.fromZoom = 6
|
||||
this.map.setZoom(5, {animate: false})
|
||||
this.map.setZoom(5, { animate: false })
|
||||
assert.notOk(qs('path[fill="none"]'))
|
||||
this.map.setZoom(6, {animate: false})
|
||||
this.map.setZoom(6, { animate: false })
|
||||
assert.ok(qs('path[fill="none"]'))
|
||||
})
|
||||
|
||||
it('should honour the toZoom option', function () {
|
||||
this.map.setZoom(6, {animate: false})
|
||||
this.map.setZoom(6, { animate: false })
|
||||
assert.ok(qs('path[fill="none"]'))
|
||||
this.datalayer.options.toZoom = 6
|
||||
this.map.setZoom(7, {animate: false})
|
||||
this.map.setZoom(7, { animate: false })
|
||||
assert.notOk(qs('path[fill="none"]'))
|
||||
this.map.setZoom(6, {animate: false})
|
||||
this.map.setZoom(6, { animate: false })
|
||||
assert.ok(qs('path[fill="none"]'))
|
||||
})
|
||||
})
|
||||
|
|
|
@ -114,7 +114,8 @@ function initMap(options) {
|
|||
urls: {
|
||||
map: '/map/{slug}_{pk}',
|
||||
datalayer_view: '/datalayer/{pk}/',
|
||||
map_update: '/map/{map_id}/update/settings/',
|
||||
map_list: '/api/maps/',
|
||||
map_detail: '/api/maps/{map_id}/',
|
||||
map_old_url: '/map/{username}/{slug}/',
|
||||
map_clone: '/map/{map_id}/update/clone/',
|
||||
map_short_url: '/m/{pk}/',
|
||||
|
@ -122,7 +123,6 @@ function initMap(options) {
|
|||
map_new: '/map/new/',
|
||||
datalayer_update: '/map/{map_id}/datalayer/update/{pk}/',
|
||||
map_delete: '/map/{map_id}/update/delete/',
|
||||
map_create: '/map/create/',
|
||||
logout: '/logout/',
|
||||
datalayer_create: '/map/{map_id}/datalayer/create/',
|
||||
login_popup_end: '/login/popupd/',
|
||||
|
|
|
@ -50,11 +50,13 @@ def test_editors_can_edit_if_status_editors(map, user):
|
|||
assert map.can_edit(user)
|
||||
|
||||
|
||||
def test_logged_in_user_should_be_allowed_for_anonymous_map_with_anonymous_edit_status(map, user, rf): # noqa
|
||||
def test_logged_in_user_should_be_allowed_for_anonymous_map_with_anonymous_edit_status(
|
||||
map, user, rf
|
||||
): # noqa
|
||||
map.owner = None
|
||||
map.edit_status = map.ANONYMOUS
|
||||
map.save()
|
||||
url = reverse('map_update', kwargs={'map_id': map.pk})
|
||||
url = reverse("map_detail", kwargs={"pk": map.pk})
|
||||
request = rf.get(url)
|
||||
request.user = user
|
||||
assert map.can_edit(user, request)
|
||||
|
@ -70,7 +72,7 @@ def test_anonymous_user_should_not_be_allowed_for_anonymous_map(map, user, rf):
|
|||
def test_clone_should_return_new_instance(map, user):
|
||||
clone = map.clone()
|
||||
assert map.pk != clone.pk
|
||||
assert u"Clone of " + map.name == clone.name
|
||||
assert "Clone of " + map.name == clone.name
|
||||
assert map.settings == clone.settings
|
||||
assert map.center == clone.center
|
||||
assert map.zoom == clone.zoom
|
||||
|
@ -108,8 +110,7 @@ def test_clone_should_clone_datalayers_and_features_too(map, user, datalayer):
|
|||
def test_publicmanager_should_get_only_public_maps(map, user, licence):
|
||||
map.share_status = map.PUBLIC
|
||||
open_map = MapFactory(owner=user, licence=licence, share_status=Map.OPEN)
|
||||
private_map = MapFactory(owner=user, licence=licence,
|
||||
share_status=Map.PRIVATE)
|
||||
private_map = MapFactory(owner=user, licence=licence, share_status=Map.PRIVATE)
|
||||
assert map in Map.public.all()
|
||||
assert open_map not in Map.public.all()
|
||||
assert private_map not in Map.public.all()
|
||||
|
|
|
@ -24,13 +24,13 @@ def post_data():
|
|||
|
||||
|
||||
def test_create(client, user, post_data):
|
||||
url = reverse("map_create")
|
||||
# POST only mendatory fields
|
||||
url = reverse("map_list")
|
||||
# POST only mandatory fields
|
||||
name = "test-map-with-new-name"
|
||||
post_data["name"] = name
|
||||
client.login(username=user.username, password="123123")
|
||||
response = client.post(url, post_data)
|
||||
assert response.status_code == 200
|
||||
assert response.status_code == 201
|
||||
j = json.loads(response.content.decode())
|
||||
created_map = Map.objects.latest("pk")
|
||||
assert j["id"] == created_map.pk
|
||||
|
@ -45,21 +45,22 @@ def test_create(client, user, post_data):
|
|||
}
|
||||
|
||||
|
||||
def test_map_create_permissions(client, settings):
|
||||
def test_map_list_permissions(client, settings):
|
||||
settings.UMAP_ALLOW_ANONYMOUS = False
|
||||
url = reverse("map_create")
|
||||
url = reverse("map_list")
|
||||
# POST anonymous
|
||||
response = client.post(url, {})
|
||||
assert response.status_code == 200
|
||||
assert login_required(response)
|
||||
|
||||
|
||||
def test_map_update_access(client, map, user):
|
||||
url = reverse("map_update", kwargs={"map_id": map.pk})
|
||||
url = reverse("map_detail", kwargs={"pk": map.pk})
|
||||
# GET anonymous
|
||||
response = client.get(url)
|
||||
assert login_required(response)
|
||||
# POST anonymous
|
||||
response = client.post(url, {})
|
||||
response = client.put(url, {}, content_type="application/json")
|
||||
assert login_required(response)
|
||||
# GET with wrong permissions
|
||||
client.login(username=user.username, password="123123")
|
||||
|
@ -67,7 +68,7 @@ def test_map_update_access(client, map, user):
|
|||
assert response.status_code == 403
|
||||
# POST with wrong permissions
|
||||
client.login(username=user.username, password="123123")
|
||||
response = client.post(url, {})
|
||||
response = client.put(url, {}, content_type="application/json")
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
|
@ -90,12 +91,12 @@ def test_map_update_permissions_access(client, map, user):
|
|||
|
||||
|
||||
def test_update(client, map, post_data):
|
||||
url = reverse("map_update", kwargs={"map_id": map.pk})
|
||||
# POST only mendatory fields
|
||||
url = reverse("map_detail", kwargs={"pk": map.pk})
|
||||
# PUT only mandatory fields
|
||||
name = "new map name"
|
||||
post_data["name"] = name
|
||||
client.login(username=map.owner.username, password="123123")
|
||||
response = client.post(url, post_data)
|
||||
response = client.put(url, post_data, content_type="application/json")
|
||||
assert response.status_code == 200
|
||||
j = json.loads(response.content.decode())
|
||||
assert "html" not in j
|
||||
|
@ -198,13 +199,13 @@ def test_clone_should_set_cloner_as_owner(client, map, user):
|
|||
|
||||
|
||||
def test_map_creation_should_allow_unicode_names(client, map, post_data):
|
||||
url = reverse("map_create")
|
||||
# POST only mendatory fields
|
||||
url = reverse("map_list")
|
||||
# POST only mandatory fields
|
||||
name = "Академический"
|
||||
post_data["name"] = name
|
||||
client.login(username=map.owner.username, password="123123")
|
||||
response = client.post(url, post_data)
|
||||
assert response.status_code == 200
|
||||
assert response.status_code == 201
|
||||
j = json.loads(response.content.decode())
|
||||
created_map = Map.objects.latest("pk")
|
||||
assert j["id"] == created_map.pk
|
||||
|
@ -317,25 +318,25 @@ def test_logged_in_user_can_edit_map_editable_by_anonymous(client, map, user):
|
|||
map.edit_status = map.ANONYMOUS
|
||||
map.save()
|
||||
client.login(username=user.username, password="123123")
|
||||
url = reverse("map_update", kwargs={"map_id": map.pk})
|
||||
url = reverse("map_detail", kwargs={"pk": map.pk})
|
||||
new_name = "this is my new name"
|
||||
data = {
|
||||
"center": '{"type":"Point","coordinates":[13.447265624999998,48.94415123418794]}', # noqa
|
||||
"name": new_name,
|
||||
}
|
||||
response = client.post(url, data)
|
||||
response = client.put(url, data, content_type="application/json")
|
||||
assert response.status_code == 200
|
||||
assert Map.objects.get(pk=map.pk).name == new_name
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("allow_anonymous")
|
||||
def test_anonymous_create(cookieclient, post_data):
|
||||
url = reverse("map_create")
|
||||
# POST only mendatory fields
|
||||
url = reverse("map_list")
|
||||
# POST only mandatory fields
|
||||
name = "test-map-with-new-name"
|
||||
post_data["name"] = name
|
||||
response = cookieclient.post(url, post_data)
|
||||
assert response.status_code == 200
|
||||
assert response.status_code == 201
|
||||
j = json.loads(response.content.decode())
|
||||
created_map = Map.objects.latest("pk")
|
||||
assert j["id"] == created_map.pk
|
||||
|
@ -349,8 +350,8 @@ def test_anonymous_create(cookieclient, post_data):
|
|||
|
||||
@pytest.mark.usefixtures("allow_anonymous")
|
||||
def test_anonymous_update_without_cookie_fails(client, anonymap, post_data): # noqa
|
||||
url = reverse("map_update", kwargs={"map_id": anonymap.pk})
|
||||
response = client.post(url, post_data)
|
||||
url = reverse("map_detail", kwargs={"pk": anonymap.pk})
|
||||
response = client.put(url, post_data, content_type="application/json")
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
|
@ -358,11 +359,11 @@ def test_anonymous_update_without_cookie_fails(client, anonymap, post_data): #
|
|||
def test_anonymous_update_with_cookie_should_work(
|
||||
cookieclient, anonymap, post_data
|
||||
): # noqa
|
||||
url = reverse("map_update", kwargs={"map_id": anonymap.pk})
|
||||
# POST only mendatory fields
|
||||
url = reverse("map_detail", kwargs={"pk": anonymap.pk})
|
||||
# POST only mandatory fields
|
||||
name = "new map name"
|
||||
post_data["name"] = name
|
||||
response = cookieclient.post(url, post_data)
|
||||
response = cookieclient.put(url, post_data, content_type="application/json")
|
||||
assert response.status_code == 200
|
||||
j = json.loads(response.content.decode())
|
||||
updated_map = Map.objects.get(pk=anonymap.pk)
|
||||
|
@ -522,7 +523,7 @@ def test_map_attach_owner_anonymous_not_allowed(cookieclient, anonymap, user):
|
|||
|
||||
def test_create_readonly(client, user, post_data, settings):
|
||||
settings.UMAP_READONLY = True
|
||||
url = reverse("map_create")
|
||||
url = reverse("map_list")
|
||||
client.login(username=user.username, password="123123")
|
||||
response = client.post(url, post_data)
|
||||
assert response.status_code == 403
|
||||
|
|
|
@ -9,6 +9,7 @@ from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
|||
from django.views.decorators.cache import cache_control, cache_page, never_cache
|
||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||
|
||||
from . import api_views
|
||||
from . import views
|
||||
from .decorators import (
|
||||
jsonize_view,
|
||||
|
@ -93,7 +94,7 @@ i18n_urls += decorated_patterns(
|
|||
)
|
||||
i18n_urls += decorated_patterns(
|
||||
[login_required_if_not_anonymous_allowed, never_cache],
|
||||
re_path(r"^map/create/$", views.MapCreate.as_view(), name="map_create"),
|
||||
path("api/maps/", api_views.MapList.as_view(), name="map_list"),
|
||||
)
|
||||
i18n_urls += decorated_patterns(
|
||||
[login_required],
|
||||
|
@ -115,9 +116,9 @@ i18n_urls += decorated_patterns(
|
|||
)
|
||||
map_urls = [
|
||||
re_path(
|
||||
r"^map/(?P<map_id>[\d]+)/update/settings/$",
|
||||
views.MapUpdate.as_view(),
|
||||
name="map_update",
|
||||
r"^api/map/(?P<pk>[\d]+)/$",
|
||||
api_views.MapDetail.as_view(),
|
||||
name="map_detail",
|
||||
),
|
||||
re_path(
|
||||
r"^map/(?P<map_id>[\d]+)/update/permissions/$",
|
||||
|
|
|
@ -50,7 +50,6 @@ from .forms import (
|
|||
AnonymousDataLayerPermissionsForm,
|
||||
AnonymousMapPermissionsForm,
|
||||
FlatErrorList,
|
||||
MapSettingsForm,
|
||||
SendLinkForm,
|
||||
UpdateMapPermissionsForm,
|
||||
UserProfileForm,
|
||||
|
@ -469,9 +468,7 @@ class MapDetailMixin:
|
|||
else:
|
||||
map_statuses = AnonymousMapPermissionsForm.STATUS
|
||||
datalayer_statuses = AnonymousDataLayerPermissionsForm.STATUS
|
||||
properties["edit_statuses"] = [
|
||||
(i, str(label)) for i, label in map_statuses
|
||||
]
|
||||
properties["edit_statuses"] = [(i, str(label)) for i, label in map_statuses]
|
||||
properties["datalayer_edit_statuses"] = [
|
||||
(i, str(label)) for i, label in datalayer_statuses
|
||||
]
|
||||
|
@ -618,48 +615,6 @@ class MapNew(MapDetailMixin, TemplateView):
|
|||
template_name = "umap/map_detail.html"
|
||||
|
||||
|
||||
class MapCreate(FormLessEditMixin, PermissionsMixin, CreateView):
|
||||
model = Map
|
||||
form_class = MapSettingsForm
|
||||
|
||||
def form_valid(self, form):
|
||||
if self.request.user.is_authenticated:
|
||||
form.instance.owner = self.request.user
|
||||
self.object = form.save()
|
||||
permissions = self.get_permissions()
|
||||
# User does not have the cookie yet.
|
||||
if not self.object.owner:
|
||||
anonymous_url = self.object.get_anonymous_edit_url()
|
||||
permissions["anonymous_edit_url"] = anonymous_url
|
||||
response = simple_json_response(
|
||||
id=self.object.pk,
|
||||
url=self.object.get_absolute_url(),
|
||||
permissions=permissions,
|
||||
)
|
||||
if not self.request.user.is_authenticated:
|
||||
key, value = self.object.signed_cookie_elements
|
||||
response.set_signed_cookie(
|
||||
key=key, value=value, max_age=ANONYMOUS_COOKIE_MAX_AGE
|
||||
)
|
||||
return response
|
||||
|
||||
|
||||
class MapUpdate(FormLessEditMixin, PermissionsMixin, UpdateView):
|
||||
model = Map
|
||||
form_class = MapSettingsForm
|
||||
pk_url_kwarg = "map_id"
|
||||
|
||||
def form_valid(self, form):
|
||||
self.object.settings = form.cleaned_data["settings"]
|
||||
self.object.save()
|
||||
return simple_json_response(
|
||||
id=self.object.pk,
|
||||
url=self.object.get_absolute_url(),
|
||||
permissions=self.get_permissions(),
|
||||
info=_("Map has been updated!"),
|
||||
)
|
||||
|
||||
|
||||
class UpdateMapPermissions(FormLessEditMixin, UpdateView):
|
||||
model = Map
|
||||
pk_url_kwarg = "map_id"
|
||||
|
|
Loading…
Reference in a new issue