full access token should work now

This commit is contained in:
Laura Klünder 2016-12-21 20:56:28 +01:00
parent e6255c8ecd
commit b856a0168a
13 changed files with 113 additions and 96 deletions

View file

@ -1,5 +1,6 @@
from django.conf import settings from django.conf import settings
from c3nav.mapdata.inclusion import get_maybe_invisible_areas_names
from c3nav.mapdata.utils.cache import get_packages_cached from c3nav.mapdata.utils.cache import get_packages_cached
@ -29,3 +30,9 @@ def can_access_package(request, package):
def filter_queryset_by_package_access(request, queryset): def filter_queryset_by_package_access(request, queryset):
return queryset if request.c3nav_full_access else queryset.filter(package__in=get_unlocked_packages(request)) return queryset if request.c3nav_full_access else queryset.filter(package__in=get_unlocked_packages(request))
def get_visible_areas(request):
areas = [':full' if request.c3nav_full_access else ':base']
areas += [name for name in get_maybe_invisible_areas_names() if name in request.c3nav_access_list]
return areas

View file

@ -1,6 +1,7 @@
import re import re
from datetime import timedelta from datetime import timedelta
from django.conf import settings
from django.db import transaction from django.db import transaction
from django.db.models import Q from django.db.models import Q
from django.utils import timezone from django.utils import timezone
@ -17,8 +18,8 @@ class AccessTokenMiddleware:
request.c3nav_access = None request.c3nav_access = None
request.c3nav_new_access = False request.c3nav_new_access = False
request.c3nav_full_access = False request.c3nav_full_access = settings.DEBUG
request.c3nav_access_list = None request.c3nav_access_list = ()
access_cookie = request.COOKIES.get('c3nav_access') access_cookie = request.COOKIES.get('c3nav_access')
if access_cookie and re.match(r'^[0-9]+:[a-zA-Z0-9]+$', access_cookie): if access_cookie and re.match(r'^[0-9]+:[a-zA-Z0-9]+$', access_cookie):

View file

@ -12,7 +12,7 @@ from rest_framework.viewsets import ReadOnlyModelViewSet, ViewSet
from c3nav.access.apply import filter_queryset_by_package_access, get_unlocked_packages_names from c3nav.access.apply import filter_queryset_by_package_access, get_unlocked_packages_names
from c3nav.mapdata.models import GEOMETRY_MAPITEM_TYPES, AreaLocation, Level, LocationGroup, Package, Source from c3nav.mapdata.models import GEOMETRY_MAPITEM_TYPES, AreaLocation, Level, LocationGroup, Package, Source
from c3nav.mapdata.models.geometry import DirectedLineGeometryMapItemWithLevel from c3nav.mapdata.models.geometry import DirectedLineGeometryMapItemWithLevel
from c3nav.mapdata.models.locations import get_location from c3nav.mapdata.search import get_location
from c3nav.mapdata.serializers.main import LevelSerializer, PackageSerializer, SourceSerializer from c3nav.mapdata.serializers.main import LevelSerializer, PackageSerializer, SourceSerializer
from c3nav.mapdata.utils.cache import (CachedReadOnlyViewSetMixin, cache_mapdata_api_response, get_levels_cached, from c3nav.mapdata.utils.cache import (CachedReadOnlyViewSetMixin, cache_mapdata_api_response, get_levels_cached,
get_packages_cached) get_packages_cached)

View file

