Skip to content

Don't allow to create subprojects with same alias #5404

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 4, 2019
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions readthedocs/projects/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,17 @@ def clean_child(self):
)
return child

def clean_alias(self):
alias = self.cleaned_data['alias']
subproject = self.project.subprojects.filter(
alias=alias).exclude(id=self.instance.pk)

if subproject.exists():
raise forms.ValidationError(
_('A subproject with this alias already exists'),
)
return alias

def get_subproject_queryset(self):
"""
Return scrubbed subproject choice queryset.
Expand Down
2 changes: 1 addition & 1 deletion readthedocs/rtd_tests/tests/test_project_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
TranslationForm,
UpdateProjectForm,
WebHookForm,
EmailHookForm
EmailHookForm,
)
from readthedocs.projects.models import EnvironmentVariable, Project

Expand Down
80 changes: 78 additions & 2 deletions readthedocs/rtd_tests/tests/test_subprojects.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,82 @@ def test_exclude_self_project_as_subproject(self):
[proj_id for (proj_id, __) in form.fields['child'].choices],
)

def test_user_cant_add_other_users_project_as_subproject(self):
user = fixture.get(User)
user_2 = fixture.get(User)
project = fixture.get(Project, slug='mainproject', users=[user])
subproject = fixture.get(Project, slug='subproject', users=[user_2])

form = ProjectRelationshipForm(
{'child': subproject.pk},
project=project,
user=user,
)
self.assertFalse(form.is_valid())
self.assertIn(
'Select a valid choice',
''.join(form.errors['child']),
)
self.assertNotIn(
subproject.id,
[proj_id for (proj_id, __) in form.fields['child'].choices],
)

def test_alias_already_exists_for_a_project(self):
user = fixture.get(User)
project = fixture.get(Project, users=[user])
subproject = fixture.get(Project, users=[user])
subproject_2 = fixture.get(Project, users=[user])
relation = fixture.get(
ProjectRelationship, parent=project, child=subproject,
alias='subproject'
)
form = ProjectRelationshipForm(
{
'child': subproject_2.id,
'alias': 'subproject'
},
project=project,
user=user,
)
self.assertFalse(form.is_valid())
error_msg = 'A subproject with this alias already exists'
self.assertDictEqual(form.errors, {'alias': [error_msg]})

def test_list_only_owner_projects_in_child_choices(self):
user = fixture.get(User)
user_2 = fixture.get(User)
project = fixture.get(Project, users=[user])
subproject = fixture.get(Project, users=[user])
subproject_2 = fixture.get(Project, users=[user_2])

form = ProjectRelationshipForm(
project=project,
user=user,
)
self.assertEqual(
[proj_id for (proj_id, __) in form.fields['child'].choices],
['', subproject.id],
)

def test_edit_only_lists_instance_project_in_child_choices(self):
user = fixture.get(User)
project = fixture.get(Project, users=[user])
subproject = fixture.get(Project, users=[user])
relation = fixture.get(
ProjectRelationship, parent=project, child=subproject,
alias='subproject'
)
form = ProjectRelationshipForm(
instance=relation,
project=project,
user=user,
)
self.assertEqual(
[proj_id for (proj_id, __) in form.fields['child'].choices],
['', relation.child.id],
)


@override_settings(PUBLIC_DOMAIN='readthedocs.org')
class ResolverBase(TestCase):
Expand All @@ -172,12 +248,12 @@ def setUp(self):
self.pip = fixture.get(Project, slug='pip', users=[self.owner], main_language_project=None)
self.subproject = fixture.get(
Project, slug='sub', language='ja',
users=[ self.owner],
users=[self.owner],
main_language_project=None,
)
self.translation = fixture.get(
Project, slug='trans', language='ja',
users=[ self.owner],
users=[self.owner],
main_language_project=None,
)
self.pip.add_subproject(self.subproject)
Expand Down