diff options
-rw-r--r-- | config/config.exs | 42 | ||||
-rw-r--r-- | lib/pleroma/user.ex | 24 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 25 | ||||
-rw-r--r-- | lib/pleroma/web/rich_media/parser.ex | 2 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/representers/activity_representer.ex | 5 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/views/activity_view.ex | 5 | ||||
-rw-r--r-- | priv/repo/migrations/20190109152453_add_visibility_function.exs | 48 | ||||
-rw-r--r-- | test/user_test.exs | 11 | ||||
-rw-r--r-- | test/web/activity_pub/activity_pub_test.exs | 36 | ||||
-rw-r--r-- | test/web/twitter_api/representers/activity_representer_test.exs | 10 | ||||
-rw-r--r-- | test/web/twitter_api/views/activity_view_test.exs | 7 |
11 files changed, 168 insertions, 47 deletions
diff --git a/config/config.exs b/config/config.exs index 9301758f0..1c55807b7 100644 --- a/config/config.exs +++ b/config/config.exs @@ -238,34 +238,34 @@ config :cors_plug, config :pleroma, Pleroma.User, restricted_nicknames: [ - "about", + ".well-known", "~", - "main", - "users", - "settings", - "objects", + "about", "activities", - "web", - "registration", - "friend-requests", - "pleroma", "api", - "tag", + "auth", + "dev", + "friend-requests", + "inbox", + "internal", + "main", + "media", + "nodeinfo", "notice", - "status", - "user-search", - "ostatus_subscribe", "oauth", + "objects", + "ostatus_subscribe", + "pleroma", + "proxy", "push", + "registration", "relay", - "inbox", - ".well-known", - "nodeinfo", - "auth", - "proxy", - "dev", - "internal", - "media" + "settings", + "status", + "tag", + "user-search", + "users", + "web" ] config :pleroma, Pleroma.Web.Federator, max_jobs: 50 diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 7c2849ce2..a49fa3fcd 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -247,10 +247,7 @@ defmodule Pleroma.User do ) |> Repo.all() - autofollowed_users - |> Enum.reduce({:ok, user}, fn other_user, {:ok, user} -> - follow(user, other_user) - end) + follow_all(user, autofollowed_users) end @doc "Inserts provided changeset, performs post-registration actions (confirmation email sending etc.)" @@ -307,6 +304,25 @@ defmodule Pleroma.User do end end + @doc "A mass follow for local users. Ignores blocks and has no side effects" + @spec follow_all(User.t(), list(User.t())) :: {atom(), User.t()} + def follow_all(follower, followeds) do + following = + (follower.following ++ Enum.map(followeds, fn %{follower_address: fa} -> fa end)) + |> Enum.uniq() + + {:ok, follower} = + follower + |> follow_changeset(%{following: following}) + |> update_and_set_cache + + Enum.each(followeds, fn followed -> + update_follower_count(followed) + end) + + {:ok, follower} + end + def follow(%User{} = follower, %User{info: info} = followed) do user_config = Application.get_env(:pleroma, :user) deny_follow_blocked = Keyword.get(user_config, :deny_follow_blocked) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index c5f62c4f8..9c1eb377f 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -364,21 +364,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do @valid_visibilities ~w[direct unlisted public private] - defp restrict_visibility(query, %{visibility: "direct"}) do - public = "https://www.w3.org/ns/activitystreams#Public" + defp restrict_visibility(query, %{visibility: visibility}) + when visibility in @valid_visibilities do + query = + from( + a in query, + where: + fragment("activity_visibility(?, ?, ?) = ?", a.actor, a.recipients, a.data, ^visibility) + ) - from( - activity in query, - join: sender in User, - on: sender.ap_id == activity.actor, - # Are non-direct statuses with no to/cc possible? - where: - fragment( - "not (? && ?)", - [^public, sender.follower_address], - activity.recipients - ) - ) + Ecto.Adapters.SQL.to_sql(:all, Repo, query) + + query end defp restrict_visibility(_query, %{visibility: visibility}) diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex index 3746feaf6..18d9e2df5 100644 --- a/lib/pleroma/web/rich_media/parser.ex +++ b/lib/pleroma/web/rich_media/parser.ex @@ -5,7 +5,7 @@ defmodule Pleroma.Web.RichMedia.Parser do def parse(url), do: parse_url(url) else def parse(url), - do: {:commit, Cachex.fetch!(:rich_media_cache, url, fn _ -> parse_url(url) end)} + do: Cachex.fetch!(:rich_media_cache, url, fn _ -> parse_url(url) end) end defp parse_url(url) do diff --git a/lib/pleroma/web/twitter_api/representers/activity_representer.ex b/lib/pleroma/web/twitter_api/representers/activity_representer.ex index 64f7c00c7..4f8f228ab 100644 --- a/lib/pleroma/web/twitter_api/representers/activity_representer.ex +++ b/lib/pleroma/web/twitter_api/representers/activity_representer.ex @@ -182,6 +182,8 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do reply_user = reply_parent && User.get_cached_by_ap_id(reply_parent.actor) + summary = HTML.strip_tags(object["summary"]) + %{ "id" => activity.id, "uri" => activity.data["object"]["id"], @@ -209,7 +211,8 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do "activity_type" => "post", "possibly_sensitive" => possibly_sensitive, "visibility" => Pleroma.Web.MastodonAPI.StatusView.get_visibility(object), - "summary" => HTML.strip_tags(object["summary"]) |> Formatter.emojify(object["emoji"]) + "summary" => summary, + "summary_html" => summary |> Formatter.emojify(object["emoji"]) } end diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex index 425df8672..108e7bfc5 100644 --- a/lib/pleroma/web/twitter_api/views/activity_view.ex +++ b/lib/pleroma/web/twitter_api/views/activity_view.ex @@ -280,6 +280,8 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do reply_user = reply_parent && User.get_cached_by_ap_id(reply_parent.actor) + summary = HTML.strip_tags(summary) + %{ "id" => activity.id, "uri" => activity.data["object"]["id"], @@ -307,7 +309,8 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do "activity_type" => "post", "possibly_sensitive" => possibly_sensitive, "visibility" => Pleroma.Web.MastodonAPI.StatusView.get_visibility(object), - "summary" => HTML.strip_tags(summary) |> Formatter.emojify(object["emoji"]) + "summary" => summary, + "summary_html" => summary |> Formatter.emojify(object["emoji"]) } end diff --git a/priv/repo/migrations/20190109152453_add_visibility_function.exs b/priv/repo/migrations/20190109152453_add_visibility_function.exs new file mode 100644 index 000000000..3aadabcd7 --- /dev/null +++ b/priv/repo/migrations/20190109152453_add_visibility_function.exs @@ -0,0 +1,48 @@ +defmodule Pleroma.Repo.Migrations.AddVisibilityFunction do + use Ecto.Migration + @disable_ddl_transaction true + + def up do + definition = """ + create or replace function activity_visibility(actor varchar, recipients varchar[], data jsonb) returns varchar as $$ + DECLARE + fa varchar; + public varchar := 'https://www.w3.org/ns/activitystreams#Public'; + BEGIN + SELECT COALESCE(users.follower_address, '') into fa from users where users.ap_id = actor; + + IF data->'to' ? public THEN + RETURN 'public'; + ELSIF data->'cc' ? public THEN + RETURN 'unlisted'; + ELSIF ARRAY[fa] && recipients THEN + RETURN 'private'; + ELSIF not(ARRAY[fa, public] && recipients) THEN + RETURN 'direct'; + ELSE + RETURN 'unknown'; + END IF; + END; + $$ LANGUAGE plpgsql IMMUTABLE; + """ + + execute(definition) + + create( + index(:activities, ["activity_visibility(actor, recipients, data)"], + name: :activities_visibility_index, + concurrently: true + ) + ) + end + + def down do + drop( + index(:activities, ["activity_visibility(actor, recipients, data)"], + name: :activities_visibility_index + ) + ) + + execute("drop function activity_visibility(actor varchar, recipients varchar[], data jsonb)") + end +end diff --git a/test/user_test.exs b/test/user_test.exs index 541252539..cfccce8d1 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -48,6 +48,17 @@ defmodule Pleroma.UserTest do assert expected_followers_collection == User.ap_followers(user) end + test "follow_all follows mutliple users" do + user = insert(:user) + followed_one = insert(:user) + followed_two = insert(:user) + + {:ok, user} = User.follow_all(user, [followed_one, followed_two]) + + assert User.following?(user, followed_one) + assert User.following?(user, followed_two) + end + test "follow takes a user and another user" do user = insert(:user) followed = insert(:user) diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index e6c998876..eafb96f3a 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -18,6 +18,42 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do :ok end + describe "fetching restricted by visibility" do + test "it restricts by the appropriate visibility" do + user = insert(:user) + + {:ok, public_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"}) + + {:ok, direct_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"}) + + {:ok, unlisted_activity} = + CommonAPI.post(user, %{"status" => ".", "visibility" => "unlisted"}) + + {:ok, private_activity} = + CommonAPI.post(user, %{"status" => ".", "visibility" => "private"}) + + activities = + ActivityPub.fetch_activities([], %{:visibility => "direct", "actor_id" => user.ap_id}) + + assert activities == [direct_activity] + + activities = + ActivityPub.fetch_activities([], %{:visibility => "unlisted", "actor_id" => user.ap_id}) + + assert activities == [unlisted_activity] + + activities = + ActivityPub.fetch_activities([], %{:visibility => "private", "actor_id" => user.ap_id}) + + assert activities == [private_activity] + + activities = + ActivityPub.fetch_activities([], %{:visibility => "public", "actor_id" => user.ap_id}) + + assert activities == [public_activity] + end + end + describe "building a user from his ap id" do test "it returns a user" do user_id = "http://mastodon.example.org/users/admin" diff --git a/test/web/twitter_api/representers/activity_representer_test.exs b/test/web/twitter_api/representers/activity_representer_test.exs index a4f97e0f2..ef0294140 100644 --- a/test/web/twitter_api/representers/activity_representer_test.exs +++ b/test/web/twitter_api/representers/activity_representer_test.exs @@ -107,7 +107,7 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenterTest do "published" => date, "type" => "Note", "content" => content_html, - "summary" => "2hu", + "summary" => "2hu :2hu:", "inReplyToStatusId" => 213_123, "attachment" => [ object @@ -129,7 +129,7 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenterTest do } expected_html = - "<p>2hu</p>alert('YAY')Some <img height=\"32px\" width=\"32px\" alt=\"2hu\" title=\"2hu\" src=\"corndog.png\" /> content mentioning <a href=\"#{ + "<p>2hu <img height=\"32px\" width=\"32px\" alt=\"2hu\" title=\"2hu\" src=\"corndog.png\" /></p>alert('YAY')Some <img height=\"32px\" width=\"32px\" alt=\"2hu\" title=\"2hu\" src=\"corndog.png\" /> content mentioning <a href=\"#{ mentioned_user.ap_id }\">@shp</a>" @@ -138,7 +138,7 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenterTest do "user" => UserView.render("show.json", %{user: user, for: follower}), "is_local" => false, "statusnet_html" => expected_html, - "text" => "2hu" <> content, + "text" => "2hu :2hu:" <> content, "is_post_verb" => true, "created_at" => "Tue May 24 13:26:08 +0000 2016", "in_reply_to_status_id" => 213_123, @@ -164,7 +164,9 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenterTest do "possibly_sensitive" => true, "uri" => activity.data["object"]["id"], "visibility" => "direct", - "summary" => "2hu" + "summary" => "2hu :2hu:", + "summary_html" => + "2hu <img height=\"32px\" width=\"32px\" alt=\"2hu\" title=\"2hu\" src=\"corndog.png\" />" } assert ActivityRepresenter.to_map(activity, %{ diff --git a/test/web/twitter_api/views/activity_view_test.exs b/test/web/twitter_api/views/activity_view_test.exs index 374440300..8b5a16add 100644 --- a/test/web/twitter_api/views/activity_view_test.exs +++ b/test/web/twitter_api/views/activity_view_test.exs @@ -81,10 +81,13 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do result = ActivityView.render("activity.json", activity: activity) - expected = + expected = ":woollysocks: meow" + + expected_html = "<img height=\"32px\" width=\"32px\" alt=\"woollysocks\" title=\"woollysocks\" src=\"http://localhost:4001/finmoji/128px/woollysocks-128.png\" /> meow" assert result["summary"] == expected + assert result["summary_html"] == expected_html end test "a create activity with a summary containing invalid HTML" do @@ -99,6 +102,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do expected = "meow" assert result["summary"] == expected + assert result["summary_html"] == expected end test "a create activity with a note" do @@ -135,6 +139,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do "pinned" => false, "statusnet_conversation_id" => convo_id, "summary" => "", + "summary_html" => "", "statusnet_html" => "Hey <span><a data-user=\"#{other_user.id}\" href=\"#{other_user.ap_id}\">@<span>shp</span></a></span>!", "tags" => [], |