Skip to content
Snippets Groups Projects
Commit 427bac09 authored by lain's avatar lain
Browse files

Rework remote user subscription.

parent 69922bc7
No related branches found
No related tags found
No related merge requests found
......@@ -37,8 +37,8 @@ defmodule Pleroma.Web.OStatus do
def handle_note(doc) do
content_html = string_from_xpath("/entry/content[1]", doc)
[author] = :xmerl_xpath.string('/entry/author[1]', doc)
{:ok, actor} = find_or_make_user(author)
uri = string_from_xpath("/entry/author/uri[1]", doc)
{:ok, actor} = find_or_make_user(uri)
context = string_from_xpath("/entry/ostatus:conversation[1]", doc) |> String.trim
context = if String.length(context) > 0 do
......@@ -78,42 +78,30 @@ defmodule Pleroma.Web.OStatus do
ActivityPub.create(to, actor, context, object, %{}, date)
end
def find_or_make_user(author_doc) do
{:xmlObj, :string, uri } = :xmerl_xpath.string('string(/author[1]/uri)', author_doc)
def find_or_make_user(uri) do
query = from user in User,
where: user.local == false and fragment("? @> ?", user.info, ^%{ostatus_uri: to_string(uri)})
where: user.local == false and fragment("? @> ?", user.info, ^%{uri: uri})
user = Repo.one(query)
if is_nil(user) do
make_user(author_doc)
make_user(uri)
else
{:ok, user}
end
end
def make_user(author_doc) do
author = string_from_xpath("/author[1]/uri", author_doc)
name = string_from_xpath("/author[1]/name", author_doc)
preferredUsername = string_from_xpath("/author[1]/poco:preferredUsername", author_doc)
displayName = string_from_xpath("/author[1]/poco:displayName", author_doc)
avatar = make_avatar_object(author_doc)
data = %{
local: false,
name: preferredUsername || name,
nickname: displayName || name,
ap_id: author,
info: %{
"ostatus_uri" => author,
"host" => URI.parse(author).host,
"system" => "ostatus"
},
avatar: avatar
}
Repo.insert(Ecto.Changeset.change(%User{}, data))
def make_user(uri) do
with {:ok, info} <- gather_user_info(uri) do
data = %{
local: false,
name: info.name,
nickname: info.nickname,
ap_id: info.uri,
info: info
}
Repo.insert(Ecto.Changeset.change(%User{}, data))
end
end
# TODO: Just takes the first one for now.
......
......@@ -42,7 +42,7 @@ defmodule Pleroma.Web.WebFinger do
# FIXME: Make this call the host-meta to find the actual address.
defp webfinger_address(domain) do
"https://#{domain}/.well-known/webfinger"
"//#{domain}/.well-known/webfinger"
end
defp webfinger_from_xml(doc) do
......@@ -61,9 +61,21 @@ defmodule Pleroma.Web.WebFinger do
end
def finger(account, getter \\ &HTTPoison.get/3) do
[name, domain] = String.split(account, "@")
domain = with [_name, domain] <- String.split(account, "@") do
domain
else _e ->
URI.parse(account).host
end
address = webfinger_address(domain)
with {:ok, %{status_code: status_code, body: body}} when status_code in 200..299 <- getter.(address, ["Accept": "application/xrd+xml"], [params: [resource: account]]),
# try https first
response = with {:ok, result} <- getter.("https:" <> address, ["Accept": "application/xrd+xml"], [params: [resource: account]]) do
{:ok, result}
else _ ->
getter.("http:" <> address, ["Accept": "application/xrd+xml"], [params: [resource: account]])
end
with {:ok, %{status_code: status_code, body: body}} when status_code in 200..299 <- response,
doc <- XML.parse_document(body),
{:ok, data} <- webfinger_from_xml(doc) do
{:ok, data}
......
......@@ -102,19 +102,21 @@ defmodule Pleroma.Web.Websub do
end
end
def subscribe(user, topic, requester \\ &request_subscription/1) do
def subscribe(subscriber, subscribed, requester \\ &request_subscription/1) do
topic = subscribed.info["topic"]
# FIXME: Race condition, use transactions
{:ok, subscription} = with subscription when not is_nil(subscription) <- Repo.get_by(WebsubClientSubscription, topic: topic) do
subscribers = [user.ap_id, subscription.subcribers] |> Enum.uniq
subscribers = [subscriber.ap_id, subscription.subscribers] |> Enum.uniq
change = Ecto.Changeset.change(subscription, %{subscribers: subscribers})
Repo.update(change)
else _e ->
subscription = %WebsubClientSubscription{
topic: topic,
subscribers: [user.ap_id],
hub: subscribed.info["hub"],
subscribers: [subscriber.ap_id],
state: "requested",
secret: :crypto.strong_rand_bytes(8) |> Base.url_encode64,
user: user
user: subscribed
}
Repo.insert(subscription)
end
......
......@@ -25,40 +25,20 @@ defmodule Pleroma.Web.OStatusTest do
end
describe "new remote user creation" do
test "make new user or find them based on an 'author' xml doc" do
incoming = File.read!("test/fixtures/user_name_only.xml")
doc = XML.parse_document(incoming)
{:ok, user} = OStatus.find_or_make_user(doc)
assert user.name == "lambda"
assert user.nickname == "lambda"
assert user.local == false
assert user.info["ostatus_uri"] == "http://gs.example.org:4040/index.php/user/1"
assert user.info["system"] == "ostatus"
assert user.ap_id == "http://gs.example.org:4040/index.php/user/1"
{:ok, user_again} = OStatus.find_or_make_user(doc)
assert user == user_again
end
test "tries to use the information in poco fields" do
incoming = File.read!("test/fixtures/user_full.xml")
doc = XML.parse_document(incoming)
# TODO make test local
uri = "https://social.heldscal.la/user/23211"
{:ok, user} = OStatus.find_or_make_user(doc)
{:ok, user} = OStatus.find_or_make_user(uri)
user = Repo.get(Pleroma.User, user.id)
assert user.name == "Constance Variable"
assert user.nickname == "lambadalambda"
assert user.local == false
assert user.info["ostatus_uri"] == "http://gs.example.org:4040/index.php/user/1"
assert user.info["system"] == "ostatus"
assert user.ap_id == "http://gs.example.org:4040/index.php/user/1"
assert List.first(user.avatar["url"])["href"] == "http://gs.example.org:4040/theme/neo-gnu/default-avatar-profile.png"
assert user.info["uri"] == uri
assert user.ap_id == uri
{:ok, user_again} = OStatus.find_or_make_user(doc)
{:ok, user_again} = OStatus.find_or_make_user(uri)
assert user == user_again
end
......@@ -84,5 +64,25 @@ defmodule Pleroma.Web.OStatusTest do
}
assert data == expected
end
test "it works with the uri" do
user = "https://social.heldscal.la/user/29191"
# TODO: make test local
{:ok, data} = OStatus.gather_user_info(user)
expected = %{
hub: "https://social.heldscal.la/main/push/hub",
magic_key: "RSA.wQ3i9UA0qmAxZ0WTIp4a-waZn_17Ez1pEEmqmqoooRsG1_BvpmOvLN0G2tEcWWxl2KOtdQMCiPptmQObeZeuj48mdsDZ4ArQinexY2hCCTcbV8Xpswpkb8K05RcKipdg07pnI7tAgQ0VWSZDImncL6YUGlG5YN8b5TjGOwk2VG8=.AQAB",
name: "shp",
nickname: "shp",
salmon: "https://social.heldscal.la/main/salmon/user/29191",
subject: "https://social.heldscal.la/user/29191",
topic: "https://social.heldscal.la/api/statuses/user_timeline/29191.atom",
uri: "https://social.heldscal.la/user/29191",
fqn: user
}
assert data == expected
end
end
end
......@@ -93,12 +93,13 @@ defmodule Pleroma.Web.WebsubTest do
end
test "initiate a subscription for a given user and topic" do
user = insert(:user)
topic = "http://example.org/some-topic.atom"
subscriber = insert(:user)
user = insert(:user, %{info: %{ "topic" => "some_topic", "hub" => "some_hub"}})
{:ok, websub} = Websub.subscribe(user, topic, &accepting_verifier/1)
assert websub.subscribers == [user.ap_id]
assert websub.topic == topic
{:ok, websub} = Websub.subscribe(subscriber, user, &accepting_verifier/1)
assert websub.subscribers == [subscriber.ap_id]
assert websub.topic == "some_topic"
assert websub.hub == "some_hub"
assert is_binary(websub.secret)
assert websub.user == user
assert websub.state == "accepted"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment