Rework remote user subscription.
authorRoger Braun <roger@rogerbraun.net>
Sat, 29 Apr 2017 17:06:01 +0000 (19:06 +0200)
committerRoger Braun <roger@rogerbraun.net>
Sat, 29 Apr 2017 17:06:01 +0000 (19:06 +0200)
lib/pleroma/web/ostatus/ostatus.ex
lib/pleroma/web/web_finger/web_finger.ex
lib/pleroma/web/websub/websub.ex
test/web/ostatus/ostatus_test.exs
test/web/websub/websub_test.exs

index 90be86755d776996f6a01ea83ab78d2b474fdb6f..3e239179e502bd5f5c72f7a82bdb0849cd722ec0 100644 (file)
@@ -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.
index 1d8c4d0c8c2e947167420e1079386dc592927c92..49796dab83b43180c4bcb4b07e506d6b025a2b07 100644 (file)
@@ -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}
index c1d48ad7a43c16aab0fb0856918b16c6af6ff60f..8e3e0a54e23ccecd1b68b2147851b412eb02baae 100644 (file)
@@ -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
index 2a5156b31b649329657899762f76602e1ff80c66..4f396d9409ea4b2b5cfe146ce4c409a816d77b67 100644 (file)
@@ -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
index 1b1ef3fa6082559ff86c3f98bae9e41b7261e9d2..25c2b8baae6068d1e0690621aa18cab4570a7807 100644 (file)
@@ -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"