From 29b7e822fbd5a9001cd31705da5f46672941813c Mon Sep 17 00:00:00 2001 From: Sebastian Huebner Date: Tue, 9 Jan 2018 12:31:11 +0100 Subject: [PATCH 01/16] added question about activating mediaproxy to config generator --- lib/mix/tasks/generate_config.ex | 3 ++- lib/mix/tasks/sample_config.eex | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/mix/tasks/generate_config.ex b/lib/mix/tasks/generate_config.ex index f20f93e4d..0dfbda226 100644 --- a/lib/mix/tasks/generate_config.ex +++ b/lib/mix/tasks/generate_config.ex @@ -8,11 +8,12 @@ def run(_) do domain = IO.gets("What is your domain name? (e.g. pleroma.soykaf.com): ") |> String.trim name = IO.gets("What is the name of your instance? (e.g. Pleroma/Soykaf): ") |> String.trim email = IO.gets("What's your admin email address: ") |> String.trim + mediaproxy = IO.gets("Do you want to activate the mediaproxy? (true/false): ") |> String.trim secret = :crypto.strong_rand_bytes(64) |> Base.encode64 |> binary_part(0, 64) dbpass = :crypto.strong_rand_bytes(64) |> Base.encode64 |> binary_part(0, 64) resultSql = EEx.eval_file("lib/mix/tasks/sample_psql.eex", [dbpass: dbpass]) - result = EEx.eval_file("lib/mix/tasks/sample_config.eex", [domain: domain, email: email, name: name, secret: secret, dbpass: dbpass]) + result = EEx.eval_file("lib/mix/tasks/sample_config.eex", [domain: domain, email: email, name: name, secret: secret, mediaproxy: mediaproxy, dbpass: dbpass]) IO.puts("\nWriting config to config/generated_config.exs.\n\nCheck it and configure your database, then copy it to either config/dev.secret.exs or config/prod.secret.exs") File.write("config/generated_config.exs", result) diff --git a/lib/mix/tasks/sample_config.eex b/lib/mix/tasks/sample_config.eex index 85a7c554e..05f11c95d 100644 --- a/lib/mix/tasks/sample_config.eex +++ b/lib/mix/tasks/sample_config.eex @@ -10,6 +10,11 @@ config :pleroma, :instance, limit: 5000, registrations_open: true +config :pleroma, :media_proxy, + enabled: <%= mediaproxy %>, + redirect_on_failure: true, + #base_url: "https://cache.pleroma.social" + # Configure your database config :pleroma, Pleroma.Repo, adapter: Ecto.Adapters.Postgres, From d56ab43609985801c853b8743f4c33f691f59924 Mon Sep 17 00:00:00 2001 From: eal Date: Fri, 12 Jan 2018 22:38:14 +0200 Subject: [PATCH 02/16] Ask for proxy URL if proxy enabled. Also change the true/false question to y/n --- lib/mix/tasks/generate_config.ex | 12 ++++++++++-- lib/mix/tasks/sample_config.eex | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/mix/tasks/generate_config.ex b/lib/mix/tasks/generate_config.ex index 0dfbda226..2d962124f 100644 --- a/lib/mix/tasks/generate_config.ex +++ b/lib/mix/tasks/generate_config.ex @@ -8,12 +8,20 @@ def run(_) do domain = IO.gets("What is your domain name? (e.g. pleroma.soykaf.com): ") |> String.trim name = IO.gets("What is the name of your instance? (e.g. Pleroma/Soykaf): ") |> String.trim email = IO.gets("What's your admin email address: ") |> String.trim - mediaproxy = IO.gets("Do you want to activate the mediaproxy? (true/false): ") |> String.trim + mediaproxy = IO.gets("Do you want to activate the mediaproxy? (y/N): ") + |> String.trim() + |> String.downcase() + |> String.starts_with?("y") + proxy_url = if mediaproxy do + IO.gets("What is the mediaproxy's URL? (e.g. https://cache.example.com): ") |> String.trim + else + "https://cache.example.com" + end secret = :crypto.strong_rand_bytes(64) |> Base.encode64 |> binary_part(0, 64) dbpass = :crypto.strong_rand_bytes(64) |> Base.encode64 |> binary_part(0, 64) resultSql = EEx.eval_file("lib/mix/tasks/sample_psql.eex", [dbpass: dbpass]) - result = EEx.eval_file("lib/mix/tasks/sample_config.eex", [domain: domain, email: email, name: name, secret: secret, mediaproxy: mediaproxy, dbpass: dbpass]) + result = EEx.eval_file("lib/mix/tasks/sample_config.eex", [domain: domain, email: email, name: name, secret: secret, mediaproxy: mediaproxy, proxy_url: proxy_url, dbpass: dbpass]) IO.puts("\nWriting config to config/generated_config.exs.\n\nCheck it and configure your database, then copy it to either config/dev.secret.exs or config/prod.secret.exs") File.write("config/generated_config.exs", result) diff --git a/lib/mix/tasks/sample_config.eex b/lib/mix/tasks/sample_config.eex index 05f11c95d..9330fae2d 100644 --- a/lib/mix/tasks/sample_config.eex +++ b/lib/mix/tasks/sample_config.eex @@ -13,7 +13,7 @@ config :pleroma, :instance, config :pleroma, :media_proxy, enabled: <%= mediaproxy %>, redirect_on_failure: true, - #base_url: "https://cache.pleroma.social" + base_url: "<%= proxy_url %>" # Configure your database config :pleroma, Pleroma.Repo, From 9717166d105cec6f9c878653aec2d409265e80a6 Mon Sep 17 00:00:00 2001 From: eal Date: Sat, 13 Jan 2018 18:24:16 +0200 Subject: [PATCH 03/16] Add a stats agent for storing data from expensive queries. --- lib/pleroma/application.ex | 1 + lib/pleroma/stats.ex | 38 +++++++++++++++++++ .../mastodon_api/mastodon_api_controller.ex | 12 ++++-- lib/pleroma/web/router.ex | 1 + 4 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 lib/pleroma/stats.ex diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index 2969ca3c4..cdfca8b1a 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -21,6 +21,7 @@ def start(_type, _args) do ]]), worker(Pleroma.Web.Federator, []), worker(Pleroma.Web.ChatChannel.ChatChannelState, []), + worker(Pleroma.Stats, []), ] ++ if Mix.env == :test, do: [], else: [worker(Pleroma.Web.Streamer, [])] diff --git a/lib/pleroma/stats.ex b/lib/pleroma/stats.ex new file mode 100644 index 000000000..45fa27b55 --- /dev/null +++ b/lib/pleroma/stats.ex @@ -0,0 +1,38 @@ +defmodule Pleroma.Stats do + use Agent + import Ecto.Query + alias Pleroma.{User, Repo, Activity} + + def start_link do + agent = Agent.start_link(fn -> %{} end, name: __MODULE__) + schedule_update() + agent + end + + def get do + Agent.get(__MODULE__, fn stats -> stats end) + end + + def schedule_update do + update_stats() + spawn(fn -> + Process.sleep(1000 * 60 * 60 * 1) # 1 hour + schedule_update() + end) + end + + def update_stats do + peers = from(u in Pleroma.User, + select: fragment("?->'host'", u.info), + where: u.local != ^true) + |> Repo.all() |> Enum.uniq() + domain_count = Enum.count(peers) + status_query = from p in Activity, + where: p.local == ^true, + where: fragment("?->'object'->>'type' = ?", p.data, ^"Note") + status_count = Repo.aggregate(status_query, :count, :id) + Agent.update(__MODULE__, fn _ -> + %{peers: peers, domain_count: domain_count, status_count: status_count} + end) + end +end diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index ffa6f42c8..6ca7a6076 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -1,6 +1,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do use Pleroma.Web, :controller - alias Pleroma.{Repo, Activity, User, Notification} + alias Pleroma.{Repo, Activity, User, Notification, Stats} alias Pleroma.Web alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView} alias Pleroma.Web.ActivityPub.ActivityPub @@ -94,6 +94,7 @@ def user(conn, %{"id" => id}) do def masto_instance(conn, _params) do user_count = Repo.aggregate(User.local_user_query, :count, :id) + %{domain_count: domain_count, status_count: status_count} = Stats.get() response = %{ uri: Web.base_url, title: Keyword.get(@instance, :name), @@ -104,9 +105,9 @@ def masto_instance(conn, _params) do streaming_api: String.replace(Web.base_url, ["http","https"], "wss") }, stats: %{ - status_count: 2, + status_count: status_count, user_count: user_count, - domain_count: 3 + domain_count: domain_count }, max_toot_chars: Keyword.get(@instance, :limit) } @@ -114,6 +115,11 @@ def masto_instance(conn, _params) do json(conn, response) end + def peers(conn, _params) do + %{peers: peers} = Stats.get() + json(conn, peers) + end + defp mastodonized_emoji do Pleroma.Formatter.get_custom_emoji() |> Enum.map(fn {shortcode, relative_url} -> diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 8e6681e68..09104fc86 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -106,6 +106,7 @@ def user_fetcher(username) do scope "/api/v1", Pleroma.Web.MastodonAPI do pipe_through :api get "/instance", MastodonAPIController, :masto_instance + get "/instance/peers", MastodonAPIController, :peers post "/apps", MastodonAPIController, :create_app get "/custom_emojis", MastodonAPIController, :custom_emojis From d8db39564eb21d9d9b572baae1886af8d0c047d5 Mon Sep 17 00:00:00 2001 From: eal Date: Sun, 14 Jan 2018 08:15:11 +0200 Subject: [PATCH 04/16] Move user count to stats agent. --- lib/pleroma/stats.ex | 13 +++++++++---- .../web/mastodon_api/mastodon_api_controller.ex | 11 ++--------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/lib/pleroma/stats.ex b/lib/pleroma/stats.ex index 45fa27b55..938e5c343 100644 --- a/lib/pleroma/stats.ex +++ b/lib/pleroma/stats.ex @@ -4,13 +4,17 @@ defmodule Pleroma.Stats do alias Pleroma.{User, Repo, Activity} def start_link do - agent = Agent.start_link(fn -> %{} end, name: __MODULE__) + agent = Agent.start_link(fn -> {[], %{}} end, name: __MODULE__) schedule_update() agent end - def get do - Agent.get(__MODULE__, fn stats -> stats end) + def get_stats do + Agent.get(__MODULE__, fn {_, stats} -> stats end) + end + + def get_peers do + Agent.get(__MODULE__, fn {peers, _} -> peers end) end def schedule_update do @@ -31,8 +35,9 @@ def update_stats do where: p.local == ^true, where: fragment("?->'object'->>'type' = ?", p.data, ^"Note") status_count = Repo.aggregate(status_query, :count, :id) + user_count = Repo.aggregate(User.local_user_query, :count, :id) Agent.update(__MODULE__, fn _ -> - %{peers: peers, domain_count: domain_count, status_count: status_count} + {peers, %{domain_count: domain_count, status_count: status_count, user_count: user_count}} end) end end diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 6ca7a6076..0615ac11a 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -93,8 +93,6 @@ def user(conn, %{"id" => id}) do @instance Application.get_env(:pleroma, :instance) def masto_instance(conn, _params) do - user_count = Repo.aggregate(User.local_user_query, :count, :id) - %{domain_count: domain_count, status_count: status_count} = Stats.get() response = %{ uri: Web.base_url, title: Keyword.get(@instance, :name), @@ -104,11 +102,7 @@ def masto_instance(conn, _params) do urls: %{ streaming_api: String.replace(Web.base_url, ["http","https"], "wss") }, - stats: %{ - status_count: status_count, - user_count: user_count, - domain_count: domain_count - }, + stats: Stats.get_stats, max_toot_chars: Keyword.get(@instance, :limit) } @@ -116,8 +110,7 @@ def masto_instance(conn, _params) do end def peers(conn, _params) do - %{peers: peers} = Stats.get() - json(conn, peers) + json(conn, Stats.get_peers) end defp mastodonized_emoji do From 6e1cb86166d82a4ac4e5fb2ecf8955b18a7ab466 Mon Sep 17 00:00:00 2001 From: eal Date: Sun, 14 Jan 2018 08:28:35 +0200 Subject: [PATCH 05/16] Fix instance test. --- test/web/mastodon_api/mastodon_api_controller_test.exs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs index 79ad671d9..93b29dfae 100644 --- a/test/web/mastodon_api/mastodon_api_controller_test.exs +++ b/test/web/mastodon_api/mastodon_api_controller_test.exs @@ -586,11 +586,14 @@ test "get instance information" do {:ok, _} = TwitterAPI.create_status(user, %{"status" => "cofe"}) + Pleroma.Stats.update_stats() + conn = conn |> get("/api/v1/instance") assert result = json_response(conn, 200) assert result["stats"]["user_count"] == 2 + assert result["stats"]["status_count"] == 1 end end From 048f61d7f86b41018214e76649c3c8588bc05a54 Mon Sep 17 00:00:00 2001 From: Hakaba Hitoyo Date: Sun, 14 Jan 2018 08:54:28 +0000 Subject: [PATCH 06/16] #95 Correct prod.exs --- config/prod.exs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/config/prod.exs b/config/prod.exs index 732bab2b0..8522c67da 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -14,9 +14,12 @@ # manifest is generated by the mix phoenix.digest task # which you typically run after static files are built. config :pleroma, Pleroma.Web.Endpoint, - on_init: {Pleroma.Web.Endpoint, :load_from_system_env, []}, - url: [host: "example.com", port: 80], - cache_static_manifest: "priv/static/cache_manifest.json" + http: [port: 4000], + protocol: "http", + debug_errors: true, + code_reloader: true, + check_origin: false, + watchers: [] # Do not print debug messages in production config :logger, level: :info From aceef36e5675253b32b0be4322b055e98a0154e7 Mon Sep 17 00:00:00 2001 From: Hakaba Hitoyo Date: Sun, 14 Jan 2018 10:57:25 +0000 Subject: [PATCH 07/16] Correct pleroma.nginx --- installation/pleroma.nginx | 2 -- 1 file changed, 2 deletions(-) diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx index 4e88a426d..92ed8f32e 100644 --- a/installation/pleroma.nginx +++ b/installation/pleroma.nginx @@ -34,6 +34,4 @@ server { proxy_pass http://localhost:4000; } - include snippets/well-known.conf; - } From 14b086eec22486d1efc8248f5f157696e7621e5b Mon Sep 17 00:00:00 2001 From: eal Date: Mon, 15 Jan 2018 22:18:17 +0200 Subject: [PATCH 08/16] Add a default profile picture and banner. This removes the placehold.it dependency. --- lib/pleroma/user.ex | 4 +-- .../web/mastodon_api/views/account_view.ex | 6 +---- .../web/twitter_api/views/user_view.ex | 2 +- priv/static/static/avi.png | Bin 0 -> 3604 bytes priv/static/static/banner.png | Bin 0 -> 1293 bytes test/web/mastodon_api/account_view_test.exs | 8 +++--- test/web/ostatus/user_representer_test.exs | 1 + test/web/twitter_api/views/user_view_test.exs | 23 ++++++++++++------ 8 files changed, 24 insertions(+), 20 deletions(-) create mode 100644 priv/static/static/avi.png create mode 100644 priv/static/static/banner.png diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 09bcf0cb4..6ba2b165c 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -29,14 +29,14 @@ defmodule Pleroma.User do def avatar_url(user) do case user.avatar do %{"url" => [%{"href" => href} | _]} -> href - _ -> "https://placehold.it/48x48" + _ -> "#{Web.base_url()}/static/avi.png" end end def banner_url(user) do case user.info["banner"] do %{"url" => [%{"href" => href} | _]} -> href - _ -> nil + _ -> "#{Web.base_url()}/static/banner.png" end end diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 1d5918988..d2a4dd366 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -5,19 +5,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do alias Pleroma.Web.CommonAPI.Utils alias Pleroma.Web.MediaProxy - defp image_url(%{"url" => [ %{ "href" => href } | _ ]}), do: href - defp image_url(_), do: nil - def render("accounts.json", %{users: users} = opts) do render_many(users, AccountView, "account.json", opts) end def render("account.json", %{user: user}) do image = User.avatar_url(user) |> MediaProxy.url() + header = User.banner_url(user) |> MediaProxy.url() user_info = User.user_info(user) - header = (image_url(user.info["banner"]) || "https://placehold.it/700x335") |> MediaProxy.url() - %{ id: to_string(user.id), username: hd(String.split(user.nickname, "@")), diff --git a/lib/pleroma/web/twitter_api/views/user_view.ex b/lib/pleroma/web/twitter_api/views/user_view.ex index cc6b450fb..1b995f42f 100644 --- a/lib/pleroma/web/twitter_api/views/user_view.ex +++ b/lib/pleroma/web/twitter_api/views/user_view.ex @@ -45,7 +45,7 @@ def render("user.json", %{user: user = %User{}} = assigns) do "screen_name" => user.nickname, "statuses_count" => user_info[:note_count], "statusnet_profile_url" => user.ap_id, - "cover_photo" => image_url(user.info["banner"]) |> MediaProxy.url(), + "cover_photo" => User.banner_url(user) |> MediaProxy.url(), "background_image" => image_url(user.info["background"]) |> MediaProxy.url(), } diff --git a/priv/static/static/avi.png b/priv/static/static/avi.png new file mode 100644 index 0000000000000000000000000000000000000000..336fd15ef331c88a057ce05ce49ae237b4e7bfbf GIT binary patch literal 3604 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 F{{dsjz|jBz literal 0 HcmV?d00001 diff --git a/priv/static/static/banner.png b/priv/static/static/banner.png new file mode 100644 index 0000000000000000000000000000000000000000..467c075d64667cdb67bac4c20ee06153bb28a774 GIT binary patch literal 1293 zcmeAS@N?(olHy`uVBq!ia0y~yVA{jL!06Ax1Qby)>#_q+Lm1 zK_HL8@yq!nH)lbX4bl(ereBt2V36p&^rj!H1b4L5hLlG6Ta5HW+olgn?lh zBa#XXg-{h33ZX_JOhi?I%}$UCpw*}fp{_!496|-E;}DiXeSuI2b@!#{user.bio} #{user.nickname} + """ assert clean(res) == clean(expected) diff --git a/test/web/twitter_api/views/user_view_test.exs b/test/web/twitter_api/views/user_view_test.exs index 753e41d20..3f84e4116 100644 --- a/test/web/twitter_api/views/user_view_test.exs +++ b/test/web/twitter_api/views/user_view_test.exs @@ -33,7 +33,8 @@ test "A user" do {:ok, user} = User.update_follower_count(user) Cachex.set(:user_cache, "user_info:#{user.id}", User.user_info(Repo.get!(User, user.id))) - image = "https://placehold.it/48x48" + image = "http://localhost:4001/static/avi.png" + banner = "http://localhost:4001/static/banner.png" represented = %{ "id" => user.id, @@ -54,7 +55,7 @@ test "A user" do "statusnet_blocking" => false, "rights" => %{}, "statusnet_profile_url" => user.ap_id, - "cover_photo" => nil, + "cover_photo" => banner, "background_image" => nil } @@ -64,7 +65,9 @@ test "A user" do test "A user for a given other follower", %{user: user} do {:ok, follower} = UserBuilder.insert(%{following: [User.ap_followers(user)]}) {:ok, user} = User.update_follower_count(user) - image = "https://placehold.it/48x48" + image = "http://localhost:4001/static/avi.png" + banner = "http://localhost:4001/static/banner.png" + represented = %{ "id" => user.id, "name" => user.name, @@ -84,7 +87,7 @@ test "A user for a given other follower", %{user: user} do "statusnet_blocking" => false, "rights" => %{}, "statusnet_profile_url" => user.ap_id, - "cover_photo" => nil, + "cover_photo" => banner, "background_image" => nil } @@ -95,7 +98,9 @@ test "A user that follows you", %{user: user} do follower = insert(:user) {:ok, follower} = User.follow(follower, user) {:ok, user} = User.update_follower_count(user) - image = "https://placehold.it/48x48" + image = "http://localhost:4001/static/avi.png" + banner = "http://localhost:4001/static/banner.png" + represented = %{ "id" => follower.id, "name" => follower.name, @@ -115,7 +120,7 @@ test "A user that follows you", %{user: user} do "statusnet_blocking" => false, "rights" => %{}, "statusnet_profile_url" => follower.ap_id, - "cover_photo" => nil, + "cover_photo" => banner, "background_image" => nil } @@ -126,7 +131,9 @@ test "A blocked user for the blocker", %{user: user} do user = insert(:user) blocker = insert(:user) User.block(blocker, user) - image = "https://placehold.it/48x48" + image = "http://localhost:4001/static/avi.png" + banner = "http://localhost:4001/static/banner.png" + represented = %{ "id" => user.id, "name" => user.name, @@ -146,7 +153,7 @@ test "A blocked user for the blocker", %{user: user} do "statusnet_blocking" => true, "rights" => %{}, "statusnet_profile_url" => user.ap_id, - "cover_photo" => nil, + "cover_photo" => banner, "background_image" => nil } From b3e7d7ae6d4ab4b871ecf18706461945fd148a1b Mon Sep 17 00:00:00 2001 From: eal Date: Tue, 16 Jan 2018 15:31:03 +0200 Subject: [PATCH 09/16] Fetch external profile in the background. --- lib/pleroma/web/twitter_api/twitter_api.ex | 10 ++++++---- test/web/twitter_api/twitter_api_test.exs | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex index d04a81cd4..faecebde0 100644 --- a/lib/pleroma/web/twitter_api/twitter_api.ex +++ b/lib/pleroma/web/twitter_api/twitter_api.ex @@ -316,10 +316,12 @@ def conversation_id_to_context(id) do def get_external_profile(for_user, uri) do with {:ok, %User{} = user} <- OStatus.find_or_make_user(uri) do - with url <- user.info["topic"], - {:ok, %{body: body}} <- @httpoison.get(url, [], follow_redirect: true, timeout: 10000, recv_timeout: 20000) do - OStatus.handle_incoming(body) - end + spawn(fn -> + with url <- user.info["topic"], + {:ok, %{body: body}} <- @httpoison.get(url, [], follow_redirect: true, timeout: 10000, recv_timeout: 20000) do + OStatus.handle_incoming(body) + end + end) {:ok, UserView.render("show.json", %{user: user, for: for_user})} else _e -> {:error, "Couldn't find user"} diff --git a/test/web/twitter_api/twitter_api_test.exs b/test/web/twitter_api/twitter_api_test.exs index 823ba3913..ac62880d5 100644 --- a/test/web/twitter_api/twitter_api_test.exs +++ b/test/web/twitter_api/twitter_api_test.exs @@ -404,7 +404,7 @@ test "fetches a user by uri" do assert represented["id"] == UserView.render("show.json", %{user: remote, for: user})["id"] # Also fetches the feed. - assert Activity.get_create_activity_by_object_ap_id("tag:mastodon.social,2017-04-05:objectId=1641750:objectType=Status") + # assert Activity.get_create_activity_by_object_ap_id("tag:mastodon.social,2017-04-05:objectId=1641750:objectType=Status") end end end From bc689740f09ee8201982455988bf5f4ccb02fe57 Mon Sep 17 00:00:00 2001 From: eal Date: Tue, 16 Jan 2018 02:17:55 +0200 Subject: [PATCH 10/16] Add remote follow path to webfinger. --- lib/pleroma/web/ostatus/ostatus.ex | 4 ++++ lib/pleroma/web/web_finger/web_finger.ex | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/ostatus/ostatus.ex b/lib/pleroma/web/ostatus/ostatus.ex index 745539b3e..e65cab3ed 100644 --- a/lib/pleroma/web/ostatus/ostatus.ex +++ b/lib/pleroma/web/ostatus/ostatus.ex @@ -22,6 +22,10 @@ def salmon_path(user) do "#{user.ap_id}/salmon" end + def remote_follow_path do + "#{Web.base_url}/ostatus_subscribe?acct={uri}" + end + def handle_incoming(xml_string) do with doc when doc != :error <- parse_document(xml_string) do entries = :xmerl_xpath.string('//entry', doc) diff --git a/lib/pleroma/web/web_finger/web_finger.ex b/lib/pleroma/web/web_finger/web_finger.ex index 026d2f98b..4ae3eab59 100644 --- a/lib/pleroma/web/web_finger/web_finger.ex +++ b/lib/pleroma/web/web_finger/web_finger.ex @@ -44,7 +44,8 @@ def represent_user(user) do {:Link, %{rel: "http://schemas.google.com/g/2010#updates-from", type: "application/atom+xml", href: OStatus.feed_path(user)}}, {:Link, %{rel: "http://webfinger.net/rel/profile-page", type: "text/html", href: user.ap_id}}, {:Link, %{rel: "salmon", href: OStatus.salmon_path(user)}}, - {:Link, %{rel: "magic-public-key", href: "data:application/magic-public-key,#{magic_key}"}} + {:Link, %{rel: "magic-public-key", href: "data:application/magic-public-key,#{magic_key}"}}, + {:Link, %{rel: "http://ostatus.org/schema/1.0/subscribe", template: OStatus.remote_follow_path()}} ] } |> XmlBuilder.to_doc From 47e8c8db05dbe1f9d0ad7790be9ae9ed40f4e909 Mon Sep 17 00:00:00 2001 From: eal Date: Thu, 18 Jan 2018 00:22:08 +0200 Subject: [PATCH 11/16] Add remote follow pages. --- lib/pleroma/web/router.ex | 13 +++++ .../twitter_api/util/follow.html.eex | 11 +++++ .../twitter_api/util/follow_login.html.eex | 14 ++++++ .../twitter_api/util/followed.html.eex | 6 +++ .../controllers/util_controller.ex | 48 +++++++++++++++++++ 5 files changed, 92 insertions(+) create mode 100644 lib/pleroma/web/templates/twitter_api/util/follow.html.eex create mode 100644 lib/pleroma/web/templates/twitter_api/util/follow_login.html.eex create mode 100644 lib/pleroma/web/templates/twitter_api/util/followed.html.eex diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 09104fc86..63dbd6245 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -28,6 +28,13 @@ def user_fetcher(username) do plug Pleroma.Plugs.AuthenticationPlug, %{fetcher: &Router.user_fetcher/1, optional: true} end + pipeline :pleroma_html do + plug :accepts, ["html"] + plug :fetch_session + plug Pleroma.Plugs.OAuthPlug + plug Pleroma.Plugs.AuthenticationPlug, %{fetcher: &Router.user_fetcher/1, optional: true} + end + pipeline :well_known do plug :accepts, ["xml", "xrd+xml"] end @@ -51,6 +58,12 @@ def user_fetcher(username) do get "/emoji", UtilController, :emoji end + scope "/", Pleroma.Web.TwitterAPI do + pipe_through :pleroma_html + get "/ostatus_subscribe", UtilController, :remote_follow + post "/ostatus_subscribe", UtilController, :do_remote_follow + end + scope "/api/pleroma", Pleroma.Web.TwitterAPI do pipe_through :authenticated_api post "/follow_import", UtilController, :follow_import diff --git a/lib/pleroma/web/templates/twitter_api/util/follow.html.eex b/lib/pleroma/web/templates/twitter_api/util/follow.html.eex new file mode 100644 index 000000000..06359fa6c --- /dev/null +++ b/lib/pleroma/web/templates/twitter_api/util/follow.html.eex @@ -0,0 +1,11 @@ +<%= if @error == :error do %> +

