diff --git a/config/config.exs b/config/config.exs
index 9c4d73465..e8cf2ed3a 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -139,7 +139,8 @@
finmoji_enabled: true,
mrf_transparency: true,
autofollowed_nicknames: [],
- max_pinned_statuses: 1
+ max_pinned_statuses: 1,
+ no_attachment_links: false
config :pleroma, :markup,
# XXX - unfortunately, inline images must be enabled by default right now, because
diff --git a/docs/config.md b/docs/config.md
index b9ad2aef7..5464fa90d 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -95,6 +95,7 @@ config :pleroma, Pleroma.Mailer,
older software for theses nicknames.
* `max_pinned_statuses`: The maximum number of pinned statuses. `0` will disable the feature.
* `autofollowed_nicknames`: Set to nicknames of (local) users that every new user should automatically follow.
+* `no_attachment_links`: Set to true to disable automatically adding attachment link text to statuses
## :logger
* `backends`: `:console` is used to send logs to stdout, `{ExSyslogger, :ex_syslogger}` to log to syslog
diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx
index 46b84fb50..a24bb0e61 100644
--- a/installation/pleroma.nginx
+++ b/installation/pleroma.nginx
@@ -79,8 +79,10 @@ server {
proxy_cache_valid 200 206 301 304 1h;
proxy_cache_lock on;
proxy_ignore_client_abort on;
- proxy_buffering off;
+ proxy_buffering on;
chunked_transfer_encoding on;
+ proxy_ignore_headers Cache-Control;
+ proxy_hide_header Cache-Control;
proxy_pass http://localhost:4000;
}
}
diff --git a/installation/pleroma.service b/installation/pleroma.service
index f1ed56cb3..72090bbc7 100644
--- a/installation/pleroma.service
+++ b/installation/pleroma.service
@@ -3,15 +3,23 @@ Description=Pleroma social network
After=network.target postgresql.service
[Service]
-User=pleroma
-WorkingDirectory=/home/pleroma/pleroma
-Environment="HOME=/home/pleroma"
-Environment="MIX_ENV=prod"
-ExecStart=/usr/local/bin/mix phx.server
ExecReload=/bin/kill $MAINPID
KillMode=process
Restart=on-failure
+; Name of the user that runs the Pleroma service.
+User=pleroma
+; Declares that Pleroma runs in production mode.
+Environment="MIX_ENV=prod"
+
+; Make sure that all paths fit your installation.
+; Path to the home directory of the user running the Pleroma service.
+Environment="HOME=/home/pleroma"
+; Path to the folder containing the Pleroma installation.
+WorkingDirectory=/home/pleroma/pleroma
+; Path to the Mix binary.
+ExecStart=/usr/bin/mix phx.server
+
; Some security directives.
; Use private /tmp and /var/tmp folders inside a new file system namespace, which are discarded after the process stops.
PrivateTmp=true
diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex
index 2696f41c0..9e50ea3f4 100644
--- a/lib/pleroma/formatter.ex
+++ b/lib/pleroma/formatter.ex
@@ -155,7 +155,9 @@ def add_user_links({subs, text}, mentions) do
short_match = String.split(match, "@") |> tl() |> hd()
{uuid,
- "@#{short_match}"}
+ "@#{
+ short_match
+ }"}
end)
{subs, uuid_text}
@@ -178,7 +180,7 @@ def add_hashtag_links({subs, text}, tags) do
subs ++
Enum.map(tags, fn {tag_text, tag, uuid} ->
url =
- "#{
+ "#{
tag_text
}"
diff --git a/lib/pleroma/html.ex b/lib/pleroma/html.ex
index 0c5b0f03f..f5c6e5033 100644
--- a/lib/pleroma/html.ex
+++ b/lib/pleroma/html.ex
@@ -78,14 +78,14 @@ defmodule Pleroma.HTML.Scrubber.TwitterText do
# links
Meta.allow_tag_with_uri_attributes("a", ["href", "data-user", "data-tag"], @valid_schemes)
- Meta.allow_tag_with_these_attributes("a", ["name", "title"])
+ Meta.allow_tag_with_these_attributes("a", ["name", "title", "class"])
# paragraphs and linebreaks
Meta.allow_tag_with_these_attributes("br", [])
Meta.allow_tag_with_these_attributes("p", [])
# microformats
- Meta.allow_tag_with_these_attributes("span", [])
+ Meta.allow_tag_with_these_attributes("span", ["class"])
# allow inline images for custom emoji
@allow_inline_images Keyword.get(@markup, :allow_inline_images)
@@ -119,7 +119,7 @@ defmodule Pleroma.HTML.Scrubber.Default do
Meta.strip_comments()
Meta.allow_tag_with_uri_attributes("a", ["href", "data-user", "data-tag"], @valid_schemes)
- Meta.allow_tag_with_these_attributes("a", ["name", "title"])
+ Meta.allow_tag_with_these_attributes("a", ["name", "title", "class"])
Meta.allow_tag_with_these_attributes("abbr", ["title"])
@@ -134,7 +134,7 @@ defmodule Pleroma.HTML.Scrubber.Default do
Meta.allow_tag_with_these_attributes("ol", [])
Meta.allow_tag_with_these_attributes("p", [])
Meta.allow_tag_with_these_attributes("pre", [])
- Meta.allow_tag_with_these_attributes("span", [])
+ Meta.allow_tag_with_these_attributes("span", ["class"])
Meta.allow_tag_with_these_attributes("strong", [])
Meta.allow_tag_with_these_attributes("u", [])
Meta.allow_tag_with_these_attributes("ul", [])
diff --git a/lib/pleroma/http/http.ex b/lib/pleroma/http/http.ex
index b8103cef6..75c58e6c9 100644
--- a/lib/pleroma/http/http.ex
+++ b/lib/pleroma/http/http.ex
@@ -31,12 +31,15 @@ def request(method, url, body \\ "", headers \\ [], options \\ []) do
process_request_options(options)
|> process_sni_options(url)
+ params = Keyword.get(options, :params, [])
+
%{}
|> Builder.method(method)
|> Builder.headers(headers)
|> Builder.opts(options)
|> Builder.url(url)
|> Builder.add_param(:body, :body, body)
+ |> Builder.add_param(:query, :query, params)
|> Enum.into([])
|> (&Tesla.request(Connection.new(), &1)).()
end
diff --git a/lib/pleroma/http/request_builder.ex b/lib/pleroma/http/request_builder.ex
index bffc7c6fe..5f2cff2c0 100644
--- a/lib/pleroma/http/request_builder.ex
+++ b/lib/pleroma/http/request_builder.ex
@@ -100,6 +100,8 @@ def add_optional_params(request, definitions, [{key, value} | tail]) do
Map
"""
@spec add_param(map(), atom, atom, any()) :: map()
+ def add_param(request, :query, :query, values), do: Map.put(request, :query, values)
+
def add_param(request, :body, :body, value), do: Map.put(request, :body, value)
def add_param(request, :body, key, value) do
@@ -107,7 +109,10 @@ def add_param(request, :body, key, value) do
|> Map.put_new_lazy(:body, &Tesla.Multipart.new/0)
|> Map.update!(
:body,
- &Tesla.Multipart.add_field(&1, key, Poison.encode!(value),
+ &Tesla.Multipart.add_field(
+ &1,
+ key,
+ Jason.encode!(value),
headers: [{:"Content-Type", "application/json"}]
)
)
diff --git a/lib/pleroma/stats.ex b/lib/pleroma/stats.ex
index 8a030ecd0..b3566ceb6 100644
--- a/lib/pleroma/stats.ex
+++ b/lib/pleroma/stats.ex
@@ -34,10 +34,11 @@ def update_stats do
peers =
from(
u in Pleroma.User,
- select: fragment("distinct ?->'host'", u.info),
+ select: fragment("distinct split_part(?, '@', 2)", u.nickname),
where: u.local != ^true
)
|> Repo.all()
+ |> Enum.filter(& &1)
domain_count = Enum.count(peers)
@@ -45,7 +46,7 @@ def update_stats do
from(u in User.local_user_query(), select: fragment("sum((?->>'note_count')::int)", u.info))
status_count = Repo.one(status_query)
- user_count = Repo.aggregate(User.local_user_query(), :count, :id)
+ user_count = Repo.aggregate(User.active_local_user_query(), :count, :id)
Agent.update(__MODULE__, fn _ ->
{peers, %{domain_count: domain_count, status_count: status_count, user_count: user_count}}
diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex
index 0b1bdeec4..0a19e737b 100644
--- a/lib/pleroma/upload.ex
+++ b/lib/pleroma/upload.ex
@@ -34,8 +34,9 @@ defmodule Pleroma.Upload do
require Logger
@type source ::
- Plug.Upload.t() | data_uri_string ::
- String.t() | {:from_local, name :: String.t(), id :: String.t(), path :: String.t()}
+ Plug.Upload.t()
+ | (data_uri_string :: String.t())
+ | {:from_local, name :: String.t(), id :: String.t(), path :: String.t()}
@type option ::
{:type, :avatar | :banner | :background}
@@ -215,6 +216,12 @@ defp tempfile_for_image(data) do
end
defp url_from_spec(base_url, {:file, path}) do
+ path =
+ path
+ |> URI.encode()
+ |> String.replace("?", "%3F")
+ |> String.replace(":", "%3A")
+
[base_url, "media", path]
|> Path.join()
end
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 13a476fd2..5137af917 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -822,7 +822,7 @@ def unblock_domain(user, domain) do
update_and_set_cache(cng)
end
- def local_user_query() do
+ def local_user_query do
from(
u in User,
where: u.local == true,
@@ -830,7 +830,14 @@ def local_user_query() do
)
end
- def moderator_user_query() do
+ def active_local_user_query do
+ from(
+ u in local_user_query(),
+ where: fragment("?->'deactivated' @> 'false'", u.info)
+ )
+ end
+
+ def moderator_user_query do
from(
u in User,
where: u.local == true,
@@ -1066,4 +1073,14 @@ defp local_nickname_regex() do
@strict_local_nickname_regex
end
end
+
+ def error_user(ap_id) do
+ %User{
+ name: ap_id,
+ ap_id: ap_id,
+ info: %User.Info{},
+ nickname: "erroruser@example.com",
+ inserted_at: NaiveDateTime.utc_now()
+ }
+ end
end
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 9c1eb377f..5b87f7462 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -515,15 +515,6 @@ defp restrict_reblogs(query, %{"exclude_reblogs" => val}) when val == "true" or
defp restrict_reblogs(query, _), do: query
- # Only search through last 100_000 activities by default
- defp restrict_recent(query, %{"whole_db" => true}), do: query
-
- defp restrict_recent(query, _) do
- since = (Repo.aggregate(Activity, :max, :id) || 0) - 100_000
-
- from(activity in query, where: activity.id > ^since)
- end
-
defp restrict_blocked(query, %{"blocking_user" => %User{info: info}}) do
blocks = info.blocks || []
domain_blocks = info.domain_blocks || []
@@ -574,7 +565,6 @@ def fetch_activities_query(recipients, opts \\ %{}) do
|> restrict_actor(opts)
|> restrict_type(opts)
|> restrict_favorited_by(opts)
- |> restrict_recent(opts)
|> restrict_blocked(opts)
|> restrict_media(opts)
|> restrict_visibility(opts)
diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
index 73ca07e84..7eed0a600 100644
--- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -54,6 +54,36 @@ def object(conn, %{"uuid" => uuid}) do
end
end
+ def object_likes(conn, %{"uuid" => uuid, "page" => page}) do
+ with ap_id <- o_status_url(conn, :object, uuid),
+ %Object{} = object <- Object.get_cached_by_ap_id(ap_id),
+ {_, true} <- {:public?, ActivityPub.is_public?(object)},
+ likes <- Utils.get_object_likes(object) do
+ {page, _} = Integer.parse(page)
+
+ conn
+ |> put_resp_header("content-type", "application/activity+json")
+ |> json(ObjectView.render("likes.json", ap_id, likes, page))
+ else
+ {:public?, false} ->
+ {:error, :not_found}
+ end
+ end
+
+ def object_likes(conn, %{"uuid" => uuid}) do
+ with ap_id <- o_status_url(conn, :object, uuid),
+ %Object{} = object <- Object.get_cached_by_ap_id(ap_id),
+ {_, true} <- {:public?, ActivityPub.is_public?(object)},
+ likes <- Utils.get_object_likes(object) do
+ conn
+ |> put_resp_header("content-type", "application/activity+json")
+ |> json(ObjectView.render("likes.json", ap_id, likes))
+ else
+ {:public?, false} ->
+ {:error, :not_found}
+ end
+ end
+
def activity(conn, %{"uuid" => uuid}) do
with ap_id <- o_status_url(conn, :activity, uuid),
%Activity{} = activity <- Activity.normalize(ap_id),
@@ -204,6 +234,15 @@ def handle_user_activity(user, %{"type" => "Delete"} = params) do
end
end
+ def handle_user_activity(user, %{"type" => "Like"} = params) do
+ with %Object{} = object <- Object.normalize(params["object"]),
+ {:ok, activity, _object} <- ActivityPub.like(user, object) do
+ {:ok, activity}
+ else
+ _ -> {:error, "Can't like object"}
+ end
+ end
+
def handle_user_activity(_, _) do
{:error, "Unhandled activity type"}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex b/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
new file mode 100644
index 000000000..081456046
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
@@ -0,0 +1,29 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2019 Pleroma Authors
.
"] do + child_object = + child_object + |> Map.put("content", "") + + object = + object + |> Map.put("object", child_object) + + {:ok, object} + end + + @impl true + def filter(object), do: {:ok, object} +end diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 87b7fc07f..86d11c874 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -629,6 +629,7 @@ def prepare_object(object) do |> add_mention_tags |> add_emoji_tags |> add_attributed_to + |> add_likes |> prepare_attachments |> set_conversation |> set_reply_to_uri @@ -641,7 +642,7 @@ def prepare_object(object) do # internal -> Mastodon # """ - def prepare_outgoing(%{"type" => "Create", "object" => %{"type" => "Note"} = object} = data) do + def prepare_outgoing(%{"type" => "Create", "object" => object} = data) do object = object |> prepare_object @@ -788,6 +789,22 @@ def add_attributed_to(object) do |> Map.put("attributedTo", attributedTo) end + def add_likes(%{"id" => id, "like_count" => likes} = object) do + likes = %{ + "id" => "#{id}/likes", + "first" => "#{id}/likes?page=1", + "type" => "OrderedCollection", + "totalItems" => likes + } + + object + |> Map.put("likes", likes) + end + + def add_likes(object) do + object + end + def prepare_attachments(object) do attachments = (object["attachment"] || []) @@ -803,7 +820,6 @@ def prepare_attachments(object) do defp strip_internal_fields(object) do object |> Map.drop([ - "likes", "like_count", "announcements", "announcement_count", diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index b313996db..6ecab773c 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -231,6 +231,27 @@ def get_existing_like(actor, %{data: %{"id" => id}}) do Repo.one(query) end + @doc """ + Returns like activities targeting an object + """ + def get_object_likes(%{data: %{"id" => id}}) do + query = + from( + activity in Activity, + # this is to use the index + where: + fragment( + "coalesce((?)->'object'->>'id', (?)->>'object') = ?", + activity.data, + activity.data, + ^id + ), + where: fragment("(?)->>'type' = 'Like'", activity.data) + ) + + Repo.all(query) + end + def make_like_data(%User{ap_id: ap_id} = actor, %{data: %{"id" => id}} = object, activity_id) do data = %{ "type" => "Like", diff --git a/lib/pleroma/web/activity_pub/views/object_view.ex b/lib/pleroma/web/activity_pub/views/object_view.ex index b5c9bf8d0..394d82fbc 100644 --- a/lib/pleroma/web/activity_pub/views/object_view.ex +++ b/lib/pleroma/web/activity_pub/views/object_view.ex @@ -35,4 +35,38 @@ def render("object.json", %{object: %Activity{} = activity}) do Map.merge(base, additional) end + + def render("likes.json", ap_id, likes, page) do + collection(likes, "#{ap_id}/likes", page) + |> Map.merge(Pleroma.Web.ActivityPub.Utils.make_json_ld_header()) + end + + def render("likes.json", ap_id, likes) do + %{ + "id" => "#{ap_id}/likes", + "type" => "OrderedCollection", + "totalItems" => length(likes), + "first" => collection(likes, "#{ap_id}/likes", 1) + } + |> Map.merge(Pleroma.Web.ActivityPub.Utils.make_json_ld_header()) + end + + def collection(collection, iri, page) do + offset = (page - 1) * 10 + items = Enum.slice(collection, offset, 10) + items = Enum.map(items, fn object -> Transmogrifier.prepare_object(object.data) end) + total = length(collection) + + map = %{ + "id" => "#{iri}?page=#{page}", + "type" => "OrderedCollectionPage", + "partOf" => iri, + "totalItems" => total, + "orderedItems" => items + } + + if offset < total do + Map.put(map, "next", "#{iri}?page=#{page + 1}") + end + end end diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 9a748d65e..504670439 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -103,7 +103,14 @@ def post(user, %{"status" => status} = data) do attachments, tags, get_content_type(data["content_type"]), - true + Enum.member?( + [true, "true"], + Map.get( + data, + "no_attachment_links", + Pleroma.Config.get([:instance, :no_attachment_links], false) + ) + ) ), context <- make_context(inReplyTo), cw <- data["spoiler_text"], diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index e00a3fb87..daad89185 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -341,7 +341,6 @@ def post_status(%{assigns: %{user: user}} = conn, %{"status" => _} = params) do params = params |> Map.put("in_reply_to_status_id", params["in_reply_to_id"]) - |> Map.put("no_attachment_links", true) idempotency_key = case get_req_header(conn, "idempotency-key") do @@ -824,9 +823,9 @@ def account_search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) d json(conn, res) end - def favourites(%{assigns: %{user: user}} = conn, _) do + def favourites(%{assigns: %{user: user}} = conn, params) do params = - %{} + params |> Map.put("type", "Create") |> Map.put("favorited_by", user.ap_id) |> Map.put("blocking_user", user) @@ -836,6 +835,7 @@ def favourites(%{assigns: %{user: user}} = conn, _) do |> Enum.reverse() conn + |> add_link_headers(:favourites, activities) |> put_view(StatusView) |> render("index.json", %{activities: activities, for: user, as: :activity}) end diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index db543ffe5..7f5a52ea3 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -32,6 +32,19 @@ defp get_replied_to_activities(activities) do end) end + defp get_user(ap_id) do + cond do + user = User.get_cached_by_ap_id(ap_id) -> + user + + user = User.get_by_guessed_nickname(ap_id) -> + user + + true -> + User.error_user(ap_id) + end + end + def render("index.json", opts) do replied_to_activities = get_replied_to_activities(opts.activities) @@ -48,7 +61,7 @@ def render( "status.json", %{activity: %{data: %{"type" => "Announce", "object" => object}} = activity} = opts ) do - user = User.get_cached_by_ap_id(activity.data["actor"]) + user = get_user(activity.data["actor"]) created_at = Utils.to_masto_date(activity.data["published"]) reblogged = Activity.get_create_activity_by_object_ap_id(object) @@ -93,7 +106,7 @@ def render( end def render("status.json", %{activity: %{data: %{"object" => object}} = activity} = opts) do - user = User.get_cached_by_ap_id(activity.data["actor"]) + user = get_user(activity.data["actor"]) like_count = object["like_count"] || 0 announcement_count = object["announcement_count"] || 0 @@ -116,7 +129,7 @@ def render("status.json", %{activity: %{data: %{"object" => object}} = activity} created_at = Utils.to_masto_date(object["published"]) reply_to = get_reply_to(activity, opts) - reply_to_user = reply_to && User.get_cached_by_ap_id(reply_to.data["actor"]) + reply_to_user = reply_to && get_user(reply_to.data["actor"]) content = object diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex index fe092bf19..6da83c6e4 100644 --- a/lib/pleroma/web/rich_media/parser.ex +++ b/lib/pleroma/web/rich_media/parser.ex @@ -1,5 +1,9 @@ defmodule Pleroma.Web.RichMedia.Parser do - @parsers [Pleroma.Web.RichMedia.Parsers.OGP, Pleroma.Web.RichMedia.Parsers.TwitterCard] + @parsers [ + Pleroma.Web.RichMedia.Parsers.OGP, + Pleroma.Web.RichMedia.Parsers.TwitterCard, + Pleroma.Web.RichMedia.Parsers.OEmbed + ] if Mix.env() == :test do def parse(url), do: parse_url(url) diff --git a/lib/pleroma/web/rich_media/parsers/oembed_parser.ex b/lib/pleroma/web/rich_media/parsers/oembed_parser.ex new file mode 100644 index 000000000..ca7226faf --- /dev/null +++ b/lib/pleroma/web/rich_media/parsers/oembed_parser.ex @@ -0,0 +1,27 @@ +defmodule Pleroma.Web.RichMedia.Parsers.OEmbed do + def parse(html, _data) do + with elements = [_ | _] <- get_discovery_data(html), + {:ok, oembed_url} <- get_oembed_url(elements), + {:ok, oembed_data} <- get_oembed_data(oembed_url) do + {:ok, oembed_data} + else + _e -> {:error, "No OEmbed data found"} + end + end + + defp get_discovery_data(html) do + html |> Floki.find("link[type='application/json+oembed']") + end + + defp get_oembed_url(nodes) do + {"link", attributes, _children} = nodes |> hd() + + {:ok, Enum.into(attributes, %{})["href"]} + end + + defp get_oembed_data(url) do + {:ok, %Tesla.Env{body: json}} = Pleroma.HTTP.get(url) + + {:ok, Poison.decode!(json)} + end +end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 25e866c48..68b02d8ca 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -431,6 +431,7 @@ defmodule Pleroma.Web.Router do get("/users/:nickname/followers", ActivityPubController, :followers) get("/users/:nickname/following", ActivityPubController, :following) get("/users/:nickname/outbox", ActivityPubController, :outbox) + get("/objects/:uuid/likes", ActivityPubController, :object_likes) end pipeline :activitypub_client do diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex index 108e7bfc5..03708d84c 100644 --- a/lib/pleroma/web/twitter_api/views/activity_view.ex +++ b/lib/pleroma/web/twitter_api/views/activity_view.ex @@ -101,20 +101,10 @@ defp get_user(ap_id, opts) do user true -> - error_user(ap_id) + User.error_user(ap_id) end end - defp error_user(ap_id) do - %User{ - name: ap_id, - ap_id: ap_id, - info: %User.Info{}, - nickname: "erroruser@example.com", - inserted_at: NaiveDateTime.utc_now() - } - end - def render("index.json", opts) do context_ids = collect_context_ids(opts.activities) users = collect_users(opts.activities) diff --git a/lib/pleroma/web/websub/websub.ex b/lib/pleroma/web/websub/websub.ex index 3a287edd9..7ca62c83b 100644 --- a/lib/pleroma/web/websub/websub.ex +++ b/lib/pleroma/web/websub/websub.ex @@ -121,6 +121,12 @@ def incoming_subscription_request(user, %{"hub.mode" => "subscribe"} = params) d end end + def incoming_subscription_request(user, params) do + Logger.info("Unhandled WebSub request for #{user.nickname}: #{inspect(params)}") + + {:error, "Invalid WebSub request"} + end + defp get_subscription(topic, callback) do Repo.get_by(WebsubServerSubscription, topic: topic, callback: callback) || %WebsubServerSubscription{} diff --git a/lib/pleroma/web/websub/websub_controller.ex b/lib/pleroma/web/websub/websub_controller.ex index 27304d988..e58f144e5 100644 --- a/lib/pleroma/web/websub/websub_controller.ex +++ b/lib/pleroma/web/websub/websub_controller.ex @@ -67,6 +67,13 @@ def websub_subscription_confirmation( end end + def websub_subscription_confirmation(conn, params) do + Logger.info("Invalid WebSub confirmation request: #{inspect(params)}") + + conn + |> send_resp(500, "Invalid parameters") + end + def websub_incoming(conn, %{"id" => id}) do with "sha1=" <> signature <- hd(get_req_header(conn, "x-hub-signature")), signature <- String.downcase(signature), diff --git a/test/fixtures/rich_media/oembed.html b/test/fixtures/rich_media/oembed.html new file mode 100644 index 000000000..55f17004b --- /dev/null +++ b/test/fixtures/rich_media/oembed.html @@ -0,0 +1,3 @@ + diff --git a/test/fixtures/rich_media/oembed.json b/test/fixtures/rich_media/oembed.json new file mode 100644 index 000000000..2a5f7a771 --- /dev/null +++ b/test/fixtures/rich_media/oembed.json @@ -0,0 +1 @@ +{"type":"photo","flickr_type":"photo","title":"Bacon Lollys","author_name":"\u202e\u202d\u202cbees\u202c","author_url":"https:\/\/www.flickr.com\/photos\/bees\/","width":"1024","height":"768","url":"https:\/\/farm4.staticflickr.com\/3040\/2362225867_4a87ab8baf_b.jpg","web_page":"https:\/\/www.flickr.com\/photos\/bees\/2362225867\/","thumbnail_url":"https:\/\/farm4.staticflickr.com\/3040\/2362225867_4a87ab8baf_q.jpg","thumbnail_width":150,"thumbnail_height":150,"web_page_short_url":"https:\/\/flic.kr\/p\/4AK2sc","license":"All Rights Reserved","license_id":0,"html":"<\/a>", + "license" => "All Rights Reserved", + "license_id" => 0, + "provider_name" => "Flickr", + "provider_url" => "https://www.flickr.com/", + "thumbnail_height" => 150, + "thumbnail_url" => + "https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_q.jpg", + "thumbnail_width" => 150, + "title" => "Bacon Lollys", + "type" => "photo", + "url" => "https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_b.jpg", + "version" => "1.0", + "web_page" => "https://www.flickr.com/photos/bees/2362225867/", + "web_page_short_url" => "https://flic.kr/p/4AK2sc", + "width" => "1024" + }} + end end diff --git a/test/web/twitter_api/twitter_api_controller_test.exs b/test/web/twitter_api/twitter_api_controller_test.exs index 5f13e7959..e08edc525 100644 --- a/test/web/twitter_api/twitter_api_controller_test.exs +++ b/test/web/twitter_api/twitter_api_controller_test.exs @@ -1357,9 +1357,9 @@ test "it updates a user's profile", %{conn: conn} do assert user.name == "new name" assert user.bio == - "hi @#{ - user2.nickname - }" + "hi @#{user2.nickname}" assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user}) end diff --git a/test/web/twitter_api/twitter_api_test.exs b/test/web/twitter_api/twitter_api_test.exs index b9feb23d4..547592ff2 100644 --- a/test/web/twitter_api/twitter_api_test.exs +++ b/test/web/twitter_api/twitter_api_test.exs @@ -38,7 +38,7 @@ test "create a status" do {:ok, activity = %Activity{}} = TwitterAPI.create_status(user, input) expected_text = - "Hello again, @shp.<script></script>