From 45e21a9df4a7b58d28624534fdde3dc9e31c6813 Mon Sep 17 00:00:00 2001 From: kPherox Date: Sun, 25 Aug 2019 06:51:05 +0900 Subject: Rename fields to fields_attributes --- lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 53cf95fbb..98b2e75f3 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -159,12 +159,12 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end) end) |> add_if_present(params, "default_scope", :default_scope) - |> add_if_present(params, "fields", :fields, fn fields -> + |> add_if_present(params, "fields_attributes", :fields, fn fields -> fields = Enum.map(fields, fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end) {:ok, fields} end) - |> add_if_present(params, "fields", :raw_fields) + |> add_if_present(params, "fields_attributes", :raw_fields) |> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store, fn value -> {:ok, Map.merge(user.info.pleroma_settings_store, value)} end) -- cgit v1.2.3 From 705b5adfc436b18ab3d1b8ff94274d9a2a6a6912 Mon Sep 17 00:00:00 2001 From: kPherox Date: Sun, 25 Aug 2019 07:02:32 +0900 Subject: Fix type of fields_attributes Convert tuple list to map list when parameters is `:urlencoded` or `:multipart` --- lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 98b2e75f3..2826cee8c 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -143,6 +143,13 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do |> Enum.concat(Formatter.get_emoji_map(emojis_text)) |> Enum.dedup() + params = + if Map.has_key?(params, "fields_attributes") && Enum.all?(params["fields_attributes"], &is_tuple/1) do + Map.update!(params, "fields_attributes", &Enum.map(&1, fn {_, v} -> v end)) + else + params + end + info_params = [ :no_rich_text, -- cgit v1.2.3 From b15e226593d4d9d58898af5576d2a7e96bed59ae Mon Sep 17 00:00:00 2001 From: kPherox Date: Sun, 25 Aug 2019 07:04:46 +0900 Subject: Change to delete empty name field --- lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 2826cee8c..ca2230630 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -144,8 +144,15 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do |> Enum.dedup() params = - if Map.has_key?(params, "fields_attributes") && Enum.all?(params["fields_attributes"], &is_tuple/1) do - Map.update!(params, "fields_attributes", &Enum.map(&1, fn {_, v} -> v end)) + if Map.has_key?(params, "fields_attributes") do + Map.update!(params, "fields_attributes", fn fields -> + if Enum.all?(fields, &is_tuple/1) do + Enum.map(fields, fn {_, v} -> v end) + else + fields + end + |> Enum.filter(fn %{"name" => n} -> n != "" end) + end) else params end -- cgit v1.2.3 From 8ca4f145a51e92c9f3a6c374ceddfac22ea300d9 Mon Sep 17 00:00:00 2001 From: kPherox Date: Mon, 26 Aug 2019 17:09:32 +0900 Subject: Extract if block into private function --- lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index ca2230630..3ca1630f4 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -119,6 +119,14 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end + defp normalize_fields_attributes(fields) do + if Enum.all?(fields, &is_tuple/1) do + Enum.map(fields, fn {_, v} -> v end) + else + fields + end + end + def update_credentials(%{assigns: %{user: user}} = conn, params) do original_user = user @@ -146,11 +154,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do params = if Map.has_key?(params, "fields_attributes") do Map.update!(params, "fields_attributes", fn fields -> - if Enum.all?(fields, &is_tuple/1) do - Enum.map(fields, fn {_, v} -> v end) - else - fields - end + fields + |> normalize_fields_attributes() |> Enum.filter(fn %{"name" => n} -> n != "" end) end) else -- cgit v1.2.3 From b63faf9819c2c49d2e9b63e7f37136eb03d8b4e8 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Sun, 8 Sep 2019 15:00:03 +0300 Subject: [#1234] Mastodon 2.4.3 hierarchical scopes initial support (WIP). --- lib/pleroma/plugs/oauth_scopes_plug.ex | 20 ++++++++++-- .../controllers/mastodon_api_controller.ex | 36 ++++++++++++++++++++++ lib/pleroma/web/oauth/oauth_controller.ex | 2 +- lib/pleroma/web/oauth/scopes.ex | 14 ++++----- lib/pleroma/web/router.ex | 14 +-------- .../web/twitter_api/controllers/util_controller.ex | 9 ++++++ 6 files changed, 71 insertions(+), 24 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/plugs/oauth_scopes_plug.ex b/lib/pleroma/plugs/oauth_scopes_plug.ex index b508628a9..41403047e 100644 --- a/lib/pleroma/plugs/oauth_scopes_plug.ex +++ b/lib/pleroma/plugs/oauth_scopes_plug.ex @@ -13,15 +13,16 @@ defmodule Pleroma.Plugs.OAuthScopesPlug do def call(%Plug.Conn{assigns: assigns} = conn, %{scopes: scopes} = options) do op = options[:op] || :| token = assigns[:token] + matched_scopes = token && filter_descendants(scopes, token.scopes) cond do is_nil(token) -> conn - op == :| && scopes -- token.scopes != scopes -> + op == :| && Enum.any?(matched_scopes) -> conn - op == :& && scopes -- token.scopes == [] -> + op == :& && matched_scopes == scopes -> conn options[:fallback] == :proceed_unauthenticated -> @@ -30,7 +31,7 @@ defmodule Pleroma.Plugs.OAuthScopesPlug do |> assign(:token, nil) true -> - missing_scopes = scopes -- token.scopes + missing_scopes = scopes -- matched_scopes permissions = Enum.join(missing_scopes, " #{op} ") error_message = @@ -42,4 +43,17 @@ defmodule Pleroma.Plugs.OAuthScopesPlug do |> halt() end end + + @doc "Filters descendants of supported scopes" + def filter_descendants(scopes, supported_scopes) do + Enum.filter( + scopes, + fn scope -> + Enum.find( + supported_scopes, + &(scope == &1 || String.starts_with?(scope, &1 <> ":")) + ) + end + ) + end end diff --git a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex index 8dfad7a54..118446c85 100644 --- a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex @@ -19,6 +19,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do alias Pleroma.Notification alias Pleroma.Object alias Pleroma.Pagination + alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.Plugs.RateLimiter alias Pleroma.Repo alias Pleroma.ScheduledActivity @@ -52,6 +53,41 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do require Logger require Pleroma.Constants + plug( + OAuthScopesPlug, + %{scopes: ["follow", "read:blocks"]} when action in [:blocks, :domain_blocks] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["follow", "write:blocks"]} + when action in [:block, :unblock, :block_domain, :unblock_domain] + ) + + plug(OAuthScopesPlug, %{scopes: ["follow", "read:follows"]} when action == :follow_requests) + + plug( + OAuthScopesPlug, + %{scopes: ["follow", "write:follows"]} + when action in [ + :follow, + :unfollow, + :subscribe, + :unsubscribe, + :authorize_follow_request, + :reject_follow_request + ] + ) + + plug(OAuthScopesPlug, %{scopes: ["follow", "read:mutes"]} when action == :mutes) + plug(OAuthScopesPlug, %{scopes: ["follow", "write:mutes"]} when action in [:mute, :unmute]) + + plug( + OAuthScopesPlug, + %{scopes: ["write:mutes"]} + when action in [:mute_conversation, :unmute_conversation] + ) + @rate_limited_relations_actions ~w(follow unfollow)a @rate_limited_status_actions ~w(reblog_status unreblog_status fav_status unfav_status diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index 81eae2c8b..130ec7895 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -451,7 +451,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do defp validate_scopes(app, params) do params |> Scopes.fetch_scopes(app.scopes) - |> Scopes.validates(app.scopes) + |> Scopes.validate(app.scopes) end def default_redirect_uri(%App{} = app) do diff --git a/lib/pleroma/web/oauth/scopes.ex b/lib/pleroma/web/oauth/scopes.ex index ad9dfb260..48bd14407 100644 --- a/lib/pleroma/web/oauth/scopes.ex +++ b/lib/pleroma/web/oauth/scopes.ex @@ -8,7 +8,7 @@ defmodule Pleroma.Web.OAuth.Scopes do """ @doc """ - Fetch scopes from requiest params. + Fetch scopes from request params. Note: `scopes` is used by Mastodon — supporting it but sticking to OAuth's standard `scope` wherever we control it @@ -53,14 +53,14 @@ defmodule Pleroma.Web.OAuth.Scopes do @doc """ Validates scopes. """ - @spec validates(list() | nil, list()) :: + @spec validate(list() | nil, list()) :: {:ok, list()} | {:error, :missing_scopes | :unsupported_scopes} - def validates([], _app_scopes), do: {:error, :missing_scopes} - def validates(nil, _app_scopes), do: {:error, :missing_scopes} + def validate([], _app_scopes), do: {:error, :missing_scopes} + def validate(nil, _app_scopes), do: {:error, :missing_scopes} - def validates(scopes, app_scopes) do - case scopes -- app_scopes do - [] -> {:ok, scopes} + def validate(scopes, app_scopes) do + case Pleroma.Plugs.OAuthScopesPlug.filter_descendants(scopes, app_scopes) do + ^scopes -> {:ok, scopes} _ -> {:error, :unsupported_scopes} end end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index cfb973f53..8c93e535e 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -104,10 +104,6 @@ defmodule Pleroma.Web.Router do plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["write"]}) end - pipeline :oauth_follow do - plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["follow"]}) - end - pipeline :oauth_push do plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["push"]}) end @@ -211,11 +207,7 @@ defmodule Pleroma.Web.Router do post("/main/ostatus", UtilController, :remote_subscribe) get("/ostatus_subscribe", UtilController, :remote_follow) - - scope [] do - pipe_through(:oauth_follow) - post("/ostatus_subscribe", UtilController, :do_remote_follow) - end + post("/ostatus_subscribe", UtilController, :do_remote_follow) end scope "/api/pleroma", Pleroma.Web.TwitterAPI do @@ -231,8 +223,6 @@ defmodule Pleroma.Web.Router do end scope [] do - pipe_through(:oauth_follow) - post("/blocks_import", UtilController, :blocks_import) post("/follow_import", UtilController, :follow_import) end @@ -373,8 +363,6 @@ defmodule Pleroma.Web.Router do end scope [] do - pipe_through(:oauth_follow) - post("/follows", MastodonAPIController, :follow) post("/accounts/:id/follow", MastodonAPIController, :follow) diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex index 3405bd3b7..1c6ad5057 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -13,11 +13,20 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do alias Pleroma.Healthcheck alias Pleroma.Notification alias Pleroma.Plugs.AuthenticationPlug + alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.User alias Pleroma.Web alias Pleroma.Web.CommonAPI alias Pleroma.Web.WebFinger + plug( + OAuthScopesPlug, + %{scopes: ["follow", "write:follows"]} + when action in [:do_remote_follow, :follow_import] + ) + + plug(OAuthScopesPlug, %{scopes: ["follow", "write:blocks"]} when action == :blocks_import) + plug(Pleroma.Plugs.SetFormatPlug when action in [:config, :version]) def help_test(conn, _params) do -- cgit v1.2.3 From e6f43a831bdd2a381ed4de493344886f312f9a38 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Sun, 15 Sep 2019 18:22:08 +0300 Subject: [#1234] Permissions-related fixes / new functionality (Masto 2.4.3 scopes). --- lib/pleroma/plugs/oauth_scopes_plug.ex | 12 +- .../web/activity_pub/activity_pub_controller.ex | 5 + lib/pleroma/web/admin_api/admin_api_controller.ex | 51 ++++ .../mastodon_api/controllers/list_controller.ex | 9 + .../controllers/mastodon_api_controller.ex | 135 ++++++++- .../mastodon_api/controllers/search_controller.ex | 5 + .../controllers/subscription_controller.ex | 2 + .../web/pleroma_api/pleroma_api_controller.ex | 13 + lib/pleroma/web/router.ex | 313 +++++++++------------ .../web/twitter_api/controllers/util_controller.ex | 11 + .../web/twitter_api/twitter_api_controller.ex | 3 + 11 files changed, 367 insertions(+), 192 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/plugs/oauth_scopes_plug.ex b/lib/pleroma/plugs/oauth_scopes_plug.ex index 41403047e..e0d61c4eb 100644 --- a/lib/pleroma/plugs/oauth_scopes_plug.ex +++ b/lib/pleroma/plugs/oauth_scopes_plug.ex @@ -6,6 +6,8 @@ defmodule Pleroma.Plugs.OAuthScopesPlug do import Plug.Conn import Pleroma.Web.Gettext + alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug + @behaviour Plug def init(%{scopes: _} = options), do: options @@ -17,7 +19,7 @@ defmodule Pleroma.Plugs.OAuthScopesPlug do cond do is_nil(token) -> - conn + maybe_perform_instance_privacy_check(conn, options) op == :| && Enum.any?(matched_scopes) -> conn @@ -29,6 +31,7 @@ defmodule Pleroma.Plugs.OAuthScopesPlug do conn |> assign(:user, nil) |> assign(:token, nil) + |> maybe_perform_instance_privacy_check(options) true -> missing_scopes = scopes -- matched_scopes @@ -56,4 +59,11 @@ defmodule Pleroma.Plugs.OAuthScopesPlug do end ) end + + defp maybe_perform_instance_privacy_check(%Plug.Conn{} = conn, options) do + case options[:skip_instance_privacy_check] do + true -> conn + _ -> EnsurePublicOrAuthenticatedPlug.call(conn, []) + end + end end diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex index 08bf1c752..7047b8254 100644 --- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex +++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex @@ -23,6 +23,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do action_fallback(:errors) + plug( + Pleroma.Plugs.OAuthScopesPlug, + %{scopes: ["read:accounts"]} when action in [:followers, :following] + ) + plug(Pleroma.Web.FederatingPlug when action in [:inbox, :relay]) plug(:set_requester_reachable when action in [:inbox]) plug(:relay_active? when action in [:relay]) diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex index 544b9d7d8..0a508d40e 100644 --- a/lib/pleroma/web/admin_api/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/admin_api_controller.ex @@ -6,6 +6,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do use Pleroma.Web, :controller alias Pleroma.Activity alias Pleroma.ModerationLog + alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.User alias Pleroma.UserInviteToken alias Pleroma.Web.ActivityPub.ActivityPub @@ -23,6 +24,56 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do require Logger + plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action == :list_user_statuses) + + plug( + OAuthScopesPlug, + %{scopes: ["write:statuses"]} when action in [:status_update, :status_delete] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["read"]} + when action in [ + :list_reports, + :report_show, + :right_get, + :get_invite_token, + :invites, + :get_password_reset, + :list_users, + :user_show, + :config_show, + :migrate_to_db, + :migrate_from_db, + :list_log + ] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["write"]} + when action in [ + :report_update_state, + :report_respond, + :user_follow, + :user_unfollow, + :user_delete, + :users_create, + :user_toggle_activation, + :tag_users, + :untag_users, + :right_add, + :right_delete, + :set_activation_status, + :relay_follow, + :relay_unfollow, + :revoke_invite, + :email_invite, + :config_update + ] + ) + @users_page_size 50 action_fallback(:errors) diff --git a/lib/pleroma/web/mastodon_api/controllers/list_controller.ex b/lib/pleroma/web/mastodon_api/controllers/list_controller.ex index 2873deda8..be7089630 100644 --- a/lib/pleroma/web/mastodon_api/controllers/list_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/list_controller.ex @@ -5,11 +5,20 @@ defmodule Pleroma.Web.MastodonAPI.ListController do use Pleroma.Web, :controller + alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.User alias Pleroma.Web.MastodonAPI.AccountView plug(:list_by_id_and_user when action not in [:index, :create]) + plug(OAuthScopesPlug, %{scopes: ["read:lists"]} when action in [:index, :show, :list_accounts]) + + plug( + OAuthScopesPlug, + %{scopes: ["write:lists"]} + when action in [:create, :update, :delete, :add_to_list, :remove_from_list] + ) + action_fallback(Pleroma.Web.MastodonAPI.FallbackController) # GET /api/v1/lists diff --git a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex index 118446c85..704664f5f 100644 --- a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex @@ -53,6 +53,123 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do require Logger require Pleroma.Constants + plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug when action != :index) + + @unauthenticated_access %{fallback: :proceed_unauthenticated, scopes: []} + + plug( + OAuthScopesPlug, + %{scopes: ["read"], skip_instance_privacy_check: true} when action == :index + ) + + plug( + OAuthScopesPlug, + %{scopes: ["read"]} when action in [:suggestions, :verify_app_credentials] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["write:accounts"]} + # Note: the following actions are not permission-secured in Mastodon: + when action in [ + :put_settings, + :update_avatar, + :update_banner, + :update_background, + :set_mascot + ] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["write:accounts"]} + when action in [:pin_status, :unpin_status, :update_credentials] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["read:statuses"]} + when action in [ + :conversations, + :scheduled_statuses, + :show_scheduled_status, + :home_timeline, + :dm_timeline + ] + ) + + plug( + OAuthScopesPlug, + %{@unauthenticated_access | scopes: ["read:statuses"]} + when action in [:user_statuses, :get_status, :get_context, :status_card, :get_poll] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["write:statuses"]} + when action in [ + :update_scheduled_status, + :delete_scheduled_status, + :post_status, + :delete_status, + :reblog_status, + :unreblog_status, + :poll_vote + ] + ) + + plug(OAuthScopesPlug, %{scopes: ["write:conversations"]} when action == :conversation_read) + + plug( + OAuthScopesPlug, + %{scopes: ["read:accounts"]} + when action in [:endorsements, :verify_credentials, :followers, :following, :get_mascot] + ) + + plug( + OAuthScopesPlug, + %{@unauthenticated_access | scopes: ["read:accounts"]} + when action in [:user, :favourited_by, :reblogged_by] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["read:favourites"]} when action in [:favourites, :user_favourites] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["write:favourites"]} when action in [:fav_status, :unfav_status] + ) + + plug(OAuthScopesPlug, %{scopes: ["read:filters"]} when action in [:get_filters, :get_filter]) + + plug( + OAuthScopesPlug, + %{scopes: ["write:filters"]} when action in [:create_filter, :update_filter, :delete_filter] + ) + + plug(OAuthScopesPlug, %{scopes: ["read:lists"]} when action in [:account_lists, :list_timeline]) + + plug(OAuthScopesPlug, %{scopes: ["write:media"]} when action in [:upload, :update_media]) + + plug( + OAuthScopesPlug, + %{scopes: ["read:notifications"]} when action in [:notifications, :get_notification] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["write:notifications"]} + when action in [:clear_notifications, :dismiss_notification, :destroy_multiple_notifications] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["write:reports"]} + when action in [:create_report, :report_update_state, :report_respond] + ) + plug( OAuthScopesPlug, %{scopes: ["follow", "read:blocks"]} when action in [:blocks, :domain_blocks] @@ -64,6 +181,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do when action in [:block, :unblock, :block_domain, :unblock_domain] ) + plug(OAuthScopesPlug, %{scopes: ["read:follows"]} when action == :relationships) plug(OAuthScopesPlug, %{scopes: ["follow", "read:follows"]} when action == :follow_requests) plug( @@ -84,8 +202,15 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do plug( OAuthScopesPlug, - %{scopes: ["write:mutes"]} - when action in [:mute_conversation, :unmute_conversation] + %{scopes: ["write:mutes"]} when action in [:mute_conversation, :unmute_conversation] + ) + + # Note: scopes not present in Mastodon: read:bookmarks, write:bookmarks + plug(OAuthScopesPlug, %{scopes: ["read:bookmarks"]} when action == :bookmarks) + + plug( + OAuthScopesPlug, + %{scopes: ["write:bookmarks"]} when action in [:bookmark_status, :unbookmark_status] ) @rate_limited_relations_actions ~w(follow unfollow)a @@ -776,7 +901,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end - def destroy_multiple(%{assigns: %{user: user}} = conn, %{"ids" => ids} = _params) do + def destroy_multiple_notifications(%{assigns: %{user: user}} = conn, %{"ids" => ids} = _params) do Notification.destroy_multiple(user, ids) json(conn, %{}) end @@ -1488,6 +1613,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do json(conn, %{}) end + def endorsements(conn, params), do: empty_array(conn, params) + def get_filters(%{assigns: %{user: user}} = conn, _) do filters = Filter.get_filters(user) res = FilterView.render("filters.json", filters: filters) @@ -1610,7 +1737,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end - def reports(%{assigns: %{user: user}} = conn, params) do + def create_report(%{assigns: %{user: user}} = conn, params) do case CommonAPI.report(user, params) do {:ok, activity} -> conn diff --git a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex index 9072aa7a4..f49ca89ed 100644 --- a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex @@ -6,6 +6,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do use Pleroma.Web, :controller alias Pleroma.Activity + alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.Plugs.RateLimiter alias Pleroma.Repo alias Pleroma.User @@ -15,6 +16,10 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do alias Pleroma.Web.MastodonAPI.StatusView require Logger + + # Note: Mastodon doesn't allow unauthenticated access (requires read:accounts / read:search) + plug(OAuthScopesPlug, %{scopes: ["read:search"], fallback: :proceed_unauthenticated}) + plug(RateLimiter, :search when action in [:search, :search2, :account_search]) def account_search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do diff --git a/lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex b/lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex index e2b17aab1..287eebf92 100644 --- a/lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex @@ -12,6 +12,8 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionController do action_fallback(:errors) + plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["push"]}) + # Creates PushSubscription # POST /api/v1/push/subscription # diff --git a/lib/pleroma/web/pleroma_api/pleroma_api_controller.ex b/lib/pleroma/web/pleroma_api/pleroma_api_controller.ex index f4df3b024..17c568a9d 100644 --- a/lib/pleroma/web/pleroma_api/pleroma_api_controller.ex +++ b/lib/pleroma/web/pleroma_api/pleroma_api_controller.ex @@ -9,11 +9,24 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do alias Pleroma.Conversation.Participation alias Pleroma.Notification + alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.MastodonAPI.ConversationView alias Pleroma.Web.MastodonAPI.NotificationView alias Pleroma.Web.MastodonAPI.StatusView + plug( + OAuthScopesPlug, + %{scopes: ["read:statuses"]} when action in [:conversation, :conversation_statuses] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["write:conversations"]} when action in [:conversations, :conversation_read] + ) + + plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action == :read_notification) + def conversation(%{assigns: %{user: user}} = conn, %{"id" => participation_id}) do with %Participation{} = participation <- Participation.get(participation_id), true <- user.id == participation.user_id do diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 8c93e535e..593da01fd 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -87,27 +87,6 @@ defmodule Pleroma.Web.Router do plug(Pleroma.Plugs.EnsureUserKeyPlug) end - pipeline :oauth_read_or_public do - plug(Pleroma.Plugs.OAuthScopesPlug, %{ - scopes: ["read"], - fallback: :proceed_unauthenticated - }) - - plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug) - end - - pipeline :oauth_read do - plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["read"]}) - end - - pipeline :oauth_write do - plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["write"]}) - end - - pipeline :oauth_push do - plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["push"]}) - end - pipeline :well_known do plug(:accepts, ["json", "jrd+json", "xml", "xrd+xml"]) end @@ -149,7 +128,12 @@ defmodule Pleroma.Web.Router do end scope "/api/pleroma/admin", Pleroma.Web.AdminAPI do - pipe_through([:admin_api, :oauth_write]) + pipe_through(:admin_api) + + get("/reports", AdminAPIController, :list_reports) + get("/reports/:id", AdminAPIController, :report_show) + put("/reports/:id", AdminAPIController, :report_update_state) + post("/reports/:id/respond", AdminAPIController, :report_respond) post("/users/follow", AdminAPIController, :user_follow) post("/users/unfollow", AdminAPIController, :user_unfollow) @@ -184,15 +168,6 @@ defmodule Pleroma.Web.Router do get("/users", AdminAPIController, :list_users) get("/users/:nickname", AdminAPIController, :user_show) - get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses) - - get("/reports", AdminAPIController, :list_reports) - get("/reports/:id", AdminAPIController, :report_show) - put("/reports/:id", AdminAPIController, :report_update_state) - post("/reports/:id/respond", AdminAPIController, :report_respond) - - put("/statuses/:id", AdminAPIController, :status_update) - delete("/statuses/:id", AdminAPIController, :status_delete) get("/config", AdminAPIController, :config_show) post("/config", AdminAPIController, :config_update) @@ -200,6 +175,10 @@ defmodule Pleroma.Web.Router do get("/config/migrate_from_db", AdminAPIController, :migrate_from_db) get("/moderation_log", AdminAPIController, :list_log) + + get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses) + put("/statuses/:id", AdminAPIController, :status_update) + delete("/statuses/:id", AdminAPIController, :status_delete) end scope "/", Pleroma.Web.TwitterAPI do @@ -213,19 +192,13 @@ defmodule Pleroma.Web.Router do scope "/api/pleroma", Pleroma.Web.TwitterAPI do pipe_through(:authenticated_api) - scope [] do - pipe_through(:oauth_write) + post("/change_password", UtilController, :change_password) + post("/delete_account", UtilController, :delete_account) + put("/notification_settings", UtilController, :update_notificaton_settings) + post("/disable_account", UtilController, :disable_account) - post("/change_password", UtilController, :change_password) - post("/delete_account", UtilController, :delete_account) - put("/notification_settings", UtilController, :update_notificaton_settings) - post("/disable_account", UtilController, :disable_account) - end - - scope [] do - post("/blocks_import", UtilController, :blocks_import) - post("/follow_import", UtilController, :follow_import) - end + post("/blocks_import", UtilController, :blocks_import) + post("/follow_import", UtilController, :follow_import) end scope "/oauth", Pleroma.Web.OAuth do @@ -252,148 +225,134 @@ defmodule Pleroma.Web.Router do scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do pipe_through(:authenticated_api) - scope [] do - pipe_through(:oauth_read) - get("/conversations/:id/statuses", PleromaAPIController, :conversation_statuses) - get("/conversations/:id", PleromaAPIController, :conversation) - end - - scope [] do - pipe_through(:oauth_write) - patch("/conversations/:id", PleromaAPIController, :update_conversation) - post("/notifications/read", PleromaAPIController, :read_notification) - end + get("/conversations/:id/statuses", PleromaAPIController, :conversation_statuses) + get("/conversations/:id", PleromaAPIController, :conversation) + patch("/conversations/:id", PleromaAPIController, :update_conversation) + post("/notifications/read", PleromaAPIController, :read_notification) end scope "/api/v1", Pleroma.Web.MastodonAPI do pipe_through(:authenticated_api) - scope [] do - pipe_through(:oauth_read) - - get("/accounts/verify_credentials", MastodonAPIController, :verify_credentials) - - get("/accounts/relationships", MastodonAPIController, :relationships) + get("/blocks", MastodonAPIController, :blocks) + get("/mutes", MastodonAPIController, :mutes) + get("/domain_blocks", MastodonAPIController, :domain_blocks) - get("/accounts/:id/lists", MastodonAPIController, :account_lists) - get("/accounts/:id/identity_proofs", MastodonAPIController, :empty_array) + get("/accounts/:id/lists", MastodonAPIController, :account_lists) + get("/lists", ListController, :index) + get("/lists/:id", ListController, :show) + get("/lists/:id/accounts", ListController, :list_accounts) - get("/follow_requests", MastodonAPIController, :follow_requests) - get("/blocks", MastodonAPIController, :blocks) - get("/mutes", MastodonAPIController, :mutes) + post("/notifications/clear", MastodonAPIController, :clear_notifications) + post("/notifications/dismiss", MastodonAPIController, :dismiss_notification) + get("/notifications", MastodonAPIController, :notifications) + get("/notifications/:id", MastodonAPIController, :get_notification) - get("/timelines/home", MastodonAPIController, :home_timeline) - get("/timelines/direct", MastodonAPIController, :dm_timeline) + delete( + "/notifications/destroy_multiple", + MastodonAPIController, + :destroy_multiple_notifications + ) - get("/favourites", MastodonAPIController, :favourites) - get("/bookmarks", MastodonAPIController, :bookmarks) + # Note: not present in Mastodon + get("/bookmarks", MastodonAPIController, :bookmarks) - post("/notifications/clear", MastodonAPIController, :clear_notifications) - post("/notifications/dismiss", MastodonAPIController, :dismiss_notification) - get("/notifications", MastodonAPIController, :notifications) - get("/notifications/:id", MastodonAPIController, :get_notification) - delete("/notifications/destroy_multiple", MastodonAPIController, :destroy_multiple) + get("/accounts/:id/identity_proofs", MastodonAPIController, :empty_array) - get("/scheduled_statuses", MastodonAPIController, :scheduled_statuses) - get("/scheduled_statuses/:id", MastodonAPIController, :show_scheduled_status) + get("/favourites", MastodonAPIController, :favourites) - get("/lists", ListController, :index) - get("/lists/:id", ListController, :show) - get("/lists/:id/accounts", ListController, :list_accounts) + get("/accounts/relationships", MastodonAPIController, :relationships) - get("/domain_blocks", MastodonAPIController, :domain_blocks) + get("/accounts/verify_credentials", MastodonAPIController, :verify_credentials) - get("/filters", MastodonAPIController, :get_filters) + get("/timelines/home", MastodonAPIController, :home_timeline) + get("/timelines/direct", MastodonAPIController, :dm_timeline) - get("/suggestions", MastodonAPIController, :suggestions) + get("/suggestions", MastodonAPIController, :suggestions) + get("/scheduled_statuses", MastodonAPIController, :scheduled_statuses) + get("/scheduled_statuses/:id", MastodonAPIController, :show_scheduled_status) + get("/follow_requests", MastodonAPIController, :follow_requests) + get("/filters", MastodonAPIController, :get_filters) + get("/endorsements", MastodonAPIController, :endorsements) + get("/conversations", MastodonAPIController, :conversations) + post("/conversations/:id/read", MastodonAPIController, :conversation_read) - get("/conversations", MastodonAPIController, :conversations) - post("/conversations/:id/read", MastodonAPIController, :conversation_read) + delete("/lists/:id", ListController, :delete) + post("/lists", ListController, :create) + put("/lists/:id", ListController, :update) - get("/endorsements", MastodonAPIController, :empty_array) - end + post("/lists/:id/accounts", ListController, :add_to_list) + delete("/lists/:id/accounts", ListController, :remove_from_list) - scope [] do - pipe_through(:oauth_write) + post("/reports", MastodonAPIController, :create_report) - patch("/accounts/update_credentials", MastodonAPIController, :update_credentials) + patch("/pleroma/accounts/update_avatar", MastodonAPIController, :update_avatar) + patch("/pleroma/accounts/update_banner", MastodonAPIController, :update_banner) + patch("/pleroma/accounts/update_background", MastodonAPIController, :update_background) - post("/statuses", MastodonAPIController, :post_status) - delete("/statuses/:id", MastodonAPIController, :delete_status) + get("/pleroma/mascot", MastodonAPIController, :get_mascot) + put("/pleroma/mascot", MastodonAPIController, :set_mascot) - post("/statuses/:id/reblog", MastodonAPIController, :reblog_status) - post("/statuses/:id/unreblog", MastodonAPIController, :unreblog_status) - post("/statuses/:id/favourite", MastodonAPIController, :fav_status) - post("/statuses/:id/unfavourite", MastodonAPIController, :unfav_status) - post("/statuses/:id/pin", MastodonAPIController, :pin_status) - post("/statuses/:id/unpin", MastodonAPIController, :unpin_status) - post("/statuses/:id/bookmark", MastodonAPIController, :bookmark_status) - post("/statuses/:id/unbookmark", MastodonAPIController, :unbookmark_status) - post("/statuses/:id/mute", MastodonAPIController, :mute_conversation) - post("/statuses/:id/unmute", MastodonAPIController, :unmute_conversation) + post("/media", MastodonAPIController, :upload) + put("/media/:id", MastodonAPIController, :update_media) - put("/scheduled_statuses/:id", MastodonAPIController, :update_scheduled_status) - delete("/scheduled_statuses/:id", MastodonAPIController, :delete_scheduled_status) + patch("/accounts/update_credentials", MastodonAPIController, :update_credentials) - post("/polls/:id/votes", MastodonAPIController, :poll_vote) + post("/polls/:id/votes", MastodonAPIController, :poll_vote) - post("/media", MastodonAPIController, :upload) - put("/media/:id", MastodonAPIController, :update_media) + post("/statuses/:id/reblog", MastodonAPIController, :reblog_status) + post("/statuses/:id/unreblog", MastodonAPIController, :unreblog_status) - delete("/lists/:id", ListController, :delete) - post("/lists", ListController, :create) - put("/lists/:id", ListController, :update) + post("/statuses/:id/pin", MastodonAPIController, :pin_status) + post("/statuses/:id/unpin", MastodonAPIController, :unpin_status) - post("/lists/:id/accounts", ListController, :add_to_list) - delete("/lists/:id/accounts", ListController, :remove_from_list) + post("/statuses/:id/mute", MastodonAPIController, :mute_conversation) + post("/statuses/:id/unmute", MastodonAPIController, :unmute_conversation) - post("/filters", MastodonAPIController, :create_filter) - get("/filters/:id", MastodonAPIController, :get_filter) - put("/filters/:id", MastodonAPIController, :update_filter) - delete("/filters/:id", MastodonAPIController, :delete_filter) + post("/statuses/:id/favourite", MastodonAPIController, :fav_status) + post("/statuses/:id/unfavourite", MastodonAPIController, :unfav_status) - patch("/pleroma/accounts/update_avatar", MastodonAPIController, :update_avatar) - patch("/pleroma/accounts/update_banner", MastodonAPIController, :update_banner) - patch("/pleroma/accounts/update_background", MastodonAPIController, :update_background) + post("/statuses", MastodonAPIController, :post_status) + delete("/statuses/:id", MastodonAPIController, :delete_status) - get("/pleroma/mascot", MastodonAPIController, :get_mascot) - put("/pleroma/mascot", MastodonAPIController, :set_mascot) + put("/scheduled_statuses/:id", MastodonAPIController, :update_scheduled_status) + delete("/scheduled_statuses/:id", MastodonAPIController, :delete_scheduled_status) - post("/reports", MastodonAPIController, :reports) - end + post("/filters", MastodonAPIController, :create_filter) + get("/filters/:id", MastodonAPIController, :get_filter) + put("/filters/:id", MastodonAPIController, :update_filter) + delete("/filters/:id", MastodonAPIController, :delete_filter) - scope [] do - post("/follows", MastodonAPIController, :follow) - post("/accounts/:id/follow", MastodonAPIController, :follow) + post("/follows", MastodonAPIController, :follow) + post("/accounts/:id/follow", MastodonAPIController, :follow) - post("/accounts/:id/unfollow", MastodonAPIController, :unfollow) - post("/accounts/:id/block", MastodonAPIController, :block) - post("/accounts/:id/unblock", MastodonAPIController, :unblock) - post("/accounts/:id/mute", MastodonAPIController, :mute) - post("/accounts/:id/unmute", MastodonAPIController, :unmute) + post("/accounts/:id/unfollow", MastodonAPIController, :unfollow) + post("/accounts/:id/block", MastodonAPIController, :block) + post("/accounts/:id/unblock", MastodonAPIController, :unblock) + post("/accounts/:id/mute", MastodonAPIController, :mute) + post("/accounts/:id/unmute", MastodonAPIController, :unmute) - post("/follow_requests/:id/authorize", MastodonAPIController, :authorize_follow_request) - post("/follow_requests/:id/reject", MastodonAPIController, :reject_follow_request) + post("/follow_requests/:id/authorize", MastodonAPIController, :authorize_follow_request) + post("/follow_requests/:id/reject", MastodonAPIController, :reject_follow_request) - post("/domain_blocks", MastodonAPIController, :block_domain) - delete("/domain_blocks", MastodonAPIController, :unblock_domain) + post("/domain_blocks", MastodonAPIController, :block_domain) + delete("/domain_blocks", MastodonAPIController, :unblock_domain) - post("/pleroma/accounts/:id/subscribe", MastodonAPIController, :subscribe) - post("/pleroma/accounts/:id/unsubscribe", MastodonAPIController, :unsubscribe) - end + post("/pleroma/accounts/:id/subscribe", MastodonAPIController, :subscribe) + post("/pleroma/accounts/:id/unsubscribe", MastodonAPIController, :unsubscribe) - scope [] do - pipe_through(:oauth_push) + post("/push/subscription", SubscriptionController, :create) + get("/push/subscription", SubscriptionController, :get) + put("/push/subscription", SubscriptionController, :update) + delete("/push/subscription", SubscriptionController, :delete) - post("/push/subscription", SubscriptionController, :create) - get("/push/subscription", SubscriptionController, :get) - put("/push/subscription", SubscriptionController, :update) - delete("/push/subscription", SubscriptionController, :delete) - end + # Note: not present in Mastodon: bookmark, unbookmark + post("/statuses/:id/bookmark", MastodonAPIController, :bookmark_status) + post("/statuses/:id/unbookmark", MastodonAPIController, :unbookmark_status) end scope "/api/web", Pleroma.Web.MastodonAPI do - pipe_through([:authenticated_api, :oauth_write]) + pipe_through(:authenticated_api) put("/settings", MastodonAPIController, :put_settings) end @@ -424,31 +383,29 @@ defmodule Pleroma.Web.Router do :account_confirmation_resend ) - scope [] do - pipe_through(:oauth_read_or_public) + get("/timelines/public", MastodonAPIController, :public_timeline) + get("/timelines/tag/:tag", MastodonAPIController, :hashtag_timeline) - get("/timelines/public", MastodonAPIController, :public_timeline) - get("/timelines/tag/:tag", MastodonAPIController, :hashtag_timeline) - get("/timelines/list/:list_id", MastodonAPIController, :list_timeline) + get("/pleroma/accounts/:id/favourites", MastodonAPIController, :user_favourites) - get("/statuses/:id", MastodonAPIController, :get_status) - get("/statuses/:id/context", MastodonAPIController, :get_context) + get("/search", SearchController, :search) - get("/polls/:id", MastodonAPIController, :get_poll) + get("/polls/:id", MastodonAPIController, :get_poll) - get("/accounts/:id/statuses", MastodonAPIController, :user_statuses) - get("/accounts/:id/followers", MastodonAPIController, :followers) - get("/accounts/:id/following", MastodonAPIController, :following) - get("/accounts/:id", MastodonAPIController, :user) + get("/accounts/:id/followers", MastodonAPIController, :followers) + get("/accounts/:id/following", MastodonAPIController, :following) - get("/search", SearchController, :search) + get("/timelines/list/:list_id", MastodonAPIController, :list_timeline) - get("/pleroma/accounts/:id/favourites", MastodonAPIController, :user_favourites) - end + get("/accounts/:id", MastodonAPIController, :user) + + get("/accounts/:id/statuses", MastodonAPIController, :user_statuses) + get("/statuses/:id", MastodonAPIController, :get_status) + get("/statuses/:id/context", MastodonAPIController, :get_context) end scope "/api/v2", Pleroma.Web.MastodonAPI do - pipe_through([:api, :oauth_read_or_public]) + pipe_through(:api) get("/search", SearchController, :search2) end @@ -478,12 +435,7 @@ defmodule Pleroma.Web.Router do get("/oauth_tokens", TwitterAPI.Controller, :oauth_tokens) delete("/oauth_tokens/:id", TwitterAPI.Controller, :revoke_token) - - scope [] do - pipe_through(:oauth_read) - - post("/qvitter/statuses/notifications/read", TwitterAPI.Controller, :notifications_read) - end + post("/qvitter/statuses/notifications/read", TwitterAPI.Controller, :notifications_read) end pipeline :ap_service_actor do @@ -547,26 +499,16 @@ defmodule Pleroma.Web.Router do scope "/", Pleroma.Web.ActivityPub do pipe_through([:activitypub_client]) - scope [] do - pipe_through(:oauth_read) - get("/api/ap/whoami", ActivityPubController, :whoami) - get("/users/:nickname/inbox", ActivityPubController, :read_inbox) - end - - scope [] do - pipe_through(:oauth_write) - post("/users/:nickname/outbox", ActivityPubController, :update_outbox) - end - - scope [] do - pipe_through(:oauth_read_or_public) - get("/users/:nickname/followers", ActivityPubController, :followers) - get("/users/:nickname/following", ActivityPubController, :following) - end + get("/api/ap/whoami", ActivityPubController, :whoami) + get("/users/:nickname/inbox", ActivityPubController, :read_inbox) + post("/users/:nickname/outbox", ActivityPubController, :update_outbox) + get("/users/:nickname/followers", ActivityPubController, :followers) + get("/users/:nickname/following", ActivityPubController, :following) end scope "/", Pleroma.Web.ActivityPub do pipe_through(:activitypub) + post("/inbox", ActivityPubController, :inbox) post("/users/:nickname/inbox", ActivityPubController, :inbox) end @@ -612,10 +554,7 @@ defmodule Pleroma.Web.Router do post("/auth/password", MastodonAPIController, :password_reset) - scope [] do - pipe_through(:oauth_read) - get("/web/*path", MastodonAPIController, :index) - end + get("/web/*path", MastodonAPIController, :index) end pipeline :remote_media do diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex index 1c6ad5057..82ed0c287 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -27,6 +27,17 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do plug(OAuthScopesPlug, %{scopes: ["follow", "write:blocks"]} when action == :blocks_import) + plug( + OAuthScopesPlug, + %{scopes: ["write:accounts"]} + when action in [ + :change_password, + :delete_account, + :update_notificaton_settings, + :disable_account + ] + ) + plug(Pleroma.Plugs.SetFormatPlug when action in [:config, :version]) def help_test(conn, _params) do diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index 42234ae09..42bd74eb5 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -7,12 +7,15 @@ defmodule Pleroma.Web.TwitterAPI.Controller do alias Ecto.Changeset alias Pleroma.Notification + alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.User alias Pleroma.Web.OAuth.Token alias Pleroma.Web.TwitterAPI.TokenView require Logger + plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action == :notifications_read) + action_fallback(:errors) def confirm_email(conn, %{"user_id" => uid, "token" => token}) do -- cgit v1.2.3 From e7afb67c5c26fcb07c1f8d4390c0573cebef9520 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Tue, 17 Sep 2019 16:16:11 +0300 Subject: [#1260] Rate-limiting for create authentication and related requests. --- lib/pleroma/web/mongooseim/mongoose_im_controller.ex | 5 +++++ lib/pleroma/web/oauth/oauth_controller.ex | 1 + 2 files changed, 6 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/web/mongooseim/mongoose_im_controller.ex b/lib/pleroma/web/mongooseim/mongoose_im_controller.ex index b786a521b..6ed181cff 100644 --- a/lib/pleroma/web/mongooseim/mongoose_im_controller.ex +++ b/lib/pleroma/web/mongooseim/mongoose_im_controller.ex @@ -4,10 +4,15 @@ defmodule Pleroma.Web.MongooseIM.MongooseIMController do use Pleroma.Web, :controller + alias Comeonin.Pbkdf2 + alias Pleroma.Plugs.RateLimiter alias Pleroma.Repo alias Pleroma.User + plug(RateLimiter, :authentication when action in [:user_exists, :check_password]) + plug(RateLimiter, {:authentication, params: ["user"]} when action == :check_password) + def user_exists(conn, %{"user" => username}) do with %User{} <- Repo.get_by(User, nickname: username, local: true) do conn diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index 81eae2c8b..281c7d2d8 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -24,6 +24,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do plug(:fetch_session) plug(:fetch_flash) + plug(Pleroma.Plugs.RateLimiter, :authentication when action == :create_authorization) action_fallback(Pleroma.Web.OAuth.FallbackController) -- cgit v1.2.3 From 76068873dbf9da191dd2487158ca88df198b811a Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Tue, 17 Sep 2019 22:19:39 +0300 Subject: [#1234] Defined admin OAuth scopes, refined other scopes. Added tests. --- lib/pleroma/web/admin_api/admin_api_controller.ex | 71 +++++++++++++--------- .../controllers/mastodon_api_controller.ex | 23 ++++++- 2 files changed, 61 insertions(+), 33 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex index 0a508d40e..fa69a23d9 100644 --- a/lib/pleroma/web/admin_api/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/admin_api_controller.ex @@ -24,38 +24,20 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do require Logger - plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action == :list_user_statuses) - plug( OAuthScopesPlug, - %{scopes: ["write:statuses"]} when action in [:status_update, :status_delete] + %{scopes: ["admin:read:accounts", "read:accounts"]} + when action in [:list_users, :user_show, :right_get, :invites] ) plug( OAuthScopesPlug, - %{scopes: ["read"]} + %{scopes: ["admin:write", "write:accounts"]} when action in [ - :list_reports, - :report_show, - :right_get, :get_invite_token, - :invites, + :revoke_invite, + :email_invite, :get_password_reset, - :list_users, - :user_show, - :config_show, - :migrate_to_db, - :migrate_from_db, - :list_log - ] - ) - - plug( - OAuthScopesPlug, - %{scopes: ["write"]} - when action in [ - :report_update_state, - :report_respond, :user_follow, :user_unfollow, :user_delete, @@ -65,15 +47,44 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do :untag_users, :right_add, :right_delete, - :set_activation_status, - :relay_follow, - :relay_unfollow, - :revoke_invite, - :email_invite, - :config_update + :set_activation_status ] ) + plug( + OAuthScopesPlug, + %{scopes: ["admin:read:reports", "read:reports"]} when action in [:list_reports, :report_show] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["admin:write:reports", "write:reports"]} + when action in [:report_update_state, :report_respond] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["admin:read:statuses", "read:statuses"]} when action == :list_user_statuses + ) + + plug( + OAuthScopesPlug, + %{scopes: ["admin:write:statuses", "write:statuses"]} + when action in [:status_update, :status_delete] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["admin:read", "read"]} + when action in [:config_show, :migrate_to_db, :migrate_from_db, :list_log] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["admin:write", "write"]} + when action in [:relay_follow, :relay_unfollow, :config_update] + ) + @users_page_size 50 action_fallback(:errors) @@ -451,7 +462,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do end end - @doc "Get a account registeration invite token (base64 string)" + @doc "Get a account registration invite token (base64 string)" def get_invite_token(conn, params) do options = params["invite"] || %{} {:ok, invite} = UserInviteToken.create_invite(options) diff --git a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex index c5632bb5e..d7a83a2f5 100644 --- a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex @@ -53,13 +53,13 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do require Logger require Pleroma.Constants - plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug when action != :index) - @unauthenticated_access %{fallback: :proceed_unauthenticated, scopes: []} + # Note: :index action handles attempt of unauthenticated access to private instance with redirect plug( OAuthScopesPlug, - %{scopes: ["read"], skip_instance_privacy_check: true} when action == :index + Map.merge(@unauthenticated_access, %{scopes: ["read"], skip_instance_privacy_check: true}) + when action == :index ) plug( @@ -220,6 +220,23 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do %{scopes: ["write:bookmarks"]} when action in [:bookmark_status, :unbookmark_status] ) + # An extra safety measure for possible actions not guarded by OAuth permissions specification + plug( + Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug + when action not in [ + :account_register, + :create_app, + :index, + :login, + :logout, + :password_reset, + :account_confirmation_resend, + :masto_instance, + :peers, + :custom_emojis + ] + ) + @rate_limited_relations_actions ~w(follow unfollow)a @rate_limited_status_actions ~w(reblog_status unreblog_status fav_status unfav_status -- cgit v1.2.3 From b4d775161cdbd1e72ed9bdf3363090c30e8c25fc Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Tue, 17 Sep 2019 23:24:55 +0300 Subject: [#1234] Undone reordering-related changes in router.ex. --- lib/pleroma/web/router.ex | 160 ++++++++++++++++++++++++---------------------- 1 file changed, 82 insertions(+), 78 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 6e80efec4..8448a00a1 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -131,11 +131,6 @@ defmodule Pleroma.Web.Router do scope "/api/pleroma/admin", Pleroma.Web.AdminAPI do pipe_through(:admin_api) - get("/reports", AdminAPIController, :list_reports) - get("/reports/:id", AdminAPIController, :report_show) - put("/reports/:id", AdminAPIController, :report_update_state) - post("/reports/:id/respond", AdminAPIController, :report_respond) - post("/users/follow", AdminAPIController, :user_follow) post("/users/unfollow", AdminAPIController, :user_unfollow) @@ -169,6 +164,15 @@ defmodule Pleroma.Web.Router do get("/users", AdminAPIController, :list_users) get("/users/:nickname", AdminAPIController, :user_show) + get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses) + + get("/reports", AdminAPIController, :list_reports) + get("/reports/:id", AdminAPIController, :report_show) + put("/reports/:id", AdminAPIController, :report_update_state) + post("/reports/:id/respond", AdminAPIController, :report_respond) + + put("/statuses/:id", AdminAPIController, :status_update) + delete("/statuses/:id", AdminAPIController, :status_delete) get("/config", AdminAPIController, :config_show) post("/config", AdminAPIController, :config_update) @@ -176,10 +180,6 @@ defmodule Pleroma.Web.Router do get("/config/migrate_from_db", AdminAPIController, :migrate_from_db) get("/moderation_log", AdminAPIController, :list_log) - - get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses) - put("/statuses/:id", AdminAPIController, :status_update) - delete("/statuses/:id", AdminAPIController, :status_delete) end scope "/", Pleroma.Web.TwitterAPI do @@ -229,6 +229,7 @@ defmodule Pleroma.Web.Router do get("/conversations/:id/statuses", PleromaAPIController, :conversation_statuses) get("/conversations/:id", PleromaAPIController, :conversation) + patch("/conversations/:id", PleromaAPIController, :update_conversation) post("/notifications/read", PleromaAPIController, :read_notification) end @@ -236,14 +237,23 @@ defmodule Pleroma.Web.Router do scope "/api/v1", Pleroma.Web.MastodonAPI do pipe_through(:authenticated_api) + get("/accounts/verify_credentials", MastodonAPIController, :verify_credentials) + + get("/accounts/relationships", MastodonAPIController, :relationships) + + get("/accounts/:id/lists", MastodonAPIController, :account_lists) + get("/accounts/:id/identity_proofs", MastodonAPIController, :empty_array) + + get("/follow_requests", MastodonAPIController, :follow_requests) get("/blocks", MastodonAPIController, :blocks) get("/mutes", MastodonAPIController, :mutes) - get("/domain_blocks", MastodonAPIController, :domain_blocks) - get("/accounts/:id/lists", MastodonAPIController, :account_lists) - get("/lists", ListController, :index) - get("/lists/:id", ListController, :show) - get("/lists/:id/accounts", ListController, :list_accounts) + get("/timelines/home", MastodonAPIController, :home_timeline) + get("/timelines/direct", MastodonAPIController, :dm_timeline) + + get("/favourites", MastodonAPIController, :favourites) + # Note: not present in Mastodon: bookmarks + get("/bookmarks", MastodonAPIController, :bookmarks) post("/notifications/clear", MastodonAPIController, :clear_notifications) post("/notifications/dismiss", MastodonAPIController, :dismiss_notification) @@ -256,75 +266,71 @@ defmodule Pleroma.Web.Router do :destroy_multiple_notifications ) - # Note: not present in Mastodon - get("/bookmarks", MastodonAPIController, :bookmarks) - - get("/accounts/:id/identity_proofs", MastodonAPIController, :empty_array) - - get("/favourites", MastodonAPIController, :favourites) - - get("/accounts/relationships", MastodonAPIController, :relationships) - - get("/accounts/verify_credentials", MastodonAPIController, :verify_credentials) - - get("/timelines/home", MastodonAPIController, :home_timeline) - get("/timelines/direct", MastodonAPIController, :dm_timeline) - - get("/suggestions", MastodonAPIController, :suggestions) get("/scheduled_statuses", MastodonAPIController, :scheduled_statuses) get("/scheduled_statuses/:id", MastodonAPIController, :show_scheduled_status) - get("/follow_requests", MastodonAPIController, :follow_requests) - get("/filters", MastodonAPIController, :get_filters) - get("/endorsements", MastodonAPIController, :endorsements) - get("/conversations", MastodonAPIController, :conversations) - post("/conversations/:id/read", MastodonAPIController, :conversation_read) - delete("/lists/:id", ListController, :delete) - post("/lists", ListController, :create) - put("/lists/:id", ListController, :update) + get("/lists", ListController, :index) + get("/lists/:id", ListController, :show) + get("/lists/:id/accounts", ListController, :list_accounts) - post("/lists/:id/accounts", ListController, :add_to_list) - delete("/lists/:id/accounts", ListController, :remove_from_list) + get("/domain_blocks", MastodonAPIController, :domain_blocks) - post("/reports", MastodonAPIController, :create_report) + get("/filters", MastodonAPIController, :get_filters) - patch("/pleroma/accounts/update_avatar", MastodonAPIController, :update_avatar) - patch("/pleroma/accounts/update_banner", MastodonAPIController, :update_banner) - patch("/pleroma/accounts/update_background", MastodonAPIController, :update_background) + get("/suggestions", MastodonAPIController, :suggestions) - get("/pleroma/mascot", MastodonAPIController, :get_mascot) - put("/pleroma/mascot", MastodonAPIController, :set_mascot) + get("/conversations", MastodonAPIController, :conversations) + post("/conversations/:id/read", MastodonAPIController, :conversation_read) - post("/media", MastodonAPIController, :upload) - put("/media/:id", MastodonAPIController, :update_media) + get("/endorsements", MastodonAPIController, :endorsements) patch("/accounts/update_credentials", MastodonAPIController, :update_credentials) - post("/polls/:id/votes", MastodonAPIController, :poll_vote) + post("/statuses", MastodonAPIController, :post_status) + delete("/statuses/:id", MastodonAPIController, :delete_status) post("/statuses/:id/reblog", MastodonAPIController, :reblog_status) post("/statuses/:id/unreblog", MastodonAPIController, :unreblog_status) - + post("/statuses/:id/favourite", MastodonAPIController, :fav_status) + post("/statuses/:id/unfavourite", MastodonAPIController, :unfav_status) post("/statuses/:id/pin", MastodonAPIController, :pin_status) post("/statuses/:id/unpin", MastodonAPIController, :unpin_status) - + # Note: not present in Mastodon: bookmark + post("/statuses/:id/bookmark", MastodonAPIController, :bookmark_status) + # Note: not present in Mastodon: unbookmark + post("/statuses/:id/unbookmark", MastodonAPIController, :unbookmark_status) post("/statuses/:id/mute", MastodonAPIController, :mute_conversation) post("/statuses/:id/unmute", MastodonAPIController, :unmute_conversation) - post("/statuses/:id/favourite", MastodonAPIController, :fav_status) - post("/statuses/:id/unfavourite", MastodonAPIController, :unfav_status) - - post("/statuses", MastodonAPIController, :post_status) - delete("/statuses/:id", MastodonAPIController, :delete_status) - put("/scheduled_statuses/:id", MastodonAPIController, :update_scheduled_status) delete("/scheduled_statuses/:id", MastodonAPIController, :delete_scheduled_status) + post("/polls/:id/votes", MastodonAPIController, :poll_vote) + + post("/media", MastodonAPIController, :upload) + put("/media/:id", MastodonAPIController, :update_media) + + delete("/lists/:id", ListController, :delete) + post("/lists", ListController, :create) + put("/lists/:id", ListController, :update) + + post("/lists/:id/accounts", ListController, :add_to_list) + delete("/lists/:id/accounts", ListController, :remove_from_list) + post("/filters", MastodonAPIController, :create_filter) get("/filters/:id", MastodonAPIController, :get_filter) put("/filters/:id", MastodonAPIController, :update_filter) delete("/filters/:id", MastodonAPIController, :delete_filter) + patch("/pleroma/accounts/update_avatar", MastodonAPIController, :update_avatar) + patch("/pleroma/accounts/update_banner", MastodonAPIController, :update_banner) + patch("/pleroma/accounts/update_background", MastodonAPIController, :update_background) + + get("/pleroma/mascot", MastodonAPIController, :get_mascot) + put("/pleroma/mascot", MastodonAPIController, :set_mascot) + + post("/reports", MastodonAPIController, :create_report) + post("/follows", MastodonAPIController, :follow) post("/accounts/:id/follow", MastodonAPIController, :follow) @@ -347,10 +353,6 @@ defmodule Pleroma.Web.Router do get("/push/subscription", SubscriptionController, :get) put("/push/subscription", SubscriptionController, :update) delete("/push/subscription", SubscriptionController, :delete) - - # Note: not present in Mastodon: bookmark, unbookmark - post("/statuses/:id/bookmark", MastodonAPIController, :bookmark_status) - post("/statuses/:id/unbookmark", MastodonAPIController, :unbookmark_status) end scope "/api/web", Pleroma.Web.MastodonAPI do @@ -362,46 +364,47 @@ defmodule Pleroma.Web.Router do scope "/api/v1", Pleroma.Web.MastodonAPI do pipe_through(:api) + post("/accounts", MastodonAPIController, :account_register) + 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) + + get("/statuses/:id/favourited_by", MastodonAPIController, :favourited_by) + get("/statuses/:id/reblogged_by", MastodonAPIController, :reblogged_by) + get("/trends", MastodonAPIController, :empty_array) get("/accounts/search", SearchController, :account_search) + post( + "/pleroma/accounts/confirmation_resend", + MastodonAPIController, + :account_confirmation_resend + ) + get("/timelines/public", MastodonAPIController, :public_timeline) get("/timelines/tag/:tag", MastodonAPIController, :hashtag_timeline) get("/timelines/list/:list_id", MastodonAPIController, :list_timeline) + get("/statuses", MastodonAPIController, :get_statuses) + get("/statuses/:id", MastodonAPIController, :get_status) + get("/statuses/:id/context", MastodonAPIController, :get_context) + get("/polls/:id", MastodonAPIController, :get_poll) - post("/accounts", MastodonAPIController, :account_register) - get("/accounts/:id", MastodonAPIController, :user) + get("/accounts/:id/statuses", MastodonAPIController, :user_statuses) get("/accounts/:id/followers", MastodonAPIController, :followers) get("/accounts/:id/following", MastodonAPIController, :following) - get("/accounts/:id/statuses", MastodonAPIController, :user_statuses) + get("/accounts/:id", MastodonAPIController, :user) get("/search", SearchController, :search) - get("/statuses", MastodonAPIController, :get_statuses) - get("/statuses/:id", MastodonAPIController, :get_status) - get("/statuses/:id/context", MastodonAPIController, :get_context) - get("/statuses/:id/card", MastodonAPIController, :status_card) - get("/statuses/:id/favourited_by", MastodonAPIController, :favourited_by) - get("/statuses/:id/reblogged_by", MastodonAPIController, :reblogged_by) - get("/pleroma/accounts/:id/favourites", MastodonAPIController, :user_favourites) - - post( - "/pleroma/accounts/confirmation_resend", - MastodonAPIController, - :account_confirmation_resend - ) end scope "/api/v2", Pleroma.Web.MastodonAPI do @@ -435,6 +438,7 @@ defmodule Pleroma.Web.Router do get("/oauth_tokens", TwitterAPI.Controller, :oauth_tokens) delete("/oauth_tokens/:id", TwitterAPI.Controller, :revoke_token) + post("/qvitter/statuses/notifications/read", TwitterAPI.Controller, :notifications_read) end -- cgit v1.2.3 From 551f2fa59eec11c94eb0ab187c06ccab7b8d5647 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Wed, 18 Sep 2019 12:31:33 +0300 Subject: [#1234] Added changelog entry, removed admin OAuth scopes. --- lib/pleroma/web/admin_api/admin_api_controller.ex | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex index 2c9840580..7f1a8e566 100644 --- a/lib/pleroma/web/admin_api/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/admin_api_controller.ex @@ -26,13 +26,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do plug( OAuthScopesPlug, - %{scopes: ["admin:read:accounts", "read:accounts"]} + %{scopes: ["read:accounts"]} when action in [:list_users, :user_show, :right_get, :invites] ) plug( OAuthScopesPlug, - %{scopes: ["admin:write", "write:accounts"]} + %{scopes: ["write:accounts"]} when action in [ :get_invite_token, :revoke_invite, @@ -53,35 +53,35 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do plug( OAuthScopesPlug, - %{scopes: ["admin:read:reports", "read:reports"]} when action in [:list_reports, :report_show] + %{scopes: ["read:reports"]} when action in [:list_reports, :report_show] ) plug( OAuthScopesPlug, - %{scopes: ["admin:write:reports", "write:reports"]} + %{scopes: ["write:reports"]} when action in [:report_update_state, :report_respond] ) plug( OAuthScopesPlug, - %{scopes: ["admin:read:statuses", "read:statuses"]} when action == :list_user_statuses + %{scopes: ["read:statuses"]} when action == :list_user_statuses ) plug( OAuthScopesPlug, - %{scopes: ["admin:write:statuses", "write:statuses"]} + %{scopes: ["write:statuses"]} when action in [:status_update, :status_delete] ) plug( OAuthScopesPlug, - %{scopes: ["admin:read", "read"]} + %{scopes: ["read"]} when action in [:config_show, :migrate_to_db, :migrate_from_db, :list_log] ) plug( OAuthScopesPlug, - %{scopes: ["admin:write", "write"]} + %{scopes: ["write"]} when action in [:relay_follow, :relay_unfollow, :config_update] ) -- cgit v1.2.3 From e4f3d7f69d5d3db787f8b4906cacc673e2f970f1 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Wed, 18 Sep 2019 10:31:10 +0000 Subject: Apply suggestion to lib/pleroma/plugs/oauth_scopes_plug.ex --- lib/pleroma/plugs/oauth_scopes_plug.ex | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/plugs/oauth_scopes_plug.ex b/lib/pleroma/plugs/oauth_scopes_plug.ex index e0d61c4eb..a3278dbef 100644 --- a/lib/pleroma/plugs/oauth_scopes_plug.ex +++ b/lib/pleroma/plugs/oauth_scopes_plug.ex @@ -61,9 +61,10 @@ defmodule Pleroma.Plugs.OAuthScopesPlug do end defp maybe_perform_instance_privacy_check(%Plug.Conn{} = conn, options) do - case options[:skip_instance_privacy_check] do - true -> conn - _ -> EnsurePublicOrAuthenticatedPlug.call(conn, []) + if options[:skip_instance_privacy_check] do + conn + else + EnsurePublicOrAuthenticatedPlug.call(conn, []) end end end -- cgit v1.2.3 From 75290cbfbd0f93cf3ecec5f44c4624b8c8601c51 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Thu, 26 Sep 2019 18:49:57 +0700 Subject: Add Pleroma.JobQueueMonitor --- lib/pleroma/application.ex | 1 + lib/pleroma/healthcheck.ex | 8 +++ lib/pleroma/job_queue_monitor.ex | 115 +++++++++++++++++++++++++++++++++++ lib/pleroma/workers/worker_helper.ex | 1 + 4 files changed, 125 insertions(+) create mode 100644 lib/pleroma/job_queue_monitor.ex (limited to 'lib') diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index 7aec2c545..3e21d4403 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -42,6 +42,7 @@ defmodule Pleroma.Application do hackney_pool_children() ++ [ Pleroma.Stats, + Pleroma.JobQueueMonitor, {Oban, Pleroma.Config.get(Oban)} ] ++ task_children(@env) ++ diff --git a/lib/pleroma/healthcheck.ex b/lib/pleroma/healthcheck.ex index 977b78c26..fc2129815 100644 --- a/lib/pleroma/healthcheck.ex +++ b/lib/pleroma/healthcheck.ex @@ -14,6 +14,7 @@ defmodule Pleroma.Healthcheck do active: 0, idle: 0, memory_used: 0, + job_queue_stats: nil, healthy: true @type t :: %__MODULE__{ @@ -21,6 +22,7 @@ defmodule Pleroma.Healthcheck do active: non_neg_integer(), idle: non_neg_integer(), memory_used: number(), + job_queue_stats: map(), healthy: boolean() } @@ -30,6 +32,7 @@ defmodule Pleroma.Healthcheck do memory_used: Float.round(:erlang.memory(:total) / 1024 / 1024, 2) } |> assign_db_info() + |> assign_job_queue_stats() |> check_health() end @@ -55,6 +58,11 @@ defmodule Pleroma.Healthcheck do Map.merge(healthcheck, db_info) end + defp assign_job_queue_stats(healthcheck) do + stats = Pleroma.JobQueueMonitor.stats() + Map.put(healthcheck, :job_queue_stats, stats) + end + @spec check_health(Healthcheck.t()) :: Healthcheck.t() def check_health(%{pool_size: pool_size, active: active} = check) when active >= pool_size do diff --git a/lib/pleroma/job_queue_monitor.ex b/lib/pleroma/job_queue_monitor.ex new file mode 100644 index 000000000..685ba2ead --- /dev/null +++ b/lib/pleroma/job_queue_monitor.ex @@ -0,0 +1,115 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.JobQueueMonitor do + use GenServer + + @initial_state %{workers: %{}, queues: %{}, processed_jobs: 0, enqueued: 0} + @queue %{processed_jobs: 0, success: 0, failure: 0, enqueued: 0} + @operation %{processed_jobs: 0, success: 0, failure: 0, enqueued: 0} + + def start_link(_) do + GenServer.start_link(__MODULE__, @initial_state, name: __MODULE__) + end + + @impl true + def init(state) do + :telemetry.attach("oban-monitor-failure", [:oban, :failure], &handle_event/4, nil) + :telemetry.attach("oban-monitor-success", [:oban, :success], &handle_event/4, nil) + + {:ok, state} + end + + def stats do + GenServer.call(__MODULE__, :stats) + end + + def enqueue({:ok, job}) do + meta = Map.take(job, [:args, :queue, :worker]) + GenServer.cast(__MODULE__, {:process_enqueue, meta}) + + {:ok, job} + end + + def enqueue(result), do: result + + def handle_event([:oban, status], %{duration: duration}, meta, _) do + GenServer.cast(__MODULE__, {:process_event, status, duration, meta}) + end + + @impl true + def handle_call(:stats, _from, state) do + {:reply, state, state} + end + + def handle_cast({:process_enqueue, meta}, state) do + state = + state + |> Map.update!(:workers, fn workers -> + workers + |> Map.put_new(meta.worker, %{}) + |> Map.update!(meta.worker, &update_worker(&1, :enqueue, meta)) + end) + |> Map.update!(:queues, fn workers -> + workers + |> Map.put_new(meta.queue, @queue) + |> Map.update!(meta.queue, fn queue -> Map.update!(queue, :enqueued, &(&1 + 1)) end) + end) + |> Map.update!(:enqueued, &(&1 + 1)) + + {:noreply, state} + end + + @impl true + def handle_cast({:process_event, status, duration, meta}, state) do + state = + state + |> Map.update!(:workers, fn workers -> + workers + |> Map.put_new(meta.worker, %{}) + |> Map.update!(meta.worker, &update_worker(&1, status, meta, duration)) + end) + |> Map.update!(:queues, fn workers -> + workers + |> Map.put_new(meta.queue, @queue) + |> Map.update!(meta.queue, &update_queue(&1, status, meta, duration)) + end) + |> Map.update!(:processed_jobs, &(&1 + 1)) + |> decr_enqueued() + + {:noreply, state} + end + + defp update_worker(worker, status, meta, duration \\ 0) do + worker + |> Map.put_new(meta.args["op"], @operation) + |> Map.update!(meta.args["op"], &update_op(&1, status, meta, duration)) + end + + defp update_op(op, :enqueue, _meta, _duration) do + op + |> Map.update!(:enqueued, &(&1 + 1)) + end + + defp update_op(op, status, _meta, _duration) do + op + |> Map.update!(:processed_jobs, &(&1 + 1)) + |> Map.update!(status, &(&1 + 1)) + |> decr_enqueued() + end + + defp update_queue(queue, status, _meta, _duration) do + queue + |> Map.update!(:processed_jobs, &(&1 + 1)) + |> Map.update!(status, &(&1 + 1)) + |> decr_enqueued() + end + + defp decr_enqueued(map) do + Map.update!(map, :enqueued, fn + 0 -> 0 + enqueued -> enqueued - 1 + end) + end +end diff --git a/lib/pleroma/workers/worker_helper.ex b/lib/pleroma/workers/worker_helper.ex index 358efa14a..a43ce8bc0 100644 --- a/lib/pleroma/workers/worker_helper.ex +++ b/lib/pleroma/workers/worker_helper.ex @@ -40,6 +40,7 @@ defmodule Pleroma.Workers.WorkerHelper do unquote(caller_module) |> apply(:new, [params, worker_args]) |> Pleroma.Repo.insert() + |> Pleroma.JobQueueMonitor.enqueue() end end end -- cgit v1.2.3 From 26693292f4b2062504fc9a24e824a6f56cb6b555 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Wed, 2 Oct 2019 14:50:25 +0700 Subject: Remove `:enqueued` counter --- lib/pleroma/job_queue_monitor.ex | 45 ++++-------------------------------- lib/pleroma/workers/worker_helper.ex | 1 - 2 files changed, 4 insertions(+), 42 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/job_queue_monitor.ex b/lib/pleroma/job_queue_monitor.ex index 685ba2ead..3feea8381 100644 --- a/lib/pleroma/job_queue_monitor.ex +++ b/lib/pleroma/job_queue_monitor.ex @@ -5,9 +5,9 @@ defmodule Pleroma.JobQueueMonitor do use GenServer - @initial_state %{workers: %{}, queues: %{}, processed_jobs: 0, enqueued: 0} - @queue %{processed_jobs: 0, success: 0, failure: 0, enqueued: 0} - @operation %{processed_jobs: 0, success: 0, failure: 0, enqueued: 0} + @initial_state %{workers: %{}, queues: %{}, processed_jobs: 0} + @queue %{processed_jobs: 0, success: 0, failure: 0} + @operation %{processed_jobs: 0, success: 0, failure: 0} def start_link(_) do GenServer.start_link(__MODULE__, @initial_state, name: __MODULE__) @@ -25,15 +25,6 @@ defmodule Pleroma.JobQueueMonitor do GenServer.call(__MODULE__, :stats) end - def enqueue({:ok, job}) do - meta = Map.take(job, [:args, :queue, :worker]) - GenServer.cast(__MODULE__, {:process_enqueue, meta}) - - {:ok, job} - end - - def enqueue(result), do: result - def handle_event([:oban, status], %{duration: duration}, meta, _) do GenServer.cast(__MODULE__, {:process_event, status, duration, meta}) end @@ -43,24 +34,6 @@ defmodule Pleroma.JobQueueMonitor do {:reply, state, state} end - def handle_cast({:process_enqueue, meta}, state) do - state = - state - |> Map.update!(:workers, fn workers -> - workers - |> Map.put_new(meta.worker, %{}) - |> Map.update!(meta.worker, &update_worker(&1, :enqueue, meta)) - end) - |> Map.update!(:queues, fn workers -> - workers - |> Map.put_new(meta.queue, @queue) - |> Map.update!(meta.queue, fn queue -> Map.update!(queue, :enqueued, &(&1 + 1)) end) - end) - |> Map.update!(:enqueued, &(&1 + 1)) - - {:noreply, state} - end - @impl true def handle_cast({:process_event, status, duration, meta}, state) do state = @@ -76,12 +49,11 @@ defmodule Pleroma.JobQueueMonitor do |> Map.update!(meta.queue, &update_queue(&1, status, meta, duration)) end) |> Map.update!(:processed_jobs, &(&1 + 1)) - |> decr_enqueued() {:noreply, state} end - defp update_worker(worker, status, meta, duration \\ 0) do + defp update_worker(worker, status, meta, duration) do worker |> Map.put_new(meta.args["op"], @operation) |> Map.update!(meta.args["op"], &update_op(&1, status, meta, duration)) @@ -96,20 +68,11 @@ defmodule Pleroma.JobQueueMonitor do op |> Map.update!(:processed_jobs, &(&1 + 1)) |> Map.update!(status, &(&1 + 1)) - |> decr_enqueued() end defp update_queue(queue, status, _meta, _duration) do queue |> Map.update!(:processed_jobs, &(&1 + 1)) |> Map.update!(status, &(&1 + 1)) - |> decr_enqueued() - end - - defp decr_enqueued(map) do - Map.update!(map, :enqueued, fn - 0 -> 0 - enqueued -> enqueued - 1 - end) end end diff --git a/lib/pleroma/workers/worker_helper.ex b/lib/pleroma/workers/worker_helper.ex index a43ce8bc0..358efa14a 100644 --- a/lib/pleroma/workers/worker_helper.ex +++ b/lib/pleroma/workers/worker_helper.ex @@ -40,7 +40,6 @@ defmodule Pleroma.Workers.WorkerHelper do unquote(caller_module) |> apply(:new, [params, worker_args]) |> Pleroma.Repo.insert() - |> Pleroma.JobQueueMonitor.enqueue() end end end -- cgit v1.2.3 From 7f2bc577250ccea26c133502787d0bbdcbc839ee Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Tue, 1 Oct 2019 17:15:58 +0700 Subject: Move `follows`, `mutes` and `blocks` actions to AccountController --- .../mastodon_api/controllers/account_controller.ex | 22 +++++++++++++++ .../controllers/mastodon_api_controller.ex | 33 ---------------------- lib/pleroma/web/router.ex | 6 ++-- 3 files changed, 25 insertions(+), 36 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex index df14ad66f..d02e35bc8 100644 --- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -301,4 +301,26 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do {:error, message} -> json_response(conn, :forbidden, %{error: message}) end end + + @doc "POST /api/v1/follows" + def follows(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do + with {_, %User{} = followed} <- {:followed, User.get_cached_by_nickname(uri)}, + {_, true} <- {:followed, follower.id != followed.id}, + {:ok, follower, followed, _} <- CommonAPI.follow(follower, followed) do + render(conn, "show.json", user: followed, for: follower) + else + {:followed, _} -> {:error, :not_found} + {:error, message} -> json_response(conn, :forbidden, %{error: message}) + end + end + + @doc "GET /api/v1/mutes" + def mutes(%{assigns: %{user: user}} = conn, _) do + render(conn, "index.json", users: User.muted_users(user), for: user, as: :user) + end + + @doc "GET /api/v1/blocks" + def blocks(%{assigns: %{user: user}} = conn, _) do + render(conn, "index.json", users: User.blocked_users(user), for: user, as: :user) + end end diff --git a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex index e92f5d089..9b62867b4 100644 --- a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex @@ -11,7 +11,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do alias Pleroma.Pagination alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub - alias Pleroma.Web.CommonAPI alias Pleroma.Web.MastodonAPI.AccountView alias Pleroma.Web.MastodonAPI.StatusView @@ -19,38 +18,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do action_fallback(Pleroma.Web.MastodonAPI.FallbackController) - def follows(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do - with {_, %User{} = followed} <- {:followed, User.get_cached_by_nickname(uri)}, - {_, true} <- {:followed, follower.id != followed.id}, - {:ok, follower, followed, _} <- CommonAPI.follow(follower, followed) do - conn - |> put_view(AccountView) - |> render("show.json", %{user: followed, for: follower}) - else - {:followed, _} -> - {:error, :not_found} - - {:error, message} -> - conn - |> put_status(:forbidden) - |> json(%{error: message}) - end - end - - def mutes(%{assigns: %{user: user}} = conn, _) do - with muted_accounts <- User.muted_users(user) do - res = AccountView.render("index.json", users: muted_accounts, for: user, as: :user) - json(conn, res) - end - end - - def blocks(%{assigns: %{user: user}} = conn, _) do - with blocked_accounts <- User.blocked_users(user) do - res = AccountView.render("index.json", users: blocked_accounts, for: user, as: :user) - json(conn, res) - end - end - def favourites(%{assigns: %{user: user}} = conn, params) do params = params diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index f91af8137..c6389b44e 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -347,8 +347,8 @@ defmodule Pleroma.Web.Router do get("/accounts/:id/identity_proofs", MastodonAPIController, :empty_array) get("/follow_requests", FollowRequestController, :index) - get("/blocks", MastodonAPIController, :blocks) - get("/mutes", MastodonAPIController, :mutes) + get("/blocks", AccountController, :blocks) + get("/mutes", AccountController, :mutes) get("/timelines/home", TimelineController, :home) get("/timelines/direct", TimelineController, :direct) @@ -426,7 +426,7 @@ defmodule Pleroma.Web.Router do scope [] do pipe_through(:oauth_follow) - post("/follows", MastodonAPIController, :follows) + post("/follows", AccountController, :follows) post("/accounts/:id/follow", AccountController, :follow) post("/accounts/:id/unfollow", AccountController, :unfollow) post("/accounts/:id/block", AccountController, :block) -- cgit v1.2.3 From e0c68eeb024c7d91b098c4e0eb6ad57551ea9ef1 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Wed, 2 Oct 2019 18:27:01 +0700 Subject: Move `:favourites` and `:bookmarks` actions to StatusController --- .../controllers/mastodon_api_controller.ex | 43 ---------------------- .../mastodon_api/controllers/status_controller.ex | 37 ++++++++++++++++++- lib/pleroma/web/router.ex | 4 +- 3 files changed, 38 insertions(+), 46 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex index 9b62867b4..7d839a8cf 100644 --- a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex @@ -5,53 +5,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do use Pleroma.Web, :controller - import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2] - - alias Pleroma.Bookmark - alias Pleroma.Pagination - alias Pleroma.User - alias Pleroma.Web.ActivityPub.ActivityPub - alias Pleroma.Web.MastodonAPI.AccountView - alias Pleroma.Web.MastodonAPI.StatusView - require Logger action_fallback(Pleroma.Web.MastodonAPI.FallbackController) - def favourites(%{assigns: %{user: user}} = conn, params) do - params = - params - |> Map.put("type", "Create") - |> Map.put("favorited_by", user.ap_id) - |> Map.put("blocking_user", user) - - activities = - ActivityPub.fetch_activities([], params) - |> Enum.reverse() - - conn - |> add_link_headers(activities) - |> put_view(StatusView) - |> render("index.json", %{activities: activities, for: user, as: :activity}) - end - - def bookmarks(%{assigns: %{user: user}} = conn, params) do - user = User.get_cached_by_id(user.id) - - bookmarks = - Bookmark.for_user_query(user.id) - |> Pagination.fetch_paginated(params) - - activities = - bookmarks - |> Enum.map(fn b -> Map.put(b.activity, :bookmark, Map.delete(b, :activity)) end) - - conn - |> add_link_headers(bookmarks) - |> put_view(StatusView) - |> render("index.json", %{activities: activities, for: user, as: :activity}) - end - # Stubs for unimplemented mastodon api # def empty_array(conn, _) do diff --git a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex index 79cced163..973334b60 100644 --- a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex @@ -5,7 +5,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do use Pleroma.Web, :controller - import Pleroma.Web.ControllerHelper, only: [try_render: 3] + import Pleroma.Web.ControllerHelper, only: [try_render: 3, add_link_headers: 2] require Ecto.Query @@ -283,4 +283,39 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do render(conn, "context.json", activity: activity, activities: activities, user: user) end end + + @doc "GET /api/v1/favourites" + def favourites(%{assigns: %{user: user}} = conn, params) do + params = + params + |> Map.put("type", "Create") + |> Map.put("favorited_by", user.ap_id) + |> Map.put("blocking_user", user) + + activities = + ActivityPub.fetch_activities([], params) + |> Enum.reverse() + + conn + |> add_link_headers(activities) + |> render("index.json", activities: activities, for: user, as: :activity) + end + + @doc "GET /api/v1/bookmarks" + def bookmarks(%{assigns: %{user: user}} = conn, params) do + user = User.get_cached_by_id(user.id) + + bookmarks = + user.id + |> Bookmark.for_user_query() + |> Pleroma.Pagination.fetch_paginated(params) + + activities = + bookmarks + |> Enum.map(fn b -> Map.put(b.activity, :bookmark, Map.delete(b, :activity)) end) + + conn + |> add_link_headers(bookmarks) + |> render("index.json", %{activities: activities, for: user, as: :activity}) + end end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index c6389b44e..c20d01c20 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -353,8 +353,8 @@ defmodule Pleroma.Web.Router do get("/timelines/home", TimelineController, :home) get("/timelines/direct", TimelineController, :direct) - get("/favourites", MastodonAPIController, :favourites) - get("/bookmarks", MastodonAPIController, :bookmarks) + get("/favourites", StatusController, :favourites) + get("/bookmarks", StatusController, :bookmarks) get("/notifications", NotificationController, :index) get("/notifications/:id", NotificationController, :show) -- cgit v1.2.3 From bd9c7807fbf21402cc0444c711c40677ca5de2a0 Mon Sep 17 00:00:00 2001 From: rinpatch Date: Thu, 3 Oct 2019 01:03:47 +0300 Subject: Move emoji task docs to a separate file --- lib/mix/tasks/pleroma/emoji.ex | 48 ------------------------------------------ 1 file changed, 48 deletions(-) (limited to 'lib') diff --git a/lib/mix/tasks/pleroma/emoji.ex b/lib/mix/tasks/pleroma/emoji.ex index 881a6f725..32b92e6af 100644 --- a/lib/mix/tasks/pleroma/emoji.ex +++ b/lib/mix/tasks/pleroma/emoji.ex @@ -6,54 +6,6 @@ defmodule Mix.Tasks.Pleroma.Emoji do use Mix.Task @shortdoc "Manages emoji packs" - @moduledoc """ - Manages emoji packs - - ## ls-packs - - mix pleroma.emoji ls-packs [OPTION...] - - Lists the emoji packs and metadata specified in the manifest. - - ### Options - - - `-m, --manifest PATH/URL` - path to a custom manifest, it can - either be an URL starting with `http`, in that case the - manifest will be fetched from that address, or a local path - - ## get-packs - - mix pleroma.emoji get-packs [OPTION...] PACKS - - Fetches, verifies and installs the specified PACKS from the - manifest into the `STATIC-DIR/emoji/PACK-NAME` - - ### Options - - - `-m, --manifest PATH/URL` - same as ls-packs - - ## gen-pack - - mix pleroma.emoji gen-pack PACK-URL - - Creates a new manifest entry and a file list from the specified - remote pack file. Currently, only .zip archives are recognized - as remote pack files and packs are therefore assumed to be zip - archives. This command is intended to run interactively and will - first ask you some basic questions about the pack, then download - the remote file and generate an SHA256 checksum for it, then - generate an emoji file list for you. - - The manifest entry will either be written to a newly created - `index.json` file or appended to the existing one, *replacing* - the old pack with the same name if it was in the file previously. - - The file list will be written to the file specified previously, - *replacing* that file. You _should_ check that the file list doesn't - contain anything you don't need in the pack, that is, anything that is - not an emoji (the whole pack is downloaded, but only emoji files - are extracted). - """ def run(["ls-packs" | args]) do Application.ensure_all_started(:hackney) -- cgit v1.2.3 From 869ea2ab90bb461ad3dd06ac974f227da369fcf8 Mon Sep 17 00:00:00 2001 From: rinpatch Date: Thu, 3 Oct 2019 01:09:51 +0300 Subject: Move digest email docs to a separate file and improve styling --- lib/mix/tasks/pleroma/digest.ex | 9 --------- 1 file changed, 9 deletions(-) (limited to 'lib') diff --git a/lib/mix/tasks/pleroma/digest.ex b/lib/mix/tasks/pleroma/digest.ex index 430116a50..100a81060 100644 --- a/lib/mix/tasks/pleroma/digest.ex +++ b/lib/mix/tasks/pleroma/digest.ex @@ -2,16 +2,7 @@ defmodule Mix.Tasks.Pleroma.Digest do use Mix.Task @shortdoc "Manages digest emails" - @moduledoc """ - Manages digest emails - ## Send digest email since given date (user registration date by default) - ignoring user activity status. - - ``mix pleroma.digest test `` - - Example: ``mix pleroma.digest test donaldtheduck 2019-05-20`` - """ def run(["test", nickname | opts]) do Mix.Pleroma.start_pleroma() -- cgit v1.2.3 From 6435ba83cd07162a9ad9a386253814e2f12d951d Mon Sep 17 00:00:00 2001 From: rinpatch Date: Thu, 3 Oct 2019 09:02:48 +0300 Subject: Move instance CLI task docs to a text file --- lib/mix/tasks/pleroma/instance.ex | 30 ------------------------------ 1 file changed, 30 deletions(-) (limited to 'lib') diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex index 1a1634fe9..25f94eceb 100644 --- a/lib/mix/tasks/pleroma/instance.ex +++ b/lib/mix/tasks/pleroma/instance.ex @@ -7,36 +7,6 @@ defmodule Mix.Tasks.Pleroma.Instance do import Mix.Pleroma @shortdoc "Manages Pleroma instance" - @moduledoc """ - Manages Pleroma instance. - - ## Generate a new instance config. - - mix pleroma.instance gen [OPTION...] - - If any options are left unspecified, you will be prompted interactively - - ## Options - - - `-f`, `--force` - overwrite any output files - - `-o PATH`, `--output PATH` - the output file for the generated configuration - - `--output-psql PATH` - the output file for the generated PostgreSQL setup - - `--domain DOMAIN` - the domain of your instance - - `--instance-name INSTANCE_NAME` - the name of your instance - - `--admin-email ADMIN_EMAIL` - the email address of the instance admin - - `--notify-email NOTIFY_EMAIL` - email address for notifications - - `--dbhost HOSTNAME` - the hostname of the PostgreSQL database to use - - `--dbname DBNAME` - the name of the database to use - - `--dbuser DBUSER` - the user (aka role) to use for the database connection - - `--dbpass DBPASS` - the password to use for the database connection - - `--rum Y/N` - Whether to enable RUM indexes - - `--indexable Y/N` - Allow/disallow indexing site by search engines - - `--db-configurable Y/N` - Allow/disallow configuring instance from admin part - - `--uploads-dir` - the directory uploads go in when using a local uploader - - `--static-dir` - the directory custom public files should be read from (custom emojis, frontend bundle overrides, robots.txt, etc.) - - `--listen-ip` - the ip the app should listen to, defaults to 127.0.0.1 - - `--listen-port` - the port the app should listen to, defaults to 4000 - """ def run(["gen" | rest]) do {options, [], []} = -- cgit v1.2.3 From 808d0a0170577155d0f1097c66c4e0b23c8303b9 Mon Sep 17 00:00:00 2001 From: rinpatch Date: Thu, 3 Oct 2019 09:10:31 +0300 Subject: Move relay docs to a separate file --- lib/mix/tasks/pleroma/relay.ex | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'lib') diff --git a/lib/mix/tasks/pleroma/relay.ex b/lib/mix/tasks/pleroma/relay.ex index 200721163..519f2d1b5 100644 --- a/lib/mix/tasks/pleroma/relay.ex +++ b/lib/mix/tasks/pleroma/relay.ex @@ -9,25 +9,7 @@ defmodule Mix.Tasks.Pleroma.Relay do alias Pleroma.Web.ActivityPub.Relay @shortdoc "Manages remote relays" - @moduledoc """ - Manages remote relays - ## Follow a remote relay - - ``mix pleroma.relay follow `` - - Example: ``mix pleroma.relay follow https://example.org/relay`` - - ## Unfollow a remote relay - - ``mix pleroma.relay unfollow `` - - Example: ``mix pleroma.relay unfollow https://example.org/relay`` - - ## List relay subscriptions - - ``mix pleroma.relay list`` - """ def run(["follow", target]) do start_pleroma() -- cgit v1.2.3 From d39ccc2e7ffd019f8fe2438f388c0a0bb8aac34a Mon Sep 17 00:00:00 2001 From: rinpatch Date: Thu, 3 Oct 2019 09:35:21 +0300 Subject: Move uploads task docs to a separate file --- lib/mix/tasks/pleroma/uploads.ex | 9 --------- 1 file changed, 9 deletions(-) (limited to 'lib') diff --git a/lib/mix/tasks/pleroma/uploads.ex b/lib/mix/tasks/pleroma/uploads.ex index 95392d81b..bc2248a76 100644 --- a/lib/mix/tasks/pleroma/uploads.ex +++ b/lib/mix/tasks/pleroma/uploads.ex @@ -12,16 +12,7 @@ defmodule Mix.Tasks.Pleroma.Uploads do @log_every 50 @shortdoc "Migrates uploads from local to remote storage" - @moduledoc """ - Manages uploads - ## Migrate uploads from local to remote storage - mix pleroma.uploads migrate_local TARGET_UPLOADER [OPTIONS...] - Options: - - `--delete` - delete local uploads after migrating them to the target uploader - - A list of available uploaders can be seen in config.exs - """ def run(["migrate_local", target_uploader | args]) do delete? = Enum.member?(args, "--delete") start_pleroma() -- cgit v1.2.3 From b4ca864c6b2e6ee9addea7fbc0b09fca581816ce Mon Sep 17 00:00:00 2001 From: rinpatch Date: Thu, 3 Oct 2019 10:15:24 +0300 Subject: Move user tasks docs to a separate file --- lib/mix/tasks/pleroma/user.ex | 79 ------------------------------------------- 1 file changed, 79 deletions(-) (limited to 'lib') diff --git a/lib/mix/tasks/pleroma/user.ex b/lib/mix/tasks/pleroma/user.ex index d93ba8dee..3cf3ad2c6 100644 --- a/lib/mix/tasks/pleroma/user.ex +++ b/lib/mix/tasks/pleroma/user.ex @@ -10,86 +10,7 @@ defmodule Mix.Tasks.Pleroma.User do alias Pleroma.Web.OAuth @shortdoc "Manages Pleroma users" - @moduledoc """ - Manages Pleroma users. - ## Create a new user. - - mix pleroma.user new NICKNAME EMAIL [OPTION...] - - Options: - - `--name NAME` - the user's name (i.e., "Lain Iwakura") - - `--bio BIO` - the user's bio - - `--password PASSWORD` - the user's password - - `--moderator`/`--no-moderator` - whether the user is a moderator - - `--admin`/`--no-admin` - whether the user is an admin - - `-y`, `--assume-yes`/`--no-assume-yes` - whether to assume yes to all questions - - ## Generate an invite link. - - mix pleroma.user invite [OPTION...] - - Options: - - `--expires-at DATE` - last day on which token is active (e.g. "2019-04-05") - - `--max-use NUMBER` - maximum numbers of token uses - - ## List generated invites - - mix pleroma.user invites - - ## Revoke invite - - mix pleroma.user revoke_invite TOKEN OR TOKEN_ID - - ## Delete the user's account. - - mix pleroma.user rm NICKNAME - - ## Delete the user's activities. - - mix pleroma.user delete_activities NICKNAME - - ## Sign user out from all applications (delete user's OAuth tokens and authorizations). - - mix pleroma.user sign_out NICKNAME - - ## Deactivate or activate the user's account. - - mix pleroma.user toggle_activated NICKNAME - - ## Unsubscribe local users from user's account and deactivate it - - mix pleroma.user unsubscribe NICKNAME - - ## Unsubscribe local users from an entire instance and deactivate all accounts - - mix pleroma.user unsubscribe_all_from_instance INSTANCE - - ## Create a password reset link. - - mix pleroma.user reset_password NICKNAME - - ## Set the value of the given user's settings. - - mix pleroma.user set NICKNAME [OPTION...] - - Options: - - `--locked`/`--no-locked` - whether the user's account is locked - - `--moderator`/`--no-moderator` - whether the user is a moderator - - `--admin`/`--no-admin` - whether the user is an admin - - ## Add tags to a user. - - mix pleroma.user tag NICKNAME TAGS - - ## Delete tags from a user. - - mix pleroma.user untag NICKNAME TAGS - - ## Toggle confirmation of the user's account. - - mix pleroma.user toggle_confirmed NICKNAME - """ def run(["new", nickname, email | rest]) do {options, [], []} = OptionParser.parse( -- cgit v1.2.3 From 6baa037903e06c80a5b5f1c34b2cfdd471ba2f8f Mon Sep 17 00:00:00 2001 From: rinpatch Date: Thu, 3 Oct 2019 11:17:29 +0300 Subject: Move database maintenance tasks docs to a separate file --- lib/mix/tasks/pleroma/database.ex | 27 --------------------------- 1 file changed, 27 deletions(-) (limited to 'lib') diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex index 890a383df..81e687f64 100644 --- a/lib/mix/tasks/pleroma/database.ex +++ b/lib/mix/tasks/pleroma/database.ex @@ -13,34 +13,7 @@ defmodule Mix.Tasks.Pleroma.Database do use Mix.Task @shortdoc "A collection of database related tasks" - @moduledoc """ - A collection of database related tasks - ## Replace embedded objects with their references - - Replaces embedded objects with references to them in the `objects` table. Only needs to be ran once. The reason why this is not a migration is because it could significantly increase the database size after being ran, however after this `VACUUM FULL` will be able to reclaim about 20% (really depends on what is in the database, your mileage may vary) of the db size before the migration. - - mix pleroma.database remove_embedded_objects - - Options: - - `--vacuum` - run `VACUUM FULL` after the embedded objects are replaced with their references - - ## Prune old objects from the database - - mix pleroma.database prune_objects - - ## Create a conversation for all existing DMs. Can be safely re-run. - - mix pleroma.database bump_all_conversations - - ## Remove duplicated items from following and update followers count for all users - - mix pleroma.database update_users_following_followers_counts - - ## Fix the pre-existing "likes" collections for all objects - - mix pleroma.database fix_likes_collections - """ def run(["remove_embedded_objects" | args]) do {options, [], []} = OptionParser.parse( -- cgit v1.2.3 From e00403af232548fdef8ad8f2923a51561b3064f6 Mon Sep 17 00:00:00 2001 From: rinpatch Date: Thu, 3 Oct 2019 13:59:49 +0300 Subject: Mix tasks: derive moduledoc from doc files --- lib/mix/tasks/pleroma/database.ex | 1 + lib/mix/tasks/pleroma/digest.ex | 1 + lib/mix/tasks/pleroma/emoji.ex | 1 + lib/mix/tasks/pleroma/instance.ex | 1 + lib/mix/tasks/pleroma/relay.ex | 1 + lib/mix/tasks/pleroma/uploads.ex | 1 + lib/mix/tasks/pleroma/user.ex | 1 + 7 files changed, 7 insertions(+) (limited to 'lib') diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex index 81e687f64..cfd9eeada 100644 --- a/lib/mix/tasks/pleroma/database.ex +++ b/lib/mix/tasks/pleroma/database.ex @@ -13,6 +13,7 @@ defmodule Mix.Tasks.Pleroma.Database do use Mix.Task @shortdoc "A collection of database related tasks" + @moduledoc File.read!("docs/administration/CLI_tasks/database.md") def run(["remove_embedded_objects" | args]) do {options, [], []} = diff --git a/lib/mix/tasks/pleroma/digest.ex b/lib/mix/tasks/pleroma/digest.ex index 100a81060..7d09e70c5 100644 --- a/lib/mix/tasks/pleroma/digest.ex +++ b/lib/mix/tasks/pleroma/digest.ex @@ -2,6 +2,7 @@ defmodule Mix.Tasks.Pleroma.Digest do use Mix.Task @shortdoc "Manages digest emails" + @moduledoc File.read!("docs/administration/CLI_tasks/digest.md") def run(["test", nickname | opts]) do Mix.Pleroma.start_pleroma() diff --git a/lib/mix/tasks/pleroma/emoji.ex b/lib/mix/tasks/pleroma/emoji.ex index 32b92e6af..6ef0a635d 100644 --- a/lib/mix/tasks/pleroma/emoji.ex +++ b/lib/mix/tasks/pleroma/emoji.ex @@ -6,6 +6,7 @@ defmodule Mix.Tasks.Pleroma.Emoji do use Mix.Task @shortdoc "Manages emoji packs" + @moduledoc File.read!("docs/administration/CLI_tasks/emoji.md") def run(["ls-packs" | args]) do Application.ensure_all_started(:hackney) diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex index 25f94eceb..9af6cda30 100644 --- a/lib/mix/tasks/pleroma/instance.ex +++ b/lib/mix/tasks/pleroma/instance.ex @@ -7,6 +7,7 @@ defmodule Mix.Tasks.Pleroma.Instance do import Mix.Pleroma @shortdoc "Manages Pleroma instance" + @moduledoc File.read!("docs/administration/CLI_tasks/instance.md") def run(["gen" | rest]) do {options, [], []} = diff --git a/lib/mix/tasks/pleroma/relay.ex b/lib/mix/tasks/pleroma/relay.ex index 519f2d1b5..d7a7b599f 100644 --- a/lib/mix/tasks/pleroma/relay.ex +++ b/lib/mix/tasks/pleroma/relay.ex @@ -9,6 +9,7 @@ defmodule Mix.Tasks.Pleroma.Relay do alias Pleroma.Web.ActivityPub.Relay @shortdoc "Manages remote relays" + @moduledoc File.read!("docs/administration/CLI_tasks/relay.md") def run(["follow", target]) do start_pleroma() diff --git a/lib/mix/tasks/pleroma/uploads.ex b/lib/mix/tasks/pleroma/uploads.ex index bc2248a76..3e6fc7ee0 100644 --- a/lib/mix/tasks/pleroma/uploads.ex +++ b/lib/mix/tasks/pleroma/uploads.ex @@ -12,6 +12,7 @@ defmodule Mix.Tasks.Pleroma.Uploads do @log_every 50 @shortdoc "Migrates uploads from local to remote storage" + @moduledoc File.read!("docs/administration/CLI_tasks/uploads.md") def run(["migrate_local", target_uploader | args]) do delete? = Enum.member?(args, "--delete") diff --git a/lib/mix/tasks/pleroma/user.ex b/lib/mix/tasks/pleroma/user.ex index 3cf3ad2c6..134b5bccc 100644 --- a/lib/mix/tasks/pleroma/user.ex +++ b/lib/mix/tasks/pleroma/user.ex @@ -10,6 +10,7 @@ defmodule Mix.Tasks.Pleroma.User do alias Pleroma.Web.OAuth @shortdoc "Manages Pleroma users" + @moduledoc File.read!("docs/administration/CLI_tasks/user.md") def run(["new", nickname, email | rest]) do {options, [], []} = -- cgit v1.2.3 From 1cae564b5d749a23f29a5303a82e27e2952a55ed Mon Sep 17 00:00:00 2001 From: rinpatch Date: Thu, 3 Oct 2019 14:12:57 +0300 Subject: Move config task docs to a separate file and mark it as WIP --- lib/mix/tasks/pleroma/config.ex | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/mix/tasks/pleroma/config.ex b/lib/mix/tasks/pleroma/config.ex index 462940e7e..11e4fde43 100644 --- a/lib/mix/tasks/pleroma/config.ex +++ b/lib/mix/tasks/pleroma/config.ex @@ -8,18 +8,7 @@ defmodule Mix.Tasks.Pleroma.Config do alias Pleroma.Repo alias Pleroma.Web.AdminAPI.Config @shortdoc "Manages the location of the config" - @moduledoc """ - Manages the location of the config. - - ## Transfers config from file to DB. - - mix pleroma.config migrate_to_db - - ## Transfers config from DB to file `config/env.exported_from_db.secret.exs` - - mix pleroma.config migrate_from_db ENV - """ - + @moduledoc File.read!("docs/administration/CLI_tasks/config.md") def run(["migrate_to_db"]) do start_pleroma() -- cgit v1.2.3 From 06d9df79c5c99069dd12e863c99167eb20b6495b Mon Sep 17 00:00:00 2001 From: eugenijm Date: Wed, 2 Oct 2019 00:37:08 +0300 Subject: Mastodon API: Add `pleroma.unread_conversation_count` to the Account entity --- lib/pleroma/conversation.ex | 2 + lib/pleroma/conversation/participation.ex | 17 +++++++ lib/pleroma/user.ex | 56 ++++++++++++++++++++++ lib/pleroma/user/info.ex | 1 + lib/pleroma/web/mastodon_api/views/account_view.ex | 11 +++++ 5 files changed, 87 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/conversation.ex b/lib/pleroma/conversation.ex index be5821ad7..098016af2 100644 --- a/lib/pleroma/conversation.ex +++ b/lib/pleroma/conversation.ex @@ -67,6 +67,8 @@ defmodule Pleroma.Conversation do participations = Enum.map(users, fn user -> + User.increment_unread_conversation_count(conversation, user) + {:ok, participation} = Participation.create_for_user_and_conversation(user, conversation, opts) diff --git a/lib/pleroma/conversation/participation.ex b/lib/pleroma/conversation/participation.ex index e946f6de2..ab81f3217 100644 --- a/lib/pleroma/conversation/participation.ex +++ b/lib/pleroma/conversation/participation.ex @@ -52,6 +52,15 @@ defmodule Pleroma.Conversation.Participation do participation |> read_cng(%{read: true}) |> Repo.update() + |> case do + {:ok, participation} -> + participation = Repo.preload(participation, :user) + User.set_unread_conversation_count(participation.user) + {:ok, participation} + + error -> + error + end end def mark_as_unread(participation) do @@ -135,4 +144,12 @@ defmodule Pleroma.Conversation.Participation do {:ok, Repo.preload(participation, :recipients, force: true)} end + + def unread_conversation_count_for_user(user) do + from(p in __MODULE__, + where: p.user_id == ^user.id, + where: not p.read, + select: %{count: count(p.id)} + ) + end end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 4c1cdd042..572dd7746 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -11,6 +11,7 @@ defmodule Pleroma.User do alias Comeonin.Pbkdf2 alias Ecto.Multi alias Pleroma.Activity + alias Pleroma.Conversation.Participation alias Pleroma.Delivery alias Pleroma.Keys alias Pleroma.Notification @@ -842,6 +843,61 @@ defmodule Pleroma.User do def maybe_update_following_count(user), do: user + def set_unread_conversation_count(%User{local: true} = user) do + unread_query = Participation.unread_conversation_count_for_user(user) + + User + |> where([u], u.id == ^user.id) + |> join(:inner, [u], p in subquery(unread_query)) + |> update([u, p], + set: [ + info: + fragment( + "jsonb_set(?, '{unread_conversation_count}', ?::varchar::jsonb, true)", + u.info, + p.count + ) + ] + ) + |> select([u], u) + |> Repo.update_all([]) + |> case do + {1, [%{info: %User.Info{}} = user]} -> set_cache(user) + _ -> {:error, user} + end + end + + def set_unread_conversation_count(_), do: :noop + + def increment_unread_conversation_count(conversation, %User{local: true} = user) do + unread_query = + Participation.unread_conversation_count_for_user(user) + |> where([p], p.conversation_id == ^conversation.id) + + User + |> join(:inner, [u], p in subquery(unread_query)) + |> update([u, p], + set: [ + info: + fragment( + "jsonb_set(?, '{unread_conversation_count}', ((?->>'unread_conversation_count')::int + 1)::varchar::jsonb, true)", + u.info, + u.info + ) + ] + ) + |> where([u], u.id == ^user.id) + |> where([u, p], p.count == 0) + |> select([u], u) + |> Repo.update_all([]) + |> case do + {1, [%{info: %User.Info{}} = user]} -> set_cache(user) + _ -> {:error, user} + end + end + + def increment_unread_conversation_count(_, _), do: :noop + def remove_duplicated_following(%User{following: following} = user) do uniq_following = Enum.uniq(following) diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex index ebd4ddebf..4b5b43d7f 100644 --- a/lib/pleroma/user/info.ex +++ b/lib/pleroma/user/info.ex @@ -47,6 +47,7 @@ defmodule Pleroma.User.Info do field(:hide_followers, :boolean, default: false) field(:hide_follows, :boolean, default: false) field(:hide_favorites, :boolean, default: true) + field(:unread_conversation_count, :integer, default: 0) field(:pinned_activities, {:array, :string}, default: []) field(:email_notifications, :map, default: %{"digest" => false}) field(:mascot, :map, default: nil) diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 99169ef95..2d4976891 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -167,6 +167,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do |> maybe_put_chat_token(user, opts[:for], opts) |> maybe_put_activation_status(user, opts[:for]) |> maybe_put_follow_requests_count(user, opts[:for]) + |> maybe_put_unread_conversation_count(user, opts[:for]) end defp username_from_nickname(string) when is_binary(string) do @@ -248,6 +249,16 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do defp maybe_put_activation_status(data, _, _), do: data + defp maybe_put_unread_conversation_count(data, %User{id: user_id} = user, %User{id: user_id}) do + data + |> Kernel.put_in( + [:pleroma, :unread_conversation_count], + user.info.unread_conversation_count + ) + end + + defp maybe_put_unread_conversation_count(data, _, _), do: data + defp image_url(%{"url" => [%{"href" => href} | _]}), do: href defp image_url(_), do: nil end -- cgit v1.2.3 From 5dc14c89cecc121ffb047c2a7c972af0b0f89ef8 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Fri, 4 Oct 2019 06:47:36 +0200 Subject: =?UTF-8?q?notification=5Fview.ex:=20Make=20sure=20`account`=20isn?= =?UTF-8?q?=E2=80=99t=20empty?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Related: https://git.pleroma.social/pleroma/pleroma/issues/1203 --- .../web/mastodon_api/views/notification_view.ex | 60 ++++++++++++---------- 1 file changed, 32 insertions(+), 28 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/mastodon_api/views/notification_view.ex b/lib/pleroma/web/mastodon_api/views/notification_view.ex index 60b58dc90..5e3dbe728 100644 --- a/lib/pleroma/web/mastodon_api/views/notification_view.ex +++ b/lib/pleroma/web/mastodon_api/views/notification_view.ex @@ -25,40 +25,44 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do parent_activity = Activity.get_create_by_object_ap_id(activity.data["object"]) mastodon_type = Activity.mastodon_notification_type(activity) - response = %{ - id: to_string(notification.id), - type: mastodon_type, - created_at: CommonAPI.Utils.to_masto_date(notification.inserted_at), - account: AccountView.render("show.json", %{user: actor, for: user}), - pleroma: %{ - is_seen: notification.seen + with %{id: _} = account <- AccountView.render("show.json", %{user: actor, for: user}) do + response = %{ + id: to_string(notification.id), + type: mastodon_type, + created_at: CommonAPI.Utils.to_masto_date(notification.inserted_at), + account: account, + pleroma: %{ + is_seen: notification.seen + } } - } - case mastodon_type do - "mention" -> - response - |> Map.merge(%{ - status: StatusView.render("show.json", %{activity: activity, for: user}) - }) + case mastodon_type do + "mention" -> + response + |> Map.merge(%{ + status: StatusView.render("show.json", %{activity: activity, for: user}) + }) - "favourite" -> - response - |> Map.merge(%{ - status: StatusView.render("show.json", %{activity: parent_activity, for: user}) - }) + "favourite" -> + response + |> Map.merge(%{ + status: StatusView.render("show.json", %{activity: parent_activity, for: user}) + }) - "reblog" -> - response - |> Map.merge(%{ - status: StatusView.render("show.json", %{activity: parent_activity, for: user}) - }) + "reblog" -> + response + |> Map.merge(%{ + status: StatusView.render("show.json", %{activity: parent_activity, for: user}) + }) - "follow" -> - response + "follow" -> + response - _ -> - nil + _ -> + nil + end + else + _ -> nil end end end -- cgit v1.2.3 From d3ac4e8083f254a6a0e329a5807c0973f55402f4 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Fri, 4 Oct 2019 13:30:46 +0700 Subject: Fix OAuthController --- lib/pleroma/web/oauth/oauth_controller.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index e418dc70d..1cd7294e7 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -460,7 +460,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do end # Special case: Local MastodonFE - defp redirect_uri(%Plug.Conn{} = conn, "."), do: mastodon_api_url(conn, :login) + defp redirect_uri(%Plug.Conn{} = conn, "."), do: auth_url(conn, :login) defp redirect_uri(%Plug.Conn{}, redirect_uri), do: redirect_uri -- cgit v1.2.3 From 821729208506980bc65e9671c5462b629dffddaa Mon Sep 17 00:00:00 2001 From: rinpatch Date: Fri, 4 Oct 2019 01:05:50 +0300 Subject: Fix get_cached_by_nickname_or_id not allowing to get local users by nickname Closes #1293 --- lib/pleroma/user.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 4c1cdd042..c2f8fa0d7 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -583,7 +583,7 @@ defmodule Pleroma.User do is_integer(nickname_or_id) or FlakeId.flake_id?(nickname_or_id) -> get_cached_by_id(nickname_or_id) || get_cached_by_nickname(nickname_or_id) - restrict_to_local == false -> + restrict_to_local == false or not String.contains?(nickname_or_id, "@") -> get_cached_by_nickname(nickname_or_id) restrict_to_local == :unauthenticated and match?(%User{}, opts[:for]) -> -- cgit v1.2.3 From 568a995d64c91f339989077da06e381b4b8cb070 Mon Sep 17 00:00:00 2001 From: lain Date: Fri, 4 Oct 2019 16:32:42 +0200 Subject: ActivityPub: Change addressing of Undo. --- lib/pleroma/web/activity_pub/utils.ex | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 0828591ee..ac5550671 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -461,14 +461,16 @@ defmodule Pleroma.Web.ActivityPub.Utils do """ def make_unannounce_data( %User{ap_id: ap_id} = user, - %Activity{data: %{"context" => context}} = activity, + %Activity{data: %{"context" => context, "object" => object}} = activity, activity_id ) do + object = Object.normalize(object) + %{ "type" => "Undo", "actor" => ap_id, "object" => activity.data, - "to" => [user.follower_address, activity.data["actor"]], + "to" => [user.follower_address, object.data["actor"]], "cc" => [Pleroma.Constants.as_public()], "context" => context } @@ -477,14 +479,16 @@ defmodule Pleroma.Web.ActivityPub.Utils do def make_unlike_data( %User{ap_id: ap_id} = user, - %Activity{data: %{"context" => context}} = activity, + %Activity{data: %{"context" => context, "object" => object}} = activity, activity_id ) do + object = Object.normalize(object) + %{ "type" => "Undo", "actor" => ap_id, "object" => activity.data, - "to" => [user.follower_address, activity.data["actor"]], + "to" => [user.follower_address, object.data["actor"]], "cc" => [Pleroma.Constants.as_public()], "context" => context } -- cgit v1.2.3 From 2417b633ed866e6517a3fa0c30d0e85fc76dd548 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 4 Oct 2019 15:21:45 +0000 Subject: streamer: add missing copyright headers --- lib/pleroma/web/streamer/ping.ex | 4 ++++ lib/pleroma/web/streamer/state.ex | 4 ++++ lib/pleroma/web/streamer/streamer_socket.ex | 4 ++++ lib/pleroma/web/streamer/supervisor.ex | 4 ++++ lib/pleroma/web/streamer/worker.ex | 4 ++++ 5 files changed, 20 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/web/streamer/ping.ex b/lib/pleroma/web/streamer/ping.ex index f77cbb95c..db3e68abe 100644 --- a/lib/pleroma/web/streamer/ping.ex +++ b/lib/pleroma/web/streamer/ping.ex @@ -1,3 +1,7 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + defmodule Pleroma.Web.Streamer.Ping do use GenServer require Logger diff --git a/lib/pleroma/web/streamer/state.ex b/lib/pleroma/web/streamer/state.ex index c48752d95..5ce3ebb8a 100644 --- a/lib/pleroma/web/streamer/state.ex +++ b/lib/pleroma/web/streamer/state.ex @@ -1,3 +1,7 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + defmodule Pleroma.Web.Streamer.State do use GenServer require Logger diff --git a/lib/pleroma/web/streamer/streamer_socket.ex b/lib/pleroma/web/streamer/streamer_socket.ex index f006c0306..cf0fa3077 100644 --- a/lib/pleroma/web/streamer/streamer_socket.ex +++ b/lib/pleroma/web/streamer/streamer_socket.ex @@ -1,3 +1,7 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + defmodule Pleroma.Web.Streamer.StreamerSocket do defstruct transport_pid: nil, user: nil diff --git a/lib/pleroma/web/streamer/supervisor.ex b/lib/pleroma/web/streamer/supervisor.ex index 6afe19323..ec5985085 100644 --- a/lib/pleroma/web/streamer/supervisor.ex +++ b/lib/pleroma/web/streamer/supervisor.ex @@ -1,3 +1,7 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + defmodule Pleroma.Web.Streamer.Supervisor do use Supervisor diff --git a/lib/pleroma/web/streamer/worker.ex b/lib/pleroma/web/streamer/worker.ex index 5804508eb..bbb7483e5 100644 --- a/lib/pleroma/web/streamer/worker.ex +++ b/lib/pleroma/web/streamer/worker.ex @@ -1,3 +1,7 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + defmodule Pleroma.Web.Streamer.Worker do use GenServer -- cgit v1.2.3 From 5a0c018d2a6d3cea15761c1cc51691dcb85a0c97 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 4 Oct 2019 15:41:55 +0000 Subject: streamer: worker: check for lack of intersectionality between a user's blocklist and an activity's recipientlist --- lib/pleroma/web/streamer/worker.ex | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/web/streamer/worker.ex b/lib/pleroma/web/streamer/worker.ex index bbb7483e5..3d2c8f473 100644 --- a/lib/pleroma/web/streamer/worker.ex +++ b/lib/pleroma/web/streamer/worker.ex @@ -132,11 +132,14 @@ defmodule Pleroma.Web.Streamer.Worker do blocks = user.info.blocks || [] mutes = user.info.mutes || [] reblog_mutes = user.info.muted_reblogs || [] + recipient_blocks = MapSet.new(blocks ++ mutes) + recipients = MapSet.new(item.recipients) domain_blocks = Pleroma.Web.ActivityPub.MRF.subdomains_regex(user.info.domain_blocks) with parent when not is_nil(parent) <- Object.normalize(item), true <- Enum.all?([blocks, mutes, reblog_mutes], &(item.actor not in &1)), true <- Enum.all?([blocks, mutes], &(parent.data["actor"] not in &1)), + true <- MapSet.disjoint?(recipients, recipient_blocks), %{host: item_host} <- URI.parse(item.actor), %{host: parent_host} <- URI.parse(parent.data["actor"]), false <- Pleroma.Web.ActivityPub.MRF.subdomain_match?(domain_blocks, item_host), -- cgit v1.2.3 From d1d058bf85a94909cb0c599bb5f2bd469de804d5 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 4 Oct 2019 15:42:25 +0000 Subject: streamer: worker: actually use should_send? consistently --- lib/pleroma/web/streamer/worker.ex | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/streamer/worker.ex b/lib/pleroma/web/streamer/worker.ex index 3d2c8f473..0ea224874 100644 --- a/lib/pleroma/web/streamer/worker.ex +++ b/lib/pleroma/web/streamer/worker.ex @@ -201,11 +201,8 @@ defmodule Pleroma.Web.Streamer.Worker do # Get the current user so we have up-to-date blocks etc. if socket_user do user = User.get_cached_by_ap_id(socket_user.ap_id) - blocks = user.info.blocks || [] - mutes = user.info.mutes || [] - with true <- Enum.all?([blocks, mutes], &(item.actor not in &1)), - true <- thread_containment(item, user) do + if should_send?(user, item) do send(transport_pid, {:text, StreamerView.render("update.json", item, user)}) end else -- cgit v1.2.3 From 83631752af053b02a05abe0e9f7d6c7cf9a5154a Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Fri, 4 Oct 2019 22:20:53 +0300 Subject: removed legacy api: "/objects/:uuid/likes" --- .../web/activity_pub/activity_pub_controller.ex | 32 ------------------- lib/pleroma/web/activity_pub/utils.ex | 10 ------ lib/pleroma/web/activity_pub/views/object_view.ex | 36 ---------------------- lib/pleroma/web/router.ex | 1 - 4 files changed, 79 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex index 7cd13b4b8..080030eb5 100644 --- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex +++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex @@ -82,38 +82,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do conn end - def object_likes(conn, %{"uuid" => uuid, "page" => page}) do - with ap_id <- o_status_url(conn, :object, uuid), - %Object{} = object <- Object.get_cached_by_ap_id(ap_id), - {_, true} <- {:public?, Visibility.is_public?(object)}, - likes <- Utils.get_object_likes(object) do - {page, _} = Integer.parse(page) - - conn - |> put_resp_content_type("application/activity+json") - |> put_view(ObjectView) - |> render("likes.json", %{ap_id: ap_id, likes: likes, page: page}) - else - {:public?, false} -> - {:error, :not_found} - end - end - - def object_likes(conn, %{"uuid" => uuid}) do - with ap_id <- o_status_url(conn, :object, uuid), - %Object{} = object <- Object.get_cached_by_ap_id(ap_id), - {_, true} <- {:public?, Visibility.is_public?(object)}, - likes <- Utils.get_object_likes(object) do - conn - |> put_resp_content_type("application/activity+json") - |> put_view(ObjectView) - |> render("likes.json", %{ap_id: ap_id, likes: likes}) - else - {:public?, false} -> - {:error, :not_found} - end - end - def activity(conn, %{"uuid" => uuid}) do with ap_id <- o_status_url(conn, :activity, uuid), %Activity{} = activity <- Activity.normalize(ap_id), diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index ac5550671..272011a9f 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -251,16 +251,6 @@ defmodule Pleroma.Web.ActivityPub.Utils do |> Repo.one() end - @doc """ - Returns like activities targeting an object - """ - def get_object_likes(%{data: %{"id" => id}}) do - id - |> Activity.Queries.by_object_id() - |> Activity.Queries.by_type("Like") - |> Repo.all() - end - @spec make_like_data(User.t(), map(), String.t()) :: map() def make_like_data( %User{ap_id: ap_id} = actor, diff --git a/lib/pleroma/web/activity_pub/views/object_view.ex b/lib/pleroma/web/activity_pub/views/object_view.ex index 88c55acdd..d8a3ec288 100644 --- a/lib/pleroma/web/activity_pub/views/object_view.ex +++ b/lib/pleroma/web/activity_pub/views/object_view.ex @@ -37,40 +37,4 @@ defmodule Pleroma.Web.ActivityPub.ObjectView do Map.merge(base, additional) end - - def render("likes.json", %{ap_id: ap_id, likes: likes, page: page}) do - collection(likes, "#{ap_id}/likes", page) - |> Map.merge(Pleroma.Web.ActivityPub.Utils.make_json_ld_header()) - end - - def render("likes.json", %{ap_id: ap_id, likes: likes}) do - %{ - "id" => "#{ap_id}/likes", - "type" => "OrderedCollection", - "totalItems" => length(likes), - "first" => collection(likes, "#{ap_id}/likes", 1) - } - |> Map.merge(Pleroma.Web.ActivityPub.Utils.make_json_ld_header()) - end - - def collection(collection, iri, page) do - offset = (page - 1) * 10 - items = Enum.slice(collection, offset, 10) - items = Enum.map(items, fn object -> Transmogrifier.prepare_object(object.data) end) - total = length(collection) - - map = %{ - "id" => "#{iri}?page=#{page}", - "type" => "OrderedCollectionPage", - "partOf" => iri, - "totalItems" => total, - "orderedItems" => items - } - - if offset + length(items) < total do - Map.put(map, "next", "#{iri}?page=#{page + 1}") - else - map - end - end end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index f91af8137..405ae724e 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -580,7 +580,6 @@ defmodule Pleroma.Web.Router do pipe_through(:ostatus) get("/users/:nickname/outbox", ActivityPubController, :outbox) - get("/objects/:uuid/likes", ActivityPubController, :object_likes) end pipeline :activitypub_client do -- cgit v1.2.3 From e07e9cb75e6605218acea1ef41772ca29124bd0d Mon Sep 17 00:00:00 2001 From: kaniini Date: Sat, 5 Oct 2019 10:00:05 +0000 Subject: Revert "Merge branch 'user-info-unread-direct-conversation' into 'develop'" This reverts merge request !1737 --- lib/pleroma/conversation.ex | 2 - lib/pleroma/conversation/participation.ex | 17 ------- lib/pleroma/user.ex | 56 ---------------------- lib/pleroma/user/info.ex | 1 - lib/pleroma/web/mastodon_api/views/account_view.ex | 11 ----- 5 files changed, 87 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/conversation.ex b/lib/pleroma/conversation.ex index 098016af2..be5821ad7 100644 --- a/lib/pleroma/conversation.ex +++ b/lib/pleroma/conversation.ex @@ -67,8 +67,6 @@ defmodule Pleroma.Conversation do participations = Enum.map(users, fn user -> - User.increment_unread_conversation_count(conversation, user) - {:ok, participation} = Participation.create_for_user_and_conversation(user, conversation, opts) diff --git a/lib/pleroma/conversation/participation.ex b/lib/pleroma/conversation/participation.ex index ab81f3217..e946f6de2 100644 --- a/lib/pleroma/conversation/participation.ex +++ b/lib/pleroma/conversation/participation.ex @@ -52,15 +52,6 @@ defmodule Pleroma.Conversation.Participation do participation |> read_cng(%{read: true}) |> Repo.update() - |> case do - {:ok, participation} -> - participation = Repo.preload(participation, :user) - User.set_unread_conversation_count(participation.user) - {:ok, participation} - - error -> - error - end end def mark_as_unread(participation) do @@ -144,12 +135,4 @@ defmodule Pleroma.Conversation.Participation do {:ok, Repo.preload(participation, :recipients, force: true)} end - - def unread_conversation_count_for_user(user) do - from(p in __MODULE__, - where: p.user_id == ^user.id, - where: not p.read, - select: %{count: count(p.id)} - ) - end end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 494a67f22..c2f8fa0d7 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -11,7 +11,6 @@ defmodule Pleroma.User do alias Comeonin.Pbkdf2 alias Ecto.Multi alias Pleroma.Activity - alias Pleroma.Conversation.Participation alias Pleroma.Delivery alias Pleroma.Keys alias Pleroma.Notification @@ -843,61 +842,6 @@ defmodule Pleroma.User do def maybe_update_following_count(user), do: user - def set_unread_conversation_count(%User{local: true} = user) do - unread_query = Participation.unread_conversation_count_for_user(user) - - User - |> where([u], u.id == ^user.id) - |> join(:inner, [u], p in subquery(unread_query)) - |> update([u, p], - set: [ - info: - fragment( - "jsonb_set(?, '{unread_conversation_count}', ?::varchar::jsonb, true)", - u.info, - p.count - ) - ] - ) - |> select([u], u) - |> Repo.update_all([]) - |> case do - {1, [%{info: %User.Info{}} = user]} -> set_cache(user) - _ -> {:error, user} - end - end - - def set_unread_conversation_count(_), do: :noop - - def increment_unread_conversation_count(conversation, %User{local: true} = user) do - unread_query = - Participation.unread_conversation_count_for_user(user) - |> where([p], p.conversation_id == ^conversation.id) - - User - |> join(:inner, [u], p in subquery(unread_query)) - |> update([u, p], - set: [ - info: - fragment( - "jsonb_set(?, '{unread_conversation_count}', ((?->>'unread_conversation_count')::int + 1)::varchar::jsonb, true)", - u.info, - u.info - ) - ] - ) - |> where([u], u.id == ^user.id) - |> where([u, p], p.count == 0) - |> select([u], u) - |> Repo.update_all([]) - |> case do - {1, [%{info: %User.Info{}} = user]} -> set_cache(user) - _ -> {:error, user} - end - end - - def increment_unread_conversation_count(_, _), do: :noop - def remove_duplicated_following(%User{following: following} = user) do uniq_following = Enum.uniq(following) diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex index 4b5b43d7f..ebd4ddebf 100644 --- a/lib/pleroma/user/info.ex +++ b/lib/pleroma/user/info.ex @@ -47,7 +47,6 @@ defmodule Pleroma.User.Info do field(:hide_followers, :boolean, default: false) field(:hide_follows, :boolean, default: false) field(:hide_favorites, :boolean, default: true) - field(:unread_conversation_count, :integer, default: 0) field(:pinned_activities, {:array, :string}, default: []) field(:email_notifications, :map, default: %{"digest" => false}) field(:mascot, :map, default: nil) diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 2d4976891..99169ef95 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -167,7 +167,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do |> maybe_put_chat_token(user, opts[:for], opts) |> maybe_put_activation_status(user, opts[:for]) |> maybe_put_follow_requests_count(user, opts[:for]) - |> maybe_put_unread_conversation_count(user, opts[:for]) end defp username_from_nickname(string) when is_binary(string) do @@ -249,16 +248,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do defp maybe_put_activation_status(data, _, _), do: data - defp maybe_put_unread_conversation_count(data, %User{id: user_id} = user, %User{id: user_id}) do - data - |> Kernel.put_in( - [:pleroma, :unread_conversation_count], - user.info.unread_conversation_count - ) - end - - defp maybe_put_unread_conversation_count(data, _, _), do: data - defp image_url(%{"url" => [%{"href" => href} | _]}), do: href defp image_url(_), do: nil end -- cgit v1.2.3 From 977e711e22dd5171cbff241c7e763de8d34eef26 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Wed, 2 Oct 2019 13:18:51 +0200 Subject: Import object from self-Announce whenever possible --- lib/pleroma/web/activity_pub/transmogrifier.ex | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 64c470fc8..8f9bf5525 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -580,7 +580,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do ) do with actor <- Containment.get_actor(data), {:ok, %User{} = actor} <- User.get_or_fetch_by_ap_id(actor), - {:ok, object} <- get_obj_helper(object_id), + {:ok, object} <- get_embedded_obj_helper(object_id, actor), public <- Visibility.is_public?(data), {:ok, activity, _object} <- ActivityPub.announce(actor, object, id, false, public) do {:ok, activity} @@ -781,6 +781,29 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end end + @spec get_embedded_obj_helper(String.t() | Object.t(), User.t()) :: {:ok, Object.t()} | nil + def get_embedded_obj_helper(%{"attributedTo" => attributedTo, "id" => object_id} = data, %User{ + ap_id: ap_id + }) + when attributedTo == ap_id do + with {:ok, activity} <- + handle_incoming(%{ + "type" => "Create", + "to" => data["to"], + "cc" => data["cc"], + "actor" => data["attributedTo"], + "object" => data + }) do + {:ok, Object.normalize(activity)} + else + _ -> get_obj_helper(object_id) + end + end + + def get_embedded_obj_helper(object_id, _) do + get_obj_helper(object_id) + end + def set_reply_to_uri(%{"inReplyTo" => in_reply_to} = object) when is_binary(in_reply_to) do with false <- String.starts_with?(in_reply_to, "http"), {:ok, %{data: replied_to_object}} <- get_obj_helper(in_reply_to) do -- cgit v1.2.3 From 791d93ff0ecb304e3278b786e66689521e9ad19d Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Wed, 2 Oct 2019 13:46:06 +0200 Subject: Make credo happy --- lib/pleroma/web/activity_pub/transmogrifier.ex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 8f9bf5525..449c777dc 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -782,16 +782,16 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end @spec get_embedded_obj_helper(String.t() | Object.t(), User.t()) :: {:ok, Object.t()} | nil - def get_embedded_obj_helper(%{"attributedTo" => attributedTo, "id" => object_id} = data, %User{ + def get_embedded_obj_helper(%{"attributedTo" => attributed_to, "id" => object_id} = data, %User{ ap_id: ap_id }) - when attributedTo == ap_id do + when attributed_to == ap_id do with {:ok, activity} <- handle_incoming(%{ "type" => "Create", "to" => data["to"], "cc" => data["cc"], - "actor" => data["attributedTo"], + "actor" => attributed_to, "object" => data }) do {:ok, Object.normalize(activity)} -- cgit v1.2.3 From 4b8524f392e659d568ba6b0648952d7a1e314be0 Mon Sep 17 00:00:00 2001 From: lain Date: Sat, 5 Oct 2019 14:49:45 +0200 Subject: ActivityPub / Transmogrifier: Correctly store incoming Update id. --- lib/pleroma/web/activity_pub/activity_pub.ex | 4 +++- lib/pleroma/web/activity_pub/transmogrifier.ex | 3 ++- lib/pleroma/web/activity_pub/utils.ex | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index c52efb578..5052d1304 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -17,6 +17,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do alias Pleroma.User alias Pleroma.Web.ActivityPub.MRF alias Pleroma.Web.ActivityPub.Transmogrifier + alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.Streamer alias Pleroma.Web.WebFinger alias Pleroma.Workers.BackgroundWorker @@ -291,8 +292,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do end def update(%{to: to, cc: cc, actor: actor, object: object} = params) do - # only accept false as false value local = !(params[:local] == false) + activity_id = params[:activity_id] with data <- %{ "to" => to, @@ -301,6 +302,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do "actor" => actor, "object" => object }, + data <- Utils.maybe_put(data, "id", activity_id), {:ok, activity} <- insert(data, local), :ok <- maybe_federate(activity) do {:ok, activity} diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 64c470fc8..c56d2dd11 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -621,7 +621,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do to: data["to"] || [], cc: data["cc"] || [], object: object, - actor: actor_id + actor: actor_id, + activity_id: data["id"] }) else e -> diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 272011a9f..4ef479f96 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -739,6 +739,6 @@ defmodule Pleroma.Web.ActivityPub.Utils do |> Repo.all() end - defp maybe_put(map, _key, nil), do: map - defp maybe_put(map, key, value), do: Map.put(map, key, value) + def maybe_put(map, _key, nil), do: map + def maybe_put(map, key, value), do: Map.put(map, key, value) end -- cgit v1.2.3 From 276a52016307707fa6a2f91bd9a3038dcfb71ba7 Mon Sep 17 00:00:00 2001 From: lain Date: Sat, 5 Oct 2019 14:53:50 +0200 Subject: CommonAPI: Create profile updates as public. This saves us lots of sending out because we can use sharedInbox. --- lib/pleroma/web/common_api/common_api.ex | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index ce73b3270..386408d51 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -16,6 +16,8 @@ defmodule Pleroma.Web.CommonAPI do import Pleroma.Web.Gettext import Pleroma.Web.CommonAPI.Utils + require Pleroma.Constants + def follow(follower, followed) do timeout = Pleroma.Config.get([:activitypub, :follow_handshake_timeout]) @@ -271,7 +273,7 @@ defmodule Pleroma.Web.CommonAPI do ActivityPub.update(%{ local: true, - to: [user.follower_address], + to: [Pleroma.Constants.as_public(), user.follower_address], cc: [], actor: user.ap_id, object: Pleroma.Web.ActivityPub.UserView.render("user.json", %{user: user}) -- cgit v1.2.3 From 8249924485965148f3a690c5d76e5f8b3bd78940 Mon Sep 17 00:00:00 2001 From: eugenijm Date: Wed, 2 Oct 2019 00:37:08 +0300 Subject: Mastodon API: Add `pleroma.unread_conversation_count` to the Account entity --- lib/pleroma/conversation.ex | 2 + lib/pleroma/conversation/participation.ex | 17 +++++++ lib/pleroma/user.ex | 56 ++++++++++++++++++++++ lib/pleroma/user/info.ex | 1 + lib/pleroma/web/mastodon_api/views/account_view.ex | 11 +++++ 5 files changed, 87 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/conversation.ex b/lib/pleroma/conversation.ex index be5821ad7..098016af2 100644 --- a/lib/pleroma/conversation.ex +++ b/lib/pleroma/conversation.ex @@ -67,6 +67,8 @@ defmodule Pleroma.Conversation do participations = Enum.map(users, fn user -> + User.increment_unread_conversation_count(conversation, user) + {:ok, participation} = Participation.create_for_user_and_conversation(user, conversation, opts) diff --git a/lib/pleroma/conversation/participation.ex b/lib/pleroma/conversation/participation.ex index e946f6de2..ab81f3217 100644 --- a/lib/pleroma/conversation/participation.ex +++ b/lib/pleroma/conversation/participation.ex @@ -52,6 +52,15 @@ defmodule Pleroma.Conversation.Participation do participation |> read_cng(%{read: true}) |> Repo.update() + |> case do + {:ok, participation} -> + participation = Repo.preload(participation, :user) + User.set_unread_conversation_count(participation.user) + {:ok, participation} + + error -> + error + end end def mark_as_unread(participation) do @@ -135,4 +144,12 @@ defmodule Pleroma.Conversation.Participation do {:ok, Repo.preload(participation, :recipients, force: true)} end + + def unread_conversation_count_for_user(user) do + from(p in __MODULE__, + where: p.user_id == ^user.id, + where: not p.read, + select: %{count: count(p.id)} + ) + end end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index c2f8fa0d7..0d665afa6 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -11,6 +11,7 @@ defmodule Pleroma.User do alias Comeonin.Pbkdf2 alias Ecto.Multi alias Pleroma.Activity + alias Pleroma.Conversation.Participation alias Pleroma.Delivery alias Pleroma.Keys alias Pleroma.Notification @@ -842,6 +843,61 @@ defmodule Pleroma.User do def maybe_update_following_count(user), do: user + def set_unread_conversation_count(%User{local: true} = user) do + unread_query = Participation.unread_conversation_count_for_user(user) + + User + |> join(:inner, [u], p in subquery(unread_query)) + |> update([u, p], + set: [ + info: + fragment( + "jsonb_set(?, '{unread_conversation_count}', ?::varchar::jsonb, true)", + u.info, + p.count + ) + ] + ) + |> where([u], u.id == ^user.id) + |> select([u], u) + |> Repo.update_all([]) + |> case do + {1, [user]} -> set_cache(user) + _ -> {:error, user} + end + end + + def set_unread_conversation_count(_), do: :noop + + def increment_unread_conversation_count(conversation, %User{local: true} = user) do + unread_query = + Participation.unread_conversation_count_for_user(user) + |> where([p], p.conversation_id == ^conversation.id) + + User + |> join(:inner, [u], p in subquery(unread_query)) + |> update([u, p], + set: [ + info: + fragment( + "jsonb_set(?, '{unread_conversation_count}', (coalesce((?->>'unread_conversation_count')::int, 0) + 1)::varchar::jsonb, true)", + u.info, + u.info + ) + ] + ) + |> where([u], u.id == ^user.id) + |> where([u, p], p.count == 0) + |> select([u], u) + |> Repo.update_all([]) + |> case do + {1, [user]} -> set_cache(user) + _ -> {:error, user} + end + end + + def increment_unread_conversation_count(_, _), do: :noop + def remove_duplicated_following(%User{following: following} = user) do uniq_following = Enum.uniq(following) diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex index ebd4ddebf..4b5b43d7f 100644 --- a/lib/pleroma/user/info.ex +++ b/lib/pleroma/user/info.ex @@ -47,6 +47,7 @@ defmodule Pleroma.User.Info do field(:hide_followers, :boolean, default: false) field(:hide_follows, :boolean, default: false) field(:hide_favorites, :boolean, default: true) + field(:unread_conversation_count, :integer, default: 0) field(:pinned_activities, {:array, :string}, default: []) field(:email_notifications, :map, default: %{"digest" => false}) field(:mascot, :map, default: nil) diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 99169ef95..2d4976891 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -167,6 +167,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do |> maybe_put_chat_token(user, opts[:for], opts) |> maybe_put_activation_status(user, opts[:for]) |> maybe_put_follow_requests_count(user, opts[:for]) + |> maybe_put_unread_conversation_count(user, opts[:for]) end defp username_from_nickname(string) when is_binary(string) do @@ -248,6 +249,16 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do defp maybe_put_activation_status(data, _, _), do: data + defp maybe_put_unread_conversation_count(data, %User{id: user_id} = user, %User{id: user_id}) do + data + |> Kernel.put_in( + [:pleroma, :unread_conversation_count], + user.info.unread_conversation_count + ) + end + + defp maybe_put_unread_conversation_count(data, _, _), do: data + defp image_url(%{"url" => [%{"href" => href} | _]}), do: href defp image_url(_), do: nil end -- cgit v1.2.3 From fefbd31c6e60e25778ed01c522273375d4f04266 Mon Sep 17 00:00:00 2001 From: rinpatch Date: Sun, 6 Oct 2019 16:22:35 +0300 Subject: Move local keys out of `user.info` --- lib/pleroma/signature.ex | 2 +- lib/pleroma/user.ex | 8 ++++++-- lib/pleroma/web/activity_pub/views/user_view.ex | 4 ++-- lib/pleroma/web/salmon/salmon.ex | 4 ++-- 4 files changed, 11 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/signature.ex b/lib/pleroma/signature.ex index f20aeb0d5..1e7c9ae86 100644 --- a/lib/pleroma/signature.ex +++ b/lib/pleroma/signature.ex @@ -48,7 +48,7 @@ defmodule Pleroma.Signature do end def sign(%User{} = user, headers) do - with {:ok, %{info: %{keys: keys}}} <- User.ensure_keys_present(user), + with {:ok, %{keys: keys}} <- User.ensure_keys_present(user), {:ok, private_key, _} <- Keys.keys_from_pem(keys) do HTTPSignatures.sign(private_key, user.ap_id <> "#main-key", headers) end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 0d665afa6..2cfb13a8c 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -51,6 +51,7 @@ defmodule Pleroma.User do field(:password_hash, :string) field(:password, :string, virtual: true) field(:password_confirmation, :string, virtual: true) + field(:keys, :string) field(:following, {:array, :string}, default: []) field(:ap_id, :string) field(:avatar, :map) @@ -1554,11 +1555,14 @@ defmodule Pleroma.User do } end - def ensure_keys_present(%{info: %{keys: keys}} = user) when not is_nil(keys), do: {:ok, user} + def ensure_keys_present(%{keys: keys} = user) when not is_nil(keys), do: {:ok, user} def ensure_keys_present(%User{} = user) do with {:ok, pem} <- Keys.generate_rsa_pem() do - update_info(user, &User.Info.set_keys(&1, pem)) + user + |> cast(%{keys: pem}, [:keys]) + |> validate_required([:keys]) + |> update_and_set_cache() end end diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex index 6bc55c85b..9b39d1629 100644 --- a/lib/pleroma/web/activity_pub/views/user_view.ex +++ b/lib/pleroma/web/activity_pub/views/user_view.ex @@ -33,7 +33,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do def render("service.json", %{user: user}) do {:ok, user} = User.ensure_keys_present(user) - {:ok, _, public_key} = Keys.keys_from_pem(user.info.keys) + {:ok, _, public_key} = Keys.keys_from_pem(user.keys) public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key) public_key = :public_key.pem_encode([public_key]) @@ -69,7 +69,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do def render("user.json", %{user: user}) do {:ok, user} = User.ensure_keys_present(user) - {:ok, _, public_key} = Keys.keys_from_pem(user.info.keys) + {:ok, _, public_key} = Keys.keys_from_pem(user.keys) public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key) public_key = :public_key.pem_encode([public_key]) diff --git a/lib/pleroma/web/salmon/salmon.ex b/lib/pleroma/web/salmon/salmon.ex index 8ba7380c0..0ffe903cd 100644 --- a/lib/pleroma/web/salmon/salmon.ex +++ b/lib/pleroma/web/salmon/salmon.ex @@ -202,7 +202,7 @@ defmodule Pleroma.Web.Salmon do @spec publish(User.t(), Pleroma.Activity.t()) :: none def publish(user, activity) - def publish(%{info: %{keys: keys}} = user, %{data: %{"type" => type}} = activity) + def publish(%{keys: keys} = user, %{data: %{"type" => type}} = activity) when type in @supported_activities do feed = ActivityRepresenter.to_simple_form(activity, user, true) @@ -238,7 +238,7 @@ defmodule Pleroma.Web.Salmon do def publish(%{id: id}, _), do: Logger.debug(fn -> "Keys missing for user #{id}" end) def gather_webfinger_links(%User{} = user) do - {:ok, _private, public} = Keys.keys_from_pem(user.info.keys) + {:ok, _private, public} = Keys.keys_from_pem(user.keys) magic_key = encode_key(public) [ -- cgit v1.2.3 From b93856874de673f1c05c557ad482d4480ca7e0a7 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Sun, 6 Oct 2019 17:12:17 +0300 Subject: [#1234] Merge remote-tracking branch 'remotes/upstream/develop' into 1234-mastodon-2-4-3-oauth-scopes # Conflicts: # CHANGELOG.md # lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex # lib/pleroma/web/router.ex --- .../web/activity_pub/activity_pub_controller.ex | 5 - lib/pleroma/web/masto_fe_controller.ex | 12 + .../mastodon_api/controllers/account_controller.ex | 10 +- .../web/mastodon_api/controllers/app_controller.ex | 3 + .../controllers/domain_block_controller.ex | 2 + .../controllers/follow_request_controller.ex | 2 + .../controllers/mastodon_api_controller.ex | 63 ----- .../mastodon_api/controllers/media_controller.ex | 5 + .../controllers/notification_controller.ex | 2 + .../mastodon_api/controllers/poll_controller.ex | 10 + .../mastodon_api/controllers/report_controller.ex | 2 + .../mastodon_api/controllers/search_controller.ex | 2 + .../mastodon_api/controllers/status_controller.ex | 5 + .../controllers/subscription_controller.ex | 2 + .../controllers/suggestion_controller.ex | 5 + .../controllers/emoji_api_controller.ex | 18 ++ lib/pleroma/web/router.ex | 285 ++++++++------------- .../web/twitter_api/controllers/util_controller.ex | 2 + 18 files changed, 186 insertions(+), 249 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex index 93fd9e248..080030eb5 100644 --- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex +++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex @@ -30,11 +30,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do when action in [:activity, :object] ) - plug( - Pleroma.Plugs.OAuthScopesPlug, - %{scopes: ["read:accounts"]} when action in [:followers, :following] - ) - plug(Pleroma.Web.FederatingPlug when action in [:inbox, :relay]) plug(:set_requester_reachable when action in [:inbox]) plug(:relay_active? when action in [:relay]) diff --git a/lib/pleroma/web/masto_fe_controller.ex b/lib/pleroma/web/masto_fe_controller.ex index ac9af7502..87860f1d5 100644 --- a/lib/pleroma/web/masto_fe_controller.ex +++ b/lib/pleroma/web/masto_fe_controller.ex @@ -5,8 +5,20 @@ defmodule Pleroma.Web.MastoFEController do use Pleroma.Web, :controller + alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.User + plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action == :put_settings) + + # Note: :index action handles attempt of unauthenticated access to private instance with redirect + plug( + OAuthScopesPlug, + %{scopes: ["read"], fallback: :proceed_unauthenticated, skip_instance_privacy_check: true} + when action == :index + ) + + plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug when action != :index) + @doc "GET /web/*path" def index(%{assigns: %{user: user}} = conn, _params) do token = get_session(conn, :oauth_token) diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex index e195f56c4..9ef7fd48d 100644 --- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -36,6 +36,11 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do plug(OAuthScopesPlug, %{scopes: ["read:lists"]} when action == :lists) + plug( + OAuthScopesPlug, + %{scopes: ["follow", "read:blocks"]} when action == :blocks + ) + plug( OAuthScopesPlug, %{scopes: ["follow", "write:blocks"]} when action in [:block, :unblock] @@ -43,11 +48,14 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do plug(OAuthScopesPlug, %{scopes: ["read:follows"]} when action == :relationships) + # Note: :follows (POST /api/v1/follows) is the same as :follow, consider removing :follows plug( OAuthScopesPlug, - %{scopes: ["follow", "write:follows"]} when action in [:follow, :unfollow] + %{scopes: ["follow", "write:follows"]} when action in [:follows, :follow, :unfollow] ) + plug(OAuthScopesPlug, %{scopes: ["follow", "read:mutes"]} when action == :mutes) + plug(OAuthScopesPlug, %{scopes: ["follow", "write:mutes"]} when action in [:mute, :unmute]) plug( diff --git a/lib/pleroma/web/mastodon_api/controllers/app_controller.ex b/lib/pleroma/web/mastodon_api/controllers/app_controller.ex index abbe16a88..13a30a34d 100644 --- a/lib/pleroma/web/mastodon_api/controllers/app_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/app_controller.ex @@ -5,6 +5,7 @@ defmodule Pleroma.Web.MastodonAPI.AppController do use Pleroma.Web, :controller + alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.Repo alias Pleroma.Web.OAuth.App alias Pleroma.Web.OAuth.Scopes @@ -12,6 +13,8 @@ defmodule Pleroma.Web.MastodonAPI.AppController do action_fallback(Pleroma.Web.MastodonAPI.FallbackController) + plug(OAuthScopesPlug, %{scopes: ["read"]} when action == :verify_credentials) + @local_mastodon_name "Mastodon-Local" @doc "POST /api/v1/apps" diff --git a/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex b/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex index 45c5ef8a4..c7606246b 100644 --- a/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex @@ -18,6 +18,8 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockController do %{scopes: ["follow", "write:blocks"]} when action != :index ) + plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug) + @doc "GET /api/v1/domain_blocks" def index(%{assigns: %{user: %{info: info}}} = conn, _) do json(conn, Map.get(info, :domain_blocks, [])) diff --git a/lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex b/lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex index 06672e2bb..3ccbdf1c6 100644 --- a/lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex @@ -21,6 +21,8 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestController do %{scopes: ["follow", "write:follows"]} when action != :index ) + plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug) + @doc "GET /api/v1/follow_requests" def index(%{assigns: %{user: followed}} = conn, _params) do follow_requests = User.get_follow_requests(followed) diff --git a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex index 32077d420..7d839a8cf 100644 --- a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex @@ -7,69 +7,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do require Logger - alias Pleroma.Plugs.OAuthScopesPlug - @unauthenticated_access %{fallback: :proceed_unauthenticated, scopes: []} - - # Note: :index action handles attempt of unauthenticated access to private instance with redirect - plug( - OAuthScopesPlug, - Map.merge(@unauthenticated_access, %{scopes: ["read"], skip_instance_privacy_check: true}) - when action == :index - ) - - plug( - OAuthScopesPlug, - %{scopes: ["read"]} when action in [:suggestions, :verify_app_credentials] - ) - - plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action == :put_settings) - - plug( - OAuthScopesPlug, - %{@unauthenticated_access | scopes: ["read:statuses"]} when action == :get_poll - ) - - plug(OAuthScopesPlug, %{scopes: ["write:statuses"]} when action == :poll_vote) - - plug(OAuthScopesPlug, %{scopes: ["read:favourites"]} when action == :favourites) - - plug(OAuthScopesPlug, %{scopes: ["write:media"]} when action in [:upload, :update_media]) - - plug( - OAuthScopesPlug, - %{scopes: ["follow", "read:blocks"]} when action == :blocks - ) - - # To do: POST /api/v1/follows is not present in Mastodon; consider removing the action - plug( - OAuthScopesPlug, - %{scopes: ["follow", "write:follows"]} when action == :follows - ) - - plug(OAuthScopesPlug, %{scopes: ["follow", "read:mutes"]} when action == :mutes) - - # Note: scope not present in Mastodon: read:bookmarks - plug(OAuthScopesPlug, %{scopes: ["read:bookmarks"]} when action == :bookmarks) - - # An extra safety measure for possible actions not guarded by OAuth permissions specification - plug( - Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug - when action not in [ - :create_app, - :index, - :login, - :logout, - :password_reset, - :masto_instance, - :peers, - :custom_emojis - ] - ) - - plug(RateLimiter, :password_reset when action == :password_reset) - - @local_mastodon_name "Mastodon-Local" - action_fallback(Pleroma.Web.MastodonAPI.FallbackController) # Stubs for unimplemented mastodon api diff --git a/lib/pleroma/web/mastodon_api/controllers/media_controller.ex b/lib/pleroma/web/mastodon_api/controllers/media_controller.ex index 57a5b60fb..ed4c08d99 100644 --- a/lib/pleroma/web/mastodon_api/controllers/media_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/media_controller.ex @@ -6,12 +6,17 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do use Pleroma.Web, :controller alias Pleroma.Object + alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub action_fallback(Pleroma.Web.MastodonAPI.FallbackController) plug(:put_view, Pleroma.Web.MastodonAPI.StatusView) + plug(OAuthScopesPlug, %{scopes: ["write:media"]}) + + plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug) + @doc "POST /api/v1/media" def create(%{assigns: %{user: user}} = conn, %{"file" => file} = data) do with {:ok, object} <- diff --git a/lib/pleroma/web/mastodon_api/controllers/notification_controller.ex b/lib/pleroma/web/mastodon_api/controllers/notification_controller.ex index 36c6defc2..16759be6a 100644 --- a/lib/pleroma/web/mastodon_api/controllers/notification_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/notification_controller.ex @@ -20,6 +20,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action not in @oauth_read_actions) + plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug) + # GET /api/v1/notifications def index(%{assigns: %{user: user}} = conn, params) do notifications = MastodonAPI.get_notifications(user, params) diff --git a/lib/pleroma/web/mastodon_api/controllers/poll_controller.ex b/lib/pleroma/web/mastodon_api/controllers/poll_controller.ex index fbf7f8673..d129f8672 100644 --- a/lib/pleroma/web/mastodon_api/controllers/poll_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/poll_controller.ex @@ -9,11 +9,21 @@ defmodule Pleroma.Web.MastodonAPI.PollController do alias Pleroma.Activity alias Pleroma.Object + alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.Web.ActivityPub.Visibility alias Pleroma.Web.CommonAPI action_fallback(Pleroma.Web.MastodonAPI.FallbackController) + plug( + OAuthScopesPlug, + %{scopes: ["read:statuses"], fallback: :proceed_unauthenticated} when action == :show + ) + + plug(OAuthScopesPlug, %{scopes: ["write:statuses"]} when action == :vote) + + plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug) + @doc "GET /api/v1/polls/:id" def show(%{assigns: %{user: user}} = conn, %{"id" => id}) do with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60), diff --git a/lib/pleroma/web/mastodon_api/controllers/report_controller.ex b/lib/pleroma/web/mastodon_api/controllers/report_controller.ex index 313f885a6..263c2180f 100644 --- a/lib/pleroma/web/mastodon_api/controllers/report_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/report_controller.ex @@ -11,6 +11,8 @@ defmodule Pleroma.Web.MastodonAPI.ReportController do plug(OAuthScopesPlug, %{scopes: ["write:reports"]} when action == :create) + plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug) + @doc "POST /api/v1/reports" def create(%{assigns: %{user: user}} = conn, params) do with {:ok, activity} <- Pleroma.Web.CommonAPI.report(user, params) do diff --git a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex index 9f39b00f8..6cfd68a84 100644 --- a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex @@ -20,6 +20,8 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do # Note: Mastodon doesn't allow unauthenticated access (requires read:accounts / read:search) plug(OAuthScopesPlug, %{scopes: ["read:search"], fallback: :proceed_unauthenticated}) + plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug) + plug(RateLimiter, :search when action in [:search, :search2, :account_search]) def account_search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do diff --git a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex index 2cbf33046..0c16e9b0f 100644 --- a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex @@ -47,6 +47,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do ] ) + plug(OAuthScopesPlug, %{scopes: ["read:favourites"]} when action == :favourites) + plug( OAuthScopesPlug, %{scopes: ["write:favourites"]} when action in [:favourite, :unfavourite] @@ -65,6 +67,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action in [:pin, :unpin]) + # Note: scope not present in Mastodon: read:bookmarks + plug(OAuthScopesPlug, %{scopes: ["read:bookmarks"]} when action == :bookmarks) + # Note: scope not present in Mastodon: write:bookmarks plug( OAuthScopesPlug, diff --git a/lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex b/lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex index 287eebf92..fc7d52824 100644 --- a/lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex @@ -14,6 +14,8 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionController do plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["push"]}) + plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug) + # Creates PushSubscription # POST /api/v1/push/subscription # diff --git a/lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex b/lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex index 9076bb849..fe71c36af 100644 --- a/lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex @@ -8,11 +8,16 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionController do require Logger alias Pleroma.Config + alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.User alias Pleroma.Web.MediaProxy action_fallback(Pleroma.Web.MastodonAPI.FallbackController) + plug(OAuthScopesPlug, %{scopes: ["read"]} when action == :index) + + plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug) + @doc "GET /api/v1/suggestions" def index(%{assigns: %{user: user}} = conn, _) do if Config.get([:suggestions, :enabled], false) do diff --git a/lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex b/lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex index 545ad80c9..a474d41d4 100644 --- a/lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex @@ -1,8 +1,26 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do use Pleroma.Web, :controller + alias Pleroma.Plugs.OAuthScopesPlug + require Logger + plug( + OAuthScopesPlug, + %{scopes: ["write"]} + when action in [ + :create, + :delete, + :download_from, + :list_from, + :import_from_fs, + :update_file, + :update_metadata + ] + ) + + plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug) + def emoji_dir_path do Path.join( Pleroma.Config.get!([:instance, :static_dir]), diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index a36c40a3b..675f485b2 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -87,31 +87,6 @@ defmodule Pleroma.Web.Router do plug(Pleroma.Plugs.EnsureUserKeyPlug) end - pipeline :oauth_read_or_public do - plug(Pleroma.Plugs.OAuthScopesPlug, %{ - scopes: ["read"], - fallback: :proceed_unauthenticated - }) - - plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug) - end - - pipeline :oauth_read do - plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["read"]}) - end - - pipeline :oauth_write do - plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["write"]}) - end - - pipeline :oauth_follow do - plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["follow"]}) - end - - pipeline :oauth_push do - plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["push"]}) - end - pipeline :well_known do plug(:accepts, ["json", "jrd+json", "xml", "xrd+xml"]) end @@ -154,7 +129,7 @@ defmodule Pleroma.Web.Router do end scope "/api/pleroma/admin", Pleroma.Web.AdminAPI do - pipe_through([:admin_api, :oauth_write]) + pipe_through(:admin_api) post("/users/follow", AdminAPIController, :user_follow) post("/users/unfollow", AdminAPIController, :user_unfollow) @@ -213,7 +188,7 @@ defmodule Pleroma.Web.Router do scope "/api/pleroma/emoji", Pleroma.Web.PleromaAPI do scope "/packs" do # Modifying packs - pipe_through([:admin_api, :oauth_write]) + pipe_through(:admin_api) post("/import_from_fs", EmojiAPIController, :import_from_fs) @@ -238,31 +213,20 @@ defmodule Pleroma.Web.Router do post("/main/ostatus", UtilController, :remote_subscribe) get("/ostatus_subscribe", UtilController, :remote_follow) - scope [] do - pipe_through(:oauth_follow) - post("/ostatus_subscribe", UtilController, :do_remote_follow) - end + post("/ostatus_subscribe", UtilController, :do_remote_follow) end scope "/api/pleroma", Pleroma.Web.TwitterAPI do pipe_through(:authenticated_api) - scope [] do - pipe_through(:oauth_write) - - post("/change_email", UtilController, :change_email) - post("/change_password", UtilController, :change_password) - post("/delete_account", UtilController, :delete_account) - put("/notification_settings", UtilController, :update_notificaton_settings) - post("/disable_account", UtilController, :disable_account) - end + post("/change_email", UtilController, :change_email) + post("/change_password", UtilController, :change_password) + post("/delete_account", UtilController, :delete_account) + put("/notification_settings", UtilController, :update_notificaton_settings) + post("/disable_account", UtilController, :disable_account) - scope [] do - pipe_through(:oauth_follow) - - post("/blocks_import", UtilController, :blocks_import) - post("/follow_import", UtilController, :follow_import) - end + post("/blocks_import", UtilController, :blocks_import) + post("/follow_import", UtilController, :follow_import) end scope "/oauth", Pleroma.Web.OAuth do @@ -289,14 +253,14 @@ defmodule Pleroma.Web.Router do scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do scope [] do pipe_through(:authenticated_api) - pipe_through(:oauth_read) + get("/conversations/:id/statuses", PleromaAPIController, :conversation_statuses) get("/conversations/:id", PleromaAPIController, :conversation) end scope [] do pipe_through(:authenticated_api) - pipe_through(:oauth_write) + patch("/conversations/:id", PleromaAPIController, :update_conversation) post("/notifications/read", PleromaAPIController, :read_notification) @@ -312,13 +276,11 @@ defmodule Pleroma.Web.Router do scope [] do pipe_through(:api) - pipe_through(:oauth_read_or_public) get("/accounts/:id/favourites", AccountController, :favourites) end scope [] do pipe_through(:authenticated_api) - pipe_through(:oauth_follow) post("/accounts/:id/subscribe", AccountController, :subscribe) post("/accounts/:id/unsubscribe", AccountController, :unsubscribe) @@ -328,131 +290,114 @@ defmodule Pleroma.Web.Router do end scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do - pipe_through([:api, :oauth_read_or_public]) - + pipe_through(:api) get("/accounts/:id/scrobbles", ScrobbleController, :user_scrobbles) end scope "/api/v1", Pleroma.Web.MastodonAPI do pipe_through(:authenticated_api) - scope [] do - pipe_through(:oauth_read) - - get("/accounts/verify_credentials", AccountController, :verify_credentials) + get("/accounts/verify_credentials", AccountController, :verify_credentials) - get("/accounts/relationships", AccountController, :relationships) + get("/accounts/relationships", AccountController, :relationships) - get("/accounts/:id/lists", AccountController, :lists) - get("/accounts/:id/identity_proofs", MastodonAPIController, :empty_array) + get("/accounts/:id/lists", AccountController, :lists) + get("/accounts/:id/identity_proofs", MastodonAPIController, :empty_array) - get("/follow_requests", FollowRequestController, :index) - get("/blocks", AccountController, :blocks) - get("/mutes", AccountController, :mutes) + get("/follow_requests", FollowRequestController, :index) + get("/blocks", AccountController, :blocks) + get("/mutes", AccountController, :mutes) - get("/timelines/home", TimelineController, :home) - get("/timelines/direct", TimelineController, :direct) + get("/timelines/home", TimelineController, :home) + get("/timelines/direct", TimelineController, :direct) - get("/favourites", StatusController, :favourites) - get("/bookmarks", StatusController, :bookmarks) + get("/favourites", StatusController, :favourites) + get("/bookmarks", StatusController, :bookmarks) - get("/notifications", NotificationController, :index) - get("/notifications/:id", NotificationController, :show) - post("/notifications/clear", NotificationController, :clear) - post("/notifications/dismiss", NotificationController, :dismiss) - delete("/notifications/destroy_multiple", NotificationController, :destroy_multiple) + get("/notifications", NotificationController, :index) + get("/notifications/:id", NotificationController, :show) + post("/notifications/clear", NotificationController, :clear) + post("/notifications/dismiss", NotificationController, :dismiss) + delete("/notifications/destroy_multiple", NotificationController, :destroy_multiple) - get("/scheduled_statuses", ScheduledActivityController, :index) - get("/scheduled_statuses/:id", ScheduledActivityController, :show) + get("/scheduled_statuses", ScheduledActivityController, :index) + get("/scheduled_statuses/:id", ScheduledActivityController, :show) - get("/lists", ListController, :index) - get("/lists/:id", ListController, :show) - get("/lists/:id/accounts", ListController, :list_accounts) + get("/lists", ListController, :index) + get("/lists/:id", ListController, :show) + get("/lists/:id/accounts", ListController, :list_accounts) - get("/domain_blocks", DomainBlockController, :index) + get("/domain_blocks", DomainBlockController, :index) - get("/filters", FilterController, :index) + get("/filters", FilterController, :index) - get("/suggestions", SuggestionController, :index) + get("/suggestions", SuggestionController, :index) - get("/conversations", ConversationController, :index) - post("/conversations/:id/read", ConversationController, :read) + get("/conversations", ConversationController, :index) + post("/conversations/:id/read", ConversationController, :read) - get("/endorsements", MastodonAPIController, :empty_array) - end + get("/endorsements", AccountController, :endorsements) - scope [] do - pipe_through(:oauth_write) + patch("/accounts/update_credentials", AccountController, :update_credentials) - patch("/accounts/update_credentials", AccountController, :update_credentials) + post("/statuses", StatusController, :create) + delete("/statuses/:id", StatusController, :delete) - post("/statuses", StatusController, :create) - delete("/statuses/:id", StatusController, :delete) + post("/statuses/:id/reblog", StatusController, :reblog) + post("/statuses/:id/unreblog", StatusController, :unreblog) + post("/statuses/:id/favourite", StatusController, :favourite) + post("/statuses/:id/unfavourite", StatusController, :unfavourite) + post("/statuses/:id/pin", StatusController, :pin) + post("/statuses/:id/unpin", StatusController, :unpin) + post("/statuses/:id/bookmark", StatusController, :bookmark) + post("/statuses/:id/unbookmark", StatusController, :unbookmark) + post("/statuses/:id/mute", StatusController, :mute_conversation) + post("/statuses/:id/unmute", StatusController, :unmute_conversation) - post("/statuses/:id/reblog", StatusController, :reblog) - post("/statuses/:id/unreblog", StatusController, :unreblog) - post("/statuses/:id/favourite", StatusController, :favourite) - post("/statuses/:id/unfavourite", StatusController, :unfavourite) - post("/statuses/:id/pin", StatusController, :pin) - post("/statuses/:id/unpin", StatusController, :unpin) - post("/statuses/:id/bookmark", StatusController, :bookmark) - post("/statuses/:id/unbookmark", StatusController, :unbookmark) - post("/statuses/:id/mute", StatusController, :mute_conversation) - post("/statuses/:id/unmute", StatusController, :unmute_conversation) + put("/scheduled_statuses/:id", ScheduledActivityController, :update) + delete("/scheduled_statuses/:id", ScheduledActivityController, :delete) - put("/scheduled_statuses/:id", ScheduledActivityController, :update) - delete("/scheduled_statuses/:id", ScheduledActivityController, :delete) + post("/polls/:id/votes", PollController, :vote) - post("/polls/:id/votes", PollController, :vote) + post("/media", MediaController, :create) + put("/media/:id", MediaController, :update) - post("/media", MediaController, :create) - put("/media/:id", MediaController, :update) + delete("/lists/:id", ListController, :delete) + post("/lists", ListController, :create) + put("/lists/:id", ListController, :update) - delete("/lists/:id", ListController, :delete) - post("/lists", ListController, :create) - put("/lists/:id", ListController, :update) + post("/lists/:id/accounts", ListController, :add_to_list) + delete("/lists/:id/accounts", ListController, :remove_from_list) - post("/lists/:id/accounts", ListController, :add_to_list) - delete("/lists/:id/accounts", ListController, :remove_from_list) + post("/filters", FilterController, :create) + get("/filters/:id", FilterController, :show) + put("/filters/:id", FilterController, :update) + delete("/filters/:id", FilterController, :delete) - post("/filters", FilterController, :create) - get("/filters/:id", FilterController, :show) - put("/filters/:id", FilterController, :update) - delete("/filters/:id", FilterController, :delete) + post("/reports", ReportController, :create) - post("/reports", ReportController, :create) - end + post("/follows", AccountController, :follows) + post("/accounts/:id/follow", AccountController, :follow) + post("/accounts/:id/unfollow", AccountController, :unfollow) + post("/accounts/:id/block", AccountController, :block) + post("/accounts/:id/unblock", AccountController, :unblock) + post("/accounts/:id/mute", AccountController, :mute) + post("/accounts/:id/unmute", AccountController, :unmute) - scope [] do - pipe_through(:oauth_follow) + post("/follow_requests/:id/authorize", FollowRequestController, :authorize) + post("/follow_requests/:id/reject", FollowRequestController, :reject) - post("/follows", AccountController, :follows) - post("/accounts/:id/follow", AccountController, :follow) - post("/accounts/:id/unfollow", AccountController, :unfollow) - post("/accounts/:id/block", AccountController, :block) - post("/accounts/:id/unblock", AccountController, :unblock) - post("/accounts/:id/mute", AccountController, :mute) - post("/accounts/:id/unmute", AccountController, :unmute) - - post("/follow_requests/:id/authorize", FollowRequestController, :authorize) - post("/follow_requests/:id/reject", FollowRequestController, :reject) - - post("/domain_blocks", DomainBlockController, :create) - delete("/domain_blocks", DomainBlockController, :delete) - end + post("/domain_blocks", DomainBlockController, :create) + delete("/domain_blocks", DomainBlockController, :delete) - scope [] do - pipe_through(:oauth_push) - - post("/push/subscription", SubscriptionController, :create) - get("/push/subscription", SubscriptionController, :get) - put("/push/subscription", SubscriptionController, :update) - delete("/push/subscription", SubscriptionController, :delete) - end + post("/push/subscription", SubscriptionController, :create) + get("/push/subscription", SubscriptionController, :get) + put("/push/subscription", SubscriptionController, :update) + delete("/push/subscription", SubscriptionController, :delete) end scope "/api/web", Pleroma.Web do - pipe_through([:authenticated_api, :oauth_write]) + pipe_through(:authenticated_api) put("/settings", MastoFEController, :put_settings) end @@ -477,30 +422,26 @@ defmodule Pleroma.Web.Router do get("/trends", MastodonAPIController, :empty_array) - scope [] do - pipe_through(:oauth_read_or_public) - - get("/timelines/public", TimelineController, :public) - get("/timelines/tag/:tag", TimelineController, :hashtag) - get("/timelines/list/:list_id", TimelineController, :list) + get("/timelines/public", TimelineController, :public) + get("/timelines/tag/:tag", TimelineController, :hashtag) + get("/timelines/list/:list_id", TimelineController, :list) - get("/statuses", StatusController, :index) - get("/statuses/:id", StatusController, :show) - get("/statuses/:id/context", StatusController, :context) + get("/statuses", StatusController, :index) + get("/statuses/:id", StatusController, :show) + get("/statuses/:id/context", StatusController, :context) - get("/polls/:id", PollController, :show) + get("/polls/:id", PollController, :show) - get("/accounts/:id/statuses", AccountController, :statuses) - get("/accounts/:id/followers", AccountController, :followers) - get("/accounts/:id/following", AccountController, :following) - get("/accounts/:id", AccountController, :show) + get("/accounts/:id/statuses", AccountController, :statuses) + get("/accounts/:id/followers", AccountController, :followers) + get("/accounts/:id/following", AccountController, :following) + get("/accounts/:id", AccountController, :show) - get("/search", SearchController, :search) - end + get("/search", SearchController, :search) end scope "/api/v2", Pleroma.Web.MastodonAPI do - pipe_through([:api, :oauth_read_or_public]) + pipe_through(:api) get("/search", SearchController, :search2) end @@ -531,11 +472,7 @@ defmodule Pleroma.Web.Router do get("/oauth_tokens", TwitterAPI.Controller, :oauth_tokens) delete("/oauth_tokens/:id", TwitterAPI.Controller, :revoke_token) - scope [] do - pipe_through(:oauth_read) - - post("/qvitter/statuses/notifications/read", TwitterAPI.Controller, :notifications_read) - end + post("/qvitter/statuses/notifications/read", TwitterAPI.Controller, :notifications_read) end pipeline :ap_service_actor do @@ -599,23 +536,14 @@ defmodule Pleroma.Web.Router do scope "/", Pleroma.Web.ActivityPub do pipe_through([:activitypub_client]) - scope [] do - pipe_through(:oauth_read) - get("/api/ap/whoami", ActivityPubController, :whoami) - get("/users/:nickname/inbox", ActivityPubController, :read_inbox) - end + get("/api/ap/whoami", ActivityPubController, :whoami) + get("/users/:nickname/inbox", ActivityPubController, :read_inbox) - scope [] do - pipe_through(:oauth_write) - post("/users/:nickname/outbox", ActivityPubController, :update_outbox) - post("/api/ap/upload_media", ActivityPubController, :upload_media) - end + post("/users/:nickname/outbox", ActivityPubController, :update_outbox) + post("/api/ap/upload_media", ActivityPubController, :upload_media) - scope [] do - pipe_through(:oauth_read_or_public) - get("/users/:nickname/followers", ActivityPubController, :followers) - get("/users/:nickname/following", ActivityPubController, :following) - end + get("/users/:nickname/followers", ActivityPubController, :followers) + get("/users/:nickname/following", ActivityPubController, :following) end scope "/", Pleroma.Web.ActivityPub do @@ -665,10 +593,7 @@ defmodule Pleroma.Web.Router do post("/auth/password", MastodonAPI.AuthController, :password_reset) - scope [] do - pipe_through(:oauth_read) - get("/web/*path", MastoFEController, :index) - end + get("/web/*path", MastoFEController, :index) end pipeline :remote_media do diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex index c84359ddb..2305bb413 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -39,6 +39,8 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do ] ) + plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action == :notifications_read) + plug(Pleroma.Plugs.SetFormatPlug when action in [:config, :version]) def help_test(conn, _params) do -- cgit v1.2.3 From 1d8e956c32e412283aed0cebf90df11121d897bb Mon Sep 17 00:00:00 2001 From: feld Date: Sun, 6 Oct 2019 14:13:04 +0000 Subject: Use the user.id instead of nickname in report URLs Ensures links to profiles of remote users work. --- lib/pleroma/emails/admin_email.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/emails/admin_email.ex b/lib/pleroma/emails/admin_email.ex index c14be02dd..5a0903c13 100644 --- a/lib/pleroma/emails/admin_email.ex +++ b/lib/pleroma/emails/admin_email.ex @@ -17,7 +17,7 @@ defmodule Pleroma.Emails.AdminEmail do end defp user_url(user) do - Helpers.o_status_url(Pleroma.Web.Endpoint, :feed_redirect, user.nickname) + Helpers.o_status_url(Pleroma.Web.Endpoint, :feed_redirect, user.id) end def report(to, reporter, account, statuses, comment) do -- cgit v1.2.3 From 58aeabd020ae7355aea6b63a331b164e8b23a6c0 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Mon, 7 Oct 2019 02:55:09 +0200 Subject: mrf/simple_policy: check actor against accept/reject --- lib/pleroma/web/activity_pub/mrf/simple_policy.ex | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex index 8aa6852f0..8e53296e7 100644 --- a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex @@ -168,7 +168,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do when obj_type in ["Application", "Group", "Organization", "Person", "Service"] do actor_info = URI.parse(actor) - with {:ok, object} <- check_avatar_removal(actor_info, object), + with {:ok, object} <- check_accept(actor_info, object), + {:ok, object} <- check_reject(actor_info, object), + {:ok, object} <- check_avatar_removal(actor_info, object), {:ok, object} <- check_banner_removal(actor_info, object) do {:ok, object} else -- cgit v1.2.3 From 4b3f77a99ff849f7593f63f7dccd206683b34d97 Mon Sep 17 00:00:00 2001 From: Sergey Suprunenko Date: Mon, 7 Oct 2019 12:20:41 +0000 Subject: Extract RSS Feed functionality from OStatus --- lib/pleroma/emails/admin_email.ex | 2 +- lib/pleroma/web/feed/feed_controller.ex | 63 ++++++++++++++++++ lib/pleroma/web/feed/feed_view.ex | 77 ++++++++++++++++++++++ lib/pleroma/web/metadata/feed.ex | 23 +++++++ lib/pleroma/web/ostatus/ostatus_controller.ex | 43 +----------- lib/pleroma/web/router.ex | 5 +- .../web/templates/feed/feed/_activity.xml.eex | 48 ++++++++++++++ .../web/templates/feed/feed/_author.xml.eex | 17 +++++ lib/pleroma/web/templates/feed/feed/feed.xml.eex | 26 ++++++++ 9 files changed, 259 insertions(+), 45 deletions(-) create mode 100644 lib/pleroma/web/feed/feed_controller.ex create mode 100644 lib/pleroma/web/feed/feed_view.ex create mode 100644 lib/pleroma/web/metadata/feed.ex create mode 100644 lib/pleroma/web/templates/feed/feed/_activity.xml.eex create mode 100644 lib/pleroma/web/templates/feed/feed/_author.xml.eex create mode 100644 lib/pleroma/web/templates/feed/feed/feed.xml.eex (limited to 'lib') diff --git a/lib/pleroma/emails/admin_email.ex b/lib/pleroma/emails/admin_email.ex index 5a0903c13..b15e4041b 100644 --- a/lib/pleroma/emails/admin_email.ex +++ b/lib/pleroma/emails/admin_email.ex @@ -17,7 +17,7 @@ defmodule Pleroma.Emails.AdminEmail do end defp user_url(user) do - Helpers.o_status_url(Pleroma.Web.Endpoint, :feed_redirect, user.id) + Helpers.feed_url(Pleroma.Web.Endpoint, :feed_redirect, user.id) end def report(to, reporter, account, statuses, comment) do diff --git a/lib/pleroma/web/feed/feed_controller.ex b/lib/pleroma/web/feed/feed_controller.ex new file mode 100644 index 000000000..d91ecef9c --- /dev/null +++ b/lib/pleroma/web/feed/feed_controller.ex @@ -0,0 +1,63 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.Feed.FeedController do + use Pleroma.Web, :controller + + alias Fallback.RedirectController + alias Pleroma.User + alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.ActivityPub.ActivityPubController + + plug(Pleroma.Plugs.SetFormatPlug when action in [:feed_redirect]) + + action_fallback(:errors) + + def feed_redirect(%{assigns: %{format: "html"}} = conn, %{"nickname" => nickname}) do + with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname_or_id(nickname)} do + RedirectController.redirector_with_meta(conn, %{user: user}) + end + end + + def feed_redirect(%{assigns: %{format: format}} = conn, _params) + when format in ["json", "activity+json"] do + ActivityPubController.call(conn, :user) + end + + def feed_redirect(conn, %{"nickname" => nickname}) do + with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do + redirect(conn, external: "#{feed_url(conn, :feed, user.nickname)}.atom") + end + end + + def feed(conn, %{"nickname" => nickname} = params) do + with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do + query_params = + params + |> Map.take(["max_id"]) + |> Map.put("type", ["Create"]) + |> Map.put("whole_db", true) + |> Map.put("actor_id", user.ap_id) + + activities = + query_params + |> ActivityPub.fetch_public_activities() + |> Enum.reverse() + + conn + |> put_resp_content_type("application/atom+xml") + |> render("feed.xml", user: user, activities: activities) + end + end + + def errors(conn, {:error, :not_found}) do + render_error(conn, :not_found, "Not found") + end + + def errors(conn, {:fetch_user, nil}), do: errors(conn, {:error, :not_found}) + + def errors(conn, _) do + render_error(conn, :internal_server_error, "Something went wrong") + end +end diff --git a/lib/pleroma/web/feed/feed_view.ex b/lib/pleroma/web/feed/feed_view.ex new file mode 100644 index 000000000..5eef1e757 --- /dev/null +++ b/lib/pleroma/web/feed/feed_view.ex @@ -0,0 +1,77 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.Feed.FeedView do + use Phoenix.HTML + use Pleroma.Web, :view + + alias Pleroma.Object + alias Pleroma.User + alias Pleroma.Web.MediaProxy + + require Pleroma.Constants + + def most_recent_update(activities, user) do + (List.first(activities) || user).updated_at + |> NaiveDateTime.to_iso8601() + end + + def logo(user) do + user + |> User.avatar_url() + |> MediaProxy.url() + end + + def last_activity(activities) do + List.last(activities) + end + + def activity_object(activity) do + Object.normalize(activity) + end + + def activity_object_data(activity) do + activity + |> activity_object() + |> Map.get(:data) + end + + def activity_content(activity) do + content = activity_object_data(activity)["content"] + + content + |> String.replace(~r/[\n\r]/, "") + |> escape() + end + + def activity_context(activity) do + activity.data["context"] + end + + def attachment_href(attachment) do + attachment["url"] + |> hd() + |> Map.get("href") + end + + def attachment_type(attachment) do + attachment["url"] + |> hd() + |> Map.get("mediaType") + end + + def get_href(id) do + with %Object{data: %{"external_url" => external_url}} <- Object.get_cached_by_ap_id(id) do + external_url + else + _e -> id + end + end + + def escape(html) do + html + |> html_escape() + |> safe_to_string() + end +end diff --git a/lib/pleroma/web/metadata/feed.ex b/lib/pleroma/web/metadata/feed.ex new file mode 100644 index 000000000..8043e6c54 --- /dev/null +++ b/lib/pleroma/web/metadata/feed.ex @@ -0,0 +1,23 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.Metadata.Providers.Feed do + alias Pleroma.Web.Endpoint + alias Pleroma.Web.Metadata.Providers.Provider + alias Pleroma.Web.Router.Helpers + + @behaviour Provider + + @impl Provider + def build_tags(%{user: user}) do + [ + {:link, + [ + rel: "alternate", + type: "application/atom+xml", + href: Helpers.feed_path(Endpoint, :feed, user.nickname) <> ".atom" + ], []} + ] + end +end diff --git a/lib/pleroma/web/ostatus/ostatus_controller.ex b/lib/pleroma/web/ostatus/ostatus_controller.ex index 8f325b28e..20f2d9ddc 100644 --- a/lib/pleroma/web/ostatus/ostatus_controller.ex +++ b/lib/pleroma/web/ostatus/ostatus_controller.ex @@ -9,16 +9,13 @@ defmodule Pleroma.Web.OStatus.OStatusController do alias Pleroma.Activity alias Pleroma.Object alias Pleroma.User - alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPubController alias Pleroma.Web.ActivityPub.ObjectView alias Pleroma.Web.ActivityPub.Visibility alias Pleroma.Web.Endpoint alias Pleroma.Web.Federator alias Pleroma.Web.Metadata.PlayerView - alias Pleroma.Web.OStatus alias Pleroma.Web.OStatus.ActivityRepresenter - alias Pleroma.Web.OStatus.FeedRepresenter alias Pleroma.Web.Router alias Pleroma.Web.XML @@ -31,49 +28,11 @@ defmodule Pleroma.Web.OStatus.OStatusController do plug( Pleroma.Plugs.SetFormatPlug - when action in [:feed_redirect, :object, :activity, :notice] + when action in [:object, :activity, :notice] ) action_fallback(:errors) - def feed_redirect(%{assigns: %{format: "html"}} = conn, %{"nickname" => nickname}) do - with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname_or_id(nickname)} do - RedirectController.redirector_with_meta(conn, %{user: user}) - end - end - - def feed_redirect(%{assigns: %{format: format}} = conn, _params) - when format in ["json", "activity+json"] do - ActivityPubController.call(conn, :user) - end - - def feed_redirect(conn, %{"nickname" => nickname}) do - with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do - redirect(conn, external: OStatus.feed_path(user)) - end - end - - def feed(conn, %{"nickname" => nickname} = params) do - with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do - activities = - params - |> Map.take(["max_id"]) - |> Map.merge(%{"whole_db" => true, "actor_id" => user.ap_id}) - |> ActivityPub.fetch_public_activities() - |> Enum.reverse() - - response = - user - |> FeedRepresenter.to_simple_form(activities, [user]) - |> :xmerl.export_simple(:xmerl_xml) - |> to_string - - conn - |> put_resp_content_type("application/atom+xml") - |> send_resp(200, response) - end - end - defp decode_or_retry(body) do with {:ok, magic_key} <- Pleroma.Web.Salmon.fetch_magic_key(body), {:ok, doc} <- Pleroma.Web.Salmon.decode_and_validate(magic_key, body) do diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 675f485b2..ae799b8ac 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -495,8 +495,9 @@ defmodule Pleroma.Web.Router do get("/activities/:uuid", OStatus.OStatusController, :activity) get("/notice/:id", OStatus.OStatusController, :notice) get("/notice/:id/embed_player", OStatus.OStatusController, :notice_player) - get("/users/:nickname/feed", OStatus.OStatusController, :feed) - get("/users/:nickname", OStatus.OStatusController, :feed_redirect) + + get("/users/:nickname/feed", Feed.FeedController, :feed) + get("/users/:nickname", Feed.FeedController, :feed_redirect) post("/users/:nickname/salmon", OStatus.OStatusController, :salmon_incoming) post("/push/hub/:nickname", Websub.WebsubController, :websub_subscription_request) diff --git a/lib/pleroma/web/templates/feed/feed/_activity.xml.eex b/lib/pleroma/web/templates/feed/feed/_activity.xml.eex new file mode 100644 index 000000000..d1f5e903c --- /dev/null +++ b/lib/pleroma/web/templates/feed/feed/_activity.xml.eex @@ -0,0 +1,48 @@ + + http://activitystrea.ms/schema/1.0/note + http://activitystrea.ms/schema/1.0/post + <%= @data["id"] %> + <%= "New note by #{@user.nickname}" %> + <%= activity_content(@activity) %> + <%= @data["published"] %> + <%= @data["published"] %> + <%= activity_context(@activity) %> + + + <%= if @data["summary"] do %> + <%= @data["summary"] %> + <% end %> + + <%= if @activity.local do %> + + + <% else %> + + <% end %> + + <%= for tag <- @data["tag"] || [] do %> + + <% end %> + + <%= for attachment <- @data["attachment"] || [] do %> + + <% end %> + + <%= if @data["inReplyTo"] do %> + + <% end %> + + <%= for id <- @activity.recipients do %> + <%= if id == Pleroma.Constants.as_public() do %> + + <% else %> + <%= unless Regex.match?(~r/^#{Pleroma.Web.base_url()}.+followers$/, id) do %> + + <% end %> + <% end %> + <% end %> + + <%= for {emoji, file} <- @data["emoji"] || %{} do %> + + <% end %> + diff --git a/lib/pleroma/web/templates/feed/feed/_author.xml.eex b/lib/pleroma/web/templates/feed/feed/_author.xml.eex new file mode 100644 index 000000000..25cbffada --- /dev/null +++ b/lib/pleroma/web/templates/feed/feed/_author.xml.eex @@ -0,0 +1,17 @@ + + <%= @user.ap_id %> + http://activitystrea.ms/schema/1.0/person + <%= @user.ap_id %> + <%= @user.nickname %> + <%= @user.name %> + <%= escape(@user.bio) %> + <%= escape(@user.bio) %> + <%= @user.nickname %> + + <%= if User.banner_url(@user) do %> + + <% end %> + <%= if @user.local do %> + true + <% end %> + diff --git a/lib/pleroma/web/templates/feed/feed/feed.xml.eex b/lib/pleroma/web/templates/feed/feed/feed.xml.eex new file mode 100644 index 000000000..fbfdc46b5 --- /dev/null +++ b/lib/pleroma/web/templates/feed/feed/feed.xml.eex @@ -0,0 +1,26 @@ + + + + <%= feed_url(@conn, :feed, @user.nickname) <> ".atom" %> + <%= @user.nickname <> "'s timeline" %> + <%= most_recent_update(@activities, @user) %> + <%= logo(@user) %> + + + + + <%= render @view_module, "_author.xml", assigns %> + + <%= if last_activity(@activities) do %> + + <% end %> + + <%= for activity <- @activities do %> + <%= render @view_module, "_activity.xml", Map.merge(assigns, %{activity: activity, data: activity_object_data(activity)}) %> + <% end %> + -- cgit v1.2.3