api for setting positions

This commit is contained in:
Laura Klünder 2019-12-28 16:35:38 +01:00
parent 01befdedb8
commit 399ac98c1c
3 changed files with 54 additions and 3 deletions

View file

@ -15,10 +15,11 @@ from django.utils.translation import ugettext_lazy as _
from rest_framework.decorators import action
from rest_framework.exceptions import NotFound, ValidationError
from rest_framework.generics import get_object_or_404
from rest_framework.mixins import RetrieveModelMixin
from rest_framework.mixins import RetrieveModelMixin, UpdateModelMixin
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet, ReadOnlyModelViewSet, ViewSet
from c3nav.mapdata.forms import PositionAPIUpdateForm
from c3nav.mapdata.models import AccessRestriction, Building, Door, Hole, LocationGroup, MapUpdate, Source, Space
from c3nav.mapdata.models.access import AccessPermission, AccessRestrictionGroup
from c3nav.mapdata.models.geometry.base import GeometryMixin
@ -464,7 +465,7 @@ class LocationBySlugViewSet(LocationViewSetBase):
return get_location_by_slug_for_request(self.kwargs['slug'], self.request)
class DynamicLocationPositionViewSet(RetrieveModelMixin, GenericViewSet):
class DynamicLocationPositionViewSet(UpdateModelMixin, RetrieveModelMixin, GenericViewSet):
queryset = LocationSlug.objects.all()
lookup_field = 'slug'
lookup_value_regex = r'[^/]+'
@ -482,6 +483,20 @@ class DynamicLocationPositionViewSet(RetrieveModelMixin, GenericViewSet):
obj = self.get_object()
return Response(obj.serialize_position())
def update(self, request, *args, **kwargs):
instance = self.get_object()
params = request.data
form = PositionAPIUpdateForm(instance=instance, data=params, request=request)
if not form.is_valid():
return Response({
'errors': form.errors,
}, status=400)
form.save()
return Response(form.instance.serialize_position())
class SourceViewSet(MapdataViewSet):
queryset = Source.objects.all()

View file

@ -8,6 +8,8 @@ from django.utils.translation import get_language_info
from django.utils.translation import ugettext_lazy as _
from c3nav.mapdata.fields import I18nField
from c3nav.mapdata.models.locations import Position
from c3nav.mapdata.utils.locations import get_location_by_id_for_request
class I18nModelFormMixin(ModelForm):
@ -62,3 +64,36 @@ class I18nModelFormMixin(ModelForm):
super().full_clean()
for field, values in self.i18n_fields:
setattr(self.instance, field.attname, {lang: value for lang, value in values.items() if value})
class PositionAPIUpdateForm(ModelForm):
secret = CharField()
def __init__(self, *args, request=None, **kwargs):
self.request = request
super().__init__(*args, **kwargs)
class Meta:
model = Position
fields = ['coordinates_id', 'timeout']
def clean_secret(self):
# not called api_secret so we don't overwrite it
api_secret = self.cleaned_data['secret']
if api_secret != self.instance.api_secret:
raise ValidationError(_('Wrong API secret.'))
return api_secret
def clean_coordinates_id(self):
coordinates_id = self.cleaned_data['coordinates_id']
if coordinates_id is None:
return coordinates_id
if not coordinates_id.startswith('c:'):
raise ValidationError(_('Invalid coordinates.'))
coordinates = get_location_by_id_for_request(self.cleaned_data['coordinates_id'], self.request)
if coordinates is None:
raise ValidationError(_('Invalid coordinates.'))
return coordinates_id

View file

@ -566,7 +566,8 @@ class Position(CustomLocationProxyMixin, models.Model):
name = models.CharField(_('name'), max_length=32)
secret = models.CharField(_('secret'), unique=True, max_length=32, default=get_position_secret)
last_coordinates_update = models.DateTimeField(_('last coordinates update'), null=True)
timeout = models.PositiveSmallIntegerField(_('timeout (in seconds)'), default=0, help_text=_('0 for no timeout'))
timeout = models.PositiveSmallIntegerField(_('timeout (in seconds)'), default=0, blank=True,
help_text=_('0 for no timeout'))
coordinates_id = models.CharField(_('coordinates'), null=True, max_length=48)
api_secret = models.CharField(_('api secret'), max_length=64, default=get_position_api_secret)