diff --git a/lib/pleroma/object/fetcher.ex b/lib/pleroma/object/fetcher.ex index 2cecfec67..897146bce 100644 --- a/lib/pleroma/object/fetcher.ex +++ b/lib/pleroma/object/fetcher.ex @@ -343,7 +343,6 @@ defp get_final_id(final_url, _intial_url) do final_url end - @doc "Do NOT use; only public for use in tests" def get_object(id) do date = Pleroma.Signature.signed_date() diff --git a/lib/pleroma/signature.ex b/lib/pleroma/signature.ex index c4ac2c87e..1374ac068 100644 --- a/lib/pleroma/signature.ex +++ b/lib/pleroma/signature.ex @@ -5,45 +5,33 @@ defmodule Pleroma.Signature do @behaviour HTTPSignatures.Adapter - alias Pleroma.EctoType.ActivityPub.ObjectValidators - alias Pleroma.Keys alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub - - @known_suffixes ["/publickey", "/main-key", "#key"] + alias Pleroma.User.SigningKey def key_id_to_actor_id(key_id) do - uri = - key_id - |> URI.parse() - |> Map.put(:fragment, nil) - |> Map.put(:query, nil) - |> remove_suffix(@known_suffixes) + # Given the key ID, first attempt to look it up in the signing keys table. + # If it's not found, then attempt to look it up via request to the remote instance. + case SigningKey.key_id_to_ap_id(key_id) do + nil -> + # this requires us to look up the url! + request_key_id_from_remote_instance(key_id) - maybe_ap_id = URI.to_string(uri) - - case ObjectValidators.ObjectID.cast(maybe_ap_id) do - {:ok, ap_id} -> - {:ok, ap_id} - - _ -> - case Pleroma.Web.WebFinger.finger(maybe_ap_id) do - {:ok, %{"ap_id" => ap_id}} -> {:ok, ap_id} - _ -> {:error, maybe_ap_id} - end + key -> + {:ok, key} end end - defp remove_suffix(uri, [test | rest]) do - if not is_nil(uri.path) and String.ends_with?(uri.path, test) do - Map.put(uri, :path, String.replace(uri.path, test, "")) - else - remove_suffix(uri, rest) + def request_key_id_from_remote_instance(key_id) do + case SigningKey.fetch_remote_key(key_id) do + {:ok, key_id} -> + {:ok, key_id} + + {:error, _} -> + {:error, "Key ID not found"} end end - defp remove_suffix(uri, []), do: uri - def fetch_public_key(conn) do with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn), {:ok, actor_id} <- key_id_to_actor_id(kid), @@ -67,8 +55,8 @@ def refetch_public_key(conn) do end end - def sign(%User{keys: keys} = user, headers) do - with {:ok, private_key, _} <- Keys.keys_from_pem(keys) do + def sign(%User{} = user, headers) do + with {:ok, private_key} <- SigningKey.private_key(user) do HTTPSignatures.sign(private_key, user.ap_id <> "#main-key", headers) end end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 2bc3e9ace..593173288 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -25,7 +25,6 @@ defmodule Pleroma.User do alias Pleroma.Hashtag alias Pleroma.User.HashtagFollow alias Pleroma.HTML - alias Pleroma.Keys alias Pleroma.MFA alias Pleroma.Notification alias Pleroma.Object @@ -43,6 +42,7 @@ defmodule Pleroma.User do alias Pleroma.Web.OAuth alias Pleroma.Web.RelMe alias Pleroma.Workers.BackgroundWorker + alias Pleroma.User.SigningKey use Pleroma.Web, :verified_routes @@ -222,6 +222,10 @@ defmodule Pleroma.User do on_replace: :delete ) + # FOR THE FUTURE: We might want to make this a one-to-many relationship + # it's entirely possible right now, but we don't have a use case for it + has_one(:signing_key, SigningKey, foreign_key: :user_id) + timestamps() end @@ -457,6 +461,7 @@ def remote_user_changeset(struct \\ %User{local: false}, params) do |> fix_follower_address() struct + |> Repo.preload(:signing_key) |> cast( params, [ @@ -495,6 +500,7 @@ def remote_user_changeset(struct \\ %User{local: false}, params) do |> validate_required([:ap_id]) |> validate_required([:name], trim: false) |> unique_constraint(:nickname) + |> cast_assoc(:signing_key, with: &SigningKey.remote_changeset/2, required: false) |> validate_format(:nickname, @email_regex) |> validate_length(:bio, max: bio_limit) |> validate_length(:name, max: name_limit) @@ -570,6 +576,7 @@ def update_changeset(struct, params \\ %{}) do :pleroma_settings_store, &{:ok, Map.merge(struct.pleroma_settings_store, &1)} ) + |> cast_assoc(:signing_key, with: &SigningKey.remote_changeset/2, requred: false) |> validate_fields(false, struct) end @@ -828,8 +835,10 @@ def put_following_and_follower_and_featured_address(changeset) do end defp put_private_key(changeset) do - {:ok, pem} = Keys.generate_rsa_pem() - put_change(changeset, :keys, pem) + ap_id = get_field(changeset, :ap_id) + + changeset + |> put_assoc(:signing_key, SigningKey.generate_local_keys(ap_id)) end defp autofollow_users(user) do @@ -2051,24 +2060,16 @@ defp create_service_actor(uri, nickname) do |> set_cache() end - def public_key(%{public_key: public_key_pem}) when is_binary(public_key_pem) do - key = - public_key_pem - |> :public_key.pem_decode() - |> hd() - |> :public_key.pem_entry_decode() - - {:ok, key} - end - - def public_key(_), do: {:error, "key not found"} + defdelegate public_key(user), to: SigningKey def get_public_key_for_ap_id(ap_id) do with {:ok, %User{} = user} <- get_or_fetch_by_ap_id(ap_id), - {:ok, public_key} <- public_key(user) do + {:ok, public_key} <- SigningKey.public_key(user) do {:ok, public_key} else - _ -> :error + e -> + Logger.error("Could not get public key for #{ap_id}.\n#{inspect(e)}") + {:error, e} end end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index c87072300..9b28e64d9 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -1547,6 +1547,17 @@ defp normalize_attachment(%{} = attachment), do: [attachment] defp normalize_attachment(attachment) when is_list(attachment), do: attachment defp normalize_attachment(_), do: [] + defp maybe_make_public_key_object(data) do + if is_map(data["publicKey"]) && is_binary(data["publicKey"]["publicKeyPem"]) do + %{ + public_key: data["publicKey"]["publicKeyPem"], + key_id: data["publicKey"]["id"] + } + else + nil + end + end + defp object_to_user_data(data, additional) do fields = data @@ -1578,9 +1589,16 @@ defp object_to_user_data(data, additional) do featured_address = data["featured"] {:ok, pinned_objects} = fetch_and_prepare_featured_from_ap_id(featured_address) - public_key = - if is_map(data["publicKey"]) && is_binary(data["publicKey"]["publicKeyPem"]) do - data["publicKey"]["publicKeyPem"] + # first, check that the owner is correct + signing_key = + if data["id"] !== data["publicKey"]["owner"] do + Logger.error( + "Owner of the public key is not the same as the actor - not saving the public key." + ) + + nil + else + maybe_make_public_key_object(data) end shared_inbox = @@ -1624,7 +1642,7 @@ defp object_to_user_data(data, additional) do bio: data["summary"] || "", actor_type: actor_type, also_known_as: also_known_as, - public_key: public_key, + signing_key: signing_key, inbox: data["inbox"], shared_inbox: shared_inbox, pinned_objects: pinned_objects, diff --git a/lib/pleroma/web/activity_pub/object_validators/user_validator.ex b/lib/pleroma/web/activity_pub/object_validators/user_validator.ex index adb291a55..b80068e37 100644 --- a/lib/pleroma/web/activity_pub/object_validators/user_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/user_validator.ex @@ -14,7 +14,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.UserValidator do @behaviour Pleroma.Web.ActivityPub.ObjectValidator.Validating alias Pleroma.Object.Containment - alias Pleroma.Signature require Pleroma.Constants @@ -23,8 +22,7 @@ def validate(object, meta) def validate(%{"type" => type, "id" => _id} = data, meta) when type in Pleroma.Constants.actor_types() do - with :ok <- validate_pubkey(data), - :ok <- validate_inbox(data), + with :ok <- validate_inbox(data), :ok <- contain_collection_origin(data) do {:ok, data, meta} else @@ -35,33 +33,6 @@ def validate(%{"type" => type, "id" => _id} = data, meta) def validate(_, _), do: {:error, "Not a user object"} - defp mabye_validate_owner(nil, _actor), do: :ok - defp mabye_validate_owner(actor, actor), do: :ok - defp mabye_validate_owner(_owner, _actor), do: :error - - defp validate_pubkey( - %{"id" => id, "publicKey" => %{"id" => pk_id, "publicKeyPem" => _key}} = data - ) - when id != nil do - with {_, {:ok, kactor}} <- {:key, Signature.key_id_to_actor_id(pk_id)}, - true <- id == kactor, - :ok <- mabye_validate_owner(Map.get(data, "owner"), id) do - :ok - else - {:key, _} -> - {:error, "Unable to determine actor id from key id"} - - false -> - {:error, "Key id does not relate to user id"} - - _ -> - {:error, "Actor does not own its public key"} - end - end - - # pubkey is optional atm - defp validate_pubkey(_data), do: :ok - defp validate_inbox(%{"id" => id, "inbox" => inbox}) do case Containment.same_origin(id, inbox) do :ok -> :ok diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex index 47b8e37e5..d855e1e40 100644 --- a/lib/pleroma/web/activity_pub/views/user_view.ex +++ b/lib/pleroma/web/activity_pub/views/user_view.ex @@ -5,7 +5,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do use Pleroma.Web, :view - alias Pleroma.Keys alias Pleroma.Object alias Pleroma.Repo alias Pleroma.User @@ -33,9 +32,7 @@ def render("endpoints.json", %{user: %User{local: true} = _user}) do def render("endpoints.json", _), do: %{} def render("service.json", %{user: user}) do - {:ok, _, public_key} = Keys.keys_from_pem(user.keys) - public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key) - public_key = :public_key.pem_encode([public_key]) + public_key = User.SigningKey.public_key_pem(user) endpoints = render("endpoints.json", %{user: user}) @@ -70,9 +67,7 @@ def render("user.json", %{user: %User{nickname: "internal." <> _} = user}), do: render("service.json", %{user: user}) |> Map.put("preferredUsername", user.nickname) def render("user.json", %{user: user}) do - {:ok, _, public_key} = Keys.keys_from_pem(user.keys) - public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key) - public_key = :public_key.pem_encode([public_key]) + public_key = User.SigningKey.public_key_pem(user) user = User.sanitize_html(user) endpoints = render("endpoints.json", %{user: user}) @@ -116,6 +111,20 @@ def render("user.json", %{user: user}) do |> Map.merge(Utils.make_json_ld_header()) end + def render("keys.json", %{user: user}) do + public_key = User.SigningKey.public_key_pem(user) + + %{ + "id" => user.ap_id, + "publicKey" => %{ + "id" => User.SigningKey.key_id_of_local_user(user), + "owner" => user.ap_id, + "publicKeyPem" => public_key + } + } + |> Map.merge(Utils.make_json_ld_header()) + end + def render("following.json", %{user: user, page: page} = opts) do showing_items = (opts[:for] && opts[:for] == user) || !user.hide_follows showing_count = showing_items || !user.hide_follows_count diff --git a/lib/pleroma/web/plugs/mapped_signature_to_identity_plug.ex b/lib/pleroma/web/plugs/mapped_signature_to_identity_plug.ex index a73def682..93d269187 100644 --- a/lib/pleroma/web/plugs/mapped_signature_to_identity_plug.ex +++ b/lib/pleroma/web/plugs/mapped_signature_to_identity_plug.ex @@ -4,7 +4,6 @@ defmodule Pleroma.Web.Plugs.MappedSignatureToIdentityPlug do alias Pleroma.Helpers.AuthHelper - alias Pleroma.Signature alias Pleroma.User alias Pleroma.Web.ActivityPub.Utils @@ -33,7 +32,7 @@ def call(%{assigns: %{valid_signature: true}, params: %{"actor" => actor}} = con |> assign(:valid_signature, false) # remove me once testsuite uses mapped capabilities instead of what we do now - {:user, nil} -> + {:user, _} -> Logger.debug("Failed to map identity from signature (lookup failure)") Logger.debug("key_id=#{inspect(key_id_from_conn(conn))}, actor=#{actor}") @@ -93,22 +92,33 @@ defp only_permit_user_routes(conn) do end defp key_id_from_conn(conn) do - with %{"keyId" => key_id} <- HTTPSignatures.signature_for_conn(conn), - {:ok, ap_id} <- Signature.key_id_to_actor_id(key_id) do - ap_id - else + case HTTPSignatures.signature_for_conn(conn) do + %{"keyId" => key_id} when is_binary(key_id) -> + key_id + _ -> nil end end defp user_from_key_id(conn) do - with key_actor_id when is_binary(key_actor_id) <- key_id_from_conn(conn), - {:ok, %User{} = user} <- User.get_or_fetch_by_ap_id(key_actor_id) do + with {:key_id, key_id} when is_binary(key_id) <- {:key_id, key_id_from_conn(conn)}, + {:mapped_ap_id, ap_id} when is_binary(ap_id) <- + {:mapped_ap_id, User.SigningKey.key_id_to_ap_id(key_id)}, + {:user_fetch, {:ok, %User{} = user}} <- {:user_fetch, User.get_or_fetch_by_ap_id(ap_id)} do user else - _ -> - nil + {:key_id, nil} -> + Logger.debug("Failed to map identity from signature (no key ID)") + {:key_id, nil} + + {:mapped_ap_id, nil} -> + Logger.debug("Failed to map identity from signature (could not map key ID to AP ID)") + {:mapped_ap_id, nil} + + {:user_fetch, {:error, _}} -> + Logger.debug("Failed to map identity from signature (lookup failure)") + {:user_fetch, nil} end end diff --git a/mix.lock b/mix.lock index 09997f29d..92a704add 100644 --- a/mix.lock +++ b/mix.lock @@ -34,14 +34,14 @@ "elasticsearch": {:git, "https://akkoma.dev/AkkomaGang/elasticsearch-elixir.git", "6cd946f75f6ab9042521a009d1d32d29a90113ca", [ref: "main"]}, "elixir_make": {:hex, :elixir_make, "0.8.4", "4960a03ce79081dee8fe119d80ad372c4e7badb84c493cc75983f9d3bc8bde0f", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "6e7f1d619b5f61dfabd0a20aa268e575572b542ac31723293a4c1a567d5ef040"}, "elixir_xml_to_map": {:hex, :elixir_xml_to_map, "3.1.0", "4d6260486a8cce59e4bf3575fe2dd2a24766546ceeef9f93fcec6f7c62a2827a", [:mix], [{:erlsom, "~> 1.4", [hex: :erlsom, repo: "hexpm", optional: false]}], "hexpm", "8fe5f2e75f90bab07ee2161120c2dc038ebcae8135554f5582990f1c8c21f911"}, - "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, + "erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"}, "erlsom": {:hex, :erlsom, "1.5.1", "c8fe2babd33ff0846403f6522328b8ab676f896b793634cfe7ef181c05316c03", [:rebar3], [], "hexpm", "7965485494c5844dd127656ac40f141aadfa174839ec1be1074e7edf5b4239eb"}, "eternal": {:hex, :eternal, "1.2.2", "d1641c86368de99375b98d183042dd6c2b234262b8d08dfd72b9eeaafc2a1abd", [:mix], [], "hexpm", "2c9fe32b9c3726703ba5e1d43a1d255a4f3f2d8f8f9bc19f094c7cb1a7a9e782"}, "ex_aws": {:hex, :ex_aws, "2.5.4", "86c5bb870a49e0ab6f5aa5dd58cf505f09d2624ebe17530db3c1b61c88a673af", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8 or ~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:mime, "~> 1.2 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e82bd0091bb9a5bb190139599f922ff3fc7aebcca4374d65c99c4e23aa6d1625"}, "ex_aws_s3": {:hex, :ex_aws_s3, "2.5.3", "422468e5c3e1a4da5298e66c3468b465cfd354b842e512cb1f6fbbe4e2f5bdaf", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "4f09dd372cc386550e484808c5ac5027766c8d0cd8271ccc578b82ee6ef4f3b8"}, "ex_const": {:hex, :ex_const, "0.3.0", "9d79516679991baf540ef445438eef1455ca91cf1a3c2680d8fb9e5bea2fe4de", [:mix], [], "hexpm", "76546322abb9e40ee4a2f454cf1c8a5b25c3672fa79bed1ea52c31e0d2428ca9"}, - "ex_doc": {:hex, :ex_doc, "0.34.0", "ab95e0775db3df71d30cf8d78728dd9261c355c81382bcd4cefdc74610bef13e", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "60734fb4c1353f270c3286df4a0d51e65a2c1d9fba66af3940847cc65a8066d7"}, - "ex_machina": {:hex, :ex_machina, "2.7.0", "b792cc3127fd0680fecdb6299235b4727a4944a09ff0fa904cc639272cd92dc7", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "419aa7a39bde11894c87a615c4ecaa52d8f107bbdd81d810465186f783245bf8"}, + "ex_doc": {:hex, :ex_doc, "0.34.1", "9751a0419bc15bc7580c73fde506b17b07f6402a1e5243be9e0f05a68c723368", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "d441f1a86a235f59088978eff870de2e815e290e44a8bd976fe5d64470a4c9d2"}, + "ex_machina": {:hex, :ex_machina, "2.8.0", "a0e847b5712065055ec3255840e2c78ef9366634d62390839d4880483be38abe", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "79fe1a9c64c0c1c1fab6c4fa5d871682cb90de5885320c187d117004627a7729"}, "ex_syslogger": {:hex, :ex_syslogger, "2.0.0", "de6de5c5472a9c4fdafb28fa6610e381ae79ebc17da6490b81d785d68bd124c9", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}, {:syslog, "~> 1.1.0", [hex: :syslog, repo: "hexpm", optional: false]}], "hexpm", "a52b2fe71764e9e6ecd149ab66635812f68e39279cbeee27c52c0e35e8b8019e"}, "excoveralls": {:hex, :excoveralls, "0.16.1", "0bd42ed05c7d2f4d180331a20113ec537be509da31fed5c8f7047ce59ee5a7c5", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "dae763468e2008cf7075a64cb1249c97cb4bc71e236c5c2b5e5cdf1cfa2bf138"}, "expo": {:hex, :expo, "0.4.1", "1c61d18a5df197dfda38861673d392e642649a9cef7694d2f97a587b2cfb319b", [:mix], [], "hexpm", "2ff7ba7a798c8c543c12550fa0e2cbc81b95d4974c65855d8d15ba7b37a1ce47"}, @@ -83,10 +83,10 @@ "nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"}, "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"}, "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"}, - "oban": {:hex, :oban, "2.17.10", "c3e5bd739b5c3fdc38eba1d43ab270a8c6ca4463bb779b7705c69400b0d87678", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4afd027b8e2bc3c399b54318b4f46ee8c40251fb55a285cb4e38b5363f0ee7c4"}, + "oban": {:hex, :oban, "2.17.11", "7a641f9f737b626030c3e2209b53df6db83740ac5537208bac7d3b9871c2d5e7", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c445c488151939d64265a5efea51973fa0b42ee4ebbb31aa83fac26543b8ac6d"}, "open_api_spex": {:hex, :open_api_spex, "3.19.1", "65ccb5d06e3d664d1eec7c5ea2af2289bd2f37897094a74d7219fb03fc2b5994", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 3.0 or ~> 4.0 or ~> 5.0", [hex: :poison, repo: "hexpm", optional: true]}, {:ymlr, "~> 2.0 or ~> 3.0 or ~> 4.0 or ~> 5.0", [hex: :ymlr, repo: "hexpm", optional: true]}], "hexpm", "392895827ce2984a3459c91a484e70708132d8c2c6c5363972b4b91d6bbac3dd"}, "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, - "phoenix": {:hex, :phoenix, "1.7.12", "1cc589e0eab99f593a8aa38ec45f15d25297dd6187ee801c8de8947090b5a9d3", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "d646192fbade9f485b01bc9920c139bfdd19d0f8df3d73fd8eaf2dfbe0d2837c"}, + "phoenix": {:hex, :phoenix, "1.7.14", "a7d0b3f1bc95987044ddada111e77bd7f75646a08518942c72a8440278ae7825", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "c7859bc56cc5dfef19ecfc240775dae358cbaa530231118a9e014df392ace61a"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.6.1", "96798325fab2fed5a824ca204e877b81f9afd2e480f581e81f7b4b64a5a477f2", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.17", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "0ae544ff99f3c482b0807c5cec2c8289e810ecacabc04959d82c3337f4703391"}, "phoenix_html": {:hex, :phoenix_html, "3.3.4", "42a09fc443bbc1da37e372a5c8e6755d046f22b9b11343bf885067357da21cb3", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "0249d3abec3714aff3415e7ee3d9786cb325be3151e6c4b3021502c585bf53fb"}, "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.7.2", "97cc4ff2dba1ebe504db72cb45098cb8e91f11160528b980bd282cc45c73b29c", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.18.3", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "0e5fdf063c7a3b620c566a30fcf68b7ee02e5e46fe48ee46a6ec3ba382dc05b7"}, @@ -95,7 +95,7 @@ "phoenix_swoosh": {:hex, :phoenix_swoosh, "1.2.1", "b74ccaa8046fbc388a62134360ee7d9742d5a8ae74063f34eb050279de7a99e1", [:mix], [{:finch, "~> 0.8", [hex: :finch, repo: "hexpm", optional: true]}, {:hackney, "~> 1.10", [hex: :hackney, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:swoosh, "~> 1.5", [hex: :swoosh, repo: "hexpm", optional: false]}], "hexpm", "4000eeba3f9d7d1a6bf56d2bd56733d5cadf41a7f0d8ffe5bb67e7d667e204a2"}, "phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"}, "phoenix_view": {:hex, :phoenix_view, "2.0.4", "b45c9d9cf15b3a1af5fb555c674b525391b6a1fe975f040fb4d913397b31abf4", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "4e992022ce14f31fe57335db27a28154afcc94e9983266835bb3040243eb620b"}, - "plug": {:hex, :plug, "1.16.0", "1d07d50cb9bb05097fdf187b31cf087c7297aafc3fed8299aac79c128a707e47", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cbf53aa1f5c4d758a7559c0bd6d59e286c2be0c6a1fac8cc3eee2f638243b93e"}, + "plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"}, "plug_cowboy": {:hex, :plug_cowboy, "2.7.1", "87677ffe3b765bc96a89be7960f81703223fe2e21efa42c125fcd0127dd9d6b2", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "02dbd5f9ab571b864ae39418db7811618506256f6d13b4a45037e5fe78dc5de3"}, "plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"}, "plug_static_index_html": {:hex, :plug_static_index_html, "1.0.0", "840123d4d3975585133485ea86af73cb2600afd7f2a976f9f5fd8b3808e636a0", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "79fd4fcf34d110605c26560cbae8f23c603ec4158c08298bd4360fdea90bb5cf"}, @@ -120,7 +120,7 @@ "telemetry_metrics_prometheus_core": {:hex, :telemetry_metrics_prometheus_core, "1.1.0", "4e15f6d7dbedb3a4e3aed2262b7e1407f166fcb9c30ca3f96635dfbbef99965c", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "0dd10e7fe8070095df063798f82709b0a1224c31b8baf6278b423898d591a069"}, "telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"}, "temple": {:git, "https://akkoma.dev/AkkomaGang/temple.git", "066a699ade472d8fa42a9d730b29a61af9bc8b59", [ref: "066a699ade472d8fa42a9d730b29a61af9bc8b59"]}, - "tesla": {:hex, :tesla, "1.9.0", "8c22db6a826e56a087eeb8cdef56889731287f53feeb3f361dec5d4c8efb6f14", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "7c240c67e855f7e63e795bf16d6b3f5115a81d1f44b7fe4eadbf656bae0fef8a"}, + "tesla": {:hex, :tesla, "1.11.0", "81b2b10213dddb27105ec6102d9eb0cc93d7097a918a0b1594f2dfd1a4601190", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "b83ab5d4c2d202e1ea2b7e17a49f788d49a699513d7c4f08f2aef2c281be69db"}, "timex": {:hex, :timex, "3.7.11", "bb95cb4eb1d06e27346325de506bcc6c30f9c6dea40d1ebe390b262fad1862d1", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.20", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.1", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "8b9024f7efbabaf9bd7aa04f65cf8dcd7c9818ca5737677c7b76acbc6a94d1aa"}, "trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bd4fde4c15f3e993a999e019d64347489b91b7a9096af68b2bdadd192afa693f"}, "tzdata": {:hex, :tzdata, "1.1.1", "20c8043476dfda8504952d00adac41c6eda23912278add38edc140ae0c5bcc46", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a69cec8352eafcd2e198dea28a34113b60fdc6cb57eb5ad65c10292a6ba89787"}, diff --git a/test/pleroma/keys_test.exs b/test/pleroma/keys_test.exs deleted file mode 100644 index 9a15bf06e..000000000 --- a/test/pleroma/keys_test.exs +++ /dev/null @@ -1,24 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2021 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.KeysTest do - use Pleroma.DataCase, async: true - - alias Pleroma.Keys - - test "generates an RSA private key pem" do - {:ok, key} = Keys.generate_rsa_pem() - - assert is_binary(key) - assert Regex.match?(~r/RSA/, key) - end - - test "returns a public and private key from a pem" do - pem = File.read!("test/fixtures/private_key.pem") - {:ok, private, public} = Keys.keys_from_pem(pem) - - assert elem(private, 0) == :RSAPrivateKey - assert elem(public, 0) == :RSAPublicKey - end -end diff --git a/test/pleroma/user_test.exs b/test/pleroma/user_test.exs index e3f0bb415..207e38993 100644 --- a/test/pleroma/user_test.exs +++ b/test/pleroma/user_test.exs @@ -639,11 +639,12 @@ test "it sets the password_hash, ap_id, private key and followers collection add changeset = User.register_changeset(%User{}, @full_user_data) assert changeset.valid? - assert is_binary(changeset.changes[:password_hash]) - assert is_binary(changeset.changes[:keys]) assert changeset.changes[:ap_id] == User.ap_id(%User{nickname: @full_user_data.nickname}) - assert is_binary(changeset.changes[:keys]) + assert changeset.changes[:signing_key] + assert changeset.changes[:signing_key].valid? + assert is_binary(changeset.changes[:signing_key].changes.private_key) + assert is_binary(changeset.changes[:signing_key].changes.public_key) assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers" end @@ -1665,7 +1666,6 @@ test "delete/1 purges a user when they wouldn't be fully deleted" do name: "qqqqqqq", password_hash: "pdfk2$1b3n159001", keys: "RSA begin buplic key", - public_key: "--PRIVATE KEYE--", avatar: %{"a" => "b"}, tags: ["qqqqq"], banner: %{"a" => "b"}, @@ -1704,8 +1704,6 @@ test "delete/1 purges a user when they wouldn't be fully deleted" do email: nil, name: nil, password_hash: nil, - keys: "RSA begin buplic key", - public_key: "--PRIVATE KEYE--", avatar: %{}, tags: [], last_refreshed_at: nil, diff --git a/test/pleroma/web/plugs/mapped_signature_to_identity_plug_test.exs b/test/pleroma/web/plugs/mapped_signature_to_identity_plug_test.exs index 086a27885..cfcccbf9e 100644 --- a/test/pleroma/web/plugs/mapped_signature_to_identity_plug_test.exs +++ b/test/pleroma/web/plugs/mapped_signature_to_identity_plug_test.exs @@ -8,52 +8,58 @@ defmodule Pleroma.Web.Plugs.MappedSignatureToIdentityPlugTest do import Tesla.Mock import Plug.Conn + import Pleroma.Factory import Pleroma.Tests.Helpers, only: [clear_config: 2] setup do mock(fn env -> apply(HttpRequestMock, :request, [env]) end) - :ok + user = insert(:user) + {:ok, %{user: user}} end - defp set_signature(conn, key_id) do + defp set_signature(conn, ap_id) do conn - |> put_req_header("signature", "keyId=\"#{key_id}\"") + |> put_req_header("signature", "keyId=\"#{ap_id}#main-key\"") |> assign(:valid_signature, true) end - test "it successfully maps a valid identity with a valid signature" do + test "it successfully maps a valid identity with a valid signature", %{user: user} do conn = build_conn(:get, "/doesntmattter") - |> set_signature("http://mastodon.example.org/users/admin") + |> set_signature(user.ap_id) |> MappedSignatureToIdentityPlug.call(%{}) refute is_nil(conn.assigns.user) end - test "it successfully maps a valid identity with a valid signature with payload" do + test "it successfully maps a valid identity with a valid signature with payload", %{user: user} do conn = - build_conn(:post, "/doesntmattter", %{"actor" => "http://mastodon.example.org/users/admin"}) - |> set_signature("http://mastodon.example.org/users/admin") + build_conn(:post, "/doesntmattter", %{"actor" => user.ap_id}) + |> set_signature(user.ap_id) |> MappedSignatureToIdentityPlug.call(%{}) refute is_nil(conn.assigns.user) end - test "it considers a mapped identity to be invalid when it mismatches a payload" do + test "it considers a mapped identity to be invalid when it mismatches a payload", %{user: user} do conn = - build_conn(:post, "/doesntmattter", %{"actor" => "http://mastodon.example.org/users/admin"}) + build_conn(:post, "/doesntmattter", %{"actor" => user.ap_id}) |> set_signature("https://niu.moe/users/rye") |> MappedSignatureToIdentityPlug.call(%{}) assert %{valid_signature: false} == conn.assigns end - test "it considers a mapped identity to be invalid when the associated instance is blocked" do + test "it considers a mapped identity to be invalid when the associated instance is blocked", %{ + user: user + } do clear_config([:activitypub, :authorized_fetch_mode], true) + # extract domain from user.ap_id + url = URI.parse(user.ap_id) clear_config([:mrf_simple, :reject], [ - {"mastodon.example.org", "anime is banned"} + {url.host, "anime is banned"} ]) on_exit(fn -> @@ -62,18 +68,20 @@ test "it considers a mapped identity to be invalid when the associated instance end) conn = - build_conn(:post, "/doesntmattter", %{"actor" => "http://mastodon.example.org/users/admin"}) - |> set_signature("http://mastodon.example.org/users/admin") + build_conn(:post, "/doesntmattter", %{"actor" => user.ap_id}) + |> set_signature(user.ap_id) |> MappedSignatureToIdentityPlug.call(%{}) assert %{valid_signature: false} == conn.assigns end - test "allowlist federation: it considers a mapped identity to be valid when the associated instance is allowed" do + test "allowlist federation: it considers a mapped identity to be valid when the associated instance is allowed", + %{user: user} do clear_config([:activitypub, :authorized_fetch_mode], true) + url = URI.parse(user.ap_id) clear_config([:mrf_simple, :accept], [ - {"mastodon.example.org", "anime is allowed"} + {url.host, "anime is allowed"} ]) on_exit(fn -> @@ -82,15 +90,16 @@ test "allowlist federation: it considers a mapped identity to be valid when the end) conn = - build_conn(:post, "/doesntmattter", %{"actor" => "http://mastodon.example.org/users/admin"}) - |> set_signature("http://mastodon.example.org/users/admin") + build_conn(:post, "/doesntmattter", %{"actor" => user.ap_id}) + |> set_signature(user.ap_id) |> MappedSignatureToIdentityPlug.call(%{}) assert conn.assigns[:valid_signature] refute is_nil(conn.assigns.user) end - test "allowlist federation: it considers a mapped identity to be invalid when the associated instance is not allowed" do + test "allowlist federation: it considers a mapped identity to be invalid when the associated instance is not allowed", + %{user: user} do clear_config([:activitypub, :authorized_fetch_mode], true) clear_config([:mrf_simple, :accept], [ @@ -103,8 +112,8 @@ test "allowlist federation: it considers a mapped identity to be invalid when th end) conn = - build_conn(:post, "/doesntmattter", %{"actor" => "http://mastodon.example.org/users/admin"}) - |> set_signature("http://mastodon.example.org/users/admin") + build_conn(:post, "/doesntmattter", %{"actor" => user.ap_id}) + |> set_signature(user.ap_id) |> MappedSignatureToIdentityPlug.call(%{}) assert %{valid_signature: false} == conn.assigns diff --git a/test/support/factory.ex b/test/support/factory.ex index 2a73a4ae6..f648179d2 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -47,7 +47,6 @@ def instance_factory(attrs \\ %{}) do end def user_factory(attrs \\ %{}) do - pem = Enum.random(@rsa_keys) # Argon2.hash_pwd_salt("test") # it really eats CPU time, so we use a precomputed hash password_hash = @@ -64,8 +63,7 @@ def user_factory(attrs \\ %{}) do last_refreshed_at: NaiveDateTime.utc_now(), notification_settings: %Pleroma.User.NotificationSetting{}, multi_factor_authentication_settings: %Pleroma.MFA.Settings{}, - ap_enabled: true, - keys: pem + ap_enabled: true } urls = @@ -90,13 +88,27 @@ def user_factory(attrs \\ %{}) do end attrs = Map.delete(attrs, :domain) + signing_key = insert(:signing_key, %{key_id: urls[:ap_id] <> "#main-key"}) user |> Map.put(:raw_bio, user.bio) + |> Map.put(:signing_key, signing_key) |> Map.merge(urls) |> merge_attributes(attrs) end + def signing_key_factory(attrs \\ %{}) do + pem = Enum.random(@rsa_keys) + {:ok, public_key} = Pleroma.User.SigningKey.private_pem_to_public_pem(pem) + + %Pleroma.User.SigningKey{ + public_key: public_key, + private_key: pem, + key_id: attrs[:key_id] || "https://example.com/key" + } + |> merge_attributes(attrs) + end + def user_relationship_factory(attrs \\ %{}) do source = attrs[:source] || insert(:user) target = attrs[:target] || insert(:user)