full access token should work now
This commit is contained in:
parent
e6255c8ecd
commit
b856a0168a
13 changed files with 113 additions and 96 deletions
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
|
51
src/c3nav/mapdata/search.py
Normal file
51
src/c3nav/mapdata/search.py
Normal 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
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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 %}
|
||||||
|
|
|
@ -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'),
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue