diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/pleroma/activity.ex | 8 | ||||
| -rw-r--r-- | lib/pleroma/html.ex | 14 | ||||
| -rw-r--r-- | lib/pleroma/notification.ex | 36 | ||||
| -rw-r--r-- | lib/pleroma/pagination.ex | 78 | ||||
| -rw-r--r-- | lib/pleroma/user.ex | 5 | ||||
| -rw-r--r-- | lib/pleroma/web/mastodon_api/mastodon_api.ex | 48 | ||||
| -rw-r--r-- | lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 2 | 
7 files changed, 132 insertions, 59 deletions
| diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index 79dc26b01..de0e66681 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -22,6 +22,10 @@ defmodule Pleroma.Activity do      "Like" => "favourite"    } +  @mastodon_to_ap_notification_types for {k, v} <- @mastodon_notification_types, +                                         into: %{}, +                                         do: {v, k} +    schema "activities" do      field(:data, :map)      field(:local, :boolean, default: true) @@ -126,6 +130,10 @@ defmodule Pleroma.Activity do    def mastodon_notification_type(%Activity{}), do: nil +  def from_mastodon_notification_type(type) do +    Map.get(@mastodon_to_ap_notification_types, type) +  end +    def all_by_actor_and_id(actor, status_ids \\ [])    def all_by_actor_and_id(_actor, []), do: [] diff --git a/lib/pleroma/html.ex b/lib/pleroma/html.ex index 05253157e..5b152d926 100644 --- a/lib/pleroma/html.ex +++ b/lib/pleroma/html.ex @@ -95,6 +95,13 @@ defmodule Pleroma.HTML.Scrubber.TwitterText do    Meta.allow_tag_with_uri_attributes("a", ["href", "data-user", "data-tag"], @valid_schemes)    Meta.allow_tag_with_these_attributes("a", ["name", "title", "class"]) +  Meta.allow_tag_with_this_attribute_values("a", "rel", [ +    "tag", +    "nofollow", +    "noopener", +    "noreferrer" +  ]) +    # paragraphs and linebreaks    Meta.allow_tag_with_these_attributes("br", [])    Meta.allow_tag_with_these_attributes("p", []) @@ -137,6 +144,13 @@ defmodule Pleroma.HTML.Scrubber.Default do    Meta.allow_tag_with_uri_attributes("a", ["href", "data-user", "data-tag"], @valid_schemes)    Meta.allow_tag_with_these_attributes("a", ["name", "title", "class"]) +  Meta.allow_tag_with_this_attribute_values("a", "rel", [ +    "tag", +    "nofollow", +    "noopener", +    "noreferrer" +  ]) +    Meta.allow_tag_with_these_attributes("abbr", ["title"])    Meta.allow_tag_with_these_attributes("b", []) diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index 765191275..a98649b63 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -7,6 +7,7 @@ defmodule Pleroma.Notification do    alias Pleroma.Activity    alias Pleroma.Notification +  alias Pleroma.Pagination    alias Pleroma.Repo    alias Pleroma.User    alias Pleroma.Web.CommonAPI @@ -28,36 +29,17 @@ defmodule Pleroma.Notification do      |> cast(attrs, [:seen])    end -  # TODO: Make generic and unify (see activity_pub.ex) -  defp restrict_max(query, %{"max_id" => max_id}) do -    from(activity in query, where: activity.id < ^max_id) +  def for_user_query(user) do +    Notification +    |> where(user_id: ^user.id) +    |> join(:inner, [n], activity in assoc(n, :activity)) +    |> preload(:activity)    end -  defp restrict_max(query, _), do: query - -  defp restrict_since(query, %{"since_id" => since_id}) do -    from(activity in query, where: activity.id > ^since_id) -  end - -  defp restrict_since(query, _), do: query -    def for_user(user, opts \\ %{}) do -    query = -      from( -        n in Notification, -        where: n.user_id == ^user.id, -        order_by: [desc: n.id], -        join: activity in assoc(n, :activity), -        preload: [activity: activity], -        limit: 20 -      ) - -    query = -      query -      |> restrict_since(opts) -      |> restrict_max(opts) - -    Repo.all(query) +    user +    |> for_user_query() +    |> Pagination.fetch_paginated(opts)    end    def set_read_up_to(%{id: user_id} = _user, id) do diff --git a/lib/pleroma/pagination.ex b/lib/pleroma/pagination.ex new file mode 100644 index 000000000..7c864deef --- /dev/null +++ b/lib/pleroma/pagination.ex @@ -0,0 +1,78 @@ +defmodule Pleroma.Pagination do +  @moduledoc """ +  Implements Mastodon-compatible pagination. +  """ + +  import Ecto.Query +  import Ecto.Changeset + +  alias Pleroma.Repo + +  @default_limit 20 + +  def fetch_paginated(query, params) do +    options = cast_params(params) + +    query +    |> paginate(options) +    |> Repo.all() +    |> enforce_order(options) +  end + +  def paginate(query, options) do +    query +    |> restrict(:min_id, options) +    |> restrict(:since_id, options) +    |> restrict(:max_id, options) +    |> restrict(:order, options) +    |> restrict(:limit, options) +  end + +  defp cast_params(params) do +    param_types = %{ +      min_id: :string, +      since_id: :string, +      max_id: :string, +      limit: :integer +    } + +    changeset = cast({%{}, param_types}, params, Map.keys(param_types)) +    changeset.changes +  end + +  defp restrict(query, :min_id, %{min_id: min_id}) do +    where(query, [q], q.id > ^min_id) +  end + +  defp restrict(query, :since_id, %{since_id: since_id}) do +    where(query, [q], q.id > ^since_id) +  end + +  defp restrict(query, :max_id, %{max_id: max_id}) do +    where(query, [q], q.id < ^max_id) +  end + +  defp restrict(query, :order, %{min_id: _}) do +    order_by(query, [u], fragment("? asc nulls last", u.id)) +  end + +  defp restrict(query, :order, _options) do +    order_by(query, [u], fragment("? desc nulls last", u.id)) +  end + +  defp restrict(query, :limit, options) do +    limit = Map.get(options, :limit, @default_limit) + +    query +    |> limit(^limit) +  end + +  defp restrict(query, _, _), do: query + +  defp enforce_order(result, %{min_id: _}) do +    result +    |> Enum.reverse() +  end + +  defp enforce_order(result, _), do: result +end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 6de766fc1..fb3bd121d 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -1159,9 +1159,12 @@ defmodule Pleroma.User do      if !is_nil(user) and !User.needs_update?(user) do        user      else +      # Whether to fetch initial posts for the user (if it's a new user & the fetching is enabled) +      should_fetch_initial = is_nil(user) and Pleroma.Config.get([:fetch_initial_posts, :enabled]) +        user = fetch_by_ap_id(ap_id) -      if Pleroma.Config.get([:fetch_initial_posts, :enabled]) do +      if should_fetch_initial do          with %User{} = user do            {:ok, _} = Task.start(__MODULE__, :fetch_initial_posts, [user])          end diff --git a/lib/pleroma/web/mastodon_api/mastodon_api.ex b/lib/pleroma/web/mastodon_api/mastodon_api.ex index 54cb6c97a..08ea5f967 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api.ex @@ -2,61 +2,49 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do    import Ecto.Query    import Ecto.Changeset -  alias Pleroma.Repo +  alias Pleroma.Activity +  alias Pleroma.Notification +  alias Pleroma.Pagination    alias Pleroma.User -  @default_limit 20 -    def get_followers(user, params \\ %{}) do      user      |> User.get_followers_query() -    |> paginate(params) -    |> Repo.all() +    |> Pagination.fetch_paginated(params)    end    def get_friends(user, params \\ %{}) do      user      |> User.get_friends_query() -    |> paginate(params) -    |> Repo.all() +    |> Pagination.fetch_paginated(params)    end -  def paginate(query, params \\ %{}) do +  def get_notifications(user, params \\ %{}) do      options = cast_params(params) -    query -    |> restrict(:max_id, options) -    |> restrict(:since_id, options) -    |> restrict(:limit, options) -    |> order_by([u], fragment("? desc nulls last", u.id)) +    user +    |> Notification.for_user_query() +    |> restrict(:exclude_types, options) +    |> Pagination.fetch_paginated(params)    end -  def cast_params(params) do +  defp cast_params(params) do      param_types = %{ -      max_id: :string, -      since_id: :string, -      limit: :integer +      exclude_types: {:array, :string}      }      changeset = cast({%{}, param_types}, params, Map.keys(param_types))      changeset.changes    end -  defp restrict(query, :max_id, %{max_id: max_id}) do -    query -    |> where([q], q.id < ^max_id) -  end - -  defp restrict(query, :since_id, %{since_id: since_id}) do -    query -    |> where([q], q.id > ^since_id) -  end - -  defp restrict(query, :limit, options) do -    limit = Map.get(options, :limit, @default_limit) +  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)      query -    |> limit(^limit) +    |> where([q, a], not fragment("? @> ARRAY[?->>'type']::varchar[]", ^ap_types, a.data))    end    defp restrict(query, _, _), do: query diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 952aa2453..2eb1da561 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -502,7 +502,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do    end    def notifications(%{assigns: %{user: user}} = conn, params) do -    notifications = Notification.for_user(user, params) +    notifications = MastodonAPI.get_notifications(user, params)      conn      |> add_link_headers(:notifications, notifications) | 
