aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorEgor Kislitsyn <egor@kislitsyn.com>2019-05-15 14:31:24 +0700
committerEgor Kislitsyn <egor@kislitsyn.com>2019-05-15 14:31:24 +0700
commita7a8f3bc2c3bb748f060812751a88873401354dd (patch)
tree44ec21d281a4dcbf2edfd716dcc4a5d0d9871beb /lib
parentfc9b4410c4182747fbcbc2cbe2b94090c887b96f (diff)
parentc133c32ef07077daaf581a4f890939b38c1d7feb (diff)
downloadpleroma-a7a8f3bc2c3bb748f060812751a88873401354dd.tar.gz
Merge remote-tracking branch 'pleroma/develop' into feature/addressable-lists
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/activity.ex16
-rw-r--r--lib/pleroma/config.ex8
-rw-r--r--lib/pleroma/gopher/server.ex6
-rw-r--r--lib/pleroma/notification.ex7
-rw-r--r--lib/pleroma/user.ex191
-rw-r--r--lib/pleroma/user/query.ex6
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex5
-rw-r--r--lib/pleroma/web/oauth/oauth_controller.ex77
-rw-r--r--lib/pleroma/web/oauth/token/response.ex32
-rw-r--r--lib/pleroma/web/oauth/token/utils.ex38
-rw-r--r--lib/pleroma/web/rich_media/helpers.ex2
-rw-r--r--lib/pleroma/web/router.ex1
-rw-r--r--lib/pleroma/web/twitter_api/controllers/util_controller.ex29
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api.ex9
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} ->