Error fetching user

+<% else %> +

Remote follow

+ +

<%= @name %>

+ <%= form_for @conn, util_path(@conn, :do_remote_follow), [as: "user"], fn f -> %> + <%= hidden_input f, :id, value: @id %> + <%= submit "Authorize" %> + <% end %> +<% end %> diff --git a/lib/pleroma/web/templates/twitter_api/util/follow_login.html.eex b/lib/pleroma/web/templates/twitter_api/util/follow_login.html.eex new file mode 100644 index 000000000..4e3a2be67 --- /dev/null +++ b/lib/pleroma/web/templates/twitter_api/util/follow_login.html.eex @@ -0,0 +1,14 @@ +<%= if @error do %> +

<%= @error %>

+<% end %> +

Log in to follow

+

<%= @name %>

+ +<%= form_for @conn, util_path(@conn, :do_remote_follow), [as: "authorization"], fn f -> %> +<%= text_input f, :name, placeholder: "Username" %> +
+<%= password_input f, :password, placeholder: "Password" %> +
+<%= hidden_input f, :id, value: @id %> +<%= submit "Authorize" %> +<% end %> diff --git a/lib/pleroma/web/templates/twitter_api/util/followed.html.eex b/lib/pleroma/web/templates/twitter_api/util/followed.html.eex new file mode 100644 index 000000000..da473d502 --- /dev/null +++ b/lib/pleroma/web/templates/twitter_api/util/followed.html.eex @@ -0,0 +1,6 @@ +<%= if @error do %> +

