remove old access app and old cache and inclusion code
This commit is contained in:
parent
c1d5c0ebef
commit
904e8f199c
31 changed files with 0 additions and 1212 deletions
|
@ -1,66 +0,0 @@
|
|||
from django.contrib import admin
|
||||
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from c3nav.access.models import AccessOperator, AccessToken, AccessTokenInstance, AccessUser
|
||||
|
||||
|
||||
class AccessOperatorInline(admin.StackedInline):
|
||||
model = AccessOperator
|
||||
can_delete = False
|
||||
|
||||
|
||||
class UserAdmin(BaseUserAdmin):
|
||||
fieldsets = (
|
||||
(None, {'fields': ('username', 'password', 'email')}),
|
||||
(_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
|
||||
'groups', 'user_permissions')}),
|
||||
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
|
||||
)
|
||||
readonly_fields = ('last_login', 'date_joined',)
|
||||
inlines = (AccessOperatorInline, )
|
||||
|
||||
|
||||
admin.site.unregister(User)
|
||||
admin.site.register(User, UserAdmin)
|
||||
|
||||
|
||||
class AccessTokenInline(admin.TabularInline):
|
||||
model = AccessToken
|
||||
show_change_link = True
|
||||
readonly_fields = ('author', 'permissions', 'description', 'creation_date', 'activated', 'expires', 'expired')
|
||||
|
||||
def has_add_permission(self, request):
|
||||
return False
|
||||
|
||||
|
||||
@admin.register(AccessUser)
|
||||
class AccessUserAdmin(admin.ModelAdmin):
|
||||
inlines = (AccessTokenInline,)
|
||||
list_display = ('user_url', 'creation_date', 'author', 'description')
|
||||
fields = ('user_url', 'creation_date', 'author', 'description')
|
||||
readonly_fields = ('creation_date', )
|
||||
|
||||
|
||||
class AccessTokenInstanceInline(admin.TabularInline):
|
||||
model = AccessTokenInstance
|
||||
fields = ('secret', 'creation_date', 'expires', )
|
||||
readonly_fields = ('secret', 'creation_date', 'expires', )
|
||||
|
||||
def has_add_permission(self, request):
|
||||
return False
|
||||
|
||||
def has_change_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
|
||||
@admin.register(AccessToken)
|
||||
class AccessTokenAdmin(admin.ModelAdmin):
|
||||
inlines = (AccessTokenInstanceInline,)
|
||||
list_display = ('__str__', 'user', 'permissions', 'author', 'creation_date', 'activated', 'expires', 'expired')
|
||||
fields = ('user', 'permissions', 'author', 'creation_date', 'activated', 'expires', 'expired', 'description')
|
||||
readonly_fields = ('user', 'creation_date', 'activated', 'expired', 'description')
|
||||
|
||||
def has_add_permission(self, request):
|
||||
return False
|
|
@ -1,27 +0,0 @@
|
|||
from django.db.models import Q
|
||||
|
||||
from c3nav.mapdata.inclusion import get_maybe_invisible_areas_names
|
||||
|
||||
|
||||
def can_access(request, item):
|
||||
# todo implement this
|
||||
return True
|
||||
|
||||
|
||||
def filter_queryset_by_access(request, queryset, filter_location_inclusion=False):
|
||||
# todo implement this
|
||||
return queryset if request.c3nav_full_access else queryset.filter(public=True)
|
||||
|
||||
|
||||
def filter_arealocations_by_access(request, queryset):
|
||||
# todo implement this
|
||||
if request.c3nav_full_access:
|
||||
return queryset
|
||||
return queryset.filter(Q(Q(public=True), ~Q(routing_inclusion='needs_permission')) |
|
||||
Q(name__in=request.c3nav_access_list))
|
||||
|
||||
|
||||
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,76 +0,0 @@
|
|||
from django.forms import ModelForm, MultipleChoiceField
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from c3nav.access.models import AccessToken, AccessUser
|
||||
|
||||
|
||||
def get_permissions_field(request):
|
||||
locations = AreaLocation.objects.filter(routing_inclusion='needs_permission').order_by('name')
|
||||
|
||||
has_operator = True
|
||||
try:
|
||||
request.user.operator
|
||||
except:
|
||||
has_operator = False
|
||||
|
||||
OPTIONS = []
|
||||
can_full = False
|
||||
if request.user.is_superuser:
|
||||
can_full = True
|
||||
elif has_operator:
|
||||
can_award = request.user.operator.can_award_permissions.split(';')
|
||||
can_full = ':full' in can_award
|
||||
if not can_full:
|
||||
locations = locations.filter(name__in=can_award)
|
||||
else:
|
||||
locations = []
|
||||
|
||||
if can_full:
|
||||
OPTIONS.append((':full', _('Full Permissions')))
|
||||
|
||||
locationgroups = {}
|
||||
locationgroups_count = {}
|
||||
for location in locations:
|
||||
for group in location.groups.all():
|
||||
if group.location_id not in locationgroups:
|
||||
locationgroups[group.location_id] = group
|
||||
locationgroups_count[group.location_id] = 0
|
||||
locationgroups_count[group.location_id] += 1
|
||||
|
||||
locationgroup_options = []
|
||||
for location_id, group in locationgroups.items():
|
||||
locationgroup_options.append((location_id, _('%(grouptitle)s (%(count)s nonpublic locations)') % {
|
||||
'grouptitle': group.title,
|
||||
'count': locationgroups_count[location_id]
|
||||
}))
|
||||
|
||||
OPTIONS += sorted(locationgroup_options)
|
||||
|
||||
if can_full:
|
||||
OPTIONS.append((':full', _('Full Permissions')))
|
||||
|
||||
OPTIONS += [(location.name, location.title) for location in locations]
|
||||
return MultipleChoiceField(choices=OPTIONS, required=True)
|
||||
|
||||
|
||||
class AccessTokenForm(ModelForm):
|
||||
def __init__(self, *args, request, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['permissions'] = get_permissions_field(request)
|
||||
|
||||
class Meta:
|
||||
model = AccessToken
|
||||
fields = ['permissions', 'description', 'expires']
|
||||
|
||||
def clean_permissions(self):
|
||||
data = self.cleaned_data['permissions']
|
||||
if ':full' in data:
|
||||
data = [':full']
|
||||
data = ';'.join(data)
|
||||
return data
|
||||
|
||||
|
||||
class AccessUserForm(ModelForm):
|
||||
class Meta:
|
||||
model = AccessUser
|
||||
fields = ['user_url', 'description']
|
|
@ -1,57 +0,0 @@
|
|||
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
|
||||
|
||||
from c3nav.access.models import AccessTokenInstance
|
||||
|
||||
|
||||
class AccessTokenMiddleware:
|
||||
def __init__(self, get_response):
|
||||
self.get_response = get_response
|
||||
|
||||
def __call__(self, request):
|
||||
request.c3nav_access_instance = None
|
||||
request.c3nav_access = None
|
||||
request.c3nav_new_access = False
|
||||
|
||||
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):
|
||||
pk, secret = access_cookie.split(':')
|
||||
queryset = AccessTokenInstance.objects.filter(Q(access_token__id=int(pk), secret=secret),
|
||||
Q(expires__isnull=True) | Q(expires__gt=timezone.now()),
|
||||
Q(access_token__expired=False),
|
||||
Q(access_token__expires__isnull=True) |
|
||||
Q(access_token__expires__gt=timezone.now()))
|
||||
access_instance = queryset.select_related('access_token').first()
|
||||
if access_instance:
|
||||
request.c3nav_access_instance = access_instance
|
||||
request.c3nav_access = access_instance.access_token
|
||||
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)
|
||||
|
||||
if request.c3nav_access is not None:
|
||||
with transaction.atomic():
|
||||
cookie_value = request.c3nav_access.new_instance()
|
||||
response.set_cookie('c3nav_access', cookie_value, expires=timezone.now() + timedelta(days=30))
|
||||
|
||||
if request.c3nav_new_access:
|
||||
request.c3nav_access.activated = True
|
||||
request.c3nav_access.save()
|
||||
|
||||
if request.c3nav_access_instance:
|
||||
access_token = request.c3nav_access_instance.access_token
|
||||
access_token.expired = True
|
||||
access_token.save()
|
||||
|
||||
return response
|
|
@ -1,83 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.4 on 2016-12-21 17:21
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='AccessOperator',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('description', models.TextField(blank=True, null=True, verbose_name='description')),
|
||||
('can_award_permissions', models.CharField(max_length=2048, verbose_name='can award permissions')),
|
||||
('access_from', models.DateTimeField(blank=True, null=True, verbose_name='has access from')),
|
||||
('access_until', models.DateTimeField(blank=True, null=True, verbose_name='has access until')),
|
||||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='operator', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'verbose_name_plural': 'Access Operator',
|
||||
'verbose_name': 'Access Operator',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AccessToken',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('permissions', models.CharField(max_length=2048, verbose_name='permissions')),
|
||||
('description', models.CharField(max_length=200, verbose_name='description')),
|
||||
('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='creation date')),
|
||||
('expires', models.DateTimeField(blank=True, null=True)),
|
||||
('expired', models.BooleanField(default=False, verbose_name='is expired')),
|
||||
('author', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='creator')),
|
||||
],
|
||||
options={
|
||||
'verbose_name_plural': 'Access Tokens',
|
||||
'verbose_name': 'Access Token',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AccessTokenInstance',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('secret', models.CharField(max_length=42, verbose_name='access secret')),
|
||||
('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='creation date')),
|
||||
('expires', models.DateTimeField(null=True)),
|
||||
('access_token', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='instances', to='access.AccessToken', verbose_name='Access Token')),
|
||||
],
|
||||
options={
|
||||
'verbose_name_plural': 'Access Tokens Instance',
|
||||
'verbose_name': 'Access Token Instance',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AccessUser',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('user_url', models.CharField(help_text='Usually an URL to a profile somewhere', max_length=200, unique=True, verbose_name='access name')),
|
||||
('description', models.TextField(blank=True, max_length=200, null=True, verbose_name='description')),
|
||||
('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='creation date')),
|
||||
('author', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='access.AccessOperator', verbose_name='creator')),
|
||||
],
|
||||
options={
|
||||
'verbose_name_plural': 'Access Users',
|
||||
'verbose_name': 'Access User',
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='accesstoken',
|
||||
name='user',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tokens', to='access.AccessUser', verbose_name='Access User'),
|
||||
),
|
||||
]
|
|
@ -1,26 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.4 on 2016-12-21 17:39
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='accesstoken',
|
||||
name='activated',
|
||||
field=models.BooleanField(default=False, verbose_name='activated'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='accesstoken',
|
||||
name='secret',
|
||||
field=models.CharField(default='', max_length=42, verbose_name='activation secret'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
|
@ -1,27 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.4 on 2016-12-21 23:11
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0002_auto_20161221_1739'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='accessoperator',
|
||||
name='description',
|
||||
field=models.TextField(blank=True, default='', verbose_name='description'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='accessuser',
|
||||
name='description',
|
||||
field=models.TextField(blank=True, default='', max_length=200, verbose_name='description'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
|
@ -1,19 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.4 on 2016-12-23 22:25
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0003_auto_20161221_2311'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='accesstokeninstance',
|
||||
options={'verbose_name': 'Access Token Instance', 'verbose_name_plural': 'Access Token Instances'},
|
||||
),
|
||||
]
|
|
@ -1,22 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.4 on 2016-12-25 10:18
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0004_auto_20161223_2225'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='accessuser',
|
||||
name='author',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='creator'),
|
||||
),
|
||||
]
|
|
@ -1,126 +0,0 @@
|
|||
import string
|
||||
from datetime import timedelta
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.db import models, transaction
|
||||
from django.db.models import Q
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.crypto import get_random_string
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class AccessOperator(models.Model):
|
||||
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='operator')
|
||||
description = models.TextField(_('description'), blank=True)
|
||||
can_award_permissions = models.CharField(_('can award permissions'), max_length=2048)
|
||||
access_from = models.DateTimeField(_('has access from'), null=True, blank=True)
|
||||
access_until = models.DateTimeField(_('has access until'), null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Access Operator')
|
||||
verbose_name_plural = _('Access Operator')
|
||||
|
||||
def __str__(self):
|
||||
return str(self.user)
|
||||
|
||||
|
||||
class AccessUser(models.Model):
|
||||
user_url = models.CharField(_('access name'), unique=True, max_length=200,
|
||||
help_text=_('Usually an URL to a profile somewhere'))
|
||||
author = models.ForeignKey(User, on_delete=models.PROTECT, null=True, blank=True,
|
||||
verbose_name=_('creator'))
|
||||
description = models.TextField(_('description'), max_length=200, blank=True)
|
||||
creation_date = models.DateTimeField(_('creation date'), auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Access User')
|
||||
verbose_name_plural = _('Access Users')
|
||||
|
||||
@property
|
||||
def valid_tokens(self):
|
||||
return self.tokens.filter(Q(expired=False) | Q(expires__isnull=False, expires__lt=timezone.now()))
|
||||
|
||||
def new_token(self, **kwargs):
|
||||
kwargs['secret'] = AccessToken.create_secret()
|
||||
return self.tokens.create(**kwargs)
|
||||
|
||||
def __str__(self):
|
||||
return self.user_url
|
||||
|
||||
|
||||
class AccessToken(models.Model):
|
||||
user = models.ForeignKey(AccessUser, on_delete=models.CASCADE, related_name='tokens',
|
||||
verbose_name=_('Access User'))
|
||||
author = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name=_('creator'), null=True, blank=True)
|
||||
permissions = models.CharField(_('permissions'), max_length=2048)
|
||||
description = models.CharField(_('description'), max_length=200)
|
||||
creation_date = models.DateTimeField(_('creation date'), auto_now_add=True)
|
||||
expires = models.DateTimeField(null=True, blank=True)
|
||||
expired = models.BooleanField(_('is expired'), default=False)
|
||||
activated = models.BooleanField(_('activated'), default=False)
|
||||
secret = models.CharField(_('activation secret'), max_length=42)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Access Token')
|
||||
verbose_name_plural = _('Access Tokens')
|
||||
|
||||
@cached_property
|
||||
def permissions_list(self):
|
||||
return self.permissions.split(';')
|
||||
|
||||
@cached_property
|
||||
def permissions_list_objects(self):
|
||||
return AreaLocation.objects.filter(name__in=self.permissions_list)
|
||||
|
||||
@cached_property
|
||||
def full_access(self):
|
||||
return ':full' in self.permissions_list
|
||||
|
||||
@property
|
||||
def is_expired(self):
|
||||
return self.expired or (self.expires is not None and self.expires < timezone.now())
|
||||
|
||||
@property
|
||||
def activation_url(self):
|
||||
if self.activated:
|
||||
return None
|
||||
return reverse('access.activate', kwargs={'pk': self.pk, 'secret': self.secret})
|
||||
|
||||
@property
|
||||
def qr_url(self):
|
||||
if self.activated:
|
||||
return None
|
||||
return reverse('access.qr', kwargs={'pk': self.pk, 'secret': self.secret})
|
||||
|
||||
@staticmethod
|
||||
def create_secret():
|
||||
return get_random_string(42, string.ascii_letters + string.digits)
|
||||
|
||||
def new_instance(self):
|
||||
with transaction.atomic():
|
||||
for instance in self.instances.filter(expires__isnull=True):
|
||||
instance.expires = timezone.now()+timedelta(seconds=5)
|
||||
instance.save()
|
||||
|
||||
self.instances.filter(expires__isnull=False, expires__lt=timezone.now()).delete()
|
||||
|
||||
secret = self.create_secret()
|
||||
self.instances.create(secret=secret)
|
||||
return '%d:%s' % (self.pk, secret)
|
||||
|
||||
def __str__(self):
|
||||
return '%s #%d' % (_('Access Token'), self.id)
|
||||
|
||||
|
||||
class AccessTokenInstance(models.Model):
|
||||
access_token = models.ForeignKey(AccessToken, on_delete=models.CASCADE, related_name='instances',
|
||||
verbose_name=_('Access Token'))
|
||||
secret = models.CharField(_('access secret'), max_length=42)
|
||||
creation_date = models.DateTimeField(_('creation date'), auto_now_add=True)
|
||||
expires = models.DateTimeField(null=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Access Token Instance')
|
||||
verbose_name_plural = _('Access Token Instances')
|
|
@ -1,44 +0,0 @@
|
|||
body, .btn {
|
||||
font-size:16px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
.login .container {
|
||||
max-width:420px;
|
||||
}
|
||||
.pager .middle {
|
||||
top:3px;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
|
||||
footer {
|
||||
text-align:center;
|
||||
}
|
||||
.languages {
|
||||
margin-bottom:0;
|
||||
height:2px;
|
||||
}
|
||||
.languages button {
|
||||
text-transform:none;
|
||||
font-weight:normal;
|
||||
margin-top:0 !important;
|
||||
border-width:0 !important;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
|
||||
.table .btn {
|
||||
font-size:14px;
|
||||
}
|
||||
.table tbody tr td {
|
||||
min-height: 29px;
|
||||
line-height:29px;
|
||||
}
|
||||
|
||||
.token img {
|
||||
width:100%;
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
{% extends 'access/base.html' %}
|
||||
|
||||
{% load bootstrap3 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block bodyclass %}login{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% if success %}
|
||||
<div class="alert alert-success">
|
||||
<strong>{% trans 'Your access token was installed on your device!' %}</strong>
|
||||
</div>
|
||||
{% else %}
|
||||
{% include 'access/fragment_token.html' %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -1,33 +0,0 @@
|
|||
{% load static %}
|
||||
{% load compress %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>c3nav control panel</title>
|
||||
{% compress css %}
|
||||
<link href="{% static 'bootstrap/css/bootstrap.css' %}" rel="stylesheet">
|
||||
<link href="{% static 'access/css/c3nav-access.css' %}" rel="stylesheet">
|
||||
{% endcompress %}
|
||||
</head>
|
||||
|
||||
<body class="{% block bodyclass %}{% endblock %}">
|
||||
|
||||
<div class="container" id="main">
|
||||
<h1>c3nav access control</h1>
|
||||
{% block nav %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
|
||||
{% include 'site/footer.html' %}
|
||||
</div>
|
||||
|
||||
{% compress js %}
|
||||
<script type="text/javascript" src="{% static 'jquery/jquery.js' %}"></script>
|
||||
{% endcompress %}
|
||||
</body>
|
||||
</html>
|
|
@ -1,17 +0,0 @@
|
|||
{% load i18n %}
|
||||
|
||||
<form action="{{ token.activation_url }}" method="POST">
|
||||
{% csrf_token %}
|
||||
<div class="token">
|
||||
<p>
|
||||
<img src="{{ token.qr_url }}">
|
||||
</p>
|
||||
<p><a href="{{ token.activation_url }}">{% trans 'Link to this token / in this QR code' %}</a></p>
|
||||
<p>
|
||||
<button type="submit" class="btn btn-default btn-block">{% trans 'Activate token on this device' %}</button>
|
||||
</p>
|
||||
<p>
|
||||
{% blocktrans %}This link QR Code / Link only works once. If you want access on multiple devices, you need multiple tokens.{% endblocktrans %}
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
|
@ -1,10 +0,0 @@
|
|||
{% extends 'access/base.html' %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block nav %}
|
||||
<ul class="nav nav-pills">
|
||||
<li class="active"><a href="{% url 'access.users' %}">{% trans 'Users' %}</a></li>
|
||||
<li><a href="{% url 'access.logout' %}">{% trans 'Log out' %}</a></li>
|
||||
</ul>
|
||||
{% endblock %}
|
|
@ -1,24 +0,0 @@
|
|||
{% extends 'access/base.html' %}
|
||||
|
||||
{% load bootstrap3 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block bodyclass %}login{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<fieldset>
|
||||
<legend>{% trans 'Log in' %}</legend>
|
||||
{% bootstrap_form form %}
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary btn-block btn-lg">{% trans 'Log in' %}</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
<p>{% blocktrans %}This is the non-public backend for creation of access tokens.{% endblocktrans %}</p>
|
||||
|
||||
<p><a class="btn btn-sm btn-default btn-block" href="{% url 'access.prove' %}">
|
||||
{% blocktrans %}Prove that you should have access{% endblocktrans %}
|
||||
</a></p>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -1,83 +0,0 @@
|
|||
|
||||
|
||||
|
||||
{% extends 'access/loggedin_base.html' %}
|
||||
|
||||
{% load bootstrap3 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<h3>Access Tokens <small>{{ user.user_url }}</small></h3>
|
||||
<p>{{ user.description }}</p>
|
||||
<form method="POST">
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<h4>{% trans 'Add new access token' %}</h4>
|
||||
<div class="row">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form new_token_form form_group_class='form-group col-md-3' %}
|
||||
<div class="form-group col-md-3">
|
||||
<label class="control-label"> </label>
|
||||
<button type="submit" name="create" class="btn btn-primary btn-block btn-sm">{% trans 'Add' %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans 'ID' %}</th>
|
||||
<th>{% trans 'Description' %}</th>
|
||||
<th>{% trans 'Author' %}</th>
|
||||
<th>{% trans 'Permissions' %}</th>
|
||||
<th>{% trans 'Creation Date' %}</th>
|
||||
<th>{% trans 'Expiration' %}</th>
|
||||
<th>{% trans 'Action' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for token in tokens %}
|
||||
<tr>
|
||||
<td>{{ token.id }}</td>
|
||||
<td>{{ token.description }}</td>
|
||||
<td>{% if token.author %}{{ token.author }}{% endif %}</td>
|
||||
<td>
|
||||
{% if token.full_access %}
|
||||
<span class="text-success">all</span>
|
||||
{% else %}
|
||||
{% for location in token.permissions_list_objects %}
|
||||
{{ location.title }},
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ token.creation_date|date:"SHORT_DATETIME_FORMAT" }}</td>
|
||||
<td>
|
||||
{% if token.is_expired %}
|
||||
{% trans 'expired' %}
|
||||
{% elif token.expires %}
|
||||
{{ token.expires|date:"SHORT_DATETIME_FORMAT" }}
|
||||
{% else %}
|
||||
{% trans 'never' %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if not token.is_expired %}
|
||||
<button class="btn btn-xs btn-danger" type="submit" name="expire" value="{{ token.id }}">{% trans 'Expire' %}</button>
|
||||
{% if not token.activated %}
|
||||
<a href="{% url 'access.user.token' user=user.id token=token.id %}" class="btn btn-xs btn-success" type="submit" name="activate" value="{{ token.id }}">{% trans 'Activate' %}</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
|
@ -1,13 +0,0 @@
|
|||
{% extends 'access/loggedin_base.html' %}
|
||||
|
||||
{% load bootstrap3 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-md-offset-4">
|
||||
{% include 'access/fragment_token.html' %}
|
||||
</div>
|
||||
</div>
|
||||
<p><a href="{% url 'access.user' pk=user.id %}">{% trans 'back to user' %}</a></p>
|
||||
{% endblock %}
|
|
@ -1,70 +0,0 @@
|
|||
{% extends 'access/loggedin_base.html' %}
|
||||
|
||||
{% load bootstrap3 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Users</h2>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans 'ID' %}</th>
|
||||
<th>{% trans 'Name' %}</th>
|
||||
<th>{% trans 'Author' %}</th>
|
||||
<th>{% trans 'Description' %}</th>
|
||||
<th>{% trans 'Active Tokens' %}</th>
|
||||
<th>{% trans 'Creation Date' %}</th>
|
||||
<th>{% trans 'Details' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for user in users %}
|
||||
<tr>
|
||||
<td>{{ user.id }}</td>
|
||||
<td>{{ user.user_url }}</td>
|
||||
<td>{% if user.author %}{{ user.author }}{% endif %}</td>
|
||||
<td>{{ user.description }}</td>
|
||||
<td>{{ user.valid_tokens.count }}</td>
|
||||
<td>{{ user.creation_date|date:"SHORT_DATETIME_FORMAT" }}</td>
|
||||
<td><a href="{% url 'access.user' pk=user.pk %}">{% trans 'Details' %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<ul class="pager">
|
||||
{% if users.has_previous %}
|
||||
<li class="previous"><a href="{% url 'acces.users' page=users.previous_page_number %}">« {% trans 'previous' %}</a></li>
|
||||
{% else %}
|
||||
<li class="previous disabled"><a href="#">« {% trans 'previous' %}</a></li>
|
||||
{% endif %}
|
||||
|
||||
<li class="middle">
|
||||
{% blocktrans with number=users.number total=users.paginator.num_pages %}Page {{ number }} of {{ total }}{% endblocktrans %}
|
||||
</li>
|
||||
|
||||
{% if users.has_next %}
|
||||
<li class="next"><a href="{% url 'acces.users' page=users.next_page_number %}">{% trans 'next' %} »</a></li>
|
||||
{% else %}
|
||||
<li class="next disabled"><a href="#">{% trans 'next' %} »</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<form method="POST">
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<h4>{% trans 'Add new access user' %}</h4>
|
||||
<div class="row">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form new_user_form form_group_class='form-group col-md-4' %}
|
||||
<div class="form-group col-md-4">
|
||||
<label class="control-label"> </label>
|
||||
<button type="submit" name="create" class="btn btn-primary btn-block btn-sm">{% trans 'Add new User' %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -1,16 +0,0 @@
|
|||
from django.conf.urls import url
|
||||
from django.contrib.auth import views as auth_views
|
||||
|
||||
from c3nav.access.views import activate_token, dashboard, show_user_token, token_qr, user_detail, user_list
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', dashboard, name='access.dashboard'),
|
||||
url(r'^activate/(?P<pk>[0-9]+):(?P<secret>[a-zA-Z0-9]+)/$', activate_token, name='access.activate'),
|
||||
url(r'^qr/(?P<pk>[0-9]+):(?P<secret>[a-zA-Z0-9]+).png$', token_qr, name='access.qr'),
|
||||
url(r'^users/$', user_list, name='access.users'),
|
||||
url(r'^users/(?P<page>[0-9]+)/$', user_list, name='access.users'),
|
||||
url(r'^user/(?P<pk>[0-9]+)/$', user_detail, name='access.user'),
|
||||
url(r'^user/(?P<user>[0-9]+)/(?P<token>[0-9]+)/$', show_user_token, name='access.user.token'),
|
||||
url(r'^login/$', auth_views.login, {'template_name': 'access/login.html'}, name='access.login'),
|
||||
url(r'^logout/$', auth_views.logout, name='access.logout'),
|
||||
]
|
|
@ -1,118 +0,0 @@
|
|||
import qrcode
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse
|
||||
|
||||
from c3nav.access.forms import AccessTokenForm, AccessUserForm
|
||||
from c3nav.access.models import AccessToken, AccessUser
|
||||
|
||||
|
||||
@login_required(login_url='/access/login/')
|
||||
def dashboard(request):
|
||||
return redirect('access.users')
|
||||
|
||||
|
||||
def activate_token(request, pk, secret):
|
||||
token = get_object_or_404(AccessToken, expired=False, activated=False, id=pk, secret=secret)
|
||||
if request.method == 'POST':
|
||||
request.c3nav_access = token
|
||||
request.c3nav_new_access = True
|
||||
return render(request, 'access/activate.html', context={
|
||||
'success': True,
|
||||
})
|
||||
|
||||
return render(request, 'access/activate.html', context={
|
||||
'token': token,
|
||||
})
|
||||
|
||||
|
||||
def token_qr(request, pk, secret):
|
||||
get_object_or_404(AccessToken, expired=False, activated=False, id=pk, secret=secret)
|
||||
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
||||
box_size=10,
|
||||
border=4,
|
||||
)
|
||||
qr.add_data(request.build_absolute_uri(reverse('access.activate', kwargs={'pk': pk, 'secret': secret})))
|
||||
qr.make(fit=True)
|
||||
|
||||
response = HttpResponse(content_type='image/png')
|
||||
qr.make_image().save(response, 'PNG')
|
||||
return response
|
||||
|
||||
|
||||
@login_required(login_url='/access/login/')
|
||||
def user_list(request, page=1):
|
||||
queryset = AccessUser.objects.all()
|
||||
paginator = Paginator(queryset, 25)
|
||||
|
||||
try:
|
||||
users = paginator.page(page)
|
||||
except PageNotAnInteger:
|
||||
return redirect('access.users')
|
||||
except EmptyPage:
|
||||
return redirect('access.users')
|
||||
|
||||
if request.method == 'POST':
|
||||
new_user_form = AccessUserForm(data=request.POST)
|
||||
if new_user_form.is_valid():
|
||||
user = new_user_form.instance
|
||||
user.author = request.user
|
||||
user.save()
|
||||
|
||||
return redirect('access.user', pk=user.id)
|
||||
else:
|
||||
new_user_form = AccessUserForm()
|
||||
|
||||
return render(request, 'access/users.html', {
|
||||
'users': users,
|
||||
'new_user_form': new_user_form,
|
||||
})
|
||||
|
||||
|
||||
@login_required(login_url='/access/login/')
|
||||
def user_detail(request, pk):
|
||||
user = get_object_or_404(AccessUser, id=pk)
|
||||
|
||||
tokens = user.tokens.order_by('-creation_date')
|
||||
|
||||
if request.method == 'POST':
|
||||
if 'expire' in request.POST:
|
||||
token = get_object_or_404(AccessToken, user=user, id=request.POST['expire'])
|
||||
token.expired = True
|
||||
token.save()
|
||||
return redirect('access.user', pk=user.id)
|
||||
|
||||
new_token_form = AccessTokenForm(data=request.POST, request=request)
|
||||
if new_token_form.is_valid():
|
||||
token = new_token_form.instance
|
||||
token.user = user
|
||||
token.secret = AccessToken.create_secret()
|
||||
|
||||
token.author = request.user
|
||||
token.save()
|
||||
|
||||
return redirect('access.user.token', user=user.id, token=token.id)
|
||||
else:
|
||||
new_token_form = AccessTokenForm(request=request)
|
||||
|
||||
return render(request, 'access/user.html', {
|
||||
'user': user,
|
||||
'new_token_form': new_token_form,
|
||||
'tokens': tokens,
|
||||
})
|
||||
|
||||
|
||||
@login_required(login_url='/access/login/')
|
||||
def show_user_token(request, user, token):
|
||||
user = get_object_or_404(AccessUser, id=user)
|
||||
token = get_object_or_404(AccessToken, user=user, id=token)
|
||||
|
||||
return render(request, 'access/user_token.html', {
|
||||
'user': user,
|
||||
'token': token,
|
||||
})
|
|
@ -3,7 +3,6 @@ from django.core.exceptions import PermissionDenied
|
|||
from django.http.response import Http404
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
|
||||
from c3nav.access.apply import can_access, filter_queryset_by_access
|
||||
from c3nav.mapdata.models import Section
|
||||
from c3nav.mapdata.models.base import EDITOR_FORM_MODELS
|
||||
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
from collections import OrderedDict
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
def get_default_include_avoid():
|
||||
include = set()
|
||||
avoid = set()
|
||||
|
||||
locations = list(AreaLocation.objects.exclude(routing_inclusion='default'))
|
||||
|
||||
for location in locations:
|
||||
if location.routing_inclusion != 'allow_avoid':
|
||||
avoid.add(location.location_id)
|
||||
|
||||
return include, avoid
|
||||
|
||||
|
||||
# Todo: add cache
|
||||
def get_includables_avoidables(request):
|
||||
includables = []
|
||||
avoidables = []
|
||||
|
||||
locations = list(AreaLocation.objects.exclude(routing_inclusion='default'))
|
||||
|
||||
if request.c3nav_full_access:
|
||||
includables.append((':nonpublic', _('non-public areas')))
|
||||
avoidables.append((':public', _('public areas')))
|
||||
|
||||
for location in locations:
|
||||
item = (location.location_id, location.title)
|
||||
|
||||
if location.location_id not in request.c3nav_access_list and not request.c3nav_full_access:
|
||||
if location.routing_inclusion == 'needs_permission':
|
||||
continue
|
||||
|
||||
if location.routing_inclusion == 'allow_avoid':
|
||||
avoidables.append(item)
|
||||
else:
|
||||
includables.append(item)
|
||||
|
||||
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)
|
||||
avoid_input = set(avoid_input) & set(avoidable)
|
||||
|
||||
default_include, default_avoid = get_default_include_avoid()
|
||||
|
||||
include = set(default_include) | include_input
|
||||
avoid = set(default_avoid) - include_input | avoid_input
|
||||
|
||||
return ':nonpublic' in includable, include, avoid
|
|
@ -1,33 +0,0 @@
|
|||
import os
|
||||
import pickle
|
||||
from contextlib import contextmanager
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils import timezone
|
||||
|
||||
last_mapdata_update_filename = os.path.join(settings.DATA_DIR, 'last_mapdata_update')
|
||||
last_mapdata_update_decorator_depth = 0
|
||||
|
||||
|
||||
def get_last_mapdata_update(default_now=False):
|
||||
try:
|
||||
with open(last_mapdata_update_filename, 'rb') as f:
|
||||
return pickle.load(f)
|
||||
except:
|
||||
return timezone.now() if default_now else None
|
||||
|
||||
|
||||
@contextmanager
|
||||
def set_last_mapdata_update():
|
||||
global last_mapdata_update_decorator_depth
|
||||
if last_mapdata_update_decorator_depth == 0:
|
||||
try:
|
||||
os.remove(last_mapdata_update_filename)
|
||||
except:
|
||||
pass
|
||||
last_mapdata_update_decorator_depth += 1
|
||||
yield
|
||||
last_mapdata_update_decorator_depth -= 1
|
||||
if last_mapdata_update_decorator_depth == 0:
|
||||
with open(last_mapdata_update_filename, 'wb') as f:
|
||||
pickle.dump(timezone.now(), f)
|
|
@ -1,97 +0,0 @@
|
|||
from calendar import timegm
|
||||
from collections import OrderedDict
|
||||
from functools import wraps
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.db.models import Q
|
||||
from django.utils.http import http_date
|
||||
from rest_framework.response import Response as APIResponse
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from c3nav.mapdata.lastupdate import get_last_mapdata_update
|
||||
|
||||
|
||||
def cache_result(cache_key, timeout=900):
|
||||
def decorator(func):
|
||||
@wraps(func)
|
||||
def inner(*args, **kwargs):
|
||||
last_update = get_last_mapdata_update()
|
||||
if last_update is None:
|
||||
return func(*args, **kwargs)
|
||||
|
||||
result = cache.get(cache_key)
|
||||
if not result:
|
||||
result = func(*args, **kwargs)
|
||||
cache.set(cache_key, result, timeout)
|
||||
return result
|
||||
return inner
|
||||
return decorator
|
||||
|
||||
|
||||
def cache_mapdata_api_response(timeout=900):
|
||||
def decorator(func):
|
||||
@wraps(func)
|
||||
def inner(self, request, *args, add_cache_key=None, **kwargs):
|
||||
last_update = get_last_mapdata_update()
|
||||
if last_update is None:
|
||||
return func(self, request, *args, **kwargs)
|
||||
|
||||
cache_key = '__'.join((
|
||||
'c3nav__mapdata__api',
|
||||
last_update.isoformat(),
|
||||
add_cache_key if add_cache_key is not None else '',
|
||||
request.accepted_renderer.format if isinstance(self, APIView) else '',
|
||||
request.path,
|
||||
))
|
||||
|
||||
response = cache.get(cache_key)
|
||||
if not response:
|
||||
response = func(self, request, *args, **kwargs)
|
||||
response['Last-Modifed'] = http_date(timegm(last_update.utctimetuple()))
|
||||
if isinstance(response, APIResponse):
|
||||
response = self.finalize_response(request, response, *args, **kwargs)
|
||||
response.render()
|
||||
if response.status_code < 400:
|
||||
cache.set(cache_key, response, timeout)
|
||||
|
||||
return response
|
||||
return inner
|
||||
return decorator
|
||||
|
||||
|
||||
class CachedReadOnlyViewSetMixin():
|
||||
def _get_add_cache_key(self, request, add_cache_key=''):
|
||||
cache_key = add_cache_key
|
||||
return cache_key
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
kwargs['add_cache_key'] = self._get_add_cache_key(request, kwargs.get('add_cache_key', ''))
|
||||
return self._list(request, *args, **kwargs)
|
||||
|
||||
@cache_mapdata_api_response()
|
||||
def _list(self, request, *args, **kwargs):
|
||||
return super().list(request, *args, **kwargs)
|
||||
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
kwargs['add_cache_key'] = self._get_add_cache_key(request, kwargs.get('add_cache_key', ''))
|
||||
return self._retrieve(request, *args, **kwargs)
|
||||
|
||||
@cache_mapdata_api_response()
|
||||
def _retrieve(self, request, *args, **kwargs):
|
||||
return super().retrieve(request, *args, **kwargs)
|
||||
|
||||
|
||||
@cache_result('c3nav__mapdata__sections')
|
||||
def get_sections_cached():
|
||||
from c3nav.mapdata.models.section import Section
|
||||
return OrderedDict((section.id, section) for section in Section.objects.all())
|
||||
|
||||
|
||||
@cache_result('c3nav__mapdata__bssids')
|
||||
def get_bssid_areas_cached():
|
||||
from c3nav.mapdata.models import AreaLocation
|
||||
bssids = {}
|
||||
for area in AreaLocation.objects.filter(~Q(bssids='')):
|
||||
for bssid in area.bssids.split('\n'):
|
||||
bssids[bssid.strip()] = area.name
|
||||
return bssids
|
|
@ -1,37 +1,3 @@
|
|||
import os
|
||||
|
||||
from django.conf import settings
|
||||
from shapely.geometry import box
|
||||
from shapely.ops import cascaded_union
|
||||
|
||||
from c3nav.mapdata.utils.cache import cache_result
|
||||
|
||||
|
||||
@cache_result('c3nav__mapdata__dimensions')
|
||||
def get_dimensions():
|
||||
# todo calculate this
|
||||
return (400, 240)
|
||||
|
||||
|
||||
@cache_result('c3nav__mapdata__render_dimensions')
|
||||
def get_render_dimensions():
|
||||
width, height = get_dimensions()
|
||||
return (width * settings.RENDER_SCALE, height * settings.RENDER_SCALE)
|
||||
|
||||
|
||||
def get_render_path(filetype, level, mode, public):
|
||||
return os.path.join(settings.RENDER_ROOT,
|
||||
'%s%s-level-%s.%s' % (('public-' if public else ''), mode, level, filetype))
|
||||
|
||||
|
||||
def get_public_private_area(level):
|
||||
from c3nav.mapdata.models import AreaLocation
|
||||
|
||||
width, height = get_dimensions()
|
||||
everything = box(0, 0, width, height)
|
||||
needs_permission = [location.geometry
|
||||
for location in AreaLocation.objects.filter(level=level,
|
||||
routing_inclusion='needs_permission')]
|
||||
public_area = level.public_geometries.areas_and_doors.difference(cascaded_union(needs_permission))
|
||||
private_area = everything.difference(public_area)
|
||||
return public_area, private_area
|
||||
|
|
|
@ -138,7 +138,6 @@ INSTALLED_APPS = [
|
|||
'c3nav.api',
|
||||
'rest_framework',
|
||||
'c3nav.mapdata',
|
||||
'c3nav.access',
|
||||
'c3nav.routing',
|
||||
'c3nav.site',
|
||||
'c3nav.editor',
|
||||
|
@ -154,7 +153,6 @@ MIDDLEWARE = [
|
|||
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'c3nav.access.middleware.AccessTokenMiddleware',
|
||||
]
|
||||
|
||||
try:
|
||||
|
|
|
@ -7,14 +7,7 @@ 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.lastupdate import get_last_mapdata_update
|
||||
from c3nav.mapdata.models.section import Section
|
||||
from c3nav.mapdata.utils.cache import get_sections_cached
|
||||
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
|
||||
|
||||
ctype_mapping = {
|
||||
'yes': ('up', 'down'),
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
from django.conf.urls import include, url
|
||||
from django.contrib import admin
|
||||
|
||||
import c3nav.access.urls
|
||||
import c3nav.api.urls
|
||||
import c3nav.editor.urls
|
||||
import c3nav.site.urls
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^access/', include(c3nav.access.urls)),
|
||||
url(r'^editor/', include(c3nav.editor.urls)),
|
||||
url(r'^api/', include(c3nav.api.urls, namespace='api')),
|
||||
url(r'^admin/', admin.site.urls),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue