Merge remote-tracking branch 'remotes/origin/develop' into feature/object-hashtags-rework

# Conflicts:
#	CHANGELOG.md
This commit is contained in:
Ivan Tashkinov 2021-01-21 20:20:35 +03:00
commit 2634a16b4c
161 changed files with 1462 additions and 473 deletions

View file

@ -13,7 +13,8 @@ defmodule Mix.Pleroma do
:flake_id,
:swoosh,
:timex,
:fast_html
:fast_html,
:oban
]
@cachex_children ["object", "user", "scrubber", "web_resp"]
@doc "Common functions to be reused in mix tasks"

View file

@ -34,7 +34,7 @@ defmodule Mix.Tasks.Pleroma.Email do
Pleroma.User.Query.build(%{
local: true,
deactivated: false,
confirmation_pending: true,
is_confirmed: false,
invisible: false
})
|> Pleroma.Repo.chunk_stream(500)

View file

@ -74,7 +74,7 @@ defmodule Mix.Tasks.Pleroma.User do
bio: bio
}
changeset = User.register_changeset(%User{}, params, need_confirmation: false)
changeset = User.register_changeset(%User{}, params, is_confirmed: true)
{:ok, _user} = User.register(changeset)
shell_info("User #{nickname} created")
@ -213,7 +213,7 @@ defmodule Mix.Tasks.Pleroma.User do
user =
case Keyword.get(options, :confirmed) do
nil -> user
value -> set_confirmed(user, value)
value -> set_confirmation(user, value)
end
user =
@ -351,7 +351,7 @@ defmodule Mix.Tasks.Pleroma.User do
with %User{} = user <- User.get_cached_by_nickname(nickname) do
{:ok, user} = User.confirm(user)
message = if user.confirmation_pending, do: "needs", else: "doesn't need"
message = if !user.is_confirmed, do: "needs", else: "doesn't need"
shell_info("#{nickname} #{message} confirmation.")
else
@ -373,7 +373,7 @@ defmodule Mix.Tasks.Pleroma.User do
|> Pleroma.Repo.chunk_stream(500, :batches)
|> Stream.each(fn users ->
users
|> Enum.each(fn user -> User.need_confirmation(user, false) end)
|> Enum.each(fn user -> User.set_confirmation(user, true) end)
end)
|> Stream.run()
end
@ -391,7 +391,7 @@ defmodule Mix.Tasks.Pleroma.User do
|> Pleroma.Repo.chunk_stream(500, :batches)
|> Stream.each(fn users ->
users
|> Enum.each(fn user -> User.need_confirmation(user, true) end)
|> Enum.each(fn user -> User.set_confirmation(user, false) end)
end)
|> Stream.run()
end
@ -454,10 +454,10 @@ defmodule Mix.Tasks.Pleroma.User do
user
end
defp set_confirmed(user, value) do
{:ok, user} = User.need_confirmation(user, !value)
defp set_confirmation(user, value) do
{:ok, user} = User.set_confirmation(user, value)
shell_info("Confirmation pending status of #{user.nickname}: #{user.confirmation_pending}")
shell_info("Confirmation status of #{user.nickname}: #{user.is_confirmed}")
user
end
end

View file

@ -298,7 +298,16 @@ defmodule Pleroma.Application do
@spec limiters_setup() :: :ok
def limiters_setup do
[Pleroma.Web.RichMedia.Helpers, Pleroma.Web.MediaProxy]
|> Enum.each(&ConcurrentLimiter.new(&1, 1, 0))
config = Config.get(ConcurrentLimiter, [])
[Pleroma.Web.RichMedia.Helpers, Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy]
|> Enum.each(fn module ->
mod_config = Keyword.get(config, module, [])
max_running = Keyword.get(mod_config, :max_running, 5)
max_waiting = Keyword.get(mod_config, :max_waiting, 5)
ConcurrentLimiter.new(module, max_running, max_waiting)
end)
end
end

View file