Error following account

+<% else %> +

Account followed!

+<% end %> + diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex index 9d5654995..a1d56e3ab 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -2,6 +2,8 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do use Pleroma.Web, :controller require Logger alias Pleroma.Web + alias Pleroma.Web.OStatus + alias Comeonin.Pbkdf2 alias Pleroma.Formatter alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.{Repo, PasswordResetToken, User} @@ -30,6 +32,52 @@ def help_test(conn, _params) do json(conn, "ok") end + def remote_follow(%{assigns: %{user: user}} = conn, %{"acct" => acct}) do + {err, followee} = OStatus.find_or_make_user(acct) + avatar = User.avatar_url(followee) + name = followee.nickname + id = followee.id + + if !!user do + conn + |> render("follow.html", %{error: err, acct: acct, avatar: avatar, name: name, id: id}) + else + conn + |> render("follow_login.html", %{error: false, acct: acct, avatar: avatar, name: name, id: id}) + end + end + + def do_remote_follow(conn, %{"authorization" => %{"name" => username, "password" => password, "id" => id}}) do + followee = Repo.get(User, id) + avatar = User.avatar_url(followee) + name = followee.nickname + with %User{} = user <- User.get_cached_by_nickname(username), + true <- Pbkdf2.checkpw(password, user.password_hash), + %User{} = followed <- Repo.get(User, id), + {:ok, follower} <- User.follow(user, followee), + {:ok, _activity} <- ActivityPub.follow(follower, followee) do + conn + |> render("followed.html", %{error: false}) + else + _e -> + conn + |> render("follow_login.html", %{error: "Wrong username or password", id: id, name: name, avatar: avatar}) + end + end + def do_remote_follow(%{assigns: %{user: user}} = conn, %{"user" => %{"id" => id}}) do + with %User{} = followee <- Repo.get(User, id), + {:ok, follower} <- User.follow(user, followee), + {:ok, _activity} <- ActivityPub.follow(follower, followee) do + conn + |> render("followed.html", %{error: false}) + else + e -> + Logger.debug("Remote follow failed with error #{inspect e}") + conn + |> render("followed.html", %{error: inspect(e)}) + end + end + @instance Application.get_env(:pleroma, :instance) def config(conn, _params) do case get_format(conn) do From fb5aa34092cf8aa04b3b7001e81cf1585ee0041a Mon Sep 17 00:00:00 2001 From: eal Date: Thu, 18 Jan 2018 03:42:09 +0200 Subject: [PATCH 12/16] Revert "Add remote follow path to webfinger." This reverts commit bc689740f09ee8201982455988bf5f4ccb02fe57. --- lib/pleroma/web/ostatus/ostatus.ex | 4 ---- lib/pleroma/web/web_finger/web_finger.ex | 3 +-- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/pleroma/web/ostatus/ostatus.ex b/lib/pleroma/web/ostatus/ostatus.ex index e65cab3ed..745539b3e 100644 --- a/lib/pleroma/web/ostatus/ostatus.ex +++ b/lib/pleroma/web/ostatus/ostatus.ex @@ -22,10 +22,6 @@ def salmon_path(user) do "#{user.ap_id}/salmon" end - def remote_follow_path do - "#{Web.base_url}/ostatus_subscribe?acct={uri}" - end - def handle_incoming(xml_string) do with doc when doc != :error <- parse_document(xml_string) do entries = :xmerl_xpath.string('//entry', doc) diff --git a/lib/pleroma/web/web_finger/web_finger.ex b/lib/pleroma/web/web_finger/web_finger.ex index 4ae3eab59..026d2f98b 100644 --- a/lib/pleroma/web/web_finger/web_finger.ex +++ b/lib/pleroma/web/web_finger/web_finger.ex @@ -44,8 +44,7 @@ def represent_user(user) do {:Link, %{rel: "http://schemas.google.com/g/2010#updates-from", type: "application/atom+xml", href: OStatus.feed_path(user)}}, {:Link, %{rel: "http://webfinger.net/rel/profile-page", type: "text/html", href: user.ap_id}}, {:Link, %{rel: "salmon", href: OStatus.salmon_path(user)}}, - {:Link, %{rel: "magic-public-key", href: "data:application/magic-public-key,#{magic_key}"}}, - {:Link, %{rel: "http://ostatus.org/schema/1.0/subscribe", template: OStatus.remote_follow_path()}} + {:Link, %{rel: "magic-public-key", href: "data:application/magic-public-key,#{magic_key}"}} ] } |> XmlBuilder.to_doc From b259b4e4d1dc27528b99744fffabfb05c676ec3f Mon Sep 17 00:00:00 2001 From: eal Date: Thu, 18 Jan 2018 03:42:18 +0200 Subject: [PATCH 13/16] Revert "Add remote follow pages." This reverts commit 47e8c8db05dbe1f9d0ad7790be9ae9ed40f4e909. --- lib/pleroma/web/router.ex | 13 ----- .../twitter_api/util/follow.html.eex | 11 ----- .../twitter_api/util/follow_login.html.eex | 14 ------ .../twitter_api/util/followed.html.eex | 6 --- .../controllers/util_controller.ex | 48 ------------------- 5 files changed, 92 deletions(-) delete mode 100644 lib/pleroma/web/templates/twitter_api/util/follow.html.eex delete mode 100644 lib/pleroma/web/templates/twitter_api/util/follow_login.html.eex delete mode 100644 lib/pleroma/web/templates/twitter_api/util/followed.html.eex diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 63dbd6245..09104fc86 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -28,13 +28,6 @@ def user_fetcher(username) do plug Pleroma.Plugs.AuthenticationPlug, %{fetcher: &Router.user_fetcher/1, optional: true} end - pipeline :pleroma_html do - plug :accepts, ["html"] - plug :fetch_session - plug Pleroma.Plugs.OAuthPlug - plug Pleroma.Plugs.AuthenticationPlug, %{fetcher: &Router.user_fetcher/1, optional: true} - end - pipeline :well_known do plug :accepts, ["xml", "xrd+xml"] end @@ -58,12 +51,6 @@ def user_fetcher(username) do get "/emoji", UtilController, :emoji end - scope "/", Pleroma.Web.TwitterAPI do - pipe_through :pleroma_html - get "/ostatus_subscribe", UtilController, :remote_follow - post "/ostatus_subscribe", UtilController, :do_remote_follow - end - scope "/api/pleroma", Pleroma.Web.TwitterAPI do pipe_through :authenticated_api post "/follow_import", UtilController, :follow_import diff --git a/lib/pleroma/web/templates/twitter_api/util/follow.html.eex b/lib/pleroma/web/templates/twitter_api/util/follow.html.eex deleted file mode 100644 index 06359fa6c..000000000 --- a/lib/pleroma/web/templates/twitter_api/util/follow.html.eex +++ /dev/null @@ -1,11 +0,0 @@ -<%= if @error == :error do %> -

