From 51a30d637fecf263c3d17356671acba12789df27 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Thu, 28 Sep 2017 09:22:56 +0300 Subject: [PATCH 1/7] WIP webapp permissions --- members/migrations/0018_auto_20170927_1918.py | 27 ++++++++++ members/models.py | 11 ++++ webapp/admin.py | 4 +- webapp/management/commands/initialize.py | 52 ++++++++++++++++++- 4 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 members/migrations/0018_auto_20170927_1918.py diff --git a/members/migrations/0018_auto_20170927_1918.py b/members/migrations/0018_auto_20170927_1918.py new file mode 100644 index 0000000..43f01be --- /dev/null +++ b/members/migrations/0018_auto_20170927_1918.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11 on 2017-09-27 16:18 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('members', '0017_auto_20170926_1316'), + ] + + operations = [ + migrations.AlterModelOptions( + name='member', + options={'permissions': (('check_by_email', 'Can check if user exists by email'), ('read', 'Can see member in list'))}, + ), + migrations.AlterModelOptions( + name='payment', + options={'permissions': (('read', 'Can see payment in list'),)}, + ), + migrations.AlterModelOptions( + name='request', + options={'permissions': (('read', 'Can see member application in list'),)}, + ), + ] diff --git a/members/models.py b/members/models.py index 7e4d7ea..2a0337d 100644 --- a/members/models.py +++ b/members/models.py @@ -43,6 +43,11 @@ class BaseMember(models.Model): class Request(BaseMember): """Member request model represents one member request.""" + class Meta: + permissions = ( + ('read', 'Can see member application in list'), + ) + submitted = models.DateTimeField(_('Submitted'), default=timezone.now) def to_member(self): @@ -55,6 +60,11 @@ class Request(BaseMember): class Payment(models.Model): """Payment model representing one payment event.""" + class Meta: + permissions = ( + ('read', 'Can see payment in list'), + ) + date = models.DateTimeField(_('Date'), default=timezone.now) source = models.CharField(_('Source'), choices=[ ('AYY', _('AYY')), @@ -88,6 +98,7 @@ class Member(BaseMember): class Meta: permissions = ( ('check_by_email', 'Can check if user exists by email'), + ('read', 'Can see member in list'), ) def last_paid(self): diff --git a/webapp/admin.py b/webapp/admin.py index 03faf69..b0b4349 100644 --- a/webapp/admin.py +++ b/webapp/admin.py @@ -6,10 +6,12 @@ from webapp.models import Feed, Tag, BaseFeed, Event from webapp.models import KaehmyForm, KaehmyMessage from webapp.models import CustomKaehmyRole, PresetKaehmyRole from modeltranslation.admin import TranslationAdmin - +from django.contrib.auth.models import Permission # this is needed so that the models get registered for translation import webapp.translation +admin.site.register(Permission) + admin.site.register(Feed, TranslationAdmin) admin.site.register(Tag, TranslationAdmin) admin.site.register(Event, TranslationAdmin) diff --git a/webapp/management/commands/initialize.py b/webapp/management/commands/initialize.py index 650a175..d7ab9da 100644 --- a/webapp/management/commands/initialize.py +++ b/webapp/management/commands/initialize.py @@ -9,12 +9,56 @@ class Command(BaseCommand): This command MUST do nothing if already run. ''' + def create_infoscreen_moderator(self): + self.stdout.write("Creating infoscreen moderator group") + infoscreen_group, created = Group.objects.get_or_create(name="infoscreen moderators") + if not created: + self.stdout.write('The group "infoscreen moderators" already existed ' + 'and was not therefore created') + + cts = ContentType.objects.filter(app_label='infoscreen') + permissions = Permission.objects.filter(content_type__in=cts) + infoscreen_group.permissions.add(*permissions) + + def create_member_register_viewer(self): + self.stdout.write("Creating member register viewer group") + viewers_group, created = Group.objects.get_or_create(name="member register viewers") + if not created: + self.stdout.write('The group "member register viewers" already existed ' + 'and was not therefore created') + + cts = ContentType.objects.filter(app_label='members') + members_permissions = Permission.objects.filter(content_type__in=cts, codename__contains='read') + + viewers_group.permissions.add(*members_permissions) + + def create_member_register_administrator(self): + self.stdout.write("Creating member register administrator group") + admins_group, created = Group.objects.get_or_create(name="member register administrators") + if not created: + self.stdout.write('The group "member register administrators" already existed ' + 'and was not therefore created') + + cts = ContentType.objects.filter(app_label='members') + permissions = Permission.objects.filter(content_type__in=cts) + admins_group.permissions.add(*permissions) + + def create_official(self): + self.stdout.write("Creating official group") + officials_group, created = Group.objects.get_or_create(name="officials") + if not created: + self.stdout.write('The group "officials" already existed ' + 'and was not therefore created') + + feed_permissions = Permission.objects.filter(codename__contains='feed') + officials_group.permissions.add(*feed_permissions) + def handle(self, *args, **options): self.stdout.write("Creating sikadmin group") sikadmin_group, created = Group.objects.get_or_create(name="sikadmin") if not created: - self.stdout.write('The group "sikadmin" already existed' + self.stdout.write('The group "sikadmin" already existed ' 'and was not therefore created') self.stdout.write("Creating sikadmin permission") @@ -27,7 +71,7 @@ class Command(BaseCommand): name='SIK Admin') if not created: - self.stdout.write('The permission "sikadmin" already existed' + self.stdout.write('The permission "sikadmin" already existed ' 'and was not therefore created') self.stdout.write("Giving sikadmin group permission to sikadmin") @@ -36,4 +80,8 @@ class Command(BaseCommand): else: sikadmin_group.permissions.add(sikadmin_permission) + self.create_infoscreen_moderator() + self.create_member_register_viewer() + self.create_member_register_administrator() + self.create_official() self.stdout.write("Initialization successful") From 75d9fb1dbb02aebea379a40ca13ce6ef079aee2b Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Thu, 28 Sep 2017 18:46:51 +0300 Subject: [PATCH 2/7] Create new permission groups and fix member register permissions --- members/migrations/0018_auto_20170927_1918.py | 6 ++-- members/models.py | 6 ++-- members/views/applications.py | 10 +++--- members/views/members.py | 18 +++++----- members/views/payments.py | 14 ++++---- members/views/utils.py | 6 ++-- webapp/management/commands/initialize.py | 34 ++++--------------- 7 files changed, 37 insertions(+), 57 deletions(-) diff --git a/members/migrations/0018_auto_20170927_1918.py b/members/migrations/0018_auto_20170927_1918.py index 43f01be..0c601a9 100644 --- a/members/migrations/0018_auto_20170927_1918.py +++ b/members/migrations/0018_auto_20170927_1918.py @@ -14,14 +14,14 @@ class Migration(migrations.Migration): operations = [ migrations.AlterModelOptions( name='member', - options={'permissions': (('check_by_email', 'Can check if user exists by email'), ('read', 'Can see member in list'))}, + options={'permissions': (('check_by_email', 'Can check if user exists by email'), ('read_member', 'Can see member in list'))}, ), migrations.AlterModelOptions( name='payment', - options={'permissions': (('read', 'Can see payment in list'),)}, + options={'permissions': (('read_payment', 'Can see payment in list'),)}, ), migrations.AlterModelOptions( name='request', - options={'permissions': (('read', 'Can see member application in list'),)}, + options={'permissions': (('read_application', 'Can see member application in list'),)}, ), ] diff --git a/members/models.py b/members/models.py index 2a0337d..8f36dbc 100644 --- a/members/models.py +++ b/members/models.py @@ -45,7 +45,7 @@ class Request(BaseMember): class Meta: permissions = ( - ('read', 'Can see member application in list'), + ('read_application', 'Can see member application in list'), ) submitted = models.DateTimeField(_('Submitted'), default=timezone.now) @@ -62,7 +62,7 @@ class Payment(models.Model): class Meta: permissions = ( - ('read', 'Can see payment in list'), + ('read_payment', 'Can see payment in list'), ) date = models.DateTimeField(_('Date'), default=timezone.now) @@ -98,7 +98,7 @@ class Member(BaseMember): class Meta: permissions = ( ('check_by_email', 'Can check if user exists by email'), - ('read', 'Can see member in list'), + ('read_member', 'Can see member in list'), ) def last_paid(self): diff --git a/members/views/applications.py b/members/views/applications.py index 9207fd7..86e100e 100644 --- a/members/views/applications.py +++ b/members/views/applications.py @@ -18,7 +18,7 @@ from members.forms import ApplicationForm @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.read_application', login_url='/login', raise_exception=True) def application_list(request, *args, **kwargs): """List member applications not yet processed.""" applications = Request.objects.all() @@ -40,7 +40,7 @@ def application_list(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.change_request', login_url='/login', raise_exception=True) def application_edit(request, *args, **kwargs): """Edit member request information.""" i = kwargs.pop('index', None) @@ -58,7 +58,7 @@ def application_edit(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.add_member', login_url='/login', raise_exception=True) def application_accept(request, *args, **kwargs): """Accept application.""" form = ApplicationForm(request.POST) @@ -86,7 +86,7 @@ def application_accept(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.delete_request', login_url='/login', raise_exception=True) def application_delete(request, *args, **kwargs): """Delete member application.""" try: @@ -114,7 +114,7 @@ def application_delete(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.delete_request', login_url='/login', raise_exception=True) def application_delete_confirm(request, *args, **kwargs): """Confirm application deletion.""" i = kwargs.pop('index', None) diff --git a/members/views/members.py b/members/views/members.py index 16467a9..0b7c9db 100644 --- a/members/views/members.py +++ b/members/views/members.py @@ -27,7 +27,7 @@ from members.views.utils import * @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.read_member', login_url='/login', raise_exception=True) def member_list(request, *args, **kwargs): """Render members list.""" search = request.GET.get('q', None) @@ -53,7 +53,7 @@ def member_list(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.add_member', login_url='/login', raise_exception=True) def member_add(request, *args, **kwargs): """Render add member page.""" form = MemberForm() @@ -62,7 +62,7 @@ def member_add(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.delete_member', login_url='/login', raise_exception=True) def member_delete_confirm(request, *args, **kwargs): """Render member deletion confirmation page.""" i = kwargs.pop('index', None) @@ -78,7 +78,7 @@ def member_delete_confirm(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.add_member', login_url='/login', raise_exception=True) def member_add_many(request, *args, **kwargs): """Render add multiple members page.""" return render(request, 'member_add_many.html', {}) @@ -86,7 +86,7 @@ def member_add_many(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.add_member', login_url='/login', raise_exception=True) def add_many_confirm(request, *args, **kwargs): models = request.session['models'] @@ -108,7 +108,7 @@ def add_many_confirm(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.add_member', login_url='/login', raise_exception=True) def member_submit(request, *args, **kwargs): """Add member based on data gained from member form.""" form = MemberForm(request.POST) @@ -128,7 +128,7 @@ def member_submit(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.change_member', login_url='/login', raise_exception=True) def member_update(request, *args, **kwargs): """Update member information.""" form = MemberForm(request.POST) @@ -154,7 +154,7 @@ def member_update(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.delete_member', login_url='/login', raise_exception=True) def member_delete(request, *args, **kwargs): """Delete member.""" try: @@ -181,7 +181,7 @@ def member_delete(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.change_member', login_url='/login', raise_exception=True) def member_edit(request, *args, **kwargs): """Edit member information.""" i = kwargs.pop('index', None) diff --git a/members/views/payments.py b/members/views/payments.py index b5f22af..988fcbe 100644 --- a/members/views/payments.py +++ b/members/views/payments.py @@ -18,7 +18,7 @@ from members.forms import PaymentForm @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.read_payment', login_url='/login', raise_exception=True) def payment_list(request, *args, **kwargs): """Render list of payments.""" search = request.GET.get('q', None) @@ -45,7 +45,7 @@ def payment_list(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.add_payment', login_url='/login', raise_exception=True) def payment_add(request, *args, **kwargs): """Render add payment form.""" form = PaymentForm() @@ -54,7 +54,7 @@ def payment_add(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.add_payment', login_url='/login', raise_exception=True) def payment_submit(request, *args, **kwargs): """Submit payment.""" form = PaymentForm(request.POST) @@ -75,7 +75,7 @@ def payment_submit(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.change_payment', login_url='/login', raise_exception=True) def payment_edit(request, *args, **kwargs): """Edit payment.""" i = kwargs.pop('index', None) @@ -93,7 +93,7 @@ def payment_edit(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.delete_payment', login_url='/login', raise_exception=True) def payment_delete_confirm(request, *args, **kwargs): """Render payment delete confirmation page.""" i = kwargs.pop('index', None) @@ -111,7 +111,7 @@ def payment_delete_confirm(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.delete_payment', login_url='/login', raise_exception=True) def payment_delete(request, *args, **kwargs): """Delete payment.""" try: @@ -139,7 +139,7 @@ def payment_delete(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.change_payment', login_url='/login', raise_exception=True) def payment_update(request, *args, **kwargs): """Update payment information.""" form = PaymentForm(request.POST) diff --git a/members/views/utils.py b/members/views/utils.py index 3463914..acf2d04 100644 --- a/members/views/utils.py +++ b/members/views/utils.py @@ -93,7 +93,7 @@ def convert_table_to_html(table, request): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.change_member', login_url='/login', raise_exception=True) def settings_page(request, *args, **kwargs): """Render member app settings page.""" return render(request, 'settings.html', {}) @@ -101,7 +101,7 @@ def settings_page(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.change_member', login_url='/login') +@permission_required(['members.change_member', 'members.change_payment'], login_url='/login', raise_exception=True) def import_csv(request, *args, **kwargs): """Get csv data imported to page and create members based on that.""" try: @@ -145,7 +145,7 @@ def import_csv(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.change_member', login_url='/login') +@permission_required('members.read_member', login_url='/login', raise_exception=True) def export_csv(request, *args, **kwargs): """Export members as csv.""" response = HttpResponse() diff --git a/webapp/management/commands/initialize.py b/webapp/management/commands/initialize.py index d7ab9da..31073e3 100644 --- a/webapp/management/commands/initialize.py +++ b/webapp/management/commands/initialize.py @@ -50,36 +50,16 @@ class Command(BaseCommand): self.stdout.write('The group "officials" already existed ' 'and was not therefore created') - feed_permissions = Permission.objects.filter(codename__contains='feed') + cts = ContentType.objects.filter(app_label='webapp') + feed_permissions = Permission.objects.filter(content_type__in=cts, codename__contains='feed') + event_permissions = Permission.objects.filter(content_type__in=cts, codename__contains='event') + registration_permissions = Permission.objects.filter(content_type__in=cts, codename__contains='registration') + officials_group.permissions.add(*feed_permissions) + officials_group.permissions.add(*event_permissions) + officials_group.permissions.add(*registration_permissions) def handle(self, *args, **options): - - self.stdout.write("Creating sikadmin group") - sikadmin_group, created = Group.objects.get_or_create(name="sikadmin") - if not created: - self.stdout.write('The group "sikadmin" already existed ' - 'and was not therefore created') - - self.stdout.write("Creating sikadmin permission") - - # TODO Use some sikadmin native model when such exists - group_ctype = ContentType.objects.get_for_model(Group) - sikadmin_permission, created = Permission.objects.get_or_create( - codename='sikadmin', - content_type=group_ctype, - name='SIK Admin') - - if not created: - self.stdout.write('The permission "sikadmin" already existed ' - 'and was not therefore created') - - self.stdout.write("Giving sikadmin group permission to sikadmin") - if sikadmin_group.permissions.filter(id=sikadmin_permission.id).exists(): - self.stdout.write("Permission already existed. skipping...") - else: - sikadmin_group.permissions.add(sikadmin_permission) - self.create_infoscreen_moderator() self.create_member_register_viewer() self.create_member_register_administrator() From 69d26deef92b7f353794b37fcf90a2894a98c7cf Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Thu, 28 Sep 2017 19:57:50 +0300 Subject: [PATCH 3/7] Rework infoscreen permissions --- infoscreen/views/__init__.py | 2 + infoscreen/{views.py => views/admin_views.py} | 118 +++--------------- infoscreen/views/public_views.py | 101 +++++++++++++++ 3 files changed, 122 insertions(+), 99 deletions(-) create mode 100644 infoscreen/views/__init__.py rename infoscreen/{views.py => views/admin_views.py} (63%) create mode 100644 infoscreen/views/public_views.py diff --git a/infoscreen/views/__init__.py b/infoscreen/views/__init__.py new file mode 100644 index 0000000..941a415 --- /dev/null +++ b/infoscreen/views/__init__.py @@ -0,0 +1,2 @@ +from infoscreen.views.admin_views import * +from infoscreen.views.public_views import * diff --git a/infoscreen/views.py b/infoscreen/views/admin_views.py similarity index 63% rename from infoscreen/views.py rename to infoscreen/views/admin_views.py index 0636f3d..152859a 100644 --- a/infoscreen/views.py +++ b/infoscreen/views/admin_views.py @@ -5,7 +5,7 @@ from django.http import HttpResponse, HttpResponseBadRequest from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.http import require_http_methods from django.contrib.contenttypes.models import ContentType -from django.contrib.auth.decorators import permission_required +from django.contrib.auth.decorators import permission_required, login_required from infoscreen.models import UploadFileForm import sikweb.settings as settings @@ -23,53 +23,22 @@ from infoscreen.models import ImageUploadForm from infoscreen.models import HSLDataModel from infoscreen.models import ApyInfoItem from infoscreen.models import VideoInfoItem -from infoscreen.hsl_fetcher import HSLFetcher -def index(request, idx, *args, **kwargs): - """Render infoscreen index page.""" - return render(request, 'infoscreen_index.html', {'rotation': idx}) - - -@permission_required('infoscreen.change_infoinstance', login_url='/login') +@login_required(login_url='/login') +@permission_required('infoscreen.change_infoinstance', raise_exception=True) def admin(request, *args, **kwargs): """Render infoscreen admin page.""" return render(request, 'infoscreen_admin.html', {}) -def default(request, *args, **kwargs): - """Try getting first rotation item.""" - try: - first = Rotation.objects.all()[0].id - except: - first = 0 - return index(request, first, *args, **kwargs) - - -def get_apy_json(request): - """Render APY diilikone page.""" - return HttpResponse( - requests.get("https://api-diilikone.apy.fi/deals/top-groups").text) - - -@require_http_methods(["GET"]) -def rotation(request, idx, *args, **kwargs): - """Get rotation.""" - try: - rotation = Rotation.objects.get(pk=idx) - except Rotation.DoesNotExist: - resp = HttpResponse('{"error": "Rotation not found"}') - resp.status_code = 404 - return resp - - return HttpResponse(json.dumps(rotation.get_dict())) - - def create_item_generator(model): """Create Infoscreen item generator.""" + @ensure_csrf_cookie @require_http_methods(["POST"]) - @permission_required('infoscreen.change_infoinstance', login_url='/login') + @login_required(login_url='/login') + @permission_required('infoscreen.add_infoinstance', raise_exception=True) def create_item(request, *args, **kwargs): try: data = json.loads(request.body.decode("utf-8")) @@ -87,9 +56,11 @@ def create_item_generator(model): def delete_item_generator(model): """Delete Infoscreen item generator.""" + @ensure_csrf_cookie @require_http_methods(["DELETE"]) - @permission_required('infoscreen.change_infoinstance', login_url='/login') + @login_required(login_url='/login') + @permission_required('infoscreen.delete_infoinstance', raise_exception=True) def delete_item(request, *args, **kwargs): idx = kwargs.pop("idx", 0) try: @@ -110,7 +81,8 @@ def delete_item_generator(model): # due to model structure this is little complicated @ensure_csrf_cookie -@permission_required('infoscreen.change_infoinstance', login_url='/login') +@login_required(login_url='/login') +@permission_required('infoscreen.delete_infoinstance', raise_exception=True) @require_http_methods(["DELETE"]) def delete_info_item(request, *args, **kwargs): """Delete info item.""" @@ -132,39 +104,10 @@ def delete_info_item(request, *args, **kwargs): return resp -@require_http_methods(["GET"]) -def rotations(request, *args, **kwargs): - """Return rotation lists.""" - rotations = list(map(lambda r: r.get_list(), Rotation.objects.all())) - return HttpResponse(json.dumps(rotations)) - - -@require_http_methods(["GET"]) -def info_types(request, *args, **kwargs): - """Return info item types.""" - types = [] - classes = InfoItem.get_subclasses() - for c in classes: - types.append({ - "name": c.display_name, - "create_template_url": c.get_create_template_url(), - }) - return HttpResponse(json.dumps(types)) - - -def info_items(request, *args, **kwargs): - """Return Infoscreen items.""" - items = [] - classes = InfoItem.get_subclasses() - for c in classes: - for i in c.objects.all(): - items.append(i.get_dict()) - return HttpResponse(json.dumps(items)) - - @require_http_methods(["POST"]) @ensure_csrf_cookie -@permission_required('infoscreen.change_infoinstance', login_url='/login') +@login_required(login_url='/login') +@permission_required('infoscreen.add_infoinstance', raise_exception=True) def create_image_item(request, *args, **kwargs): """Create image Infoscreen item.""" form = ImageUploadForm(request.POST, request.FILES) @@ -180,7 +123,8 @@ def create_image_item(request, *args, **kwargs): @require_http_methods(["POST"]) @ensure_csrf_cookie -@permission_required('infoscreen.change_infoinstance', login_url='/login') +@login_required(login_url='/login') +@permission_required('infoscreen.add_infoinstance', raise_exception=True) def create_video_item(request, *args, **kwargs): """Create video Infoscreen item.""" form = UploadFileForm(request.POST, request.FILES) @@ -196,7 +140,8 @@ def create_video_item(request, *args, **kwargs): @require_http_methods(["POST"]) @ensure_csrf_cookie -@permission_required('infoscreen.add_rotation', login_url='/login') +@login_required(login_url='/login') +@permission_required('infoscreen.add_rotation', raise_exception=True) def create_rotation(request, *args, **kwargs): """Create rotation.""" try: @@ -217,7 +162,8 @@ def create_rotation(request, *args, **kwargs): @require_http_methods(["DELETE"]) @ensure_csrf_cookie -@permission_required('infoscreen.delete_rotation', login_url='/login') +@login_required(login_url='/login') +@permission_required('infoscreen.delete_rotation', raise_exception=True) def delete_rotation(request, *args, **kwargs): """Delete rotation.""" id = kwargs.pop("id", 0) @@ -233,32 +179,6 @@ def delete_rotation(request, *args, **kwargs): return resp -@require_http_methods(["GET"]) -def hsl_timetable_settings(request, *args, **kwargs): - """Set HSL timetable settings.""" - d = {"departure_threshold": settings.HSL_DEPARTURE_THRESHOLD, - "hurry_threshold": settings.HSL_HURRY_THRESHOLD} - resp = json.dumps(d) - return HttpResponse(resp, status=200) - - -@require_http_methods(["GET"]) -def CurrentHSLView(request, *args, **kwargs): - """Get HSL data and return it.""" - fetcher = HSLFetcher() - fetcherThread = threading.Thread(target=fetcher.fetch_if_needed, args=[]) - fetcherThread.setDaemon(False) - fetcherThread.start() - - data = HSLDataModel.objects.all() - if len(data) < 1: - return HttpResponse( - '{"error" : "Could not find timetables from database."}', - status=500) - - return HttpResponse(data[len(data) - 1].data, status=200) - - createInstance = create_item_generator(InfoInstance) deleteInstance = delete_item_generator(InfoInstance) createABBItem = create_item_generator(ABBInfoItem) diff --git a/infoscreen/views/public_views.py b/infoscreen/views/public_views.py new file mode 100644 index 0000000..d0c264b --- /dev/null +++ b/infoscreen/views/public_views.py @@ -0,0 +1,101 @@ +from django.shortcuts import render +from django.http import HttpResponse, HttpResponseBadRequest +from django.views.decorators.http import require_http_methods + +from infoscreen.models import Rotation, InfoItem, InfoInstance +from infoscreen.hsl_fetcher import HSLFetcher + +import json + + +@require_http_methods(["GET"]) +def index(request, idx, *args, **kwargs): + """Render infoscreen index page.""" + return render(request, 'infoscreen_index.html', {'rotation': idx}) + + +@require_http_methods(["GET"]) +def default(request, *args, **kwargs): + """Try getting first rotation item.""" + try: + first = Rotation.objects.all()[0].id + except: + first = 0 + return index(request, first, *args, **kwargs) + + +@require_http_methods(["GET"]) +def get_apy_json(request): + """Render APY diilikone page.""" + return HttpResponse( + requests.get("https://api-diilikone.apy.fi/deals/top-groups").text) + + +@require_http_methods(["GET"]) +def rotation(request, idx, *args, **kwargs): + """Get rotation.""" + try: + rotation = Rotation.objects.get(pk=idx) + except Rotation.DoesNotExist: + resp = HttpResponse('{"error": "Rotation not found"}') + resp.status_code = 404 + return resp + + return HttpResponse(json.dumps(rotation.get_dict())) + + +@require_http_methods(["GET"]) +def rotations(request, *args, **kwargs): + """Return rotation lists.""" + rotations = list(map(lambda r: r.get_list(), Rotation.objects.all())) + return HttpResponse(json.dumps(rotations)) + + +@require_http_methods(["GET"]) +def info_types(request, *args, **kwargs): + """Return info item types.""" + types = [] + classes = InfoItem.get_subclasses() + for c in classes: + types.append({ + "name": c.display_name, + "create_template_url": c.get_create_template_url(), + }) + return HttpResponse(json.dumps(types)) + + +@require_http_methods(["GET"]) +def info_items(request, *args, **kwargs): + """Return Infoscreen items.""" + items = [] + classes = InfoItem.get_subclasses() + for c in classes: + for i in c.objects.all(): + items.append(i.get_dict()) + return HttpResponse(json.dumps(items)) + + +@require_http_methods(["GET"]) +def hsl_timetable_settings(request, *args, **kwargs): + """Set HSL timetable settings.""" + d = {"departure_threshold": settings.HSL_DEPARTURE_THRESHOLD, + "hurry_threshold": settings.HSL_HURRY_THRESHOLD} + resp = json.dumps(d) + return HttpResponse(resp, status=200) + + +@require_http_methods(["GET"]) +def CurrentHSLView(request, *args, **kwargs): + """Get HSL data and return it.""" + fetcher = HSLFetcher() + fetcherThread = threading.Thread(target=fetcher.fetch_if_needed, args=[]) + fetcherThread.setDaemon(False) + fetcherThread.start() + + data = HSLDataModel.objects.all() + if len(data) < 1: + return HttpResponse( + '{"error" : "Could not find timetables from database."}', + status=500) + + return HttpResponse(data[len(data) - 1].data, status=200) From 3901c21c6762cc2ccb537734fed2790f391a79a8 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Thu, 28 Sep 2017 20:28:19 +0300 Subject: [PATCH 4/7] Fix decorators in members --- members/views/applications.py | 17 +++++++++++------ members/views/members.py | 30 ++++++++++++++++++++---------- members/views/payments.py | 23 +++++++++++++++-------- members/views/utils.py | 8 +++++--- 4 files changed, 51 insertions(+), 27 deletions(-) diff --git a/members/views/applications.py b/members/views/applications.py index 86e100e..8324d53 100644 --- a/members/views/applications.py +++ b/members/views/applications.py @@ -1,5 +1,5 @@ from django.shortcuts import render -from django.contrib.auth.decorators import permission_required +from django.contrib.auth.decorators import permission_required, login_required from django.views.decorators.http import require_http_methods from django.views.decorators.csrf import ensure_csrf_cookie from django.http import HttpResponse, HttpResponseRedirect @@ -18,7 +18,8 @@ from members.forms import ApplicationForm @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.read_application', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.read_application', raise_exception=True) def application_list(request, *args, **kwargs): """List member applications not yet processed.""" applications = Request.objects.all() @@ -40,7 +41,8 @@ def application_list(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.change_request', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.change_request', raise_exception=True) def application_edit(request, *args, **kwargs): """Edit member request information.""" i = kwargs.pop('index', None) @@ -58,7 +60,8 @@ def application_edit(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.add_member', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.add_member', raise_exception=True) def application_accept(request, *args, **kwargs): """Accept application.""" form = ApplicationForm(request.POST) @@ -86,7 +89,8 @@ def application_accept(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.delete_request', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.delete_request', raise_exception=True) def application_delete(request, *args, **kwargs): """Delete member application.""" try: @@ -114,7 +118,8 @@ def application_delete(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.delete_request', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.delete_request', raise_exception=True) def application_delete_confirm(request, *args, **kwargs): """Confirm application deletion.""" i = kwargs.pop('index', None) diff --git a/members/views/members.py b/members/views/members.py index 0b7c9db..0321296 100644 --- a/members/views/members.py +++ b/members/views/members.py @@ -1,5 +1,5 @@ from django.shortcuts import render -from django.contrib.auth.decorators import permission_required +from django.contrib.auth.decorators import permission_required, login_required from django.utils.decorators import method_decorator from django.views.decorators.http import require_http_methods from django.views.decorators.csrf import ensure_csrf_cookie @@ -27,7 +27,8 @@ from members.views.utils import * @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.read_member', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.read_member', raise_exception=True) def member_list(request, *args, **kwargs): """Render members list.""" search = request.GET.get('q', None) @@ -53,7 +54,8 @@ def member_list(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.add_member', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.add_member', raise_exception=True) def member_add(request, *args, **kwargs): """Render add member page.""" form = MemberForm() @@ -62,7 +64,8 @@ def member_add(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.delete_member', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.delete_member', raise_exception=True) def member_delete_confirm(request, *args, **kwargs): """Render member deletion confirmation page.""" i = kwargs.pop('index', None) @@ -78,7 +81,8 @@ def member_delete_confirm(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.add_member', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.add_member', raise_exception=True) def member_add_many(request, *args, **kwargs): """Render add multiple members page.""" return render(request, 'member_add_many.html', {}) @@ -86,7 +90,8 @@ def member_add_many(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.add_member', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.add_member', raise_exception=True) def add_many_confirm(request, *args, **kwargs): models = request.session['models'] @@ -108,7 +113,8 @@ def add_many_confirm(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.add_member', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.add_member', raise_exception=True) def member_submit(request, *args, **kwargs): """Add member based on data gained from member form.""" form = MemberForm(request.POST) @@ -128,7 +134,8 @@ def member_submit(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.change_member', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.change_member', raise_exception=True) def member_update(request, *args, **kwargs): """Update member information.""" form = MemberForm(request.POST) @@ -154,7 +161,8 @@ def member_update(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.delete_member', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.delete_member', raise_exception=True) def member_delete(request, *args, **kwargs): """Delete member.""" try: @@ -181,7 +189,8 @@ def member_delete(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.change_member', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.change_member', raise_exception=True) def member_edit(request, *args, **kwargs): """Edit member information.""" i = kwargs.pop('index', None) @@ -197,6 +206,7 @@ def member_edit(request, *args, **kwargs): class MemberAutoComplete(autocomplete.Select2QuerySetView): + @method_decorator(login_required(login_url='/login')) def get_queryset(self): qs = Member.objects.all() diff --git a/members/views/payments.py b/members/views/payments.py index 988fcbe..4c9a587 100644 --- a/members/views/payments.py +++ b/members/views/payments.py @@ -1,5 +1,5 @@ from django.shortcuts import render -from django.contrib.auth.decorators import permission_required +from django.contrib.auth.decorators import permission_required, login_required from django.views.decorators.http import require_http_methods from django.views.decorators.csrf import ensure_csrf_cookie from django.http import HttpResponse, HttpResponseRedirect @@ -18,7 +18,8 @@ from members.forms import PaymentForm @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.read_payment', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.read_payment', raise_exception=True) def payment_list(request, *args, **kwargs): """Render list of payments.""" search = request.GET.get('q', None) @@ -45,7 +46,8 @@ def payment_list(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.add_payment', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.add_payment', raise_exception=True) def payment_add(request, *args, **kwargs): """Render add payment form.""" form = PaymentForm() @@ -54,7 +56,8 @@ def payment_add(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.add_payment', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.add_payment', raise_exception=True) def payment_submit(request, *args, **kwargs): """Submit payment.""" form = PaymentForm(request.POST) @@ -75,7 +78,8 @@ def payment_submit(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.change_payment', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.change_payment', raise_exception=True) def payment_edit(request, *args, **kwargs): """Edit payment.""" i = kwargs.pop('index', None) @@ -93,7 +97,8 @@ def payment_edit(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.delete_payment', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.delete_payment', raise_exception=True) def payment_delete_confirm(request, *args, **kwargs): """Render payment delete confirmation page.""" i = kwargs.pop('index', None) @@ -111,7 +116,8 @@ def payment_delete_confirm(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.delete_payment', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.delete_payment', raise_exception=True) def payment_delete(request, *args, **kwargs): """Delete payment.""" try: @@ -139,7 +145,8 @@ def payment_delete(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required('members.change_payment', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.change_payment', raise_exception=True) def payment_update(request, *args, **kwargs): """Update payment information.""" form = PaymentForm(request.POST) diff --git a/members/views/utils.py b/members/views/utils.py index acf2d04..8d8e7ae 100644 --- a/members/views/utils.py +++ b/members/views/utils.py @@ -1,5 +1,5 @@ from django.shortcuts import render -from django.contrib.auth.decorators import permission_required +from django.contrib.auth.decorators import permission_required, login_required from django.views.decorators.http import require_http_methods from django.views.decorators.csrf import ensure_csrf_cookie from django.http import HttpResponse, HttpResponseRedirect @@ -93,7 +93,8 @@ def convert_table_to_html(table, request): @ensure_csrf_cookie @require_http_methods(["GET"]) -@permission_required('members.change_member', login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required('members.change_member', raise_exception=True) def settings_page(request, *args, **kwargs): """Render member app settings page.""" return render(request, 'settings.html', {}) @@ -101,7 +102,8 @@ def settings_page(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) -@permission_required(['members.change_member', 'members.change_payment'], login_url='/login', raise_exception=True) +@login_required(login_url='/login') +@permission_required(['members.change_member', 'members.change_payment'], raise_exception=True) def import_csv(request, *args, **kwargs): """Get csv data imported to page and create members based on that.""" try: From 285a0e7dbf7634febce11e9bdbc2374f28f3ec99 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Thu, 28 Sep 2017 20:29:54 +0300 Subject: [PATCH 5/7] Fix decorators in webapp --- webapp/views.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/webapp/views.py b/webapp/views.py index d398898..3aac545 100644 --- a/webapp/views.py +++ b/webapp/views.py @@ -5,7 +5,7 @@ from django.contrib.auth import login, logout, authenticate from django.views.decorators.http import require_http_methods from django.views.decorators.csrf import ensure_csrf_cookie from django.http import HttpResponse, HttpResponseRedirect -from django.contrib.auth.decorators import permission_required +from django.contrib.auth.decorators import permission_required, login_required from django.conf import settings import logging from webapp.models import OhlhafvChallenge @@ -21,7 +21,8 @@ def main_index(request, *args, **kwargs): @require_http_methods(["GET", "POST"]) @ensure_csrf_cookie -@permission_required('members.change_member', login_url='/login') +@login_required(login_url='/login') +@permission_required('members.change_member') def admin_index(request, *args, **kwargs): """Render admin main page.""" return render(request, "admin_index.html", {}) @@ -50,7 +51,7 @@ def login_view(request, *args, **kwargs): return render(request, "login.html", {}) -@require_http_methods(["POST"]) +@require_http_methods(["GET", "POST"]) def logout_view(request, *args, **kwargs): """Logout user and return to main page.""" logout(request) From 8f06190bd0c3c8ab18a080f1b793885bb59e8c75 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Thu, 28 Sep 2017 23:36:12 +0300 Subject: [PATCH 6/7] Use django-suit for SIK Admin --- locale/en/LC_MESSAGES/django.mo | Bin 6691 -> 6691 bytes locale/en/LC_MESSAGES/django.po | 168 +++++++++++++------ locale/fi/LC_MESSAGES/django.mo | Bin 8490 -> 9070 bytes locale/fi/LC_MESSAGES/django.po | 158 +++++++++++------ requirements.txt | 1 + sikweb/base.py | 30 ++++ static/css/sikadmin.css | 17 ++ templates/admin/base_site.html | 74 ++++++++ webapp/admin.py | 3 +- webapp/migrations/0015_auto_20170928_2331.py | 41 +++++ webapp/models.py | 31 ++++ webapp/translation.py | 9 +- 12 files changed, 428 insertions(+), 104 deletions(-) create mode 100644 static/css/sikadmin.css create mode 100644 templates/admin/base_site.html create mode 100644 webapp/migrations/0015_auto_20170928_2331.py diff --git a/locale/en/LC_MESSAGES/django.mo b/locale/en/LC_MESSAGES/django.mo index 6364efbbae44f602d2bc38d8c392c0efb7c5eaef..b901384c48f255de2ae62472152bd3591b672c34 100644 GIT binary patch delta 20 bcmZ2%ve;xpk085+f{~Gxsrlx~f)h9ZM|=iU delta 20 bcmZ2%ve;xpk086Lf{~$>vC-zqf)h9ZM\n" "Language-Team: LANGUAGE \n" @@ -33,7 +33,7 @@ msgstr "External website" msgid "Sössö articles" msgstr "Sössö articles" -#: infoscreen/models.py:199 +#: infoscreen/models.py:199 webapp/models.py:70 msgid "Events" msgstr "Events" @@ -169,8 +169,8 @@ msgstr "Select rotation to edit" msgid "id" msgstr "id" -#: infoscreen/templates/infoscreen_admin.html:141 webapp/models.py:60 -#: webapp/models.py:94 webapp/models.py:107 +#: infoscreen/templates/infoscreen_admin.html:141 webapp/models.py:91 +#: webapp/models.py:125 webapp/models.py:138 msgid "Name" msgstr "Name" @@ -184,12 +184,12 @@ msgid "Language" msgstr "Language" #: infoscreen/templates/infoscreen_admin.html:161 -#: members/templates/settings.html:20 sikweb/base.py:216 +#: members/templates/settings.html:20 sikweb/base.py:221 msgid "Finnish" msgstr "Finnish" #: infoscreen/templates/infoscreen_admin.html:162 -#: members/templates/settings.html:21 sikweb/base.py:217 +#: members/templates/settings.html:21 sikweb/base.py:222 msgid "English" msgstr "English" @@ -200,56 +200,56 @@ msgstr "English" msgid "Submit" msgstr "Submitted" -#: members/forms.py:103 members/tables.py:32 +#: members/forms.py:110 members/tables.py:32 msgid "Member" msgstr "Member" -#: members/models.py:13 +#: members/models.py:14 msgid "First name" msgstr "First name" -#: members/models.py:14 +#: members/models.py:15 msgid "Last name" msgstr "Last name" -#: members/models.py:15 webapp/models.py:95 webapp/models.py:108 +#: members/models.py:16 webapp/models.py:126 webapp/models.py:139 msgid "Email" msgstr "Email" -#: members/models.py:16 +#: members/models.py:17 msgid "Place of residence" msgstr "Place of residence" -#: members/models.py:18 members/models.py:83 +#: members/models.py:19 members/models.py:70 #: members/templates/member_add_many.html:35 msgid "AYY" msgstr "AYY" -#: members/models.py:19 +#: members/models.py:20 msgid "JAS" msgstr "JAS" -#: members/models.py:69 +#: members/models.py:51 msgid "Submitted" msgstr "Submitted" -#: members/models.py:81 +#: members/models.py:68 msgid "Date" msgstr "Date" -#: members/models.py:82 +#: members/models.py:69 msgid "Source" msgstr "Source" -#: members/models.py:84 +#: members/models.py:71 msgid "Cash" msgstr "Cash" -#: members/models.py:85 members/templates/member_add_many.html:36 +#: members/models.py:72 members/templates/member_add_many.html:36 msgid "Bank transfer" msgstr "Bank transfer" -#: members/models.py:102 +#: members/models.py:96 msgid "Created" msgstr "Created" @@ -453,130 +453,196 @@ msgstr "Payment events" msgid "Payments in register:" msgstr "Member register" -#: members/views/applications.py:49 members/views/applications.py:96 -#: members/views/applications.py:124 +#: members/views/applications.py:51 members/views/applications.py:100 +#: members/views/applications.py:129 msgid "No application id specified" msgstr "No application id specified" -#: members/views/applications.py:77 +#: members/views/applications.py:80 msgid "Successfully accepted application" msgstr "Successfully accepted application" -#: members/views/applications.py:84 +#: members/views/applications.py:87 msgid "Could not accept application object" msgstr "Could not accept application object" -#: members/views/applications.py:100 +#: members/views/applications.py:104 msgid "Successfully deleted application" msgstr "Successfully deleted application" -#: members/views/applications.py:112 +#: members/views/applications.py:116 msgid "Could not delete application object" msgstr "Could not delete application object" -#: members/views/members.py:70 members/views/members.py:163 -#: members/views/members.py:189 +#: members/views/members.py:74 members/views/members.py:172 +#: members/views/members.py:199 msgid "No member id specified" msgstr "No member id specified" -#: members/views/members.py:105 +#: members/views/members.py:111 msgid "Failed to import members" msgstr "Failed to import members" -#: members/views/members.py:118 +#: members/views/members.py:125 msgid "Successfully added member" msgstr "Successfully added member" -#: members/views/members.py:143 +#: members/views/members.py:151 msgid "Successfully updated member" msgstr "Successfully updated member" -#: members/views/members.py:151 +#: members/views/members.py:159 msgid "Could not update member object" msgstr "Could not update member object" -#: members/views/members.py:167 +#: members/views/members.py:176 msgid "Successfully deleted member" msgstr "Successfully deleted member" -#: members/views/members.py:178 +#: members/views/members.py:187 msgid "Could not delete member object" msgstr "Could not delete member object" -#: members/views/payments.py:69 +#: members/views/payments.py:70 msgid "Successfully added payment for member" msgstr "Successfully added payment for member" -#: members/views/payments.py:87 members/views/payments.py:105 -#: members/views/payments.py:124 +#: members/views/payments.py:89 members/views/payments.py:108 +#: members/views/payments.py:128 msgid "No payment id specified" msgstr "No payment id specified" -#: members/views/payments.py:129 +#: members/views/payments.py:133 msgid "Successfully deleted payment" msgstr "Successfully deleted payment" -#: members/views/payments.py:139 +#: members/views/payments.py:143 msgid "Could not delete payment object" msgstr "Could not delete payment object" -#: members/views/payments.py:158 +#: members/views/payments.py:163 msgid "Successfully updated payment" msgstr "Successfully updated payment" -#: members/views/payments.py:165 +#: members/views/payments.py:170 msgid "Could not update payment object" msgstr "Could not update payment object" -#: members/views/utils.py:110 +#: members/views/utils.py:115 msgid "Missing \"textfield\" POST request field" msgstr "Missing \"textfield\" POST request field" +#: templates/admin/base_site.html:33 +#, fuzzy +#| msgid "Language" +msgid "language" +msgstr "Language" + +#: templates/admin/base_site.html:43 +msgid "Go" +msgstr "" + #: templates/footer.html:7 msgid "Copyright Aalto-yliopiston Sähköinsinöörikilta ry" msgstr "Copyright Aalto-yliopiston Sähköinsinöörikilta ry" -#: webapp/models.py:61 +#: webapp/models.py:15 +msgid "Webapp" +msgstr "" + +#: webapp/models.py:26 +msgid "Tag" +msgstr "" + +#: webapp/models.py:27 +msgid "Tags" +msgstr "" + +#: webapp/models.py:30 +msgid "Tag: {}" +msgstr "" + +#: webapp/models.py:50 +msgid "Feed: {}" +msgstr "" + +#: webapp/models.py:53 +msgid "Feed" +msgstr "" + +#: webapp/models.py:54 +msgid "Feeds" +msgstr "" + +#: webapp/models.py:66 +#, fuzzy +#| msgid "Events" +msgid "Event: {}" +msgstr "Events" + +#: webapp/models.py:69 +#, fuzzy +#| msgid "Events" +msgid "Event" +msgstr "Events" + +#: webapp/models.py:81 +msgid "Registration: {}" +msgstr "" + +#: webapp/models.py:84 +#, fuzzy +#| msgid "Rotation" +msgid "Registration" +msgstr "Rotation" + +#: webapp/models.py:85 +#, fuzzy +#| msgid "Rotations" +msgid "Registrations" +msgstr "Rotations" + +#: webapp/models.py:92 #, fuzzy #| msgid "Add member" msgid "Board member" msgstr "Add member" -#: webapp/models.py:67 +#: webapp/models.py:98 #, fuzzy #| msgid "Duration" msgid "Description" msgstr "Duration" -#: webapp/models.py:68 +#: webapp/models.py:99 msgid "Summary" msgstr "" -#: webapp/models.py:96 +#: webapp/models.py:127 msgid "Message" msgstr "" -#: webapp/models.py:109 +#: webapp/models.py:140 msgid "Year" msgstr "" -#: webapp/models.py:123 +#: webapp/models.py:154 msgid "Role" msgstr "" -#: webapp/models.py:125 +#: webapp/models.py:156 msgid "Start date" msgstr "" -#: webapp/models.py:126 +#: webapp/models.py:157 msgid "End date" msgstr "" -#: webapp/models.py:136 +#: webapp/models.py:167 msgid "Official" msgstr "" -#: webapp/models.py:138 +#: webapp/models.py:169 msgid "Phone number" msgstr "" diff --git a/locale/fi/LC_MESSAGES/django.mo b/locale/fi/LC_MESSAGES/django.mo index d57a49a90a032e4ae4175f6680e48ab2849ef0e1..23bf56e0fe2bb477218b2d1ebcb00cfd2f330706 100644 GIT binary patch delta 3773 zcmY+F32anV6oxNlE1ML`6c7qiN?A(TDy0QvD^RE`B9>JUhxXA9ZKtL4rh)|r5oD94 z)XHK)h*4q?5z` zHK;^xLIwB-D#2ErqHG7{kAtdEH`tE&rZ#u`h1*pg91}{Mcz5zAyuTX*RLIp6LqbrVuF?8dh z0wh2^mtyY^f=Tp8+WrFQp`Q;m?`k*zuJ26!RkF8nDDWw$OwT|as&h~SE?9qqi$T3e=_7}rpHr%?cGv(+S4+qfm>h~SZ(`a)60saBI!VU~l!YNSm46z(({o|l2Hq~-o*xqoUN)&)v(FVw(Of}R*Z&?2k zs1==pTG4r^gf2q`{vN7=*DY__`*)%C{vK4Ktq7)Z;a(UDm<%<+Fvw!eD5wE5p-y?8 z?JtE2upDZS%b_Z_8>YY`&D%AK!s4e^pD&dX~N6%UkRE3AbIKBT<1*nRA z)sy&4-$UYPvurG7xHlbf^ilpem9LRqDA=mCCpM08~ZRKz?Qy7X>~F z^(B4Z_UjX=za~C!9T%Zia2YD0t57R#w7doRnLAvRXaau}s#r4AS(ya&dQF8&Y^n8^ zLM6V^_N$=chQk4 zu`mlNP9;>O!cfnLw_@l$u7+A^9n=a>LXL&`8uo#|K_%qzMpu$-IT&ixdY?%{+D3raIAwGxEUtHYRIC^ahMJpAU_jJIlM3x4uI1kKjU&q zg?pg3tR8B;E0LC%*X`LwnMes5q~N;(|s{zRyX%z!%mb6^Z~ ztiK30qrV?Lie{muXgN~ToRd(0G#3p*;q_cLA+^EChg3$jHE258j%K53G!f~5s%by> zpej^^)J8-RxvKnQkdoKgYTBmInXmnS9OFf_(B7Q}ldQb}zJP*gob{DJmG^!df}v`t za*NSO)EsGRDv=IzEmB(@g?S0iKeF8m>awD1_Lp$UD9ax=3f_ z6{Mzv%vU+mwCBUEt!-1|ZT+w9lcoL7v94Dk|3Ri4jYm(RrY(bx4%7rxgJO_cDauEE zQ5jl-3Xs}kQJ752VemO??}p)dTvDt<$vk0g;bm(lz)ols+Gc%%UZ((ZP(P%$7bT<3 z>d?Gsjttr(Xc6j;^d>wRT|eJvIvbH%15L=ExMa2l}^C*=KD&VK!L9!+8yn! zT3b^bmp#C73QP_cIU+{T@wDPB6`z+rQKs3{^PBUtmgn zfx?il(5V^kSSw75)dV$Z8Jtm@#Z_$n^)D zfU%4OmK}6l6AYD=`ppzK6!61&K7UbxukK!t`k3_GlF~B2>-s`W9~s_sC6PJ)_XLyG uecY>0Oz*sq3gtTHz7buh^*S}zyhGZ~a$LguD?@Hghor<-)BR3~-~0=|?4R2J delta 3206 zcmYk8Yfx2H6vsD+sVE}Ivmh>_;p38uZ_Ff83Pmx+1k3CSBsbv7L$nmVrkR>%Gv1nN za?+-(No_JQzZF`e&h&w?Vk*l~M?Tm~%cjX1r|kE?cVX_i|MS~xopbhDd+ogsTq)jP z6g-z0^RlDuKpChl#<>o7wl5djxBZ=~foI?;IDLR~y45Ex!a=YXb~+pdGvRHp#QgK% zAnbA&3u_=lxJJm3LAQ=hJdSM;t{A9PCzgG66V1hkX&6J57Tw|P|p=Y z`RABDANIpu3NxV}_JLdA1me3F>Ez%zVf+!^i5*8)S z3Rq_TMUXkTB~XFt&2EAG+(s^GFa(2o@gN<|^I{L^A98&RVWo|LV1u|t^jJBIZ$yI2I(lkVyH?~85`_@)ld~^gGy+V z`Co?`crVoZ??Zm>C>K5dIn1&1=Pzh$6JrZhZN5g2H|7mpUqS(!FIX4bc|NStD z>4rBW)C-+Zo9Hamhvov*zysLIN+=oX`AnnNI2G#sSx`$*0hM4KjMw>JM~7;-7ocYF zCL9kB!>RBRRG=K{rILD~2ATv_(pgYTQ4UoRAJllY=5K=&u(v^dXF8w4|Crl3 z+i)lx3QM6EHo+|T22=u{Km|GlHPbHhcSDu>7pUET)%;PcqY{cWCO{>e26eoL!0`DW zPDdpfV=RISP!1Ka3bL%O5h{_*Py_6Qs>DlBm3bGc)Q6!ea182`+XeOf?@&wi7u5J{ zuwXdzcy^j*kOcKYI#l3EP!*T~wf5DJWp}kufi{?bC)CV#nY|k-;9jVN-+`Lo2T*~J zL%n}GgZeAbIeXw|yYUZXKf3;8qmpJrm2xc99+_N-TpT;by3%IRrJ}$4~)ILIv!E+LRZe61fId zp?{%fJdh~boJo)mjmw2mkkcG)ZCv{i->smd56WXm1GONPZaSKUdfGNRqmhEFLwQJ> zNl8DA)U*TzNEI4`h#5Znk3%(8q^E7AGoJXa2tACNk=k-JGu(^(>!ppj7(InlDK*W! zrJk**{9eM;kgtUu&s1@DXJQ!K#D2Gp=^=J`V zjW!@1G9pOz`B7Ef|;IUX*&H tcW8Fz;81;LQCv&wiUz-%xw19jZ}7LD%ltID{VPv)bSOE;8!FAo_zwVN9h?9F diff --git a/locale/fi/LC_MESSAGES/django.po b/locale/fi/LC_MESSAGES/django.po index 2145ded..66aa1fd 100644 --- a/locale/fi/LC_MESSAGES/django.po +++ b/locale/fi/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-09-25 21:32+0300\n" +"POT-Creation-Date: 2017-09-28 22:57+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -34,7 +34,7 @@ msgstr "Ulkoinen verkkosivu" msgid "Sössö articles" msgstr "Sössön artikkelit" -#: infoscreen/models.py:199 +#: infoscreen/models.py:199 webapp/models.py:70 msgid "Events" msgstr "Tapahtumat" @@ -168,8 +168,8 @@ msgstr "Valitse muokattava rotaatio" msgid "id" msgstr "id" -#: infoscreen/templates/infoscreen_admin.html:141 webapp/models.py:60 -#: webapp/models.py:94 webapp/models.py:107 +#: infoscreen/templates/infoscreen_admin.html:141 webapp/models.py:91 +#: webapp/models.py:125 webapp/models.py:138 msgid "Name" msgstr "Nimi" @@ -183,12 +183,12 @@ msgid "Language" msgstr "Kieli" #: infoscreen/templates/infoscreen_admin.html:161 -#: members/templates/settings.html:20 sikweb/base.py:216 +#: members/templates/settings.html:20 sikweb/base.py:221 msgid "Finnish" msgstr "suomi" #: infoscreen/templates/infoscreen_admin.html:162 -#: members/templates/settings.html:21 sikweb/base.py:217 +#: members/templates/settings.html:21 sikweb/base.py:222 msgid "English" msgstr "englanti" @@ -197,56 +197,56 @@ msgstr "englanti" msgid "Submit" msgstr "Lisää" -#: members/forms.py:103 members/tables.py:32 +#: members/forms.py:110 members/tables.py:32 msgid "Member" msgstr "Jäsen" -#: members/models.py:13 +#: members/models.py:14 msgid "First name" msgstr "Etunimi" -#: members/models.py:14 +#: members/models.py:15 msgid "Last name" msgstr "Sukunimi" -#: members/models.py:15 webapp/models.py:95 webapp/models.py:108 +#: members/models.py:16 webapp/models.py:126 webapp/models.py:139 msgid "Email" msgstr "Sähköposti" -#: members/models.py:16 +#: members/models.py:17 msgid "Place of residence" msgstr "Asuinpaikka" -#: members/models.py:18 members/models.py:83 +#: members/models.py:19 members/models.py:70 #: members/templates/member_add_many.html:35 msgid "AYY" msgstr "AYY" -#: members/models.py:19 +#: members/models.py:20 msgid "JAS" msgstr "JAS" -#: members/models.py:69 +#: members/models.py:51 msgid "Submitted" msgstr "Lisätty" -#: members/models.py:81 +#: members/models.py:68 msgid "Date" msgstr "Päivämäärä" -#: members/models.py:82 +#: members/models.py:69 msgid "Source" msgstr "Lähde" -#: members/models.py:84 +#: members/models.py:71 msgid "Cash" msgstr "Käteinen" -#: members/models.py:85 members/templates/member_add_many.html:36 +#: members/models.py:72 members/templates/member_add_many.html:36 msgid "Bank transfer" msgstr "Tilisiirto" -#: members/models.py:102 +#: members/models.py:96 msgid "Created" msgstr "Lisätty" @@ -443,126 +443,182 @@ msgstr "Maksutapahtumat" msgid "Payments in register:" msgstr "Maksutapahtumia:" -#: members/views/applications.py:49 members/views/applications.py:96 -#: members/views/applications.py:124 +#: members/views/applications.py:51 members/views/applications.py:100 +#: members/views/applications.py:129 msgid "No application id specified" msgstr "Hakemuksen ID ei määritelty" -#: members/views/applications.py:77 +#: members/views/applications.py:80 msgid "Successfully accepted application" msgstr "Onnistuneesti hyväksyttiin hakemus" -#: members/views/applications.py:84 +#: members/views/applications.py:87 msgid "Could not accept application object" msgstr "Hakemusobjektia ei voitu hyväksyä" -#: members/views/applications.py:100 +#: members/views/applications.py:104 msgid "Successfully deleted application" msgstr "Onnistuneesti poistettiin hakemus" -#: members/views/applications.py:112 +#: members/views/applications.py:116 msgid "Could not delete application object" msgstr "Hakemusobjektia ei voitu poistaa" -#: members/views/members.py:70 members/views/members.py:163 -#: members/views/members.py:189 +#: members/views/members.py:74 members/views/members.py:172 +#: members/views/members.py:199 msgid "No member id specified" msgstr "Jäsenen ID ei määritelty" -#: members/views/members.py:105 +#: members/views/members.py:111 msgid "Failed to import members" msgstr "Jäsenten tuonti epäonnistui" -#: members/views/members.py:118 +#: members/views/members.py:125 msgid "Successfully added member" msgstr "Onnistuneesti lisättiin jäsen" -#: members/views/members.py:143 +#: members/views/members.py:151 msgid "Successfully updated member" msgstr "Onnistuneesti päivitettiin jäsen" -#: members/views/members.py:151 +#: members/views/members.py:159 msgid "Could not update member object" msgstr "Jäsenobjektia ei voitu päivittää" -#: members/views/members.py:167 +#: members/views/members.py:176 msgid "Successfully deleted member" msgstr "Onnistuneesti poistettiin jäsen" -#: members/views/members.py:178 +#: members/views/members.py:187 msgid "Could not delete member object" msgstr "Jäsenobjektia ei voitu poistaa" -#: members/views/payments.py:69 +#: members/views/payments.py:70 msgid "Successfully added payment for member" msgstr "Onnistuneesti lisättiin maksutapahtuma jäsenelle" -#: members/views/payments.py:87 members/views/payments.py:105 -#: members/views/payments.py:124 +#: members/views/payments.py:89 members/views/payments.py:108 +#: members/views/payments.py:128 msgid "No payment id specified" msgstr "Maksutapahtuman ID ei määritelty" -#: members/views/payments.py:129 +#: members/views/payments.py:133 msgid "Successfully deleted payment" msgstr "Onnistuneesti poistettiin maksutapahtuma" -#: members/views/payments.py:139 +#: members/views/payments.py:143 msgid "Could not delete payment object" msgstr "Maksutapahtumaobjektia ei voitu poistaa" -#: members/views/payments.py:158 +#: members/views/payments.py:163 msgid "Successfully updated payment" msgstr "Onnistuneesti päivitettiin maksutapahtuma" -#: members/views/payments.py:165 +#: members/views/payments.py:170 msgid "Could not update payment object" msgstr "Maksutapahtumaobjektia ei voitu päivittää" -#: members/views/utils.py:110 +#: members/views/utils.py:115 msgid "Missing \"textfield\" POST request field" msgstr "Puuttuva \"textfield\" POST-kenttä" +#: templates/admin/base_site.html:33 +msgid "language" +msgstr "Kieli" + +#: templates/admin/base_site.html:43 +msgid "Go" +msgstr "Vaihda" + #: templates/footer.html:7 msgid "Copyright Aalto-yliopiston Sähköinsinöörikilta ry" msgstr "Copyright Aalto-yliopiston Sähköinsinöörikilta ry" -#: webapp/models.py:61 +#: webapp/models.py:15 +msgid "Webapp" +msgstr "Nettisivut" + +#: webapp/models.py:26 +msgid "Tag" +msgstr "Tunniste" + +#: webapp/models.py:27 +msgid "Tags" +msgstr "Tunnisteet" + +#: webapp/models.py:30 +msgid "Tag: {}" +msgstr "Tunniste: {}" + +#: webapp/models.py:50 +msgid "Feed: {}" +msgstr "Uutinen: {}" + +#: webapp/models.py:53 +msgid "Feed" +msgstr "Uutinen" + +#: webapp/models.py:54 +msgid "Feeds" +msgstr "Uutiset" + +#: webapp/models.py:66 +msgid "Event: {}" +msgstr "Tapahtuma: {}" + +#: webapp/models.py:69 +msgid "Event" +msgstr "Tapahtuma" + +#: webapp/models.py:81 +msgid "Registration: {}" +msgstr "Registration: {}" + +#: webapp/models.py:84 +msgid "Registration" +msgstr "Ilmoittautuminen" + +#: webapp/models.py:85 +msgid "Registrations" +msgstr "Ilmoittautumiset" + +#: webapp/models.py:92 msgid "Board member" msgstr "Hallituksen jäsen" -#: webapp/models.py:67 +#: webapp/models.py:98 msgid "Description" msgstr "Kuvaus" -#: webapp/models.py:68 +#: webapp/models.py:99 msgid "Summary" msgstr "Tiivistelmä" -#: webapp/models.py:96 +#: webapp/models.py:127 msgid "Message" msgstr "Viesti" -#: webapp/models.py:109 +#: webapp/models.py:140 msgid "Year" msgstr "Vuosi" -#: webapp/models.py:123 +#: webapp/models.py:154 msgid "Role" msgstr "Rooli" -#: webapp/models.py:125 +#: webapp/models.py:156 msgid "Start date" msgstr "Alkupäivämäärä" -#: webapp/models.py:126 +#: webapp/models.py:157 msgid "End date" msgstr "Loppupäivämäärä" -#: webapp/models.py:136 +#: webapp/models.py:167 msgid "Official" msgstr "Toimihenkilö" -#: webapp/models.py:138 +#: webapp/models.py:169 msgid "Phone number" msgstr "Puhelinnumero" diff --git a/requirements.txt b/requirements.txt index 42871fa..8c2804c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -28,3 +28,4 @@ django-phonenumber-field==1.3.0 paho-mqtt==1.3.0 django-autocomplete-light==3.2.10 six==1.10.0 +django-suit==0.2.25 diff --git a/sikweb/base.py b/sikweb/base.py index 5cdb35a..aa5ec1c 100644 --- a/sikweb/base.py +++ b/sikweb/base.py @@ -64,6 +64,7 @@ LOGGING = { INSTALLED_APPS = [ 'modeltranslation', # has to be before admin for translation admin to work + 'suit', 'dal', 'dal_select2', 'django.contrib.admin', @@ -249,3 +250,32 @@ STATICFILES_DIRS = ( ) MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_URL = '/media/' + +SUIT_CONFIG = { + # header + 'ADMIN_NAME': 'SIK Admin', + # 'HEADER_DATE_FORMAT': 'l, j. F Y', + # 'HEADER_TIME_FORMAT': 'H:i', + + # forms + # 'SHOW_REQUIRED_ASTERISK': True, # Default True + # 'CONFIRM_UNSAVED_CHANGES': True, # Default True + + # menu + # 'SEARCH_URL': '/admin/auth/user/', + # 'MENU_ICONS': { + # 'sites': 'icon-leaf', + # 'auth': 'icon-lock', + # }, + # 'MENU_OPEN_FIRST_CHILD': True, # Default True + # 'MENU_EXCLUDE': ('auth.group',), + # 'MENU': ( + # 'sites', + # {'app': 'auth', 'icon':'icon-lock', 'models': ('user', 'group')}, + # {'label': 'Settings', 'icon':'icon-cog', 'models': ('auth.user', 'auth.group')}, + # {'label': 'Support', 'icon':'icon-question-sign', 'url': '/support/'}, + # ), + + # misc + # 'LIST_PER_PAGE': 15 +} diff --git a/static/css/sikadmin.css b/static/css/sikadmin.css new file mode 100644 index 0000000..41aeb61 --- /dev/null +++ b/static/css/sikadmin.css @@ -0,0 +1,17 @@ +body { + font-size: 14px; +} + +.header { + background: #003366; + padding-top: 1rem; + padding-bottom: 1rem; +} + +.header #branding { + border-right: 0px; +} + +.header .header-content.header-content-first { + border-left: 0px; +} diff --git a/templates/admin/base_site.html b/templates/admin/base_site.html new file mode 100644 index 0000000..ee05b40 --- /dev/null +++ b/templates/admin/base_site.html @@ -0,0 +1,74 @@ +{% extends "admin/base.html" %} +{% load admin_static %} + +{% load i18n %} +{# Additional content here, some extra meta tags or favicon #} +{#{% block extrahead %}#} +{#{% endblock %}#} + + +{# Additional CSS includes #} +{% block extrastyle %} + +{% endblock %} + + +{# Additional JS files in footer, right before #} +{#{% block extrajs %}#} +{# #} +{#{% endblock %}#} + + +{# Footer links (left side) #} +{#{% block footer_links %}#} +{# Documentation#} +{#{% endblock %}#} + +{# Additional header content like notifications or language switcher #} +{% block header_content %} + {{ block.super }} +
+
{% csrf_token %} + + + +
+ + +
+{% endblock %} + +{# Footer branding name (center) #} +{#{% block footer_branding %}#} +{#{% endblock %}#} + + +{# Footer copyright (right side) #} +{#{% block copyright %}#} +{# Copyright © 2013 Client
Developed by YourName #} +{#{% endblock %}#} diff --git a/webapp/admin.py b/webapp/admin.py index b0b4349..59a0086 100644 --- a/webapp/admin.py +++ b/webapp/admin.py @@ -2,7 +2,7 @@ from django.contrib import admin from webapp.models import Official, Role -from webapp.models import Feed, Tag, BaseFeed, Event +from webapp.models import Feed, Tag, BaseFeed, Event, Registration from webapp.models import KaehmyForm, KaehmyMessage from webapp.models import CustomKaehmyRole, PresetKaehmyRole from modeltranslation.admin import TranslationAdmin @@ -15,6 +15,7 @@ admin.site.register(Permission) admin.site.register(Feed, TranslationAdmin) admin.site.register(Tag, TranslationAdmin) admin.site.register(Event, TranslationAdmin) +admin.site.register(Registration, TranslationAdmin) admin.site.register(Official) admin.site.register(Role) admin.site.register(KaehmyForm) diff --git a/webapp/migrations/0015_auto_20170928_2331.py b/webapp/migrations/0015_auto_20170928_2331.py new file mode 100644 index 0000000..baaa4bb --- /dev/null +++ b/webapp/migrations/0015_auto_20170928_2331.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11 on 2017-09-28 20:31 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('webapp', '0014_auto_20170920_1807'), + ] + + operations = [ + migrations.AlterModelOptions( + name='event', + options={'verbose_name': 'Event', 'verbose_name_plural': 'Events'}, + ), + migrations.AlterModelOptions( + name='feed', + options={'verbose_name': 'Feed', 'verbose_name_plural': 'Feeds'}, + ), + migrations.AlterModelOptions( + name='registration', + options={'verbose_name': 'Registration', 'verbose_name_plural': 'Registrations'}, + ), + migrations.AlterModelOptions( + name='tag', + options={'verbose_name': 'Tag', 'verbose_name_plural': 'Tags'}, + ), + migrations.AddField( + model_name='registration', + name='name_en', + field=models.CharField(max_length=255, null=True), + ), + migrations.AddField( + model_name='registration', + name='name_fi', + field=models.CharField(max_length=255, null=True), + ), + ] diff --git a/webapp/models.py b/webapp/models.py index 812d9f9..b48add0 100644 --- a/webapp/models.py +++ b/webapp/models.py @@ -12,6 +12,9 @@ from phonenumber_field.modelfields import PhoneNumberField from django.contrib.postgres.fields import JSONField +VERBOSE_NAME = _('Webapp') + + class Tag(models.Model): """Model for tag.""" @@ -19,6 +22,13 @@ class Tag(models.Model): name = models.CharField(max_length=127) icon = models.ImageField() + class Meta: + verbose_name = _('Tag') + verbose_name_plural = _('Tags') + + def __str__(self): + return _('Tag: {}').format(self.slug) + class BaseFeed(models.Model): """Model containing something showing on some info feed.""" @@ -36,6 +46,13 @@ class Feed(BaseFeed): publish_time = models.DateTimeField(default=timezone.now) autohide = models.DateTimeField(default=month_from_now) + def __str__(self): + return _('Feed: {}').format(self.title) + + class Meta: + verbose_name = _('Feed') + verbose_name_plural = _('Feeds') + class Event(BaseFeed): """Model for event.""" @@ -45,6 +62,13 @@ class Event(BaseFeed): registration = models.ForeignKey( 'Registration', on_delete=models.CASCADE, null=True) + def __str__(self): + return _('Event: {}').format(self.title) + + class Meta: + verbose_name = _('Event') + verbose_name_plural = _('Events') + class Registration(models.Model): """Model for event registration.""" @@ -53,6 +77,13 @@ class Registration(models.Model): email = models.EmailField() options = JSONField() + def __str__(self): + return _('Registration: {}').format(self.name) + + class Meta: + verbose_name = _('Registration') + verbose_name_plural = _('Registrations') + class BaseRole(models.Model): """Base model for occupations/roles.""" diff --git a/webapp/translation.py b/webapp/translation.py index 9ee016d..36b4cfc 100644 --- a/webapp/translation.py +++ b/webapp/translation.py @@ -1,7 +1,7 @@ """Translation classes.""" from modeltranslation.translator import register, TranslationOptions -from webapp.models import BaseFeed, Feed, Tag, Event +from webapp.models import BaseFeed, Feed, Tag, Event, Registration @register(BaseFeed) @@ -30,3 +30,10 @@ class TagTranslationOptions(TranslationOptions): """Class for tag translation options.""" fields = ('name',) + + +@register(Registration) +class RegistrationTranslationOptions(TranslationOptions): + """Class for registration translation options.""" + + fields = ('name',) From 4099e5fa2499560cbc91eb74e1d8d73db95d2cb7 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Fri, 29 Sep 2017 00:05:17 +0300 Subject: [PATCH 7/7] Fix broken tests --- infoscreen/tests.py | 10 ++++++---- infoscreen/views/public_views.py | 6 ++++-- members/views/members.py | 1 - sikweb/base.py | 3 +++ 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/infoscreen/tests.py b/infoscreen/tests.py index 69ee0fa..e2064d9 100644 --- a/infoscreen/tests.py +++ b/infoscreen/tests.py @@ -1,11 +1,13 @@ """File containing Infoscreen tests.""" -from django.test import TestCase +from django.test import TestCase, Client from infoscreen.models import Rotation from infoscreen.models import SossoInfoItem from django.http import HttpRequest import infoscreen.views +import logging + class InfoscreenTestCase(TestCase): """Test cases for testing infoscreen methods.""" @@ -14,6 +16,7 @@ class InfoscreenTestCase(TestCase): """Create some dummy models.""" Rotation.objects.create(name="test_rot") SossoInfoItem.objects.create() + self.c = Client() def test_rotation_created(self): """Check if the dummy model actually exists.""" @@ -32,7 +35,6 @@ class InfoscreenTestCase(TestCase): That would mean that something meaningful has been included in the response. """ - req = HttpRequest() - resp = infoscreen.views.info_items(req) - content = resp.content.decode('utf-8') + resp = self.c.get('/infoscreen/items') + content = resp.json() self.assertTrue(len(content) > 0) diff --git a/infoscreen/views/public_views.py b/infoscreen/views/public_views.py index d0c264b..461a547 100644 --- a/infoscreen/views/public_views.py +++ b/infoscreen/views/public_views.py @@ -1,11 +1,12 @@ from django.shortcuts import render -from django.http import HttpResponse, HttpResponseBadRequest +from django.http import HttpResponse, JsonResponse, HttpResponseBadRequest from django.views.decorators.http import require_http_methods from infoscreen.models import Rotation, InfoItem, InfoInstance from infoscreen.hsl_fetcher import HSLFetcher import json +import logging @require_http_methods(["GET"]) @@ -72,7 +73,8 @@ def info_items(request, *args, **kwargs): for c in classes: for i in c.objects.all(): items.append(i.get_dict()) - return HttpResponse(json.dumps(items)) + + return JsonResponse(items, safe=False) @require_http_methods(["GET"]) diff --git a/members/views/members.py b/members/views/members.py index 0321296..c50ed79 100644 --- a/members/views/members.py +++ b/members/views/members.py @@ -206,7 +206,6 @@ def member_edit(request, *args, **kwargs): class MemberAutoComplete(autocomplete.Select2QuerySetView): - @method_decorator(login_required(login_url='/login')) def get_queryset(self): qs = Member.objects.all() diff --git a/sikweb/base.py b/sikweb/base.py index aa5ec1c..3b7637f 100644 --- a/sikweb/base.py +++ b/sikweb/base.py @@ -251,6 +251,9 @@ STATICFILES_DIRS = ( MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_URL = '/media/' +LOGIN_URL = '/login/' +LOGIN_REDIRECT_URL = '/admin' + SUIT_CONFIG = { # header 'ADMIN_NAME': 'SIK Admin',