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 c3nav.mapdata.inclusion import get_maybe_invisible_areas_names
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):
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
from datetime import timedelta
from django.conf import settings
from django.db import transaction
from django.db.models import Q
from django.utils import timezone
@ -17,8 +18,8 @@ class AccessTokenMiddleware:
request.c3nav_access = None
request.c3nav_new_access = False
request.c3nav_full_access = False
request.c3nav_access_list = None
request.c3nav_full_access = settings.DEBUG
request.c3nav_access_list = ()
access_cookie = request.COOKIES.get('c3nav_access')
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.mapdata.models import GEOMETRY_MAPITEM_TYPES, AreaLocation, Level, LocationGroup, Package, Source
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.utils.cache import (CachedReadOnlyViewSetMixin, cache_mapdata_api_response, get_levels_cached,
get_packages_cached)

View file

@ -1,9 +1,7 @@
from collections import OrderedDict
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from c3nav.access.apply import can_access_package
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(LocationGroup.objects.exclude(routing_inclusion='default'))
if settings.DEBUG:
if request.c3nav_full_access:
includables.append((':nonpublic', _('non-public areas')))
avoidables.append((':public', _('public areas')))
from c3nav.access.apply import can_access_package
for location in locations:
item = (location.location_id, location.title)
# Todo: allow by access token
if not can_access_package(request, location.package):
continue
# Todo: allow by access token
if location.routing_inclusion == 'needs_permission' and not settings.DEBUG:
continue
if location.routing_inclusion == 'needs_permission':
if not request.c3nav_full_access and location.location_id not in request.c3nav_access_list:
continue
if location.routing_inclusion == 'allow_avoid':
avoidables.append(item)
@ -52,6 +51,14 @@ def get_includables_avoidables(request):
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):
includable, avoidable = get_includables_avoidables(request)
include_input = set(include_input) & set(includable)

View file

@ -1,20 +1,16 @@
import re
from collections import OrderedDict
import numpy as np
from django.core.cache import cache
from django.db import models
from django.db.models import Q
from django.utils.functional import cached_property
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.lastupdate import get_last_mapdata_update
from c3nav.mapdata.models import Level
from c3nav.mapdata.models.base import MapItem
from c3nav.mapdata.models.geometry import GeometryMapItemWithLevel
from c3nav.mapdata.utils.cache import get_levels_cached
class Location:
@ -238,49 +234,6 @@ class AreaLocation(LocationModelMixin, GeometryMapItemWithLevel):
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):
def __init__(self, level: Level, x: int, y: int):
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 {
color:#FFFFFF;
position:absolute;
top:150px;
top:250px;
left:16px;
}

View file

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

View file

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

View file

@ -4,7 +4,8 @@
{% load i18n %}
{% 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 %}
<div class="row locations">
{% trans "Location" as heading %}

View file

@ -3,7 +3,7 @@ from django.conf.urls import url
from c3nav.site.views import level_image, main
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'^o/(?P<origin>[a-z0-9-_:]+)/$', main, name='site.origin'),
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 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.urls import reverse
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.models import Level
from c3nav.mapdata.models.locations import get_location, search_location
from c3nav.mapdata.render.compose import composer
from c3nav.mapdata.search import get_location, search_location
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.graph import Graph
@ -68,6 +70,7 @@ def main(request, location=None, origin=None, destination=None):
'full_access': request.c3nav_full_access,
'access_list': request.c3nav_access_list,
'visible_areas': get_visible_areas(request),
}
width, height = get_dimensions()
@ -209,6 +212,18 @@ def main(request, location=None, origin=None, destination=None):
return response
def level_image(request, level):
def level_image(request, area, level):
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