summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Gleason <alex@alexgleason.me>2021-05-22 16:31:43 -0500
committerAlex Gleason <alex@alexgleason.me>2021-05-22 16:31:43 -0500
commit6124cfe9ae3eeb91fba9ecd1c8d5558fcc16c1c8 (patch)
tree98dc34e4bf681a752efa2b411c48f0c8883915b5
parent93c0eb49db271d5166e7642006ffbdac276bf27d (diff)
Cycles: refactor Pleroma.User, Pleroma.User.Registration
Breaks cycles involving UserEmail
-rw-r--r--lib/mix/tasks/pleroma/email.ex2
-rw-r--r--lib/mix/tasks/pleroma/user.ex13
-rw-r--r--lib/pleroma/user.ex318
-rw-r--r--lib/pleroma/user/registration.ex321
-rw-r--r--lib/pleroma/web/admin_api/controllers/admin_api_controller.ex4
-rw-r--r--lib/pleroma/web/admin_api/controllers/user_controller.ex6
-rw-r--r--lib/pleroma/web/auth/ldap_authenticator.ex5
-rw-r--r--lib/pleroma/web/auth/pleroma_authenticator.ex2
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/account_controller.ex2
-rw-r--r--lib/pleroma/web/twitter_api/controller.ex2
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api.ex4
-rw-r--r--test/pleroma/user_test.exs64
12 files changed, 379 insertions, 364 deletions
diff --git a/lib/mix/tasks/pleroma/email.ex b/lib/mix/tasks/pleroma/email.ex
index 4ce8c9b05..7a05d7b93 100644
--- a/lib/mix/tasks/pleroma/email.ex
+++ b/lib/mix/tasks/pleroma/email.ex
@@ -38,7 +38,7 @@ defmodule Mix.Tasks.Pleroma.Email do
invisible: false
})
|> Pleroma.Repo.chunk_stream(500)
- |> Stream.each(&Pleroma.User.maybe_send_confirmation_email(&1))
+ |> Stream.each(&Pleroma.User.Registration.maybe_send_confirmation_email(&1))
|> Stream.run()
end
end
diff --git a/lib/mix/tasks/pleroma/user.ex b/lib/mix/tasks/pleroma/user.ex
index 53d5fc6d9..1e75a39ca 100644
--- a/lib/mix/tasks/pleroma/user.ex
+++ b/lib/mix/tasks/pleroma/user.ex
@@ -7,6 +7,7 @@ defmodule Mix.Tasks.Pleroma.User do
import Mix.Pleroma
alias Ecto.Changeset
alias Pleroma.User
+ alias Pleroma.User.Registration
alias Pleroma.UserInviteToken
alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.Pipeline
@@ -74,8 +75,8 @@ defmodule Mix.Tasks.Pleroma.User do
bio: bio
}
- changeset = User.register_changeset(%User{}, params, is_confirmed: true)
- {:ok, _user} = User.register(changeset)
+ changeset = Registration.register_changeset(%User{}, params, is_confirmed: true)
+ {:ok, _user} = Registration.register(changeset)
shell_info("User #{nickname} created")
@@ -355,7 +356,7 @@ defmodule Mix.Tasks.Pleroma.User do
start_pleroma()
with %User{} = user <- User.get_cached_by_nickname(nickname) do
- {:ok, user} = User.confirm(user)
+ {:ok, user} = Registration.confirm(user)
message = if !user.is_confirmed, do: "needs", else: "doesn't need"
@@ -379,7 +380,7 @@ defmodule Mix.Tasks.Pleroma.User do
|> Pleroma.Repo.chunk_stream(500, :batches)
|> Stream.each(fn users ->
users
- |> Enum.each(fn user -> User.set_confirmation(user, true) end)
+ |> Enum.each(fn user -> Registration.set_confirmation(user, true) end)
end)
|> Stream.run()
end
@@ -397,7 +398,7 @@ defmodule Mix.Tasks.Pleroma.User do
|> Pleroma.Repo.chunk_stream(500, :batches)
|> Stream.each(fn users ->
users
- |> Enum.each(fn user -> User.set_confirmation(user, false) end)
+ |> Enum.each(fn user -> Registration.set_confirmation(user, false) end)
end)
|> Stream.run()
end
@@ -461,7 +462,7 @@ defmodule Mix.Tasks.Pleroma.User do
end
defp set_confirmation(user, value) do
- {:ok, user} = User.set_confirmation(user, value)
+ {:ok, user} = Registration.set_confirmation(user, value)
shell_info("Confirmation status of #{user.nickname}: #{user.is_confirmed}")
user
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index a7c930dee..710303fe3 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -645,95 +645,6 @@ defmodule Pleroma.User do
@spec force_password_reset(User.t()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
def force_password_reset(user), do: update_password_reset_pending(user, true)
- # Used to auto-register LDAP accounts which won't have a password hash stored locally
- def register_changeset_ldap(struct, params = %{password: password})
- when is_nil(password) do
- params = Map.put_new(params, :accepts_chat_messages, true)
-
- params =
- if Map.has_key?(params, :email) do
- Map.put_new(params, :email, params[:email])
- else
- params
- end
-
- struct
- |> cast(params, [
- :name,
- :nickname,
- :email,
- :accepts_chat_messages
- ])
- |> validate_required([:name, :nickname])
- |> unique_constraint(:nickname)
- |> validate_exclusion(:nickname, Config.get([User, :restricted_nicknames]))
- |> validate_format(:nickname, local_nickname_regex())
- |> put_ap_id()
- |> unique_constraint(:ap_id)
- |> put_following_and_follower_address()
- end
-
- def register_changeset(struct, params \\ %{}, opts \\ []) do
- bio_limit = Config.get([:instance, :user_bio_length], 5000)
- name_limit = Config.get([:instance, :user_name_length], 100)
- reason_limit = Config.get([:instance, :registration_reason_length], 500)
- params = Map.put_new(params, :accepts_chat_messages, true)
-
- confirmed? =
- if is_nil(opts[:confirmed]) do
- !Config.get([:instance, :account_activation_required])
- else
- opts[:confirmed]
- end
-
- approved? =
- if is_nil(opts[:approved]) do
- !Config.get([:instance, :account_approval_required])
- else
- opts[:approved]
- end
-
- struct
- |> confirmation_changeset(set_confirmation: confirmed?)
- |> approval_changeset(set_approval: approved?)
- |> cast(params, [
- :bio,
- :raw_bio,
- :email,
- :name,
- :nickname,
- :password,
- :password_confirmation,
- :emoji,
- :accepts_chat_messages,
- :registration_reason
- ])
- |> validate_required([:name, :nickname, :password, :password_confirmation])
- |> validate_confirmation(:password)
- |> unique_constraint(:email)
- |> validate_format(:email, @email_regex)
- |> validate_change(:email, fn :email, email ->
- valid? =
- Config.get([User, :email_blacklist])
- |> Enum.all?(fn blacklisted_domain ->
- !String.ends_with?(email, ["@" <> blacklisted_domain, "." <> blacklisted_domain])
- end)
-
- if valid?, do: [], else: [email: "Invalid email"]
- end)
- |> unique_constraint(:nickname)
- |> validate_exclusion(:nickname, Config.get([User, :restricted_nicknames]))
- |> validate_format(:nickname, local_nickname_regex())
- |> validate_length(:bio, max: bio_limit)
- |> validate_length(:name, min: 1, max: name_limit)
- |> validate_length(:registration_reason, max: reason_limit)
- |> maybe_validate_required_email(opts[:external])
- |> put_password_hash
- |> put_ap_id()
- |> unique_constraint(:ap_id)
- |> put_following_and_follower_address()
- end
-
def maybe_validate_required_email(changeset, true), do: changeset
def maybe_validate_required_email(changeset, _) do
@@ -744,159 +655,6 @@ defmodule Pleroma.User do
end
end
- defp put_ap_id(changeset) do
- ap_id = ap_id(%User{nickname: get_field(changeset, :nickname)})
- put_change(changeset, :ap_id, ap_id)
- end
-
- defp put_following_and_follower_address(changeset) do
- followers = ap_followers(%User{nickname: get_field(changeset, :nickname)})
-
- changeset
- |> put_change(:follower_address, followers)
- end
-
- defp autofollow_users(user) do
- candidates = Config.get([:instance, :autofollowed_nicknames])
-
- autofollowed_users =
- User.Query.build(%{nickname: candidates, local: true, is_active: true})
- |> Repo.all()
-
- follow_all(user, autofollowed_users)
- end
-
- defp autofollowing_users(user) do
- candidates = Config.get([:instance, :autofollowing_nicknames])
-
- User.Query.build(%{nickname: candidates, local: true, deactivated: false})
- |> Repo.all()
- |> Enum.each(&follow(&1, user, :follow_accept))
-
- {:ok, :success}
- end
-
- @doc "Inserts provided changeset, performs post-registration actions (confirmation email sending etc.)"
- def register(%Ecto.Changeset{} = changeset) do
- with {:ok, user} <- Repo.insert(changeset) do
- post_register_action(user)
- end
- end
-
- def post_register_action(%User{is_confirmed: false} = user) do
- with {:ok, _} <- maybe_send_confirmation_email(user) do
- {:ok, user}
- end
- end
-
- 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{is_approved: true, is_confirmed: true} = user) do
- with {:ok, user} <- autofollow_users(user),
- {:ok, _} <- autofollowing_users(user),
- {:ok, user} <- set_cache(user),
- {:ok, _} <- maybe_send_registration_email(user),
- {:ok, _} <- maybe_send_welcome_email(user),
- {:ok, _} <- maybe_send_welcome_message(user),
- {:ok, _} <- maybe_send_welcome_chat_message(user) do
- {:ok, user}
- end
- end
-
- defp send_user_approval_email(user) do
- user
- |> Pleroma.Emails.UserEmail.approval_pending_email()
- |> Pleroma.Emails.Mailer.deliver_async()
-
- {:ok, :enqueued}
- end
-
- defp send_admin_approval_emails(user) do
- all_superusers()
- |> Enum.filter(fn user -> not is_nil(user.email) end)
- |> Enum.each(fn superuser ->
- superuser
- |> Pleroma.Emails.AdminEmail.new_unapproved_registration(user)
- |> Pleroma.Emails.Mailer.deliver_async()
- end)
-
- {:ok, :enqueued}
- end
-
- defp maybe_send_welcome_message(user) do
- if User.WelcomeMessage.enabled?() do
- User.WelcomeMessage.post_message(user)
- {:ok, :enqueued}
- else
- {:ok, :noop}
- end
- end
-
- defp maybe_send_welcome_chat_message(user) do
- if User.WelcomeChatMessage.enabled?() do
- User.WelcomeChatMessage.post_message(user)
- {:ok, :enqueued}
- else
- {:ok, :noop}
- end
- end
-
- defp maybe_send_welcome_email(%User{email: email} = user) when is_binary(email) do
- if User.WelcomeEmail.enabled?() do
- User.WelcomeEmail.send_email(user)
- {:ok, :enqueued}
- else
- {:ok, :noop}
- end
- end
-
- defp maybe_send_welcome_email(_), do: {:ok, :noop}
-
- @spec maybe_send_confirmation_email(User.t()) :: {:ok, :enqueued | :noop}
- def maybe_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)
- {:ok, :enqueued}
- else
- {:ok, :noop}
- end
- end
-
- def maybe_send_confirmation_email(_), do: {:ok, :noop}
-
- @spec send_confirmation_email(Uset.t()) :: User.t()
- def send_confirmation_email(%User{} = user) do
- user
- |> Pleroma.Emails.UserEmail.account_confirmation_email()
- |> Pleroma.Emails.Mailer.deliver_async()
-
- user
- end
-
- @spec maybe_send_registration_email(User.t()) :: {:ok, :enqueued | :noop}
- defp maybe_send_registration_email(%User{email: email} = user) when is_binary(email) do
- with false <- User.WelcomeEmail.enabled?(),
- false <- Config.get([:instance, :account_activation_required], false),
- false <- Config.get([:instance, :account_approval_required], false) do
- user
- |> Pleroma.Emails.UserEmail.successful_registration_email()
- |> Pleroma.Emails.Mailer.deliver_async()
-
- {:ok, :enqueued}
- else
- _ ->
- {:ok, :noop}
- end
- end
-
- defp maybe_send_registration_email(_), do: {:ok, :noop}
-
def needs_update?(%User{local: true}), do: false
def needs_update?(%User{local: false, last_refreshed_at: nil}), do: true
@@ -1610,42 +1368,6 @@ defmodule Pleroma.User do
end
end
- def approve(users) when is_list(users) do
- Repo.transaction(fn ->
- Enum.map(users, fn user ->
- with {:ok, user} <- approve(user), do: user
- end)
- end)
- end
-
- 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}
- end
- end
-
- def approve(%User{} = user), do: {:ok, user}
-
- def confirm(users) when is_list(users) do
- Repo.transaction(fn ->
- Enum.map(users, fn user ->
- with {:ok, user} <- confirm(user), do: user
- end)
- end)
- end
-
- 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}
- end
- end
-
- def confirm(%User{} = user), do: {:ok, user}
-
def update_notification_settings(%User{} = user, settings) do
user
|> cast(%{notification_settings: settings}, [])
@@ -2021,7 +1743,7 @@ defmodule Pleroma.User do
|> Enum.map(&String.downcase/1)
end
- defp local_nickname_regex do
+ def local_nickname_regex do
if Config.get([:instance, :extended_nickname_format]) do
@extended_local_nickname_regex
else
@@ -2141,13 +1863,6 @@ defmodule Pleroma.User do
updated_user
end
- @spec set_confirmation(User.t(), boolean()) :: {:ok, User.t()} | {:error, Changeset.t()}
- def set_confirmation(%User{} = user, bool) do
- user
- |> confirmation_changeset(set_confirmation: bool)
- |> update_and_set_cache()
- end
-
def get_mascot(%{mascot: %{} = mascot}) when not is_nil(mascot) do
mascot
end
@@ -2187,13 +1902,11 @@ defmodule Pleroma.User do
|> Repo.all()
end
- defp put_password_hash(
- %Ecto.Changeset{valid?: true, changes: %{password: password}} = changeset
- ) do
+ def put_password_hash(%Ecto.Changeset{valid?: true, changes: %{password: password}} = changeset) do
change(changeset, password_hash: Pleroma.Password.Pbkdf2.hash_pwd_salt(password))
end
- defp put_password_hash(changeset), do: changeset
+ def put_password_hash(changeset), do: changeset
def is_internal_user?(%User{nickname: nil}), do: true
def is_internal_user?(%User{local: true, nickname: "internal." <> _}), do: true
@@ -2311,29 +2024,6 @@ defmodule Pleroma.User do
|> update_and_set_cache()
end
- @spec confirmation_changeset(User.t(), keyword()) :: Changeset.t()
- def confirmation_changeset(user, set_confirmation: confirmed?) do
- params =
- if confirmed? do
- %{
- is_confirmed: true,
- confirmation_token: nil
- }
- else
- %{
- is_confirmed: false,
- confirmation_token: :crypto.strong_rand_bytes(32) |> Base.url_encode64()
- }
- end
-
- cast(user, params, [:is_confirmed, :confirmation_token])
- end
-
- @spec approval_changeset(User.t(), keyword()) :: Changeset.t()
- 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
if id not in user.pinned_activities do
max_pinned_statuses = Config.get([:instance, :max_pinned_statuses], 0)
@@ -2474,4 +2164,6 @@ defmodule Pleroma.User do
|> where([u], u.local == true)
|> Repo.aggregate(:count)
end
+
+ def email_regex, do: @email_regex
end
diff --git a/lib/pleroma/user/registration.ex b/lib/pleroma/user/registration.ex
new file mode 100644
index 000000000..45a9efbcf
--- /dev/null
+++ b/lib/pleroma/user/registration.ex
@@ -0,0 +1,321 @@
+defmodule Pleroma.User.Registration do
+ alias Pleroma.Config
+ alias Pleroma.Emails.AdminEmail
+ alias Pleroma.Emails.Mailer
+ alias Pleroma.Emails.UserEmail
+ alias Pleroma.Repo
+ alias Pleroma.User
+ alias Pleroma.User.WelcomeChatMessage
+ alias Pleroma.User.WelcomeEmail
+ alias Pleroma.User.WelcomeMessage
+
+ import Ecto.Changeset
+
+ @doc "Inserts provided changeset, performs post-registration actions (confirmation email sending etc.)"
+ def register(%Ecto.Changeset{} = changeset) do
+ with {:ok, user} <- Repo.insert(changeset) do
+ post_register_action(user)
+ end
+ end
+
+ def post_register_action(%User{is_confirmed: false} = user) do
+ with {:ok, _} <- maybe_send_confirmation_email(user) do
+ {:ok, user}
+ end
+ end
+
+ 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{is_approved: true, is_confirmed: true} = user) do
+ with {:ok, user} <- autofollow_users(user),
+ {:ok, _} <- autofollowing_users(user),
+ {:ok, user} <- User.set_cache(user),
+ {:ok, _} <- maybe_send_registration_email(user),
+ {:ok, _} <- maybe_send_welcome_email(user),
+ {:ok, _} <- maybe_send_welcome_message(user),
+ {:ok, _} <- maybe_send_welcome_chat_message(user) do
+ {:ok, user}
+ end
+ end
+
+ defp send_user_approval_email(user) do
+ user
+ |> UserEmail.approval_pending_email()
+ |> Mailer.deliver_async()
+
+ {:ok, :enqueued}
+ end
+
+ defp send_admin_approval_emails(user) do
+ User.all_superusers()
+ |> Enum.filter(fn user -> not is_nil(user.email) end)
+ |> Enum.each(fn superuser ->
+ superuser
+ |> AdminEmail.new_unapproved_registration(user)
+ |> Mailer.deliver_async()
+ end)
+
+ {:ok, :enqueued}
+ end
+
+ defp maybe_send_welcome_message(user) do
+ if WelcomeMessage.enabled?() do
+ WelcomeMessage.post_message(user)
+ {:ok, :enqueued}
+ else
+ {:ok, :noop}
+ end
+ end
+
+ defp maybe_send_welcome_chat_message(user) do
+ if WelcomeChatMessage.enabled?() do
+ WelcomeChatMessage.post_message(user)
+ {:ok, :enqueued}
+ else
+ {:ok, :noop}
+ end
+ end
+
+ defp maybe_send_welcome_email(%User{email: email} = user) when is_binary(email) do
+ if WelcomeEmail.enabled?() do
+ WelcomeEmail.send_email(user)
+ {:ok, :enqueued}
+ else
+ {:ok, :noop}
+ end
+ end
+
+ defp maybe_send_welcome_email(_), do: {:ok, :noop}
+
+ @spec maybe_send_confirmation_email(User.t()) :: {:ok, :enqueued | :noop}
+ def maybe_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)
+ {:ok, :enqueued}
+ else
+ {:ok, :noop}
+ end
+ end
+
+ def maybe_send_confirmation_email(_), do: {:ok, :noop}
+
+ @spec send_confirmation_email(User.t()) :: User.t()
+ def send_confirmation_email(%User{} = user) do
+ user
+ |> UserEmail.account_confirmation_email()
+ |> Mailer.deliver_async()
+
+ user
+ end
+
+ @spec maybe_send_registration_email(User.t()) :: {:ok, :enqueued | :noop}
+ defp maybe_send_registration_email(%User{email: email} = user) when is_binary(email) do
+ with false <- WelcomeEmail.enabled?(),
+ false <- Config.get([:instance, :account_activation_required], false),
+ false <- Config.get([:instance, :account_approval_required], false) do
+ user
+ |> UserEmail.successful_registration_email()
+ |> Mailer.deliver_async()
+
+ {:ok, :enqueued}
+ else
+ _ ->
+ {:ok, :noop}
+ end
+ end
+
+ defp maybe_send_registration_email(_), do: {:ok, :noop}
+
+ def approve(users) when is_list(users) do
+ Repo.transaction(fn ->
+ Enum.map(users, fn user ->
+ with {:ok, user} <- approve(user), do: user
+ end)
+ end)
+ end
+
+ def approve(%User{is_approved: false} = user) do
+ with chg <- change(user, is_approved: true),
+ {:ok, user} <- User.update_and_set_cache(chg) do
+ post_register_action(user)
+ {:ok, user}
+ end
+ end
+
+ def approve(%User{} = user), do: {:ok, user}
+
+ def confirm(users) when is_list(users) do
+ Repo.transaction(fn ->
+ Enum.map(users, fn user ->
+ with {:ok, user} <- confirm(user), do: user
+ end)
+ end)
+ end
+
+ def confirm(%User{is_confirmed: false} = user) do
+ with chg <- confirmation_changeset(user, set_confirmation: true),
+ {:ok, user} <- User.update_and_set_cache(chg) do
+ post_register_action(user)
+ {:ok, user}
+ end
+ end
+
+ def confirm(%User{} = user), do: {:ok, user}
+
+ # Used to auto-register LDAP accounts which won't have a password hash stored locally
+ def register_changeset_ldap(struct, params = %{password: password})
+ when is_nil(password) do
+ params = Map.put_new(params, :accepts_chat_messages, true)
+
+ params =
+ if Map.has_key?(params, :email) do
+ Map.put_new(params, :email, params[:email])
+ else
+ params
+ end
+
+ struct
+ |> cast(params, [
+ :name,
+ :nickname,
+ :email,
+ :accepts_chat_messages
+ ])
+ |> validate_required([:name, :nickname])
+ |> unique_constraint(:nickname)
+ |> validate_exclusion(:nickname, Config.get([User, :restricted_nicknames]))
+ |> validate_format(:nickname, User.local_nickname_regex())
+ |> put_ap_id()
+ |> unique_constraint(:ap_id)
+ |> put_following_and_follower_address()
+ end
+
+ def register_changeset(struct, params \\ %{}, opts \\ []) do
+ bio_limit = Config.get([:instance, :user_bio_length], 5000)
+ name_limit = Config.get([:instance, :user_name_length], 100)
+ reason_limit = Config.get([:instance, :registration_reason_length], 500)
+ params = Map.put_new(params, :accepts_chat_messages, true)
+
+ confirmed? =
+ if is_nil(opts[:confirmed]) do
+ !Config.get([:instance, :account_activation_required])
+ else
+ opts[:confirmed]
+ end
+
+ approved? =
+ if is_nil(opts[:approved]) do
+ !Config.get([:instance, :account_approval_required])
+ else
+ opts[:approved]
+ end
+
+ struct
+ |> confirmation_changeset(set_confirmation: confirmed?)
+ |> approval_changeset(set_approval: approved?)
+ |> cast(params, [
+ :bio,
+ :raw_bio,
+ :email,
+ :name,
+ :nickname,
+ :password,
+ :password_confirmation,
+ :emoji,
+ :accepts_chat_messages,
+ :registration_reason
+ ])
+ |> validate_required([:name, :nickname, :password, :password_confirmation])
+ |> validate_confirmation(:password)
+ |> unique_constraint(:email)
+ |> validate_format(:email, User.email_regex())
+ |> validate_change(:email, fn :email, email ->
+ valid? =
+ Config.get([User, :email_blacklist])
+ |> Enum.all?(fn blacklisted_domain ->
+ !String.ends_with?(email, ["@" <> blacklisted_domain, "." <> blacklisted_domain])
+ end)
+
+ if valid?, do: [], else: [email: "Invalid email"]
+ end)
+ |> unique_constraint(:nickname)
+ |> validate_exclusion(:nickname, Config.get([User, :restricted_nicknames]))
+ |> validate_format(:nickname, User.local_nickname_regex())
+ |> validate_length(:bio, max: bio_limit)
+ |> validate_length(:name, min: 1, max: name_limit)
+ |> validate_length(:registration_reason, max: reason_limit)
+ |> User.maybe_validate_required_email(opts[:external])
+ |> User.put_password_hash()
+ |> put_ap_id()
+ |> unique_constraint(:ap_id)
+ |> put_following_and_follower_address()
+ end
+
+ @spec confirmation_changeset(User.t(), keyword()) :: Changeset.t()
+ def confirmation_changeset(user, set_confirmation: confirmed?) do
+ params =
+ if confirmed? do
+ %{
+ is_confirmed: true,
+ confirmation_token: nil
+ }
+ else
+ %{
+ is_confirmed: false,
+ confirmation_token: :crypto.strong_rand_bytes(32) |> Base.url_encode64()
+ }
+ end
+
+ cast(user, params, [:is_confirmed, :confirmation_token])
+ end
+
+ @spec approval_changeset(User.t(), keyword()) :: Changeset.t()
+ def approval_changeset(user, set_approval: approved?) do
+ cast(user, %{is_approved: approved?}, [:is_approved])
+ end
+
+ @spec set_confirmation(User.t(), boolean()) :: {:ok, User.t()} | {:error, Changeset.t()}
+ def set_confirmation(%User{} = user, bool) do
+ user
+ |> confirmation_changeset(set_confirmation: bool)
+ |> User.update_and_set_cache()
+ end
+
+ defp put_ap_id(changeset) do
+ ap_id = User.ap_id(%User{nickname: get_field(changeset, :nickname)})
+ put_change(changeset, :ap_id, ap_id)
+ end
+
+ defp put_following_and_follower_address(changeset) do
+ followers = User.ap_followers(%User{nickname: get_field(changeset, :nickname)})
+
+ changeset
+ |> put_change(:follower_address, followers)
+ end
+
+ defp autofollow_users(user) do
+ candidates = Config.get([:instance, :autofollowed_nicknames])
+
+ autofollowed_users =
+ User.Query.build(%{nickname: candidates, local: true, is_active: true})
+ |> Repo.all()
+
+ User.follow_all(user, autofollowed_users)
+ end
+
+ defp autofollowing_users(user) do
+ candidates = Config.get([:instance, :autofollowing_nicknames])
+
+ User.Query.build(%{nickname: candidates, local: true, deactivated: false})
+ |> Repo.all()
+ |> Enum.each(&User.follow(&1, user, :follow_accept))
+
+ {:ok, :success}
+ end
+end
diff --git a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex
index 839ac1a8d..ef1058123 100644
--- a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex
@@ -419,7 +419,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
def confirm_email(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
- User.confirm(users)
+ User.Registration.confirm(users)
ModerationLog.insert_log(%{actor: admin, subject: users, action: "confirm_email"})
@@ -431,7 +431,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
Enum.map(nicknames, fn nickname ->
nickname
|> User.get_cached_by_nickname()
- |> User.send_confirmation_email()
+ |> User.Registration.send_confirmation_email()
end)
ModerationLog.insert_log(%{actor: admin, subject: users, action: "resend_confirmation_email"})
diff --git a/lib/pleroma/web/admin_api/controllers/user_controller.ex b/lib/pleroma/web/admin_api/controllers/user_controller.ex
index 65bc63cb9..9d3b32f39 100644
--- a/lib/pleroma/web/admin_api/controllers/user_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/user_controller.ex
@@ -117,7 +117,7 @@ defmodule Pleroma.Web.AdminAPI.UserController do
bio: "."
}
- User.register_changeset(%User{}, user_data, need_confirmation: false)
+ User.Registration.register_changeset(%User{}, user_data, need_confirmation: false)
end)
|> Enum.reduce(Ecto.Multi.new(), fn changeset, multi ->
Ecto.Multi.insert(multi, Ecto.UUID.generate(), changeset)
@@ -129,7 +129,7 @@ defmodule Pleroma.Web.AdminAPI.UserController do
users
|> Map.values()
|> Enum.map(fn user ->
- {:ok, user} = User.post_register_action(user)
+ {:ok, user} = User.Registration.post_register_action(user)
user
end)
@@ -219,7 +219,7 @@ defmodule Pleroma.Web.AdminAPI.UserController do
def approve(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
- {:ok, updated_users} = User.approve(users)
+ {:ok, updated_users} = User.Registration.approve(users)
ModerationLog.insert_log(%{
actor: admin,
diff --git a/lib/pleroma/web/auth/ldap_authenticator.ex b/lib/pleroma/web/auth/ldap_authenticator.ex
index 17e08a2a6..d0513263c 100644
--- a/lib/pleroma/web/auth/ldap_authenticator.ex
+++ b/lib/pleroma/web/auth/ldap_authenticator.ex
@@ -4,6 +4,7 @@
defmodule Pleroma.Web.Auth.LDAPAuthenticator do
alias Pleroma.User
+ alias Pleroma.User.Registration
require Logger
@@ -116,9 +117,9 @@ defmodule Pleroma.Web.Auth.LDAPAuthenticator do
_ -> params
end
- changeset = User.register_changeset_ldap(%User{}, params)
+ changeset = Registration.register_changeset_ldap(%User{}, params)
- case User.register(changeset) do
+ case Registration.register(changeset) do
{:ok, user} -> user
error -> error
end
diff --git a/lib/pleroma/web/auth/pleroma_authenticator.ex b/lib/pleroma/web/auth/pleroma_authenticator.ex
index 401f23c9f..ff7dd7034 100644
--- a/lib/pleroma/web/auth/pleroma_authenticator.ex
+++ b/lib/pleroma/web/auth/pleroma_authenticator.ex
@@ -73,7 +73,7 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticator do
random_password = :crypto.strong_rand_bytes(64) |> Base.encode64()
with {:ok, new_user} <-
- User.register_changeset(
+ User.Registration.register_changeset(
%User{},
%{
email: email,
diff --git a/lib/pleroma/web/pleroma_api/controllers/account_controller.ex b/lib/pleroma/web/pleroma_api/controllers/account_controller.ex
index 6e01c5497..518d7d542 100644
--- a/lib/pleroma/web/pleroma_api/controllers/account_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/account_controller.ex
@@ -55,7 +55,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do
nickname_or_email = params[:email] || params[:nickname]
with %User{} = user <- User.get_by_nickname_or_email(nickname_or_email),
- {:ok, _} <- User.maybe_send_confirmation_email(user) do
+ {:ok, _} <- User.Registration.maybe_send_confirmation_email(user) do
json_response(conn, :no_content, "")
end
end
diff --git a/lib/pleroma/web/twitter_api/controller.ex b/lib/pleroma/web/twitter_api/controller.ex
index 077bfa70d..852af9d30 100644
--- a/lib/pleroma/web/twitter_api/controller.ex
+++ b/lib/pleroma/web/twitter_api/controller.ex
@@ -31,7 +31,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.is_confirmed and user.confirmation_token == token,
- {:ok, _} <- User.confirm(user) do
+ {:ok, _} <- User.Registration.confirm(user) do
redirect(conn, to: "/")
end
end
diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex
index 76ca82d20..c581fc622 100644
--- a/lib/pleroma/web/twitter_api/twitter_api.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api.ex
@@ -41,9 +41,9 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
end
defp create_user(params, opts) do
- changeset = User.register_changeset(%User{}, params, opts)
+ changeset = User.Registration.register_changeset(%User{}, params, opts)
- case User.register(changeset) do
+ case User.Registration.register(changeset) do
{:ok, user} ->
{:ok, user}
diff --git a/test/pleroma/user_test.exs b/test/pleroma/user_test.exs
index 79c7d7ed1..8f53f5277 100644
--- a/test/pleroma/user_test.exs
+++ b/test/pleroma/user_test.exs
@@ -401,9 +401,9 @@ defmodule Pleroma.UserTest do
remote_user.nickname
])
- cng = User.register_changeset(%User{}, @full_user_data)
+ cng = User.Registration.register_changeset(%User{}, @full_user_data)
- {:ok, registered_user} = User.register(cng)
+ {:ok, registered_user} = User.Registration.register(cng)
assert User.following?(registered_user, user)
refute User.following?(registered_user, remote_user)
@@ -418,9 +418,9 @@ defmodule Pleroma.UserTest do
user2.nickname
])
- cng = User.register_changeset(%User{}, @full_user_data)
+ cng = User.Registration.register_changeset(%User{}, @full_user_data)
- {:ok, registered_user} = User.register(cng)
+ {:ok, registered_user} = User.Registration.register(cng)
assert User.following?(user1, registered_user)
assert User.following?(user2, registered_user)
@@ -432,8 +432,8 @@ defmodule Pleroma.UserTest do
clear_config([:welcome, :direct_message, :sender_nickname], welcome_user.nickname)
clear_config([:welcome, :direct_message, :message], "Hello, this is a direct message")
- cng = User.register_changeset(%User{}, @full_user_data)
- {:ok, registered_user} = User.register(cng)
+ cng = User.Registration.register_changeset(%User{}, @full_user_data)
+ {:ok, registered_user} = User.Registration.register(cng)
ObanHelpers.perform_all()
activity = Repo.one(Pleroma.Activity)
@@ -448,8 +448,8 @@ defmodule Pleroma.UserTest do
clear_config([:welcome, :chat_message, :sender_nickname], welcome_user.nickname)
clear_config([:welcome, :chat_message, :message], "Hello, this is a chat message")
- cng = User.register_changeset(%User{}, @full_user_data)
- {:ok, registered_user} = User.register(cng)
+ cng = User.Registration.register_changeset(%User{}, @full_user_data)
+ {:ok, registered_user} = User.Registration.register(cng)
ObanHelpers.perform_all()
activity = Repo.one(Pleroma.Activity)
@@ -487,8 +487,8 @@ defmodule Pleroma.UserTest do
clear_config([:welcome, :chat_message, :sender_nickname], welcome_user.nickname)
clear_config([:welcome, :chat_message, :message], "Hello, this is a chat message")
- cng = User.register_changeset(%User{}, @full_user_data)
- {:ok, registered_user} = User.register(cng)
+ cng = User.Registration.register_changeset(%User{}, @full_user_data)
+ {:ok, registered_user} = User.Registration.register(cng)
ObanHelpers.perform_all()
activity = Repo.one(Pleroma.Activity)
@@ -509,8 +509,8 @@ defmodule Pleroma.UserTest do
instance_name = Pleroma.Config.get([:instance, :name])
- cng = User.register_changeset(%User{}, @full_user_data)
- {:ok, registered_user} = User.register(cng)
+ cng = User.Registration.register_changeset(%User{}, @full_user_data)
+ {:ok, registered_user} = User.Registration.register(cng)
ObanHelpers.perform_all()
assert_email_sent(
@@ -524,8 +524,8 @@ defmodule Pleroma.UserTest do
test "it sends a confirm email" do
clear_config([:instance, :account_activation_required], true)
- cng = User.register_changeset(%User{}, @full_user_data)
- {:ok, registered_user} = User.register(cng)
+ cng = User.Registration.register_changeset(%User{}, @full_user_data)
+ {:ok, registered_user} = User.Registration.register(cng)
ObanHelpers.perform_all()
Pleroma.Emails.UserEmail.account_confirmation_email(registered_user)
@@ -539,8 +539,8 @@ defmodule Pleroma.UserTest do
clear_config([:instance, :account_approval_required], true)
{:ok, user} =
- User.register_changeset(%User{}, @full_user_data)
- |> User.register()
+ User.Registration.register_changeset(%User{}, @full_user_data)
+ |> User.Registration.register()
ObanHelpers.perform_all()
@@ -557,8 +557,8 @@ defmodule Pleroma.UserTest do
clear_config([:instance, :account_approval_required], false)
{:ok, user} =
- User.register_changeset(%User{}, @full_user_data)
- |> User.register()
+ User.Registration.register_changeset(%User{}, @full_user_data)
+ |> User.Registration.register()
ObanHelpers.perform_all()
@@ -579,7 +579,7 @@ defmodule Pleroma.UserTest do
|> Map.keys()
|> Enum.each(fn key ->
params = Map.delete(@full_user_data, key)
- changeset = User.register_changeset(%User{}, params)
+ changeset = User.Registration.register_changeset(%User{}, params)
assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
end)
@@ -592,7 +592,7 @@ defmodule Pleroma.UserTest do
|> Map.keys()
|> Enum.each(fn key ->
params = Map.delete(@full_user_data, key)
- changeset = User.register_changeset(%User{}, params)
+ changeset = User.Registration.register_changeset(%User{}, params)
assert if key in [:bio, :email], do: changeset.valid?, else: not changeset.valid?
end)
@@ -607,7 +607,7 @@ defmodule Pleroma.UserTest do
@full_user_data
|> Map.put(:nickname, restricted_name)
- changeset = User.register_changeset(%User{}, params)
+ changeset = User.Registration.register_changeset(%User{}, params)
refute changeset.valid?
end
@@ -617,26 +617,26 @@ defmodule Pleroma.UserTest do
# Block with match
params = Map.put(@full_user_data, :email, "troll@trolling.world")
- changeset = User.register_changeset(%User{}, params)
+ changeset = User.Registration.register_changeset(%User{}, params)
refute changeset.valid?
# Block with subdomain match
params = Map.put(@full_user_data, :email, "troll@gnomes.trolling.world")
- changeset = User.register_changeset(%User{}, params)
+ changeset = User.Registration.register_changeset(%User{}, params)
refute changeset.valid?
# Pass with different domains that are similar
params = Map.put(@full_user_data, :email, "troll@gnomestrolling.world")
- changeset = User.register_changeset(%User{}, params)
+ changeset = User.Registration.register_changeset(%User{}, params)
assert changeset.valid?
params = Map.put(@full_user_data, :email, "troll@trolling.world.us")
- changeset = User.register_changeset(%User{}, params)
+ changeset = User.Registration.register_changeset(%User{}, params)
assert changeset.valid?
end
test "it sets the password_hash and ap_id" do
- changeset = User.register_changeset(%User{}, @full_user_data)
+ changeset = User.Registration.register_changeset(%User{}, @full_user_data)
assert changeset.valid?
@@ -647,7 +647,7 @@ defmodule Pleroma.UserTest do
end
test "it sets the 'accepts_chat_messages' set to true" do
- changeset = User.register_changeset(%User{}, @full_user_data)
+ changeset = User.Registration.register_changeset(%User{}, @full_user_data)
assert changeset.valid?
{:ok, user} = Repo.insert(changeset)
@@ -656,7 +656,7 @@ defmodule Pleroma.UserTest do
end
test "it creates a confirmed user" do
- changeset = User.register_changeset(%User{}, @full_user_data)
+ changeset = User.Registration.register_changeset(%User{}, @full_user_data)
assert changeset.valid?
{:ok, user} = Repo.insert(changeset)
@@ -677,7 +677,7 @@ defmodule Pleroma.UserTest do
setup do: clear_config([:instance, :account_activation_required], true)
test "it creates unconfirmed user" do
- changeset = User.register_changeset(%User{}, @full_user_data)
+ changeset = User.Registration.register_changeset(%User{}, @full_user_data)
assert changeset.valid?
{:ok, user} = Repo.insert(changeset)
@@ -687,7 +687,7 @@ defmodule Pleroma.UserTest do
end
test "it creates confirmed user if :confirmed option is given" do
- changeset = User.register_changeset(%User{}, @full_user_data, confirmed: true)
+ changeset = User.Registration.register_changeset(%User{}, @full_user_data, confirmed: true)
assert changeset.valid?
{:ok, user} = Repo.insert(changeset)
@@ -710,7 +710,7 @@ defmodule Pleroma.UserTest do
setup do: clear_config([:instance, :account_approval_required], true)
test "it creates unapproved user" do
- changeset = User.register_changeset(%User{}, @full_user_data)
+ changeset = User.Registration.register_changeset(%User{}, @full_user_data)
assert changeset.valid?
{:ok, user} = Repo.insert(changeset)
@@ -731,7 +731,7 @@ defmodule Pleroma.UserTest do
"Quia et nesciunt dolores numquam ipsam nisi sapiente soluta. Ullam repudiandae nisi quam porro officiis officiis ad. Consequatur animi velit ex quia. Odit voluptatem perferendis quia ut nisi. Dignissimos sit soluta atque aliquid dolorem ut dolorum ut. Labore voluptates iste iusto amet voluptatum earum. Ad fugit illum nam eos ut nemo. Pariatur ea fuga non aspernatur. Dignissimos debitis officia corporis est nisi ab et. Atque itaque alias eius voluptas minus. Accusamus numquam tempore occaecati in."
)
- changeset = User.register_changeset(%User{}, params)
+ changeset = User.Registration.register_changeset(%User{}, params)
refute changeset.valid?
end