Skip to content

Commit

Permalink
Verify also URLs of existing releases
Browse files Browse the repository at this point in the history
  • Loading branch information
facutuesca committed Jul 19, 2024
1 parent 892a932 commit 19d4e21
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 4 deletions.
84 changes: 82 additions & 2 deletions tests/unit/forklift/test_legacy.py
Original file line number Diff line number Diff line change
Expand Up @@ -3815,11 +3815,11 @@ def failing_verify(_self, _verifier, _policy, _dist):
("https://google.com", False), # Totally different
("https://github.com/foo", False), # Missing parts
("https://github.com/foo/bar/", True), # Exactly the same
("https://github.com/foo/bar/readme.md", True), # Additonal parts
("https://github.com/foo/bar/readme.md", True), # Additional parts
("https://github.com/foo/bar", True), # Missing trailing slash
],
)
def test_release_url_verified(
def test_new_release_url_verified(
self, monkeypatch, pyramid_config, db_request, metrics, url, expected
):
project = ProjectFactory.create()
Expand Down Expand Up @@ -3878,6 +3878,86 @@ def test_release_url_verified(
assert release_url is not None
assert release_url.verified == expected

def test_new_publisher_verifies_existing_release_url(
self,
monkeypatch,
pyramid_config,
db_request,
metrics,
):
repo_name = "my_new_repo"
verified_url = "https://github.com/foo/bar"
unverified_url = f"https://github.com/foo/{repo_name}"

project = ProjectFactory.create()
release = ReleaseFactory.create(project=project, version="1.0")
# We start with an existing release, with one verified URL and one unverified
# URL. Uploading a new file with a Trusted Publisher that matches the unverified
# URL should mark it as verified.
release.project_urls = {
"verified_url": {"url": verified_url, "verified": True},
"unverified_url": {"url": unverified_url, "verified": False},
}
publisher = GitHubPublisherFactory.create(projects=[project])
publisher.repository_owner = "foo"
publisher.repository_name = repo_name
claims = {"sha": "somesha"}
identity = PublisherTokenContext(publisher, SignedClaims(claims))
db_request.oidc_publisher = identity.publisher
db_request.oidc_claims = identity.claims

db_request.db.add(Classifier(classifier="Environment :: Other Environment"))
db_request.db.add(Classifier(classifier="Programming Language :: Python"))

filename = "{}-{}.tar.gz".format(project.name, "1.0")

pyramid_config.testing_securitypolicy(identity=identity)
db_request.user_agent = "warehouse-tests/6.6.6"
db_request.POST = MultiDict(
{
"metadata_version": "1.2",
"name": project.name,
"version": "1.0",
"summary": "This is my summary!",
"filetype": "sdist",
"md5_digest": _TAR_GZ_PKG_MD5,
"content": pretend.stub(
filename=filename,
file=io.BytesIO(_TAR_GZ_PKG_TESTDATA),
type="application/tar",
),
}
)
db_request.POST.extend(
[
("classifiers", "Environment :: Other Environment"),
("classifiers", "Programming Language :: Python"),
("requires_dist", "foo"),
("requires_dist", "bar (>1.0)"),
("requires_external", "Cheese (>1.0)"),
("provides", "testing"),
]
)
db_request.POST.add("project_urls", f"verified_url, {verified_url}")
db_request.POST.add("project_urls", f"unverified_url, {unverified_url}")

storage_service = pretend.stub(store=lambda path, filepath, meta: None)
db_request.find_service = lambda svc, name=None, context=None: {
IFileStorage: storage_service,
IMetricsService: metrics,
}.get(svc)

legacy.file_upload(db_request)

# After successful upload, the Release should have now both URLs verified
release_urls = (
db_request.db.query(ReleaseURL).filter(Release.project == project).all()
)
release_urls = {r.name: r.verified for r in release_urls}
assert "verified_url" in release_urls and "unverified_url" in release_urls
assert release_urls["verified_url"]
assert release_urls["unverified_url"]

@pytest.mark.parametrize(
"version, expected_version",
[
Expand Down
15 changes: 15 additions & 0 deletions warehouse/forklift/legacy.py
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,7 @@ def file_upload(request):
}
)
try:
is_new_release = False
canonical_version = packaging.utils.canonicalize_version(meta.version)
release = (
request.db.query(Release)
Expand Down Expand Up @@ -908,6 +909,7 @@ def file_upload(request):
uploaded_via=request.user_agent,
)
request.db.add(release)
is_new_release = True

# TODO: This should be handled by some sort of database trigger or
# a SQLAlchemy hook or the like instead of doing it inline in
Expand Down Expand Up @@ -1307,6 +1309,19 @@ def file_upload(request):
},
)

# For existing releases, we check if any of the existing project URLs are unverified
# and have been verified in the current upload. In that case, we mark them as
# verified.
if not is_new_release and project_urls:
for name, release_url in release._project_urls.items():
if (
not release_url.verified
and name in project_urls
and project_urls[name]["url"] == release_url.url
and project_urls[name]["verified"]
):
release_url.verified = True

# Check if the user has any 2FA methods enabled, and if not, email them.
if request.user and not request.user.has_two_factor:
warnings.append("Two factor authentication is not enabled for your account.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
create verified field for ReleaseUrl
Revision ID: 26455e3712a2
Revises: b14df478c48f
Revises: bb6943882aa9
Create Date: 2024-04-30 18:40:17.149050
"""

Expand All @@ -22,7 +22,7 @@
from alembic import op

revision = "26455e3712a2"
down_revision = "b14df478c48f"
down_revision = "bb6943882aa9"


def upgrade():
Expand Down

0 comments on commit 19d4e21

Please sign in to comment.