diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/pleroma/emails/admin_email.ex | 15 | ||||
| -rw-r--r-- | lib/pleroma/moderation_log.ex | 11 | ||||
| -rw-r--r-- | lib/pleroma/user.ex | 59 | ||||
| -rw-r--r-- | lib/pleroma/user/query.ex | 5 | ||||
| -rw-r--r-- | lib/pleroma/web/admin_api/controllers/admin_api_controller.ex | 18 | ||||
| -rw-r--r-- | lib/pleroma/web/admin_api/views/account_view.ex | 4 | ||||
| -rw-r--r-- | lib/pleroma/web/mastodon_api/views/instance_view.ex | 1 | ||||
| -rw-r--r-- | lib/pleroma/web/oauth/oauth_controller.ex | 10 | ||||
| -rw-r--r-- | lib/pleroma/web/router.ex | 1 | ||||
| -rw-r--r-- | lib/pleroma/web/twitter_api/twitter_api.ex | 14 | 
10 files changed, 128 insertions, 10 deletions
| diff --git a/lib/pleroma/emails/admin_email.ex b/lib/pleroma/emails/admin_email.ex index aa0b2a66b..c27ad1065 100644 --- a/lib/pleroma/emails/admin_email.ex +++ b/lib/pleroma/emails/admin_email.ex @@ -8,6 +8,7 @@ defmodule Pleroma.Emails.AdminEmail do    import Swoosh.Email    alias Pleroma.Config +  alias Pleroma.HTML    alias Pleroma.Web.Router.Helpers    defp instance_config, do: Config.get(:instance) @@ -82,4 +83,18 @@ defmodule Pleroma.Emails.AdminEmail do      |> subject("#{instance_name()} Report")      |> html_body(html_body)    end + +  def new_unapproved_registration(to, account) do +    html_body = """ +    <p>New account for review: <a href="#{user_url(account)}">@#{account.nickname}</a></p> +    <blockquote>#{HTML.strip_tags(account.registration_reason)}</blockquote> +    <a href="#{Pleroma.Web.base_url()}/pleroma/admin">Visit AdminFE</a> +    """ + +    new() +    |> to({to.name, to.email}) +    |> from({instance_name(), instance_notify_email()}) +    |> subject("New account up for review on #{instance_name()} (@#{account.nickname})") +    |> html_body(html_body) +  end  end diff --git a/lib/pleroma/moderation_log.ex b/lib/pleroma/moderation_log.ex index 7aacd9d80..31c9afe2a 100644 --- a/lib/pleroma/moderation_log.ex +++ b/lib/pleroma/moderation_log.ex @@ -413,6 +413,17 @@ defmodule Pleroma.ModerationLog do    def get_log_entry_message(%ModerationLog{          data: %{            "actor" => %{"nickname" => actor_nickname}, +          "action" => "approve", +          "subject" => users +        } +      }) do +    "@#{actor_nickname} approved users: #{users_to_nicknames_string(users)}" +  end + +  @spec get_log_entry_message(ModerationLog) :: String.t() +  def get_log_entry_message(%ModerationLog{ +        data: %{ +          "actor" => %{"nickname" => actor_nickname},            "nicknames" => nicknames,            "tags" => tags,            "action" => "tag" diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index ed1db04c9..dcf6ebee2 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -42,7 +42,12 @@ defmodule Pleroma.User do    require Logger    @type t :: %__MODULE__{} -  @type account_status :: :active | :deactivated | :password_reset_pending | :confirmation_pending +  @type account_status :: +          :active +          | :deactivated +          | :password_reset_pending +          | :confirmation_pending +          | :approval_pending    @primary_key {:id, FlakeId.Ecto.CompatType, autogenerate: true}    # credo:disable-for-next-line Credo.Check.Readability.MaxLineLength @@ -106,6 +111,8 @@ defmodule Pleroma.User do      field(:locked, :boolean, default: false)      field(:confirmation_pending, :boolean, default: false)      field(:password_reset_pending, :boolean, default: false) +    field(:approval_pending, :boolean, default: false) +    field(:registration_reason, :string, default: nil)      field(:confirmation_token, :string, default: nil)      field(:default_scope, :string, default: "public")      field(:domain_blocks, {:array, :string}, default: []) @@ -262,6 +269,7 @@ 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{approval_pending: true}), do: :approval_pending    def account_status(%User{confirmation_pending: true}) do      if Config.get([:instance, :account_activation_required]) do @@ -633,6 +641,7 @@ defmodule Pleroma.User do    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)      need_confirmation? = @@ -642,8 +651,16 @@ defmodule Pleroma.User do          opts[:need_confirmation]        end +    need_approval? = +      if is_nil(opts[:need_approval]) do +        Config.get([:instance, :account_approval_required]) +      else +        opts[:need_approval] +      end +      struct      |> confirmation_changeset(need_confirmation: need_confirmation?) +    |> approval_changeset(need_approval: need_approval?)      |> cast(params, [        :bio,        :raw_bio, @@ -653,7 +670,8 @@ defmodule Pleroma.User do        :password,        :password_confirmation,        :emoji, -      :accepts_chat_messages +      :accepts_chat_messages, +      :registration_reason      ])      |> validate_required([:name, :nickname, :password, :password_confirmation])      |> validate_confirmation(:password) @@ -664,6 +682,7 @@ defmodule Pleroma.User do      |> validate_format(:email, @email_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() @@ -1494,6 +1513,19 @@ 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{} = user) do +    change(user, approval_pending: false) +    |> update_and_set_cache() +  end +    def update_notification_settings(%User{} = user, settings) do      user      |> cast(%{notification_settings: settings}, []) @@ -1520,12 +1552,17 @@ defmodule Pleroma.User do    defp delete_or_deactivate(%User{local: true} = user) do      status = account_status(user) -    if status == :confirmation_pending do -      delete_and_invalidate_cache(user) -    else -      user -      |> change(%{deactivated: true, email: nil}) -      |> update_and_set_cache() +    case status do +      :confirmation_pending -> +        delete_and_invalidate_cache(user) + +      :approval_pending -> +        delete_and_invalidate_cache(user) + +      _ -> +        user +        |> change(%{deactivated: true, email: nil}) +        |> update_and_set_cache()      end    end @@ -2178,6 +2215,12 @@ defmodule Pleroma.User do      cast(user, params, [:confirmation_pending, :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]) +  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) diff --git a/lib/pleroma/user/query.ex b/lib/pleroma/user/query.ex index 66ffe9090..45553cb6c 100644 --- a/lib/pleroma/user/query.ex +++ b/lib/pleroma/user/query.ex @@ -42,6 +42,7 @@ defmodule Pleroma.User.Query do              external: boolean(),              active: boolean(),              deactivated: boolean(), +            need_approval: boolean(),              is_admin: boolean(),              is_moderator: boolean(),              super_users: boolean(), @@ -146,6 +147,10 @@ defmodule Pleroma.User.Query do      |> where([u], not is_nil(u.nickname))    end +  defp compose_query({:need_approval, _}, query) do +    where(query, [u], u.approval_pending) +  end +    defp compose_query({:followers, %User{id: id}}, query) do      query      |> where([u], u.id != ^id) 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 5101e28d6..aa2af1ab5 100644 --- a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex @@ -44,6 +44,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do             :user_toggle_activation,             :user_activate,             :user_deactivate, +           :user_approve,             :tag_users,             :untag_users,             :right_add, @@ -303,6 +304,21 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do      |> render("index.json", %{users: Keyword.values(updated_users)})    end +  def user_approve(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do +    users = Enum.map(nicknames, &User.get_cached_by_nickname/1) +    {:ok, updated_users} = User.approve(users) + +    ModerationLog.insert_log(%{ +      actor: admin, +      subject: users, +      action: "approve" +    }) + +    conn +    |> put_view(AccountView) +    |> render("index.json", %{users: updated_users}) +  end +    def tag_users(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames, "tags" => tags}) do      with {:ok, _} <- User.tag(nicknames, tags) do        ModerationLog.insert_log(%{ @@ -354,7 +370,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do      end    end -  @filters ~w(local external active deactivated is_admin is_moderator) +  @filters ~w(local external active deactivated need_approval is_admin is_moderator)    @spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{}    defp maybe_parse_filters(filters) when is_nil(filters) or filters == "", do: %{} diff --git a/lib/pleroma/web/admin_api/views/account_view.ex b/lib/pleroma/web/admin_api/views/account_view.ex index 88fbb5315..333e72e42 100644 --- a/lib/pleroma/web/admin_api/views/account_view.ex +++ b/lib/pleroma/web/admin_api/views/account_view.ex @@ -77,7 +77,9 @@ defmodule Pleroma.Web.AdminAPI.AccountView do        "roles" => User.roles(user),        "tags" => user.tags || [],        "confirmation_pending" => user.confirmation_pending, -      "url" => user.uri || user.ap_id +      "approval_pending" => user.approval_pending, +      "url" => user.uri || user.ap_id, +      "registration_reason" => user.registration_reason      }    end diff --git a/lib/pleroma/web/mastodon_api/views/instance_view.ex b/lib/pleroma/web/mastodon_api/views/instance_view.ex index cd3bc7f00..ea2d3aa9c 100644 --- a/lib/pleroma/web/mastodon_api/views/instance_view.ex +++ b/lib/pleroma/web/mastodon_api/views/instance_view.ex @@ -26,6 +26,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do        thumbnail: Keyword.get(instance, :instance_thumbnail),        languages: ["en"],        registrations: Keyword.get(instance, :registrations_open), +      approval_required: Keyword.get(instance, :account_approval_required),        # Extra (not present in Mastodon):        max_toot_chars: Keyword.get(instance, :limit),        poll_limits: Keyword.get(instance, :poll_limits), diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index 7683589cf..61fe81d33 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -337,6 +337,16 @@ defmodule Pleroma.Web.OAuth.OAuthController do      )    end +  defp handle_token_exchange_error(%Plug.Conn{} = conn, {:account_status, :approval_pending}) do +    render_error( +      conn, +      :forbidden, +      "Your account is awaiting approval.", +      %{}, +      "awaiting_approval" +    ) +  end +    defp handle_token_exchange_error(%Plug.Conn{} = conn, _error) do      render_invalid_credentials_error(conn)    end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 386308362..c6433cc53 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -138,6 +138,7 @@ defmodule Pleroma.Web.Router do      patch("/users/:nickname/toggle_activation", AdminAPIController, :user_toggle_activation)      patch("/users/activate", AdminAPIController, :user_activate)      patch("/users/deactivate", AdminAPIController, :user_deactivate) +    patch("/users/approve", AdminAPIController, :user_approve)      put("/users/tag", AdminAPIController, :tag_users)      delete("/users/tag", AdminAPIController, :untag_users) diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex index 5cfb385ac..2294d9d0d 100644 --- a/lib/pleroma/web/twitter_api/twitter_api.ex +++ b/lib/pleroma/web/twitter_api/twitter_api.ex @@ -19,6 +19,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do        |> Map.put(:nickname, params[:username])        |> Map.put(:name, Map.get(params, :fullname, params[:username]))        |> Map.put(:password_confirmation, params[:password]) +      |> Map.put(:registration_reason, params[:reason])      if Pleroma.Config.get([:instance, :registrations_open]) do        create_user(params, opts) @@ -44,6 +45,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do      case User.register(changeset) do        {:ok, user} -> +        maybe_notify_admins(user)          {:ok, user}        {:error, changeset} -> @@ -56,6 +58,18 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do      end    end +  defp maybe_notify_admins(%User{} = account) do +    if Pleroma.Config.get([:instance, :account_approval_required]) do +      User.all_superusers() +      |> Enum.filter(fn user -> not is_nil(user.email) end) +      |> Enum.each(fn superuser -> +        superuser +        |> Pleroma.Emails.AdminEmail.new_unapproved_registration(account) +        |> Pleroma.Emails.Mailer.deliver_async() +      end) +    end +  end +    def password_reset(nickname_or_email) do      with true <- is_binary(nickname_or_email),           %User{local: true, email: email} = user when is_binary(email) <- | 