Error fetching user

-<% else %> -

Remote follow

- -

<%= @name %>

- <%= form_for @conn, util_path(@conn, :do_remote_follow), [as: "user"], fn f -> %> - <%= hidden_input f, :id, value: @id %> - <%= submit "Authorize" %> - <% end %> -<% end %> diff --git a/lib/pleroma/web/templates/twitter_api/util/follow_login.html.eex b/lib/pleroma/web/templates/twitter_api/util/follow_login.html.eex deleted file mode 100644 index 4e3a2be67..000000000 --- a/lib/pleroma/web/templates/twitter_api/util/follow_login.html.eex +++ /dev/null @@ -1,14 +0,0 @@ -<%= if @error do %> -

<%= @error %>

-<% end %> -

Log in to follow

-

<%= @name %>

- -<%= form_for @conn, util_path(@conn, :do_remote_follow), [as: "authorization"], fn f -> %> -<%= text_input f, :name, placeholder: "Username" %> -
-<%= password_input f, :password, placeholder: "Password" %> -
-<%= hidden_input f, :id, value: @id %> -<%= submit "Authorize" %> -<% end %> diff --git a/lib/pleroma/web/templates/twitter_api/util/followed.html.eex b/lib/pleroma/web/templates/twitter_api/util/followed.html.eex deleted file mode 100644 index da473d502..000000000 --- a/lib/pleroma/web/templates/twitter_api/util/followed.html.eex +++ /dev/null @@ -1,6 +0,0 @@ -<%= if @error do %> -

