Compare commits
1 Commits
ce874fa151
...
53cf9d4e20
Author | SHA1 | Date | |
---|---|---|---|
53cf9d4e20 |
@ -4,11 +4,6 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
## 2.6.3
|
||||
|
||||
### Security
|
||||
- Fix webfinger spoofing.
|
||||
|
||||
## 2.6.2
|
||||
|
||||
### Security
|
||||
|
@ -1 +0,0 @@
|
||||
Fix validate_webfinger when running a different domain for Webfinger
|
@ -210,8 +210,7 @@ defmodule Pleroma.Application do
|
||||
expiration: chat_message_id_idempotency_key_expiration(),
|
||||
limit: 500_000
|
||||
),
|
||||
build_cachex("rel_me", limit: 2500),
|
||||
build_cachex("host_meta", default_ttl: :timer.minutes(120), limit: 5000)
|
||||
build_cachex("rel_me", limit: 2500)
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -155,16 +155,7 @@ defmodule Pleroma.Web.WebFinger do
|
||||
end
|
||||
end
|
||||
|
||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||
def find_lrdd_template(domain) do
|
||||
@cachex.fetch!(:host_meta_cache, domain, fn _ ->
|
||||
{:commit, fetch_lrdd_template(domain)}
|
||||
end)
|
||||
rescue
|
||||
e -> {:error, "Cachex error: #{inspect(e)}"}
|
||||
end
|
||||
|
||||
defp fetch_lrdd_template(domain) do
|
||||
# WebFinger is restricted to HTTPS - https://tools.ietf.org/html/rfc7033#section-9.1
|
||||
meta_url = "https://#{domain}/.well-known/host-meta"
|
||||
|
||||
@ -177,7 +168,7 @@ defmodule Pleroma.Web.WebFinger do
|
||||
end
|
||||
end
|
||||
|
||||
defp get_address_from_domain(domain, "acct:" <> _ = encoded_account) when is_binary(domain) do
|
||||
defp get_address_from_domain(domain, encoded_account) when is_binary(domain) do
|
||||
case find_lrdd_template(domain) do
|
||||
{:ok, template} ->
|
||||
String.replace(template, "{uri}", encoded_account)
|
||||
@ -187,11 +178,6 @@ defmodule Pleroma.Web.WebFinger do
|
||||
end
|
||||
end
|
||||
|
||||
defp get_address_from_domain(domain, account) when is_binary(domain) do
|
||||
encoded_account = URI.encode("acct:#{account}")
|
||||
get_address_from_domain(domain, encoded_account)
|
||||
end
|
||||
|
||||
defp get_address_from_domain(_, _), do: {:error, :webfinger_no_domain}
|
||||
|
||||
@spec finger(String.t()) :: {:ok, map()} | {:error, any()}
|
||||
@ -206,7 +192,9 @@ defmodule Pleroma.Web.WebFinger do
|
||||
URI.parse(account).host
|
||||
end
|
||||
|
||||
with address when is_binary(address) <- get_address_from_domain(domain, account),
|
||||
encoded_account = URI.encode("acct:#{account}")
|
||||
|
||||
with address when is_binary(address) <- get_address_from_domain(domain, encoded_account),
|
||||
{:ok, %{status: status, body: body, headers: headers}} when status in 200..299 <-
|
||||
HTTP.get(
|
||||
address,
|
||||
@ -228,28 +216,10 @@ defmodule Pleroma.Web.WebFinger do
|
||||
_ ->
|
||||
{:error, {:content_type, nil}}
|
||||
end
|
||||
|> case do
|
||||
{:ok, data} -> validate_webfinger(address, data)
|
||||
error -> error
|
||||
end
|
||||
else
|
||||
error ->
|
||||
Logger.debug("Couldn't finger #{account}: #{inspect(error)}")
|
||||
error
|
||||
end
|
||||
end
|
||||
|
||||
defp validate_webfinger(request_url, %{"subject" => "acct:" <> acct = subject} = data) do
|
||||
with [_name, acct_host] <- String.split(acct, "@"),
|
||||
{_, url} <- {:address, get_address_from_domain(acct_host, subject)},
|
||||
%URI{host: request_host} <- URI.parse(request_url),
|
||||
%URI{host: acct_host} <- URI.parse(url),
|
||||
{_, true} <- {:hosts_match, acct_host == request_host} do
|
||||
{:ok, data}
|
||||
else
|
||||
_ -> {:error, {:webfinger_invalid, request_url, data}}
|
||||
end
|
||||
end
|
||||
|
||||
defp validate_webfinger(url, data), do: {:error, {:webfinger_invalid, url, data}}
|
||||
end
|
||||
|
2
mix.exs
2
mix.exs
@ -4,7 +4,7 @@ defmodule Pleroma.Mixfile do
|
||||
def project do
|
||||
[
|
||||
app: :pleroma,
|
||||
version: version("2.6.3"),
|
||||
version: version("2.6.2"),
|
||||
elixir: "~> 1.11",
|
||||
elixirc_paths: elixirc_paths(Mix.env()),
|
||||
compilers: [:phoenix] ++ Mix.compilers(),
|
||||
|
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
<Link rel="lrdd" template="https://gleasonator.com/.well-known/webfinger?resource={uri}" type="application/xrd+xml" />
|
||||
</XRD>
|
28
test/fixtures/tesla_mock/webfinger_spoof.json
vendored
28
test/fixtures/tesla_mock/webfinger_spoof.json
vendored
@ -1,28 +0,0 @@
|
||||
{
|
||||
"aliases": [
|
||||
"https://gleasonator.com/users/alex",
|
||||
"https://mitra.social/users/alex"
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"href": "https://gleasonator.com/users/alex",
|
||||
"rel": "http://webfinger.net/rel/profile-page",
|
||||
"type": "text/html"
|
||||
},
|
||||
{
|
||||
"href": "https://gleasonator.com/users/alex",
|
||||
"rel": "self",
|
||||
"type": "application/activity+json"
|
||||
},
|
||||
{
|
||||
"href": "https://gleasonator.com/users/alex",
|
||||
"rel": "self",
|
||||
"type": "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
|
||||
},
|
||||
{
|
||||
"rel": "http://ostatus.org/schema/1.0/subscribe",
|
||||
"template": "https://gleasonator.com/ostatus_subscribe?acct={uri}"
|
||||
}
|
||||
],
|
||||
"subject": "acct:trump@whitehouse.gov"
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"subject": "acct:graf@poa.st",
|
||||
"aliases": [
|
||||
"https://fba.ryona.agenc/webfingertest"
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"rel": "http://webfinger.net/rel/profile-page",
|
||||
"type": "text/html",
|
||||
"href": "https://fba.ryona.agenc/webfingertest"
|
||||
},
|
||||
{
|
||||
"rel": "self",
|
||||
"type": "application/activity+json",
|
||||
"href": "https://fba.ryona.agenc/webfingertest"
|
||||
},
|
||||
{
|
||||
"rel": "http://ostatus.org/schema/1.0/subscribe",
|
||||
"template": "https://fba.ryona.agenc/contact/follow?url={uri}"
|
||||
},
|
||||
{
|
||||
"rel": "http://schemas.google.com/g/2010#updates-from",
|
||||
"type": "application/atom+xml",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"rel": "salmon",
|
||||
"href": "https://fba.ryona.agenc/salmon/friendica"
|
||||
},
|
||||
{
|
||||
"rel": "http://microformats.org/profile/hcard",
|
||||
"type": "text/html",
|
||||
"href": "https://fba.ryona.agenc/hcard/friendica"
|
||||
},
|
||||
{
|
||||
"rel": "http://joindiaspora.com/seed_location",
|
||||
"type": "text/html",
|
||||
"href": "https://fba.ryona.agenc"
|
||||
}
|
||||
]
|
||||
}
|
@ -872,19 +872,109 @@ defmodule Pleroma.UserTest do
|
||||
setup do: clear_config([Pleroma.Web.WebFinger, :update_nickname_on_user_fetch], true)
|
||||
|
||||
test "for mastodon" do
|
||||
ap_id = "a@mastodon.example"
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://example.com/.well-known/host-meta"} ->
|
||||
%Tesla.Env{
|
||||
status: 302,
|
||||
headers: [{"location", "https://sub.example.com/.well-known/host-meta"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/.well-known/host-meta"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/masto-host-meta.xml"
|
||||
|> File.read!()
|
||||
|> String.replace("{{domain}}", "sub.example.com")
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/.well-known/webfinger?resource=acct:a@example.com"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/masto-webfinger.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "example.com")
|
||||
|> String.replace("{{subdomain}}", "sub.example.com"),
|
||||
headers: [{"content-type", "application/jrd+json"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/users/a"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/masto-user.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "sub.example.com"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/users/a/collections/featured"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
File.read!("test/fixtures/users_mock/masto_featured.json")
|
||||
|> String.replace("{{domain}}", "sub.example.com")
|
||||
|> String.replace("{{nickname}}", "a"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
ap_id = "a@example.com"
|
||||
{:ok, fetched_user} = User.get_or_fetch(ap_id)
|
||||
|
||||
assert fetched_user.ap_id == "https://sub.mastodon.example/users/a"
|
||||
assert fetched_user.nickname == "a@mastodon.example"
|
||||
assert fetched_user.ap_id == "https://sub.example.com/users/a"
|
||||
assert fetched_user.nickname == "a@example.com"
|
||||
end
|
||||
|
||||
test "for pleroma" do
|
||||
ap_id = "a@pleroma.example"
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://example.com/.well-known/host-meta"} ->
|
||||
%Tesla.Env{
|
||||
status: 302,
|
||||
headers: [{"location", "https://sub.example.com/.well-known/host-meta"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/.well-known/host-meta"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/pleroma-host-meta.xml"
|
||||
|> File.read!()
|
||||
|> String.replace("{{domain}}", "sub.example.com")
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/.well-known/webfinger?resource=acct:a@example.com"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/pleroma-webfinger.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "example.com")
|
||||
|> String.replace("{{subdomain}}", "sub.example.com"),
|
||||
headers: [{"content-type", "application/jrd+json"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/users/a"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/pleroma-user.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "sub.example.com"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
ap_id = "a@example.com"
|
||||
{:ok, fetched_user} = User.get_or_fetch(ap_id)
|
||||
|
||||
assert fetched_user.ap_id == "https://sub.pleroma.example/users/a"
|
||||
assert fetched_user.nickname == "a@pleroma.example"
|
||||
assert fetched_user.ap_id == "https://sub.example.com/users/a"
|
||||
assert fetched_user.nickname == "a@example.com"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -48,7 +48,12 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do
|
||||
]
|
||||
end
|
||||
|
||||
test "reach user on tld, while pleroma is running on subdomain" do
|
||||
test "reach user on tld, while pleroma is runned on subdomain" do
|
||||
Pleroma.Web.Endpoint.config_change(
|
||||
[{Pleroma.Web.Endpoint, url: [host: "sub.example.com"]}],
|
||||
[]
|
||||
)
|
||||
|
||||
clear_config([Pleroma.Web.Endpoint, :url, :host], "sub.example.com")
|
||||
|
||||
clear_config([Pleroma.Web.WebFinger, :domain], "example.com")
|
||||
|
@ -76,6 +76,15 @@ defmodule Pleroma.Web.WebFingerTest do
|
||||
{:ok, _data} = WebFinger.finger(user)
|
||||
end
|
||||
|
||||
test "returns the ActivityPub actor URI and subscribe address for an ActivityPub user with the ld+json mimetype" do
|
||||
user = "kaniini@gerzilla.de"
|
||||
|
||||
{:ok, data} = WebFinger.finger(user)
|
||||
|
||||
assert data["ap_id"] == "https://gerzilla.de/channel/kaniini"
|
||||
assert data["subscribe_address"] == "https://gerzilla.de/follow?f=&url={uri}"
|
||||
end
|
||||
|
||||
test "it work for AP-only user" do
|
||||
user = "kpherox@mstdn.jp"
|
||||
|
||||
@ -90,6 +99,12 @@ defmodule Pleroma.Web.WebFingerTest do
|
||||
assert data["subscribe_address"] == "https://mstdn.jp/authorize_interaction?acct={uri}"
|
||||
end
|
||||
|
||||
test "it works for friendica" do
|
||||
user = "lain@squeet.me"
|
||||
|
||||
{:ok, _data} = WebFinger.finger(user)
|
||||
end
|
||||
|
||||
test "it gets the xrd endpoint" do
|
||||
{:ok, template} = WebFinger.find_lrdd_template("social.heldscal.la")
|
||||
|
||||
@ -188,44 +203,5 @@ defmodule Pleroma.Web.WebFingerTest do
|
||||
|
||||
assert :error = WebFinger.finger("pekorino@pawoo.net")
|
||||
end
|
||||
|
||||
test "prevents spoofing" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{
|
||||
url: "https://gleasonator.com/.well-known/webfinger?resource=acct:alex@gleasonator.com"
|
||||
} ->
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/tesla_mock/webfinger_spoof.json"),
|
||||
headers: [{"content-type", "application/jrd+json"}]
|
||||
}}
|
||||
|
||||
%{url: "https://gleasonator.com/.well-known/host-meta"} ->
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/tesla_mock/gleasonator.com_host_meta")
|
||||
}}
|
||||
end)
|
||||
|
||||
{:error, _data} = WebFinger.finger("alex@gleasonator.com")
|
||||
end
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "prevents forgeries" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://fba.ryona.agency/.well-known/webfinger?resource=acct:graf@fba.ryona.agency"} ->
|
||||
fake_webfinger =
|
||||
File.read!("test/fixtures/webfinger/graf-imposter-webfinger.json") |> Jason.decode!()
|
||||
|
||||
Tesla.Mock.json(fake_webfinger)
|
||||
|
||||
%{url: "https://fba.ryona.agency/.well-known/host-meta"} ->
|
||||
{:ok, %Tesla.Env{status: 404}}
|
||||
end)
|
||||
|
||||
assert {:error, _} = WebFinger.finger("graf@fba.ryona.agency")
|
||||
end
|
||||
end
|
||||
|
@ -1464,177 +1464,6 @@ defmodule HttpRequestMock do
|
||||
}}
|
||||
end
|
||||
|
||||
def get("https://google.com/", _, _, _) do
|
||||
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/google.html")}}
|
||||
end
|
||||
|
||||
def get("https://yahoo.com/", _, _, _) do
|
||||
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/yahoo.html")}}
|
||||
end
|
||||
|
||||
def get("https://example.com/error", _, _, _), do: {:error, :overload}
|
||||
|
||||
def get("https://example.com/ogp-missing-title", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/rich_media/ogp-missing-title.html")
|
||||
}}
|
||||
end
|
||||
|
||||
def get("https://example.com/oembed", _, _, _) do
|
||||
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/oembed.html")}}
|
||||
end
|
||||
|
||||
def get("https://example.com/oembed.json", _, _, _) do
|
||||
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/oembed.json")}}
|
||||
end
|
||||
|
||||
def get("https://example.com/twitter-card", _, _, _) do
|
||||
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/twitter_card.html")}}
|
||||
end
|
||||
|
||||
def get("https://example.com/non-ogp", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/non_ogp_embed.html")}}
|
||||
end
|
||||
|
||||
def get("https://example.com/empty", _, _, _) do
|
||||
{:ok, %Tesla.Env{status: 200, body: "hello"}}
|
||||
end
|
||||
|
||||
def get("https://friends.grishka.me/posts/54642", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/tesla_mock/smithereen_non_anonymous_poll.json"),
|
||||
headers: activitypub_object_headers()
|
||||
}}
|
||||
end
|
||||
|
||||
def get("https://friends.grishka.me/users/1", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/tesla_mock/smithereen_user.json"),
|
||||
headers: activitypub_object_headers()
|
||||
}}
|
||||
end
|
||||
|
||||
def get("https://mastodon.example/.well-known/host-meta", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 302,
|
||||
headers: [{"location", "https://sub.mastodon.example/.well-known/host-meta"}]
|
||||
}}
|
||||
end
|
||||
|
||||
def get("https://sub.mastodon.example/.well-known/host-meta", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/masto-host-meta.xml"
|
||||
|> File.read!()
|
||||
|> String.replace("{{domain}}", "sub.mastodon.example")
|
||||
}}
|
||||
end
|
||||
|
||||
def get(
|
||||
"https://sub.mastodon.example/.well-known/webfinger?resource=acct:a@mastodon.example",
|
||||
_,
|
||||
_,
|
||||
_
|
||||
) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/masto-webfinger.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "mastodon.example")
|
||||
|> String.replace("{{subdomain}}", "sub.mastodon.example"),
|
||||
headers: [{"content-type", "application/jrd+json"}]
|
||||
}}
|
||||
end
|
||||
|
||||
def get("https://sub.mastodon.example/users/a", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/masto-user.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "sub.mastodon.example"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}}
|
||||
end
|
||||
|
||||
def get("https://sub.mastodon.example/users/a/collections/featured", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
File.read!("test/fixtures/users_mock/masto_featured.json")
|
||||
|> String.replace("{{domain}}", "sub.mastodon.example")
|
||||
|> String.replace("{{nickname}}", "a"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}}
|
||||
end
|
||||
|
||||
def get("https://pleroma.example/.well-known/host-meta", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 302,
|
||||
headers: [{"location", "https://sub.pleroma.example/.well-known/host-meta"}]
|
||||
}}
|
||||
end
|
||||
|
||||
def get("https://sub.pleroma.example/.well-known/host-meta", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/pleroma-host-meta.xml"
|
||||
|> File.read!()
|
||||
|> String.replace("{{domain}}", "sub.pleroma.example")
|
||||
}}
|
||||
end
|
||||
|
||||
def get(
|
||||
"https://sub.pleroma.example/.well-known/webfinger?resource=acct:a@pleroma.example",
|
||||
_,
|
||||
_,
|
||||
_
|
||||
) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/pleroma-webfinger.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "pleroma.example")
|
||||
|> String.replace("{{subdomain}}", "sub.pleroma.example"),
|
||||
headers: [{"content-type", "application/jrd+json"}]
|
||||
}}
|
||||
end
|
||||
|
||||
def get("https://sub.pleroma.example/users/a", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/pleroma-user.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "sub.pleroma.example"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}}
|
||||
end
|
||||
|
||||
def get(url, query, body, headers) do
|
||||
{:error,
|
||||
"Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{inspect(headers)}"}
|
||||
|
Loading…
Reference in New Issue
Block a user