aboutsummaryrefslogtreecommitdiff
path: root/lib/pleroma/web
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pleroma/web')
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex41
-rw-r--r--lib/pleroma/web/activity_pub/transmogrifier.ex14
-rw-r--r--lib/pleroma/web/endpoint.ex2
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api_controller.ex56
-rw-r--r--lib/pleroma/web/mastodon_api/views/account_view.ex12
-rw-r--r--lib/pleroma/web/nodeinfo/nodeinfo_controller.ex6
-rw-r--r--lib/pleroma/web/streamer.ex21
-rw-r--r--lib/pleroma/web/twitter_api/controllers/util_controller.ex55
-rw-r--r--lib/pleroma/web/twitter_api/views/activity_view.ex3
9 files changed, 144 insertions, 66 deletions
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index ed2240530..361e93e91 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -14,8 +14,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
# For Announce activities, we filter the recipients based on following status for any actors
# that match actual users. See issue #164 for more information about why this is necessary.
- def get_recipients(%{"type" => "Announce"} = data) do
- recipients = (data["to"] || []) ++ (data["cc"] || [])
+ defp get_recipients(%{"type" => "Announce"} = data) do
+ to = data["to"] || []
+ cc = data["cc"] || []
+ recipients = to ++ cc
actor = User.get_cached_by_ap_id(data["actor"])
recipients
@@ -28,10 +30,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
User.following?(user, actor)
end
end)
+
+ {recipients, to, cc}
end
- def get_recipients(data) do
- (data["to"] || []) ++ (data["cc"] || [])
+ defp get_recipients(data) do
+ to = data["to"] || []
+ cc = data["cc"] || []
+ recipients = to ++ cc
+ {recipients, to, cc}
end
defp check_actor_is_active(actor) do
@@ -53,12 +60,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
:ok <- check_actor_is_active(map["actor"]),
{:ok, map} <- MRF.filter(map),
:ok <- insert_full_object(map) do
+ {recipients, _, _} = get_recipients(map)
+
{:ok, activity} =
Repo.insert(%Activity{
data: map,
local: local,
actor: map["actor"],
- recipients: get_recipients(map)
+ recipients: recipients
})
Notification.create_notifications(activity)
@@ -404,6 +413,20 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp restrict_tag(query, _), do: query
+ defp restrict_to_cc(query, recipients_to, recipients_cc) do
+ from(
+ activity in query,
+ where:
+ fragment(
+ "(?->'to' \\?| ?) or (?->'cc' \\?| ?)",
+ activity.data,
+ ^recipients_to,
+ activity.data,
+ ^recipients_cc
+ )
+ )
+ end
+
defp restrict_recipients(query, [], _user), do: query
defp restrict_recipients(query, recipients, nil) do
@@ -545,6 +568,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> Enum.reverse()
end
+ def fetch_activities_bounded(recipients_to, recipients_cc, opts \\ %{}) do
+ fetch_activities_query([], opts)
+ |> restrict_to_cc(recipients_to, recipients_cc)
+ |> Repo.all()
+ |> Enum.reverse()
+ end
+
def upload(file) do
data = Upload.store(file, Application.get_env(:pleroma, :instance)[:dedupe_media])
Repo.insert(%Object{data: data})
@@ -722,6 +752,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/endpoint.ex b/lib/pleroma/web/endpoint.ex
index cbedca004..1e5ac2721 100644
--- a/lib/pleroma/web/endpoint.ex
+++ b/lib/pleroma/web/endpoint.ex
@@ -11,7 +11,7 @@ defmodule Pleroma.Web.Endpoint do
#
# You should set gzip to true if you are running phoenix.digest
# when deploying your static files in production.
- plug(Plug.Static, at: "/media", from: Pleroma.Upload.upload_path(), gzip: false)
+ plug(Plug.Static, at: "/media", from: Pleroma.Uploaders.Local.upload_path(), gzip: false)
plug(
Plug.Static,
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index b930b002e..49a8655f0 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.OAuth.{Authorization, Token, App}
+ alias Pleroma.Web.MediaProxy
alias Comeonin.Pbkdf2
import Ecto.Query
require Logger
@@ -653,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
@@ -680,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/"
@@ -704,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)
@@ -850,9 +831,14 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|> Map.put("type", "Create")
|> Map.put("blocking_user", user)
- # adding title is a hack to not make empty lists function like a public timeline
+ # we must filter the following list for the user to avoid leaking statuses the user
+ # does not actually have permission to see (for more info, peruse security issue #270).
+ following_to =
+ following
+ |> Enum.filter(fn x -> x in user.following end)
+
activities =
- ActivityPub.fetch_activities([title | following], params)
+ ActivityPub.fetch_activities_bounded(following_to, following, params)
|> Enum.reverse()
conn
@@ -1044,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" ->
%{
@@ -1184,6 +1172,12 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
)
end)
+ |> Enum.map(fn x ->
+ Map.put(x, "avatar", MediaProxy.url(x["avatar"]))
+ end)
+ |> Enum.map(fn x ->
+ Map.put(x, "avatar_static", MediaProxy.url(x["avatar_static"]))
+ end)
conn
|> json(data2)
diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex
index 634985fb6..85aac493f 100644
--- a/lib/pleroma/web/mastodon_api/views/account_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/account_view.ex
@@ -34,7 +34,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
%{
id: to_string(user.id),
- username: hd(String.split(user.nickname, "@")),
+ username: username_from_nickname(user.nickname),
acct: user.nickname,
display_name: user.name || user.nickname,
locked: user_info.locked,
@@ -53,7 +53,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
bot: bot,
source: %{
note: "",
- privacy: "public",
+ privacy: user_info.default_scope,
sensitive: "false"
}
}
@@ -63,7 +63,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
%{
id: to_string(user.id),
acct: user.nickname,
- username: hd(String.split(user.nickname, "@")),
+ username: username_from_nickname(user.nickname),
url: user.ap_id
}
end
@@ -83,4 +83,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
def render("relationships.json", %{user: user, targets: targets}) do
render_many(targets, AccountView, "relationship.json", user: user, as: :target)
end
+
+ defp username_from_nickname(string) when is_binary(string) do
+ hd(String.split(string, "@"))
+ end
+
+ defp username_from_nickname(_), do: nil
end
diff --git a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
index 2fab60274..9155e42cd 100644
--- a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
+++ b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
@@ -22,6 +22,8 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
instance = Application.get_env(:pleroma, :instance)
media_proxy = Application.get_env(:pleroma, :media_proxy)
suggestions = Application.get_env(:pleroma, :suggestions)
+ chat = Application.get_env(:pleroma, :chat)
+ gopher = Application.get_env(:pleroma, :gopher)
stats = Stats.get_stats()
response = %{
@@ -52,7 +54,9 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
thirdPartyEngine: Keyword.get(suggestions, :third_party_engine, ""),
timeout: Keyword.get(suggestions, :timeout, 5000),
web: Keyword.get(suggestions, :web, "")
- }
+ },
+ chat: Keyword.get(chat, :enabled),
+ gopher: Keyword.get(gopher, :enabled)
}
}
diff --git a/lib/pleroma/web/streamer.ex b/lib/pleroma/web/streamer.ex
index c61bad830..6b6d40346 100644
--- a/lib/pleroma/web/streamer.ex
+++ b/lib/pleroma/web/streamer.ex
@@ -1,7 +1,8 @@
defmodule Pleroma.Web.Streamer do
use GenServer
require Logger
- alias Pleroma.{User, Notification, Activity, Object}
+ alias Pleroma.{User, Notification, Activity, Object, Repo}
+ alias Pleroma.Web.ActivityPub.ActivityPub
def init(args) do
{:ok, args}
@@ -60,8 +61,24 @@ defmodule Pleroma.Web.Streamer do
end
def handle_cast(%{action: :stream, topic: "list", item: item}, topics) do
+ author = User.get_cached_by_ap_id(item.data["actor"])
+
+ # filter the recipient list if the activity is not public, see #270.
+ recipient_lists =
+ case ActivityPub.is_public?(item) do
+ true ->
+ Pleroma.List.get_lists_from_activity(item)
+
+ _ ->
+ Pleroma.List.get_lists_from_activity(item)
+ |> Enum.filter(fn list ->
+ owner = Repo.get(User, list.user_id)
+ author.follower_address in owner.following
+ end)
+ end
+
recipient_topics =
- Pleroma.List.get_lists_from_activity(item)
+ recipient_lists
|> Enum.map(fn %{id: id} -> "list:#{id}" end)
Enum.each(recipient_topics || [], fn list_topic ->
diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
index d1ecebf61..886b70f5f 100644
--- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex
+++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
@@ -156,28 +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),
- 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"
}