diff options
Diffstat (limited to 'lib')
18 files changed, 179 insertions, 47 deletions
diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index 60dba3434..3ef3b3f58 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -77,7 +77,6 @@ defmodule Pleroma.Notification do |> exclude_notification_muted(user, exclude_notification_muted_opts) |> exclude_blocked(user, exclude_blocked_opts) |> exclude_visibility(opts) - |> exclude_move(opts) end defp exclude_blocked(query, user, opts) do @@ -107,14 +106,6 @@ defmodule Pleroma.Notification do |> where([n, a, o, tm], is_nil(tm.user_id)) end - defp exclude_move(query, %{with_move: true}) do - query - end - - defp exclude_move(query, _opts) do - where(query, [n, a], fragment("?->>'type' != 'Move'", a.data)) - end - @valid_visibilities ~w[direct unlisted public private] defp exclude_visibility(query, %{exclude_visibilities: visibility}) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 911dde6e2..8693c0b80 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -237,7 +237,18 @@ defmodule Pleroma.User do def visible_for?(%User{invisible: true}, _), do: false - def visible_for?(%User{id: user_id}, %User{id: for_id}) when user_id == for_id, do: true + def visible_for?(%User{id: user_id}, %User{id: user_id}), do: true + + def visible_for?(%User{local: local} = user, nil) do + cfg_key = + if local, + do: :local, + else: :remote + + if Config.get([:restrict_unauthenticated, :profiles, cfg_key]), + do: false, + else: account_status(user) == :active + end def visible_for?(%User{} = user, for_user) do account_status(user) == :active || superuser?(for_user) diff --git a/lib/pleroma/web/activity_pub/visibility.ex b/lib/pleroma/web/activity_pub/visibility.ex index 6f226fc92..453a6842e 100644 --- a/lib/pleroma/web/activity_pub/visibility.ex +++ b/lib/pleroma/web/activity_pub/visibility.ex @@ -44,6 +44,7 @@ defmodule Pleroma.Web.ActivityPub.Visibility do def is_list?(%{data: %{"listMessage" => _}}), do: true def is_list?(_), do: false + @spec visible_for_user?(Activity.t(), User.t() | nil) :: boolean() def visible_for_user?(%{actor: ap_id}, %User{ap_id: ap_id}), do: true def visible_for_user?(%{data: %{"listMessage" => list_ap_id}} = activity, %User{} = user) do @@ -55,14 +56,21 @@ defmodule Pleroma.Web.ActivityPub.Visibility do def visible_for_user?(%{data: %{"listMessage" => _}}, nil), do: false - def visible_for_user?(activity, nil) do - is_public?(activity) + def visible_for_user?(%{local: local} = activity, nil) do + cfg_key = + if local, + do: :local, + else: :remote + + if Pleroma.Config.get([:restrict_unauthenticated, :activities, cfg_key]), + do: false, + else: is_public?(activity) end def visible_for_user?(activity, user) do x = [user.ap_id | User.following(user)] y = [activity.actor] ++ activity.data["to"] ++ (activity.data["cc"] || []) - visible_for_user?(activity, nil) || Enum.any?(x, &(&1 in y)) + is_public?(activity) || Enum.any?(x, &(&1 in y)) end def entire_thread_visible_for_user?(%Activity{} = activity, %User{} = user) do diff --git a/lib/pleroma/web/controller_helper.ex b/lib/pleroma/web/controller_helper.ex index c9a3a2585..ad293cda9 100644 --- a/lib/pleroma/web/controller_helper.ex +++ b/lib/pleroma/web/controller_helper.ex @@ -87,7 +87,8 @@ defmodule Pleroma.Web.ControllerHelper do render_error(conn, :not_implemented, "Can't display this activity") end - @spec put_in_if_exist(map(), atom() | String.t(), any) :: map() - def put_in_if_exist(map, _key, nil), do: map - def put_in_if_exist(map, key, value), do: put_in(map, key, value) + @spec put_if_exist(map(), atom() | String.t(), any) :: map() + def put_if_exist(map, _key, nil), do: map + + def put_if_exist(map, key, value), do: Map.put(map, key, value) end diff --git a/lib/pleroma/web/feed/tag_controller.ex b/lib/pleroma/web/feed/tag_controller.ex index 75c9ea17e..8133f8480 100644 --- a/lib/pleroma/web/feed/tag_controller.ex +++ b/lib/pleroma/web/feed/tag_controller.ex @@ -9,18 +9,18 @@ defmodule Pleroma.Web.Feed.TagController do alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.Feed.FeedView - import Pleroma.Web.ControllerHelper, only: [put_in_if_exist: 3] + import Pleroma.Web.ControllerHelper, only: [put_if_exist: 3] def feed(conn, %{"tag" => raw_tag} = params) do {format, tag} = parse_tag(raw_tag) activities = %{"type" => ["Create"], "tag" => tag} - |> put_in_if_exist("max_id", params["max_id"]) + |> put_if_exist("max_id", params["max_id"]) |> ActivityPub.fetch_public_activities() conn - |> put_resp_content_type("application/atom+xml") + |> put_resp_content_type("application/#{format}+xml") |> put_view(FeedView) |> render("tag.#{format}", activities: activities, diff --git a/lib/pleroma/web/feed/user_controller.ex b/lib/pleroma/web/feed/user_controller.ex index 9ba602d9f..e27f85929 100644 --- a/lib/pleroma/web/feed/user_controller.ex +++ b/lib/pleroma/web/feed/user_controller.ex @@ -11,7 +11,7 @@ defmodule Pleroma.Web.Feed.UserController do alias Pleroma.Web.ActivityPub.ActivityPubController alias Pleroma.Web.Feed.FeedView - import Pleroma.Web.ControllerHelper, only: [put_in_if_exist: 3] + import Pleroma.Web.ControllerHelper, only: [put_if_exist: 3] plug(Pleroma.Plugs.SetFormatPlug when action in [:feed_redirect]) @@ -40,19 +40,28 @@ defmodule Pleroma.Web.Feed.UserController do end def feed(conn, %{"nickname" => nickname} = params) do + format = get_format(conn) + + format = + if format in ["rss", "atom"] do + format + else + "atom" + end + with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do activities = %{ "type" => ["Create"], "actor_id" => user.ap_id } - |> put_in_if_exist("max_id", params["max_id"]) + |> put_if_exist("max_id", params["max_id"]) |> ActivityPub.fetch_public_activities() conn - |> put_resp_content_type("application/atom+xml") + |> put_resp_content_type("application/#{format}+xml") |> put_view(FeedView) - |> render("user.xml", + |> render("user.#{format}", user: user, activities: activities, feed_config: Pleroma.Config.get([:feed]) diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex index 88c997b9f..6dbf11ac9 100644 --- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -60,7 +60,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do plug( Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug - when action != :create + when action not in [:create, :show, :statuses] ) @relations [:follow, :unfollow] @@ -259,7 +259,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do @doc "GET /api/v1/accounts/:id/statuses" def statuses(%{assigns: %{user: reading_user}} = conn, params) do - with %User{} = user <- User.get_cached_by_nickname_or_id(params["id"], for: reading_user) do + with %User{} = user <- User.get_cached_by_nickname_or_id(params["id"], for: reading_user), + true <- User.visible_for?(user, reading_user) do params = params |> Map.put("tag", params["tagged"]) @@ -271,6 +272,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do |> add_link_headers(activities) |> put_view(StatusView) |> render("index.json", activities: activities, for: reading_user, as: :activity) + else + _e -> render_error(conn, :not_found, "Can't find user") end end diff --git a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex index 5c90065f6..37afe6949 100644 --- a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex @@ -76,7 +76,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do %{scopes: ["write:bookmarks"]} when action in [:bookmark, :unbookmark] ) - plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug) + plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug when action not in [:index, :show]) @rate_limited_status_actions ~w(reblog unreblog favourite unfavourite create delete)a diff --git a/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex b/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex index 09e08271b..91f41416d 100644 --- a/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex @@ -27,7 +27,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action in [:home, :direct]) plug(OAuthScopesPlug, %{scopes: ["read:lists"]} when action == :list) - plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug) + plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug when action != :public) plug(:put_view, Pleroma.Web.MastodonAPI.StatusView) @@ -75,17 +75,30 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do def public(%{assigns: %{user: user}} = conn, params) do local_only = truthy_param?(params["local"]) - activities = - params - |> Map.put("type", ["Create", "Announce"]) - |> Map.put("local_only", local_only) - |> Map.put("blocking_user", user) - |> Map.put("muting_user", user) - |> ActivityPub.fetch_public_activities() + cfg_key = + if local_only do + :local + else + :federated + end - conn - |> add_link_headers(activities, %{"local" => local_only}) - |> render("index.json", activities: activities, for: user, as: :activity) + restrict? = Pleroma.Config.get([:restrict_unauthenticated, :timelines, cfg_key]) + + if not (restrict? and is_nil(user)) do + activities = + params + |> Map.put("type", ["Create", "Announce"]) + |> Map.put("local_only", local_only) + |> Map.put("blocking_user", user) + |> Map.put("muting_user", user) + |> ActivityPub.fetch_public_activities() + + conn + |> add_link_headers(activities, %{"local" => local_only}) + |> render("index.json", activities: activities, for: user, as: :activity) + else + render_error(conn, :unauthorized, "authorization required for timeline view") + end end def hashtag_fetching(params, user, local_only) do diff --git a/lib/pleroma/web/mastodon_api/mastodon_api.ex b/lib/pleroma/web/mastodon_api/mastodon_api.ex index 3fe2be521..70da64a7a 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api.ex @@ -55,6 +55,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do user |> Notification.for_user_query(options) + |> restrict(:include_types, options) |> restrict(:exclude_types, options) |> restrict(:account_ap_id, options) |> Pagination.fetch_paginated(params) @@ -69,10 +70,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do defp cast_params(params) do param_types = %{ exclude_types: {:array, :string}, + include_types: {:array, :string}, exclude_visibilities: {:array, :string}, reblogs: :boolean, with_muted: :boolean, - with_move: :boolean, account_ap_id: :string } @@ -80,14 +81,16 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do changeset.changes end + defp restrict(query, :include_types, %{include_types: mastodon_types = [_ | _]}) do + ap_types = convert_and_filter_mastodon_types(mastodon_types) + + where(query, [q, a], fragment("? @> ARRAY[?->>'type']::varchar[]", ^ap_types, a.data)) + end + defp restrict(query, :exclude_types, %{exclude_types: mastodon_types = [_ | _]}) do - ap_types = - mastodon_types - |> Enum.map(&Activity.from_mastodon_notification_type/1) - |> Enum.filter(& &1) + ap_types = convert_and_filter_mastodon_types(mastodon_types) - query - |> where([q, a], not fragment("? @> ARRAY[?->>'type']::varchar[]", ^ap_types, a.data)) + where(query, [q, a], not fragment("? @> ARRAY[?->>'type']::varchar[]", ^ap_types, a.data)) end defp restrict(query, :account_ap_id, %{account_ap_id: account_ap_id}) do @@ -95,4 +98,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do end defp restrict(query, _, _), do: query + + defp convert_and_filter_mastodon_types(types) do + types + |> Enum.map(&Activity.from_mastodon_notification_type/1) + |> Enum.filter(& &1) + end end diff --git a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex index 18eb41333..30838b1eb 100644 --- a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex +++ b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex @@ -60,6 +60,7 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do "pleroma_explicit_addressing", "shareable_emoji_packs", "multifetch", + "pleroma:api/v1/notifications:include_types_filter", if Config.get([:media_proxy, :enabled]) do "media_proxy" end, diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index e4e3ee704..3f36f6c1a 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -513,7 +513,7 @@ defmodule Pleroma.Web.Router do end pipeline :ostatus do - plug(:accepts, ["html", "xml", "atom", "activity+json", "json"]) + plug(:accepts, ["html", "xml", "rss", "atom", "activity+json", "json"]) plug(Pleroma.Plugs.StaticFEPlug) end diff --git a/lib/pleroma/web/templates/feed/feed/_activity.xml.eex b/lib/pleroma/web/templates/feed/feed/_activity.atom.eex index ac8a75009..ac8a75009 100644 --- a/lib/pleroma/web/templates/feed/feed/_activity.xml.eex +++ b/lib/pleroma/web/templates/feed/feed/_activity.atom.eex diff --git a/lib/pleroma/web/templates/feed/feed/_activity.rss.eex b/lib/pleroma/web/templates/feed/feed/_activity.rss.eex new file mode 100644 index 000000000..a4dbed638 --- /dev/null +++ b/lib/pleroma/web/templates/feed/feed/_activity.rss.eex @@ -0,0 +1,49 @@ +<item> + <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> + <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> + <guid><%= @data["id"] %></guid> + <title><%= activity_title(@object, Keyword.get(@feed_config, :post_title, %{})) %></title> + <description><%= activity_content(@object) %></description> + <pubDate><%= @data["published"] %></pubDate> + <updated><%= @data["published"] %></updated> + <ostatus:conversation ref="<%= activity_context(@activity) %>"> + <%= activity_context(@activity) %> + </ostatus:conversation> + <link rel="ostatus:conversation"><%= activity_context(@activity) %></link> + + <%= if @data["summary"] do %> + <description><%= @data["summary"] %></description> + <% end %> + + <%= if @activity.local do %> + <link><%= @data["id"] %></link> + <% else %> + <link><%= @data["external_url"] %></link> + <% end %> + + <%= for tag <- @data["tag"] || [] do %> + <category term="<%= tag %>"></category> + <% end %> + + <%= for attachment <- @data["attachment"] || [] do %> + <link type="<%= attachment_type(attachment) %>"><%= attachment_href(attachment) %></link> + <% end %> + + <%= if @data["inReplyTo"] do %> + <thr:in-reply-to ref='<%= @data["inReplyTo"] %>' href='<%= get_href(@data["inReplyTo"]) %>'/> + <% end %> + + <%= for id <- @activity.recipients do %> + <%= if id == Pleroma.Constants.as_public() do %> + <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection">http://activityschema.org/collection/public</link> + <% else %> + <%= unless Regex.match?(~r/^#{Pleroma.Web.base_url()}.+followers$/, id) do %> + <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person"><%= id %></link> + <% end %> + <% end %> + <% end %> + + <%= for {emoji, file} <- @data["emoji"] || %{} do %> + <link name="<%= emoji %>" rel="emoji"><%= file %></link> + <% end %> +</item> diff --git a/lib/pleroma/web/templates/feed/feed/_author.xml.eex b/lib/pleroma/web/templates/feed/feed/_author.atom.eex index 25cbffada..25cbffada 100644 --- a/lib/pleroma/web/templates/feed/feed/_author.xml.eex +++ b/lib/pleroma/web/templates/feed/feed/_author.atom.eex diff --git a/lib/pleroma/web/templates/feed/feed/_author.rss.eex b/lib/pleroma/web/templates/feed/feed/_author.rss.eex new file mode 100644 index 000000000..526aeddcf --- /dev/null +++ b/lib/pleroma/web/templates/feed/feed/_author.rss.eex @@ -0,0 +1,17 @@ +<managingEditor> + <guid><%= @user.ap_id %></guid> + <activity:object>http://activitystrea.ms/schema/1.0/person</activity:object> + <uri><%= @user.ap_id %></uri> + <poco:preferredUsername><%= @user.nickname %></poco:preferredUsername> + <poco:displayName><%= @user.name %></poco:displayName> + <poco:note><%= escape(@user.bio) %></poco:note> + <description><%= escape(@user.bio) %></description> + <name><%= @user.nickname %></name> + <link rel="avatar"><%= User.avatar_url(@user) %></link> + <%= if User.banner_url(@user) do %> + <link rel="header"><%= User.banner_url(@user) %></link> + <% end %> + <%= if @user.local do %> + <ap_enabled>true</ap_enabled> + <% end %> +</managingEditor> diff --git a/lib/pleroma/web/templates/feed/feed/user.xml.eex b/lib/pleroma/web/templates/feed/feed/user.atom.eex index d274c08ae..c6acd848f 100644 --- a/lib/pleroma/web/templates/feed/feed/user.xml.eex +++ b/lib/pleroma/web/templates/feed/feed/user.atom.eex @@ -12,13 +12,13 @@ <logo><%= logo(@user) %></logo> <link rel="self" href="<%= '#{user_feed_url(@conn, :feed, @user.nickname)}.atom' %>" type="application/atom+xml"/> - <%= render @view_module, "_author.xml", assigns %> + <%= render @view_module, "_author.atom", assigns %> <%= if last_activity(@activities) do %> <link rel="next" href="<%= '#{user_feed_url(@conn, :feed, @user.nickname)}.atom?max_id=#{last_activity(@activities).id}' %>" type="application/atom+xml"/> <% end %> <%= for activity <- @activities do %> - <%= render @view_module, "_activity.xml", Map.merge(assigns, prepare_activity(activity)) %> + <%= render @view_module, "_activity.atom", Map.merge(assigns, prepare_activity(activity)) %> <% end %> </feed> diff --git a/lib/pleroma/web/templates/feed/feed/user.rss.eex b/lib/pleroma/web/templates/feed/feed/user.rss.eex new file mode 100644 index 000000000..d69120480 --- /dev/null +++ b/lib/pleroma/web/templates/feed/feed/user.rss.eex @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<rss version="2.0"> + <channel> + <guid><%= user_feed_url(@conn, :feed, @user.nickname) <> ".rss" %></guid> + <title><%= @user.nickname <> "'s timeline" %></title> + <updated><%= most_recent_update(@activities, @user) %></updated> + <image><%= logo(@user) %></image> + <link><%= '#{user_feed_url(@conn, :feed, @user.nickname)}.rss' %></link> + + <%= render @view_module, "_author.rss", assigns %> + + <%= if last_activity(@activities) do %> + <link rel="next"><%= '#{user_feed_url(@conn, :feed, @user.nickname)}.rss?max_id=#{last_activity(@activities).id}' %></link> + <% end %> + + <%= for activity <- @activities do %> + <%= render @view_module, "_activity.rss", Map.merge(assigns, prepare_activity(activity)) %> + <% end %> + </channel> +</rss> |