Merge branch 'develop' into admin-be

This commit is contained in:
Alexander Strizhakov 2020-01-11 12:15:42 +03:00
commit 1630ecaa20
No known key found for this signature in database
GPG key ID: 022896A53AEF1381
39 changed files with 1263 additions and 1966 deletions

View file

@ -18,16 +18,13 @@ defmodule Pleroma.Plugs.OAuthScopesPlug do
token = assigns[:token]
scopes = transform_scopes(scopes, options)
matched_scopes = token && filter_descendants(scopes, token.scopes)
matched_scopes = (token && filter_descendants(scopes, token.scopes)) || []
cond do
is_nil(token) ->
maybe_perform_instance_privacy_check(conn, options)
op == :| && Enum.any?(matched_scopes) ->
token && op == :| && Enum.any?(matched_scopes) ->
conn
op == :& && matched_scopes == scopes ->
token && op == :& && matched_scopes == scopes ->
conn
options[:fallback] == :proceed_unauthenticated ->

View file

@ -1430,20 +1430,47 @@ defmodule Pleroma.User do
Creates an internal service actor by URI if missing.
Optionally takes nickname for addressing.
"""
def get_or_create_service_actor_by_ap_id(uri, nickname \\ nil) do
with user when is_nil(user) <- get_cached_by_ap_id(uri) do
{:ok, user} =
%User{
invisible: true,
local: true,
ap_id: uri,
nickname: nickname,
follower_address: uri <> "/followers"
}
|> Repo.insert()
@spec get_or_create_service_actor_by_ap_id(String.t(), String.t()) :: User.t() | nil
def get_or_create_service_actor_by_ap_id(uri, nickname) do
{_, user} =
case get_cached_by_ap_id(uri) do
nil ->
with {:error, %{errors: errors}} <- create_service_actor(uri, nickname) do
Logger.error("Cannot create service actor: #{uri}/.\n#{inspect(errors)}")
{:error, nil}
end
user
end
%User{invisible: false} = user ->
set_invisible(user)
user ->
{:ok, user}
end
user
end
@spec set_invisible(User.t()) :: {:ok, User.t()}
defp set_invisible(user) do
user
|> change(%{invisible: true})
|> update_and_set_cache()
end
@spec create_service_actor(String.t(), String.t()) ::
{:ok, User.t()} | {:error, Ecto.Changeset.t()}
defp create_service_actor(uri, nickname) do
%User{
invisible: true,
local: true,
ap_id: uri,
nickname: nickname,
follower_address: uri <> "/followers"
}
|> change
|> unique_constraint(:nickname)
|> Repo.insert()
|> set_cache()
end
# AP style
@ -1855,9 +1882,9 @@ defmodule Pleroma.User do
])
with {:ok, updated_user} <- update_and_set_cache(changeset) do
if user.is_admin && !updated_user.is_admin do
# Tokens & authorizations containing any admin scopes must be revoked (revoking all).
# This is an extra safety measure (tokens' admin scopes won't be accepted for non-admins).
if user.is_admin != updated_user.is_admin do
# Admin status change results in change of accessible OAuth scopes, and instead of changing
# already issued tokens we revoke them, requiring user to sign in again
global_sign_out(user)
end

View file

@ -9,10 +9,12 @@ defmodule Pleroma.Web.ActivityPub.Relay do
alias Pleroma.Web.ActivityPub.ActivityPub
require Logger
@relay_nickname "relay"
def get_actor do
actor =
relay_ap_id()
|> User.get_or_create_service_actor_by_ap_id()
|> User.get_or_create_service_actor_by_ap_id(@relay_nickname)
actor
end

View file

@ -88,7 +88,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
plug(
OAuthScopesPlug,
%{scopes: ["read"], admin: true}
when action in [:config_show, :migrate_to_db, :migrate_from_db, :list_log]
when action in [:config_show, :migrate_from_db, :list_log]
)
plug(

View file

@ -20,18 +20,21 @@ defmodule Pleroma.Web.MastoFEController do
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)
def index(%{assigns: %{user: user, token: token}} = conn, _params)
when not is_nil(user) and not is_nil(token) do
conn
|> put_layout(false)
|> render("index.html",
token: token.token,
user: user,
custom_emojis: Pleroma.Emoji.get_all()
)
end
if user && token do
conn
|> put_layout(false)
|> render("index.html", token: token, user: user, custom_emojis: Pleroma.Emoji.get_all())
else
conn
|> put_session(:return_to, conn.request_path)
|> redirect(to: "/web/login")
end
def index(conn, _params) do
conn
|> put_session(:return_to, conn.request_path)
|> redirect(to: "/web/login")
end
@doc "GET /web/manifest.json"

View file

@ -52,7 +52,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
@doc """
Lists the packs available on the instance as JSON.
The information is public and does not require authentification. The format is
The information is public and does not require authentication. The format is
a map of "pack directory name" to pack.json contents.
"""
def list_packs(conn, _params) do

View file

@ -22,7 +22,14 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
plug(
OAuthScopesPlug,
%{scopes: ["read:statuses"]} when action in [:conversation, :conversation_statuses]
%{scopes: ["read:statuses"]}
when action in [:conversation, :conversation_statuses, :emoji_reactions_by]
)
plug(
OAuthScopesPlug,
%{scopes: ["write:statuses"]}
when action in [:react_with_emoji, :unreact_with_emoji]
)
plug(

View file

@ -22,7 +22,14 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
plug(
OAuthScopesPlug,
%{scopes: ["follow", "write:follows"]}
when action in [:do_remote_follow, :follow_import]
when action == :follow_import
)
# Note: follower can submit the form (with password auth) not being signed in (having no token)
plug(
OAuthScopesPlug,
%{fallback: :proceed_unauthenticated, scopes: ["follow", "write:follows"]}
when action == :do_remote_follow
)
plug(OAuthScopesPlug, %{scopes: ["follow", "write:blocks"]} when action == :blocks_import)
@ -113,6 +120,28 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
end
end
def do_remote_follow(%{assigns: %{user: user}} = conn, %{"user" => %{"id" => id}})
when not is_nil(user) do
with {:fetch_user, %User{} = followee} <- {:fetch_user, User.get_cached_by_id(id)},
{:ok, _follower, _followee, _activity} <- CommonAPI.follow(user, followee) do
conn
|> render("followed.html", %{error: false})
else
# Was already following user
{:error, "Could not follow user:" <> _rest} ->
render(conn, "followed.html", %{error: "Error following account"})
{:fetch_user, error} ->
Logger.debug("Remote follow failed with error #{inspect(error)}")
render(conn, "followed.html", %{error: "Could not find user"})
e ->
Logger.debug("Remote follow failed with error #{inspect(e)}")
render(conn, "followed.html", %{error: "Something went wrong."})
end
end
# Note: "id" is the id of followee user, disregard incorrect placing under "authorization"
def do_remote_follow(conn, %{
"authorization" => %{"name" => username, "password" => password, "id" => id}
}) do
@ -146,24 +175,12 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
end
end
def do_remote_follow(%{assigns: %{user: user}} = conn, %{"user" => %{"id" => id}}) do
with {:fetch_user, %User{} = followee} <- {:fetch_user, User.get_cached_by_id(id)},
{:ok, _follower, _followee, _activity} <- CommonAPI.follow(user, followee) do
conn
|> render("followed.html", %{error: false})
else
# Was already following user
{:error, "Could not follow user:" <> _rest} ->
render(conn, "followed.html", %{error: "Error following account"})
def do_remote_follow(%{assigns: %{user: nil}} = conn, _) do
render(conn, "followed.html", %{error: "Insufficient permissions: follow | write:follows."})
end
{:fetch_user, error} ->
Logger.debug("Remote follow failed with error #{inspect(error)}")
render(conn, "followed.html", %{error: "Could not find user"})
e ->
Logger.debug("Remote follow failed with error #{inspect(e)}")
render(conn, "followed.html", %{error: "Something went wrong."})
end
def do_remote_follow(conn, _) do
render(conn, "followed.html", %{error: "Something went wrong."})
end
def notifications_read(%{assigns: %{user: user}} = conn, %{"id" => notification_id}) do
@ -346,7 +363,9 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
end
def delete_account(%{assigns: %{user: user}} = conn, params) do
case CommonAPI.Utils.confirm_current_password(user, params["password"]) do
password = params["password"] || ""
case CommonAPI.Utils.confirm_current_password(user, password) do
{:ok, user} ->
User.delete(user)
json(conn, %{status: "success"})