add REST API

This commit is contained in:
Laura Klünder 2016-09-11 21:39:01 +02:00
parent 906eaea14a
commit 5f5152718f
9 changed files with 159 additions and 0 deletions

View file

View file

@ -0,0 +1,28 @@
from rest_framework.permissions import BasePermission
from rest_framework.exceptions import PermissionDenied
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from ..mapdata.models import Source
def get_unlocked_packages(request):
return set(settings.PUBLIC_PACKAGES) | set(request.session.get('unlocked_packages', ()))
def can_access_package(request, package):
print(package.name == 'de.c3nav.33c3.base')
return package.name == 'de.c3nav.33c3.base'
return settings.DEBUG or package.name in get_unlocked_packages(request)
def filter_source_queryset(request, queryset):
return queryset if settings.DEBUG else queryset.filter(package__name__in=get_unlocked_packages(request))
class LockedMapFeatures(BasePermission):
def has_object_permission(self, request, view, obj):
if isinstance(obj, Source):
if not can_access_package(request, obj.package):
raise PermissionDenied(_('This Source belongs to a package you don\'t have access to.'))
return True

View file

@ -0,0 +1,29 @@
from rest_framework.serializers import ModelSerializer
from ..mapdata.models import Level, Package, Source
class BoundsMixin:
def to_representation(self, obj):
result = super().to_representation(obj)
if obj.bottom is not None:
result['bounds'] = ((obj.bottom, obj.left), (obj.top, obj.right))
return result
class LevelSerializer(ModelSerializer):
class Meta:
model = Level
fields = ('name', 'altitude', 'package')
class PackageSerializer(BoundsMixin, ModelSerializer):
class Meta:
model = Package
fields = ('name', 'depends')
class SourceSerializer(BoundsMixin, ModelSerializer):
class Meta:
model = Source
fields = ('name', 'package')

15
src/c3nav/api/urls.py Normal file
View file

@ -0,0 +1,15 @@
from django.conf.urls import include, url
from rest_framework.routers import DefaultRouter
from .views import map as map_views
router = DefaultRouter()
router.register(r'map/levels', map_views.LevelViewSet)
router.register(r'map/packages', map_views.PackageViewSet)
router.register(r'map/sources', map_views.SourceViewSet)
urlpatterns = [
url(r'^(?P<version>v\d+)/', include(router.urls, namespace='v1')),
]

View file

View file

@ -0,0 +1,65 @@
import mimetypes
import os
from django.conf import settings
from django.core.files import File
from django.http import HttpResponse
from rest_framework.viewsets import ReadOnlyModelViewSet
from rest_framework.decorators import detail_route
from ...mapdata.models import Level, Package, Source
from ..serializers import LevelSerializer, PackageSerializer, SourceSerializer
from ..permissions import filter_source_queryset
class LevelViewSet(ReadOnlyModelViewSet):
"""
Returns a list of all levels on the map.
"""
queryset = Level.objects.all()
serializer_class = LevelSerializer
lookup_value_regex = '[^/]+'
filter_fields = ('altitude', 'package')
ordering_fields = ('altitude', 'package')
ordering = ('altitude',)
search_fields = ('name',)
class PackageViewSet(ReadOnlyModelViewSet):
"""
Returns a list of all packages the map consists of.
"""
queryset = Package.objects.all()
serializer_class = PackageSerializer
lookup_value_regex = '[^/]+'
filter_fields = ('name', 'depends')
ordering_fields = ('name',)
ordering = ('name',)
search_fields = ('name',)
class SourceViewSet(ReadOnlyModelViewSet):
"""
Returns a list of source images (to use as a drafts).
Call /sources/{name}/image to get the image.
"""
queryset = Source.objects.all()
serializer_class = SourceSerializer
lookup_value_regex = '[^/]+'
filter_fields = ('package',)
ordering_fields = ('name', 'package')
ordering = ('name',)
search_fields = ('name',)
def get_queryset(self):
return filter_source_queryset(self.request, super().get_queryset())
@detail_route(methods=['get'])
def image(self, request, pk=None, version=None):
source = self.get_object()
response = HttpResponse(content_type=mimetypes.guess_type(source.name)[0])
image_path = os.path.join(settings.MAP_ROOT, source.package.directory, 'sources', source.name)
for chunk in File(open(image_path, 'rb')).chunks():
response.write(chunk)
return response