diff --git a/tests/unit/admin/views/test_organizations.py b/tests/unit/admin/views/test_organizations.py index 3c7dcf772243..7e93e8d532bd 100644 --- a/tests/unit/admin/views/test_organizations.py +++ b/tests/unit/admin/views/test_organizations.py @@ -617,6 +617,7 @@ def test_detail(self, db_request): assert result["user"] == organization_application.submitted_by assert result["form"].name.data == organization_application.name assert result["conflicting_applications"] == [] + assert result["conflicting_namespace_prefixes"] == [] assert result["organization_application"] == organization_application @pytest.mark.usefixtures("_enable_organizations") @@ -669,6 +670,7 @@ def test_detail_edit_invalid(self, db_request): assert result["form"].name.data == existing_organization.name assert result["form"].name.errors != [] assert result["conflicting_applications"] == [] + assert result["conflicting_namespace_prefixes"] == [] assert result["organization_application"] == organization_application @pytest.mark.usefixtures("_enable_organizations") @@ -683,6 +685,7 @@ def test_detail_is_approved_true(self, db_request): assert result["user"] == organization_application.submitted_by assert result["form"].name.data == organization_application.name assert result["conflicting_applications"] == [] + assert result["conflicting_namespace_prefixes"] == [] assert result["organization_application"] == organization_application @pytest.mark.usefixtures("_enable_organizations") @@ -697,17 +700,25 @@ def test_detail_is_approved_false(self, db_request): assert result["user"] == organization_application.submitted_by assert result["form"].name.data == organization_application.name assert result["conflicting_applications"] == [] + assert result["conflicting_namespace_prefixes"] == [] assert result["organization_application"] == organization_application @pytest.mark.usefixtures("_enable_organizations") @pytest.mark.parametrize( - ("name", "conflicts"), + ("name", "conflicts", "conflicting_prefixes", "not_conflicting"), [ - ("pypi", ["PyPI", "pypi"]), - ("py-pi", ["Py-PI", "PY-PI"]), + ( + "pypi", + ["PyPI", "pypi"], + ["pypi-common", "PyPi_rocks", "pypi-team-garbage"], + ["py-pi"], + ), + ("py-pi", ["Py-PI", "PY-PI"], ["py", "py-pi_dot-com"], ["pypi"]), ], ) - def test_detail_conflicting_applications(self, db_request, name, conflicts): + def test_detail_conflicting_applications( + self, db_request, name, conflicts, conflicting_prefixes, not_conflicting + ): organization_application = OrganizationApplicationFactory.create( name=name, status=OrganizationApplicationStatus.Declined ) @@ -718,6 +729,14 @@ def test_detail_conflicting_applications(self, db_request, name, conflicts): ], key=lambda o: o.submitted, ) + conflicting_prefix_applications = sorted( + [ + OrganizationApplicationFactory.create(name=conflict) + for conflict in conflicting_prefixes + ], + key=lambda o: o.submitted, + ) + [OrganizationApplicationFactory.create(name=name) for name in not_conflicting] db_request.matchdict["organization_application_id"] = ( organization_application.id ) @@ -725,6 +744,13 @@ def test_detail_conflicting_applications(self, db_request, name, conflicts): assert result["user"] == organization_application.submitted_by assert result["form"].name.data == organization_application.name assert result["conflicting_applications"] == conflicting_applications + assert result["conflicting_namespace_prefixes"] == [ + conflict + for conflict in sorted( + conflicting_applications + conflicting_prefix_applications, + key=lambda o: o.submitted, + ) + ] assert result["organization_application"] == organization_application @pytest.mark.usefixtures("_enable_organizations") diff --git a/warehouse/admin/templates/admin/organization_applications/detail.html b/warehouse/admin/templates/admin/organization_applications/detail.html index a73e8416b50d..ffe55600d1f4 100644 --- a/warehouse/admin/templates/admin/organization_applications/detail.html +++ b/warehouse/admin/templates/admin/organization_applications/detail.html @@ -388,10 +388,31 @@

Organization Request{% if information_requests %}{% if ou
- + {% for application in conflicting_applications %} + + + + + {% endfor %} +
ApplicationSubmittedRequestor
ApplicationStatusSubmittedRequestor
{{ application.name }}{{ application.status }}{{ application.submitted|format_date() }}{{ application.submitted_by.username }}
+
+ + {% endif %} + {% if conflicting_namespace_prefixes %} +
+ +
+ + + {% for application in conflicting_namespace_prefixes %} + + + diff --git a/warehouse/admin/views/organizations.py b/warehouse/admin/views/organizations.py index cf306717f5f3..0f291d580a41 100644 --- a/warehouse/admin/views/organizations.py +++ b/warehouse/admin/views/organizations.py @@ -372,12 +372,39 @@ def organization_application_detail(request): .all() ) + parts = organization_application.normalized_name.split("-") + conflicting_namespace_prefixes = ( + request.db.query(OrganizationApplication) + .filter( + or_( + *( + [ + OrganizationApplication.normalized_name == parts[0], + OrganizationApplication.normalized_name.startswith( + parts[0] + "-" + ), + ] + + [ + OrganizationApplication.normalized_name.startswith( + "-".join(parts[: i + 1]) + ) + for i in range(1, len(parts)) + ] + ) + ) + ) + .filter(OrganizationApplication.id != organization_application.id) + .order_by(OrganizationApplication.submitted) + .all() + ) + user = user_service.get_user(organization_application.submitted_by_id) return { "organization_application": organization_application, "form": form, "conflicting_applications": conflicting_applications, + "conflicting_namespace_prefixes": conflicting_namespace_prefixes, "user": user, }
ApplicationStatusSubmittedRequestor
{{ application.name }}{{ application.status }} {{ application.submitted|format_date() }} {{ application.submitted_by.username }}