[#114] User.Info: renamed `confirmation_update` to `confirmation_change`.
[akkoma] / lib / pleroma / user.ex
index f10cdfbc8ee21b6c78eb147948af94ac88aa22c0..41d01cbf5cf1dc87af9efcb8d057db3d4f2017f5 100644 (file)
@@ -14,7 +14,7 @@ defmodule Pleroma.User do
   @email_regex ~r/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
 
   @strict_local_nickname_regex ~r/^[a-zA-Z\d]+$/
-  @extended_local_nickname_regex ~r/^[a-zA-Z\d_]+$/
+  @extended_local_nickname_regex ~r/^[a-zA-Z\d_-]+$/
 
   schema "users" do
     field(:bio, :string)
@@ -38,6 +38,8 @@ defmodule Pleroma.User do
     timestamps()
   end
 
+  def auth_active?(user), do: user.info && !user.info.confirmation_pending
+
   def avatar_url(user) do
     case user.avatar do
       %{"url" => [%{"href" => href} | _]} -> href
@@ -72,13 +74,15 @@ defmodule Pleroma.User do
 
   def user_info(%User{} = user) do
     oneself = if user.local, do: 1, else: 0
+    user_info = user.info
 
     %{
       following_count: length(user.following) - oneself,
-      note_count: user.info.note_count,
-      follower_count: user.info.follower_count,
-      locked: user.info.locked,
-      default_scope: user.info.default_scope
+      note_count: user_info.note_count,
+      follower_count: user_info.follower_count,
+      locked: user_info.locked,
+      confirmation_pending: user_info.confirmation_pending,
+      default_scope: user_info.default_scope
     }
   end
 
@@ -168,7 +172,14 @@ defmodule Pleroma.User do
     update_and_set_cache(password_update_changeset(user, data))
   end
 
-  def register_changeset(struct, params \\ %{}) do
+  def register_changeset(struct, params \\ %{}, opts \\ []) do
+    confirmation_status =
+      if opts[:confirmed] || !Pleroma.Config.get([:instance, :account_activation_required]) do
+        :confirmed
+      else
+        :unconfirmed
+      end
+
     changeset =
       struct
       |> cast(params, [:bio, :email, :name, :nickname, :password, :password_confirmation])
@@ -180,7 +191,7 @@ defmodule Pleroma.User do
       |> validate_format(:email, @email_regex)
       |> validate_length(:bio, max: 1000)
       |> validate_length(:name, min: 1, max: 100)
-      |> put_change(:info, %Pleroma.User.Info{})
+      |> put_change(:info, User.Info.confirmation_change(%User.Info{}, confirmation_status))
 
     if changeset.valid? do
       hashed = Pbkdf2.hashpwsalt(changeset.changes[:password])
@@ -197,6 +208,24 @@ defmodule Pleroma.User do
     end
   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
+      {:ok, _} = try_send_confirmation_email(user)
+      {:ok, user}
+    end
+  end
+
+  def try_send_confirmation_email(%User{} = user) do
+    if user.info.confirmation_pending do
+      user
+      |> Pleroma.UserEmail.account_confirmation_email()
+      |> Pleroma.Mailer.deliver()
+    else
+      {:ok, :noop}
+    end
+  end
+
   def needs_update?(%User{local: true}), do: false
 
   def needs_update?(%User{local: false, last_refreshed_at: nil}), do: true
@@ -364,6 +393,10 @@ defmodule Pleroma.User do
     end
   end
 
+  def get_by_confirmation_token(token) do
+    Repo.one(from(u in User, where: fragment("? ->> 'confirmation_token' = ?", u.info, ^token)))
+  end
+
   def get_followers_query(%User{id: id, follower_address: follower_address}) do
     from(
       u in User,
@@ -838,7 +871,7 @@ defmodule Pleroma.User do
     do: tag(User.get_by_nickname(nickname), tags)
 
   def tag(%User{} = user, tags),
-    do: update_tags(user, Enum.uniq(user.tags ++ normalize_tags(tags)))
+    do: update_tags(user, Enum.uniq((user.tags || []) ++ normalize_tags(tags)))
 
   def untag(user_identifiers, tags) when is_list(user_identifiers) do
     Repo.transaction(fn ->
@@ -849,7 +882,8 @@ defmodule Pleroma.User do
   def untag(nickname, tags) when is_binary(nickname),
     do: untag(User.get_by_nickname(nickname), tags)
 
-  def untag(%User{} = user, tags), do: update_tags(user, user.tags -- normalize_tags(tags))
+  def untag(%User{} = user, tags),
+    do: update_tags(user, (user.tags || []) -- normalize_tags(tags))
 
   defp update_tags(%User{} = user, new_tags) do
     {:ok, updated_user} =