manager: add edit/view permissions to agendas (#13201)
This commit is contained in:
parent
f466770c8b
commit
6fa14100e3
|
@ -0,0 +1,29 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('auth', '0006_require_contenttypes_0002'),
|
||||
('agendas', '0009_auto_20160911_1640'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='event',
|
||||
options={'ordering': ['agenda', 'start_datetime', 'label']},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='agenda',
|
||||
name='edit_role',
|
||||
field=models.ForeignKey(related_name='+', default=None, verbose_name='Edit Role', to='auth.Group', blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='agenda',
|
||||
name='view_role',
|
||||
field=models.ForeignKey(related_name='+', default=None, verbose_name='View Role', to='auth.Group', blank=True, null=True),
|
||||
),
|
||||
]
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
import datetime
|
||||
|
||||
from django.contrib.auth.models import Group
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
from django.db import transaction
|
||||
|
@ -40,6 +41,10 @@ class Agenda(models.Model):
|
|||
_('Minimal booking delay (in days)'), default=1)
|
||||
maximal_booking_delay = models.PositiveIntegerField(
|
||||
_('Maximal booking delay (in days)'), default=56) # eight weeks
|
||||
edit_role = models.ForeignKey(Group, blank=True, null=True, default=None,
|
||||
related_name='+', verbose_name=_('Edit Role'))
|
||||
view_role = models.ForeignKey(Group, blank=True, null=True, default=None,
|
||||
related_name='+', verbose_name=_('View Role'))
|
||||
|
||||
class Meta:
|
||||
ordering = ['label']
|
||||
|
@ -62,6 +67,18 @@ class Agenda(models.Model):
|
|||
def get_absolute_url(self):
|
||||
return reverse('chrono-manager-agenda-view', kwargs={'pk': self.id})
|
||||
|
||||
def can_be_managed(self, user):
|
||||
if user.is_staff:
|
||||
return True
|
||||
group_ids = [x.id for x in user.groups.all()]
|
||||
return bool(self.edit_role_id in group_ids)
|
||||
|
||||
def can_be_viewed(self, user):
|
||||
if self.can_be_managed(user):
|
||||
return True
|
||||
group_ids = [x.id for x in user.groups.all()]
|
||||
return bool(self.view_role_id in group_ids)
|
||||
|
||||
|
||||
WEEKDAYS_LIST = sorted(WEEKDAYS.items(), key=lambda x: x[0])
|
||||
|
||||
|
|
|
@ -5,14 +5,18 @@
|
|||
<h2>{{ object.label }}
|
||||
<span class="identifier">[{% trans "identifier:" %} {{object.id}}]</span></h2>
|
||||
</h2>
|
||||
<a rel="popup" href="{% url 'chrono-manager-agenda-delete' pk=object.id %}">{% trans 'Delete' %}</a>
|
||||
<a rel="popup" href="{% url 'chrono-manager-agenda-edit' pk=object.id %}">{% trans 'Options' %}</a>
|
||||
{% if object.kind == "events" %}
|
||||
<a rel="popup" href="{% url 'chrono-manager-agenda-import-events' pk=object.id %}">{% trans 'Import Events' %}</a>
|
||||
<a rel="popup" href="{% url 'chrono-manager-agenda-add-event' pk=object.id %}">{% trans 'New Event' %}</a>
|
||||
{% else %}
|
||||
<a rel="popup" href="{% url 'chrono-manager-agenda-add-meeting-type' pk=object.id %}">{% trans 'New Meeting Type' %}</a>
|
||||
<a rel="popup" href="{% url 'chrono-manager-agenda-add-time-period' pk=object.id %}">{% trans 'New Time Period' %}</a>
|
||||
{% if user.is_staff %}
|
||||
<a rel="popup" href="{% url 'chrono-manager-agenda-delete' pk=object.id %}">{% trans 'Delete' %}</a>
|
||||
{% endif %}
|
||||
{% if user_can_manage %}
|
||||
<a rel="popup" href="{% url 'chrono-manager-agenda-edit' pk=object.id %}">{% trans 'Options' %}</a>
|
||||
{% if object.kind == "events" %}
|
||||
<a rel="popup" href="{% url 'chrono-manager-agenda-import-events' pk=object.id %}">{% trans 'Import Events' %}</a>
|
||||
<a rel="popup" href="{% url 'chrono-manager-agenda-add-event' pk=object.id %}">{% trans 'New Event' %}</a>
|
||||
{% else %}
|
||||
<a rel="popup" href="{% url 'chrono-manager-agenda-add-meeting-type' pk=object.id %}">{% trans 'New Meeting Type' %}</a>
|
||||
<a rel="popup" href="{% url 'chrono-manager-agenda-add-time-period' pk=object.id %}">{% trans 'New Time Period' %}</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
@ -39,7 +43,7 @@
|
|||
{% elif event.waiting_list_places %}
|
||||
data-total="{{event.waiting_list_places}}" data-booked="{{event.waiting_list}}"
|
||||
{% endif %}
|
||||
><a href="{% url 'chrono-manager-event-edit' pk=event.id %}">
|
||||
><a href="{% if user_can_manage %}{% url 'chrono-manager-event-edit' pk=event.id %}{% else %}#{% endif %}">
|
||||
{% if event.label %}{{event.label}} / {% endif %}
|
||||
{{ event.start_datetime }}
|
||||
{% if event.full %}/ <span class="full">{% trans "full" %}</span>{% endif %}
|
||||
|
@ -77,7 +81,7 @@
|
|||
<div>
|
||||
<ul class="objects-list single-links">
|
||||
{% for meeting_type in object.meetingtype_set.all %}
|
||||
<li><a href="{% url 'chrono-manager-meeting-type-edit' pk=meeting_type.id %}">
|
||||
<li><a href="{% if user_can_manage %}{% url 'chrono-manager-meeting-type-edit' pk=meeting_type.id %}{% else %}#{% endif %}">
|
||||
{{meeting_type.label}}
|
||||
<span class="identifier">[{% trans "identifier:" %} {{meeting_type.id}}]</span></h2>
|
||||
</a>
|
||||
|
@ -99,7 +103,7 @@
|
|||
<div>
|
||||
<ul class="objects-list single-links">
|
||||
{% for time_period in object.timeperiod_set.all %}
|
||||
<li><a href="{% url 'chrono-manager-time-period-edit' pk=time_period.id %}">
|
||||
<li><a href="{% if user_can_manage %}{% url 'chrono-manager-time-period-edit' pk=time_period.id %}{% else %}#{% endif %}">
|
||||
{{time_period.weekday_str}} / {{time_period.start_time}} → {{time_period.end_time}}
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
|
||||
{% block appbar %}
|
||||
<h2>{% trans 'Agendas' %}</h2>
|
||||
{% if user.is_staff %}
|
||||
<a rel="popup" href="{% url 'chrono-manager-agenda-add' %}">{% trans 'New' %}</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
import json
|
||||
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.urlresolvers import reverse, reverse_lazy
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.db.models import Q
|
||||
from django.http import HttpResponse, Http404
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.encoding import force_text
|
||||
from django.views.generic import (DetailView, CreateView, UpdateView,
|
||||
|
@ -34,13 +35,25 @@ class HomepageView(ListView):
|
|||
template_name = 'chrono/manager_home.html'
|
||||
model = Agenda
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super(HomepageView, self).get_queryset()
|
||||
if not self.request.user.is_staff:
|
||||
group_ids = [x.id for x in self.request.user.groups.all()]
|
||||
queryset = queryset.filter(Q(view_role_id__in=group_ids) | Q(edit_role_id__in=group_ids))
|
||||
return queryset
|
||||
|
||||
homepage = HomepageView.as_view()
|
||||
|
||||
|
||||
class AgendaAddView(CreateView):
|
||||
template_name = 'chrono/manager_agenda_form.html'
|
||||
model = Agenda
|
||||
fields = ['label', 'kind']
|
||||
fields = ['label', 'kind', 'edit_role', 'view_role']
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.user.is_staff:
|
||||
raise PermissionDenied()
|
||||
return super(AgendaAddView, self).dispatch(request, *args, **kwargs)
|
||||
|
||||
agenda_add = AgendaAddView.as_view()
|
||||
|
||||
|
@ -48,7 +61,13 @@ agenda_add = AgendaAddView.as_view()
|
|||
class AgendaEditView(UpdateView):
|
||||
template_name = 'chrono/manager_agenda_form.html'
|
||||
model = Agenda
|
||||
fields = ['label', 'minimal_booking_delay', 'maximal_booking_delay']
|
||||
fields = ['label', 'edit_role', 'view_role', 'minimal_booking_delay', 'maximal_booking_delay']
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
obj = super(AgendaEditView, self).get_object(queryset=queryset)
|
||||
if not obj.can_be_managed(self.request.user):
|
||||
raise PermissionDenied()
|
||||
return obj
|
||||
|
||||
agenda_edit = AgendaEditView.as_view()
|
||||
|
||||
|
@ -58,6 +77,11 @@ class AgendaDeleteView(DeleteView):
|
|||
model = Agenda
|
||||
success_url = reverse_lazy('chrono-manager-homepage')
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.user.is_staff:
|
||||
raise PermissionDenied()
|
||||
return super(AgendaDeleteView, self).dispatch(request, *args, **kwargs)
|
||||
|
||||
agenda_delete = AgendaDeleteView.as_view()
|
||||
|
||||
|
||||
|
@ -65,27 +89,65 @@ class AgendaView(DetailView):
|
|||
template_name = 'chrono/manager_agenda_view.html'
|
||||
model = Agenda
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(AgendaView, self).get_context_data(**kwargs)
|
||||
if not self.get_object().can_be_viewed(self.request.user):
|
||||
raise PermissionDenied()
|
||||
context['user_can_manage'] = self.get_object().can_be_managed(self.request.user)
|
||||
return context
|
||||
|
||||
agenda_view = AgendaView.as_view()
|
||||
|
||||
|
||||
class AgendaAddEventView(CreateView):
|
||||
class ManagedAgendaMixin(object):
|
||||
agenda = None
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
try:
|
||||
self.agenda = Agenda.objects.get(id=kwargs.get('pk'))
|
||||
except Agenda.DoesNotExist:
|
||||
raise Http404()
|
||||
if not self.agenda.can_be_managed(request.user):
|
||||
raise PermissionDenied()
|
||||
return super(ManagedAgendaMixin, self).dispatch(request,*args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ManagedAgendaMixin, self).get_context_data(**kwargs)
|
||||
context['agenda'] = self.agenda
|
||||
return context
|
||||
|
||||
def get_initial(self):
|
||||
initial = super(ManagedAgendaMixin, self).get_initial()
|
||||
initial['agenda'] = self.agenda.id
|
||||
return initial
|
||||
|
||||
def get_success_url(self):
|
||||
return self.agenda.get_absolute_url()
|
||||
|
||||
|
||||
class ManagedAgendaSubobjectMixin(object):
|
||||
agenda = None
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.agenda = self.get_object().agenda
|
||||
if not self.agenda.can_be_managed(request.user):
|
||||
raise PermissionDenied()
|
||||
return super(ManagedAgendaSubobjectMixin, self).dispatch(request,*args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ManagedAgendaSubobjectMixin, self).get_context_data(**kwargs)
|
||||
context['agenda'] = self.object.agenda
|
||||
return context
|
||||
|
||||
def get_success_url(self):
|
||||
return self.agenda.get_absolute_url()
|
||||
|
||||
|
||||
class AgendaAddEventView(ManagedAgendaMixin, CreateView):
|
||||
template_name = 'chrono/manager_event_form.html'
|
||||
model = Event
|
||||
form_class = EventForm
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('chrono-manager-agenda-view', kwargs={'pk': self.kwargs.get('pk')})
|
||||
|
||||
def get_initial(self):
|
||||
initial = super(AgendaAddEventView, self).get_initial()
|
||||
initial['agenda'] = self.kwargs.get('pk')
|
||||
return initial
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(AgendaAddEventView, self).get_context_data(**kwargs)
|
||||
context['agenda'] = Agenda.objects.get(id=self.kwargs.get('pk'))
|
||||
return context
|
||||
|
||||
agenda_add_event = AgendaAddEventView.as_view()
|
||||
|
||||
|
||||
|
@ -95,130 +157,66 @@ class AgendaImportEventsSampleView(TemplateView):
|
|||
|
||||
agenda_import_events_sample_csv = AgendaImportEventsSampleView.as_view()
|
||||
|
||||
class AgendaImportEventsView(FormView):
|
||||
|
||||
class AgendaImportEventsView(ManagedAgendaMixin, FormView):
|
||||
form_class = ImportEventsForm
|
||||
template_name = 'chrono/manager_import_events.html'
|
||||
agenda = None
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.agenda = get_object_or_404(Agenda, id=kwargs.get('pk'))
|
||||
return super(AgendaImportEventsView, self).dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(AgendaImportEventsView, self).get_context_data(**kwargs)
|
||||
context['agenda'] = self.agenda
|
||||
return context
|
||||
|
||||
def form_valid(self, form):
|
||||
if form.events:
|
||||
for event in form.events:
|
||||
event.agenda = self.agenda
|
||||
event.agenda_id = self.kwargs['pk']
|
||||
event.save()
|
||||
messages.info(self.request, _('%d events have been imported.') % len(form.events))
|
||||
return super(AgendaImportEventsView, self).form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('chrono-manager-agenda-view', kwargs={'pk': self.agenda.id})
|
||||
|
||||
agenda_import_events = AgendaImportEventsView.as_view()
|
||||
|
||||
|
||||
class EventEditView(UpdateView):
|
||||
class EventEditView(ManagedAgendaSubobjectMixin, UpdateView):
|
||||
template_name = 'chrono/manager_event_form.html'
|
||||
model = Event
|
||||
form_class = EventForm
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(EventEditView, self).get_context_data(**kwargs)
|
||||
context['agenda'] = self.object.agenda
|
||||
return context
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('chrono-manager-agenda-view', kwargs={'pk': self.object.agenda_id})
|
||||
|
||||
event_edit = EventEditView.as_view()
|
||||
|
||||
|
||||
class EventDeleteView(DeleteView):
|
||||
class EventDeleteView(ManagedAgendaSubobjectMixin, DeleteView):
|
||||
template_name = 'chrono/manager_confirm_delete.html'
|
||||
model = Event
|
||||
|
||||
def get_success_url(self):
|
||||
return self.object.agenda.get_absolute_url()
|
||||
|
||||
event_delete = EventDeleteView.as_view()
|
||||
|
||||
|
||||
class AgendaAddMeetingTypeView(CreateView):
|
||||
class AgendaAddMeetingTypeView(ManagedAgendaMixin, CreateView):
|
||||
template_name = 'chrono/manager_meeting_type_form.html'
|
||||
model = Event
|
||||
form_class = MeetingTypeForm
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('chrono-manager-agenda-view', kwargs={'pk': self.kwargs.get('pk')})
|
||||
|
||||
def get_initial(self):
|
||||
initial = super(AgendaAddMeetingTypeView, self).get_initial()
|
||||
initial['agenda'] = self.kwargs.get('pk')
|
||||
return initial
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(AgendaAddMeetingTypeView, self).get_context_data(**kwargs)
|
||||
context['agenda'] = Agenda.objects.get(id=self.kwargs.get('pk'))
|
||||
return context
|
||||
|
||||
agenda_add_meeting_type = AgendaAddMeetingTypeView.as_view()
|
||||
|
||||
class MeetingTypeEditView(UpdateView):
|
||||
class MeetingTypeEditView(ManagedAgendaSubobjectMixin, UpdateView):
|
||||
template_name = 'chrono/manager_meeting_type_form.html'
|
||||
model = MeetingType
|
||||
form_class = MeetingTypeForm
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(MeetingTypeEditView, self).get_context_data(**kwargs)
|
||||
context['agenda'] = self.object.agenda
|
||||
return context
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('chrono-manager-agenda-view', kwargs={'pk': self.object.agenda_id})
|
||||
|
||||
meeting_type_edit = MeetingTypeEditView.as_view()
|
||||
|
||||
|
||||
class AgendaAddTimePeriodView(CreateView):
|
||||
class AgendaAddTimePeriodView(ManagedAgendaMixin, CreateView):
|
||||
template_name = 'chrono/manager_time_period_form.html'
|
||||
model = Event
|
||||
form_class = TimePeriodForm
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('chrono-manager-agenda-view', kwargs={'pk': self.kwargs.get('pk')})
|
||||
|
||||
def get_initial(self):
|
||||
initial = super(AgendaAddTimePeriodView, self).get_initial()
|
||||
initial['agenda'] = self.kwargs.get('pk')
|
||||
return initial
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(AgendaAddTimePeriodView, self).get_context_data(**kwargs)
|
||||
context['agenda'] = Agenda.objects.get(id=self.kwargs.get('pk'))
|
||||
return context
|
||||
|
||||
agenda_add_time_period = AgendaAddTimePeriodView.as_view()
|
||||
|
||||
|
||||
class TimePeriodEditView(UpdateView):
|
||||
class TimePeriodEditView(ManagedAgendaSubobjectMixin, UpdateView):
|
||||
template_name = 'chrono/manager_time_period_form.html'
|
||||
model = TimePeriod
|
||||
form_class = TimePeriodForm
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(TimePeriodEditView, self).get_context_data(**kwargs)
|
||||
context['agenda'] = self.object.agenda
|
||||
return context
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('chrono-manager-agenda-view', kwargs={'pk': self.object.agenda_id})
|
||||
|
||||
time_period_edit = TimePeriodEditView.as_view()
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
from django.contrib.auth.decorators import user_passes_test
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.urlresolvers import RegexURLPattern, RegexURLResolver
|
||||
from django.db.models import Q
|
||||
|
||||
from .agendas.models import Agenda
|
||||
|
||||
|
||||
class DecoratedURLPattern(RegexURLPattern):
|
||||
def resolve(self, *args, **kwargs):
|
||||
|
@ -53,6 +57,10 @@ def manager_required(function=None, login_url=None):
|
|||
if user and user.is_staff:
|
||||
return True
|
||||
if user and not user.is_anonymous():
|
||||
# /manage/ is open to anyone authorized to view or edit an agenda.
|
||||
group_ids = [x.id for x in user.groups.all()]
|
||||
if Agenda.objects.filter(Q(view_role_id__in=group_ids) | Q(edit_role_id__in=group_ids)).exists():
|
||||
return True
|
||||
raise PermissionDenied()
|
||||
# As the last resort, show the login form
|
||||
return False
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.models import User, Group
|
||||
from django.utils.timezone import make_aware
|
||||
import datetime
|
||||
import pytest
|
||||
|
@ -20,6 +20,18 @@ def simple_user():
|
|||
user = User.objects.create_user('user', password='user')
|
||||
return user
|
||||
|
||||
@pytest.fixture
|
||||
def manager_user():
|
||||
try:
|
||||
user = User.objects.get(username='manager')
|
||||
except User.DoesNotExist:
|
||||
user = User.objects.create_user('manager', password='manager')
|
||||
group, created = Group.objects.get_or_create(name='Managers')
|
||||
if created:
|
||||
group.save()
|
||||
user.groups = [group]
|
||||
return user
|
||||
|
||||
@pytest.fixture
|
||||
def admin_user():
|
||||
try:
|
||||
|
@ -46,6 +58,26 @@ def test_simple_user_access(app, simple_user):
|
|||
app = login(app, username='user', password='user')
|
||||
assert app.get('/manage/', status=403)
|
||||
|
||||
def test_manager_user_access(app, manager_user):
|
||||
# connect while being logged as a manager user, access should be granted if
|
||||
# there's at least an agenda that is viewable or editable.
|
||||
app = login(app, username='manager', password='manager')
|
||||
assert app.get('/manage/', status=403)
|
||||
|
||||
agenda = Agenda(label=u'Foo bar')
|
||||
agenda.save()
|
||||
assert app.get('/manage/', status=403)
|
||||
|
||||
agenda.view_role = manager_user.groups.all()[0]
|
||||
agenda.edit_role = None
|
||||
agenda.save()
|
||||
assert app.get('/manage/', status=200)
|
||||
|
||||
agenda.edit_role = manager_user.groups.all()[0]
|
||||
agenda.view_role = None
|
||||
agenda.save()
|
||||
assert app.get('/manage/', status=200)
|
||||
|
||||
def test_home_redirect(app):
|
||||
assert app.get('/', status=302).location == 'http://localhost:80/manage/'
|
||||
|
||||
|
@ -73,17 +105,44 @@ def test_menu_json(app, admin_user):
|
|||
resp2 = app.get('/manage/menu.json?callback=Q', status=200)
|
||||
assert resp2.body == 'Q(%s);' % resp.body
|
||||
|
||||
def test_view_agendas_as_manager(app, manager_user):
|
||||
agenda = Agenda(label=u'Foo Bar')
|
||||
agenda.view_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
|
||||
agenda = Agenda(label=u'Bar Foo')
|
||||
agenda.save()
|
||||
|
||||
app = login(app, username='manager', password='manager')
|
||||
resp = app.get('/manage/', status=200)
|
||||
assert 'Foo Bar' in resp.body
|
||||
assert 'Bar Foo' not in resp.body
|
||||
assert 'New' not in resp.body
|
||||
|
||||
app.get('/manage/agendas/%s/' % agenda.id, status=403)
|
||||
|
||||
def test_add_agenda(app, admin_user):
|
||||
app = login(app)
|
||||
resp = app.get('/manage/', status=200)
|
||||
resp = resp.click('New')
|
||||
resp.form['label'] = 'Foo bar'
|
||||
resp = resp.form.submit()
|
||||
|
||||
agenda = Agenda.objects.get(label='Foo bar')
|
||||
assert resp.location == 'http://localhost:80/manage/agendas/%s/' % agenda.id
|
||||
resp = resp.follow()
|
||||
assert '<h2>Foo bar' in resp.body
|
||||
|
||||
def test_add_agenda_as_manager(app, manager_user):
|
||||
# open /manage/ access to manager_user, and check agenda creation is not
|
||||
# allowed.
|
||||
agenda = Agenda(label='Foo bar')
|
||||
agenda.view_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
app = login(app, username='manager', password='manager')
|
||||
resp = app.get('/manage/', status=200)
|
||||
resp = app.get('/manage/agendas/add/', status=403)
|
||||
|
||||
def test_options_agenda(app, admin_user):
|
||||
agenda = Agenda(label=u'Foo bar')
|
||||
agenda.save()
|
||||
|
@ -98,6 +157,29 @@ def test_options_agenda(app, admin_user):
|
|||
resp = resp.follow()
|
||||
assert '<h2>Foo baz' in resp.body
|
||||
|
||||
def test_options_agenda_as_manager(app, manager_user):
|
||||
agenda = Agenda(label=u'Foo bar')
|
||||
agenda.view_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
app = login(app, username='manager', password='manager')
|
||||
resp = app.get('/manage/', status=200)
|
||||
resp = resp.click('Foo bar')
|
||||
assert not 'Options' in resp.body
|
||||
resp = app.get('/manage/agendas/%s/edit' % agenda.id, status=403)
|
||||
|
||||
agenda.edit_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
|
||||
resp = app.get('/manage/', status=200)
|
||||
resp = resp.click('Foo bar')
|
||||
resp = resp.click('Options')
|
||||
assert resp.form['label'].value == 'Foo bar'
|
||||
resp.form['label'] = 'Foo baz'
|
||||
resp = resp.form.submit()
|
||||
assert resp.location == 'http://localhost:80/manage/agendas/%s/' % agenda.id
|
||||
resp = resp.follow()
|
||||
assert '<h2>Foo baz' in resp.body
|
||||
|
||||
def test_delete_agenda(app, admin_user):
|
||||
agenda = Agenda(label=u'Foo bar')
|
||||
agenda.save()
|
||||
|
@ -110,6 +192,17 @@ def test_delete_agenda(app, admin_user):
|
|||
resp = resp.follow()
|
||||
assert not 'Foo bar' in resp.body
|
||||
|
||||
def test_delete_agenda_as_manager(app, manager_user):
|
||||
agenda = Agenda(label=u'Foo bar')
|
||||
agenda.edit_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
app = login(app, username='manager', password='manager')
|
||||
resp = app.get('/manage/', status=200)
|
||||
resp = resp.click('Foo bar')
|
||||
assert 'Options' in resp.body
|
||||
assert 'Delete' not in resp.body
|
||||
resp = app.get('/manage/agendas/%s/delete' % agenda.id, status=403)
|
||||
|
||||
def test_add_event(app, admin_user):
|
||||
agenda = Agenda(label=u'Foo bar')
|
||||
agenda.save()
|
||||
|
@ -127,6 +220,35 @@ def test_add_event(app, admin_user):
|
|||
assert 'Feb. 15, 2016, 5 p.m.' in resp.body
|
||||
assert '10 places' in resp.body
|
||||
|
||||
def test_add_event_on_missing_agenda(app, admin_user):
|
||||
app = login(app)
|
||||
app.get('/manage/agendas/%s/add-event' % '999', status=404)
|
||||
|
||||
def test_add_event_as_manager(app, manager_user):
|
||||
agenda = Agenda(label=u'Foo bar')
|
||||
agenda.view_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
app = login(app, username='manager', password='manager')
|
||||
resp = app.get('/manage/agendas/%s/' % agenda.id, status=200)
|
||||
assert "This agenda doesn't have any event yet." in resp.body
|
||||
assert '>New Event<' not in resp.body
|
||||
app.get('/manage/agendas/%s/add-event' % agenda.id, status=403)
|
||||
|
||||
agenda.edit_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
|
||||
resp = app.get('/manage/agendas/%s/' % agenda.id, status=200)
|
||||
resp = resp.click('New Event')
|
||||
resp.form['start_datetime'] = '2016-02-15 17:00'
|
||||
resp.form['places'] = 10
|
||||
resp = resp.form.submit()
|
||||
resp = resp.follow()
|
||||
event = Event.objects.get(places=10)
|
||||
assert not "This agenda doesn't have any event yet." in resp.body
|
||||
assert '/manage/events/%s/' % event.id in resp.body
|
||||
assert 'Feb. 15, 2016, 5 p.m.' in resp.body
|
||||
assert '10 places' in resp.body
|
||||
|
||||
def test_edit_event(app, admin_user):
|
||||
agenda = Agenda(label=u'Foo bar')
|
||||
agenda.save()
|
||||
|
@ -145,6 +267,35 @@ def test_edit_event(app, admin_user):
|
|||
assert 'Feb. 16, 2016, 5 p.m.' in resp.body
|
||||
assert '20 places' in resp.body
|
||||
|
||||
def test_edit_missing_event(app, admin_user):
|
||||
app = login(app)
|
||||
app.get('/manage/agendas/999/', status=404)
|
||||
|
||||
def test_edit_event_as_manager(app, manager_user):
|
||||
agenda = Agenda(label=u'Foo bar')
|
||||
agenda.view_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
event = Event(start_datetime=datetime.datetime(2016, 2, 15, 17, 0),
|
||||
places=20, agenda=agenda)
|
||||
event.save()
|
||||
app = login(app, username='manager', password='manager')
|
||||
resp = app.get('/manage/agendas/%s/' % agenda.id, status=200)
|
||||
assert '/events/%s/' % event.id not in resp.body
|
||||
resp = app.get('/manage/events/%s/' % event.id, status=403)
|
||||
|
||||
agenda.edit_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
resp = app.get('/manage/agendas/%s/' % agenda.id, status=200)
|
||||
resp = resp.click('Feb. 15, 2016, 5 p.m.')
|
||||
assert resp.form['start_datetime'].value == '15/02/2016 17:00'
|
||||
resp.form['start_datetime'] = '2016-02-16 17:00'
|
||||
resp.form['places'] = 20
|
||||
resp = resp.form.submit()
|
||||
resp = resp.follow()
|
||||
assert '/manage/events/%s/' % event.id in resp.body
|
||||
assert 'Feb. 16, 2016, 5 p.m.' in resp.body
|
||||
assert '20 places' in resp.body
|
||||
|
||||
def test_booked_places(app, admin_user):
|
||||
agenda = Agenda(label=u'Foo bar')
|
||||
agenda.save()
|
||||
|
@ -199,6 +350,22 @@ def test_delete_event(app, admin_user):
|
|||
assert resp.location == 'http://localhost:80/manage/agendas/%s/' % agenda.id
|
||||
assert Event.objects.count() == 0
|
||||
|
||||
def test_delete_event_as_manager(app, manager_user):
|
||||
agenda = Agenda(label=u'Foo bar')
|
||||
agenda.edit_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
event = Event(start_datetime=datetime.datetime(2016, 2, 15, 17, 0),
|
||||
places=10, agenda=agenda)
|
||||
event.save()
|
||||
|
||||
app = login(app, username='manager', password='manager')
|
||||
resp = app.get('/manage/agendas/%s/' % agenda.id, status=200)
|
||||
resp = resp.click(href='/manage/events/%s' % event.id)
|
||||
resp = resp.click('Delete')
|
||||
resp = resp.form.submit()
|
||||
assert resp.location == 'http://localhost:80/manage/agendas/%s/' % agenda.id
|
||||
assert Event.objects.count() == 0
|
||||
|
||||
def test_import_events(app, admin_user):
|
||||
agenda = Agenda(label=u'Foo bar')
|
||||
agenda.save()
|
||||
|
|
Loading…
Reference in New Issue