Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into frontend-bundles-admin
This commit is contained in:
commit
dc36d6e9d2
35 changed files with 721 additions and 40 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -27,6 +27,8 @@ erl_crash.dump
|
|||
# variables.
|
||||
/config/*.secret.exs
|
||||
/config/generated_config.exs
|
||||
/config/*.env
|
||||
|
||||
|
||||
# Database setup file, some may forget to delete it
|
||||
/config/setup_db.psql
|
||||
|
|
|
@ -68,6 +68,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
- Support pagination in emoji packs API (for packs and for files in pack)
|
||||
- Support for viewing instances favicons next to posts and accounts
|
||||
- Added Pleroma.Upload.Filter.Exiftool as an alternate EXIF stripping mechanism targeting GPS/location metadata.
|
||||
- "By approval" registrations mode.
|
||||
- Configuration: Added `:welcome` settings for the welcome message to newly registered users.
|
||||
|
||||
<details>
|
||||
|
|
|
@ -205,6 +205,7 @@ config :pleroma, :instance,
|
|||
registrations_open: true,
|
||||
invites_enabled: false,
|
||||
account_activation_required: false,
|
||||
account_approval_required: false,
|
||||
federating: true,
|
||||
federation_incoming_replies_max_depth: 100,
|
||||
federation_reachability_timeout_days: 7,
|
||||
|
@ -237,6 +238,7 @@ config :pleroma, :instance,
|
|||
max_remote_account_fields: 20,
|
||||
account_field_name_length: 512,
|
||||
account_field_value_length: 2048,
|
||||
registration_reason_length: 500,
|
||||
external_user_synchronization: true,
|
||||
extended_nickname_format: true,
|
||||
cleanup_attachments: false,
|
||||
|
|
|
@ -661,6 +661,11 @@ config :pleroma, :config_description, [
|
|||
type: :boolean,
|
||||
description: "Require users to confirm their emails before signing in"
|
||||
},
|
||||
%{
|
||||
key: :account_approval_required,
|
||||
type: :boolean,
|
||||
description: "Require users to be manually approved by an admin before signing in"
|
||||
},
|
||||
%{
|
||||
key: :federating,
|
||||
type: :boolean,
|
||||
|
@ -874,6 +879,14 @@ config :pleroma, :config_description, [
|
|||
2048
|
||||
]
|
||||
},
|
||||
%{
|
||||
key: :registration_reason_length,
|
||||
type: :integer,
|
||||
description: "Maximum registration reason length. Default: 500.",
|
||||
suggestions: [
|
||||
500
|
||||
]
|
||||
},
|
||||
%{
|
||||
key: :external_user_synchronization,
|
||||
type: :boolean,
|
||||
|
|
|
@ -19,6 +19,7 @@ Configuration options:
|
|||
- `local`: only local users
|
||||
- `external`: only external users
|
||||
- `active`: only active users
|
||||
- `need_approval`: only unapproved users
|
||||
- `deactivated`: only deactivated users
|
||||
- `is_admin`: users with admin role
|
||||
- `is_moderator`: users with moderator role
|
||||
|
@ -46,7 +47,10 @@ Configuration options:
|
|||
"local": bool,
|
||||
"tags": array,
|
||||
"avatar": string,
|
||||
"display_name": string
|
||||
"display_name": string,
|
||||
"confirmation_pending": bool,
|
||||
"approval_pending": bool,
|
||||
"registration_reason": string,
|
||||
},
|
||||
...
|
||||
]
|
||||
|
@ -242,6 +246,24 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
|||
}
|
||||
```
|
||||
|
||||
## `PATCH /api/pleroma/admin/users/approve`
|
||||
|
||||
### Approve user
|
||||
|
||||
- Params:
|
||||
- `nicknames`: nicknames array
|
||||
- Response:
|
||||
|
||||
```json
|
||||
{
|
||||
users: [
|
||||
{
|
||||
// user object
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## `GET /api/pleroma/admin/users/:nickname_or_id`
|
||||
|
||||
### Retrive the details of a user
|
||||
|
|
9
docs/administration/CLI_tasks/release_environments.md
Normal file
9
docs/administration/CLI_tasks/release_environments.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Generate release environment file
|
||||
|
||||
```sh tab="OTP"
|
||||
./bin/pleroma_ctl release_env gen
|
||||
```
|
||||
|
||||
```sh tab="From Source"
|
||||
mix pleroma.release_env gen
|
||||
```
|
|
@ -33,6 +33,7 @@ To add configuration to your config file, you can copy it from the base config.
|
|||
* `registrations_open`: Enable registrations for anyone, invitations can be enabled when false.
|
||||
* `invites_enabled`: Enable user invitations for admins (depends on `registrations_open: false`).
|
||||
* `account_activation_required`: Require users to confirm their emails before signing in.
|
||||
* `account_approval_required`: Require users to be manually approved by an admin before signing in.
|
||||
* `federating`: Enable federation with other instances.
|
||||
* `federation_incoming_replies_max_depth`: Max. depth of reply-to activities fetching on incoming federation, to prevent out-of-memory situations while fetching very long threads. If set to `nil`, threads of any depth will be fetched. Lower this value if you experience out-of-memory crashes.
|
||||
* `federation_reachability_timeout_days`: Timeout (in days) of each external federation target being unreachable prior to pausing federating to it.
|
||||
|
@ -58,6 +59,7 @@ To add configuration to your config file, you can copy it from the base config.
|
|||
* `max_remote_account_fields`: The maximum number of custom fields in the remote user profile (default: `20`).
|
||||
* `account_field_name_length`: An account field name maximum length (default: `512`).
|
||||
* `account_field_value_length`: An account field value maximum length (default: `2048`).
|
||||
* `registration_reason_length`: Maximum registration reason length (default: `500`).
|
||||
* `external_user_synchronization`: Enabling following/followers counters synchronization for external users.
|
||||
* `cleanup_attachments`: Remove attachments along with statuses. Does not affect duplicate files and attachments without status. Enabling this will increase load to database when deleting statuses on larger instances.
|
||||
|
||||
|
|
|
@ -121,6 +121,9 @@ chown -R pleroma /etc/pleroma
|
|||
# Run the config generator
|
||||
su pleroma -s $SHELL -lc "./bin/pleroma_ctl instance gen --output /etc/pleroma/config.exs --output-psql /tmp/setup_db.psql"
|
||||
|
||||
# Run the environment file generator.
|
||||
su pleroma -s $SHELL -lc "./bin/pleroma_ctl release_env gen"
|
||||
|
||||
# Create the postgres database
|
||||
su postgres -s $SHELL -lc "psql -f /tmp/setup_db.psql"
|
||||
|
||||
|
@ -131,7 +134,7 @@ su pleroma -s $SHELL -lc "./bin/pleroma_ctl migrate"
|
|||
# su pleroma -s $SHELL -lc "./bin/pleroma_ctl migrate --migrations-path priv/repo/optional_migrations/rum_indexing/"
|
||||
|
||||
# Start the instance to verify that everything is working as expected
|
||||
su pleroma -s $SHELL -lc "./bin/pleroma daemon"
|
||||
su pleroma -s $SHELL -lc "export $(cat /opt/pleroma/config/pleroma.env); ./bin/pleroma daemon"
|
||||
|
||||
# Wait for about 20 seconds and query the instance endpoint, if it shows your uri, name and email correctly, you are configured correctly
|
||||
sleep 20 && curl http://localhost:4000/api/v1/instance
|
||||
|
@ -200,6 +203,7 @@ rc-update add pleroma
|
|||
# Copy the service into a proper directory
|
||||
cp /opt/pleroma/installation/pleroma.service /etc/systemd/system/pleroma.service
|
||||
|
||||
|
||||
# Start pleroma and enable it on boot
|
||||
systemctl start pleroma
|
||||
systemctl enable pleroma
|
||||
|
@ -275,4 +279,3 @@ This will create an account withe the username of 'joeuser' with the email addre
|
|||
## Questions
|
||||
|
||||
Questions about the installation or didn’t it work as it should be, ask in [#pleroma:matrix.org](https://matrix.heldscal.la/#/room/#freenode_#pleroma:matrix.org) or IRC Channel **#pleroma** on **Freenode**.
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ pidfile="/var/run/pleroma.pid"
|
|||
directory=/opt/pleroma
|
||||
healthcheck_delay=60
|
||||
healthcheck_timer=30
|
||||
export $(cat /opt/pleroma/config/pleroma.env)
|
||||
|
||||
: ${pleroma_port:-4000}
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@ Environment="MIX_ENV=prod"
|
|||
Environment="HOME=/var/lib/pleroma"
|
||||
; Path to the folder containing the Pleroma installation.
|
||||
WorkingDirectory=/opt/pleroma
|
||||
; Path to the environment file. the file contains RELEASE_COOKIE and etc
|
||||
EnvironmentFile=/opt/pleroma/config/pleroma.env
|
||||
; Path to the Mix binary.
|
||||
ExecStart=/usr/bin/mix phx.server
|
||||
|
||||
|
|
76
lib/mix/tasks/pleroma/release_env.ex
Normal file
76
lib/mix/tasks/pleroma/release_env.ex
Normal file
|
@ -0,0 +1,76 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Mix.Tasks.Pleroma.ReleaseEnv do
|
||||
use Mix.Task
|
||||
import Mix.Pleroma
|
||||
|
||||
@shortdoc "Generate Pleroma environment file."
|
||||
@moduledoc File.read!("docs/administration/CLI_tasks/release_environments.md")
|
||||
|
||||
def run(["gen" | rest]) do
|
||||
{options, [], []} =
|
||||
OptionParser.parse(
|
||||
rest,
|
||||
strict: [
|
||||
force: :boolean,
|
||||
path: :string
|
||||
],
|
||||
aliases: [
|
||||
p: :path,
|
||||
f: :force
|
||||
]
|
||||
)
|
||||
|
||||
file_path =
|
||||
get_option(
|
||||
options,
|
||||
:path,
|
||||
"Environment file path",
|
||||
"./config/pleroma.env"
|
||||
)
|
||||
|
||||
env_path = Path.expand(file_path)
|
||||
|
||||
proceed? =
|
||||
if File.exists?(env_path) do
|
||||
get_option(
|
||||
options,
|
||||
:force,
|
||||
"Environment file already exists. Do you want to overwrite the #{env_path} file? (y/n)",
|
||||
"n"
|
||||
) === "y"
|
||||
else
|
||||
true
|
||||
end
|
||||
|
||||
if proceed? do
|
||||
case do_generate(env_path) do
|
||||
{:error, reason} ->
|
||||
shell_error(
|
||||
File.Error.message(%{action: "write to file", reason: reason, path: env_path})
|
||||
)
|
||||
|
||||
_ ->
|
||||
shell_info("\nThe file generated: #{env_path}.\n")
|
||||
|
||||
shell_info("""
|
||||
WARNING: before start pleroma app please make sure to make the file read-only and non-modifiable.
|
||||
Example:
|
||||
chmod 0444 #{file_path}
|
||||
chattr +i #{file_path}
|
||||
""")
|
||||
end
|
||||
else
|
||||
shell_info("\nThe file is exist. #{env_path}.\n")
|
||||
end
|
||||
end
|
||||
|
||||
def do_generate(path) do
|
||||
content = "RELEASE_COOKIE=#{Base.encode32(:crypto.strong_rand_bytes(32))}"
|
||||
|
||||
File.mkdir_p!(Path.dirname(path))
|
||||
File.write(path, content)
|
||||
end
|
||||
end
|
|
@ -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
|
||||
|
|
|
@ -409,6 +409,17 @@ defmodule Pleroma.ModerationLog do
|
|||
"@#{actor_nickname} deactivated 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},
|
||||
"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: %{
|
||||
|
|
|
@ -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,9 +1552,14 @@ defmodule Pleroma.User do
|
|||
defp delete_or_deactivate(%User{local: true} = user) do
|
||||
status = account_status(user)
|
||||
|
||||
if status == :confirmation_pending do
|
||||
case status do
|
||||
:confirmation_pending ->
|
||||
delete_and_invalidate_cache(user)
|
||||
else
|
||||
|
||||
:approval_pending ->
|
||||
delete_and_invalidate_cache(user)
|
||||
|
||||
_ ->
|
||||
user
|
||||
|> change(%{deactivated: true, email: nil})
|
||||
|> update_and_set_cache()
|
||||
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -27,7 +27,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrepended do
|
|||
|
||||
def filter_by_summary(_in_reply_to, child), do: child
|
||||
|
||||
def filter(%{"type" => "Create", "object" => child_object} = object) do
|
||||
def filter(%{"type" => "Create", "object" => child_object} = object)
|
||||
when is_map(child_object) do
|
||||
child =
|
||||
child_object["inReplyTo"]
|
||||
|> Object.normalize(child_object["inReplyTo"])
|
||||
|
|
|
@ -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: %{}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ defmodule Pleroma.Web.Feed.UserController do
|
|||
"atom"
|
||||
end
|
||||
|
||||
with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do
|
||||
with {_, %User{local: true} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do
|
||||
activities =
|
||||
%{
|
||||
type: ["Create"],
|
||||
|
@ -71,6 +71,7 @@ defmodule Pleroma.Web.Feed.UserController do
|
|||
render_error(conn, :not_found, "Not found")
|
||||
end
|
||||
|
||||
def errors(conn, {:fetch_user, %User{local: false}}), do: errors(conn, {:error, :not_found})
|
||||
def errors(conn, {:fetch_user, nil}), do: errors(conn, {:error, :not_found})
|
||||
|
||||
def errors(conn, _) do
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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) <-
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
defmodule Pleroma.Repo.Migrations.AddApprovalFieldsToUsers do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
alter table(:users) do
|
||||
add(:approval_pending, :boolean)
|
||||
add(:registration_reason, :text)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -46,4 +46,24 @@ defmodule Pleroma.Emails.AdminEmailTest do
|
|||
assert res.to == [{to_user.name, to_user.email}]
|
||||
assert res.from == {config[:name], config[:notify_email]}
|
||||
end
|
||||
|
||||
test "new unapproved registration email" do
|
||||
config = Pleroma.Config.get(:instance)
|
||||
to_user = insert(:user)
|
||||
account = insert(:user, registration_reason: "Plz let me in")
|
||||
|
||||
res = AdminEmail.new_unapproved_registration(to_user, account)
|
||||
|
||||
account_url = Helpers.user_feed_url(Pleroma.Web.Endpoint, :feed_redirect, account.id)
|
||||
|
||||
assert res.to == [{to_user.name, to_user.email}]
|
||||
assert res.from == {config[:name], config[:notify_email]}
|
||||
assert res.subject == "New account up for review on #{config[:name]} (@#{account.nickname})"
|
||||
|
||||
assert res.html_body == """
|
||||
<p>New account for review: <a href="#{account_url}">@#{account.nickname}</a></p>
|
||||
<blockquote>Plz let me in</blockquote>
|
||||
<a href="http://localhost:4001/pleroma/admin">Visit AdminFE</a>
|
||||
"""
|
||||
end
|
||||
end
|
||||
|
|
30
test/tasks/release_env_test.exs
Normal file
30
test/tasks/release_env_test.exs
Normal file
|
@ -0,0 +1,30 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Mix.Tasks.Pleroma.ReleaseEnvTest do
|
||||
use ExUnit.Case
|
||||
import ExUnit.CaptureIO, only: [capture_io: 1]
|
||||
|
||||
@path "config/pleroma.test.env"
|
||||
|
||||
def do_clean do
|
||||
if File.exists?(@path) do
|
||||
File.rm_rf(@path)
|
||||
end
|
||||
end
|
||||
|
||||
setup do
|
||||
do_clean()
|
||||
on_exit(fn -> do_clean() end)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "generate pleroma.env" do
|
||||
assert capture_io(fn ->
|
||||
Mix.Tasks.Pleroma.ReleaseEnv.run(["gen", "--path", @path, "--force"])
|
||||
end) =~ "The file generated"
|
||||
|
||||
assert File.read!(@path) =~ "RELEASE_COOKIE="
|
||||
end
|
||||
end
|
|
@ -543,6 +543,46 @@ defmodule Pleroma.UserTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "user registration, with :account_approval_required" do
|
||||
@full_user_data %{
|
||||
bio: "A guy",
|
||||
name: "my name",
|
||||
nickname: "nick",
|
||||
password: "test",
|
||||
password_confirmation: "test",
|
||||
email: "email@example.com",
|
||||
registration_reason: "I'm a cool guy :)"
|
||||
}
|
||||
setup do: clear_config([:instance, :account_approval_required], true)
|
||||
|
||||
test "it creates unapproved user" do
|
||||
changeset = User.register_changeset(%User{}, @full_user_data)
|
||||
assert changeset.valid?
|
||||
|
||||
{:ok, user} = Repo.insert(changeset)
|
||||
|
||||
assert user.approval_pending
|
||||
assert user.registration_reason == "I'm a cool guy :)"
|
||||
end
|
||||
|
||||
test "it restricts length of registration reason" do
|
||||
reason_limit = Pleroma.Config.get([:instance, :registration_reason_length])
|
||||
|
||||
assert is_integer(reason_limit)
|
||||
|
||||
params =
|
||||
@full_user_data
|
||||
|> Map.put(
|
||||
:registration_reason,
|
||||
"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)
|
||||
|
||||
refute changeset.valid?
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_or_fetch/1" do
|
||||
test "gets an existing user by nickname" do
|
||||
user = insert(:user)
|
||||
|
@ -1208,6 +1248,31 @@ defmodule Pleroma.UserTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "approve" do
|
||||
test "approves a user" do
|
||||
user = insert(:user, approval_pending: true)
|
||||
assert true == user.approval_pending
|
||||
{:ok, user} = User.approve(user)
|
||||
assert false == user.approval_pending
|
||||
end
|
||||
|
||||
test "approves a list of users" do
|
||||
unapproved_users = [
|
||||
insert(:user, approval_pending: true),
|
||||
insert(:user, approval_pending: true),
|
||||
insert(:user, approval_pending: true)
|
||||
]
|
||||
|
||||
{:ok, users} = User.approve(unapproved_users)
|
||||
|
||||
assert Enum.count(users) == 3
|
||||
|
||||
Enum.each(users, fn user ->
|
||||
assert false == user.approval_pending
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete" do
|
||||
setup do
|
||||
{:ok, user} = insert(:user) |> User.set_cache()
|
||||
|
@ -1295,6 +1360,17 @@ defmodule Pleroma.UserTest do
|
|||
end
|
||||
end
|
||||
|
||||
test "delete/1 when approval is pending deletes the user" do
|
||||
user = insert(:user, approval_pending: true)
|
||||
{:ok, user: user}
|
||||
|
||||
{:ok, job} = User.delete(user)
|
||||
{:ok, _} = ObanHelpers.perform(job)
|
||||
|
||||
refute User.get_cached_by_id(user.id)
|
||||
refute User.get_by_id(user.id)
|
||||
end
|
||||
|
||||
test "get_public_key_for_ap_id fetches a user that's not in the db" do
|
||||
assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
|
||||
end
|
||||
|
@ -1369,6 +1445,14 @@ defmodule Pleroma.UserTest do
|
|||
user = insert(:user, local: true, confirmation_pending: false, deactivated: true)
|
||||
assert User.account_status(user) == :deactivated
|
||||
end
|
||||
|
||||
test "returns :approval_pending for unapproved user" do
|
||||
user = insert(:user, local: true, approval_pending: true)
|
||||
assert User.account_status(user) == :approval_pending
|
||||
|
||||
user = insert(:user, local: true, confirmation_pending: true, approval_pending: true)
|
||||
assert User.account_status(user) == :approval_pending
|
||||
end
|
||||
end
|
||||
|
||||
describe "superuser?/1" do
|
||||
|
|
|
@ -78,5 +78,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrependedTest do
|
|||
assert {:ok, res} = EnsureRePrepended.filter(message)
|
||||
assert res == message
|
||||
end
|
||||
|
||||
test "it skips if the object is only a reference" do
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => "somereference"
|
||||
}
|
||||
|
||||
assert {:ok, res} = EnsureRePrepended.filter(message)
|
||||
assert res == message
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -349,7 +349,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(user.name || user.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => user.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => user.ap_id,
|
||||
"registration_reason" => nil
|
||||
}
|
||||
|
||||
assert expected == json_response(conn, 200)
|
||||
|
@ -613,6 +615,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
describe "GET /api/pleroma/admin/users" do
|
||||
test "renders users array for the first page", %{conn: conn, admin: admin} do
|
||||
user = insert(:user, local: false, tags: ["foo", "bar"])
|
||||
user2 = insert(:user, approval_pending: true, registration_reason: "I'm a chill dude")
|
||||
|
||||
conn = get(conn, "/api/pleroma/admin/users?page=1")
|
||||
|
||||
users =
|
||||
|
@ -627,7 +631,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(admin) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(admin.name || admin.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => admin.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => admin.ap_id,
|
||||
"registration_reason" => nil
|
||||
},
|
||||
%{
|
||||
"deactivated" => user.deactivated,
|
||||
|
@ -639,13 +645,29 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(user.name || user.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => user.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => user.ap_id,
|
||||
"registration_reason" => nil
|
||||
},
|
||||
%{
|
||||
"deactivated" => user2.deactivated,
|
||||
"id" => user2.id,
|
||||
"nickname" => user2.nickname,
|
||||
"roles" => %{"admin" => false, "moderator" => false},
|
||||
"local" => true,
|
||||
"tags" => [],
|
||||
"avatar" => User.avatar_url(user2) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(user2.name || user2.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"approval_pending" => true,
|
||||
"url" => user2.ap_id,
|
||||
"registration_reason" => "I'm a chill dude"
|
||||
}
|
||||
]
|
||||
|> Enum.sort_by(& &1["nickname"])
|
||||
|
||||
assert json_response(conn, 200) == %{
|
||||
"count" => 2,
|
||||
"count" => 3,
|
||||
"page_size" => 50,
|
||||
"users" => users
|
||||
}
|
||||
|
@ -712,7 +734,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(user.name || user.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => user.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => user.ap_id,
|
||||
"registration_reason" => nil
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -738,7 +762,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(user.name || user.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => user.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => user.ap_id,
|
||||
"registration_reason" => nil
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -764,7 +790,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(user.name || user.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => user.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => user.ap_id,
|
||||
"registration_reason" => nil
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -790,7 +818,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(user.name || user.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => user.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => user.ap_id,
|
||||
"registration_reason" => nil
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -816,7 +846,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(user.name || user.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => user.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => user.ap_id,
|
||||
"registration_reason" => nil
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -842,7 +874,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(user.name || user.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => user.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => user.ap_id,
|
||||
"registration_reason" => nil
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -863,7 +897,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(user2) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(user2.name || user2.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => user2.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => user2.ap_id,
|
||||
"registration_reason" => nil
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -896,7 +932,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(user.name || user.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => user.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => user.ap_id,
|
||||
"registration_reason" => nil
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -922,7 +960,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(user.name || user.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => user.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => user.ap_id,
|
||||
"registration_reason" => nil
|
||||
},
|
||||
%{
|
||||
"deactivated" => admin.deactivated,
|
||||
|
@ -934,7 +974,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(admin) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(admin.name || admin.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => admin.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => admin.ap_id,
|
||||
"registration_reason" => nil
|
||||
},
|
||||
%{
|
||||
"deactivated" => false,
|
||||
|
@ -946,7 +988,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(old_admin) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => old_admin.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => old_admin.ap_id,
|
||||
"registration_reason" => nil
|
||||
}
|
||||
]
|
||||
|> Enum.sort_by(& &1["nickname"])
|
||||
|
@ -958,6 +1002,44 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
}
|
||||
end
|
||||
|
||||
test "only unapproved users", %{conn: conn} do
|
||||
user =
|
||||
insert(:user,
|
||||
nickname: "sadboy",
|
||||
approval_pending: true,
|
||||
registration_reason: "Plz let me in!"
|
||||
)
|
||||
|
||||
insert(:user, nickname: "happyboy", approval_pending: false)
|
||||
|
||||
conn = get(conn, "/api/pleroma/admin/users?filters=need_approval")
|
||||
|
||||
users =
|
||||
[
|
||||
%{
|
||||
"deactivated" => user.deactivated,
|
||||
"id" => user.id,
|
||||
"nickname" => user.nickname,
|
||||
"roles" => %{"admin" => false, "moderator" => false},
|
||||
"local" => true,
|
||||
"tags" => [],
|
||||
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(user.name || user.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"approval_pending" => true,
|
||||
"url" => user.ap_id,
|
||||
"registration_reason" => "Plz let me in!"
|
||||
}
|
||||
]
|
||||
|> Enum.sort_by(& &1["nickname"])
|
||||
|
||||
assert json_response(conn, 200) == %{
|
||||
"count" => 1,
|
||||
"page_size" => 50,
|
||||
"users" => users
|
||||
}
|
||||
end
|
||||
|
||||
test "load only admins", %{conn: conn, admin: admin} do
|
||||
second_admin = insert(:user, is_admin: true)
|
||||
insert(:user)
|
||||
|
@ -977,7 +1059,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(admin) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(admin.name || admin.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => admin.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => admin.ap_id,
|
||||
"registration_reason" => nil
|
||||
},
|
||||
%{
|
||||
"deactivated" => false,
|
||||
|
@ -989,7 +1073,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(second_admin) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => second_admin.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => second_admin.ap_id,
|
||||
"registration_reason" => nil
|
||||
}
|
||||
]
|
||||
|> Enum.sort_by(& &1["nickname"])
|
||||
|
@ -1022,7 +1108,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(moderator) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(moderator.name || moderator.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => moderator.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => moderator.ap_id,
|
||||
"registration_reason" => nil
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1048,7 +1136,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(user1) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(user1.name || user1.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => user1.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => user1.ap_id,
|
||||
"registration_reason" => nil
|
||||
},
|
||||
%{
|
||||
"deactivated" => false,
|
||||
|
@ -1060,7 +1150,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(user2) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(user2.name || user2.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => user2.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => user2.ap_id,
|
||||
"registration_reason" => nil
|
||||
}
|
||||
]
|
||||
|> Enum.sort_by(& &1["nickname"])
|
||||
|
@ -1100,7 +1192,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(user.name || user.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => user.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => user.ap_id,
|
||||
"registration_reason" => nil
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1125,7 +1219,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(admin) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(admin.name || admin.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => admin.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => admin.ap_id,
|
||||
"registration_reason" => nil
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1172,6 +1268,26 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}"
|
||||
end
|
||||
|
||||
test "PATCH /api/pleroma/admin/users/approve", %{admin: admin, conn: conn} do
|
||||
user_one = insert(:user, approval_pending: true)
|
||||
user_two = insert(:user, approval_pending: true)
|
||||
|
||||
conn =
|
||||
patch(
|
||||
conn,
|
||||
"/api/pleroma/admin/users/approve",
|
||||
%{nicknames: [user_one.nickname, user_two.nickname]}
|
||||
)
|
||||
|
||||
response = json_response(conn, 200)
|
||||
assert Enum.map(response["users"], & &1["approval_pending"]) == [false, false]
|
||||
|
||||
log_entry = Repo.one(ModerationLog)
|
||||
|
||||
assert ModerationLog.get_log_entry_message(log_entry) ==
|
||||
"@#{admin.nickname} approved users: @#{user_one.nickname}, @#{user_two.nickname}"
|
||||
end
|
||||
|
||||
test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admin, conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
|
@ -1188,7 +1304,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
|
||||
"display_name" => HTML.strip_tags(user.name || user.nickname),
|
||||
"confirmation_pending" => false,
|
||||
"url" => user.ap_id
|
||||
"approval_pending" => false,
|
||||
"url" => user.ap_id,
|
||||
"registration_reason" => nil
|
||||
}
|
||||
|
||||
log_entry = Repo.one(ModerationLog)
|
||||
|
|
|
@ -166,5 +166,16 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do
|
|||
assert total == 3
|
||||
assert count == 1
|
||||
end
|
||||
|
||||
test "it returns unapproved user" do
|
||||
unapproved = insert(:user, approval_pending: true)
|
||||
insert(:user)
|
||||
insert(:user)
|
||||
|
||||
{:ok, _results, total} = Search.user()
|
||||
{:ok, [^unapproved], count} = Search.user(%{need_approval: true})
|
||||
assert total == 3
|
||||
assert count == 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -181,6 +181,17 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
|
|||
|
||||
assert activity_titles == ['public', 'unlisted']
|
||||
end
|
||||
|
||||
test "returns 404 when the user is remote", %{conn: conn} do
|
||||
user = insert(:user, local: false)
|
||||
|
||||
{:ok, _} = CommonAPI.post(user, %{status: "test"})
|
||||
|
||||
assert conn
|
||||
|> put_req_header("accept", "application/atom+xml")
|
||||
|> get(user_feed_path(conn, :feed, user.nickname))
|
||||
|> response(404)
|
||||
end
|
||||
end
|
||||
|
||||
# Note: see ActivityPubControllerTest for JSON format tests
|
||||
|
|
|
@ -904,6 +904,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
end
|
||||
|
||||
setup do: clear_config([:instance, :account_activation_required])
|
||||
setup do: clear_config([:instance, :account_approval_required])
|
||||
|
||||
test "Account registration via Application", %{conn: conn} do
|
||||
conn =
|
||||
|
@ -968,6 +969,75 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
assert token_from_db.user.confirmation_pending
|
||||
end
|
||||
|
||||
test "Account registration via app with account_approval_required", %{conn: conn} do
|
||||
Pleroma.Config.put([:instance, :account_approval_required], true)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/apps", %{
|
||||
client_name: "client_name",
|
||||
redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
|
||||
scopes: "read, write, follow"
|
||||
})
|
||||
|
||||
assert %{
|
||||
"client_id" => client_id,
|
||||
"client_secret" => client_secret,
|
||||
"id" => _,
|
||||
"name" => "client_name",
|
||||
"redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
|
||||
"vapid_key" => _,
|
||||
"website" => nil
|
||||
} = json_response_and_validate_schema(conn, 200)
|
||||
|
||||
conn =
|
||||
post(conn, "/oauth/token", %{
|
||||
grant_type: "client_credentials",
|
||||
client_id: client_id,
|
||||
client_secret: client_secret
|
||||
})
|
||||
|
||||
assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
|
||||
json_response(conn, 200)
|
||||
|
||||
assert token
|
||||
token_from_db = Repo.get_by(Token, token: token)
|
||||
assert token_from_db
|
||||
assert refresh
|
||||
assert scope == "read write follow"
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> put_req_header("content-type", "multipart/form-data")
|
||||
|> put_req_header("authorization", "Bearer " <> token)
|
||||
|> post("/api/v1/accounts", %{
|
||||
username: "lain",
|
||||
email: "lain@example.org",
|
||||
password: "PlzDontHackLain",
|
||||
bio: "Test Bio",
|
||||
agreement: true,
|
||||
reason: "I'm a cool dude, bro"
|
||||
})
|
||||
|
||||
%{
|
||||
"access_token" => token,
|
||||
"created_at" => _created_at,
|
||||
"scope" => ^scope,
|
||||
"token_type" => "Bearer"
|
||||
} = json_response_and_validate_schema(conn, 200)
|
||||
|
||||
token_from_db = Repo.get_by(Token, token: token)
|
||||
assert token_from_db
|
||||
token_from_db = Repo.preload(token_from_db, :user)
|
||||
assert token_from_db.user
|
||||
|
||||
assert token_from_db.user.confirmation_pending
|
||||
assert token_from_db.user.approval_pending
|
||||
|
||||
assert token_from_db.user.registration_reason == "I'm a cool dude, bro"
|
||||
end
|
||||
|
||||
test "returns error when user already registred", %{conn: conn, valid_params: valid_params} do
|
||||
_user = insert(:user, email: "lain@example.org")
|
||||
app_token = insert(:oauth_token, user: nil)
|
||||
|
|
|
@ -27,6 +27,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do
|
|||
"thumbnail" => _,
|
||||
"languages" => _,
|
||||
"registrations" => _,
|
||||
"approval_required" => _,
|
||||
"poll_limits" => _,
|
||||
"upload_limit" => _,
|
||||
"avatar_upload_limit" => _,
|
||||
|
|
|
@ -19,7 +19,10 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
|
|||
key: "_test",
|
||||
signing_salt: "cooldude"
|
||||
]
|
||||
setup do: clear_config([:instance, :account_activation_required])
|
||||
setup do
|
||||
clear_config([:instance, :account_activation_required])
|
||||
clear_config([:instance, :account_approval_required])
|
||||
end
|
||||
|
||||
describe "in OAuth consumer mode, " do
|
||||
setup do
|
||||
|
@ -995,6 +998,30 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
|
|||
}
|
||||
end
|
||||
|
||||
test "rejects token exchange for valid credentials belonging to an unapproved user" do
|
||||
password = "testpassword"
|
||||
|
||||
user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt(password), approval_pending: true)
|
||||
|
||||
refute Pleroma.User.account_status(user) == :active
|
||||
|
||||
app = insert(:oauth_app)
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> post("/oauth/token", %{
|
||||
"grant_type" => "password",
|
||||
"username" => user.nickname,
|
||||
"password" => password,
|
||||
"client_id" => app.client_id,
|
||||
"client_secret" => app.client_secret
|
||||
})
|
||||
|
||||
assert resp = json_response(conn, 403)
|
||||
assert %{"error" => _} = resp
|
||||
refute Map.has_key?(resp, "access_token")
|
||||
end
|
||||
|
||||
test "rejects an invalid authorization code" do
|
||||
app = insert(:oauth_app)
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
import Pleroma.Factory
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.User
|
||||
|
@ -79,6 +79,42 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
|
|||
)
|
||||
end
|
||||
|
||||
test "it sends an admin email if :account_approval_required is specified in instance config" do
|
||||
admin = insert(:user, is_admin: true)
|
||||
setting = Pleroma.Config.get([:instance, :account_approval_required])
|
||||
|
||||
unless setting do
|
||||
Pleroma.Config.put([:instance, :account_approval_required], true)
|
||||
on_exit(fn -> Pleroma.Config.put([:instance, :account_approval_required], setting) end)
|
||||
end
|
||||
|
||||
data = %{
|
||||
:username => "lain",
|
||||
:email => "lain@wired.jp",
|
||||
:fullname => "lain iwakura",
|
||||
:bio => "",
|
||||
:password => "bear",
|
||||
:confirm => "bear",
|
||||
:reason => "I love anime"
|
||||
}
|
||||
|
||||
{:ok, user} = TwitterAPI.register_user(data)
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
assert user.approval_pending
|
||||
|
||||
email = Pleroma.Emails.AdminEmail.new_unapproved_registration(admin, user)
|
||||
|
||||
notify_email = Pleroma.Config.get([:instance, :notify_email])
|
||||
instance_name = Pleroma.Config.get([:instance, :name])
|
||||
|
||||
Swoosh.TestAssertions.assert_email_sent(
|
||||
from: {instance_name, notify_email},
|
||||
to: {admin.name, admin.email},
|
||||
html_body: email.html_body
|
||||
)
|
||||
end
|
||||
|
||||
test "it registers a new user and parses mentions in the bio" do
|
||||
data1 = %{
|
||||
:username => "john",
|
||||
|
|
Loading…
Reference in a new issue