mirror of https://github.com/snachodog/mybuddy.git
Raise permission denied instead of redirecting to login (#49).
This commit is contained in:
parent
ab2717ed56
commit
08488af718
|
@ -1,5 +1,12 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- 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):
|
class StaffOnlyMixin(AccessMixin):
|
||||||
|
|
|
@ -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 %}
|
|
@ -2,8 +2,7 @@
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth import update_session_auth_hash
|
from django.contrib.auth import update_session_auth_hash
|
||||||
from django.contrib.auth.forms import PasswordChangeForm
|
from django.contrib.auth.forms import PasswordChangeForm
|
||||||
from django.contrib.auth.mixins import (LoginRequiredMixin,
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
PermissionRequiredMixin)
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.contrib.messages.views import SuccessMessageMixin
|
from django.contrib.messages.views import SuccessMessageMixin
|
||||||
from django.shortcuts import redirect, render
|
from django.shortcuts import redirect, render
|
||||||
|
@ -15,15 +14,12 @@ from django.views.generic.edit import CreateView, UpdateView, DeleteView
|
||||||
from django_filters.views import FilterView
|
from django_filters.views import FilterView
|
||||||
|
|
||||||
from babybuddy import forms
|
from babybuddy import forms
|
||||||
from babybuddy.mixins import StaffOnlyMixin
|
from babybuddy.mixins import PermissionRequired403Mixin, StaffOnlyMixin
|
||||||
from core import models
|
|
||||||
|
|
||||||
|
|
||||||
class RootRouter(LoginRequiredMixin, RedirectView):
|
class RootRouter(LoginRequiredMixin, RedirectView):
|
||||||
"""
|
"""
|
||||||
Redirects to the welcome page if no children are in the database, a child
|
Redirects to the site dashboard.
|
||||||
dashboard if only one child is in the database, and the dashboard page if
|
|
||||||
more than one child is in the database.
|
|
||||||
"""
|
"""
|
||||||
def get_redirect_url(self, *args, **kwargs):
|
def get_redirect_url(self, *args, **kwargs):
|
||||||
self.url = reverse('dashboard:dashboard')
|
self.url = reverse('dashboard:dashboard')
|
||||||
|
@ -38,7 +34,7 @@ class UserList(StaffOnlyMixin, FilterView):
|
||||||
filter_fields = ('username', 'first_name', 'last_name', 'email')
|
filter_fields = ('username', 'first_name', 'last_name', 'email')
|
||||||
|
|
||||||
|
|
||||||
class UserAdd(StaffOnlyMixin, PermissionRequiredMixin, SuccessMessageMixin,
|
class UserAdd(StaffOnlyMixin, PermissionRequired403Mixin, SuccessMessageMixin,
|
||||||
CreateView):
|
CreateView):
|
||||||
model = User
|
model = User
|
||||||
template_name = 'babybuddy/user_form.html'
|
template_name = 'babybuddy/user_form.html'
|
||||||
|
@ -48,8 +44,8 @@ class UserAdd(StaffOnlyMixin, PermissionRequiredMixin, SuccessMessageMixin,
|
||||||
success_message = 'User %(username)s added!'
|
success_message = 'User %(username)s added!'
|
||||||
|
|
||||||
|
|
||||||
class UserUpdate(StaffOnlyMixin, PermissionRequiredMixin, SuccessMessageMixin,
|
class UserUpdate(StaffOnlyMixin, PermissionRequired403Mixin,
|
||||||
UpdateView):
|
SuccessMessageMixin, UpdateView):
|
||||||
model = User
|
model = User
|
||||||
template_name = 'babybuddy/user_form.html'
|
template_name = 'babybuddy/user_form.html'
|
||||||
permission_required = ('admin.change_user',)
|
permission_required = ('admin.change_user',)
|
||||||
|
@ -58,7 +54,7 @@ class UserUpdate(StaffOnlyMixin, PermissionRequiredMixin, SuccessMessageMixin,
|
||||||
success_message = 'User %(username)s updated.'
|
success_message = 'User %(username)s updated.'
|
||||||
|
|
||||||
|
|
||||||
class UserDelete(StaffOnlyMixin, PermissionRequiredMixin,
|
class UserDelete(StaffOnlyMixin, PermissionRequired403Mixin,
|
||||||
DeleteView):
|
DeleteView):
|
||||||
model = User
|
model = User
|
||||||
template_name = 'babybuddy/user_confirm_delete.html'
|
template_name = 'babybuddy/user_confirm_delete.html'
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
|
||||||
from django.contrib.messages.views import SuccessMessageMixin
|
from django.contrib.messages.views import SuccessMessageMixin
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
@ -10,10 +9,11 @@ from django.views.generic.edit import CreateView, UpdateView, DeleteView
|
||||||
|
|
||||||
from django_filters.views import FilterView
|
from django_filters.views import FilterView
|
||||||
|
|
||||||
|
from babybuddy.mixins import PermissionRequired403Mixin
|
||||||
from core import forms, models, timeline
|
from core import forms, models, timeline
|
||||||
|
|
||||||
|
|
||||||
class CoreAddView(PermissionRequiredMixin, SuccessMessageMixin, CreateView):
|
class CoreAddView(PermissionRequired403Mixin, SuccessMessageMixin, CreateView):
|
||||||
def get_success_message(self, cleaned_data):
|
def get_success_message(self, cleaned_data):
|
||||||
cleaned_data['model'] = self.model._meta.verbose_name.title()
|
cleaned_data['model'] = self.model._meta.verbose_name.title()
|
||||||
if 'child' in cleaned_data:
|
if 'child' in cleaned_data:
|
||||||
|
@ -23,7 +23,8 @@ class CoreAddView(PermissionRequiredMixin, SuccessMessageMixin, CreateView):
|
||||||
return self.success_message % 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):
|
def get_success_message(self, cleaned_data):
|
||||||
cleaned_data['model'] = self.model._meta.verbose_name.title()
|
cleaned_data['model'] = self.model._meta.verbose_name.title()
|
||||||
if 'child' in cleaned_data:
|
if 'child' in cleaned_data:
|
||||||
|
@ -33,7 +34,7 @@ class CoreUpdateView(PermissionRequiredMixin, SuccessMessageMixin, UpdateView):
|
||||||
return self.success_message % cleaned_data
|
return self.success_message % cleaned_data
|
||||||
|
|
||||||
|
|
||||||
class CoreDeleteView(PermissionRequiredMixin, DeleteView):
|
class CoreDeleteView(PermissionRequired403Mixin, DeleteView):
|
||||||
"""
|
"""
|
||||||
SuccessMessageMixin is not compatible DeleteView.
|
SuccessMessageMixin is not compatible DeleteView.
|
||||||
See: https://code.djangoproject.com/ticket/21936
|
See: https://code.djangoproject.com/ticket/21936
|
||||||
|
@ -45,7 +46,7 @@ class CoreDeleteView(PermissionRequiredMixin, DeleteView):
|
||||||
return super(CoreDeleteView, self).delete(request, *args, **kwargs)
|
return super(CoreDeleteView, self).delete(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class ChildList(PermissionRequiredMixin, FilterView):
|
class ChildList(PermissionRequired403Mixin, FilterView):
|
||||||
model = models.Child
|
model = models.Child
|
||||||
template_name = 'core/child_list.html'
|
template_name = 'core/child_list.html'
|
||||||
permission_required = ('core.view_child',)
|
permission_required = ('core.view_child',)
|
||||||
|
@ -61,7 +62,7 @@ class ChildAdd(CoreAddView):
|
||||||
success_message = '%(first_name)s %(last_name)s added!'
|
success_message = '%(first_name)s %(last_name)s added!'
|
||||||
|
|
||||||
|
|
||||||
class ChildDetail(PermissionRequiredMixin, DetailView):
|
class ChildDetail(PermissionRequired403Mixin, DetailView):
|
||||||
model = models.Child
|
model = models.Child
|
||||||
permission_required = ('core.view_child',)
|
permission_required = ('core.view_child',)
|
||||||
|
|
||||||
|
@ -93,7 +94,7 @@ class ChildDelete(CoreUpdateView):
|
||||||
success_url = reverse_lazy('core:child-list')
|
success_url = reverse_lazy('core:child-list')
|
||||||
|
|
||||||
|
|
||||||
class DiaperChangeList(PermissionRequiredMixin, FilterView):
|
class DiaperChangeList(PermissionRequired403Mixin, FilterView):
|
||||||
model = models.DiaperChange
|
model = models.DiaperChange
|
||||||
template_name = 'core/diaperchange_list.html'
|
template_name = 'core/diaperchange_list.html'
|
||||||
permission_required = ('core.view_diaperchange',)
|
permission_required = ('core.view_diaperchange',)
|
||||||
|
@ -121,7 +122,7 @@ class DiaperChangeDelete(CoreDeleteView):
|
||||||
success_url = reverse_lazy('core:diaperchange-list')
|
success_url = reverse_lazy('core:diaperchange-list')
|
||||||
|
|
||||||
|
|
||||||
class FeedingList(PermissionRequiredMixin, FilterView):
|
class FeedingList(PermissionRequired403Mixin, FilterView):
|
||||||
model = models.Feeding
|
model = models.Feeding
|
||||||
template_name = 'core/feeding_list.html'
|
template_name = 'core/feeding_list.html'
|
||||||
permission_required = ('core.view_feeding',)
|
permission_required = ('core.view_feeding',)
|
||||||
|
@ -155,7 +156,7 @@ class FeedingDelete(CoreDeleteView):
|
||||||
success_url = reverse_lazy('core:feeding-list')
|
success_url = reverse_lazy('core:feeding-list')
|
||||||
|
|
||||||
|
|
||||||
class NoteList(PermissionRequiredMixin, FilterView):
|
class NoteList(PermissionRequired403Mixin, FilterView):
|
||||||
model = models.Note
|
model = models.Note
|
||||||
template_name = 'core/note_list.html'
|
template_name = 'core/note_list.html'
|
||||||
permission_required = ('core.view_note',)
|
permission_required = ('core.view_note',)
|
||||||
|
@ -183,7 +184,7 @@ class NoteDelete(CoreDeleteView):
|
||||||
success_url = reverse_lazy('core:note-list')
|
success_url = reverse_lazy('core:note-list')
|
||||||
|
|
||||||
|
|
||||||
class SleepList(PermissionRequiredMixin, FilterView):
|
class SleepList(PermissionRequired403Mixin, FilterView):
|
||||||
model = models.Sleep
|
model = models.Sleep
|
||||||
template_name = 'core/sleep_list.html'
|
template_name = 'core/sleep_list.html'
|
||||||
permission_required = ('core.view_sleep',)
|
permission_required = ('core.view_sleep',)
|
||||||
|
@ -217,7 +218,7 @@ class SleepDelete(CoreDeleteView):
|
||||||
success_url = reverse_lazy('core:sleep-list')
|
success_url = reverse_lazy('core:sleep-list')
|
||||||
|
|
||||||
|
|
||||||
class TimerList(PermissionRequiredMixin, FilterView):
|
class TimerList(PermissionRequired403Mixin, FilterView):
|
||||||
model = models.Timer
|
model = models.Timer
|
||||||
template_name = 'core/timer_list.html'
|
template_name = 'core/timer_list.html'
|
||||||
permission_required = ('core.view_timer',)
|
permission_required = ('core.view_timer',)
|
||||||
|
@ -225,12 +226,12 @@ class TimerList(PermissionRequiredMixin, FilterView):
|
||||||
filter_fields = ('active', 'user')
|
filter_fields = ('active', 'user')
|
||||||
|
|
||||||
|
|
||||||
class TimerDetail(PermissionRequiredMixin, DetailView):
|
class TimerDetail(PermissionRequired403Mixin, DetailView):
|
||||||
model = models.Timer
|
model = models.Timer
|
||||||
permission_required = ('core.view_timer',)
|
permission_required = ('core.view_timer',)
|
||||||
|
|
||||||
|
|
||||||
class TimerAdd(PermissionRequiredMixin, CreateView):
|
class TimerAdd(PermissionRequired403Mixin, CreateView):
|
||||||
model = models.Timer
|
model = models.Timer
|
||||||
permission_required = ('core.add_timer',)
|
permission_required = ('core.add_timer',)
|
||||||
form_class = forms.TimerForm
|
form_class = forms.TimerForm
|
||||||
|
@ -260,7 +261,7 @@ class TimerUpdate(CoreUpdateView):
|
||||||
return reverse('core:timer-detail', kwargs={'pk': instance.pk})
|
return reverse('core:timer-detail', kwargs={'pk': instance.pk})
|
||||||
|
|
||||||
|
|
||||||
class TimerAddQuick(PermissionRequiredMixin, RedirectView):
|
class TimerAddQuick(PermissionRequired403Mixin, RedirectView):
|
||||||
permission_required = ('core.add_timer',)
|
permission_required = ('core.add_timer',)
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
|
@ -271,7 +272,7 @@ class TimerAddQuick(PermissionRequiredMixin, RedirectView):
|
||||||
return super(TimerAddQuick, self).get(request, *args, **kwargs)
|
return super(TimerAddQuick, self).get(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class TimerRestart(PermissionRequiredMixin, RedirectView):
|
class TimerRestart(PermissionRequired403Mixin, RedirectView):
|
||||||
permission_required = ('core.change_timer',)
|
permission_required = ('core.change_timer',)
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
|
@ -284,7 +285,7 @@ class TimerRestart(PermissionRequiredMixin, RedirectView):
|
||||||
return reverse('core:timer-detail', kwargs={'pk': kwargs['pk']})
|
return reverse('core:timer-detail', kwargs={'pk': kwargs['pk']})
|
||||||
|
|
||||||
|
|
||||||
class TimerStop(PermissionRequiredMixin, SuccessMessageMixin, RedirectView):
|
class TimerStop(PermissionRequired403Mixin, SuccessMessageMixin, RedirectView):
|
||||||
permission_required = ('core.change_timer',)
|
permission_required = ('core.change_timer',)
|
||||||
success_message = '%(timer)s stopped.'
|
success_message = '%(timer)s stopped.'
|
||||||
|
|
||||||
|
@ -304,7 +305,7 @@ class TimerDelete(CoreDeleteView):
|
||||||
success_url = reverse_lazy('core:timer-list')
|
success_url = reverse_lazy('core:timer-list')
|
||||||
|
|
||||||
|
|
||||||
class TummyTimeList(PermissionRequiredMixin, FilterView):
|
class TummyTimeList(PermissionRequired403Mixin, FilterView):
|
||||||
model = models.TummyTime
|
model = models.TummyTime
|
||||||
template_name = 'core/tummytime_list.html'
|
template_name = 'core/tummytime_list.html'
|
||||||
permission_required = ('core.view_tummytime',)
|
permission_required = ('core.view_tummytime',)
|
||||||
|
@ -338,7 +339,7 @@ class TummyTimeDelete(CoreDeleteView):
|
||||||
success_url = reverse_lazy('core:tummytime-list')
|
success_url = reverse_lazy('core:tummytime-list')
|
||||||
|
|
||||||
|
|
||||||
class WeightList(PermissionRequiredMixin, FilterView):
|
class WeightList(PermissionRequired403Mixin, FilterView):
|
||||||
model = models.Weight
|
model = models.Weight
|
||||||
template_name = 'core/weight_list.html'
|
template_name = 'core/weight_list.html'
|
||||||
permission_required = ('core.view_weight',)
|
permission_required = ('core.view_weight',)
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from django.contrib.auth.mixins import (LoginRequiredMixin,
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
PermissionRequiredMixin)
|
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.views.generic.base import TemplateView
|
from django.views.generic.base import TemplateView
|
||||||
from django.views.generic.detail import DetailView
|
from django.views.generic.detail import DetailView
|
||||||
|
|
||||||
|
from babybuddy.mixins import PermissionRequired403Mixin
|
||||||
from core.models import Child
|
from core.models import Child
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,7 +33,8 @@ class Dashboard(LoginRequiredMixin, TemplateView):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class ChildDashboard(PermissionRequiredMixin, DetailView):
|
class ChildDashboard(PermissionRequired403Mixin, DetailView):
|
||||||
model = Child
|
model = Child
|
||||||
permission_required = ('core.view_child',)
|
permission_required = ('core.view_child',)
|
||||||
|
raise_exception = True
|
||||||
template_name = 'dashboard/child.html'
|
template_name = 'dashboard/child.html'
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
|
||||||
from django.views.generic.detail import DetailView
|
from django.views.generic.detail import DetailView
|
||||||
|
|
||||||
|
from babybuddy.mixins import PermissionRequired403Mixin
|
||||||
from core import models
|
from core import models
|
||||||
|
|
||||||
from . import graphs
|
from . import graphs
|
||||||
|
|
||||||
|
|
||||||
class DiaperChangeLifetimesChildReport(PermissionRequiredMixin, DetailView):
|
class DiaperChangeLifetimesChildReport(PermissionRequired403Mixin, DetailView):
|
||||||
"""
|
"""
|
||||||
Graph of diaper "lifetimes" - time between diaper changes.
|
Graph of diaper "lifetimes" - time between diaper changes.
|
||||||
"""
|
"""
|
||||||
|
@ -26,7 +26,7 @@ class DiaperChangeLifetimesChildReport(PermissionRequiredMixin, DetailView):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class DiaperChangeTypesChildReport(PermissionRequiredMixin, DetailView):
|
class DiaperChangeTypesChildReport(PermissionRequired403Mixin, DetailView):
|
||||||
"""
|
"""
|
||||||
Graph of diaper changes by day and type.
|
Graph of diaper changes by day and type.
|
||||||
"""
|
"""
|
||||||
|
@ -45,7 +45,7 @@ class DiaperChangeTypesChildReport(PermissionRequiredMixin, DetailView):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class FeedingDurationChildReport(PermissionRequiredMixin, DetailView):
|
class FeedingDurationChildReport(PermissionRequired403Mixin, DetailView):
|
||||||
"""
|
"""
|
||||||
Graph of feeding durations over time.
|
Graph of feeding durations over time.
|
||||||
"""
|
"""
|
||||||
|
@ -69,7 +69,7 @@ class FeedingDurationChildReport(PermissionRequiredMixin, DetailView):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class SleepPatternChildReport(PermissionRequiredMixin, DetailView):
|
class SleepPatternChildReport(PermissionRequired403Mixin, DetailView):
|
||||||
"""
|
"""
|
||||||
Graph of sleep pattern comparing sleep to wake times by day.
|
Graph of sleep pattern comparing sleep to wake times by day.
|
||||||
"""
|
"""
|
||||||
|
@ -93,7 +93,7 @@ class SleepPatternChildReport(PermissionRequiredMixin, DetailView):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class SleepTotalsChildReport(PermissionRequiredMixin, DetailView):
|
class SleepTotalsChildReport(PermissionRequired403Mixin, DetailView):
|
||||||
"""
|
"""
|
||||||
Graph of total sleep by day.
|
Graph of total sleep by day.
|
||||||
"""
|
"""
|
||||||
|
@ -117,7 +117,7 @@ class SleepTotalsChildReport(PermissionRequiredMixin, DetailView):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class WeightWeightChildReoport(PermissionRequiredMixin, DetailView):
|
class WeightWeightChildReoport(PermissionRequired403Mixin, DetailView):
|
||||||
"""
|
"""
|
||||||
Graph of weight change over time.
|
Graph of weight change over time.
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue