Skip to content

Commit dcb5049

Browse files
Allow removing subprojects for non-subproject admins
Also adding tests on removing subprojects
1 parent 0e93ce4 commit dcb5049

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

readthedocs/projects/views/private.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ def project_subprojects(request, project_slug):
426426
@login_required
427427
def project_subprojects_delete(request, project_slug, child_slug):
428428
parent = get_object_or_404(Project.objects.for_admin_user(request.user), slug=project_slug)
429-
child = get_object_or_404(Project.objects.for_admin_user(request.user), slug=child_slug)
429+
child = get_object_or_404(Project.objects.all(), slug=child_slug)
430430
parent.remove_subproject(child)
431431
return HttpResponseRedirect(reverse('projects_subprojects',
432432
args=[parent.slug]))

readthedocs/rtd_tests/tests/test_views.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from django.core.urlresolvers import reverse
33
from django.test import TestCase
44
from django.utils.six.moves.urllib.parse import urlsplit
5+
from django_dynamic_fixture import G, N
56

67
from readthedocs.builds.constants import LATEST
78
from readthedocs.projects.models import Project
@@ -168,3 +169,38 @@ def test_project_redirects(self):
168169
def test_project_redirects_delete(self):
169170
response = self.client.get('/dashboard/pip/redirects/delete/')
170171
self.assertRedirectToLogin(response)
172+
173+
174+
class SubprojectViewTests(TestCase):
175+
def setUp(self):
176+
self.user = N(User, username='test')
177+
self.user.set_password('test')
178+
self.user.save()
179+
180+
self.project = G(Project, slug='my-mainproject')
181+
self.subproject = G(Project, slug='my-subproject')
182+
self.project.add_subproject(self.subproject)
183+
184+
self.client.login(username='test', password='test')
185+
186+
def test_deny_delete_for_non_project_admins(self):
187+
response = self.client.get('/dashboard/my-mainproject/subprojects/delete/my-subproject/')
188+
self.assertEqual(response.status_code, 404)
189+
190+
self.assertTrue(self.subproject in [r.child for r in self.project.subprojects.all()])
191+
192+
def test_admins_can_delete_subprojects(self):
193+
self.project.users.add(self.user)
194+
self.subproject.users.add(self.user)
195+
196+
response = self.client.get('/dashboard/my-mainproject/subprojects/delete/my-subproject/')
197+
self.assertEqual(response.status_code, 302)
198+
self.assertTrue(self.subproject not in [r.child for r in self.project.subprojects.all()])
199+
200+
def test_project_admins_can_delete_subprojects_that_they_are_not_admin_of(self):
201+
self.project.users.add(self.user)
202+
self.assertFalse(self.subproject.user_is_admin(self.user))
203+
204+
response = self.client.get('/dashboard/my-mainproject/subprojects/delete/my-subproject/')
205+
self.assertEqual(response.status_code, 302)
206+
self.assertTrue(self.subproject not in [r.child for r in self.project.subprojects.all()])

0 commit comments

Comments
 (0)