diff options
18 files changed, 484 insertions, 238 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 diff --git a/priv/repo/migrations/20190325215156_update_status_reply_count.exs b/priv/repo/migrations/20190325215156_update_status_reply_count.exs new file mode 100644 index 000000000..50f1fe10b --- /dev/null +++ b/priv/repo/migrations/20190325215156_update_status_reply_count.exs @@ -0,0 +1,48 @@ +defmodule Pleroma.Repo.Migrations.UpdateStatusReplyCount do + use Ecto.Migration + + @public "https://www.w3.org/ns/activitystreams#Public" + + def up do + execute(""" + WITH reply_count AS ( + SELECT count(*) AS count, data->>'inReplyTo' AS ap_id + FROM objects + WHERE + data->>'inReplyTo' IS NOT NULL AND + data->>'type' = 'Note' AND ( + data->'cc' ? '#{@public}' OR + data->'to' ? '#{@public}') + GROUP BY data->>'inReplyTo' + ) + UPDATE objects AS o + SET "data" = jsonb_set(o.data, '{repliesCount}', reply_count.count::varchar::jsonb, true) + FROM reply_count + WHERE reply_count.ap_id = o.data->>'id'; + """) + + execute(""" + WITH reply_count AS (SELECT + count(*) as count, + data->'object'->>'inReplyTo' AS ap_id + FROM + activities + WHERE + data->'object'->>'inReplyTo' IS NOT NULL AND + data->'object'->>'type' = 'Note' AND ( + data->'object'->'cc' ? '#{@public}' OR + data->'object'->'to' ? '#{@public}') + GROUP BY + data->'object'->>'inReplyTo' + ) + UPDATE activities AS a + SET "data" = jsonb_set(a.data, '{object, repliesCount}', reply_count.count::varchar::jsonb, true) + FROM reply_count + WHERE reply_count.ap_id = a.data->'object'->>'id'; + """) + end + + def down do + :noop + end +end diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index 96ad64e62..ac5fbe0a9 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -232,6 +232,39 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do user = Repo.get(User, user.id) assert user.info.note_count == 2 end + + test "increases replies count" do + user = insert(:user) + user2 = insert(:user) + + {:ok, activity} = CommonAPI.post(user, %{"status" => "1", "visibility" => "public"}) + ap_id = activity.data["id"] + reply_data = %{"status" => "1", "in_reply_to_status_id" => activity.id} + + # public + {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "public")) + assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id) + assert data["object"]["repliesCount"] == 1 + assert object.data["repliesCount"] == 1 + + # unlisted + {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "unlisted")) + assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id) + assert data["object"]["repliesCount"] == 2 + assert object.data["repliesCount"] == 2 + + # private + {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "private")) + assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id) + assert data["object"]["repliesCount"] == 2 + assert object.data["repliesCount"] == 2 + + # direct + {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "direct")) + assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id) + assert data["object"]["repliesCount"] == 2 + assert object.data["repliesCount"] == 2 + end end describe "fetch activities for recipients" do @@ -461,7 +494,21 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do activities = ActivityPub.fetch_activities([], %{"muting_user" => user}) - refute Enum.member?(activities, activity) + refute Enum.any?(activities, fn %{id: id} -> id == activity.id end) + end + + test "returns reblogs for users for whom reblogs have not been muted" do + activity = insert(:note_activity) + user = insert(:user) + booster = insert(:user) + {:ok, user} = CommonAPI.hide_reblogs(user, booster) + {:ok, user} = CommonAPI.show_reblogs(user, booster) + + {:ok, activity, _} = CommonAPI.repeat(activity.id, booster) + + activities = ActivityPub.fetch_activities([], %{"muting_user" => user}) + + assert Enum.any?(activities, fn %{id: id} -> id == activity.id end) end end @@ -751,6 +798,40 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do assert user.ap_id in delete.data["to"] end + + test "decreases reply count" do + user = insert(:user) + user2 = insert(:user) + + {:ok, activity} = CommonAPI.post(user, %{"status" => "1", "visibility" => "public"}) + reply_data = %{"status" => "1", "in_reply_to_status_id" => activity.id} + ap_id = activity.data["id"] + + {:ok, public_reply} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "public")) + {:ok, unlisted_reply} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "unlisted")) + {:ok, private_reply} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "private")) + {:ok, direct_reply} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "direct")) + + _ = CommonAPI.delete(direct_reply.id, user2) + assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id) + assert data["object"]["repliesCount"] == 2 + assert object.data["repliesCount"] == 2 + + _ = CommonAPI.delete(private_reply.id, user2) + assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id) + assert data["object"]["repliesCount"] == 2 + assert object.data["repliesCount"] == 2 + + _ = CommonAPI.delete(public_reply.id, user2) + assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id) + assert data["object"]["repliesCount"] == 1 + assert object.data["repliesCount"] == 1 + + _ = CommonAPI.delete(unlisted_reply.id, user2) + assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id) + assert data["object"]["repliesCount"] == 0 + assert object.data["repliesCount"] == 0 + end end describe "timeline post-processing" do @@ -789,6 +870,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do activities = ActivityPub.fetch_activities([user1.ap_id | user1.following]) + private_activity_1 = Activity.get_by_ap_id_with_object(private_activity_1.data["id"]) assert [public_activity, private_activity_1, private_activity_3] == activities assert length(activities) == 3 diff --git a/test/web/activity_pub/views/user_view_test.exs b/test/web/activity_pub/views/user_view_test.exs index 0bc1d4728..9fb9455d2 100644 --- a/test/web/activity_pub/views/user_view_test.exs +++ b/test/web/activity_pub/views/user_view_test.exs @@ -16,6 +16,29 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do assert String.contains?(result["publicKey"]["publicKeyPem"], "BEGIN PUBLIC KEY") end + test "Does not add an avatar image if the user hasn't set one" do + user = insert(:user) + {:ok, user} = Pleroma.Web.WebFinger.ensure_keys_present(user) + + result = UserView.render("user.json", %{user: user}) + refute result["icon"] + refute result["image"] + + user = + insert(:user, + avatar: %{"url" => [%{"href" => "https://someurl"}]}, + info: %{ + banner: %{"url" => [%{"href" => "https://somebanner"}]} + } + ) + + {:ok, user} = Pleroma.Web.WebFinger.ensure_keys_present(user) + + result = UserView.render("user.json", %{user: user}) + assert result["icon"]["url"] == "https://someurl" + assert result["image"]["url"] == "https://somebanner" + end + describe "endpoints" do test "local users have a usable endpoints structure" do user = insert(:user) diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs index b2302422b..d9bcbf5a9 100644 --- a/test/web/mastodon_api/mastodon_api_controller_test.exs +++ b/test/web/mastodon_api/mastodon_api_controller_test.exs @@ -14,7 +14,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.CommonAPI alias Pleroma.Web.MastodonAPI.FilterView + alias Pleroma.Web.OAuth.App alias Pleroma.Web.OStatus + alias Pleroma.Web.Push alias Pleroma.Web.TwitterAPI.TwitterAPI import Pleroma.Factory import ExUnit.CaptureLog @@ -332,6 +334,53 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do assert id == to_string(user.id) end + test "apps/verify_credentials", %{conn: conn} do + token = insert(:oauth_token) + + conn = + conn + |> assign(:user, token.user) + |> assign(:token, token) + |> get("/api/v1/apps/verify_credentials") + + app = Repo.preload(token, :app).app + + expected = %{ + "name" => app.client_name, + "website" => app.website, + "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key) + } + + assert expected == json_response(conn, 200) + end + + test "creates an oauth app", %{conn: conn} do + user = insert(:user) + app_attrs = build(:oauth_app) + + conn = + conn + |> assign(:user, user) + |> post("/api/v1/apps", %{ + client_name: app_attrs.client_name, + redirect_uris: app_attrs.redirect_uris + }) + + [app] = Repo.all(App) + + expected = %{ + "name" => app.client_name, + "website" => app.website, + "client_id" => app.client_id, + "client_secret" => app.client_secret, + "id" => app.id |> to_string(), + "redirect_uri" => app.redirect_uris, + "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key) + } + + assert expected == json_response(conn, 200) + end + test "get a status", %{conn: conn} do activity = insert(:note_activity) @@ -1808,6 +1857,27 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do end test "get instance information", %{conn: conn} do + conn = get(conn, "/api/v1/instance") + assert result = json_response(conn, 200) + + # Note: not checking for "max_toot_chars" since it's optional + assert %{ + "uri" => _, + "title" => _, + "description" => _, + "version" => _, + "email" => _, + "urls" => %{ + "streaming_api" => _ + }, + "stats" => _, + "thumbnail" => _, + "languages" => _, + "registrations" => _ + } = result + end + + test "get instance stats", %{conn: conn} do user = insert(:user, %{local: true}) user2 = insert(:user, %{local: true}) diff --git a/test/web/oauth/oauth_controller_test.exs b/test/web/oauth/oauth_controller_test.exs index ff1e56fe9..84ec7b4ee 100644 --- a/test/web/oauth/oauth_controller_test.exs +++ b/test/web/oauth/oauth_controller_test.exs @@ -87,7 +87,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do assert result =~ app.redirect_uris # Error message - assert result =~ "Permissions not specified" + assert result =~ "This action is outside the authorized scopes" end test "returns 401 for scopes beyond app scopes", %{conn: conn} do @@ -113,7 +113,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do assert result =~ app.redirect_uris # Error message - assert result =~ "Permissions not specified" + assert result =~ "This action is outside the authorized scopes" end test "issues a token for an all-body request" do diff --git a/test/web/twitter_api/representers/activity_representer_test.exs b/test/web/twitter_api/representers/activity_representer_test.exs deleted file mode 100644 index d154385a0..000000000 --- a/test/web/twitter_api/representers/activity_representer_test.exs +++ /dev/null @@ -1,170 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenterTest do - use Pleroma.DataCase - alias Pleroma.Activity - alias Pleroma.Object - alias Pleroma.User - alias Pleroma.Web.ActivityPub.ActivityPub - alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter - alias Pleroma.Web.TwitterAPI.Representers.ObjectRepresenter - alias Pleroma.Web.TwitterAPI.UserView - import Pleroma.Factory - - test "a like activity" do - user = insert(:user) - note_activity = insert(:note_activity) - object = Object.get_by_ap_id(note_activity.data["object"]["id"]) - - {:ok, like_activity, _object} = ActivityPub.like(user, object) - - status = - ActivityRepresenter.to_map(like_activity, %{user: user, liked_activity: note_activity}) - - assert status["id"] == like_activity.id - assert status["in_reply_to_status_id"] == note_activity.id - - note_activity = Activity.get_by_ap_id(note_activity.data["id"]) - activity_actor = Repo.get_by(User, ap_id: note_activity.data["actor"]) - liked_status = ActivityRepresenter.to_map(note_activity, %{user: activity_actor, for: user}) - assert liked_status["favorited"] == true - assert status["activity_type"] == "like" - end - - test "an activity" do - user = insert(:user) - # {:ok, mentioned_user } = UserBuilder.insert(%{nickname: "shp", ap_id: "shp"}) - mentioned_user = insert(:user, %{nickname: "shp"}) - - # {:ok, follower} = UserBuilder.insert(%{following: [User.ap_followers(user)]}) - follower = insert(:user, %{following: [User.ap_followers(user)]}) - - object = %Object{ - data: %{ - "type" => "Image", - "url" => [ - %{ - "type" => "Link", - "mediaType" => "image/jpg", - "href" => "http://example.org/image.jpg" - } - ], - "uuid" => 1 - } - } - - content_html = - "<script>alert('YAY')</script>Some :2hu: content mentioning <a href='#{mentioned_user.ap_id}'>@shp</shp>" - - content = HtmlSanitizeEx.strip_tags(content_html) - date = DateTime.from_naive!(~N[2016-05-24 13:26:08.003], "Etc/UTC") |> DateTime.to_iso8601() - - {:ok, convo_object} = Object.context_mapping("2hu") |> Repo.insert() - - to = [ - User.ap_followers(user), - "https://www.w3.org/ns/activitystreams#Public", - mentioned_user.ap_id - ] - - activity = %Activity{ - id: 1, - data: %{ - "type" => "Create", - "id" => "id", - "to" => to, - "actor" => User.ap_id(user), - "object" => %{ - "published" => date, - "type" => "Note", - "content" => content_html, - "summary" => "2hu :2hu:", - "inReplyToStatusId" => 213_123, - "attachment" => [ - object - ], - "external_url" => "some url", - "like_count" => 5, - "announcement_count" => 3, - "context" => "2hu", - "tag" => ["content", "mentioning", "nsfw"], - "emoji" => %{ - "2hu" => "corndog.png" - } - }, - "published" => date, - "context" => "2hu" - }, - local: false, - recipients: to - } - - corndog_emojo = ~s(<img height="32px" width="32px" alt="2hu" title="2hu" src="corndog.png" />) - - expected_html = - ~s(<p>2hu ) <> - corndog_emojo <> - ~s(</p>alert\('YAY'\)Some ) <> - corndog_emojo <> - ~s( content mentioning <a href=") <> mentioned_user.ap_id <> ~s(">@shp</a>) - - expected_status = %{ - "id" => activity.id, - "user" => UserView.render("show.json", %{user: user, for: follower}), - "is_local" => false, - "statusnet_html" => expected_html, - "text" => "2hu :2hu:" <> content, - "is_post_verb" => true, - "created_at" => "Tue May 24 13:26:08 +0000 2016", - "in_reply_to_status_id" => 213_123, - "in_reply_to_screen_name" => nil, - "in_reply_to_user_id" => nil, - "in_reply_to_profileurl" => nil, - "in_reply_to_ostatus_uri" => nil, - "statusnet_conversation_id" => convo_object.id, - "attachments" => [ - ObjectRepresenter.to_map(object) - ], - "attentions" => [ - UserView.render("show.json", %{user: mentioned_user, for: follower}) - ], - "fave_num" => 5, - "repeat_num" => 3, - "favorited" => false, - "repeated" => false, - "pinned" => false, - "external_url" => "some url", - "tags" => ["nsfw", "content", "mentioning"], - "activity_type" => "post", - "possibly_sensitive" => true, - "uri" => activity.data["object"]["id"], - "visibility" => "direct", - "card" => nil, - "muted" => false, - "summary" => "2hu :2hu:", - "summary_html" => - "2hu <img height=\"32px\" width=\"32px\" alt=\"2hu\" title=\"2hu\" src=\"corndog.png\" />" - } - - assert ActivityRepresenter.to_map(activity, %{ - user: user, - for: follower, - mentioned: [mentioned_user] - }) == expected_status - end - - test "a delete activity" do - object = insert(:note) - user = User.get_by_ap_id(object.data["actor"]) - - {:ok, delete} = ActivityPub.delete(object) - - map = ActivityRepresenter.to_map(delete, %{user: user}) - - assert map["is_post_verb"] == false - assert map["activity_type"] == "delete" - assert map["uri"] == object.data["id"] - end -end diff --git a/test/web/twitter_api/twitter_api_controller_test.exs b/test/web/twitter_api/twitter_api_controller_test.exs index 1b810c9a0..083540017 100644 --- a/test/web/twitter_api/twitter_api_controller_test.exs +++ b/test/web/twitter_api/twitter_api_controller_test.exs @@ -16,9 +16,9 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.CommonAPI alias Pleroma.Web.OAuth.Token + alias Pleroma.Web.TwitterAPI.ActivityView alias Pleroma.Web.TwitterAPI.Controller alias Pleroma.Web.TwitterAPI.NotificationView - alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter alias Pleroma.Web.TwitterAPI.TwitterAPI alias Pleroma.Web.TwitterAPI.UserView @@ -116,7 +116,11 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do |> post(request_path, %{status: "Nice meme.", visibility: "private"}) assert json_response(conn, 200) == - ActivityRepresenter.to_map(Repo.one(Activity), %{user: user, for: user}) + ActivityView.render("activity.json", %{ + activity: Repo.one(Activity), + user: user, + for: user + }) end end @@ -273,7 +277,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do response = json_response(conn, 200) - assert response == ActivityRepresenter.to_map(activity, %{user: actor}) + assert response == ActivityView.render("activity.json", %{activity: activity, user: actor}) end end @@ -372,7 +376,8 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do assert response == Enum.map(returned_activities, fn activity -> - ActivityRepresenter.to_map(activity, %{ + ActivityView.render("activity.json", %{ + activity: activity, user: User.get_cached_by_ap_id(activity.data["actor"]), for: current_user }) @@ -469,10 +474,10 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do assert length(response) == 1 assert Enum.at(response, 0) == - ActivityRepresenter.to_map(activity, %{ + ActivityView.render("activity.json", %{ user: current_user, for: current_user, - mentioned: [current_user] + activity: activity }) end @@ -594,7 +599,9 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do conn = get(conn, "/api/statuses/user_timeline.json", %{"user_id" => user.id}) response = json_response(conn, 200) assert length(response) == 1 - assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user}) + + assert Enum.at(response, 0) == + ActivityView.render("activity.json", %{user: user, activity: activity}) end test "with screen_name", %{conn: conn} do @@ -604,7 +611,9 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do conn = get(conn, "/api/statuses/user_timeline.json", %{"screen_name" => user.nickname}) response = json_response(conn, 200) assert length(response) == 1 - assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user}) + + assert Enum.at(response, 0) == + ActivityView.render("activity.json", %{user: user, activity: activity}) end test "with credentials", %{conn: conn, user: current_user} do @@ -620,7 +629,11 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do assert length(response) == 1 assert Enum.at(response, 0) == - ActivityRepresenter.to_map(activity, %{user: current_user, for: current_user}) + ActivityView.render("activity.json", %{ + user: current_user, + for: current_user, + activity: activity + }) end test "with credentials with user_id", %{conn: conn, user: current_user} do @@ -635,7 +648,9 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do response = json_response(conn, 200) assert length(response) == 1 - assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user}) + + assert Enum.at(response, 0) == + ActivityView.render("activity.json", %{user: user, activity: activity}) end test "with credentials screen_name", %{conn: conn, user: current_user} do @@ -650,7 +665,9 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do response = json_response(conn, 200) assert length(response) == 1 - assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user}) + + assert Enum.at(response, 0) == + ActivityView.render("activity.json", %{user: user, activity: activity}) end test "with credentials with user_id, excluding RTs", %{conn: conn, user: current_user} do @@ -669,7 +686,9 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do response = json_response(conn, 200) assert length(response) == 1 - assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user}) + + assert Enum.at(response, 0) == + ActivityView.render("activity.json", %{user: user, activity: activity}) conn = conn @@ -678,7 +697,9 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do response = json_response(conn, 200) assert length(response) == 1 - assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user}) + + assert Enum.at(response, 0) == + ActivityView.render("activity.json", %{user: user, activity: activity}) end end @@ -937,7 +958,11 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"]) assert json_response(response, 200) == - ActivityRepresenter.to_map(activity, %{user: activity_user, for: current_user}) + ActivityView.render("activity.json", %{ + user: activity_user, + for: current_user, + activity: activity + }) end end @@ -971,7 +996,11 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"]) assert json_response(response, 200) == - ActivityRepresenter.to_map(activity, %{user: activity_user, for: current_user}) + ActivityView.render("activity.json", %{ + user: activity_user, + for: current_user, + activity: activity + }) end end @@ -1955,7 +1984,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do user = refresh_record(user) assert json_response(response, 200) == - ActivityRepresenter.to_map(activity, %{user: user, for: user}) + ActivityView.render("activity.json", %{user: user, for: user, activity: activity}) end end @@ -1985,7 +2014,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do user = refresh_record(user) assert json_response(response, 200) == - ActivityRepresenter.to_map(activity, %{user: user, for: user}) + ActivityView.render("activity.json", %{user: user, for: user, activity: activity}) end end |