Skip to content
This repository was archived by the owner on Jan 26, 2021. It is now read-only.

Added fix to disable unauthorized access by volunteers #430

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion vms/event/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from django.utils.decorators import method_decorator
from django.shortcuts import render_to_response
from django.http import Http404

from vms.utils import check_correct_volunteer_shift_sign_up

class AdministratorLoginRequiredMixin(object):

Expand Down Expand Up @@ -122,6 +122,7 @@ def get_queryset(self):


@login_required
@check_correct_volunteer_shift_sign_up
def list_sign_up(request, volunteer_id):
if request.method == 'POST':
form = EventDateForm(request.POST)
Expand Down
2 changes: 1 addition & 1 deletion vms/shift/tests/test_viewVolunteerShift.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def test_access_another_existing_volunteer_view(self):
def test_access_another_nonexisting_volunteer_view(self):
upcoming_shift_page = self.upcoming_shift_page
upcoming_shift_page.get_page(self.live_server_url, upcoming_shift_page.view_shift_page + '65459')
found = re.search('Not Found', self.driver.page_source)
found = re.search('You don\'t have the required rights', self.driver.page_source)
self.assertNotEqual(found, None)

def test_view_without_any_assigned_shift(self):
Expand Down
65 changes: 31 additions & 34 deletions vms/shift/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from django.views.generic import ListView
from django.utils.decorators import method_decorator
from django.core.urlresolvers import reverse_lazy

from vms.utils import check_correct_volunteer, check_correct_volunteer_shift

class AdministratorLoginRequiredMixin(object):

Expand All @@ -40,6 +40,10 @@ class AddHoursView(LoginRequiredMixin, FormView):
template_name = 'shift/add_hours.html'
form_class = HoursForm

@method_decorator(check_correct_volunteer_shift)
def dispatch(self, *args, **kwargs):
return super(AddHoursView, self).dispatch(*args, **kwargs)

def get_context_data(self, **kwargs):
context = super(AddHoursView, self).get_context_data(**kwargs)
shift_id = self.kwargs['shift_id']
Expand Down Expand Up @@ -161,13 +165,20 @@ def cancel(request, shift_id, volunteer_id):

# check that either an admin or volunteer is logged in
if not admin and not volunteer:
return HttpResponse(status=403)
return render(
request,
'vms/no_volunteer_rights.html',
status=403
)

# if a volunteer is logged in, verify that they are canceling their own shift
if volunteer:
if (int(volunteer.id) != int(volunteer_id)):
return HttpResponse(status=403)

return render(
request,
'vms/no_volunteer_rights.html',
status=403
)
if request.method == 'POST':
try:
cancel_shift_registration(volunteer_id, shift_id)
Expand Down Expand Up @@ -368,6 +379,11 @@ class EditHoursView(LoginRequiredMixin, FormView):
template_name = 'shift/edit_hours.html'
form_class = HoursForm

@method_decorator(check_correct_volunteer_shift)
def dispatch(self, *args, **kwargs):
return super(EditHoursView, self).dispatch(*args, **kwargs)


def get_context_data(self, **kwargs):
context = super(EditHoursView, self).get_context_data(**kwargs)
volunteer_id = self.kwargs['volunteer_id']
Expand Down Expand Up @@ -568,6 +584,10 @@ def sign_up(request, shift_id, volunteer_id):
class ViewHoursView(LoginRequiredMixin, FormView, TemplateView):
template_name = 'shift/hours_list.html'

@method_decorator(check_correct_volunteer)
def dispatch(self, *args, **kwargs):
return super(ViewHoursView, self).dispatch(*args, **kwargs)

def get_context_data(self, **kwargs):
context = super(ViewHoursView, self).get_context_data(**kwargs)
volunteer_id = self.kwargs['volunteer_id']
Expand All @@ -577,37 +597,14 @@ def get_context_data(self, **kwargs):


@login_required
@check_correct_volunteer
def view_volunteer_shifts(request, volunteer_id):
user = request.user
vol = None

try:
vol = user.volunteer
except ObjectDoesNotExist:
pass

# check that a volunteer is logged in
if vol:
if volunteer_id:
volunteer = get_volunteer_by_id(volunteer_id)
if volunteer:
user = request.user
if int(user.volunteer.id) == int(volunteer_id):
shift_list = get_unlogged_shifts_by_volunteer_id(volunteer_id)
return render(
request,
'shift/volunteer_shifts.html',
{'shift_list': shift_list, 'volunteer_id': volunteer_id, }
)
else:
return HttpResponse(status=403)
else:
raise Http404
else:
raise Http404
else:
return HttpResponse(status=403)

shift_list = get_unlogged_shifts_by_volunteer_id(volunteer_id)
return render(
request,
'shift/volunteer_shifts.html',
{'shift_list': shift_list, 'volunteer_id': volunteer_id, }
)

class VolunteerSearchView(AdministratorLoginRequiredMixin, FormView):
template_name = 'shift/volunteer_search.html'
Expand Down
22 changes: 22 additions & 0 deletions vms/vms/templates/vms/no_volunteer_rights.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{% extends "vms/base.html" %}

