more stuff about access and footer

This commit is contained in:
Laura Klünder 2016-12-21 20:14:40 +01:00
parent 4421d1a3e8
commit e6255c8ecd
17 changed files with 97 additions and 68 deletions

31
src/c3nav/access/apply.py Normal file
View file

@ -0,0 +1,31 @@
from django.conf import settings
from c3nav.mapdata.utils.cache import get_packages_cached
def get_public_packages():
packages_cached = get_packages_cached()
return [packages_cached[name] for name in settings.PUBLIC_PACKAGES]
def get_nonpublic_packages():
packages_cached = get_packages_cached()
return [package for name, package in packages_cached.items() if name not in settings.PUBLIC_PACKAGES]
def get_unlocked_packages(request, packages_cached=None):
return tuple(get_packages_cached().values()) if request.c3nav_full_access else get_public_packages()
def get_unlocked_packages_names(request, packages_cached=None):
if request.c3nav_full_access:
return get_packages_cached().keys()
return settings.PUBLIC_PACKAGES
def can_access_package(request, package):
return request.c3nav_full_access or package.name in get_unlocked_packages_names(request)
def filter_queryset_by_package_access(request, queryset):
return queryset if request.c3nav_full_access else queryset.filter(package__in=get_unlocked_packages(request))

View file

@ -17,6 +17,9 @@ 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_access_list = None
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):
pk, secret = access_cookie.split(':') pk, secret = access_cookie.split(':')
@ -31,6 +34,9 @@ class AccessTokenMiddleware:
request.c3nav_access = access_instance.access_token request.c3nav_access = access_instance.access_token
request.c3nav_access.instances.filter(creation_date__lt=access_instance.creation_date).delete() request.c3nav_access.instances.filter(creation_date__lt=access_instance.creation_date).delete()
request.c3nav_full_access = request.c3nav_access.full_access
request.c3nav_access_list = request.c3nav_access.permissions_list
response = self.get_response(request) response = self.get_response(request)
if request.c3nav_access is not None: if request.c3nav_access is not None:

View file

@ -7,6 +7,7 @@ from django.db.models import Q
from django.urls import reverse from django.urls import reverse
from django.utils import timezone from django.utils import timezone
from django.utils.crypto import get_random_string from django.utils.crypto import get_random_string
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -65,6 +66,14 @@ class AccessToken(models.Model):
verbose_name = _('Access Token') verbose_name = _('Access Token')
verbose_name_plural = _('Access Tokens') verbose_name_plural = _('Access Tokens')
@cached_property
def permissions_list(self):
return self.permissions.split(';')
@cached_property
def full_access(self):
return ':full' in self.permissions_list
@property @property
def activation_url(self): def activation_url(self):
if self.activated: if self.activated:

View file