@ -40,7 +40,8 @@ defmodule Pleroma.Config.DeprecationWarnings do
:ok <- check_welcome_message_config(),
:ok <- check_gun_pool_options(),
:ok <- check_activity_expiration_config(),
:ok <- check_remote_ip_plug_name() do
:ok <- check_remote_ip_plug_name(),
:ok <- check_uploders_s3_public_endpoint() do
:ok
else
_ ->
@ -193,4 +194,25 @@ defmodule Pleroma.Config.DeprecationWarnings do
warning_preface
)
end
@spec check_uploders_s3_public_endpoint() :: :ok | nil
def check_uploders_s3_public_endpoint do
s3_config = Pleroma.Config.get([Pleroma.Uploaders.S3])
use_old_config = Keyword.has_key?(s3_config, :public_endpoint)
if use_old_config do
Logger.error("""
!!!DEPRECATION WARNING!!!
Your config is using the old setting for controlling the URL of media uploaded to your S3 bucket.\n
Please make the following change at your earliest convenience.\n
\n* `config :pleroma, Pleroma.Uploaders.S3, public_endpoint` is now equal to:
\n* `config :pleroma, Pleroma.Upload, base_url`
""")
:error
else
:ok
end
end
end

View file

@ -71,7 +71,7 @@ defmodule Pleroma.MFA do
@spec generate_backup_codes(User.t()) :: {:ok, list(binary)} | {:error, String.t()}
def generate_backup_codes(%User{} = user) do
with codes <- BackupCodes.generate(),
hashed_codes <- Enum.map(codes, &Pbkdf2.hash_pwd_salt/1),
hashed_codes <- Enum.map(codes, &Pleroma.Password.Pbkdf2.hash_pwd_salt/1),
changeset <- Changeset.cast_backup_codes(user, hashed_codes),
{:ok, _} <- User.update_and_set_cache(changeset) do
{:ok, codes}

View file

@ -0,0 +1,55 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Password.Pbkdf2 do
@moduledoc """
This module implements Pbkdf2 passwords in terms of Plug.Crypto.
"""
alias Plug.Crypto.KeyGenerator
def decode64(str) do
str
|> String.replace(".", "+")
|> Base.decode64!(padding: false)
end
def encode64(bin) do
bin
|> Base.encode64(padding: false)
|> String.replace("+", ".")
end
def verify_pass(password, hash) do
["pbkdf2-" <> digest, iterations, salt, hash] = String.split(hash, "$", trim: true)
salt = decode64(salt)
iterations = String.to_integer(iterations)
digest = String.to_atom(digest)
binary_hash =
KeyGenerator.generate(password, salt, digest: digest, iterations: iterations, length: 64)
encode64(binary_hash) == hash
end
def hash_pwd_salt(password, opts \\ []) do
salt =
Keyword.get_lazy(opts, :salt, fn ->
:crypto.strong_rand_bytes(16)
end)
digest = Keyword.get(opts, :digest, :sha512)
iterations =
Keyword.get(opts, :iterations, Pleroma.Config.get([:password, :iterations], 160_000))
binary_hash =
KeyGenerator.generate(password, salt, digest: digest, iterations: iterations, length: 64)
"$pbkdf2-#{digest}$#{iterations}$#{encode64(salt)}$#{encode64(binary_hash)}"
end
end

View file

@ -131,12 +131,7 @@ defmodule Pleroma.Upload do
uploader: Keyword.get(opts, :uploader, Pleroma.Config.get([__MODULE__, :uploader])),
filters: Keyword.get(opts, :filters, Pleroma.Config.get([__MODULE__, :filters])),
description: Keyword.get(opts, :description),
base_url:
Keyword.get(
opts,
:base_url,
Pleroma.Config.get([__MODULE__, :base_url], Pleroma.Web.base_url())
)
base_url: base_url()
}
end
@ -217,14 +212,7 @@ defmodule Pleroma.Upload do
""
end
prefix =
if is_nil(Pleroma.Config.get([__MODULE__, :base_url])) do
"media"
else
""
end
[base_url, prefix, path]
[base_url, path]
|> Path.join()
end
@ -241,13 +229,15 @@ defmodule Pleroma.Upload do
Pleroma.Uploaders.S3 ->
bucket = Config.get([Pleroma.Uploaders.S3, :bucket])
truncated_namespace = Config.get([Pleroma.Uploaders.S3, :truncated_namespace])
namespace = Config.get([Pleroma.Uploaders.S3, :bucket_namespace])
bucket_with_namespace =
cond do
truncated_namespace = Config.get([Pleroma.Uploaders.S3, :truncated_namespace]) ->
!is_nil(truncated_namespace) ->
truncated_namespace
namespace = Config.get([Pleroma.Uploaders.S3, :bucket_namespace]) ->
!is_nil(namespace) ->
namespace <> ":" <> bucket
true ->
@ -261,7 +251,7 @@ defmodule Pleroma.Upload do
end
_ ->
public_endpoint || upload_base_url
public_endpoint || upload_base_url || Pleroma.Web.base_url() <> "/media/"
end
end
end

