diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pleroma/activity.ex | 16 | ||||
-rw-r--r-- | lib/pleroma/config.ex | 8 | ||||
-rw-r--r-- | lib/pleroma/gopher/server.ex | 6 | ||||
-rw-r--r-- | lib/pleroma/notification.ex | 7 | ||||
-rw-r--r-- | lib/pleroma/user.ex | 191 | ||||
-rw-r--r-- | lib/pleroma/user/query.ex | 6 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 5 | ||||
-rw-r--r-- | lib/pleroma/web/oauth/oauth_controller.ex | 77 | ||||
-rw-r--r-- | lib/pleroma/web/oauth/token/response.ex | 32 | ||||
-rw-r--r-- | lib/pleroma/web/oauth/token/utils.ex | 38 | ||||
-rw-r--r-- | lib/pleroma/web/rich_media/helpers.ex | 2 | ||||
-rw-r--r-- | lib/pleroma/web/router.ex | 1 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/controllers/util_controller.ex | 29 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/twitter_api.ex | 9 |
14 files changed, 276 insertions, 151 deletions
diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index c121e800f..4a0919478 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -132,7 +132,10 @@ defmodule Pleroma.Activity do end def get_by_id(id) do - Repo.get(Activity, id) + Activity + |> where([a], a.id == ^id) + |> restrict_deactivated_users() + |> Repo.one() end def get_by_id_with_object(id) do @@ -200,6 +203,7 @@ defmodule Pleroma.Activity do def get_create_by_object_ap_id(ap_id) when is_binary(ap_id) do create_by_object_ap_id(ap_id) + |> restrict_deactivated_users() |> Repo.one() end @@ -314,4 +318,14 @@ defmodule Pleroma.Activity do def query_by_actor(actor) do from(a in Activity, where: a.actor == ^actor) end + + def restrict_deactivated_users(query) do + from(activity in query, + where: + fragment( + "? not in (SELECT ap_id FROM users WHERE info->'deactivated' @> 'true')", + activity.actor + ) + ) + end end diff --git a/lib/pleroma/config.ex b/lib/pleroma/config.ex index 189faa15f..71a47b9fb 100644 --- a/lib/pleroma/config.ex +++ b/lib/pleroma/config.ex @@ -12,8 +12,12 @@ defmodule Pleroma.Config do def get([key], default), do: get(key, default) def get([parent_key | keys], default) do - Application.get_env(:pleroma, parent_key) - |> get_in(keys) || default + case :pleroma + |> Application.get_env(parent_key) + |> get_in(keys) do + nil -> default + any -> any + end end def get(key, default) do diff --git a/lib/pleroma/gopher/server.ex b/lib/pleroma/gopher/server.ex index 1d2e0785c..b3319e137 100644 --- a/lib/pleroma/gopher/server.ex +++ b/lib/pleroma/gopher/server.ex @@ -77,13 +77,13 @@ defmodule Pleroma.Gopher.Server.ProtocolHandler do user = User.get_cached_by_ap_id(activity.data["actor"]) object = Object.normalize(activity) - like_count = object["like_count"] || 0 - announcement_count = object["announcement_count"] || 0 + like_count = object.data["like_count"] || 0 + announcement_count = object.data["announcement_count"] || 0 link("Post ##{activity.id} by #{user.nickname}", "/notices/#{activity.id}") <> info("#{like_count} likes, #{announcement_count} repeats") <> "i\tfake\t(NULL)\t0\r\n" <> - info(HTML.strip_tags(String.replace(object["content"], "<br>", "\r"))) + info(HTML.strip_tags(String.replace(object.data["content"], "<br>", "\r"))) end) |> Enum.join("i\tfake\t(NULL)\t0\r\n") end diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index dd274cf6b..844264307 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -33,6 +33,13 @@ defmodule Pleroma.Notification do def for_user_query(user) do Notification |> where(user_id: ^user.id) + |> where( + [n, a], + fragment( + "? not in (SELECT ap_id FROM users WHERE info->'deactivated' @> 'true')", + a.actor + ) + ) |> join(:inner, [n], activity in assoc(n, :activity)) |> join(:left, [n, a], object in Object, on: diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 474de9ba5..c6a562a61 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -105,10 +105,8 @@ defmodule Pleroma.User do def ap_followers(%User{} = user), do: "#{ap_id(user)}/followers" def user_info(%User{} = user) do - oneself = if user.local, do: 1, else: 0 - %{ - following_count: length(user.following) - oneself, + following_count: following_count(user), note_count: user.info.note_count, follower_count: user.info.follower_count, locked: user.info.locked, @@ -117,6 +115,20 @@ defmodule Pleroma.User do } end + def restrict_deactivated(query) do + from(u in query, + where: not fragment("? \\? 'deactivated' AND ?->'deactivated' @> 'true'", u.info, u.info) + ) + end + + def following_count(%User{following: []}), do: 0 + + def following_count(%User{} = user) do + user + |> get_friends_query() + |> Repo.aggregate(:count, :id) + end + def remote_user_creation(params) do params = params @@ -255,7 +267,7 @@ defmodule Pleroma.User do candidates = Pleroma.Config.get([:instance, :autofollowed_nicknames]) autofollowed_users = - User.Query.build(%{nickname: candidates, local: true}) + User.Query.build(%{nickname: candidates, local: true, deactivated: false}) |> Repo.all() follow_all(user, autofollowed_users) @@ -413,24 +425,6 @@ defmodule Pleroma.User do Enum.member?(follower.following, followed.follower_address) end - def follow_import(%User{} = follower, followed_identifiers) - when is_list(followed_identifiers) do - Enum.map( - followed_identifiers, - fn followed_identifier -> - with {:ok, %User{} = followed} <- get_or_fetch(followed_identifier), - {:ok, follower} <- maybe_direct_follow(follower, followed), - {:ok, _} <- ActivityPub.follow(follower, followed) do - followed - else - err -> - Logger.debug("follow_import failed for #{followed_identifier} with: #{inspect(err)}") - err - end - end - ) - end - def locked?(%User{} = user) do user.info.locked || false end @@ -552,8 +546,7 @@ defmodule Pleroma.User do with [_nick, _domain] <- String.split(nickname, "@"), {:ok, user} <- fetch_by_nickname(nickname) do if Pleroma.Config.get([:fetch_initial_posts, :enabled]) do - # TODO turn into job - {:ok, _} = Task.start(__MODULE__, :fetch_initial_posts, [user]) + fetch_initial_posts(user) end {:ok, user} @@ -564,19 +557,12 @@ defmodule Pleroma.User do end @doc "Fetch some posts when the user has just been federated with" - def fetch_initial_posts(user) do - pages = Pleroma.Config.get!([:fetch_initial_posts, :pages]) - - Enum.each( - # Insert all the posts in reverse order, so they're in the right order on the timeline - Enum.reverse(Utils.fetch_ordered_collection(user.info.source_data["outbox"], pages)), - &Pleroma.Web.Federator.incoming_ap_doc/1 - ) - end + def fetch_initial_posts(user), + do: PleromaJobQueue.enqueue(:background, __MODULE__, [:fetch_initial_posts, user]) @spec get_followers_query(User.t(), pos_integer() | nil) :: Ecto.Query.t() def get_followers_query(%User{} = user, nil) do - User.Query.build(%{followers: user}) + User.Query.build(%{followers: user, deactivated: false}) end def get_followers_query(user, page) do @@ -601,7 +587,7 @@ defmodule Pleroma.User do @spec get_friends_query(User.t(), pos_integer() | nil) :: Ecto.Query.t() def get_friends_query(%User{} = user, nil) do - User.Query.build(%{friends: user}) + User.Query.build(%{friends: user, deactivated: false}) end def get_friends_query(user, page) do @@ -691,16 +677,16 @@ defmodule Pleroma.User do info_cng = User.Info.set_note_count(user.info, note_count) - cng = - change(user) - |> put_embed(:info, info_cng) - - update_and_set_cache(cng) + user + |> change() + |> put_embed(:info, info_cng) + |> update_and_set_cache() end def update_follower_count(%User{} = user) do follower_count_query = - User.Query.build(%{followers: user}) |> select([u], %{count: count(u.id)}) + User.Query.build(%{followers: user, deactivated: false}) + |> select([u], %{count: count(u.id)}) User |> where(id: ^user.id) @@ -725,7 +711,7 @@ defmodule Pleroma.User do @spec get_users_from_set([String.t()], boolean()) :: [User.t()] def get_users_from_set(ap_ids, local_only \\ true) do - criteria = %{ap_id: ap_ids} + criteria = %{ap_id: ap_ids, deactivated: false} criteria = if local_only, do: Map.put(criteria, :local, true), else: criteria User.Query.build(criteria) @@ -734,7 +720,7 @@ defmodule Pleroma.User do @spec get_recipients_from_activity(Activity.t()) :: [User.t()] def get_recipients_from_activity(%Activity{recipients: to}) do - User.Query.build(%{recipients_from_activity: to, local: true}) + User.Query.build(%{recipients_from_activity: to, local: true, deactivated: false}) |> Repo.all() end @@ -832,6 +818,7 @@ defmodule Pleroma.User do ^processed_query ) ) + |> restrict_deactivated() end defp trigram_search_subquery(term) do @@ -850,23 +837,7 @@ defmodule Pleroma.User do }, where: fragment("trim(? || ' ' || coalesce(?, '')) % ?", u.nickname, u.name, ^term) ) - end - - def blocks_import(%User{} = blocker, blocked_identifiers) when is_list(blocked_identifiers) do - Enum.map( - blocked_identifiers, - fn blocked_identifier -> - with {:ok, %User{} = blocked} <- get_or_fetch(blocked_identifier), - {:ok, blocker} <- block(blocker, blocked), - {:ok, _} <- ActivityPub.block(blocker, blocked) do - blocked - else - err -> - Logger.debug("blocks_import failed for #{blocked_identifier} with: #{inspect(err)}") - err - end - end - ) + |> restrict_deactivated() end def mute(muter, %User{ap_id: ap_id}) do @@ -999,19 +970,19 @@ defmodule Pleroma.User do @spec muted_users(User.t()) :: [User.t()] def muted_users(user) do - User.Query.build(%{ap_id: user.info.mutes}) + User.Query.build(%{ap_id: user.info.mutes, deactivated: false}) |> Repo.all() end @spec blocked_users(User.t()) :: [User.t()] def blocked_users(user) do - User.Query.build(%{ap_id: user.info.blocks}) + User.Query.build(%{ap_id: user.info.blocks, deactivated: false}) |> Repo.all() end @spec subscribers(User.t()) :: [User.t()] def subscribers(user) do - User.Query.build(%{ap_id: user.info.subscribers}) + User.Query.build(%{ap_id: user.info.subscribers, deactivated: false}) |> Repo.all() end @@ -1039,14 +1010,25 @@ defmodule Pleroma.User do update_and_set_cache(cng) end + def deactivate_async(user, status \\ true) do + PleromaJobQueue.enqueue(:background, __MODULE__, [:deactivate_async, user, status]) + end + def deactivate(%User{} = user, status \\ true) do info_cng = User.Info.set_activation_status(user.info, status) - cng = - change(user) - |> put_embed(:info, info_cng) + with {:ok, friends} <- User.get_friends(user), + {:ok, followers} <- User.get_followers(user), + {:ok, user} <- + user + |> change() + |> put_embed(:info, info_cng) + |> update_and_set_cache() do + Enum.each(followers, &invalidate_cache(&1)) + Enum.each(friends, &update_follower_count(&1)) - update_and_set_cache(cng) + {:ok, user} + end end def update_notification_settings(%User{} = user, settings \\ %{}) do @@ -1077,6 +1059,75 @@ defmodule Pleroma.User do delete_user_activities(user) end + @spec perform(atom(), User.t()) :: {:ok, User.t()} + def perform(:fetch_initial_posts, %User{} = user) do + pages = Pleroma.Config.get!([:fetch_initial_posts, :pages]) + + Enum.each( + # Insert all the posts in reverse order, so they're in the right order on the timeline + Enum.reverse(Utils.fetch_ordered_collection(user.info.source_data["outbox"], pages)), + &Pleroma.Web.Federator.incoming_ap_doc/1 + ) + + {:ok, user} + end + + def perform(:deactivate_async, user, status), do: deactivate(user, status) + + @spec perform(atom(), User.t(), list()) :: list() | {:error, any()} + def perform(:blocks_import, %User{} = blocker, blocked_identifiers) + when is_list(blocked_identifiers) do + Enum.map( + blocked_identifiers, + fn blocked_identifier -> + with {:ok, %User{} = blocked} <- get_or_fetch(blocked_identifier), + {:ok, blocker} <- block(blocker, blocked), + {:ok, _} <- ActivityPub.block(blocker, blocked) do + blocked + else + err -> + Logger.debug("blocks_import failed for #{blocked_identifier} with: #{inspect(err)}") + err + end + end + ) + end + + @spec perform(atom(), User.t(), list()) :: list() | {:error, any()} + def perform(:follow_import, %User{} = follower, followed_identifiers) + when is_list(followed_identifiers) do + Enum.map( + followed_identifiers, + fn followed_identifier -> + with {:ok, %User{} = followed} <- get_or_fetch(followed_identifier), + {:ok, follower} <- maybe_direct_follow(follower, followed), + {:ok, _} <- ActivityPub.follow(follower, followed) do + followed + else + err -> + Logger.debug("follow_import failed for #{followed_identifier} with: #{inspect(err)}") + err + end + end + ) + end + + def blocks_import(%User{} = blocker, blocked_identifiers) when is_list(blocked_identifiers), + do: + PleromaJobQueue.enqueue(:background, __MODULE__, [ + :blocks_import, + blocker, + blocked_identifiers + ]) + + def follow_import(%User{} = follower, followed_identifiers) when is_list(followed_identifiers), + do: + PleromaJobQueue.enqueue(:background, __MODULE__, [ + :follow_import, + follower, + followed_identifiers + ]) + def delete_user_activities(%User{ap_id: ap_id} = user) do stream = ap_id @@ -1130,8 +1181,8 @@ defmodule Pleroma.User do resp = fetch_by_ap_id(ap_id) if should_fetch_initial do - with {:ok, %User{} = user} = resp do - {:ok, _} = Task.start(__MODULE__, :fetch_initial_posts, [user]) + with {:ok, %User{} = user} <- resp do + fetch_initial_posts(user) end end @@ -1320,7 +1371,7 @@ defmodule Pleroma.User do @spec all_superusers() :: [User.t()] def all_superusers do - User.Query.build(%{super_users: true, local: true}) + User.Query.build(%{super_users: true, local: true, deactivated: false}) |> Repo.all() end diff --git a/lib/pleroma/user/query.ex b/lib/pleroma/user/query.ex index 2dfe5ce92..ace9c05f2 100644 --- a/lib/pleroma/user/query.ex +++ b/lib/pleroma/user/query.ex @@ -118,7 +118,11 @@ defmodule Pleroma.User.Query do |> where([u], not is_nil(u.nickname)) end - defp compose_query({:deactivated, _}, query) do + defp compose_query({:deactivated, false}, query) do + User.restrict_deactivated(query) + end + + defp compose_query({:deactivated, true}, query) do where(query, [u], fragment("?->'deactivated' @> 'true'", u.info)) |> where([u], not is_nil(u.nickname)) end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index eba8f8018..b1ce5ae52 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -132,9 +132,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do activity end - Task.start(fn -> - Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity) - end) + PleromaJobQueue.enqueue(:background, Pleroma.Web.RichMedia.Helpers, [:fetch, activity]) Notification.create_notifications(activity) @@ -851,6 +849,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do |> restrict_reblogs(opts) |> restrict_pinned(opts) |> restrict_muted_reblogs(opts) + |> Activity.restrict_deactivated_users() end def fetch_activities(recipients, opts \\ %{}) do diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index 4ee8339e2..ae2b80d95 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -19,8 +19,6 @@ defmodule Pleroma.Web.OAuth.OAuthController do if Pleroma.Config.oauth_consumer_enabled?(), do: plug(Ueberauth) - @expires_in Pleroma.Config.get([:oauth2, :token_expires_in], 600) - plug(:fetch_session) plug(:fetch_flash) @@ -144,14 +142,14 @@ defmodule Pleroma.Web.OAuth.OAuthController do @doc "Renew access_token with refresh_token" def token_exchange( conn, - %{"grant_type" => "refresh_token", "refresh_token" => token} = params + %{"grant_type" => "refresh_token", "refresh_token" => token} = _params ) do - with %App{} = app <- get_app_from_request(conn, params), + with {:ok, app} <- Token.Utils.fetch_app(conn), {:ok, %{user: user} = token} <- Token.get_by_refresh_token(app, token), {:ok, token} <- RefreshToken.grant(token) do response_attrs = %{created_at: Token.Utils.format_created_at(token)} - json(conn, response_token(user, token, response_attrs)) + json(conn, Token.Response.build(user, token, response_attrs)) else _error -> put_status(conn, 400) @@ -160,14 +158,14 @@ defmodule Pleroma.Web.OAuth.OAuthController do end def token_exchange(conn, %{"grant_type" => "authorization_code"} = params) do - with %App{} = app <- get_app_from_request(conn, params), + with {:ok, app} <- Token.Utils.fetch_app(conn), fixed_token = Token.Utils.fix_padding(params["code"]), {:ok, auth} <- Authorization.get_by_token(app, fixed_token), %User{} = user <- User.get_cached_by_id(auth.user_id), {:ok, token} <- Token.exchange_token(app, auth) do response_attrs = %{created_at: Token.Utils.format_created_at(token)} - json(conn, response_token(user, token, response_attrs)) + json(conn, Token.Response.build(user, token, response_attrs)) else _error -> put_status(conn, 400) @@ -179,14 +177,14 @@ defmodule Pleroma.Web.OAuth.OAuthController do conn, %{"grant_type" => "password"} = params ) do - with {_, {:ok, %User{} = user}} <- {:get_user, Authenticator.get_user(conn)}, - %App{} = app <- get_app_from_request(conn, params), + with {:ok, %User{} = user} <- Authenticator.get_user(conn), + {:ok, app} <- Token.Utils.fetch_app(conn), {:auth_active, true} <- {:auth_active, User.auth_active?(user)}, {:user_active, true} <- {:user_active, !user.info.deactivated}, {:ok, scopes} <- validate_scopes(app, params), {:ok, auth} <- Authorization.create_authorization(app, user, scopes), {:ok, token} <- Token.exchange_token(app, auth) do - json(conn, response_token(user, token)) + json(conn, Token.Response.build(user, token)) else {:auth_active, false} -> # Per https://github.com/tootsuite/mastodon/blob/ @@ -218,21 +216,11 @@ defmodule Pleroma.Web.OAuth.OAuthController do token_exchange(conn, params) end - def token_exchange(conn, %{"grant_type" => "client_credentials"} = params) do - with %App{} = app <- get_app_from_request(conn, params), + def token_exchange(conn, %{"grant_type" => "client_credentials"} = _params) do + with {:ok, app} <- Token.Utils.fetch_app(conn), {:ok, auth} <- Authorization.create_authorization(app, %User{}), - {:ok, token} <- Token.exchange_token(app, auth), - {:ok, inserted_at} <- DateTime.from_naive(token.inserted_at, "Etc/UTC") do - response = %{ - token_type: "Bearer", - access_token: token.token, - refresh_token: token.refresh_token, - created_at: DateTime.to_unix(inserted_at), - expires_in: 60 * 10, - scope: Enum.join(token.scopes, " ") - } - - json(conn, response) + {:ok, token} <- Token.exchange_token(app, auth) do + json(conn, Token.Response.build_for_client_credentials(token)) else _error -> put_status(conn, 400) @@ -244,7 +232,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do def token_exchange(conn, params), do: bad_request(conn, params) def token_revoke(conn, %{"token" => _token} = params) do - with %App{} = app <- get_app_from_request(conn, params), + with {:ok, app} <- Token.Utils.fetch_app(conn), {:ok, _token} <- RevokeToken.revoke(app, params) do json(conn, %{}) else @@ -427,33 +415,6 @@ defmodule Pleroma.Web.OAuth.OAuthController do end end - defp get_app_from_request(conn, params) do - conn - |> fetch_client_credentials(params) - |> fetch_client - end - - defp fetch_client({id, secret}) when is_binary(id) and is_binary(secret) do - Repo.get_by(App, client_id: id, client_secret: secret) - end - - defp fetch_client({_id, _secret}), do: nil - - defp fetch_client_credentials(conn, params) do - # Per RFC 6749, HTTP Basic is preferred to body params - with ["Basic " <> encoded] <- get_req_header(conn, "authorization"), - {:ok, decoded} <- Base.decode64(encoded), - [id, secret] <- - Enum.map( - String.split(decoded, ":"), - fn s -> URI.decode_www_form(s) end - ) do - {id, secret} - else - _ -> {params["client_id"], params["client_secret"]} - end - end - # Special case: Local MastodonFE defp redirect_uri(conn, "."), do: mastodon_api_url(conn, :login) @@ -464,18 +425,6 @@ defmodule Pleroma.Web.OAuth.OAuthController do defp put_session_registration_id(conn, registration_id), do: put_session(conn, :registration_id, registration_id) - defp response_token(%User{} = user, token, opts \\ %{}) do - %{ - token_type: "Bearer", - access_token: token.token, - refresh_token: token.refresh_token, - expires_in: @expires_in, - scope: Enum.join(token.scopes, " "), - me: user.ap_id - } - |> Map.merge(opts) - end - @spec validate_scopes(App.t(), map()) :: {:ok, list()} | {:error, :missing_scopes | :unsupported_scopes} defp validate_scopes(app, params) do diff --git a/lib/pleroma/web/oauth/token/response.ex b/lib/pleroma/web/oauth/token/response.ex new file mode 100644 index 000000000..64e78b183 --- /dev/null +++ b/lib/pleroma/web/oauth/token/response.ex @@ -0,0 +1,32 @@ +defmodule Pleroma.Web.OAuth.Token.Response do + @moduledoc false + + alias Pleroma.User + alias Pleroma.Web.OAuth.Token.Utils + + @expires_in Pleroma.Config.get([:oauth2, :token_expires_in], 600) + + @doc false + def build(%User{} = user, token, opts \\ %{}) do + %{ + token_type: "Bearer", + access_token: token.token, + refresh_token: token.refresh_token, + expires_in: @expires_in, + scope: Enum.join(token.scopes, " "), + me: user.ap_id + } + |> Map.merge(opts) + end + + def build_for_client_credentials(token) do + %{ + token_type: "Bearer", + access_token: token.token, + refresh_token: token.refresh_token, + created_at: Utils.format_created_at(token), + expires_in: @expires_in, + scope: Enum.join(token.scopes, " ") + } + end +end diff --git a/lib/pleroma/web/oauth/token/utils.ex b/lib/pleroma/web/oauth/token/utils.ex index a81560a1c..7a4fddafd 100644 --- a/lib/pleroma/web/oauth/token/utils.ex +++ b/lib/pleroma/web/oauth/token/utils.ex @@ -3,6 +3,44 @@ defmodule Pleroma.Web.OAuth.Token.Utils do Auxiliary functions for dealing with tokens. """ + alias Pleroma.Repo + alias Pleroma.Web.OAuth.App + + @doc "Fetch app by client credentials from request" + @spec fetch_app(Plug.Conn.t()) :: {:ok, App.t()} | {:error, :not_found} + def fetch_app(conn) do + res = + conn + |> fetch_client_credentials() + |> fetch_client + + case res do + %App{} = app -> {:ok, app} + _ -> {:error, :not_found} + end + end + + defp fetch_client({id, secret}) when is_binary(id) and is_binary(secret) do + Repo.get_by(App, client_id: id, client_secret: secret) + end + + defp fetch_client({_id, _secret}), do: nil + + defp fetch_client_credentials(conn) do + # Per RFC 6749, HTTP Basic is preferred to body params + with ["Basic " <> encoded] <- Plug.Conn.get_req_header(conn, "authorization"), + {:ok, decoded} <- Base.decode64(encoded), + [id, secret] <- + Enum.map( + String.split(decoded, ":"), + fn s -> URI.decode_www_form(s) end + ) do + {id, secret} + else + _ -> {conn.params["client_id"], conn.params["client_secret"]} + end + end + @doc "convert token inserted_at to unix timestamp" def format_created_at(%{inserted_at: inserted_at} = _token) do inserted_at diff --git a/lib/pleroma/web/rich_media/helpers.ex b/lib/pleroma/web/rich_media/helpers.ex index f67aaf58b..0162a5be9 100644 --- a/lib/pleroma/web/rich_media/helpers.ex +++ b/lib/pleroma/web/rich_media/helpers.ex @@ -34,4 +34,6 @@ defmodule Pleroma.Web.RichMedia.Helpers do end def fetch_data_for_activity(_), do: %{} + + def perform(:fetch, %Activity{} = activity), do: fetch_data_for_activity(activity) end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 51146d010..80af0afe1 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -215,6 +215,7 @@ defmodule Pleroma.Web.Router do 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 diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex index c03f8ab3a..89c55ef0e 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -309,8 +309,13 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do Enum.map(lines, fn line -> String.split(line, ",") |> List.first() end) - |> List.delete("Account address"), - {:ok, _} = Task.start(fn -> User.follow_import(follower, followed_identifiers) end) do + |> List.delete("Account address") do + PleromaJobQueue.enqueue(:background, User, [ + :follow_import, + follower, + followed_identifiers + ]) + json(conn, "job started") end end @@ -320,8 +325,13 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do end def blocks_import(%{assigns: %{user: blocker}} = conn, %{"list" => list}) do - with blocked_identifiers <- String.split(list), - {:ok, _} = Task.start(fn -> User.blocks_import(blocker, blocked_identifiers) end) do + with blocked_identifiers <- String.split(list) do + PleromaJobQueue.enqueue(:background, User, [ + :blocks_import, + blocker, + blocked_identifiers + ]) + json(conn, "job started") end end @@ -360,6 +370,17 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do end end + def disable_account(%{assigns: %{user: user}} = conn, params) do + case CommonAPI.Utils.confirm_current_password(user, params["password"]) do + {:ok, user} -> + User.deactivate_async(user) + json(conn, %{status: "success"}) + + {:error, msg} -> + json(conn, %{error: msg}) + end + end + def captcha(conn, _params) do json(conn, Pleroma.Captcha.new()) end diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex index 1362ef57c..41e1c2877 100644 --- a/lib/pleroma/web/twitter_api/twitter_api.ex +++ b/lib/pleroma/web/twitter_api/twitter_api.ex @@ -236,12 +236,15 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do def get_user(user \\ nil, params) do case params do %{"user_id" => user_id} -> - case target = User.get_cached_by_nickname_or_id(user_id) do + case User.get_cached_by_nickname_or_id(user_id) do nil -> {:error, "No user with such user_id"} - _ -> - {:ok, target} + %User{info: %{deactivated: true}} -> + {:error, "User has been disabled"} + + user -> + {:ok, user} end %{"screen_name" => nickname} -> |