defmodule NullaWeb.InboxControllerTest do use NullaWeb.ConnCase alias Nulla.Snowflake alias Nulla.Models.User alias Nulla.Models.Actor setup do Nulla.Fixtures.Data.create() :ok end describe "POST /users/username/inbox" do test "Validate follow request", %{conn: conn} do actor = Actor.get_actor(preferredUsername: "test") target_actor = Actor.get_actor(preferredUsername: "test2") user = User.get_user(id: actor.id) follow_activity = %{ "@context" => "https://www.w3.org/ns/activitystreams", "id" => Snowflake.next_id(), "type" => "Follow", "actor" => actor.ap_id, "object" => target_actor.ap_id } body = Jason.encode!(follow_activity) digest = "SHA-256=" <> (:crypto.hash(:sha256, body) |> Base.encode64()) date = Calendar.strftime(DateTime.utc_now(), "%a, %d %b %Y %H:%M:%S GMT") uri = URI.parse("/users/test2/inbox") signature_string = """ (request-target): post #{uri.path} host: localhost date: #{date} digest: #{digest} """ private_key = case :public_key.pem_decode(user.privateKeyPem) do [entry] -> :public_key.pem_entry_decode(entry) _ -> raise "Invalid PEM format" end signature = :public_key.sign(signature_string, :sha256, private_key) |> Base.encode64() signature_header = """ keyId="#{actor.publicKey["id"]}", algorithm="rsa-sha256", headers="(request-target) host date digest", signature="#{signature}" """ |> String.replace("\n", "") |> String.trim() conn = conn |> put_req_header("content-type", "application/activity+json") |> put_req_header("accept", "application/activity+json") |> put_req_header("date", date) |> put_req_header("digest", digest) |> put_req_header("signature", signature_header) |> post("/users/test2/inbox", body) assert conn.status == 200 end end end