@ -1,9 +1,7 @@
from collections import OrderedDict from collections import OrderedDict
from django.conf import settings
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from c3nav.access.apply import can_access_package
from c3nav.mapdata.models import AreaLocation, LocationGroup from c3nav.mapdata.models import AreaLocation, LocationGroup
@ -29,20 +27,21 @@ def get_includables_avoidables(request):
locations = list(AreaLocation.objects.exclude(routing_inclusion='default')) locations = list(AreaLocation.objects.exclude(routing_inclusion='default'))
locations += list(LocationGroup.objects.exclude(routing_inclusion='default')) locations += list(LocationGroup.objects.exclude(routing_inclusion='default'))
if settings.DEBUG: if request.c3nav_full_access:
includables.append((':nonpublic', _('non-public areas'))) includables.append((':nonpublic', _('non-public areas')))
avoidables.append((':public', _('public areas'))) avoidables.append((':public', _('public areas')))
from c3nav.access.apply import can_access_package
for location in locations: for location in locations:
item = (location.location_id, location.title) item = (location.location_id, location.title)
# Todo: allow by access token
if not can_access_package(request, location.package): if not can_access_package(request, location.package):
continue continue
# Todo: allow by access token if location.routing_inclusion == 'needs_permission':
if location.routing_inclusion == 'needs_permission' and not settings.DEBUG: if not request.c3nav_full_access and location.location_id not in request.c3nav_access_list:
continue continue
if location.routing_inclusion == 'allow_avoid': if location.routing_inclusion == 'allow_avoid':
avoidables.append(item) avoidables.append(item)
@ -52,6 +51,14 @@ def get_includables_avoidables(request):
return OrderedDict(includables), OrderedDict(avoidables) return OrderedDict(includables), OrderedDict(avoidables)
def get_maybe_invisible_areas():
return AreaLocation.objects.exclude(routing_inclusion='default')
def get_maybe_invisible_areas_names():
return tuple(area.name for area in get_maybe_invisible_areas())
def parse_include_avoid(request, include_input, avoid_input): def parse_include_avoid(request, include_input, avoid_input):
includable, avoidable = get_includables_avoidables(request) includable, avoidable = get_includables_avoidables(request)
include_input = set(include_input) & set(includable) include_input = set(include_input) & set(includable)

View file

@ -1,20 +1,16 @@
import re
from collections import OrderedDict from collections import OrderedDict
import numpy as np import numpy as np
from django.core.cache import cache from django.core.cache import cache
from django.db import models from django.db import models
from django.db.models import Q
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from c3nav.access.apply import filter_queryset_by_package_access
from c3nav.mapdata.fields import JSONField from c3nav.mapdata.fields import JSONField
from c3nav.mapdata.lastupdate import get_last_mapdata_update from c3nav.mapdata.lastupdate import get_last_mapdata_update
from c3nav.mapdata.models import Level from c3nav.mapdata.models import Level
from c3nav.mapdata.models.base import MapItem from c3nav.mapdata.models.base import MapItem
from c3nav.mapdata.models.geometry import GeometryMapItemWithLevel from c3nav.mapdata.models.geometry import GeometryMapItemWithLevel
from c3nav.mapdata.utils.cache import get_levels_cached
class Location: class Location:
@ -238,49 +234,6 @@ class AreaLocation(LocationModelMixin, GeometryMapItemWithLevel):
return self.title return self.title
def get_location(request, name):
match = re.match('^c:(?P<level>[a-z0-9-_]+):(?P<x>[0-9]+):(?P<y>[0-9]+)$', name)
if match:
levels = get_levels_cached()
level = levels.get(match.group('level'))
if level is None:
return None
return PointLocation(level=level, x=int(match.group('x'))/100, y=int(match.group('y'))/100)
if name.startswith('g:'):
return filter_queryset_by_package_access(request, LocationGroup.objects.filter(name=name[2:])).first()
return filter_queryset_by_package_access(request, AreaLocation.objects.filter(name=name)).first()
def filter_words(queryset, words):
for word in words:
queryset = queryset.filter(Q(name__icontains=word) | Q(titles__icontains=word))
return queryset
def search_location(request, search):
results = []
location = get_location(request, search)
if location:
results.append(location)
words = search.split(' ')[:10]
queryset = AreaLocation.objects.all()
if isinstance(location, AreaLocation):
queryset.exclude(name=location.name)
results += sorted(filter_words(filter_queryset_by_package_access(request, queryset), words),
key=AreaLocation.get_sort_key, reverse=True)
queryset = LocationGroup.objects.all()
if isinstance(location, LocationGroup):
queryset.exclude(name=location.name)
results += list(filter_words(filter_queryset_by_package_access(request, queryset), words)[:10])
return results
class PointLocation(Location): class PointLocation(Location):
def __init__(self, level: Level, x: int, y: int): def __init__(self, level: Level, x: int, y: int):
self.level = level self.level = level

View file

@ -1,23 +0,0 @@
import mimetypes
from django.conf import settings
from django.core.files import File
from django.http import HttpResponse
from c3nav.mapdata.utils.misc import get_render_path
class LevelComposer:
def get_level_image(self, request, level):
if settings.DIRECT_EDITING:
img = get_render_path('png', level.name, 'full', True)
else:
img = get_render_path('png', level.name, 'full', False)
response = HttpResponse(content_type=mimetypes.guess_type(img)[0])
for chunk in File(open(img, 'rb')).chunks():
response.write(chunk)
return response
composer = LevelComposer()