Error following account

-<% else %> -

Account followed!

-<% end %> - diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex index a1d56e3ab..9d5654995 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -2,8 +2,6 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do use Pleroma.Web, :controller require Logger alias Pleroma.Web - alias Pleroma.Web.OStatus - alias Comeonin.Pbkdf2 alias Pleroma.Formatter alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.{Repo, PasswordResetToken, User} @@ -32,52 +30,6 @@ def help_test(conn, _params) do json(conn, "ok") end - def remote_follow(%{assigns: %{user: user}} = conn, %{"acct" => acct}) do - {err, followee} = OStatus.find_or_make_user(acct) - avatar = User.avatar_url(followee) - name = followee.nickname - id = followee.id - - if !!user do - conn - |> render("follow.html", %{error: err, acct: acct, avatar: avatar, name: name, id: id}) - else - conn - |> render("follow_login.html", %{error: false, acct: acct, avatar: avatar, name: name, id: id}) - end - end - - def do_remote_follow(conn, %{"authorization" => %{"name" => username, "password" => password, "id" => id}}) do - followee = Repo.get(User, id) - avatar = User.avatar_url(followee) - name = followee.nickname - with %User{} = user <- User.get_cached_by_nickname(username), - true <- Pbkdf2.checkpw(password, user.password_hash), - %User{} = followed <- Repo.get(User, id), - {:ok, follower} <- User.follow(user, followee), - {:ok, _activity} <- ActivityPub.follow(follower, followee) do - conn - |> render("followed.html", %{error: false}) - else - _e -> - conn - |> render("follow_login.html", %{error: "Wrong username or password", id: id, name: name, avatar: avatar}) - end - end - def do_remote_follow(%{assigns: %{user: user}} = conn, %{"user" => %{"id" => id}}) do - with %User{} = followee <- Repo.get(User, id), - {:ok, follower} <- User.follow(user, followee), - {:ok, _activity} <- ActivityPub.follow(follower, followee) do - conn - |> render("followed.html", %{error: false}) - else - e -> - Logger.debug("Remote follow failed with error #{inspect e}") - conn - |> render("followed.html", %{error: inspect(e)}) - end - end - @instance Application.get_env(:pleroma, :instance) def config(conn, _params) do case get_format(conn) do From 57d413e65541f47a3c303be88c0ac6d4bfed33a9 Mon Sep 17 00:00:00 2001 From: eal Date: Thu, 18 Jan 2018 18:42:32 +0200 Subject: [PATCH 14/16] Revert "Revert "Add remote follow path to webfinger."" This reverts commit fb5aa34092cf8aa04b3b7001e81cf1585ee0041a. --- lib/pleroma/web/ostatus/ostatus.ex | 4 ++++ lib/pleroma/web/web_finger/web_finger.ex | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/ostatus/ostatus.ex b/lib/pleroma/web/ostatus/ostatus.ex index 745539b3e..e65cab3ed 100644 --- a/lib/pleroma/web/ostatus/ostatus.ex +++ b/lib/pleroma/web/ostatus/ostatus.ex @@ -22,6 +22,10 @@ def salmon_path(user) do "#{user.ap_id}/salmon" end + def remote_follow_path do + "#{Web.base_url}/ostatus_subscribe?acct={uri}" + end + def handle_incoming(xml_string) do with doc when doc != :error <- parse_document(xml_string) do entries = :xmerl_xpath.string('//entry', doc) diff --git a/lib/pleroma/web/web_finger/web_finger.ex b/lib/pleroma/web/web_finger/web_finger.ex index 026d2f98b..4ae3eab59 100644 --- a/lib/pleroma/web/web_finger/web_finger.ex +++ b/lib/pleroma/web/web_finger/web_finger.ex @@ -44,7 +44,8 @@ def represent_user(user) do {:Link, %{rel: "http://schemas.google.com/g/2010#updates-from", type: "application/atom+xml", href: OStatus.feed_path(user)}}, {:Link, %{rel: "http://webfinger.net/rel/profile-page", type: "text/html", href: user.ap_id}}, {:Link, %{rel: "salmon", href: OStatus.salmon_path(user)}}, - {:Link, %{rel: "magic-public-key", href: "data:application/magic-public-key,#{magic_key}"}} + {:Link, %{rel: "magic-public-key", href: "data:application/magic-public-key,#{magic_key}"}}, + {:Link, %{rel: "http://ostatus.org/schema/1.0/subscribe", template: OStatus.remote_follow_path()}} ] } |> XmlBuilder.to_doc From beb13bf3a9b207119d70bb817ff1ea92f17a11be Mon Sep 17 00:00:00 2001 From: eal Date: Thu, 18 Jan 2018 18:42:44 +0200 Subject: [PATCH 15/16] Revert "Revert "Add remote follow pages."" This reverts commit b259b4e4d1dc27528b99744fffabfb05c676ec3f. --- lib/pleroma/web/router.ex | 13 +++++ .../twitter_api/util/follow.html.eex | 11 +++++ .../twitter_api/util/follow_login.html.eex | 14 ++++++ .../twitter_api/util/followed.html.eex | 6 +++ .../controllers/util_controller.ex | 48 +++++++++++++++++++ 5 files changed, 92 insertions(+) create mode 100644 lib/pleroma/web/templates/twitter_api/util/follow.html.eex create mode 100644 lib/pleroma/web/templates/twitter_api/util/follow_login.html.eex create mode 100644 lib/pleroma/web/templates/twitter_api/util/followed.html.eex diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 09104fc86..63dbd6245 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -28,6 +28,13 @@ def user_fetcher(username) do plug Pleroma.Plugs.AuthenticationPlug, %{fetcher: &Router.user_fetcher/1, optional: true} end + pipeline :pleroma_html do + plug :accepts, ["html"] + plug :fetch_session + plug Pleroma.Plugs.OAuthPlug + plug Pleroma.Plugs.AuthenticationPlug, %{fetcher: &Router.user_fetcher/1, optional: true} + end + pipeline :well_known do plug :accepts, ["xml", "xrd+xml"] end @@ -51,6 +58,12 @@ def user_fetcher(username) do get "/emoji", UtilController, :emoji end + scope "/", Pleroma.Web.TwitterAPI do + pipe_through :pleroma_html + get "/ostatus_subscribe", UtilController, :remote_follow + post "/ostatus_subscribe", UtilController, :do_remote_follow + end + scope "/api/pleroma", Pleroma.Web.TwitterAPI do pipe_through :authenticated_api post "/follow_import", UtilController, :follow_import diff --git a/lib/pleroma/web/templates/twitter_api/util/follow.html.eex b/lib/pleroma/web/templates/twitter_api/util/follow.html.eex new file mode 100644 index 000000000..06359fa6c --- /dev/null +++ b/lib/pleroma/web/templates/twitter_api/util/follow.html.eex @@ -0,0 +1,11 @@ +<%= if @error == :error do %> +

