diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/pleroma/activity.ex | 46 | ||||
| -rw-r--r-- | lib/pleroma/object.ex | 46 | ||||
| -rw-r--r-- | lib/pleroma/user.ex | 14 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 35 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/views/user_view.ex | 23 | ||||
| -rw-r--r-- | lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 25 | ||||
| -rw-r--r-- | lib/pleroma/web/mastodon_api/views/app_view.ex | 41 | ||||
| -rw-r--r-- | lib/pleroma/web/mastodon_api/views/status_view.ex | 2 | ||||
| -rw-r--r-- | lib/pleroma/web/oauth/oauth_controller.ex | 12 | ||||
| -rw-r--r-- | lib/pleroma/web/router.ex | 1 | ||||
| -rw-r--r-- | lib/pleroma/web/twitter_api/representers/activity_representer.ex | 15 | 
11 files changed, 212 insertions, 48 deletions
| diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index 3dfabe9f3..bc3f8caba 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -245,4 +245,50 @@ defmodule Pleroma.Activity do      |> where([s], s.actor == ^actor)      |> Repo.all()    end + +  def increase_replies_count(id) do +    Activity +    |> where(id: ^id) +    |> update([a], +      set: [ +        data: +          fragment( +            """ +            jsonb_set(?, '{object, repliesCount}', +              (coalesce((?->'object'->>'repliesCount')::int, 0) + 1)::varchar::jsonb, true) +            """, +            a.data, +            a.data +          ) +      ] +    ) +    |> Repo.update_all([]) +    |> case do +      {1, [activity]} -> activity +      _ -> {:error, "Not found"} +    end +  end + +  def decrease_replies_count(id) do +    Activity +    |> where(id: ^id) +    |> update([a], +      set: [ +        data: +          fragment( +            """ +            jsonb_set(?, '{object, repliesCount}', +              (greatest(0, (?->'object'->>'repliesCount')::int - 1))::varchar::jsonb, true) +            """, +            a.data, +            a.data +          ) +      ] +    ) +    |> Repo.update_all([]) +    |> case do +      {1, [activity]} -> activity +      _ -> {:error, "Not found"} +    end +  end  end diff --git a/lib/pleroma/object.ex b/lib/pleroma/object.ex index 193ae3fa8..8a670645d 100644 --- a/lib/pleroma/object.ex +++ b/lib/pleroma/object.ex @@ -133,4 +133,50 @@ defmodule Pleroma.Object do        e -> e      end    end + +  def increase_replies_count(ap_id) do +    Object +    |> where([o], fragment("?->>'id' = ?::text", o.data, ^to_string(ap_id))) +    |> update([o], +      set: [ +        data: +          fragment( +            """ +            jsonb_set(?, '{repliesCount}', +              (coalesce((?->>'repliesCount')::int, 0) + 1)::varchar::jsonb, true) +            """, +            o.data, +            o.data +          ) +      ] +    ) +    |> Repo.update_all([]) +    |> case do +      {1, [object]} -> set_cache(object) +      _ -> {:error, "Not found"} +    end +  end + +  def decrease_replies_count(ap_id) do +    Object +    |> where([o], fragment("?->>'id' = ?::text", o.data, ^to_string(ap_id))) +    |> update([o], +      set: [ +        data: +          fragment( +            """ +            jsonb_set(?, '{repliesCount}', +              (greatest(0, (?->>'repliesCount')::int - 1))::varchar::jsonb, true) +            """, +            o.data, +            o.data +          ) +      ] +    ) +    |> Repo.update_all([]) +    |> case do +      {1, [object]} -> set_cache(object) +      _ -> {:error, "Not found"} +    end +  end  end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 495f9bdf5..728b00a56 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -60,14 +60,10 @@ defmodule Pleroma.User do      timestamps()    end -  def auth_active?(%User{local: false}), do: true - -  def auth_active?(%User{info: %User.Info{confirmation_pending: false}}), do: true -    def auth_active?(%User{info: %User.Info{confirmation_pending: true}}),      do: !Pleroma.Config.get([:instance, :account_activation_required]) -  def auth_active?(_), do: false +  def auth_active?(%User{}), do: true    def visible_for?(user, for_user \\ nil) @@ -83,17 +79,17 @@ defmodule Pleroma.User do    def superuser?(%User{local: true, info: %User.Info{is_moderator: true}}), do: true    def superuser?(_), do: false -  def avatar_url(user) do +  def avatar_url(user, options \\ []) do      case user.avatar do        %{"url" => [%{"href" => href} | _]} -> href -      _ -> "#{Web.base_url()}/images/avi.png" +      _ -> !options[:no_default] && "#{Web.base_url()}/images/avi.png"      end    end -  def banner_url(user) do +  def banner_url(user, options \\ []) do      case user.info.banner do        %{"url" => [%{"href" => href} | _]} -> href -      _ -> "#{Web.base_url()}/images/banner.png" +      _ -> !options[:no_default] && "#{Web.base_url()}/images/banner.png"      end    end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 80c64ae04..6e1ed7ec9 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -89,6 +89,30 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do      if is_public?(object), do: User.decrease_note_count(actor), else: {:ok, actor}    end +  def increase_replies_count_if_reply(%{ +        "object" => +          %{"inReplyTo" => reply_ap_id, "inReplyToStatusId" => reply_status_id} = object, +        "type" => "Create" +      }) do +    if is_public?(object) do +      Activity.increase_replies_count(reply_status_id) +      Object.increase_replies_count(reply_ap_id) +    end +  end + +  def increase_replies_count_if_reply(_create_data), do: :noop + +  def decrease_replies_count_if_reply(%Object{ +        data: %{"inReplyTo" => reply_ap_id, "inReplyToStatusId" => reply_status_id} = object +      }) do +    if is_public?(object) do +      Activity.decrease_replies_count(reply_status_id) +      Object.decrease_replies_count(reply_ap_id) +    end +  end + +  def decrease_replies_count_if_reply(_object), do: :noop +    def insert(map, local \\ true) when is_map(map) do      with nil <- Activity.normalize(map),           map <- lazy_put_activity_defaults(map), @@ -178,6 +202,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do               additional             ),           {:ok, activity} <- insert(create_data, local), +         _ <- increase_replies_count_if_reply(create_data),           # Changing note count prior to enqueuing federation task in order to avoid           # race conditions on updating user.info           {:ok, _actor} <- increase_note_count_if_public(actor, activity), @@ -329,6 +354,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do             "deleted_activity_id" => activity && activity.id           },           {:ok, activity} <- insert(data, local), +         _ <- decrease_replies_count_if_reply(object),           # Changing note count prior to enqueuing federation task in order to avoid           # race conditions on updating user.info           {:ok, _actor} <- decrease_note_count_if_public(user, object), @@ -711,8 +737,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do      from(        activity in query, -      where: fragment("not ?->>'type' = 'Announce'", activity.data), -      where: fragment("not ? = ANY(?)", activity.actor, ^muted_reblogs) +      where: +        fragment( +          "not ( ?->>'type' = 'Announce' and ? = ANY(?))", +          activity.data, +          activity.actor, +          ^muted_reblogs +        )      )    end diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex index 3d00dcbf2..5926a3294 100644 --- a/lib/pleroma/web/activity_pub/views/user_view.ex +++ b/lib/pleroma/web/activity_pub/views/user_view.ex @@ -87,16 +87,10 @@ defmodule Pleroma.Web.ActivityPub.UserView do          "publicKeyPem" => public_key        },        "endpoints" => endpoints, -      "icon" => %{ -        "type" => "Image", -        "url" => User.avatar_url(user) -      }, -      "image" => %{ -        "type" => "Image", -        "url" => User.banner_url(user) -      },        "tag" => user.info.source_data["tag"] || []      } +    |> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user)) +    |> Map.merge(maybe_make_image(&User.banner_url/2, "image", user))      |> Map.merge(Utils.make_json_ld_header())    end @@ -294,4 +288,17 @@ defmodule Pleroma.Web.ActivityPub.UserView do        map      end    end + +  defp maybe_make_image(func, key, user) do +    if image = func.(user, no_default: true) do +      %{ +        key => %{ +          "type" => "Image", +          "url" => image +        } +      } +    else +      %{} +    end +  end  end diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 6be0f2baf..eee4e7678 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -18,6 +18,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do    alias Pleroma.Web.ActivityPub.Visibility    alias Pleroma.Web.CommonAPI    alias Pleroma.Web.MastodonAPI.AccountView +  alias Pleroma.Web.MastodonAPI.AppView    alias Pleroma.Web.MastodonAPI.FilterView    alias Pleroma.Web.MastodonAPI.ListView    alias Pleroma.Web.MastodonAPI.MastodonAPI @@ -51,16 +52,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do      with cs <- App.register_changeset(%App{}, app_attrs),           false <- cs.changes[:client_name] == @local_mastodon_name,           {:ok, app} <- Repo.insert(cs) do -      res = %{ -        id: app.id |> to_string, -        name: app.client_name, -        client_id: app.client_id, -        client_secret: app.client_secret, -        redirect_uri: app.redirect_uris, -        website: app.website -      } - -      json(conn, res) +      conn +      |> put_view(AppView) +      |> render("show.json", %{app: app})      end    end @@ -132,6 +126,14 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do      json(conn, account)    end +  def verify_app_credentials(%{assigns: %{user: _user, token: token}} = conn, _) do +    with %Token{app: %App{} = app} <- Repo.preload(token, :app) do +      conn +      |> put_view(AppView) +      |> render("short.json", %{app: app}) +    end +  end +    def user(%{assigns: %{user: for_user}} = conn, %{"id" => nickname_or_id}) do      with %User{} = user <- User.get_cached_by_nickname_or_id(nickname_or_id),           true <- User.auth_active?(user) || user.id == for_user.id || User.superuser?(for_user) do @@ -161,6 +163,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do        },        stats: Stats.get_stats(),        thumbnail: Web.base_url() <> "/instance/thumbnail.jpeg", +      languages: ["en"], +      registrations: Pleroma.Config.get([:instance, :registrations_open]), +      # Extra (not present in Mastodon):        max_toot_chars: Keyword.get(instance, :limit)      } diff --git a/lib/pleroma/web/mastodon_api/views/app_view.ex b/lib/pleroma/web/mastodon_api/views/app_view.ex new file mode 100644 index 000000000..f52b693a6 --- /dev/null +++ b/lib/pleroma/web/mastodon_api/views/app_view.ex @@ -0,0 +1,41 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MastodonAPI.AppView do +  use Pleroma.Web, :view + +  alias Pleroma.Web.OAuth.App + +  @vapid_key :web_push_encryption +             |> Application.get_env(:vapid_details, []) +             |> Keyword.get(:public_key) + +  def render("show.json", %{app: %App{} = app}) do +    %{ +      id: app.id |> to_string, +      name: app.client_name, +      client_id: app.client_id, +      client_secret: app.client_secret, +      redirect_uri: app.redirect_uris, +      website: app.website +    } +    |> with_vapid_key() +  end + +  def render("short.json", %{app: %App{website: webiste, client_name: name}}) do +    %{ +      name: name, +      website: webiste +    } +    |> with_vapid_key() +  end + +  defp with_vapid_key(data) do +    if @vapid_key do +      Map.put(data, "vapid_key", @vapid_key) +    else +      data +    end +  end +end diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index 1ca8338cc..200bb453d 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -174,7 +174,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do        content: content,        created_at: created_at,        reblogs_count: announcement_count, -      replies_count: 0, +      replies_count: object["repliesCount"] || 0,        favourites_count: like_count,        reblogged: present?(repeated),        favourited: present?(favorited), diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index d151efe9e..ebb3dd253 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -83,14 +83,18 @@ defmodule Pleroma.Web.OAuth.OAuthController do        end      else        {scopes_issue, _} when scopes_issue in [:unsupported_scopes, :missing_scopes] -> +        # Per https://github.com/tootsuite/mastodon/blob/ +        #   51e154f5e87968d6bb115e053689767ab33e80cd/app/controllers/api/base_controller.rb#L39          conn -        |> put_flash(:error, "Permissions not specified.") +        |> put_flash(:error, "This action is outside the authorized scopes")          |> put_status(:unauthorized)          |> authorize(auth_params)        {:auth_active, false} -> +        # Per https://github.com/tootsuite/mastodon/blob/ +        #   51e154f5e87968d6bb115e053689767ab33e80cd/app/controllers/api/base_controller.rb#L76          conn -        |> put_flash(:error, "Account confirmation pending.") +        |> put_flash(:error, "Your login is missing a confirmed e-mail address")          |> put_status(:forbidden)          |> authorize(auth_params) @@ -149,9 +153,11 @@ defmodule Pleroma.Web.OAuth.OAuthController do        json(conn, response)      else        {:auth_active, false} -> +        # Per https://github.com/tootsuite/mastodon/blob/ +        #   51e154f5e87968d6bb115e053689767ab33e80cd/app/controllers/api/base_controller.rb#L76          conn          |> put_status(:forbidden) -        |> json(%{error: "Account confirmation pending"}) +        |> json(%{error: "Your login is missing a confirmed e-mail address"})        _error ->          put_status(conn, 400) diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index befd382ba..32e5f7644 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -328,6 +328,7 @@ defmodule Pleroma.Web.Router do      get("/instance", MastodonAPIController, :masto_instance)      get("/instance/peers", MastodonAPIController, :peers)      post("/apps", MastodonAPIController, :create_app) +    get("/apps/verify_credentials", MastodonAPIController, :verify_app_credentials)      get("/custom_emojis", MastodonAPIController, :custom_emojis)      get("/statuses/:id/card", MastodonAPIController, :status_card) diff --git a/lib/pleroma/web/twitter_api/representers/activity_representer.ex b/lib/pleroma/web/twitter_api/representers/activity_representer.ex deleted file mode 100644 index 55c612ddd..000000000 --- a/lib/pleroma/web/twitter_api/representers/activity_representer.ex +++ /dev/null @@ -1,15 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -# FIXME: Remove this module? -# THIS MODULE IS DEPRECATED! DON'T USE IT! -# USE THE Pleroma.Web.TwitterAPI.Views.ActivityView MODULE! -defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do -  def to_map(activity, opts) do -    Pleroma.Web.TwitterAPI.ActivityView.render( -      "activity.json", -      Map.put(opts, :activity, activity) -    ) -  end -end | 
