Skip to content

Commit 57003c6

Browse files
committed
[Fix readthedocs#4576] Do not delete projects which have multiple users
1 parent dde104d commit 57003c6

File tree

3 files changed

+43
-3
lines changed

3 files changed

+43
-3
lines changed

readthedocs/core/signals.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from django.dispatch import receiver
1313
from future.backports.urllib.parse import urlparse
1414

15+
from readthedocs.oauth.models import RemoteOrganization
1516
from readthedocs.projects.models import Project, Domain
1617

1718
log = logging.getLogger(__name__)
@@ -79,12 +80,16 @@ def decide_if_cors(sender, request, **kwargs): # pylint: disable=unused-argumen
7980
def delete_projects_and_organizations(sender, instance, *args, **kwargs):
8081
# Here we count the owner list from the projects that the user own
8182
# Then exclude the projects where there are more than one owner
82-
projects = instance.projects.all().annotate(num_users=Count('users')).exclude(num_users__gt=1)
83+
# Add annotate before filter
84+
# https://bit.ly/2Nne6ZJ
85+
projects = (Project.objects.annotate(num_users=Count('users')).filter(users=instance.id)
86+
.exclude(num_users__gt=1))
8387

8488
# Here we count the users list from the organization that the user belong
8589
# Then exclude the organizations where there are more than one user
86-
oauth_organizations = (instance.oauth_organizations.annotate(num_users=Count('users'))
87-
.exclude(num_users__gt=1))
90+
oauth_organizations = (RemoteOrganization.objects.annotate(num_users=Count('users'))
91+
.filter(users=instance.id)
92+
.exclude(num_users__gt=1))
8893

8994
projects.delete()
9095
oauth_organizations.delete()

readthedocs/core/tests/__init__.py

Whitespace-only changes.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import pytest
2+
3+
from django.contrib.auth.models import User
4+
from django_dynamic_fixture import G
5+
6+
from readthedocs.oauth.models import RemoteOrganization
7+
from readthedocs.projects.models import Project
8+
9+
10+
@pytest.mark.django_db
11+
class TestProjectOrganizationSignal(object):
12+
13+
@pytest.mark.parametrize('model', [Project, RemoteOrganization])
14+
def test_multiple_users_project_organization_not_delete(self, model):
15+
"""
16+
Check Project or RemoteOrganization which have multiple users do not get deleted
17+
when any of the user delete his account.
18+
"""
19+
20+
obj = G(model)
21+
user1 = G(User)
22+
user2 = G(User)
23+
obj.users.add(user1, user2)
24+
25+
obj.refresh_from_db()
26+
assert obj.users.all().count() > 1
27+
# Delete 1 user of the project
28+
user1.delete()
29+
30+
# The project should still exist and it should have 1 user
31+
obj.refresh_from_db()
32+
assert obj.id
33+
obj_users = obj.users.all()
34+
assert len(obj_users) == 1
35+
assert user2 in obj_users

0 commit comments

Comments
 (0)