Error fetching user

+<% else %> +

Remote follow

+ +

<%= @name %>

+ <%= form_for @conn, util_path(@conn, :do_remote_follow), [as: "user"], fn f -> %> + <%= hidden_input f, :id, value: @id %> + <%= submit "Authorize" %> + <% end %> +<% end %> diff --git a/lib/pleroma/web/templates/twitter_api/util/follow_login.html.eex b/lib/pleroma/web/templates/twitter_api/util/follow_login.html.eex new file mode 100644 index 000000000..4e3a2be67 --- /dev/null +++ b/lib/pleroma/web/templates/twitter_api/util/follow_login.html.eex @@ -0,0 +1,14 @@ +<%= if @error do %> +

<%= @error %>

+<% end %> +

Log in to follow

+

<%= @name %>

+ +<%= form_for @conn, util_path(@conn, :do_remote_follow), [as: "authorization"], fn f -> %> +<%= text_input f, :name, placeholder: "Username" %> +
+<%= password_input f, :password, placeholder: "Password" %> +
+<%= hidden_input f, :id, value: @id %> +<%= submit "Authorize" %> +<% end %> diff --git a/lib/pleroma/web/templates/twitter_api/util/followed.html.eex b/lib/pleroma/web/templates/twitter_api/util/followed.html.eex new file mode 100644 index 000000000..da473d502 --- /dev/null +++ b/lib/pleroma/web/templates/twitter_api/util/followed.html.eex @@ -0,0 +1,6 @@ +<%= if @error do %> +

