From: kaniini Date: Mon, 22 Apr 2019 02:07:19 +0000 (+0000) Subject: Merge branch 'rework-emoji-management' into 'develop' X-Git-Url: http://git.squeep.com/?a=commitdiff_plain;h=7fcbda702e76b6390076c28832f5aea80086d15a;hp=3cefdc62e0dda75985221853fb123572d6fc068b;p=akkoma Merge branch 'rework-emoji-management' into 'develop' Remove finmoji and add a way to download emojis in packs Closes #817 and #821 See merge request pleroma/pleroma!1073 --- diff --git a/CHANGELOG.md b/CHANGELOG.md index c778e0234..ed078bc69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/docs/api/differences_in_mastoapi_responses.md b/docs/api/differences_in_mastoapi_responses.md index ed3fd9b67..63644fc56 100644 --- a/docs/api/differences_in_mastoapi_responses.md +++ b/docs/api/differences_in_mastoapi_responses.md @@ -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. diff --git a/lib/pleroma/web/mastodon_api/mastodon_api.ex b/lib/pleroma/web/mastodon_api/mastodon_api.ex index 382f07e6b..3a3ec7c2a 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api.ex @@ -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)) diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 2a81dcc67..d271d3786 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -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") diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index f8961eb6c..17c33080b 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -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, diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index 9874bac23..5ea04635d 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -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 diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs index 786af2088..fae5af837 100644 --- a/test/web/mastodon_api/mastodon_api_controller_test.exs +++ b/test/web/mastodon_api/mastodon_api_controller_test.exs @@ -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) diff --git a/test/web/oauth/oauth_controller_test.exs b/test/web/oauth/oauth_controller_test.exs index fb505fab3..6e96537ec 100644 --- a/test/web/oauth/oauth_controller_test.exs +++ b/test/web/oauth/oauth_controller_test.exs @@ -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)