diff --git a/src/c3nav/access/__init__.py b/src/c3nav/access/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/c3nav/access/admin.py b/src/c3nav/access/admin.py deleted file mode 100644 index 48d993be..00000000 --- a/src/c3nav/access/admin.py +++ /dev/null @@ -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 diff --git a/src/c3nav/access/apply.py b/src/c3nav/access/apply.py deleted file mode 100644 index 7db0bb87..00000000 --- a/src/c3nav/access/apply.py +++ /dev/null @@ -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 diff --git a/src/c3nav/access/forms.py b/src/c3nav/access/forms.py deleted file mode 100644 index cfbba04a..00000000 --- a/src/c3nav/access/forms.py +++ /dev/null @@ -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'] diff --git a/src/c3nav/access/middleware.py b/src/c3nav/access/middleware.py deleted file mode 100644 index 81b09440..00000000 --- a/src/c3nav/access/middleware.py +++ /dev/null @@ -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 diff --git a/src/c3nav/access/migrations/0001_initial.py b/src/c3nav/access/migrations/0001_initial.py deleted file mode 100644 index 13d446ea..00000000 --- a/src/c3nav/access/migrations/0001_initial.py +++ /dev/null @@ -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'), - ), - ] diff --git a/src/c3nav/access/migrations/0002_auto_20161221_1739.py b/src/c3nav/access/migrations/0002_auto_20161221_1739.py deleted file mode 100644 index 49f42e84..00000000 --- a/src/c3nav/access/migrations/0002_auto_20161221_1739.py +++ /dev/null @@ -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, - ), - ] diff --git a/src/c3nav/access/migrations/0003_auto_20161221_2311.py b/src/c3nav/access/migrations/0003_auto_20161221_2311.py deleted file mode 100644 index 7815884d..00000000 --- a/src/c3nav/access/migrations/0003_auto_20161221_2311.py +++ /dev/null @@ -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, - ), - ] diff --git a/src/c3nav/access/migrations/0004_auto_20161223_2225.py b/src/c3nav/access/migrations/0004_auto_20161223_2225.py deleted file mode 100644 index 808fe77d..00000000 --- a/src/c3nav/access/migrations/0004_auto_20161223_2225.py +++ /dev/null @@ -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'}, - ), - ] diff --git a/src/c3nav/access/migrations/0005_auto_20161225_1018.py b/src/c3nav/access/migrations/0005_auto_20161225_1018.py deleted file mode 100644 index 5c1c46f3..00000000 --- a/src/c3nav/access/migrations/0005_auto_20161225_1018.py +++ /dev/null @@ -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'), - ), - ] diff --git a/src/c3nav/access/migrations/__init__.py b/src/c3nav/access/migrations/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/c3nav/access/models.py b/src/c3nav/access/models.py deleted file mode 100644 index 4fed824d..00000000 --- a/src/c3nav/access/models.py +++ /dev/null @@ -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') diff --git a/src/c3nav/access/static/access/css/c3nav-access.css b/src/c3nav/access/static/access/css/c3nav-access.css deleted file mode 100644 index 04c01547..00000000 --- a/src/c3nav/access/static/access/css/c3nav-access.css +++ /dev/null @@ -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%; -} diff --git a/src/c3nav/access/templates/access/activate.html b/src/c3nav/access/templates/access/activate.html deleted file mode 100644 index 0f7b24e8..00000000 --- a/src/c3nav/access/templates/access/activate.html +++ /dev/null @@ -1,16 +0,0 @@ -{% extends 'access/base.html' %} - -{% load bootstrap3 %} -{% load i18n %} - -{% block bodyclass %}login{% endblock %} - -{% block content %} - {% if success %} -
{{ user.description }}
- - - -{% endblock %} diff --git a/src/c3nav/access/templates/access/user_token.html b/src/c3nav/access/templates/access/user_token.html deleted file mode 100644 index 60d35cd9..00000000 --- a/src/c3nav/access/templates/access/user_token.html +++ /dev/null @@ -1,13 +0,0 @@ -{% extends 'access/loggedin_base.html' %} - -{% load bootstrap3 %} -{% load i18n %} - -{% block content %} -{% trans 'ID' %} | -{% trans 'Name' %} | -{% trans 'Author' %} | -{% trans 'Description' %} | -{% trans 'Active Tokens' %} | -{% trans 'Creation Date' %} | -{% trans 'Details' %} | -
---|---|---|---|---|---|---|
{{ user.id }} | -{{ user.user_url }} | -{% if user.author %}{{ user.author }}{% endif %} | -{{ user.description }} | -{{ user.valid_tokens.count }} | -{{ user.creation_date|date:"SHORT_DATETIME_FORMAT" }} | -{% trans 'Details' %} | -