Merge branch 'rework-emoji-management' into 'develop'
authorkaniini <nenolod@gmail.com>
Mon, 22 Apr 2019 02:07:19 +0000 (02:07 +0000)
committerkaniini <nenolod@gmail.com>
Mon, 22 Apr 2019 02:07:19 +0000 (02:07 +0000)
Remove finmoji and add a way to download emojis in packs

Closes #817 and #821

See merge request pleroma/pleroma!1073

CHANGELOG.md
docs/api/differences_in_mastoapi_responses.md
lib/pleroma/web/mastodon_api/mastodon_api.ex
lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
lib/pleroma/web/mastodon_api/views/status_view.ex
lib/pleroma/web/oauth/oauth_controller.ex
test/web/mastodon_api/mastodon_api_controller_test.exs
test/web/oauth/oauth_controller_test.exs

index c778e02340554ead809290b0ca4cf0fc795b83f6..ed078bc6966f457ccd6898302164410ed00b94b9 100644 (file)
@@ -69,10 +69,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - MediaProxy: Parse name from content disposition headers even for non-whitelisted types
 - MediaProxy: S3 link encoding
 - Rich Media: Reject any data which cannot be explicitly encoded into JSON
+- Pleroma API: Importing follows from Mastodon 2.8+
 - Mastodon API: `/api/v1/favourites` serving only public activities
 - Mastodon API: Reblogs having `in_reply_to_id` - `null` even when they are replies
 - Mastodon API: Streaming API broadcasting wrong activity id
 - Mastodon API: 500 errors when requesting a card for a private conversation
+- Mastodon API: Handling of `reblogs` in `/api/v1/accounts/:id/follow`
+- Mastodon API: Correct `reblogged`, `favourited`, and `bookmarked` values in the reblog status JSON
 
 ## [0.9.9999] - 2019-04-05
 ### Security
index ed3fd9b671e337ecc85c512487a1401eaa203671..63644fc56a4a013d2b426ee2a5c1e3a5af9d8110 100644 (file)
@@ -58,3 +58,4 @@ Has these additional fields under the `pleroma` object:
 Additional parameters can be added to the JSON body/Form data:
 
 - `preview`: boolean, if set to `true` the post won't be actually posted, but the status entitiy would still be rendered back. This could be useful for previewing rich text/custom emoji, for example.
+- `content_type`: string, contain the MIME type of the status, it is transformed into HTML by the backend. You can get the list of the supported MIME types with the nodeinfo endpoint.
index 382f07e6b1f930536ed3c3f7dc0d6c22ec473725..3a3ec7c2a05077054afa2e53fc719a554b9d3840 100644 (file)
@@ -7,6 +7,31 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
   alias Pleroma.Pagination
   alias Pleroma.ScheduledActivity
   alias Pleroma.User
+  alias Pleroma.Web.CommonAPI
+
+  def follow(follower, followed, params \\ %{}) do
+    options = cast_params(params)
+    reblogs = options[:reblogs]
+
+    result =
+      if not User.following?(follower, followed) do
+        CommonAPI.follow(follower, followed)
+      else
+        {:ok, follower, followed, nil}
+      end
+
+    with {:ok, follower, followed, _} <- result do
+      reblogs
+      |> case do
+        false -> CommonAPI.hide_reblogs(follower, followed)
+        _ -> CommonAPI.show_reblogs(follower, followed)
+      end
+      |> case do
+        {:ok, follower} -> {:ok, follower}
+        _ -> {:ok, follower}
+      end
+    end
+  end
 
   def get_followers(user, params \\ %{}) do
     user
@@ -37,7 +62,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
 
   defp cast_params(params) do
     param_types = %{
-      exclude_types: {:array, :string}
+      exclude_types: {:array, :string},
+      reblogs: :boolean
     }
 
     changeset = cast({%{}, param_types}, params, Map.keys(param_types))
index 2a81dcc674e98df6db136b3aea5803c075cd1a87..d271d3786b1322f88538dfb568eeb79e73581867 100644 (file)
@@ -338,7 +338,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
   end
 
   def get_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
-    with %Activity{} = activity <- Activity.get_by_id(id),
+    with %Activity{} = activity <- Activity.get_by_id_with_object(id),
          true <- Visibility.visible_for_user?(activity, user) do
       conn
       |> put_view(StatusView)