View file

@ -0,0 +1,51 @@
import re
from django.db.models import Q
from c3nav.access.apply import filter_queryset_by_package_access
from c3nav.mapdata.models import AreaLocation, LocationGroup
from c3nav.mapdata.models.locations import PointLocation
from c3nav.mapdata.utils.cache import get_levels_cached
def get_location(request, name):
match = re.match('^c:(?P<level>[a-z0-9-_]+):(?P<x>[0-9]+):(?P<y>[0-9]+)$', name)
if match:
levels = get_levels_cached()
level = levels.get(match.group('level'))
if level is None:
return None
return PointLocation(level=level, x=int(match.group('x'))/100, y=int(match.group('y'))/100)
if name.startswith('g:'):
return filter_queryset_by_package_access(request, LocationGroup.objects.filter(name=name[2:])).first()
return filter_queryset_by_package_access(request, AreaLocation.objects.filter(name=name)).first()
def filter_words(queryset, words):
for word in words:
queryset = queryset.filter(Q(name__icontains=word) | Q(titles__icontains=word))
return queryset
def search_location(request, search):
results = []
location = get_location(request, search)
if location:
results.append(location)
words = search.split(' ')[:10]
queryset = AreaLocation.objects.all()
if isinstance(location, AreaLocation):
queryset.exclude(name=location.name)
results += sorted(filter_words(filter_queryset_by_package_access(request, queryset), words),
key=AreaLocation.get_sort_key, reverse=True)
queryset = LocationGroup.objects.all()
if isinstance(location, LocationGroup):
queryset.exclude(name=location.name)
results += list(filter_words(filter_queryset_by_package_access(request, queryset), words)[:10])
return results

View file

