Boulangerie_Website/backend/users/test_permissions.py
Louis Mazin 4db822aebe big maj
2026-10-05 17:52:28 +02:00

137 lines
8.9 KiB
Python

from django.contrib.auth import get_user_model
from rest_framework.test import APITestCase
from .models import PermissionDefaults, UserPermissions
from .permissions import PERMISSION_NAMES
class PermissionAPITests(APITestCase):
def setUp(self):
self.admin = get_user_model().objects.create_user(username='manager', is_staff=True)
self.alice = get_user_model().objects.create_user(username='alice')
self.bob = get_user_model().objects.create_user(username='bob')
self.event = dict(name='Rendez-vous', start_date='2030-01-07', end_date='2030-01-07', is_public=False)
self.note = dict(title='Information', content='', kind='info', is_public=True, recipient_ids=[])
self.leave = dict(kind='leave', start_date='2030-01-07', proposed_slots=[])
def edit_permissions(self, scope='team', user=None, reset=False, **values):
self.client.force_authenticate(self.admin)
data = self.client.get('/api/users/permissions/').data
settings = dict(data['defaults']) if scope == 'team' else dict.fromkeys(PERMISSION_NAMES, None)
settings.update(values)
return self.client.put('/api/users/permissions/', dict(scope=scope, user_id=(user or self.alice).pk,
expected_revision=data['revision'], reset_individual=reset, permissions=settings), format='json')
def test_current_and_future_users_inherit_team_rules(self):
self.assertEqual(self.edit_permissions(request_leave=False, create_personal_event=False, create_publication=False).status_code, 200)
newcomer = get_user_model().objects.create_user(username='new')
for person in [self.alice, newcomer]:
self.client.force_authenticate(person)
self.assertEqual(self.client.get('/api/users/me/').data['permissions'], dict.fromkeys(PERMISSION_NAMES, False))
def test_individual_allow_deny_and_return_to_team(self):
self.edit_permissions(request_leave=False)
self.edit_permissions(scope='user', request_leave=True, create_publication=False)
self.client.force_authenticate(self.alice)
self.assertEqual(self.client.get('/api/users/me/').data['permissions'], dict(request_leave=True, create_personal_event=True, create_publication=False))
self.edit_permissions(scope='user')
self.client.force_authenticate(self.alice)
self.assertFalse(self.client.get('/api/users/me/').data['permissions']['request_leave'])
self.assertTrue(self.client.get('/api/users/me/').data['permissions']['create_publication'])
def test_team_change_preserves_individual_overrides_unless_reset(self):
self.edit_permissions(scope='user', create_publication=True)
self.edit_permissions(create_publication=False)
self.client.force_authenticate(self.alice)
self.assertTrue(self.client.get('/api/users/me/').data['permissions']['create_publication'])
self.edit_permissions(reset=True, create_publication=False)
self.client.force_authenticate(self.alice)
self.assertFalse(self.client.get('/api/users/me/').data['permissions']['create_publication'])
self.assertIsNone(UserPermissions.objects.get(user=self.alice).create_publication)
def test_employee_cannot_manage_permissions(self):
self.client.force_authenticate(self.alice)
self.assertEqual(self.client.get('/api/users/permissions/').status_code, 403)
self.assertEqual(self.client.put('/api/users/permissions/', {}, format='json').status_code, 403)
self.assertEqual(self.client.patch('/api/users/me/', {'permissions': {'create_publication': True}}, format='json').status_code, 405)
def test_admin_always_allowed_and_permissions_not_mass_assignable(self):
self.edit_permissions(request_leave=False, create_personal_event=False, create_publication=False)
self.client.force_authenticate(self.admin)
self.assertEqual(self.client.get('/api/users/me/').data['permissions'], dict.fromkeys(PERMISSION_NAMES, True))
self.assertEqual(self.client.post('/api/notes/', self.note, format='json').status_code, 201)
result = self.client.patch(f'/api/users/{self.alice.pk}/', {'permissions': dict.fromkeys(PERMISSION_NAMES, True)}, format='json')
self.assertEqual(result.status_code, 200)
self.assertFalse(result.data['permissions']['create_publication'])
def test_stale_permission_update_returns_conflict(self):
result = self.edit_permissions(request_leave=False)
old_revision = result.data['revision']
self.edit_permissions(request_leave=True)
result = self.client.put('/api/users/permissions/', dict(scope='team', expected_revision=old_revision, permissions=dict.fromkeys(PERMISSION_NAMES, False)), format='json')
self.assertEqual(result.status_code, 409)
self.assertTrue(PermissionDefaults.objects.get().request_leave)
def test_team_cannot_inherit_and_invalid_requests_do_not_save(self):
result = self.edit_permissions(request_leave=None)
self.assertEqual(result.status_code, 400)
self.assertTrue(PermissionDefaults.objects.get().request_leave)
def test_leave_creation_and_preview_blocked_but_hours_allowed(self):
self.edit_permissions(request_leave=False)
self.client.force_authenticate(self.alice)
for path in ['/api/planning/requests/', '/api/planning/requests/preview/']:
self.assertEqual(self.client.post(path, self.leave, format='json').status_code, 403)
request = dict(kind='hours', start_date='2030-01-07', proposed_slots=[dict(start_time='08:00', end_time='12:00', end_day_offset=0)])
self.assertEqual(self.client.post('/api/planning/requests/', request, format='json').status_code, 201)
def test_pending_leave_can_be_read_and_cancelled_after_revocation(self):
self.client.force_authenticate(self.alice)
request = self.client.post('/api/planning/requests/', self.leave, format='json')
self.assertEqual(request.status_code, 201)
self.edit_permissions(request_leave=False)
self.client.force_authenticate(self.alice)
self.assertEqual(self.client.get('/api/planning/requests/').data['count'], 1)
self.assertEqual(self.client.post(f"/api/planning/requests/{request.data['id']}/decision/", {'action': 'cancel'}, format='json').status_code, 200)
def test_both_event_creation_routes_enforce_permission(self):
self.edit_permissions(create_personal_event=False)
self.client.force_authenticate(self.alice)
for path in ['/api/event/', '/api/event/create/']:
self.assertEqual(self.client.post(path, self.event, format='json').status_code, 403)
self.edit_permissions(scope='user', create_personal_event=True)
self.client.force_authenticate(self.alice)
self.assertEqual(self.client.post('/api/event/', self.event, format='json').status_code, 201)
def test_employee_events_stay_private_and_admin_can_publish(self):
self.client.force_authenticate(self.alice)
result = self.client.post('/api/event/', {**self.event, 'is_public': True}, format='json')
self.assertEqual(result.status_code, 201)
self.assertFalse(result.data['is_public'])
self.client.force_authenticate(self.admin)
result = self.client.post('/api/event/', {**self.event, 'is_public': True}, format='json')
self.assertTrue(result.data['is_public'])
def test_existing_personal_event_can_be_edited_after_creation_revoked(self):
self.client.force_authenticate(self.alice)
event = self.client.post('/api/event/', self.event, format='json').data
self.edit_permissions(create_personal_event=False)
self.client.force_authenticate(self.alice)
self.assertEqual(self.client.patch(f"/api/event/{event['id']}/", {'name': 'Rendez-vous modifié'}, format='json').status_code, 200)
def test_publications_blocked_but_reading_and_voting_still_allowed(self):
self.client.force_authenticate(self.admin)
poll = self.client.post('/api/notes/', dict(title='Question', kind='poll', is_public=True, recipient_ids=[], poll_settings=dict(vote_mode='single', options=['Oui', 'Non'])), format='json')
self.assertEqual(poll.status_code, 201, poll.data)
self.edit_permissions(create_publication=False)
self.client.force_authenticate(self.alice)
self.assertEqual(self.client.post('/api/notes/', self.note, format='json').status_code, 403)
self.assertEqual(self.client.get('/api/notes/').status_code, 200)
result = self.client.put(f"/api/notes/{poll.data['id']}/vote/", {'option_ids': [poll.data['poll']['options'][0]['id']]}, format='json')
self.assertEqual(result.status_code, 200, result.data)
def test_default_permissions_preserve_existing_behaviour(self):
self.client.force_authenticate(self.alice)
self.assertEqual(self.client.get('/api/users/me/').data['permissions'], dict.fromkeys(PERMISSION_NAMES, True))
self.assertEqual(self.client.post('/api/notes/', self.note, format='json').status_code, 201)