@@ -487,7 +487,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
   end
 
   def reblog_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
-    with {:ok, announce, _activity} <- CommonAPI.repeat(ap_id_or_id, user) do
+    with {:ok, announce, _activity} <- CommonAPI.repeat(ap_id_or_id, user),
+         %Activity{} = announce <- Activity.normalize(announce.data) do
       conn
       |> put_view(StatusView)
       |> try_render("status.json", %{activity: announce, for: user, as: :activity})
@@ -496,7 +497,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
 
   def unreblog_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
     with {:ok, _unannounce, %{data: %{"id" => id}}} <- CommonAPI.unrepeat(ap_id_or_id, user),
-         %Activity{} = activity <- Activity.get_create_by_object_ap_id(id) do
+         %Activity{} = activity <- Activity.get_create_by_object_ap_id_with_object(id) do
       conn
       |> put_view(StatusView)
       |> try_render("status.json", %{activity: activity, for: user, as: :activity})
@@ -821,8 +822,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
   def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
     with {_, %User{} = followed} <- {:followed, User.get_cached_by_id(id)},
          {_, true} <- {:followed, follower.id != followed.id},
-         false <- User.following?(follower, followed),
-         {:ok, follower, followed, _} <- CommonAPI.follow(follower, followed) do
+         {:ok, follower} <- MastodonAPI.follow(follower, followed, conn.params) do
       conn
       |> put_view(AccountView)
       |> render("relationship.json", %{user: follower, target: followed})
@@ -830,19 +830,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
       {:followed, _} ->
         {:error, :not_found}
 
-      true ->
-        followed = User.get_cached_by_id(id)
-
-        {:ok, follower} =
-          case conn.params["reblogs"] do
-            true -> CommonAPI.show_reblogs(follower, followed)
-            false -> CommonAPI.hide_reblogs(follower, followed)
-          end
-
-        conn
-        |> put_view(AccountView)
-        |> render("relationship.json", %{user: follower, target: followed})
-
       {:error, message} ->
         conn
         |> put_resp_content_type("application/json")
index f8961eb6c08d0c1509ca3d82f13e9c7b7507bf06..17c33080bb55fed51f309201d454e20b78a5bc70 100644 (file)
@@ -83,6 +83,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
     reblogged_activity = Activity.get_create_by_object_ap_id(object)
     reblogged = render("status.json", Map.put(opts, :activity, reblogged_activity))
 
+    activity_object = Object.normalize(activity)
+    favorited = opts[:for] && opts[:for].ap_id in (activity_object.data["likes"] || [])
+    bookmarked = opts[:for] && activity_object.data["id"] in opts[:for].bookmarks
+
     mentions =
       activity.recipients
       |> Enum.map(fn ap_id -> User.get_cached_by_ap_id(ap_id) end)
@@ -103,8 +107,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
       replies_count: 0,
       favourites_count: 0,
       reblogged: reblogged?(reblogged_activity, opts[:for]),
-      favourited: false,
-      bookmarked: false,
+      favourited: present?(favorited),
+      bookmarked: present?(bookmarked),
       muted: false,
       pinned: pinned?(activity, user),
       sensitive: false,
index 9874bac2319bdc706b9cd6cc348cb0f3243e9af0..5ea04635dfe823a22e34d7cd24ce4b6311894bdc 100644 (file)
@@ -23,6 +23,12 @@ defmodule Pleroma.Web.OAuth.OAuthController do
 
   action_fallback(Pleroma.Web.OAuth.FallbackController)
 
+  # Note: this definition is only called from error-handling methods with `conn.params` as 2nd arg
+  def authorize(conn, %{"authorization" => _} = params) do
+    {auth_attrs, params} = Map.pop(params, "authorization")
+    authorize(conn, Map.merge(params, auth_attrs))
+  end
+
   def authorize(%{assigns: %{token: %Token{} = token}} = conn, params) do
     if ControllerHelper.truthy_param?(params["force_login"]) do
       do_authorize(conn, params)
@@ -44,21 +50,20 @@ defmodule Pleroma.Web.OAuth.OAuthController do
 
   def authorize(conn, params), do: do_authorize(conn, params)
 
-  defp do_authorize(conn, %{"authorization" => auth_attrs}), do: do_authorize(conn, auth_attrs)
-
-  defp do_authorize(conn, auth_attrs) do
-    app = Repo.get_by(App, client_id: auth_attrs["client_id"])
+  defp do_authorize(conn, params) do
+    app = Repo.get_by(App, client_id: params["client_id"])
     available_scopes = (app && app.scopes) || []