Error following account

+<% else %> +

Account followed!

+<% end %> + diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex index 9d5654995..a1d56e3ab 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -2,6 +2,8 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do use Pleroma.Web, :controller require Logger alias Pleroma.Web + alias Pleroma.Web.OStatus + alias Comeonin.Pbkdf2 alias Pleroma.Formatter alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.{Repo, PasswordResetToken, User} @@ -30,6 +32,52 @@ def help_test(conn, _params) do json(conn, "ok") end + def remote_follow(%{assigns: %{user: user}} = conn, %{"acct" => acct}) do + {err, followee} = OStatus.find_or_make_user(acct) + avatar = User.avatar_url(followee) + name = followee.nickname + id = followee.id + + if !!user do + conn + |> render("follow.html", %{error: err, acct: acct, avatar: avatar, name: name, id: id}) + else + conn + |> render("follow_login.html", %{error: false, acct: acct, avatar: avatar, name: name, id: id}) + end + end + + def do_remote_follow(conn, %{"authorization" => %{"name" => username, "password" => password, "id" => id}}) do + followee = Repo.get(User, id) + avatar = User.avatar_url(followee) + name = followee.nickname + with %User{} = user <- User.get_cached_by_nickname(username), + true <- Pbkdf2.checkpw(password, user.password_hash), + %User{} = followed <- Repo.get(User, id), + {:ok, follower} <- User.follow(user, followee), + {:ok, _activity} <- ActivityPub.follow(follower, followee) do + conn + |> render("followed.html", %{error: false}) + else + _e -> + conn + |> render("follow_login.html", %{error: "Wrong username or password", id: id, name: name, avatar: avatar}) + end + end + def do_remote_follow(%{assigns: %{user: user}} = conn, %{"user" => %{"id" => id}}) do + with %User{} = followee <- Repo.get(User, id), + {:ok, follower} <- User.follow(user, followee), + {:ok, _activity} <- ActivityPub.follow(follower, followee) do + conn + |> render("followed.html", %{error: false}) + else + e -> + Logger.debug("Remote follow failed with error #{inspect e}") + conn + |> render("followed.html", %{error: inspect(e)}) + end + end + @instance Application.get_env(:pleroma, :instance) def config(conn, _params) do case get_format(conn) do From 0f722a8c223c1953c9c9fb45e73cc9ace92839e2 Mon Sep 17 00:00:00 2001 From: Roger Braun Date: Sat, 20 Jan 2018 18:38:30 +0100 Subject: [PATCH 16/16] Stats: Make less crashy and improve query. --- lib/pleroma/stats.ex | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/pleroma/stats.ex b/lib/pleroma/stats.ex index 938e5c343..0484f1a2d 100644 --- a/lib/pleroma/stats.ex +++ b/lib/pleroma/stats.ex @@ -5,7 +5,7 @@ defmodule Pleroma.Stats do def start_link do agent = Agent.start_link(fn -> {[], %{}} end, name: __MODULE__) - schedule_update() + spawn(fn -> schedule_update() end) agent end @@ -18,23 +18,22 @@ def get_peers do end def schedule_update do - update_stats() spawn(fn -> Process.sleep(1000 * 60 * 60 * 1) # 1 hour schedule_update() end) + update_stats() end def update_stats do peers = from(u in Pleroma.User, - select: fragment("?->'host'", u.info), + select: fragment("distinct ?->'host'", u.info), where: u.local != ^true) - |> Repo.all() |> Enum.uniq() + |> Repo.all() domain_count = Enum.count(peers) - status_query = from p in Activity, - where: p.local == ^true, - where: fragment("?->'object'->>'type' = ?", p.data, ^"Note") - status_count = Repo.aggregate(status_query, :count, :id) + status_query = from(u in User.local_user_query, + select: fragment("sum((?->>'note_count')::int)", u.info)) + status_count = Repo.one(status_query) |> IO.inspect user_count = Repo.aggregate(User.local_user_query, :count, :id) Agent.update(__MODULE__, fn _ -> {peers, %{domain_count: domain_count, status_count: status_count, user_count: user_count}}