GooDrive/backend/drive/test_protected_deletions.py
Louis Mazin 8ec0397288 nice
2026-10-14 16:54:05 +02:00

169 lines
9.8 KiB
Python

"""Deletion contract: admin may remove shared spaces, never private spaces.
Run: USE_SQLITE=true python manage.py test drive.test_protected_deletions
"""
import tempfile
import uuid
from pathlib import Path
from django.contrib.auth import get_user_model
from django.test import TestCase, override_settings
from rest_framework.test import APIClient
from .models import DriveItem, DriveSpace, SpaceGrant, ArchivedDriveAccount
from .spaces import ensure_space, ensure_private_space, create_space
class ProtectedDeletionTests(TestCase):
def setUp(self):
tmp = tempfile.TemporaryDirectory()
self.addCleanup(tmp.cleanup)
self.storage = Path(tmp.name)
override = override_settings(DRIVE_STORAGE_ROOT=self.storage,
FILE_UPLOAD_TEMP_DIR=str(self.storage / '.uploads'))
override.enable()
self.addCleanup(override.disable)
User = get_user_model()
self.admin = User.objects.create_superuser('test-admin', 'admin@example.org', 'VeryStrongPass123!')
self.alice = User.objects.create_user('test-alice', password='VeryStrongPass123!')
self.root = ensure_space(self.admin)
self.admin_private = ensure_private_space(self.admin)
self.assigned = create_space(self.alice, self.root, 'Alice partagé')
self.private = ensure_private_space(self.alice)
self.client = APIClient()
self.client.force_authenticate(user=self.admin)
def private_file(self):
item = DriveItem.objects.create(owner=self.alice, space=self.private,
name='mon-secret.txt', storage_key=str(uuid.uuid4()),
storage_location=f'{self.private.relative_path}/mon-secret.txt', size=6)
path = self.storage / item.storage_location
path.write_bytes(b'secret')
return item, path
def test_admin_cannot_browse_or_delete_any_other_private_space(self):
item, path = self.private_file()
result = self.client.get('/api/drive/spaces/')
self.assertEqual(result.status_code, 200, result.data)
self.assertNotIn(self.private.pk, [s['id'] for s in result.data['spaces']])
self.assertEqual(self.client.get('/api/drive/items/', {'space':self.private.pk}).status_code, 403)
self.assertEqual(self.client.get('/api/drive/stats/', {'space':self.private.pk}).status_code, 403)
self.assertEqual(self.client.post(f'/api/drive/items/{item.pk}/link/').status_code, 403)
self.assertEqual(self.client.delete(f'/api/drive/spaces/{self.private.pk}/',
{'confirm_name':self.private.display_name}, format='json').status_code, 403)
self.client.force_authenticate(user=self.alice)
self.assertEqual(self.client.delete(f'/api/drive/spaces/{self.private.pk}/',
{'confirm_name':self.private.display_name}, format='json').status_code, 403)
self.assertTrue(path.is_file())
def test_admin_can_delete_assigned_shared_space_without_private_loss(self):
secret, path = self.private_file()
shared_path = self.storage / self.assigned.relative_path
self.assertTrue(shared_path.is_dir())
with self.captureOnCommitCallbacks(execute=True):
res = self.client.delete(f'/api/drive/spaces/{self.assigned.pk}/',
{'confirm_name':self.assigned.display_name}, format='json')
self.assertEqual(res.status_code, 200, res.data)
self.assertFalse(DriveSpace.objects.filter(pk=self.assigned.pk).exists())
self.assertFalse(shared_path.exists())
self.private.refresh_from_db()
self.assertEqual(self.private.parent_id, self.root.pk)
self.assertTrue(path.exists())
self.assertTrue(DriveItem.objects.filter(pk=secret.pk).exists())
self.client.force_authenticate(user=self.alice)
self.assertIsNone(ensure_space(self.alice))
self.assertIsNone(self.client.get('/api/auth/me/').data['space_id'])
self.assertEqual(self.client.get('/api/drive/items/', {'space':self.private.pk}).status_code, 200)
self.assertEqual(self.client.get('/api/drive/items/', {'space':self.root.pk}).status_code, 403)
def test_admin_root_reset_keeps_root_and_private_files(self):
item, private_path = self.private_file()
root_folder = DriveItem.objects.create(owner=self.admin, space=self.root,
name='public-folder', is_folder=True)
public_path = self.storage / 'public-folder'
public_path.mkdir()
shared_path = self.storage / self.assigned.relative_path
self.assertTrue(shared_path.is_dir())
with self.captureOnCommitCallbacks(execute=True):
res = self.client.delete(f'/api/drive/spaces/{self.root.pk}/',
{'confirm_name':self.root.display_name}, format='json')
self.assertEqual(res.status_code, 200, res.data)
self.assertTrue(res.data['root_reset'])
self.assertTrue(DriveSpace.objects.filter(pk=self.root.pk).exists())
self.assertFalse(DriveSpace.objects.filter(pk=self.assigned.pk).exists())
self.assertFalse(DriveItem.objects.filter(pk=root_folder.pk).exists())
self.assertFalse(shared_path.exists())
self.assertFalse(public_path.exists())
self.assertTrue(private_path.exists())
self.assertTrue(DriveItem.objects.filter(pk=item.pk).exists())
self.assertTrue((self.storage/'privates').is_dir())
def test_user_deletion_removes_private_directory_and_keeps_shared_files(self):
item, path = self.private_file()
self.assertEqual(self.client.delete(f'/api/drive/admin/users/{self.admin.pk}/',
{'confirm_username':self.admin.username}, format='json').status_code, 403)
self.assertEqual(self.client.delete(f'/api/drive/admin/users/{self.alice.pk}/',
{'confirm_username':'wrong'}, format='json').status_code, 400)
shared = DriveItem.objects.create(owner=self.alice, space=self.root,
name='communal.txt', storage_key=str(uuid.uuid4()),
storage_location='communal.txt', size=4)
shared_path = self.storage / 'communal.txt'
shared_path.write_bytes(b'team')
with self.captureOnCommitCallbacks(execute=True):
self.assertEqual(self.client.delete(f'/api/drive/admin/users/{self.alice.pk}/',
{'confirm_username':self.alice.username}, format='json').status_code, 204)
self.alice.refresh_from_db()
self.assertFalse(self.alice.is_active)
self.assertFalse(self.alice.has_usable_password())
self.assertTrue(ArchivedDriveAccount.objects.filter(user=self.alice).exists())
self.assertNotIn(self.alice.pk, [u['id'] for u in self.client.get('/api/drive/admin/users/').data['users']])
self.assertFalse(path.exists())
self.assertFalse((self.storage / self.private.relative_path).exists())
self.assertFalse(DriveSpace.objects.filter(pk=self.private.pk).exists())
self.assertFalse(DriveItem.objects.filter(pk=item.pk).exists())
self.assertTrue(shared_path.exists())
self.assertTrue(DriveItem.objects.filter(pk=shared.pk).exists())
self.assertEqual(self.client.delete(f'/api/drive/admin/users/{self.alice.pk}/',
{'confirm_username':self.alice.username}, format='json').status_code, 404)
def test_non_admin_cannot_delete_other_users(self):
self.client.force_authenticate(user=self.alice)
self.assertEqual(self.client.delete(f'/api/drive/admin/users/{self.admin.pk}/',
{'confirm_username':self.admin.username}, format='json').status_code, 403)
def test_admin_can_revoke_space_grants_without_removing_private_storage(self):
from .models import SpaceGrant
# Access granted explicitly by invitation/existing-account grant.
grant = SpaceGrant.objects.create(user=self.alice, space=self.root,
can_write=True, can_invite=True)
rsp = self.client.get(f'/api/drive/admin/users/{self.alice.pk}/access/')
self.assertEqual(rsp.status_code, 200, rsp.data)
self.assertTrue(any(a['kind'] == 'grant' and a['space_id'] == self.root.pk
for a in rsp.data['accesses']))
self.assertNotIn(self.private.pk, [a['space_id'] for a in rsp.data['accesses']])
rsp = self.client.delete(f'/api/drive/admin/users/{self.alice.pk}/access/grant/{self.root.pk}/')
self.assertEqual(rsp.status_code, 204)
self.assertFalse(SpaceGrant.objects.filter(pk=grant.pk).exists())
self.assertTrue(DriveSpace.objects.filter(pk=self.root.pk).exists())
self.assertTrue(DriveSpace.objects.filter(pk=self.private.pk).exists())
# Older accounts are linked directly to their assigned shared space.
rsp = self.client.delete(f'/api/drive/admin/users/{self.alice.pk}/access/owner/{self.assigned.pk}/')
self.assertEqual(rsp.status_code, 204)
self.assigned.refresh_from_db()
self.assertIsNone(self.assigned.user_id)
self.assertIsNone(ensure_space(self.alice))
self.client.force_authenticate(user=self.alice)
self.assertEqual(self.client.get('/api/drive/items/', {'space':self.root.pk}).status_code,403)
self.assertEqual(self.client.get('/api/drive/items/', {'space':self.private.pk}).status_code,200)
self.assertEqual(self.client.get(f'/api/drive/admin/users/{self.alice.pk}/access/').status_code,403)
def test_account_delete_rejects_private_folder_outside_privates(self):
self.private.relative_path = f'{self.assigned.relative_path}/legacy'
self.private.save(update_fields=['relative_path'])
original = self.storage / self.private.relative_path
original.mkdir(parents=True, exist_ok=True)
rsp=self.client.delete(f'/api/drive/admin/users/{self.alice.pk}/',
{'confirm_username':self.alice.username},format='json')
self.assertEqual(rsp.status_code,409)
self.assertTrue(DriveSpace.objects.filter(pk=self.private.pk).exists())
self.assertTrue(original.exists())