{% load i18n %}

{% block content %}
<div class="spacer"></div>

{% csrf_token %}
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">{% trans "No Access" %}</h3>
</div>
<div class="panel-body">
<br>
{% trans "You don't have the required rights" %}
<br>
<br>
<input type="button" class="btn btn-default" value="{% blocktrans %}Return to Previous Page{% endblocktrans %}" onClick="javascript:history.go(-1);">
</div>
</div>

{% endblock %}
120 changes: 120 additions & 0 deletions vms/vms/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
from functools import wraps
from django.http import Http404
from django.shortcuts import render
from volunteer.models import Volunteer


def check_correct_volunteer(func):
@wraps(func)
def wrapped_view(request, volunteer_id):
req_volunteer = getattr(request.user, "volunteer",
hasattr(request.user, "administrator"))
if not req_volunteer:
raise Http404
elif req_volunteer is not True:
try:
volunteer = Volunteer.objects.get(id=volunteer_id)
except Volunteer.DoesNotExist:
return render(
request,
"vms/no_volunteer_rights.html",
status=403
)
if volunteer.id == req_volunteer.id:
return func(request, volunteer_id=volunteer_id)
else:
return render(
request,
"vms/no_volunteer_rights.html",
status=403
)
else:
return render(
request,
"vms/no_volunteer_rights.html",
status=403
)
return render(
request,
"vms/no_volunteer_rights.html",
status=403
)
return wrapped_view


def check_correct_volunteer_shift(func):
@wraps(func)
def wrapped_view(request, shift_id, volunteer_id):
req_volunteer = getattr(request.user, "volunteer",
hasattr(request.user, "administrator"))
if not req_volunteer:
raise Http404
elif req_volunteer is not True:
try:
volunteer = Volunteer.objects.get(id=volunteer_id)
except Volunteer.DoesNotExist:
return render(
request,
"vms/no_volunteer_rights.html",
status=403
)
if volunteer.id == req_volunteer.id:
return func(request, volunteer_id=volunteer_id)
else:
return render(
request,
"vms/no_volunteer_rights.html",
status=403
)
else:
return render(
request,
"vms/no_volunteer_rights.html",
status=403
)
return render(
request,
"vms/no_volunteer_rights.html",
status=403
)
return wrapped_view


def check_correct_volunteer_shift_sign_up(func):
@wraps(func)
def wrapped_view(request, volunteer_id):
req_volunteer = getattr(request.user, "volunteer",
hasattr(request.user, "administrator"))
if req_volunteer is True:
return func(request, volunteer_id=volunteer_id)
if not req_volunteer:
raise Http404
elif req_volunteer is not True:
try:
volunteer = Volunteer.objects.get(id=volunteer_id)
except Volunteer.DoesNotExist:
return render(
request,
"vms/no_volunteer_rights.html",
status=403
)
if volunteer.id == req_volunteer.id:
return func(request, volunteer_id=volunteer_id)
else:
return render(
request,
"vms/no_volunteer_rights.html",
status=403
)
else:
return render(
request,
"vms/no_volunteer_rights.html",
status=403
)
return render(
request,
"vms/no_volunteer_rights.html",
status=403
)
return wrapped_view
16 changes: 15 additions & 1 deletion vms/volunteer/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
from volunteer.validation import validate_file
from django.views.generic import View
from django.core.urlresolvers import reverse_lazy

from vms.utils import check_correct_volunteer
from django.utils.decorators import method_decorator

@login_required
def download_resume(request, volunteer_id):
Expand Down Expand Up @@ -59,6 +60,11 @@ def delete_resume(request, volunteer_id):
'''

class VolunteerUpdateView(LoginRequiredMixin, UpdateView, FormView):

@method_decorator(check_correct_volunteer)
def dispatch(self, *args, **kwargs):
return super(VolunteerUpdateView, self).dispatch(*args, **kwargs)

form_class = VolunteerForm
template_name = 'volunteer/edit.html'
success_url = reverse_lazy('volunteer:profile')
Expand Down Expand Up @@ -108,6 +114,10 @@ def form_valid(self, form):
class ProfileView(LoginRequiredMixin, DetailView):
template_name = 'volunteer/profile.html'

@method_decorator(check_correct_volunteer)
def dispatch(self, *args, **kwargs):
return super(ProfileView, self).dispatch(*args, **kwargs)

def get_object(self, queryset=None):
volunteer_id = self.kwargs['volunteer_id']
obj = Volunteer.objects.get(id=self.kwargs['volunteer_id'])
Expand All @@ -123,6 +133,10 @@ def get_object(self, queryset=None):

class GenerateReportView(LoginRequiredMixin, View):

@method_decorator(check_correct_volunteer)
def dispatch(self, *args, **kwargs):
return super(GenerateReportView, self).dispatch(*args, **kwargs)

def get(self, request, *args, **kwargs):
view = ShowFormView.as_view()
return view(request, *args,**kwargs)
Expand Down