@ -4,9 +4,9 @@ from django.contrib.auth.decorators import login_required
from django.db import transaction from django.db import transaction
from django.shortcuts import get_object_or_404, render from django.shortcuts import get_object_or_404, render
from c3nav.access.apply import get_nonpublic_packages
from c3nav.access.models import AccessToken, AccessUser from c3nav.access.models import AccessToken, AccessUser
from c3nav.editor.hosters import get_hoster_for_package from c3nav.editor.hosters import get_hoster_for_package
from c3nav.mapdata.permissions import get_nonpublic_packages
@login_required(login_url='/access/login/') @login_required(login_url='/access/login/')
@ -54,7 +54,7 @@ def prove(request):
else: else:
user = AccessUser.objects.create(user_url=user_id) user = AccessUser.objects.create(user_url=user_id)
token = user.new_token(permissions=':all', description='automatically created') token = user.new_token(permissions=':full', description='automatically created')
return render(request, 'access/prove.html', context={ return render(request, 'access/prove.html', context={
'hosters': hosters, 'hosters': hosters,
'success': True, 'success': True,

View file

@ -9,8 +9,8 @@ from django.forms.widgets import HiddenInput
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from shapely.geometry.geo import mapping from shapely.geometry.geo import mapping
from c3nav.access.apply import get_unlocked_packages
from c3nav.mapdata.models import Package from c3nav.mapdata.models import Package
from c3nav.mapdata.permissions import get_unlocked_packages
class MapitemFormMixin(ModelForm): class MapitemFormMixin(ModelForm):

View file

@ -6,12 +6,12 @@ from django.http.response import Http404
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render
from django.utils import translation from django.utils import translation
from c3nav.access.apply import can_access_package, filter_queryset_by_package_access
from c3nav.editor.hosters import get_hoster_for_package, hosters from c3nav.editor.hosters import get_hoster_for_package, hosters
from c3nav.mapdata.models import AreaLocation from c3nav.mapdata.models import AreaLocation
from c3nav.mapdata.models.base import MAPITEM_TYPES from c3nav.mapdata.models.base import MAPITEM_TYPES
from c3nav.mapdata.models.package import Package from c3nav.mapdata.models.package import Package
from c3nav.mapdata.packageio.write import json_encode from c3nav.mapdata.packageio.write import json_encode
from c3nav.mapdata.permissions import can_access_package, filter_queryset_by_package_access
def list_mapitemtypes(request, level): def list_mapitemtypes(request, level):

View file

@ -9,10 +9,10 @@ from rest_framework.decorators import detail_route
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.viewsets import ReadOnlyModelViewSet, ViewSet 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 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.models.locations import get_location
from c3nav.mapdata.permissions import filter_queryset_by_package_access, get_unlocked_packages_names
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

@ -3,8 +3,8 @@ from collections import OrderedDict
from django.conf import settings 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
from c3nav.mapdata.permissions import can_access_package
def get_default_include_avoid(): def get_default_include_avoid():

View file

@ -86,7 +86,7 @@ class LevelGeometries():
self.level = level self.level = level
self.only_public = only_public self.only_public = only_public
from c3nav.mapdata.permissions import get_public_packages from c3nav.access.apply import get_public_packages
self.public_packages = get_public_packages() self.public_packages = get_public_packages()
def query(self, name): def query(self, name):

View file

@ -8,12 +8,12 @@ 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.permissions import filter_queryset_by_package_access
from c3nav.mapdata.utils.cache import get_levels_cached from c3nav.mapdata.utils.cache import get_levels_cached

View file

@ -1,58 +0,0 @@
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from rest_framework.exceptions import PermissionDenied
from rest_framework.permissions import BasePermission
from shapely.geometry import box
from c3nav.mapdata.models import Source
from c3nav.mapdata.utils.cache import get_packages_cached
from c3nav.mapdata.utils.misc import get_dimensions
def get_public_packages():
packages_cached = get_packages_cached()
return [packages_cached[name] for name in settings.PUBLIC_PACKAGES]
def get_nonpublic_packages():
packages_cached = get_packages_cached()
return [package for name, package in packages_cached.items() if name not in settings.PUBLIC_PACKAGES]
def get_unlocked_packages_names(request, packages_cached=None):
if packages_cached is None:
packages_cached = get_packages_cached()
if settings.DIRECT_EDITING:
return packages_cached.keys()
return set(settings.PUBLIC_PACKAGES) | set(request.session.get('unlocked_packages', ()))
def get_unlocked_packages(request, packages_cached=None):
if packages_cached is None:
packages_cached = get_packages_cached()
names = get_unlocked_packages_names(request, packages_cached=packages_cached)
return tuple(packages_cached[name] for name in names if name in packages_cached)
def can_access_package(request, package):
return settings.DEBUG or package.name in get_unlocked_packages_names(request)
def filter_queryset_by_package_access(request, queryset):
return queryset if settings.DIRECT_EDITING else queryset.filter(package__in=get_unlocked_packages(request))
def get_public_private_area(level):
width, height = get_dimensions()
everything = box(0, 0, width, height)
public_area = level.public_geometries.areas_and_doors
private_area = everything.difference(public_area)
return public_area, private_area
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

@ -62,7 +62,7 @@ class CachedReadOnlyViewSetMixin():
include_package_access = False include_package_access = False
def _get_unlocked_packages_ids(self, request): def _get_unlocked_packages_ids(self, request):
from c3nav.mapdata.permissions import get_unlocked_packages from c3nav.access.apply import get_unlocked_packages
return ','.join(str(i) for i in sorted(package.id for package in get_unlocked_packages(request))) return ','.join(str(i) for i in sorted(package.id for package in get_unlocked_packages(request)))
def _get_add_cache_key(self, request, add_cache_key=''): def _get_add_cache_key(self, request, add_cache_key=''):

View file

@ -2,6 +2,7 @@ import os
from django.conf import settings from django.conf import settings
from django.db.models import Max, Min from django.db.models import Max, Min
from shapely.geometry import box
from c3nav.mapdata.models import Package from c3nav.mapdata.models import Package
from c3nav.mapdata.utils.cache import cache_result from c3nav.mapdata.utils.cache import cache_result
@ -25,3 +26,11 @@ def get_render_dimensions():
def get_render_path(filetype, level, mode, public): def get_render_path(filetype, level, mode, public):
return os.path.join(settings.RENDER_ROOT, return os.path.join(settings.RENDER_ROOT,
'%s%s-level-%s.%s' % (('public-' if public else ''), mode, level, filetype)) '%s%s-level-%s.%s' % (('public-' if public else ''), mode, level, filetype))
def get_public_private_area(level):
width, height = get_dimensions()
everything = box(0, 0, width, height)
public_area = level.public_geometries.areas_and_doors
private_area = everything.difference(public_area)
return public_area, private_area

View file

@ -10,8 +10,9 @@ from scipy.sparse.csgraph._shortest_path import shortest_path
from scipy.sparse.csgraph._tools import csgraph_from_dense from scipy.sparse.csgraph._tools import csgraph_from_dense
from shapely.geometry import CAP_STYLE, JOIN_STYLE, LineString from shapely.geometry import CAP_STYLE, JOIN_STYLE, LineString
from c3nav.mapdata.permissions import get_public_packages, get_public_private_area from c3nav.access.apply import get_public_packages
from c3nav.mapdata.utils.geometry import assert_multilinestring, assert_multipolygon from c3nav.mapdata.utils.geometry import assert_multilinestring, assert_multipolygon
from c3nav.mapdata.utils.misc import get_public_private_area
from c3nav.routing.point import GraphPoint from c3nav.routing.point import GraphPoint
from c3nav.routing.room import GraphRoom from c3nav.routing.room import GraphRoom
from c3nav.routing.utils.base import get_nearest_point from c3nav.routing.utils.base import get_nearest_point

View file

@ -264,3 +264,8 @@ circle.pos {
background-repeat:no-repeat; background-repeat:no-repeat;
background-position:center; background-position:center;
} }
footer {
text-align:center;
}

View file

@ -1,5 +1,7 @@
{% load static %} {% load static %}
{% load compress %} {% load compress %}
{% load i18n %}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -19,6 +21,27 @@
<h1>c3nav</h1> <h1>c3nav</h1>
{% block content %} {% block content %}
{% endblock %} {% endblock %}
<footer>
<a href="https://github.com/c3nav/c3nav">GitHub</a>
- <a href="https://twitter.com/c3nav">Twitter</a>
<a href="{% url 'editor.index' %}">{% trans 'Editor' %}</a>
<a href="/api/">{% trans 'API' %}</a>
{% if full_access or access_list %}
<br><small>
{% if full_access %}
{% trans 'full access unlocked' %}
{% else %}
{{ access_list }}
{% blocktrans count count=access_list|length %}
one area unlocked
{% plural %}
{{ count }} areas unlocked
{% endblocktrans %}
{% endif %}
</small>
{% endif %}
</footer>
</div> </div>
{% compress js %} {% compress js %}

View file

@ -65,6 +65,9 @@ def main(request, location=None, origin=None, destination=None):
'destination': destination, 'destination': destination,
'mode': mode, 'mode': mode,
'active_field': active_field, 'active_field': active_field,
'full_access': request.c3nav_full_access,
'access_list': request.c3nav_access_list,
} }
width, height = get_dimensions() width, height = get_dimensions()