Skip to content

Commit

Permalink
Raise permission denied instead of redirecting to login (#49).
Browse files Browse the repository at this point in the history
  • Loading branch information
cdubz committed May 20, 2018
1 parent ab2717e commit 08488af
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 40 deletions.
9 changes: 8 additions & 1 deletion babybuddy/mixins.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# -*- coding: utf-8 -*-
from django.contrib.auth.mixins import AccessMixin
from django.contrib.auth.mixins import AccessMixin, PermissionRequiredMixin


class PermissionRequired403Mixin(PermissionRequiredMixin):
"""
Raise an exception instead of redirecting to login.
"""
raise_exception = True


class StaffOnlyMixin(AccessMixin):
Expand Down
15 changes: 15 additions & 0 deletions babybuddy/templates/403.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{% extends 'babybuddy/page.html' %}
{% load widget_tweaks %}

{% block title %}403 Permission Denied{% endblock %}

{% block breadcrumbs %}
<li class="breadcrumb-item active" aria-current="page">Permission Denied</li>
{% endblock %}

{% block content %}
<div class="alert alert-danger" role="alert">
You do not have permission to access this resource. Contact a site
administrator for assistance.
</div>
{% endblock %}
18 changes: 7 additions & 11 deletions babybuddy/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
from django.contrib import messages
from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.forms import PasswordChangeForm
from django.contrib.auth.mixins import (LoginRequiredMixin,
PermissionRequiredMixin)
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.models import User
from django.contrib.messages.views import SuccessMessageMixin
from django.shortcuts import redirect, render
Expand All @@ -15,15 +14,12 @@
from django_filters.views import FilterView

from babybuddy import forms
from babybuddy.mixins import StaffOnlyMixin
from core import models
from babybuddy.mixins import PermissionRequired403Mixin, StaffOnlyMixin


class RootRouter(LoginRequiredMixin, RedirectView):
"""
Redirects to the welcome page if no children are in the database, a child
dashboard if only one child is in the database, and the dashboard page if
more than one child is in the database.
Redirects to the site dashboard.
"""
def get_redirect_url(self, *args, **kwargs):
self.url = reverse('dashboard:dashboard')
Expand All @@ -38,7 +34,7 @@ class UserList(StaffOnlyMixin, FilterView):
filter_fields = ('username', 'first_name', 'last_name', 'email')


class UserAdd(StaffOnlyMixin, PermissionRequiredMixin, SuccessMessageMixin,
class UserAdd(StaffOnlyMixin, PermissionRequired403Mixin, SuccessMessageMixin,
CreateView):
model = User
template_name = 'babybuddy/user_form.html'
Expand All @@ -48,8 +44,8 @@ class UserAdd(StaffOnlyMixin, PermissionRequiredMixin, SuccessMessageMixin,
success_message = 'User %(username)s added!'


class UserUpdate(StaffOnlyMixin, PermissionRequiredMixin, SuccessMessageMixin,
UpdateView):
class UserUpdate(StaffOnlyMixin, PermissionRequired403Mixin,
SuccessMessageMixin, UpdateView):
model = User
template_name = 'babybuddy/user_form.html'
permission_required = ('admin.change_user',)
Expand All @@ -58,7 +54,7 @@ class UserUpdate(StaffOnlyMixin, PermissionRequiredMixin, SuccessMessageMixin,
success_message = 'User %(username)s updated.'


class UserDelete(StaffOnlyMixin, PermissionRequiredMixin,
class UserDelete(StaffOnlyMixin, PermissionRequired403Mixin,
DeleteView):
model = User
template_name = 'babybuddy/user_confirm_delete.html'
Expand Down
37 changes: 19 additions & 18 deletions core/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
from django.contrib import messages
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.contrib.messages.views import SuccessMessageMixin
from django.urls import reverse, reverse_lazy
from django.utils import timezone
Expand All @@ -10,10 +9,11 @@

from django_filters.views import FilterView

from babybuddy.mixins import PermissionRequired403Mixin
from core import forms, models, timeline


class CoreAddView(PermissionRequiredMixin, SuccessMessageMixin, CreateView):
class CoreAddView(PermissionRequired403Mixin, SuccessMessageMixin, CreateView):
def get_success_message(self, cleaned_data):
cleaned_data['model'] = self.model._meta.verbose_name.title()
if 'child' in cleaned_data:
Expand All @@ -23,7 +23,8 @@ def get_success_message(self, cleaned_data):
return self.success_message % cleaned_data


class CoreUpdateView(PermissionRequiredMixin, SuccessMessageMixin, UpdateView):
class CoreUpdateView(PermissionRequired403Mixin, SuccessMessageMixin,
UpdateView):
def get_success_message(self, cleaned_data):
cleaned_data['model'] = self.model._meta.verbose_name.title()
if 'child' in cleaned_data:
Expand All @@ -33,7 +34,7 @@ def get_success_message(self, cleaned_data):
return self.success_message % cleaned_data


class CoreDeleteView(PermissionRequiredMixin, DeleteView):
class CoreDeleteView(PermissionRequired403Mixin, DeleteView):
"""
SuccessMessageMixin is not compatible DeleteView.
See: https://code.djangoproject.com/ticket/21936
Expand All @@ -45,7 +46,7 @@ def delete(self, request, *args, **kwargs):
return super(CoreDeleteView, self).delete(request, *args, **kwargs)


class ChildList(PermissionRequiredMixin, FilterView):
class ChildList(PermissionRequired403Mixin, FilterView):
model = models.Child
template_name = 'core/child_list.html'
permission_required = ('core.view_child',)
Expand All @@ -61,7 +62,7 @@ class ChildAdd(CoreAddView):
success_message = '%(first_name)s %(last_name)s added!'


class ChildDetail(PermissionRequiredMixin, DetailView):
class ChildDetail(PermissionRequired403Mixin, DetailView):
model = models.Child
permission_required = ('core.view_child',)

Expand Down Expand Up @@ -93,7 +94,7 @@ class ChildDelete(CoreUpdateView):
success_url = reverse_lazy('core:child-list')


class DiaperChangeList(PermissionRequiredMixin, FilterView):
class DiaperChangeList(PermissionRequired403Mixin, FilterView):
model = models.DiaperChange
template_name = 'core/diaperchange_list.html'
permission_required = ('core.view_diaperchange',)
Expand Down Expand Up @@ -121,7 +122,7 @@ class DiaperChangeDelete(CoreDeleteView):
success_url = reverse_lazy('core:diaperchange-list')


class FeedingList(PermissionRequiredMixin, FilterView):
class FeedingList(PermissionRequired403Mixin, FilterView):
model = models.Feeding
template_name = 'core/feeding_list.html'
permission_required = ('core.view_feeding',)
Expand Down Expand Up @@ -155,7 +156,7 @@ class FeedingDelete(CoreDeleteView):
success_url = reverse_lazy('core:feeding-list')


class NoteList(PermissionRequiredMixin, FilterView):
class NoteList(PermissionRequired403Mixin, FilterView):
model = models.Note
template_name = 'core/note_list.html'
permission_required = ('core.view_note',)
Expand Down Expand Up @@ -183,7 +184,7 @@ class NoteDelete(CoreDeleteView):
success_url = reverse_lazy('core:note-list')


class SleepList(PermissionRequiredMixin, FilterView):
class SleepList(PermissionRequired403Mixin, FilterView):
model = models.Sleep
template_name = 'core/sleep_list.html'
permission_required = ('core.view_sleep',)
Expand Down Expand Up @@ -217,20 +218,20 @@ class SleepDelete(CoreDeleteView):
success_url = reverse_lazy('core:sleep-list')


class TimerList(PermissionRequiredMixin, FilterView):
class TimerList(PermissionRequired403Mixin, FilterView):
model = models.Timer
template_name = 'core/timer_list.html'
permission_required = ('core.view_timer',)
paginate_by = 10
filter_fields = ('active', 'user')


class TimerDetail(PermissionRequiredMixin, DetailView):
class TimerDetail(PermissionRequired403Mixin, DetailView):
model = models.Timer
permission_required = ('core.view_timer',)


class TimerAdd(PermissionRequiredMixin, CreateView):
class TimerAdd(PermissionRequired403Mixin, CreateView):
model = models.Timer
permission_required = ('core.add_timer',)
form_class = forms.TimerForm
Expand Down Expand Up @@ -260,7 +261,7 @@ def get_success_url(self):
return reverse('core:timer-detail', kwargs={'pk': instance.pk})


class TimerAddQuick(PermissionRequiredMixin, RedirectView):
class TimerAddQuick(PermissionRequired403Mixin, RedirectView):
permission_required = ('core.add_timer',)

def get(self, request, *args, **kwargs):
Expand All @@ -271,7 +272,7 @@ def get(self, request, *args, **kwargs):
return super(TimerAddQuick, self).get(request, *args, **kwargs)


class TimerRestart(PermissionRequiredMixin, RedirectView):
class TimerRestart(PermissionRequired403Mixin, RedirectView):
permission_required = ('core.change_timer',)

def get(self, request, *args, **kwargs):
Expand All @@ -284,7 +285,7 @@ def get_redirect_url(self, *args, **kwargs):
return reverse('core:timer-detail', kwargs={'pk': kwargs['pk']})


class TimerStop(PermissionRequiredMixin, SuccessMessageMixin, RedirectView):
class TimerStop(PermissionRequired403Mixin, SuccessMessageMixin, RedirectView):
permission_required = ('core.change_timer',)
success_message = '%(timer)s stopped.'

Expand All @@ -304,7 +305,7 @@ class TimerDelete(CoreDeleteView):
success_url = reverse_lazy('core:timer-list')


class TummyTimeList(PermissionRequiredMixin, FilterView):
class TummyTimeList(PermissionRequired403Mixin, FilterView):
model = models.TummyTime
template_name = 'core/tummytime_list.html'
permission_required = ('core.view_tummytime',)
Expand Down Expand Up @@ -338,7 +339,7 @@ class TummyTimeDelete(CoreDeleteView):
success_url = reverse_lazy('core:tummytime-list')


class WeightList(PermissionRequiredMixin, FilterView):
class WeightList(PermissionRequired403Mixin, FilterView):
model = models.Weight
template_name = 'core/weight_list.html'
permission_required = ('core.view_weight',)
Expand Down
7 changes: 4 additions & 3 deletions dashboard/views.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# -*- coding: utf-8 -*-
from django.contrib.auth.mixins import (LoginRequiredMixin,
PermissionRequiredMixin)
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.views.generic.base import TemplateView
from django.views.generic.detail import DetailView

from babybuddy.mixins import PermissionRequired403Mixin
from core.models import Child


Expand Down Expand Up @@ -33,7 +33,8 @@ def get_context_data(self, **kwargs):
return context


class ChildDashboard(PermissionRequiredMixin, DetailView):
class ChildDashboard(PermissionRequired403Mixin, DetailView):
model = Child
permission_required = ('core.view_child',)
raise_exception = True
template_name = 'dashboard/child.html'
14 changes: 7 additions & 7 deletions reports/views.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# -*- coding: utf-8 -*-
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.views.generic.detail import DetailView

from babybuddy.mixins import PermissionRequired403Mixin
from core import models

from . import graphs


class DiaperChangeLifetimesChildReport(PermissionRequiredMixin, DetailView):
class DiaperChangeLifetimesChildReport(PermissionRequired403Mixin, DetailView):
"""
Graph of diaper "lifetimes" - time between diaper changes.
"""
Expand All @@ -26,7 +26,7 @@ def get_context_data(self, **kwargs):
return context


class DiaperChangeTypesChildReport(PermissionRequiredMixin, DetailView):
class DiaperChangeTypesChildReport(PermissionRequired403Mixin, DetailView):
"""
Graph of diaper changes by day and type.
"""
Expand All @@ -45,7 +45,7 @@ def get_context_data(self, **kwargs):
return context


class FeedingDurationChildReport(PermissionRequiredMixin, DetailView):
class FeedingDurationChildReport(PermissionRequired403Mixin, DetailView):
"""
Graph of feeding durations over time.
"""
Expand All @@ -69,7 +69,7 @@ def get_context_data(self, **kwargs):
return context


class SleepPatternChildReport(PermissionRequiredMixin, DetailView):
class SleepPatternChildReport(PermissionRequired403Mixin, DetailView):
"""
Graph of sleep pattern comparing sleep to wake times by day.
"""
Expand All @@ -93,7 +93,7 @@ def get_context_data(self, **kwargs):
return context


class SleepTotalsChildReport(PermissionRequiredMixin, DetailView):
class SleepTotalsChildReport(PermissionRequired403Mixin, DetailView):
"""
Graph of total sleep by day.
"""
Expand All @@ -117,7 +117,7 @@ def get_context_data(self, **kwargs):
return context


class WeightWeightChildReoport(PermissionRequiredMixin, DetailView):
class WeightWeightChildReoport(PermissionRequired403Mixin, DetailView):
"""
Graph of weight change over time.
"""
Expand Down

0 comments on commit 08488af

Please sign in to comment.