X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fweb%2Fmastodon_api%2Fmastodon_api_controller.ex;h=11fcd1c111aadea62bf9552bfc01cbee27f385f3;hb=980b5288ed119a3579afe632dff3391528ff399c;hp=5cb007740bcebc66129584a7db6f32c6f1dca114;hpb=e1c40b8ca288fe689cd78a96b34276089df3babe;p=akkoma diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 5cb007740..11fcd1c11 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -1,14 +1,27 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do use Pleroma.Web, :controller alias Pleroma.{Repo, Object, Activity, User, Notification, Stats} alias Pleroma.Web - alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView, ListView, FilterView} + + alias Pleroma.Web.MastodonAPI.{ + StatusView, + AccountView, + MastodonView, + ListView, + FilterView, + PushSubscriptionView + } + alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.CommonAPI alias Pleroma.Web.OAuth.{Authorization, Token, App} alias Pleroma.Web.MediaProxy - alias Comeonin.Pbkdf2 + import Ecto.Query require Logger @@ -32,75 +45,55 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end - def update_credentials(%{assigns: %{user: user}} = conn, params) do - original_user = user - - avatar_upload_limit = - Application.get_env(:pleroma, :instance) - |> Keyword.fetch(:avatar_upload_limit) - - banner_upload_limit = - Application.get_env(:pleroma, :instance) - |> Keyword.fetch(:banner_upload_limit) - - params = - if bio = params["note"] do - Map.put(params, "bio", bio) - else - params + defp add_if_present( + map, + params, + params_field, + map_field, + value_function \\ fn x -> {:ok, x} end + ) do + if Map.has_key?(params, params_field) do + case value_function.(params[params_field]) do + {:ok, new_value} -> Map.put(map, map_field, new_value) + :error -> map end + else + map + end + end - params = - if name = params["display_name"] do - Map.put(params, "name", name) - else - params - end + def update_credentials(%{assigns: %{user: user}} = conn, params) do + original_user = user - user = - if avatar = params["avatar"] do - with %Plug.Upload{} <- avatar, - {:ok, object} <- ActivityPub.upload(avatar, avatar_upload_limit), - change = Ecto.Changeset.change(user, %{avatar: object.data}), - {:ok, user} = User.update_and_set_cache(change) do - user + user_params = + %{} + |> add_if_present(params, "display_name", :name) + |> add_if_present(params, "note", :bio, fn value -> {:ok, User.parse_bio(value)} end) + |> add_if_present(params, "avatar", :avatar, fn value -> + with %Plug.Upload{} <- value, + {:ok, object} <- ActivityPub.upload(value, type: :avatar) do + {:ok, object.data} else - _e -> user + _ -> :error end - else - user - end + end) - user = - if banner = params["header"] do - with %Plug.Upload{} <- banner, - {:ok, object} <- ActivityPub.upload(banner, banner_upload_limit), - new_info <- Map.put(user.info, "banner", object.data), - change <- User.info_changeset(user, %{info: new_info}), - {:ok, user} <- User.update_and_set_cache(change) do - user + info_params = + %{} + |> add_if_present(params, "locked", :locked, fn value -> {:ok, value == "true"} end) + |> add_if_present(params, "header", :banner, fn value -> + with %Plug.Upload{} <- value, + {:ok, object} <- ActivityPub.upload(value, type: :banner) do + {:ok, object.data} else - _e -> user + _ -> :error end - else - user - end + end) - user = - if locked = params["locked"] do - with locked <- locked == "true", - new_info <- Map.put(user.info, "locked", locked), - change <- User.info_changeset(user, %{info: new_info}), - {:ok, user} <- User.update_and_set_cache(change) do - user - else - _e -> user - end - else - user - end + info_cng = User.Info.mastodon_profile_update(user.info, info_params) - with changeset <- User.update_changeset(user, params), + with changeset <- User.update_changeset(user, user_params), + changeset <- Ecto.Changeset.put_embed(changeset, :info, info_cng), {:ok, user} <- User.update_and_set_cache(changeset) do if original_user != user do CommonAPI.update(user) @@ -121,7 +114,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end def user(%{assigns: %{user: for_user}} = conn, %{"id" => id}) do - with %User{} = user <- Repo.get(User, id) do + with %User{} = user <- Repo.get(User, id), + true <- User.auth_active?(user) || user.id == for_user.id || User.superuser?(for_user) do account = AccountView.render("account.json", %{user: user, for: for_user}) json(conn, account) else @@ -132,22 +126,23 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end - @instance Application.get_env(:pleroma, :instance) @mastodon_api_level "2.5.0" def masto_instance(conn, _params) do + instance = Pleroma.Config.get(:instance) + response = %{ uri: Web.base_url(), - title: Keyword.get(@instance, :name), - description: Keyword.get(@instance, :description), - version: "#{@mastodon_api_level} (compatible; #{Keyword.get(@instance, :version)})", - email: Keyword.get(@instance, :email), + title: Keyword.get(instance, :name), + description: Keyword.get(instance, :description), + version: "#{@mastodon_api_level} (compatible; #{Pleroma.Application.named_version()})", + email: Keyword.get(instance, :email), urls: %{ streaming_api: String.replace(Pleroma.Web.Endpoint.static_url(), "http", "ws") }, stats: Stats.get_stats(), thumbnail: Web.base_url() <> "/instance/thumbnail.jpeg", - max_toot_chars: Keyword.get(@instance, :limit) + max_toot_chars: Keyword.get(instance, :limit) } json(conn, response) @@ -236,7 +231,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do conn |> add_link_headers(:home_timeline, activities) - |> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity}) + |> put_view(StatusView) + |> render("index.json", %{activities: activities, for: user, as: :activity}) end def public_timeline(%{assigns: %{user: user}} = conn, params) do @@ -254,7 +250,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do conn |> add_link_headers(:public_timeline, activities, false, %{"local" => local_only}) - |> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity}) + |> put_view(StatusView) + |> render("index.json", %{activities: activities, for: user, as: :activity}) end def user_statuses(%{assigns: %{user: reading_user}} = conn, params) do @@ -269,7 +266,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do conn |> add_link_headers(:user_statuses, activities, params["id"]) - |> render(StatusView, "index.json", %{ + |> put_view(StatusView) + |> render("index.json", %{ activities: activities, for: reading_user, as: :activity @@ -277,21 +275,27 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end - def dm_timeline(%{assigns: %{user: user}} = conn, _params) do + def dm_timeline(%{assigns: %{user: user}} = conn, params) do query = - ActivityPub.fetch_activities_query([user.ap_id], %{"type" => "Create", visibility: "direct"}) + ActivityPub.fetch_activities_query( + [user.ap_id], + Map.merge(params, %{"type" => "Create", visibility: "direct"}) + ) activities = Repo.all(query) conn |> add_link_headers(:dm_timeline, activities) - |> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity}) + |> put_view(StatusView) + |> render("index.json", %{activities: activities, for: user, as: :activity}) end def get_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do with %Activity{} = activity <- Repo.get(Activity, id), true <- ActivityPub.visible_for_user?(activity, user) do - try_render(conn, StatusView, "status.json", %{activity: activity, for: user}) + conn + |> put_view(StatusView) + |> try_render("status.json", %{activity: activity, for: user}) end end @@ -354,7 +358,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do {:ok, activity} = Cachex.fetch!(:idempotency_cache, idempotency_key, fn _ -> CommonAPI.post(user, params) end) - try_render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity}) + conn + |> put_view(StatusView) + |> try_render("status.json", %{activity: activity, for: user, as: :activity}) end def delete_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do @@ -370,28 +376,36 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do 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 - try_render(conn, StatusView, "status.json", %{activity: announce, for: user, as: :activity}) + conn + |> put_view(StatusView) + |> try_render("status.json", %{activity: announce, for: user, as: :activity}) end end 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_activity_by_object_ap_id(id) do - try_render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity}) + conn + |> put_view(StatusView) + |> try_render("status.json", %{activity: activity, for: user, as: :activity}) end end def fav_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do with {:ok, _fav, %{data: %{"id" => id}}} <- CommonAPI.favorite(ap_id_or_id, user), %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do - try_render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity}) + conn + |> put_view(StatusView) + |> try_render("status.json", %{activity: activity, for: user, as: :activity}) end end def unfav_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do with {:ok, _, _, %{data: %{"id" => id}}} <- CommonAPI.unfavorite(ap_id_or_id, user), %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do - try_render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity}) + conn + |> put_view(StatusView) + |> try_render("status.json", %{activity: activity, for: user, as: :activity}) end end @@ -440,43 +454,46 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do id = List.wrap(id) q = from(u in User, where: u.id in ^id) targets = Repo.all(q) - render(conn, AccountView, "relationships.json", %{user: user, targets: targets}) + + conn + |> put_view(AccountView) + |> render("relationships.json", %{user: user, targets: targets}) end - def update_media(%{assigns: %{user: _}} = conn, data) do + # Instead of returning a 400 when no "id" params is present, Mastodon returns an empty array. + def relationships(%{assigns: %{user: _user}} = conn, _), do: json(conn, []) + + def update_media(%{assigns: %{user: user}} = conn, data) do with %Object{} = object <- Repo.get(Object, data["id"]), + true <- Object.authorize_mutation(object, user), true <- is_binary(data["description"]), description <- data["description"] do new_data = %{object.data | "name" => description} - change = Object.change(object, %{data: new_data}) - {:ok, _} = Repo.update(change) + {:ok, _} = + object + |> Object.change(%{data: new_data}) + |> Repo.update() - data = - new_data - |> Map.put("id", object.id) + attachment_data = Map.put(new_data, "id", object.id) - render(conn, StatusView, "attachment.json", %{attachment: data}) + conn + |> put_view(StatusView) + |> render("attachment.json", %{attachment: attachment_data}) end end - def upload(%{assigns: %{user: _}} = conn, %{"file" => file} = data) do - with {:ok, object} <- ActivityPub.upload(file) do - objdata = - if Map.has_key?(data, "description") do - Map.put(object.data, "name", data["description"]) - else - object.data - end - - change = Object.change(object, %{data: objdata}) - {:ok, object} = Repo.update(change) + def upload(%{assigns: %{user: user}} = conn, %{"file" => file} = data) do + with {:ok, object} <- + ActivityPub.upload(file, + actor: User.ap_id(user), + description: Map.get(data, "description") + ) do + attachment_data = Map.put(object.data, "id", object.id) - objdata = - objdata - |> Map.put("id", object.id) - - render(conn, StatusView, "attachment.json", %{attachment: objdata}) + conn + |> put_view(StatusView) + |> render("attachment.json", %{attachment: attachment_data}) end end @@ -484,7 +501,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do with %Activity{data: %{"object" => %{"likes" => likes}}} <- Repo.get(Activity, id) do q = from(u in User, where: u.ap_id in ^likes) users = Repo.all(q) - render(conn, AccountView, "accounts.json", %{users: users, as: :user}) + + conn + |> put_view(AccountView) + |> render(AccountView, "accounts.json", %{users: users, as: :user}) else _ -> json(conn, []) end @@ -494,7 +514,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do with %Activity{data: %{"object" => %{"announcements" => announces}}} <- Repo.get(Activity, id) do q = from(u in User, where: u.ap_id in ^announces) users = Repo.all(q) - render(conn, AccountView, "accounts.json", %{users: users, as: :user}) + + conn + |> put_view(AccountView) + |> render("accounts.json", %{users: users, as: :user}) else _ -> json(conn, []) end @@ -516,27 +539,47 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do conn |> add_link_headers(:hashtag_timeline, activities, params["tag"], %{"local" => local_only}) - |> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity}) + |> put_view(StatusView) + |> render("index.json", %{activities: activities, for: user, as: :activity}) end - # TODO: Pagination - def followers(conn, %{"id" => id}) do + def followers(%{assigns: %{user: for_user}} = conn, %{"id" => id}) do with %User{} = user <- Repo.get(User, id), {:ok, followers} <- User.get_followers(user) do - render(conn, AccountView, "accounts.json", %{users: followers, as: :user}) + followers = + cond do + for_user && user.id == for_user.id -> followers + user.info.hide_network -> [] + true -> followers + end + + conn + |> put_view(AccountView) + |> render("accounts.json", %{users: followers, as: :user}) end end - def following(conn, %{"id" => id}) do + def following(%{assigns: %{user: for_user}} = conn, %{"id" => id}) do with %User{} = user <- Repo.get(User, id), {:ok, followers} <- User.get_friends(user) do - render(conn, AccountView, "accounts.json", %{users: followers, as: :user}) + followers = + cond do + for_user && user.id == for_user.id -> followers + user.info.hide_network -> [] + true -> followers + end + + conn + |> put_view(AccountView) + |> render("accounts.json", %{users: followers, as: :user}) end end def follow_requests(%{assigns: %{user: followed}} = conn, _params) do with {:ok, follow_requests} <- User.get_follow_requests(followed) do - render(conn, AccountView, "accounts.json", %{users: follow_requests, as: :user}) + conn + |> put_view(AccountView) + |> render("accounts.json", %{users: follow_requests, as: :user}) end end @@ -552,7 +595,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do object: follow_activity.data["id"], type: "Accept" }) do - render(conn, AccountView, "relationship.json", %{user: followed, target: follower}) + conn + |> put_view(AccountView) + |> render("relationship.json", %{user: followed, target: follower}) else {:error, message} -> conn @@ -572,7 +617,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do object: follow_activity.data["id"], type: "Reject" }) do - render(conn, AccountView, "relationship.json", %{user: followed, target: follower}) + conn + |> put_view(AccountView) + |> render("relationship.json", %{user: followed, target: follower}) else {:error, message} -> conn @@ -581,16 +628,19 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end - @activitypub Application.get_env(:pleroma, :activitypub) - @follow_handshake_timeout Keyword.get(@activitypub, :follow_handshake_timeout) - def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do with %User{} = followed <- Repo.get(User, id), {:ok, follower} <- User.maybe_direct_follow(follower, followed), {:ok, _activity} <- ActivityPub.follow(follower, followed), {:ok, follower, followed} <- - User.wait_and_refresh(@follow_handshake_timeout, follower, followed) do - render(conn, AccountView, "relationship.json", %{user: follower, target: followed}) + User.wait_and_refresh( + Pleroma.Config.get([:activitypub, :follow_handshake_timeout]), + follower, + followed + ) do + conn + |> put_view(AccountView) + |> render("relationship.json", %{user: follower, target: followed}) else {:error, message} -> conn @@ -603,7 +653,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do with %User{} = followed <- Repo.get_by(User, nickname: uri), {:ok, follower} <- User.maybe_direct_follow(follower, followed), {:ok, _activity} <- ActivityPub.follow(follower, followed) do - render(conn, AccountView, "account.json", %{user: followed, for: follower}) + conn + |> put_view(AccountView) + |> render("account.json", %{user: followed, for: follower}) else {:error, message} -> conn @@ -616,7 +668,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do with %User{} = followed <- Repo.get(User, id), {:ok, _activity} <- ActivityPub.unfollow(follower, followed), {:ok, follower, _} <- User.unfollow(follower, followed) do - render(conn, AccountView, "relationship.json", %{user: follower, target: followed}) + conn + |> put_view(AccountView) + |> render("relationship.json", %{user: follower, target: followed}) end end @@ -624,7 +678,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do with %User{} = blocked <- Repo.get(User, id), {:ok, blocker} <- User.block(blocker, blocked), {:ok, _activity} <- ActivityPub.block(blocker, blocked) do - render(conn, AccountView, "relationship.json", %{user: blocker, target: blocked}) + conn + |> put_view(AccountView) + |> render("relationship.json", %{user: blocker, target: blocked}) else {:error, message} -> conn @@ -637,7 +693,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do with %User{} = blocked <- Repo.get(User, id), {:ok, blocker} <- User.unblock(blocker, blocked), {:ok, _activity} <- ActivityPub.unblock(blocker, blocked) do - render(conn, AccountView, "relationship.json", %{user: blocker, target: blocked}) + conn + |> put_view(AccountView) + |> render("relationship.json", %{user: blocker, target: blocked}) else {:error, message} -> conn @@ -646,17 +704,15 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end - # TODO: Use proper query def blocks(%{assigns: %{user: user}} = conn, _) do - with blocked_users <- user.info["blocks"] || [], - accounts <- Enum.map(blocked_users, fn ap_id -> User.get_cached_by_ap_id(ap_id) end) do - res = AccountView.render("accounts.json", users: accounts, for: user, as: :user) + with blocked_accounts <- User.blocked_users(user) do + res = AccountView.render("accounts.json", users: blocked_accounts, for: user, as: :user) json(conn, res) end end def domain_blocks(%{assigns: %{user: %{info: info}}} = conn, _) do - json(conn, info["domain_blocks"] || []) + json(conn, info.domain_blocks || []) end def block_domain(%{assigns: %{user: blocker}} = conn, %{"domain" => domain}) do @@ -762,7 +818,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do |> Enum.reverse() conn - |> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity}) + |> put_view(StatusView) + |> render("index.json", %{activities: activities, for: user, as: :activity}) end def get_lists(%{assigns: %{user: user}} = conn, opts) do @@ -830,7 +887,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do def list_accounts(%{assigns: %{user: user}} = conn, %{"id" => id}) do with %Pleroma.List{} = list <- Pleroma.List.get(id, user), {:ok, users} = Pleroma.List.get_following(list) do - render(conn, AccountView, "accounts.json", %{users: users, as: :user}) + conn + |> put_view(AccountView) + |> render("accounts.json", %{users: users, as: :user}) end end @@ -846,7 +905,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end def list_timeline(%{assigns: %{user: user}} = conn, %{"list_id" => id} = params) do - with %Pleroma.List{title: title, following: following} <- Pleroma.List.get(id, user) do + with %Pleroma.List{title: _title, following: following} <- Pleroma.List.get(id, user) do params = params |> Map.put("type", "Create") @@ -863,7 +922,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do |> Enum.reverse() conn - |> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity}) + |> put_view(StatusView) + |> render("index.json", %{activities: activities, for: user, as: :activity}) else _e -> conn @@ -880,6 +940,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do if user && token do mastodon_emoji = mastodonized_emoji() + limit = Pleroma.Config.get([:instance, :limit]) + accounts = Map.put(%{}, user.id, AccountView.render("account.json", %{user: user, for: user})) @@ -899,14 +961,14 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do auto_play_gif: false, display_sensitive_media: false, reduce_motion: false, - max_toot_chars: Keyword.get(@instance, :limit) + max_toot_chars: limit }, rights: %{ - delete_others_notice: !!user.info["is_moderator"] + delete_others_notice: !!user.info.is_moderator }, compose: %{ me: "#{user.id}", - default_privacy: user.info["default_scope"] || "public", + default_privacy: user.info.default_scope, default_sensitive: false }, media_attachments: %{ @@ -926,7 +988,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do ] }, settings: - Map.get(user.info, "settings") || + user.info.settings || %{ onboarded: true, home: %{ @@ -959,13 +1021,14 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do push_subscription: nil, accounts: accounts, custom_emojis: mastodon_emoji, - char_limit: Keyword.get(@instance, :limit) + char_limit: limit } |> Jason.encode!() conn |> put_layout(false) - |> render(MastodonView, "index.html", %{initial_state: initial_state}) + |> put_view(MastodonView) + |> render("index.html", %{initial_state: initial_state}) else conn |> redirect(to: "/web/login") @@ -973,15 +1036,17 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end def put_settings(%{assigns: %{user: user}} = conn, %{"data" => settings} = _params) do - with new_info <- Map.put(user.info, "settings", settings), - change <- User.info_changeset(user, %{info: new_info}), - {:ok, _user} <- User.update_and_set_cache(change) do - conn - |> json(%{}) + info_cng = User.Info.mastodon_settings_update(user.info, settings) + + with changeset <- Ecto.Changeset.change(user), + changeset <- Ecto.Changeset.put_embed(changeset, :info, info_cng), + {:ok, _user} <- User.update_and_set_cache(changeset) do + json(conn, %{}) else e -> conn - |> json(%{error: inspect(e)}) + |> put_resp_content_type("application/json") + |> send_resp(500, Jason.encode!(%{"error" => inspect(e)})) end end @@ -1036,7 +1101,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do Logger.debug("Unimplemented, returning unmodified relationship") with %User{} = target <- Repo.get(User, id) do - render(conn, AccountView, "relationship.json", %{user: user, target: target}) + conn + |> put_view(AccountView) + |> render("relationship.json", %{user: user, target: target}) end end @@ -1052,52 +1119,37 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do def render_notification(user, %{id: id, activity: activity, inserted_at: created_at} = _params) do actor = User.get_cached_by_ap_id(activity.data["actor"]) + parent_activity = Activity.get_create_activity_by_object_ap_id(activity.data["object"]) + mastodon_type = Activity.mastodon_notification_type(activity) - created_at = - NaiveDateTime.to_iso8601(created_at) - |> String.replace(~r/(\.\d+)?$/, ".000Z", global: false) - - id = id |> to_string + response = %{ + id: to_string(id), + type: mastodon_type, + created_at: CommonAPI.Utils.to_masto_date(created_at), + account: AccountView.render("account.json", %{user: actor, for: user}) + } - case activity.data["type"] do - "Create" -> - %{ - id: id, - type: "mention", - created_at: created_at, - account: AccountView.render("account.json", %{user: actor, for: user}), + case mastodon_type do + "mention" -> + response + |> Map.merge(%{ status: StatusView.render("status.json", %{activity: activity, for: user}) - } + }) - "Like" -> - liked_activity = Activity.get_create_activity_by_object_ap_id(activity.data["object"]) + "favourite" -> + response + |> Map.merge(%{ + status: StatusView.render("status.json", %{activity: parent_activity, for: user}) + }) - %{ - id: id, - type: "favourite", - created_at: created_at, - account: AccountView.render("account.json", %{user: actor, for: user}), - status: StatusView.render("status.json", %{activity: liked_activity, for: user}) - } + "reblog" -> + response + |> Map.merge(%{ + status: StatusView.render("status.json", %{activity: parent_activity, for: user}) + }) - "Announce" -> - announced_activity = Activity.get_create_activity_by_object_ap_id(activity.data["object"]) - - %{ - id: id, - type: "reblog", - created_at: created_at, - account: AccountView.render("account.json", %{user: actor, for: user}), - status: StatusView.render("status.json", %{activity: announced_activity, for: user}) - } - - "Follow" -> - %{ - id: id, - type: "follow", - created_at: created_at, - account: AccountView.render("account.json", %{user: actor, for: user}) - } + "follow" -> + response _ -> nil @@ -1163,30 +1215,65 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do json(conn, %{}) end + def create_push_subscription(%{assigns: %{user: user, token: token}} = conn, params) do + true = Pleroma.Web.Push.enabled() + Pleroma.Web.Push.Subscription.delete_if_exists(user, token) + {:ok, subscription} = Pleroma.Web.Push.Subscription.create(user, token, params) + view = PushSubscriptionView.render("push_subscription.json", subscription: subscription) + json(conn, view) + end + + def get_push_subscription(%{assigns: %{user: user, token: token}} = conn, _params) do + true = Pleroma.Web.Push.enabled() + subscription = Pleroma.Web.Push.Subscription.get(user, token) + view = PushSubscriptionView.render("push_subscription.json", subscription: subscription) + json(conn, view) + end + + def update_push_subscription( + %{assigns: %{user: user, token: token}} = conn, + params + ) do + true = Pleroma.Web.Push.enabled() + {:ok, subscription} = Pleroma.Web.Push.Subscription.update(user, token, params) + view = PushSubscriptionView.render("push_subscription.json", subscription: subscription) + json(conn, view) + end + + def delete_push_subscription(%{assigns: %{user: user, token: token}} = conn, _params) do + true = Pleroma.Web.Push.enabled() + {:ok, _response} = Pleroma.Web.Push.Subscription.delete(user, token) + json(conn, %{}) + end + def errors(conn, _) do conn |> put_status(500) |> json("Something went wrong") end - @suggestions Application.get_env(:pleroma, :suggestions) - def suggestions(%{assigns: %{user: user}} = conn, _) do - if Keyword.get(@suggestions, :enabled, false) do - api = Keyword.get(@suggestions, :third_party_engine, "") - timeout = Keyword.get(@suggestions, :timeout, 5000) - limit = Keyword.get(@suggestions, :limit, 23) + suggestions = Pleroma.Config.get(:suggestions) + + if Keyword.get(suggestions, :enabled, false) do + api = Keyword.get(suggestions, :third_party_engine, "") + timeout = Keyword.get(suggestions, :timeout, 5000) + limit = Keyword.get(suggestions, :limit, 23) - host = - Application.get_env(:pleroma, Pleroma.Web.Endpoint) - |> Keyword.get(:url) - |> Keyword.get(:host) + host = Pleroma.Config.get([Pleroma.Web.Endpoint, :url, :host]) user = user.nickname url = String.replace(api, "{{host}}", host) |> String.replace("{{user}}", user) - with {:ok, %{status_code: 200, body: body}} <- - @httpoison.get(url, [], timeout: timeout, recv_timeout: timeout), + with {:ok, %{status: 200, body: body}} <- + @httpoison.get( + url, + [], + adapter: [ + timeout: timeout, + recv_timeout: timeout + ] + ), {:ok, data} <- Jason.decode(body) do data2 = Enum.slice(data, 0, limit) @@ -1217,9 +1304,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end - def try_render(conn, renderer, target, params) + def try_render(conn, target, params) when is_binary(target) do - res = render(conn, renderer, target, params) + res = render(conn, target, params) if res == nil do conn @@ -1230,7 +1317,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end - def try_render(conn, _, _, _) do + def try_render(conn, _, _) do conn |> put_status(501) |> json(%{error: "Can't display this activity"})