Skip to content

Verified project links for project details. #15862

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 19 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
27 changes: 27 additions & 0 deletions tests/unit/packaging/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,33 @@ def test_trusted_published_all(self, db_session):

assert release.trusted_published

@pytest.mark.parametrize(
"url, publisher_url, expected",
[
("xpto.com", "https://pub/url/", False), # Totally different
("https://pub/", "https://pub/url/", False), # Missing parts
("https://pub/url/", "https://pub/url/", True), # Exactly the same
("https://pub/url/blah.md", "https://pub/url/", True), # Additonal parts
("https://pub/url", "https://pub/url/", True), # Missing trailing slash
("https://pub/url/", "https://pub/url", True), # Extratrailing slash
],
)
def test_is_url_verified(self, db_session, url, publisher_url, expected):
project = DBProjectFactory.create()
release = DBReleaseFactory.create(project=project)
release_file = DBFileFactory.create(
release=release,
filename=f"{release.project.name}-{release.version}.tar.gz",
python_version="source",
)
DBFileEventFactory.create(
source=release_file,
tag="fake:event",
additional={"publisher_url": publisher_url},
)

assert project.is_verified_url(url) is expected

def test_trusted_published_mixed(self, db_session):
release = DBReleaseFactory.create()
rfile_1 = DBFileFactory.create(
Expand Down
51 changes: 26 additions & 25 deletions warehouse/locale/messages.pot
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,7 @@ msgstr ""
#: warehouse/templates/includes/accounts/profile-actions.html:30
#: warehouse/templates/includes/accounts/profile-callout.html:18
#: warehouse/templates/includes/hash-modal.html:23
#: warehouse/templates/includes/packaging/project-data.html:106
#: warehouse/templates/includes/packaging/project-data.html:125
#: warehouse/templates/index.html:100 warehouse/templates/index.html:104
#: warehouse/templates/manage/account.html:228
#: warehouse/templates/manage/account.html:234
Expand Down Expand Up @@ -3077,47 +3077,48 @@ msgstr ""
msgid "Members"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:16
#: warehouse/templates/includes/packaging/project-data.html:27
msgid "Verified details"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:31
#: warehouse/templates/includes/packaging/project-data.html:30
#: warehouse/templates/includes/packaging/project-data.html:73
msgid "Project links"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:52
msgid "Maintainers"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:33
#: warehouse/templates/includes/packaging/project-data.html:54
msgid "Avatar for {username} from gravatar.com"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:49
#: warehouse/templates/includes/packaging/project-data.html:70
msgid "Unverified details"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:52
msgid "Project links"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:66
#: warehouse/templates/includes/packaging/project-data.html:85
msgid "GitHub Statistics"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:74
#: warehouse/templates/includes/packaging/project-data.html:93
msgid "Stars:"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:82
#: warehouse/templates/includes/packaging/project-data.html:101
msgid "Forks:"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:90
#: warehouse/templates/includes/packaging/project-data.html:109
msgid "Open issues:"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:98
#: warehouse/templates/includes/packaging/project-data.html:117
msgid "Open PRs:"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:106
#: warehouse/templates/includes/packaging/project-data.html:125
#, python-format
msgid ""
"View statistics for this project via <a href=\"%(libs_io_href)s\" "
Expand All @@ -3126,38 +3127,38 @@ msgid ""
"rel=\"noopener\">our public dataset on Google BigQuery</a>"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:113
#: warehouse/templates/includes/packaging/project-data.html:132
msgid "Meta"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:115
#: warehouse/templates/includes/packaging/project-data.html:134
msgid "License:"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:118
#: warehouse/templates/includes/packaging/project-data.html:120
#: warehouse/templates/includes/packaging/project-data.html:137
#: warehouse/templates/includes/packaging/project-data.html:139
msgid "Author:"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:123
#: warehouse/templates/includes/packaging/project-data.html:125
#: warehouse/templates/includes/packaging/project-data.html:142
#: warehouse/templates/includes/packaging/project-data.html:144
#: warehouse/templates/pages/help.html:610
msgid "Maintainer:"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:130
#: warehouse/templates/includes/packaging/project-data.html:149
msgid "Tags"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:140
#: warehouse/templates/includes/packaging/project-data.html:159
msgid "Requires:"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:145
#: warehouse/templates/includes/packaging/project-data.html:164
msgid "Provides-Extra:"
msgstr ""

#: warehouse/templates/includes/packaging/project-data.html:153
#: warehouse/templates/includes/packaging/project-data.html:172
#: warehouse/templates/pages/classifiers.html:16
#: warehouse/templates/pages/classifiers.html:21
#: warehouse/templates/pages/sitemap.html:39
Expand Down
18 changes: 18 additions & 0 deletions warehouse/packaging/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
Text,
UniqueConstraint,
func,
literal,
or_,
orm,
sql,
Expand Down Expand Up @@ -399,6 +400,23 @@ def latest_version(self):
.first()
)

def is_verified_url(self, url):
url = url.rstrip("/") + "/" # Ensure a single trailing slash
return (
orm.object_session(self)
.query(File.Event)
.join(File)
.join(Release)
.join(Project)
.filter(Project.id == self.id)
.filter(
literal(url).ilike(
File.Event.additional.op("->>")("publisher_url") + "%"
)
)
.scalar()
) is not None


class DependencyKind(enum.IntEnum):
requires = 1
Expand Down
27 changes: 23 additions & 4 deletions warehouse/templates/includes/packaging/project-data.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,30 @@
# limitations under the License.
-#}

{% set verified_urls, unverified_urls = [],[] %}
{% for name, url in release.urls.items() %}
{% if is_valid_uri(url) %}
{% if name in ["Source", "Homepage", "Issues"] and project.is_verified_url(url) %}
{{ verified_urls.append((name, url)) }}
{% else %}
{{ unverified_urls.append((name, url)) }}
{% endif %}
{% endif %}
{% endfor %}

<div class="sidebar-section verified">
<h3 class="sidebar-section__title">{% trans %}Verified details{% endtrans %}</h3>
<small><i>These details have been verified by PyPI</i></small>
{% if verified_urls.values() %}
<h6>{% trans %}Project links{% endtrans %}</h6>
{% for name, url in verified_urls %}
<li>
<a class="vertical-tabs__tab vertical-tabs__tab--with-icon vertical-tabs__tab--condensed" href="{{ url }}" rel="nofollow">
{{ url_icon(name, url) }}{{ name }} <i class="fa fa-circle-check check"></i>
</a>
</li>
{% endfor %}
{% endif %}
{% if project.organization %}
<h6>Owner</h6>
<span class="sidebar-section__maintainer">
Expand Down Expand Up @@ -48,17 +69,15 @@ <h6>{% trans %}Maintainers{% endtrans %}</h6>
<div class="sidebar-section verified">
<h3 class="sidebar-section__title">{% trans %}Unverified details{% endtrans %}</h3>
<small><i>These details have <b>not</b> been verified by PyPI</i></small>
{% if release.urls.values() | contains_valid_uris %}
{% if unverified_urls.values() %}
<h6>{% trans %}Project links{% endtrans %}</h6>
<ul class="vertical-tabs__list">
{% for name, url in release.urls.items() %}
{% if is_valid_uri(url) %}
{% for name, url in unverified_urls %}
<li>
<a class="vertical-tabs__tab vertical-tabs__tab--with-icon vertical-tabs__tab--condensed" href="{{ url }}" rel="nofollow">
{{ url_icon(name, url) }}{{ name }}
</a>
</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
Expand Down