GooDrive/backend/drive/test_protected_deletions.py
Louis Mazin 7da4c7cd67 nice
2026-10-14 16:35:14 +02:00

122 lines
6.9 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_anonymizes_account_but_keeps_private(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)
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.assertTrue(path.exists())
self.assertTrue(DriveSpace.objects.filter(pk=self.private.pk, private_owner=self.alice).exists())
self.assertTrue(DriveItem.objects.filter(pk=item.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)