manager: set a dedicated 403 response on home page (#48367)

This commit is contained in:
Nicolas Roche 2020-12-03 10:54:56 +01:00
parent 4cd2ba019c
commit ef55e9de56
5 changed files with 30 additions and 33 deletions

View File

@ -35,12 +35,19 @@
</div>
{% endfor %}
{% else %}
{% if user.is_staff %}
<div class="big-msg-info">
{% blocktrans %}
This site doesn't have any agenda yet. Click on the "New" button in the top
right of the page to add a first one.
{% endblocktrans %}
</div>
{% else %}
<div class="big-msg-sorry">
<p>{% trans 'This screen display agendas you can access.' %}</p>
<p>{% trans 'Unfortunately, there is still no agenda configurated this way.' %}</p>
</div>
{% endif %}
{% endif %}
{% endblock %}

View File

@ -118,6 +118,15 @@ class HomepageView(ListView):
queryset = queryset.filter(Q(view_role_id__in=group_ids) | Q(edit_role_id__in=group_ids))
return queryset.order_by('category__label', 'label')
def get(self, request, *args, **kwargs):
self.object_list = self.get_queryset()
context = self.get_context_data()
if self.request.user.is_staff or self.object_list.count():
status = 200
else:
status = 403
return self.render_to_response(context, status=status)
homepage = HomepageView.as_view()
@ -2389,6 +2398,8 @@ class UnavailabilityCalendarListView(ListView):
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))
if not queryset.count():
raise PermissionDenied
return queryset.order_by('label')

View File

@ -15,11 +15,12 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.conf.urls import include, url
from django.conf.urls.static import static
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from .urls_utils import decorated_includes, manager_required
from .urls_utils import decorated_includes
from .views import homepage, LoginView, LogoutView
from .api.urls import urlpatterns as chrono_api_urls
@ -28,7 +29,7 @@ from .manager.urls import urlpatterns as chrono_manager_urls
urlpatterns = [
url(r'^$', homepage, name='home'),
url(r'^manage/', decorated_includes(manager_required, include(chrono_manager_urls))),
url(r'^manage/', decorated_includes(login_required, include(chrono_manager_urls))),
url(r'^api/', include(chrono_api_urls)),
url(r'^logout/$', LogoutView.as_view(), name='auth_logout'),
url(r'^login/$', LoginView.as_view(), name='auth_login'),

View File

@ -46,27 +46,3 @@ def decorated_includes(func, includes, *args, **kwargs):
item._decorate_with = func
return urlconf_module, app_name, namespace
def manager_required(function=None, login_url=None):
def check_manager(user):
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()
or UnavailabilityCalendar.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
actual_decorator = user_passes_test(check_manager, login_url=login_url)
if function:
return actual_decorator(function)
return actual_decorator

View File

@ -108,7 +108,9 @@ def test_unlogged_access(app):
def test_simple_user_access(app, simple_user):
# connect while being logged as a simple user, access should be forbidden
app = login(app, username='user', password='user')
assert app.get('/manage/', status=403)
resp = app.get('/manage/', status=403)
assert 'Unfortunately, there is still no agenda' in resp.html.find(
'div', {'class': 'big-msg-sorry'}).text
def test_manager_user_access(app, manager_user):
@ -126,8 +128,8 @@ def test_manager_user_access(app, manager_user):
agenda.save()
assert app.get('/manage/', status=200)
agenda.edit_role = manager_user.groups.all()[0]
agenda.view_role = None
agenda.edit_role = None
agenda.view_role = manager_user.groups.all()[0]
agenda.save()
assert app.get('/manage/', status=200)
@ -2994,7 +2996,7 @@ def test_agenda_day_view(app, admin_user, manager_user, api_user):
resp = app.get(
'/manage/agendas/%s/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day), status=200
)
assert len(ctx.captured_queries) == 14
assert len(ctx.captured_queries) == 12
# day is displaying rows from 10am to 6pm,
# opening hours, 10am to 1pm gives top: 300%
# rest of the day, 1pm to 6(+1)pm gives 600%
@ -3934,7 +3936,7 @@ def test_virtual_agenda_day_view(app, admin_user, manager_user):
resp = app.get(
'/manage/agendas/%s/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day), status=200
)
assert len(ctx.captured_queries) == 15
assert len(ctx.captured_queries) == 13
# day is displaying rows from 10am to 6pm,
# opening hours, 10am to 1pm gives top: 300%
# rest of the day, 1pm to 6(+1)pm gives 600%
@ -5037,12 +5039,12 @@ def test_unavailability_calendar_homepage_permission(app, manager_user):
unavailability_calendar.view_role = group
unavailability_calendar.edit_role = None
unavailability_calendar.save()
resp = app.get('/manage/')
resp = app.get('/manage/', status=403)
resp = resp.click('Unavailability calendars')
unavailability_calendar.view_role = None
unavailability_calendar.edit_role = group
unavailability_calendar.save()
resp = app.get('/manage/')
resp = app.get('/manage/', status=403)
resp = resp.click('Unavailability calendars')