View file

@ -110,9 +110,9 @@ defmodule Pleroma.User do
field(:follower_count, :integer, default: 0)
field(:following_count, :integer, default: 0)
field(:is_locked, :boolean, default: false)
field(:confirmation_pending, :boolean, default: false)
field(:is_confirmed, :boolean, default: true)
field(:password_reset_pending, :boolean, default: false)
field(:approval_pending, :boolean, default: false)
field(:is_approved, :boolean, default: true)
field(:registration_reason, :string, default: nil)
field(:confirmation_token, :string, default: nil)
field(:default_scope, :string, default: "public")
@ -288,16 +288,8 @@ defmodule Pleroma.User do
@spec account_status(User.t()) :: account_status()
def account_status(%User{deactivated: true}), do: :deactivated
def account_status(%User{password_reset_pending: true}), do: :password_reset_pending
def account_status(%User{local: true, approval_pending: true}), do: :approval_pending
def account_status(%User{local: true, confirmation_pending: true}) do
if Config.get([:instance, :account_activation_required]) do
:confirmation_pending
else
:active
end
end
def account_status(%User{local: true, is_approved: false}), do: :approval_pending
def account_status(%User{local: true, is_confirmed: false}), do: :confirmation_pending
def account_status(%User{}), do: :active
@spec visible_for(User.t(), User.t() | nil) ::
@ -704,23 +696,23 @@ defmodule Pleroma.User do
reason_limit = Config.get([:instance, :registration_reason_length], 500)
params = Map.put_new(params, :accepts_chat_messages, true)
need_confirmation? =
if is_nil(opts[:need_confirmation]) do
Config.get([:instance, :account_activation_required])
confirmed? =
if is_nil(opts[:confirmed]) do
!Config.get([:instance, :account_activation_required])
else
opts[:need_confirmation]
opts[:confirmed]
end
need_approval? =
if is_nil(opts[:need_approval]) do
Config.get([:instance, :account_approval_required])
approved? =
if is_nil(opts[:approved]) do
!Config.get([:instance, :account_approval_required])
else
opts[:need_approval]
opts[:approved]
end
struct
|> confirmation_changeset(need_confirmation: need_confirmation?)
|> approval_changeset(need_approval: need_approval?)
|> confirmation_changeset(set_confirmation: confirmed?)
|> approval_changeset(set_approval: approved?)
|> cast(params, [
:bio,
:raw_bio,
@ -808,20 +800,20 @@ defmodule Pleroma.User do
end
end
def post_register_action(%User{confirmation_pending: true} = user) do
def post_register_action(%User{is_confirmed: false} = user) do
with {:ok, _} <- try_send_confirmation_email(user) do
{:ok, user}
end
end
def post_register_action(%User{approval_pending: true} = user) do
def post_register_action(%User{is_approved: false} = user) do
with {:ok, _} <- send_user_approval_email(user),
{:ok, _} <- send_admin_approval_emails(user) do
{:ok, user}
end
end
def post_register_action(%User{approval_pending: false, confirmation_pending: false} = user) do
def post_register_action(%User{is_approved: true, is_confirmed: true} = user) do
with {:ok, user} <- autofollow_users(user),
{:ok, _} <- autofollowing_users(user),
{:ok, user} <- set_cache(user),
@ -882,7 +874,7 @@ defmodule Pleroma.User do
def send_welcome_email(_), do: {:ok, :noop}
@spec try_send_confirmation_email(User.t()) :: {:ok, :enqueued | :noop}
def try_send_confirmation_email(%User{confirmation_pending: true, email: email} = user)
def try_send_confirmation_email(%User{is_confirmed: false, email: email} = user)
when is_binary(email) do
if Config.get([:instance, :account_activation_required]) do
send_confirmation_email(user)
@ -1624,8 +1616,8 @@ defmodule Pleroma.User do
end)
end
def approve(%User{approval_pending: true} = user) do
with chg <- change(user, approval_pending: false),
def approve(%User{is_approved: false} = user) do
with chg <- change(user, is_approved: true),
{:ok, user} <- update_and_set_cache(chg) do
post_register_action(user)
{:ok, user}
@ -1642,8 +1634,8 @@ defmodule Pleroma.User do
end)
end
def confirm(%User{confirmation_pending: true} = user) do
with chg <- confirmation_changeset(user, need_confirmation: false),
def confirm(%User{is_confirmed: false} = user) do
with chg <- confirmation_changeset(user, set_confirmation: true),
{:ok, user} <- update_and_set_cache(chg) do
post_register_action(user)
{:ok, user}
@ -1682,9 +1674,9 @@ defmodule Pleroma.User do
follower_count: 0,
following_count: 0,
is_locked: false,
confirmation_pending: false,
is_confirmed: true,
password_reset_pending: false,
approval_pending: false,
is_approved: true,
registration_reason: nil,
confirmation_token: nil,
domain_blocks: [],
@ -2138,10 +2130,10 @@ defmodule Pleroma.User do
updated_user
end
@spec need_confirmation(User.t(), boolean()) :: {:ok, User.t()} | {:error, Changeset.t()}
def need_confirmation(%User{} = user, bool) do
@spec set_confirmation(User.t(), boolean()) :: {:ok, User.t()} | {:error, Changeset.t()}
def set_confirmation(%User{} = user, bool) do
user
|> confirmation_changeset(need_confirmation: bool)
|> confirmation_changeset(set_confirmation: bool)
|> update_and_set_cache()
end
@ -2187,7 +2179,7 @@ defmodule Pleroma.User do
defp put_password_hash(
%Ecto.Changeset{valid?: true, changes: %{password: password}} = changeset
) do
change(changeset, password_hash: Pbkdf2.hash_pwd_salt(password))
change(changeset, password_hash: Pleroma.Password.Pbkdf2.hash_pwd_salt(password))
end
defp put_password_hash(changeset), do: changeset
@ -2309,27 +2301,26 @@ defmodule Pleroma.User do
end
@spec confirmation_changeset(User.t(), keyword()) :: Changeset.t()
def confirmation_changeset(user, need_confirmation: need_confirmation?) do
def confirmation_changeset(user, set_confirmation: confirmed?) do
params =
if need_confirmation? do
if confirmed? do
%{
confirmation_pending: true,
confirmation_token: :crypto.strong_rand_bytes(32) |> Base.url_encode64()
is_confirmed: true,
confirmation_token: nil
}
else
%{
confirmation_pending: false,
confirmation_token: nil
is_confirmed: false,
confirmation_token: :crypto.strong_rand_bytes(32) |> Base.url_encode64()
}
end
cast(user, params, [:confirmation_pending, :confirmation_token])
cast(user, params, [:is_confirmed, :confirmation_token])
end
@spec approval_changeset(User.t(), keyword()) :: Changeset.t()
def approval_changeset(user, need_approval: need_approval?) do
params = if need_approval?, do: %{approval_pending: true}, else: %{approval_pending: false}
cast(user, params, [:approval_pending])
def approval_changeset(user, set_approval: approved?) do
cast(user, %{is_approved: approved?}, [:is_approved])
end
def add_pinnned_activity(user, %Pleroma.Activity{id: id}) do

