diff options
Diffstat (limited to 'lib/pleroma/web')
-rw-r--r-- | lib/pleroma/web/admin_api/admin_api_controller.ex | 20 | ||||
-rw-r--r-- | lib/pleroma/web/endpoint.ex | 20 | ||||
-rw-r--r-- | lib/pleroma/web/mastodon_api/mastodon_api.ex | 7 | ||||
-rw-r--r-- | lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 116 | ||||
-rw-r--r-- | lib/pleroma/web/mastodon_api/views/scheduled_activity_view.ex | 57 | ||||
-rw-r--r-- | lib/pleroma/web/mastodon_api/views/status_view.ex | 14 | ||||
-rw-r--r-- | lib/pleroma/web/metadata/utils.ex | 2 | ||||
-rw-r--r-- | lib/pleroma/web/oauth/oauth_controller.ex | 6 | ||||
-rw-r--r-- | lib/pleroma/web/router.ex | 10 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/views/activity_view.ex | 6 |
10 files changed, 239 insertions, 19 deletions
diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex index b3a09e49e..78bf31893 100644 --- a/lib/pleroma/web/admin_api/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/admin_api_controller.ex @@ -25,6 +25,26 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do |> json(nickname) end + def user_follow(conn, %{"follower" => follower_nick, "followed" => followed_nick}) do + with %User{} = follower <- User.get_by_nickname(follower_nick), + %User{} = followed <- User.get_by_nickname(followed_nick) do + User.follow(follower, followed) + end + + conn + |> json("ok") + end + + def user_unfollow(conn, %{"follower" => follower_nick, "followed" => followed_nick}) do + with %User{} = follower <- User.get_by_nickname(follower_nick), + %User{} = followed <- User.get_by_nickname(followed_nick) do + User.unfollow(follower, followed) + end + + conn + |> json("ok") + end + def user_create( conn, %{"nickname" => nickname, "email" => email, "password" => password} diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index fa2d1cbe7..6d9528c86 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -70,6 +70,26 @@ defmodule Pleroma.Web.Endpoint do extra: "SameSite=Strict" ) + # Note: the plug and its configuration is compile-time this can't be upstreamed yet + if proxies = Pleroma.Config.get([__MODULE__, :reverse_proxies]) do + plug(RemoteIp, proxies: proxies) + end + + defmodule Instrumenter do + use Prometheus.PhoenixInstrumenter + end + + defmodule PipelineInstrumenter do + use Prometheus.PlugPipelineInstrumenter + end + + defmodule MetricsExporter do + use Prometheus.PlugExporter + end + + plug(PipelineInstrumenter) + plug(MetricsExporter) + plug(Pleroma.Web.Router) @doc """ diff --git a/lib/pleroma/web/mastodon_api/mastodon_api.ex b/lib/pleroma/web/mastodon_api/mastodon_api.ex index 08ea5f967..382f07e6b 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api.ex @@ -5,6 +5,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do alias Pleroma.Activity alias Pleroma.Notification alias Pleroma.Pagination + alias Pleroma.ScheduledActivity alias Pleroma.User def get_followers(user, params \\ %{}) do @@ -28,6 +29,12 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do |> Pagination.fetch_paginated(params) end + def get_scheduled_activities(user, params \\ %{}) do + user + |> ScheduledActivity.for_user_query() + |> Pagination.fetch_paginated(params) + end + defp cast_params(params) do param_types = %{ exclude_types: {:array, :string} diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 0de2cca4e..fc8a2458c 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -5,12 +5,14 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do use Pleroma.Web, :controller + alias Ecto.Changeset alias Pleroma.Activity alias Pleroma.Config alias Pleroma.Filter alias Pleroma.Notification alias Pleroma.Object alias Pleroma.Repo + alias Pleroma.ScheduledActivity alias Pleroma.Stats alias Pleroma.User alias Pleroma.Web @@ -25,6 +27,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do alias Pleroma.Web.MastodonAPI.MastodonView alias Pleroma.Web.MastodonAPI.NotificationView alias Pleroma.Web.MastodonAPI.ReportView + alias Pleroma.Web.MastodonAPI.ScheduledActivityView alias Pleroma.Web.MastodonAPI.StatusView alias Pleroma.Web.MediaProxy alias Pleroma.Web.OAuth.App @@ -364,6 +367,55 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end + def scheduled_statuses(%{assigns: %{user: user}} = conn, params) do + with scheduled_activities <- MastodonAPI.get_scheduled_activities(user, params) do + conn + |> add_link_headers(:scheduled_statuses, scheduled_activities) + |> put_view(ScheduledActivityView) + |> render("index.json", %{scheduled_activities: scheduled_activities}) + end + end + + def show_scheduled_status(%{assigns: %{user: user}} = conn, %{"id" => scheduled_activity_id}) do + with %ScheduledActivity{} = scheduled_activity <- + ScheduledActivity.get(user, scheduled_activity_id) do + conn + |> put_view(ScheduledActivityView) + |> render("show.json", %{scheduled_activity: scheduled_activity}) + else + _ -> {:error, :not_found} + end + end + + def update_scheduled_status( + %{assigns: %{user: user}} = conn, + %{"id" => scheduled_activity_id} = params + ) do + with %ScheduledActivity{} = scheduled_activity <- + ScheduledActivity.get(user, scheduled_activity_id), + {:ok, scheduled_activity} <- ScheduledActivity.update(scheduled_activity, params) do + conn + |> put_view(ScheduledActivityView) + |> render("show.json", %{scheduled_activity: scheduled_activity}) + else + nil -> {:error, :not_found} + error -> error + end + end + + def delete_scheduled_status(%{assigns: %{user: user}} = conn, %{"id" => scheduled_activity_id}) do + with %ScheduledActivity{} = scheduled_activity <- + ScheduledActivity.get(user, scheduled_activity_id), + {:ok, scheduled_activity} <- ScheduledActivity.delete(scheduled_activity) do + conn + |> put_view(ScheduledActivityView) + |> render("show.json", %{scheduled_activity: scheduled_activity}) + else + nil -> {:error, :not_found} + error -> error + end + end + def post_status(conn, %{"status" => "", "media_ids" => media_ids} = params) when length(media_ids) > 0 do params = @@ -384,12 +436,27 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do _ -> Ecto.UUID.generate() end - {:ok, activity} = - Cachex.fetch!(:idempotency_cache, idempotency_key, fn _ -> CommonAPI.post(user, params) end) + scheduled_at = params["scheduled_at"] - conn - |> put_view(StatusView) - |> try_render("status.json", %{activity: activity, for: user, as: :activity}) + if scheduled_at && ScheduledActivity.far_enough?(scheduled_at) do + with {:ok, scheduled_activity} <- + ScheduledActivity.create(user, %{"params" => params, "scheduled_at" => scheduled_at}) do + conn + |> put_view(ScheduledActivityView) + |> render("show.json", %{scheduled_activity: scheduled_activity}) + end + else + params = Map.drop(params, ["scheduled_at"]) + + {:ok, activity} = + Cachex.fetch!(:idempotency_cache, idempotency_key, fn _ -> + CommonAPI.post(user, params) + end) + + conn + |> put_view(StatusView) + |> try_render("status.json", %{activity: activity, for: user, as: :activity}) + end end def delete_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do @@ -1091,9 +1158,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end def index(%{assigns: %{user: user}} = conn, _params) do - token = - conn - |> get_session(:oauth_token) + token = get_session(conn, :oauth_token) if user && token do mastodon_emoji = mastodonized_emoji() @@ -1121,7 +1186,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do auto_play_gif: false, display_sensitive_media: false, reduce_motion: false, - max_toot_chars: limit + max_toot_chars: limit, + mascot: "/images/pleroma-fox-tan-smol.png" }, rights: %{ delete_others_notice: present?(user.info.is_moderator), @@ -1193,6 +1259,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do |> render("index.html", %{initial_state: initial_state, flavour: flavour}) else conn + |> put_session(:return_to, conn.request_path) |> redirect(to: "/web/login") end end @@ -1277,12 +1344,20 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do scope: Enum.join(app.scopes, " ") ) - conn - |> redirect(to: path) + redirect(conn, to: path) end end - defp local_mastodon_root_path(conn), do: mastodon_api_path(conn, :index, ["getting-started"]) + defp local_mastodon_root_path(conn) do + case get_session(conn, :return_to) do + nil -> + mastodon_api_path(conn, :index, ["getting-started"]) + + return_to -> + delete_session(conn, :return_to) + return_to + end + end defp get_or_make_app do find_attrs = %{client_name: @local_mastodon_name, redirect_uris: "."} @@ -1398,6 +1473,23 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do # fallback action # + def errors(conn, {:error, %Changeset{} = changeset}) do + error_message = + changeset + |> Changeset.traverse_errors(fn {message, _opt} -> message end) + |> Enum.map_join(", ", fn {_k, v} -> v end) + + conn + |> put_status(422) + |> json(%{error: error_message}) + end + + def errors(conn, {:error, :not_found}) do + conn + |> put_status(404) + |> json(%{error: "Record not found"}) + end + def errors(conn, _) do conn |> put_status(500) diff --git a/lib/pleroma/web/mastodon_api/views/scheduled_activity_view.ex b/lib/pleroma/web/mastodon_api/views/scheduled_activity_view.ex new file mode 100644 index 000000000..0aae15ab9 --- /dev/null +++ b/lib/pleroma/web/mastodon_api/views/scheduled_activity_view.ex @@ -0,0 +1,57 @@ +# 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.ScheduledActivityView do + use Pleroma.Web, :view + + alias Pleroma.ScheduledActivity + alias Pleroma.Web.CommonAPI + alias Pleroma.Web.MastodonAPI.ScheduledActivityView + alias Pleroma.Web.MastodonAPI.StatusView + + def render("index.json", %{scheduled_activities: scheduled_activities}) do + render_many(scheduled_activities, ScheduledActivityView, "show.json") + end + + def render("show.json", %{scheduled_activity: %ScheduledActivity{} = scheduled_activity}) do + %{ + id: to_string(scheduled_activity.id), + scheduled_at: CommonAPI.Utils.to_masto_date(scheduled_activity.scheduled_at), + params: status_params(scheduled_activity.params) + } + |> with_media_attachments(scheduled_activity) + end + + defp with_media_attachments(data, %{params: %{"media_attachments" => media_attachments}}) do + try do + attachments = render_many(media_attachments, StatusView, "attachment.json", as: :attachment) + Map.put(data, :media_attachments, attachments) + rescue + _ -> data + end + end + + defp with_media_attachments(data, _), do: data + + defp status_params(params) do + data = %{ + text: params["status"], + sensitive: params["sensitive"], + spoiler_text: params["spoiler_text"], + visibility: params["visibility"], + scheduled_at: params["scheduled_at"], + poll: params["poll"], + in_reply_to_id: params["in_reply_to_id"] + } + + data = + if media_ids = params["media_ids"] do + Map.put(data, :media_ids, media_ids) + else + data + end + + data + 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 200bb453d..4c0b53bdd 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -147,10 +147,18 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do content = object |> render_content() - |> HTML.get_cached_scrubbed_html_for_object( + |> HTML.get_cached_scrubbed_html_for_activity( User.html_filter_policy(opts[:for]), activity, - __MODULE__ + "mastoapi:content" + ) + + summary = + (object["summary"] || "") + |> HTML.get_cached_scrubbed_html_for_activity( + User.html_filter_policy(opts[:for]), + activity, + "mastoapi:summary" ) card = render("card.json", Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity)) @@ -182,7 +190,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do muted: CommonAPI.thread_muted?(user, activity) || User.mutes?(opts[:for], user), pinned: pinned?(activity, user), sensitive: sensitive, - spoiler_text: object["summary"] || "", + spoiler_text: summary, visibility: get_visibility(object), media_attachments: attachments, mentions: mentions, diff --git a/lib/pleroma/web/metadata/utils.ex b/lib/pleroma/web/metadata/utils.ex index 23bbde1a6..58385a3d1 100644 --- a/lib/pleroma/web/metadata/utils.ex +++ b/lib/pleroma/web/metadata/utils.ex @@ -12,7 +12,7 @@ defmodule Pleroma.Web.Metadata.Utils do # html content comes from DB already encoded, decode first and scrub after |> HtmlEntities.decode() |> String.replace(~r/<br\s?\/?>/, " ") - |> HTML.get_cached_stripped_html_for_object(object, __MODULE__) + |> HTML.get_cached_stripped_html_for_activity(object, "metadata") |> Formatter.demojify() |> Formatter.truncate() end diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index 26d53df1a..aac8f97fc 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -152,6 +152,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do with {_, {:ok, %User{} = user}} <- {:get_user, Authenticator.get_user(conn)}, %App{} = app <- get_app_from_request(conn, params), {:auth_active, true} <- {:auth_active, User.auth_active?(user)}, + {:user_active, true} <- {:user_active, !user.info.deactivated}, scopes <- oauth_scopes(params, app.scopes), [] <- scopes -- app.scopes, true <- Enum.any?(scopes), @@ -175,6 +176,11 @@ defmodule Pleroma.Web.OAuth.OAuthController do |> put_status(:forbidden) |> json(%{error: "Your login is missing a confirmed e-mail address"}) + {:user_active, false} -> + conn + |> put_status(:forbidden) + |> json(%{error: "Your account is currently disabled"}) + _error -> put_status(conn, 400) |> json(%{error: "Invalid credentials"}) diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 605a327fc..3b5ac6fdd 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -140,8 +140,12 @@ defmodule Pleroma.Web.Router do scope "/api/pleroma/admin", Pleroma.Web.AdminAPI do pipe_through([:admin_api, :oauth_write]) + post("/user/follow", AdminAPIController, :user_follow) + post("/user/unfollow", AdminAPIController, :user_unfollow) + get("/users", AdminAPIController, :list_users) get("/users/:nickname", AdminAPIController, :user_show) + delete("/user", AdminAPIController, :user_delete) patch("/users/:nickname/toggle_activation", AdminAPIController, :user_toggle_activation) post("/user", AdminAPIController, :user_create) @@ -240,6 +244,9 @@ defmodule Pleroma.Web.Router do get("/notifications", MastodonAPIController, :notifications) get("/notifications/:id", MastodonAPIController, :get_notification) + get("/scheduled_statuses", MastodonAPIController, :scheduled_statuses) + get("/scheduled_statuses/:id", MastodonAPIController, :show_scheduled_status) + get("/lists", MastodonAPIController, :get_lists) get("/lists/:id", MastodonAPIController, :get_list) get("/lists/:id/accounts", MastodonAPIController, :list_accounts) @@ -274,6 +281,9 @@ defmodule Pleroma.Web.Router do post("/statuses/:id/mute", MastodonAPIController, :mute_conversation) post("/statuses/:id/unmute", MastodonAPIController, :unmute_conversation) + put("/scheduled_statuses/:id", MastodonAPIController, :update_scheduled_status) + delete("/scheduled_statuses/:id", MastodonAPIController, :delete_scheduled_status) + post("/media", MastodonAPIController, :upload) put("/media/:id", MastodonAPIController, :update_media) diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex index aa1d41fa2..433322eb8 100644 --- a/lib/pleroma/web/twitter_api/views/activity_view.ex +++ b/lib/pleroma/web/twitter_api/views/activity_view.ex @@ -254,10 +254,10 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do html = content - |> HTML.get_cached_scrubbed_html_for_object( + |> HTML.get_cached_scrubbed_html_for_activity( User.html_filter_policy(opts[:for]), activity, - __MODULE__ + "twitterapi:content" ) |> Formatter.emojify(object["emoji"]) @@ -265,7 +265,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do if content do content |> String.replace(~r/<br\s?\/?>/, "\n") - |> HTML.get_cached_stripped_html_for_object(activity, __MODULE__) + |> HTML.get_cached_stripped_html_for_activity(activity, "twitterapi:content") else "" end |