@ -86,7 +86,7 @@ body, .btn {
.locationselect-map .scroll-hint { .locationselect-map .scroll-hint {
color:#FFFFFF; color:#FFFFFF;
position:absolute; position:absolute;
top:150px; top:250px;
left:16px; left:16px;
} }

View file

@ -5,6 +5,7 @@ c3nav = {
c3nav.svg_width = parseInt(c3nav.main_view.attr('data-svg-width')); c3nav.svg_width = parseInt(c3nav.main_view.attr('data-svg-width'));
c3nav.svg_height = parseInt(c3nav.main_view.attr('data-svg-height')); c3nav.svg_height = parseInt(c3nav.main_view.attr('data-svg-height'));
c3nav.visible_areas = c3nav.main_view.attr('data-visible-areas').split(';');
c3nav._typeahead_locations = new Bloodhound({ c3nav._typeahead_locations = new Bloodhound({
datumTokenizer: function(data) { datumTokenizer: function(data) {
@ -77,11 +78,13 @@ c3nav = {
$(this).siblings().removeClass('active'); $(this).siblings().removeClass('active');
$(this).addClass('active'); $(this).addClass('active');
map_container.find('img').remove(); map_container.find('img').remove();
map_container.append($('<img>').attr({ for (var i=0;i<c3nav.visible_areas.length;i++) {
'src': '/map/'+level+'.png', map_container.append($('<img>').attr({
'width': c3nav.svg_width, 'src': '/map/'+level+'/'+c3nav.visible_areas[i]+'.png',
'height': c3nav.svg_height 'width': c3nav.svg_width,
})); 'height': c3nav.svg_height
}));
}
map_container.attr('data-level', level); map_container.attr('data-level', level);
}, },
_locationselect_click_image: function(e) { _locationselect_click_image: function(e) {

View file

@ -31,8 +31,10 @@
<div class="map-container"> <div class="map-container">
<div class="dummy" style="width:{{ svg_width }}px;height:{{ svg_height }}px;"></div> <div class="dummy" style="width:{{ svg_width }}px;height:{{ svg_height }}px;"></div>
{% if map_level %} {% if map_level %}
<input type="image" src="/map/{{ map_level }}.png" width="{{ svg_width }}" height="{{ svg_height }}"> {% for area in visible_areas %}
<p class="scroll-hint">{% trans 'You have Javascript deactivated. Please scroll in this direction ⇘' %}</p> <input type="image" src="{% url 'site.level_image' level=map_level area=area %}" width="{{ svg_width }}" height="{{ svg_height }}">
{% endfor %}
<p class="scroll-hint">{% trans 'Javascript is disabled. Please scroll in this direction ⇘' %}</p>
{% endif %} {% endif %}
</div> </div>
<div class="map-buttons"> <div class="map-buttons">

View file

@ -4,7 +4,8 @@
{% load i18n %} {% load i18n %}
{% block content %} {% block content %}
<form method="post" class="main-view mode-{{ mode }}{% if origin and destination %} can-route{% endif %}" data-svg-width="{{ svg_width }}" data-svg-height="{{ svg_height }}"> <form method="post" class="main-view mode-{{ mode }}{% if origin and destination %} can-route{% endif %}"
data-svg-width="{{ svg_width }}" data-svg-height="{{ svg_height }}" data-visible-areas="{{ visible_areas | join:';' }}"
{% csrf_token %} {% csrf_token %}
<div class="row locations"> <div class="row locations">
{% trans "Location" as heading %} {% trans "Location" as heading %}

View file

@ -3,7 +3,7 @@ from django.conf.urls import url
from c3nav.site.views import level_image, main from c3nav.site.views import level_image, main
urlpatterns = [ urlpatterns = [
url(r'^map/(?P<level>[a-z0-9-_:]+).png$', level_image, name='site.level_image'), url(r'^map/(?P<level>[a-z0-9-_:]+)/(?P<area>[a-z0-9-_:]+).png$', level_image, name='site.level_image'),
url(r'^l/(?P<location>[a-z0-9-_:]+)/$', main, name='site.location'), url(r'^l/(?P<location>[a-z0-9-_:]+)/$', main, name='site.location'),
url(r'^o/(?P<origin>[a-z0-9-_:]+)/$', main, name='site.origin'), url(r'^o/(?P<origin>[a-z0-9-_:]+)/$', main, name='site.origin'),
url(r'^d/(?P<destination>[a-z0-9-_:]+)/$', main, name='site.destination'), url(r'^d/(?P<destination>[a-z0-9-_:]+)/$', main, name='site.destination'),

View file

@ -1,16 +1,18 @@
import mimetypes
from datetime import timedelta from datetime import timedelta
from django.http import Http404 from django.core.files import File
from django.http import Http404, HttpResponse
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse from django.urls import reverse
from django.utils import timezone from django.utils import timezone
from c3nav.access.apply import get_visible_areas
from c3nav.mapdata.inclusion import get_includables_avoidables, parse_include_avoid from c3nav.mapdata.inclusion import get_includables_avoidables, parse_include_avoid
from c3nav.mapdata.models import Level from c3nav.mapdata.models import Level
from c3nav.mapdata.models.locations import get_location, search_location from c3nav.mapdata.search import get_location, search_location
from c3nav.mapdata.render.compose import composer
from c3nav.mapdata.utils.cache import get_levels_cached from c3nav.mapdata.utils.cache import get_levels_cached
from c3nav.mapdata.utils.misc import get_dimensions from c3nav.mapdata.utils.misc import get_dimensions, get_render_path
from c3nav.routing.exceptions import AlreadyThere, NoRouteFound, NotYetRoutable from c3nav.routing.exceptions import AlreadyThere, NoRouteFound, NotYetRoutable
from c3nav.routing.graph import Graph from c3nav.routing.graph import Graph
@ -68,6 +70,7 @@ def main(request, location=None, origin=None, destination=None):
'full_access': request.c3nav_full_access, 'full_access': request.c3nav_full_access,
'access_list': request.c3nav_access_list, 'access_list': request.c3nav_access_list,
'visible_areas': get_visible_areas(request),
} }
width, height = get_dimensions() width, height = get_dimensions()
@ -209,6 +212,18 @@ def main(request, location=None, origin=None, destination=None):
return response return response
def level_image(request, level): def level_image(request, area, level):
level = get_object_or_404(Level, name=level, intermediate=False) level = get_object_or_404(Level, name=level, intermediate=False)
return composer.get_level_image(request, level) if area == ':base':
img = get_render_path('png', level.name, 'full', True)
elif area == ':full':
if not request.c3nav_full_access:
raise Http404
img = get_render_path('png', level.name, 'full', False)
else:
raise Http404
response = HttpResponse(content_type=mimetypes.guess_type(img)[0])
for chunk in File(open(img, 'rb')).chunks():
response.write(chunk)
return response