View file

@ -138,7 +138,8 @@ defmodule Pleroma.User.Query do
defp compose_query({:active, _}, query) do
User.restrict_deactivated(query)
|> where([u], u.approval_pending == false)
|> where([u], u.is_approved == true)
|> where([u], u.is_confirmed == true)
end
defp compose_query({:legacy_active, _}, query) do
@ -155,15 +156,15 @@ defmodule Pleroma.User.Query do
end
defp compose_query({:confirmation_pending, bool}, query) do
where(query, [u], u.confirmation_pending == ^bool)
where(query, [u], u.is_confirmed != ^bool)
end
defp compose_query({:need_approval, _}, query) do
where(query, [u], u.approval_pending)
where(query, [u], u.is_approved == false)
end
defp compose_query({:unconfirmed, _}, query) do
where(query, [u], u.confirmation_pending)
where(query, [u], u.is_confirmed == false)
end
defp compose_query({:followers, %User{id: id}}, query) do

View file

@ -30,7 +30,10 @@ defmodule Pleroma.Utils do
"""
@spec command_available?(String.t()) :: boolean()
def command_available?(command) do
match?({_output, 0}, System.cmd("sh", ["-c", "command -v #{command}"]))
case :os.find_executable(String.to_charlist(command)) do
false -> false
_ -> true
end
end
@doc "creates the uniq temporary directory"

View file

@ -27,7 +27,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy do
if Pleroma.Config.get(:env) == :test do
fetch(prefetch_url)
else
ConcurrentLimiter.limit(MediaProxy, fn ->
ConcurrentLimiter.limit(__MODULE__, fn ->
Task.start(fn -> fetch(prefetch_url) end)
end)
end

View file

@ -77,8 +77,8 @@ defmodule Pleroma.Web.AdminAPI.AccountView do
"local" => user.local,
"roles" => User.roles(user),
"tags" => user.tags || [],
"confirmation_pending" => user.confirmation_pending,
"approval_pending" => user.approval_pending,
"is_confirmed" => user.is_confirmed,
"is_approved" => user.is_approved,
"url" => user.uri || user.ap_id,
"registration_reason" => user.registration_reason,
"actor_type" => user.actor_type

View file

@ -191,7 +191,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
moderator: %Schema{type: :boolean}
}
},
confirmation_pending: %Schema{type: :boolean}
is_confirmed: %Schema{type: :boolean}
})
}
end

View file

@ -142,7 +142,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.StatusOperation do
}
},
tags: %Schema{type: :string},
confirmation_pending: %Schema{type: :string}
is_confirmed: %Schema{type: :string}
}
}
end

View file

@ -236,7 +236,7 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
"account" => %{
"pleroma" => %{
"is_admin" => false,
"confirmation_pending" => false,
"is_confirmed" => true,
"hide_followers_count" => false,
"is_moderator" => false,
"hide_favorites" => true,

View file

@ -117,7 +117,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
request_body("Parameters", %Schema{
type: :object,
properties: %{
visibility: %Schema{allOf: [VisibilityScope], default: "public"}
visibility: %Schema{allOf: [VisibilityScope]}
}
}),
responses: %{

View file

@ -48,7 +48,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
},
background_image: %Schema{type: :string, nullable: true, format: :uri},
chat_token: %Schema{type: :string},
confirmation_pending: %Schema{
is_confirmed: %Schema{
type: :boolean,
description:
"whether the user account is waiting on email confirmation to be activated"
@ -166,7 +166,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
"pleroma" => %{
"allow_following_move" => true,
"background_image" => nil,
"confirmation_pending" => true,
"is_confirmed" => false,
"hide_favorites" => true,
"hide_followers" => false,
"hide_followers_count" => false,

View file

@ -23,7 +23,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Chat do
"account" => %{
"pleroma" => %{
"is_admin" => false,
"confirmation_pending" => false,
"is_confirmed" => true,
"hide_followers_count" => false,
"is_moderator" => false,
"hide_favorites" => true,

View file

@ -256,7 +256,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
"note" => "Tester Number 6",
"pleroma" => %{
"background_image" => nil,
"confirmation_pending" => false,
"is_confirmed" => true,
"hide_favorites" => true,
"hide_followers" => false,
"hide_followers_count" => false,

View file

@ -84,7 +84,7 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticator do
password_confirmation: random_password
},
external: true,
need_confirmation: false
confirmed: true
)
|> Repo.insert(),
{:ok, _} <-

View file

@ -266,7 +266,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
pleroma: %{
ap_id: user.ap_id,
also_known_as: user.also_known_as,
confirmation_pending: user.confirmation_pending,
is_confirmed: user.is_confirmed,
tags: user.tags,
hide_followers_count: user.hide_followers_count,
hide_follows_count: user.hide_follows_count,

View file

@ -48,7 +48,7 @@ defmodule Pleroma.Web.Plugs.AuthenticationPlug do
end
def checkpw(password, "$pbkdf2" <> _ = password_hash) do
Pbkdf2.verify_pass(password, password_hash)
Pleroma.Password.Pbkdf2.verify_pass(password, password_hash)
end
def checkpw(_password, _password_hash) do

View file

@ -30,7 +30,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
def confirm_email(conn, %{"user_id" => uid, "token" => token}) do
with %User{} = user <- User.get_cached_by_id(uid),
true <- user.local and user.confirmation_pending and user.confirmation_token == token,
true <- user.local and !user.is_confirmed and user.confirmation_token == token,
{:ok, _} <- User.confirm(user) do
redirect(conn, to: "/")
end