defmodule GitGud.PackagesSubstrateTest do
@moduledoc """
Phase 0: the parts every registry format sits on, exercised without
any format adapter in play.
"""
use GitGud.DataCase, async: true
alias GitGud.Packages
alias GitGud.Packages.Auth
alias GitGud.Packages.Format
import GitGud.ForgeFixtures
setup do
{user, repo} = repository_fixture()
{:ok, user: user, repo: repo}
end
describe "publish_file/5" do
test "creates the package, version and file rows", %{repo: repo, user: user} do
assert {:ok, pkg, ver, file} =
Packages.publish_file(repo, "pypi", "Widget", "1.0.0", %{
filename: "widget-1.0.0.tar.gz",
body: "sdist bytes",
content_type: "application/x-tar",
uploader: user
})
assert pkg.format == "pypi"
assert pkg.name == "Widget"
assert pkg.latest_version == "1.0.0"
assert ver.version == "1.0.0"
assert file.size == byte_size("sdist bytes")
assert file.sha256 ==
Base.encode16(:crypto.hash(:sha256, "sdist bytes"), case: :lower)
assert {:ok, "sdist bytes"} = Packages.read_file(file)
end
test "a second file joins the same version", %{repo: repo} do
{:ok, _, _, _} =
Packages.publish_file(repo, "pypi", "widget", "1.0.0", %{
filename: "widget-1.0.0.tar.gz",
body: "sdist"
})
{:ok, pkg, ver, _} =
Packages.publish_file(repo, "pypi", "widget", "1.0.0", %{
filename: "widget-1.0.0-py3-none-any.whl",
body: "wheel"
})
assert [_, _] = Packages.list_files(ver)
assert [ver_only] = Packages.list_versions(pkg)
assert ver_only.id == ver.id
end
test "re-uploading identical bytes is a no-op, not a conflict", %{repo: repo} do
attrs = %{filename: "widget-1.0.0.tar.gz", body: "sdist"}
{:ok, _, _, first} = Packages.publish_file(repo, "pypi", "widget", "1.0.0", attrs)
{:ok, _, _, second} = Packages.publish_file(repo, "pypi", "widget", "1.0.0", attrs)
assert first.id == second.id
end
test "a published filename can never point at different bytes", %{repo: repo} do
{:ok, _, _, _} =
Packages.publish_file(repo, "pypi", "widget", "1.0.0", %{
filename: "widget-1.0.0.tar.gz",
body: "sdist"
})
assert {:error, :file_exists} =
Packages.publish_file(repo, "pypi", "widget", "1.0.0", %{
filename: "widget-1.0.0.tar.gz",
body: "different sdist"
})
end
test "the same name under two formats is two packages", %{repo: repo} do
{:ok, pypi, _, _} =
Packages.publish_file(repo, "pypi", "widget", "1.0.0", %{
filename: "a.tar.gz",
body: "a"
})
{:ok, cargo, _, _} =
Packages.publish_file(repo, "cargo", "widget", "1.0.0", %{
filename: "b.crate",
body: "b"
})
refute pypi.id == cargo.id
assert [^pypi] = Packages.list_packages(repo, "pypi")
assert [^cargo] = Packages.list_packages(repo, "cargo")
end
end
describe "lookup" do
test "goes through the normalized name", %{repo: repo} do
{:ok, pkg, _, _} =
Packages.publish_file(repo, "cargo", "Serde", "1.0.0", %{
filename: "serde-1.0.0.crate",
body: "crate"
})
assert Packages.get_package(repo, "cargo", "serde").id == pkg.id
assert Packages.get_package(repo, "cargo", "SERDE").id == pkg.id
assert Packages.get_package(repo, "cargo", "nope") == nil
end
test "list_package_files/1 flattens versions into downloadables", %{repo: repo} do
for v <- ["1.0.0", "1.1.0"] do
{:ok, _, _, _} =
Packages.publish_file(repo, "pypi", "widget", v, %{
filename: "widget-#{v}.tar.gz",
body: "sdist #{v}"
})
end
pkg = Packages.get_package(repo, "pypi", "widget")
files = Packages.list_package_files(pkg)
assert length(files) == 2
assert Enum.all?(files, &(&1.package_version.version in ["1.0.0", "1.1.0"]))
end
end
describe "yanking" do
test "flags the version without removing its bytes", %{repo: repo} do
{:ok, pkg, ver, file} =
Packages.publish_file(repo, "pypi", "widget", "1.0.0", %{
filename: "widget-1.0.0.tar.gz",
body: "sdist"
})
{:ok, _} = Packages.set_yanked(ver, true, "broken metadata")
assert %{yanked: true, yanked_reason: "broken metadata"} =
Packages.get_version(pkg, "1.0.0")
assert {:ok, "sdist"} = Packages.read_file(file)
end
end
describe "Format" do
test "an unregistered format has no adapter" do
assert Format.adapter("oci") == :error
assert Format.adapter("nonsense") == :error
end
test "normalization falls back to case folding" do
assert Format.normalize("oci", "Foo.Bar") == "foo.bar"
end
end
describe "Auth" do
test "a registry token authenticates and carries its own scopes", %{repo: repo} do
{:ok, _token, plaintext} = Packages.create_registry_token(repo, "ci", ["pull", "push"])
conn = conn_with_auth("Basic " <> Base.encode64("__token__:#{plaintext}"))
assert {:token, repo_id, scopes} = Auth.authenticate(conn)
assert repo_id == repo.id
assert "push" in scopes
end
test "a bare Authorization value works too — mix and cargo send that", %{repo: repo} do
{:ok, _token, plaintext} = Packages.create_registry_token(repo, "ci", ["pull"])
assert {:token, _, ["pull"]} = Auth.authenticate(conn_with_auth(plaintext))
end
test "a pull-only token may not write", %{repo: repo} do
{:ok, _token, plaintext} = Packages.create_registry_token(repo, "ro", ["pull"])
principal = Auth.authenticate(conn_with_auth(plaintext))
assert Auth.authorize(principal, repo, :read)
refute Auth.authorize(principal, repo, :write)
end
test "a token minted for another repo is worth no more than anonymous", %{repo: repo} do
{_other_user, other_repo} = repository_fixture()
{:ok, _t, plaintext} = Packages.create_registry_token(other_repo, "ci", ["pull", "push"])
principal = Auth.authenticate(conn_with_auth(plaintext))
refute Auth.authorize(principal, %{repo | visibility: "private"}, :read)
refute Auth.authorize(principal, repo, :write)
end
test "anonymous reads public repositories only", %{repo: repo} do
assert Auth.authorize(:anonymous, %{repo | visibility: "public"}, :read)
refute Auth.authorize(:anonymous, %{repo | visibility: "internal"}, :read)
refute Auth.authorize(:anonymous, %{repo | visibility: "private"}, :read)
refute Auth.authorize(:anonymous, %{repo | visibility: "public"}, :write)
end
test "the owner may write", %{repo: repo, user: user} do
assert Auth.authorize({:user, user, :all}, repo, :write)
end
test "no credentials at all is anonymous" do
assert Auth.authenticate(Plug.Test.conn(:get, "/")) == :anonymous
assert Auth.authenticate(conn_with_auth("Basic not-base64")) == :anonymous
end
end
defp conn_with_auth(value) do
Plug.Test.conn(:get, "/") |> Plug.Conn.put_req_header("authorization", value)
end
end
neiam
/gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
1
Log in to mark this repository.
7.2 KiB · text
History
95e9713