-    scopes = oauth_scopes(auth_attrs, nil) || available_scopes
+    scopes = oauth_scopes(params, nil) || available_scopes
 
+    # Note: `params` might differ from `conn.params`; use `@params` not `@conn.params` in template
     render(conn, Authenticator.auth_template(), %{
-      response_type: auth_attrs["response_type"],
-      client_id: auth_attrs["client_id"],
+      response_type: params["response_type"],
+      client_id: params["client_id"],
       available_scopes: available_scopes,
       scopes: scopes,
-      redirect_uri: auth_attrs["redirect_uri"],
-      state: auth_attrs["state"],
-      params: auth_attrs
+      redirect_uri: params["redirect_uri"],
+      state: params["state"],
+      params: params
     })
   end
 
index 786af2088d202f59bb94e03bf19427f44d3791a3..fae5af837fd164862130e270cc396450a9d7b6bd 100644 (file)
@@ -1021,6 +1021,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
       user1 = insert(:user)
       user2 = insert(:user)
       user3 = insert(:user)
+      CommonAPI.favorite(activity.id, user2)
+      {:ok, user2} = User.bookmark(user2, activity.data["object"]["id"])
       {:ok, reblog_activity1, _object} = CommonAPI.repeat(activity.id, user1)
       {:ok, _, _object} = CommonAPI.repeat(activity.id, user2)
 
@@ -1031,7 +1033,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
 
       assert %{
                "reblog" => %{"id" => id, "reblogged" => false, "reblogs_count" => 2},
-               "reblogged" => false
+               "reblogged" => false,
+               "favourited" => false,
+               "bookmarked" => false
              } = json_response(conn_res, 200)
 
       conn_res =
@@ -1041,7 +1045,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
 
       assert %{
                "reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 2},
-               "reblogged" => true
+               "reblogged" => true,
+               "favourited" => true,
+               "bookmarked" => true
              } = json_response(conn_res, 200)
 
       assert to_string(activity.id) == id
@@ -1620,6 +1626,44 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
     assert id == to_string(other_user.id)
   end
 
+  test "following without reblogs" do
+    follower = insert(:user)
+    followed = insert(:user)
+    other_user = insert(:user)
+
+    conn =
+      build_conn()
+      |> assign(:user, follower)
+      |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=false")
+
+    assert %{"showing_reblogs" => false} = json_response(conn, 200)
+
+    {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hey"})
+    {:ok, reblog, _} = CommonAPI.repeat(activity.id, followed)
+
+    conn =
+      build_conn()
+      |> assign(:user, User.get_cached_by_id(follower.id))
+      |> get("/api/v1/timelines/home")
+
+    assert [] == json_response(conn, 200)
+
+    conn =
+      build_conn()
+      |> assign(:user, follower)
+      |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=true")
+
+    assert %{"showing_reblogs" => true} = json_response(conn, 200)
+
+    conn =
+      build_conn()
+      |> assign(:user, User.get_cached_by_id(follower.id))
+      |> get("/api/v1/timelines/home")
+
+    expected_activity_id = reblog.id
+    assert [%{"id" => ^expected_activity_id}] = json_response(conn, 200)
+  end
+
   test "following / unfollowing errors" do
     user = insert(:user)
 
index fb505fab32ea4986120a64c226ca2b4c2f37650a..6e96537ecc9759834aa5dc10287ad71902303c55 100644 (file)
@@ -365,6 +365,27 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
       assert html_response(conn, 200) =~ ~s(type="submit")
     end
 
+    test "properly handles internal calls with `authorization`-wrapped params", %{
+      app: app,
+      conn: conn
+    } do
+      conn =
+        get(
+          conn,
+          "/oauth/authorize",
+          %{
+            "authorization" => %{
+              "response_type" => "code",
+              "client_id" => app.client_id,
+              "redirect_uri" => app.redirect_uris,
+              "scope" => "read"
+            }
+          }
+        )
+
+      assert html_response(conn, 200) =~ ~s(type="submit")
+    end
+
     test "renders authentication page if user is already authenticated but `force_login` is tru-ish",
          %{app: app, conn: conn} do
       token = insert(:oauth_token, app_id: app.id)