Merge branch 'develop' into gun
This commit is contained in:
commit
39ed608b13
34 changed files with 457 additions and 90 deletions
|
@ -38,6 +38,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
- Rate limiter is now disabled for localhost/socket (unless remoteip plug is enabled)
|
||||
- Logger: default log level changed from `warn` to `info`.
|
||||
- Config mix task `migrate_to_db` truncates `config` table before migrating the config file.
|
||||
- Allow account registration without an email
|
||||
- Default to `prepare: :unnamed` in the database configuration.
|
||||
- Instance stats are now loaded on startup instead of being empty until next hourly job.
|
||||
<details>
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
Replaces embedded objects with references to them in the `objects` table. Only needs to be ran once if the instance was created before Pleroma 1.0.5. The reason why this is not a migration is because it could significantly increase the database size after being ran, however after this `VACUUM FULL` will be able to reclaim about 20% (really depends on what is in the database, your mileage may vary) of the db size before the migration.
|
||||
|
||||
```sh tab="OTP"
|
||||
./bin/pleroma_ctl database remove_embedded_objects [<options>]
|
||||
./bin/pleroma_ctl database remove_embedded_objects [option ...]
|
||||
```
|
||||
|
||||
```sh tab="From Source"
|
||||
mix pleroma.database remove_embedded_objects [<options>]
|
||||
mix pleroma.database remove_embedded_objects [option ...]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
@ -28,11 +28,11 @@ This will prune remote posts older than 90 days (configurable with [`config :ple
|
|||
The disk space will only be reclaimed after `VACUUM FULL`. You may run out of disk space during the execution of the task or vacuuming if you don't have about 1/3rds of the database size free.
|
||||
|
||||
```sh tab="OTP"
|
||||
./bin/pleroma_ctl database prune_objects [<options>]
|
||||
./bin/pleroma_ctl database prune_objects [option ...]
|
||||
```
|
||||
|
||||
```sh tab="From Source"
|
||||
mix pleroma.database prune_objects [<options>]
|
||||
mix pleroma.database prune_objects [option ...]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
## Send digest email since given date (user registration date by default) ignoring user activity status.
|
||||
|
||||
```sh tab="OTP"
|
||||
./bin/pleroma_ctl digest test <nickname> [<since_date>]
|
||||
./bin/pleroma_ctl digest test <nickname> [since_date]
|
||||
```
|
||||
|
||||
```sh tab="From Source"
|
||||
mix pleroma.digest test <nickname> [<since_date>]
|
||||
mix pleroma.digest test <nickname> [since_date]
|
||||
```
|
||||
|
||||
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
## Lists emoji packs and metadata specified in the manifest
|
||||
|
||||
```sh tab="OTP"
|
||||
./bin/pleroma_ctl emoji ls-packs [<options>]
|
||||
./bin/pleroma_ctl emoji ls-packs [option ...]
|
||||
```
|
||||
|
||||
```sh tab="From Source"
|
||||
mix pleroma.emoji ls-packs [<options>]
|
||||
mix pleroma.emoji ls-packs [option ...]
|
||||
```
|
||||
|
||||
|
||||
|
@ -19,11 +19,11 @@ mix pleroma.emoji ls-packs [<options>]
|
|||
## Fetch, verify and install the specified packs from the manifest into `STATIC-DIR/emoji/PACK-NAME`
|
||||
|
||||
```sh tab="OTP"
|
||||
./bin/pleroma_ctl emoji get-packs [<options>] <packs>
|
||||
./bin/pleroma_ctl emoji get-packs [option ...] <pack ...>
|
||||
```
|
||||
|
||||
```sh tab="From Source"
|
||||
mix pleroma.emoji get-packs [<options>] <packs>
|
||||
mix pleroma.emoji get-packs [option ...] <pack ...>
|
||||
```
|
||||
|
||||
### Options
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
|
||||
## Generate a new configuration file
|
||||
```sh tab="OTP"
|
||||
./bin/pleroma_ctl instance gen [<options>]
|
||||
./bin/pleroma_ctl instance gen [option ...]
|
||||
```
|
||||
|
||||
```sh tab="From Source"
|
||||
mix pleroma.instance gen [<options>]
|
||||
mix pleroma.instance gen [option ...]
|
||||
```
|
||||
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
|
||||
## Migrate uploads from local to remote storage
|
||||
```sh tab="OTP"
|
||||
./bin/pleroma_ctl uploads migrate_local <target_uploader> [<options>]
|
||||
./bin/pleroma_ctl uploads migrate_local <target_uploader> [option ...]
|
||||
```
|
||||
|
||||
```sh tab="From Source"
|
||||
mix pleroma.uploads migrate_local <target_uploader> [<options>]
|
||||
mix pleroma.uploads migrate_local <target_uploader> [option ...]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
## Create a user
|
||||
|
||||
```sh tab="OTP"
|
||||
./bin/pleroma_ctl user new <email> [<options>]
|
||||
./bin/pleroma_ctl user new <nickname> <email> [option ...]
|
||||
```
|
||||
|
||||
```sh tab="From Source"
|
||||
mix pleroma.user new <email> [<options>]
|
||||
mix pleroma.user new <nickname> <email> [option ...]
|
||||
```
|
||||
|
||||
|
||||
|
@ -33,11 +33,11 @@ mix pleroma.user list
|
|||
|
||||
## Generate an invite link
|
||||
```sh tab="OTP"
|
||||
./bin/pleroma_ctl user invite [<options>]
|
||||
./bin/pleroma_ctl user invite [option ...]
|
||||
```
|
||||
|
||||
```sh tab="From Source"
|
||||
mix pleroma.user invite [<options>]
|
||||
mix pleroma.user invite [option ...]
|
||||
```
|
||||
|
||||
|
||||
|
@ -137,11 +137,11 @@ mix pleroma.user reset_password <nickname>
|
|||
|
||||
## Set the value of the given user's settings
|
||||
```sh tab="OTP"
|
||||
./bin/pleroma_ctl user set <nickname> [<options>]
|
||||
./bin/pleroma_ctl user set <nickname> [option ...]
|
||||
```
|
||||
|
||||
```sh tab="From Source"
|
||||
mix pleroma.user set <nickname> [<options>]
|
||||
mix pleroma.user set <nickname> [option ...]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
|
|
@ -18,9 +18,8 @@
|
|||
6. Run `sudo -Hu postgres pg_restore -d <pleroma_db> -v -1 </path/to/backup_location/pleroma.pgdump>`
|
||||
7. If you installed a newer Pleroma version, you should run `mix ecto.migrate`[^1]. This task performs database migrations, if there were any.
|
||||
8. Restart the Pleroma service.
|
||||
9. After you've restarted Pleroma, you will notice that postgres will take up more cpu resources than usual. A lot in fact. To fix this you must do a VACUUM ANLAYZE. This can also be done while the instance is still running like so:
|
||||
$ sudo -u postgres psql pleroma_database_name
|
||||
pleroma=# VACUUM ANALYZE;
|
||||
9. Run `sudo -Hu postgres vacuumdb --all --analyze-in-stages`. This will quickly generate the statistics so that postgres can properly plan queries.
|
||||
|
||||
[^1]: Prefix with `MIX_ENV=prod` to run it using the production config file.
|
||||
|
||||
## Remove
|
||||
|
|
|
@ -156,8 +156,8 @@ cp /opt/pleroma/installation/pleroma.nginx /etc/nginx/conf.d/pleroma.conf
|
|||
```
|
||||
|
||||
```sh tab="Debian/Ubuntu"
|
||||
cp /opt/pleroma/installation/pleroma.nginx /etc/nginx/sites-available/pleroma.nginx
|
||||
ln -s /etc/nginx/sites-available/pleroma.nginx /etc/nginx/sites-enabled/pleroma.nginx
|
||||
cp /opt/pleroma/installation/pleroma.nginx /etc/nginx/sites-available/pleroma.conf
|
||||
ln -s /etc/nginx/sites-available/pleroma.conf /etc/nginx/sites-enabled/pleroma.conf
|
||||
```
|
||||
|
||||
If your distro does not have either of those you can append `include /etc/nginx/pleroma.conf` to the end of the http section in /etc/nginx/nginx.conf and
|
||||
|
|
|
@ -28,7 +28,7 @@ defmodule Mix.Tasks.Pleroma.Docs do
|
|||
defp do_run(implementation) do
|
||||
start_pleroma()
|
||||
|
||||
with descriptions <- Pleroma.Config.Loader.load("config/description.exs"),
|
||||
with descriptions <- Pleroma.Config.Loader.read("config/description.exs"),
|
||||
{:ok, file_path} <-
|
||||
Pleroma.Docs.Generator.process(
|
||||
implementation,
|
||||
|
|
|
@ -35,7 +35,7 @@ defmodule Mix.Tasks.Pleroma.Relay do
|
|||
def run(["list"]) do
|
||||
start_pleroma()
|
||||
|
||||
with {:ok, list} <- Relay.list() do
|
||||
with {:ok, list} <- Relay.list(true) do
|
||||
list |> Enum.each(&shell_info(&1))
|
||||
else
|
||||
{:error, e} -> shell_error("Error while fetching relay subscription list: #{inspect(e)}")
|
||||
|
|
|
@ -308,6 +308,13 @@ defmodule Pleroma.Activity do
|
|||
|> where([a], fragment("? ->> 'state' = 'pending'", a.data))
|
||||
end
|
||||
|
||||
def following_requests_for_actor(%Pleroma.User{ap_id: ap_id}) do
|
||||
Queries.by_type("Follow")
|
||||
|> where([a], fragment("?->>'state' = 'pending'", a.data))
|
||||
|> where([a], a.actor == ^ap_id)
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
def restrict_deactivated_users(query) do
|
||||
deactivated_users =
|
||||
from(u in User.Query.build(%{deactivated: true}), select: u.ap_id)
|
||||
|
|
|
@ -35,6 +35,7 @@ defmodule Pleroma.Application do
|
|||
# See http://elixir-lang.org/docs/stable/elixir/Application.html
|
||||
# for more information on OTP Applications
|
||||
def start(_type, _args) do
|
||||
Pleroma.Config.Holder.save_default()
|
||||
Pleroma.HTML.compile_scrubbers()
|
||||
Config.DeprecationWarnings.warn()
|
||||
Pleroma.Plugs.HTTPSecurityPlug.warn_if_disabled()
|
||||
|
|
|
@ -3,14 +3,33 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Config.Holder do
|
||||
@config Pleroma.Config.Loader.load_and_merge()
|
||||
@config Pleroma.Config.Loader.default_config()
|
||||
|
||||
@spec config() :: keyword()
|
||||
def config, do: @config
|
||||
@spec save_default() :: :ok
|
||||
def save_default do
|
||||
default_config =
|
||||
if System.get_env("RELEASE_NAME") do
|
||||
release_config =
|
||||
[:code.root_dir(), "releases", System.get_env("RELEASE_VSN"), "releases.exs"]
|
||||
|> Path.join()
|
||||
|> Pleroma.Config.Loader.read()
|
||||
|
||||
@spec config(atom()) :: any()
|
||||
def config(group), do: @config[group]
|
||||
Pleroma.Config.Loader.merge(@config, release_config)
|
||||
else
|
||||
@config
|
||||
end
|
||||
|
||||
@spec config(atom(), atom()) :: any()
|
||||
def config(group, key), do: @config[group][key]
|
||||
Pleroma.Config.put(:default_config, default_config)
|
||||
end
|
||||
|
||||
@spec default_config() :: keyword()
|
||||
def default_config, do: get_default()
|
||||
|
||||
@spec default_config(atom()) :: keyword()
|
||||
def default_config(group), do: Keyword.get(get_default(), group)
|
||||
|
||||
@spec default_config(atom(), atom()) :: keyword()
|
||||
def default_config(group, key), do: get_in(get_default(), [group, key])
|
||||
|
||||
defp get_default, do: Pleroma.Config.get(:default_config)
|
||||
end
|
||||
|
|
|
@ -13,32 +13,28 @@ defmodule Pleroma.Config.Loader do
|
|||
]
|
||||
|
||||
if Code.ensure_loaded?(Config.Reader) do
|
||||
@spec load(Path.t()) :: keyword()
|
||||
def load(path), do: Config.Reader.read!(path)
|
||||
@reader Config.Reader
|
||||
|
||||
defp do_merge(conf1, conf2), do: Config.Reader.merge(conf1, conf2)
|
||||
def read(path), do: @reader.read!(path)
|
||||
else
|
||||
# support for Elixir less than 1.9
|
||||
@spec load(Path.t()) :: keyword()
|
||||
def load(path) do
|
||||
@reader Mix.Config
|
||||
def read(path) do
|
||||
path
|
||||
|> Mix.Config.eval!()
|
||||
|> @reader.eval!()
|
||||
|> elem(0)
|
||||
end
|
||||
|
||||
defp do_merge(conf1, conf2), do: Mix.Config.merge(conf1, conf2)
|
||||
end
|
||||
|
||||
@spec load_and_merge() :: keyword()
|
||||
def load_and_merge do
|
||||
all_paths =
|
||||
if Pleroma.Config.get(:release),
|
||||
do: ["config/config.exs", "config/releases.exs"],
|
||||
else: ["config/config.exs"]
|
||||
@spec read(Path.t()) :: keyword()
|
||||
|
||||
all_paths
|
||||
|> Enum.map(&load(&1))
|
||||
|> Enum.reduce([], &do_merge(&2, &1))
|
||||
@spec merge(keyword(), keyword()) :: keyword()
|
||||
def merge(c1, c2), do: @reader.merge(c1, c2)
|
||||
|
||||
@spec default_config() :: keyword()
|
||||
def default_config do
|
||||
"config/config.exs"
|
||||
|> read()
|
||||
|> filter()
|
||||
end
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ defmodule Pleroma.Config.TransferTask do
|
|||
key = ConfigDB.from_string(setting.key)
|
||||
group = ConfigDB.from_string(setting.group)
|
||||
|
||||
default = Config.Holder.config(group, key)
|
||||
default = Config.Holder.default_config(group, key)
|
||||
value = ConfigDB.from_binary(setting.value)
|
||||
|
||||
merged_value =
|
||||
|
|
|
@ -15,7 +15,7 @@ defmodule Pleroma.Docs.JSON do
|
|||
end
|
||||
|
||||
def compile do
|
||||
with config <- Pleroma.Config.Loader.load("config/description.exs") do
|
||||
with config <- Pleroma.Config.Loader.read("config/description.exs") do
|
||||
config[:pleroma][:config_description]
|
||||
|> Pleroma.Docs.Generator.convert_to_strings()
|
||||
|> Jason.encode!()
|
||||
|
|
|
@ -530,7 +530,14 @@ defmodule Pleroma.User do
|
|||
end
|
||||
|
||||
def maybe_validate_required_email(changeset, true), do: changeset
|
||||
def maybe_validate_required_email(changeset, _), do: validate_required(changeset, [:email])
|
||||
|
||||
def maybe_validate_required_email(changeset, _) do
|
||||
if Pleroma.Config.get([:instance, :account_activation_required]) do
|
||||
validate_required(changeset, [:email])
|
||||
else
|
||||
changeset
|
||||
end
|
||||
end
|
||||
|
||||
defp put_ap_id(changeset) do
|
||||
ap_id = ap_id(%User{nickname: get_field(changeset, :nickname)})
|
||||
|
|
|
@ -60,15 +60,28 @@ defmodule Pleroma.Web.ActivityPub.Relay do
|
|||
|
||||
def publish(_), do: {:error, "Not implemented"}
|
||||
|
||||
@spec list() :: {:ok, [String.t()]} | {:error, any()}
|
||||
def list do
|
||||
@spec list(boolean()) :: {:ok, [String.t()]} | {:error, any()}
|
||||
def list(with_not_accepted \\ false) do
|
||||
with %User{} = user <- get_actor() do
|
||||
list =
|
||||
accepted =
|
||||
user
|
||||
|> User.following()
|
||||
|> Enum.map(fn entry -> URI.parse(entry).host end)
|
||||
|> Enum.uniq()
|
||||
|
||||
list =
|
||||
if with_not_accepted do
|
||||
without_accept =
|
||||
user
|
||||
|> Pleroma.Activity.following_requests_for_actor()
|
||||
|> Enum.map(fn a -> URI.parse(a.data["object"]).host <> " (no Accept received)" end)
|
||||
|> Enum.uniq()
|
||||
|
||||
accepted ++ without_accept
|
||||
else
|
||||
accepted
|
||||
end
|
||||
|
||||
{:ok, list}
|
||||
else
|
||||
error -> format_error(error)
|
||||
|
|
|
@ -834,7 +834,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|
|||
configs = ConfigDB.get_all_as_keyword()
|
||||
|
||||
merged =
|
||||
Config.Holder.config()
|
||||
Config.Holder.default_config()
|
||||
|> ConfigDB.merge(configs)
|
||||
|> Enum.map(fn {group, values} ->
|
||||
Enum.map(values, fn {key, value} ->
|
||||
|
|
|
@ -591,7 +591,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|
|||
limit = Pleroma.Config.get([:instance, :limit])
|
||||
length = String.length(full_payload)
|
||||
|
||||
if length < limit do
|
||||
if length <= limit do
|
||||
:ok
|
||||
else
|
||||
{:error, dgettext("errors", "The status is over the character limit")}
|
||||
|
|
|
@ -76,7 +76,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||
@doc "POST /api/v1/accounts"
|
||||
def create(
|
||||
%{assigns: %{app: app}} = conn,
|
||||
%{"username" => nickname, "email" => _, "password" => _, "agreement" => true} = params
|
||||
%{"username" => nickname, "password" => _, "agreement" => true} = params
|
||||
) do
|
||||
params =
|
||||
params
|
||||
|
@ -93,7 +93,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||
|> Map.put("bio", params["bio"] || "")
|
||||
|> Map.put("confirm", params["password"])
|
||||
|
||||
with {:ok, user} <- TwitterAPI.register_user(params, need_confirmation: true),
|
||||
with :ok <- validate_email_param(params),
|
||||
{:ok, user} <- TwitterAPI.register_user(params, need_confirmation: true),
|
||||
{:ok, token} <- Token.create_token(app, user, %{scopes: app.scopes}) do
|
||||
json(conn, %{
|
||||
token_type: "Bearer",
|
||||
|
@ -114,6 +115,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||
render_error(conn, :forbidden, "Invalid credentials")
|
||||
end
|
||||
|
||||
defp validate_email_param(%{"email" => _}), do: :ok
|
||||
|
||||
defp validate_email_param(_) do
|
||||
case Pleroma.Config.get([:instance, :account_activation_required]) do
|
||||
true -> {:error, %{"error" => "Missing parameters"}}
|
||||
_ -> :ok
|
||||
end
|
||||
end
|
||||
|
||||
@doc "GET /api/v1/accounts/verify_credentials"
|
||||
def verify_credentials(%{assigns: %{user: user}} = conn, _) do
|
||||
chat_token = Phoenix.Token.sign(conn, "user socket", user.id)
|
||||
|
|
176
priv/static/static/static-fe.css
Normal file
176
priv/static/static/static-fe.css
Normal file
|
@ -0,0 +1,176 @@
|
|||
body {
|
||||
background-color: #282c37;
|
||||
font-family: sans-serif;
|
||||
color: white;
|
||||
}
|
||||
|
||||
main {
|
||||
margin: 50px auto;
|
||||
max-width: 960px;
|
||||
padding: 40px;
|
||||
background-color: #313543;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
header {
|
||||
margin: 50px auto;
|
||||
max-width: 960px;
|
||||
padding: 40px;
|
||||
background-color: #313543;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.activity {
|
||||
border-radius: 4px;
|
||||
padding: 1em;
|
||||
padding-bottom: 2em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.avatar img {
|
||||
float: left;
|
||||
border-radius: 4px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.activity-content img, video, audio {
|
||||
padding: 1em;
|
||||
max-width: 800px;
|
||||
max-height: 800px;
|
||||
}
|
||||
|
||||
#selected {
|
||||
background-color: #1b2735;
|
||||
}
|
||||
|
||||
.counts dt, .counts dd {
|
||||
float: left;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.h-card {
|
||||
min-height: 48px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
header a, .h-card a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
header a:hover, .h-card a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.display-name {
|
||||
padding-top: 4px;
|
||||
display: block;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* keep emoji from being hilariously huge */
|
||||
.display-name img {
|
||||
max-height: 1em;
|
||||
}
|
||||
|
||||
.display-name .nickname {
|
||||
padding-top: 4px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.nickname:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.pull-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.collapse {
|
||||
margin: 0;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #9baec8;
|
||||
font-weight: normal;
|
||||
font-size: 20px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
input {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
margin-top: 20px;
|
||||
background-color: rgba(0,0,0,.1);
|
||||
color: white;
|
||||
border: 0;
|
||||
border-bottom: 2px solid #9baec8;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
border-bottom: 2px solid #4b8ed8;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
button {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
color: white;
|
||||
background-color: #419bdd;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
padding: 10px;
|
||||
margin-top: 30px;
|
||||
text-transform: uppercase;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.alert-danger {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
color: #D8000C;
|
||||
background-color: #FFD2D2;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
padding: 10px;
|
||||
margin-top: 20px;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.alert-info {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
color: #00529B;
|
||||
background-color: #BDE5F8;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
padding: 10px;
|
||||
margin-top: 20px;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
}
|
|
@ -7,8 +7,8 @@ defmodule Pleroma.Config.HolderTest do
|
|||
|
||||
alias Pleroma.Config.Holder
|
||||
|
||||
test "config/0" do
|
||||
config = Holder.config()
|
||||
test "default_config/0" do
|
||||
config = Holder.default_config()
|
||||
assert config[:pleroma][Pleroma.Uploaders.Local][:uploads] == "test/uploads"
|
||||
assert config[:tesla][:adapter] == Tesla.Mock
|
||||
|
||||
|
@ -20,15 +20,15 @@ defmodule Pleroma.Config.HolderTest do
|
|||
refute config[:phoenix][:serve_endpoints]
|
||||
end
|
||||
|
||||
test "config/1" do
|
||||
pleroma_config = Holder.config(:pleroma)
|
||||
test "default_config/1" do
|
||||
pleroma_config = Holder.default_config(:pleroma)
|
||||
assert pleroma_config[Pleroma.Uploaders.Local][:uploads] == "test/uploads"
|
||||
tesla_config = Holder.config(:tesla)
|
||||
tesla_config = Holder.default_config(:tesla)
|
||||
assert tesla_config[:adapter] == Tesla.Mock
|
||||
end
|
||||
|
||||
test "config/2" do
|
||||
assert Holder.config(:pleroma, Pleroma.Uploaders.Local) == [uploads: "test/uploads"]
|
||||
assert Holder.config(:tesla, :adapter) == Tesla.Mock
|
||||
test "default_config/2" do
|
||||
assert Holder.default_config(:pleroma, Pleroma.Uploaders.Local) == [uploads: "test/uploads"]
|
||||
assert Holder.default_config(:tesla, :adapter) == Tesla.Mock
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,28 +7,13 @@ defmodule Pleroma.Config.LoaderTest do
|
|||
|
||||
alias Pleroma.Config.Loader
|
||||
|
||||
test "load/1" do
|
||||
config = Loader.load("test/fixtures/config/temp.secret.exs")
|
||||
test "read/1" do
|
||||
config = Loader.read("test/fixtures/config/temp.secret.exs")
|
||||
assert config[:pleroma][:first_setting][:key] == "value"
|
||||
assert config[:pleroma][:first_setting][:key2] == [Pleroma.Repo]
|
||||
assert config[:quack][:level] == :info
|
||||
end
|
||||
|
||||
test "load_and_merge/0" do
|
||||
config = Loader.load_and_merge()
|
||||
|
||||
refute config[:pleroma][Pleroma.Repo]
|
||||
refute config[:pleroma][Pleroma.Web.Endpoint]
|
||||
refute config[:pleroma][:env]
|
||||
refute config[:pleroma][:configurable_from_database]
|
||||
refute config[:pleroma][:database]
|
||||
refute config[:phoenix][:serve_endpoints]
|
||||
|
||||
assert config[:pleroma][:ecto_repos] == [Pleroma.Repo]
|
||||
assert config[:pleroma][Pleroma.Uploaders.Local][:uploads] == "test/uploads"
|
||||
assert config[:tesla][:adapter] == Tesla.Mock
|
||||
end
|
||||
|
||||
test "filter_group/2" do
|
||||
assert Loader.filter_group(:pleroma,
|
||||
pleroma: [
|
||||
|
|
|
@ -70,7 +70,7 @@ defmodule Pleroma.Config.TransferTaskTest do
|
|||
|
||||
assert Application.get_env(:quack, :level) == :info
|
||||
assert Application.get_env(:quack, :meta) == [:none]
|
||||
default = Pleroma.Config.Holder.config(:quack, :webhook_url)
|
||||
default = Pleroma.Config.Holder.default_config(:quack, :webhook_url)
|
||||
assert Application.get_env(:quack, :webhook_url) == default
|
||||
|
||||
on_exit(fn ->
|
||||
|
|
15
test/fixtures/relay/accept-follow.json
vendored
Normal file
15
test/fixtures/relay/accept-follow.json
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
"actor": "https://relay.mastodon.host/actor",
|
||||
"id": "https://relay.mastodon.host/activities/ec477b69-db26-4019-923e-cf809de516ab",
|
||||
"object": {
|
||||
"actor": "{{ap_id}}",
|
||||
"id": "{{activity_id}}",
|
||||
"object": "https://relay.mastodon.host/actor",
|
||||
"type": "Follow"
|
||||
},
|
||||
"to": [
|
||||
"{{ap_id}}"
|
||||
],
|
||||
"type": "Accept"
|
||||
}
|
20
test/fixtures/relay/relay.json
vendored
Normal file
20
test/fixtures/relay/relay.json
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
"endpoints": {
|
||||
"sharedInbox": "https://relay.mastodon.host/inbox"
|
||||
},
|
||||
"followers": "https://relay.mastodon.host/followers",
|
||||
"following": "https://relay.mastodon.host/following",
|
||||
"inbox": "https://relay.mastodon.host/inbox",
|
||||
"name": "ActivityRelay",
|
||||
"type": "Application",
|
||||
"id": "https://relay.mastodon.host/actor",
|
||||
"publicKey": {
|
||||
"id": "https://relay.mastodon.host/actor#main-key",
|
||||
"owner": "https://relay.mastodon.host/actor",
|
||||
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuNYHNYETdsZFsdcTTEQo\nlsTP9yz4ZjOGrQ1EjoBA7NkjBUxxUAPxZbBjWPT9F+L3IbCX1IwI2OrBM/KwDlug\nV41xnjNmxSCUNpxX5IMZtFaAz9/hWu6xkRTs9Bh6XWZxi+db905aOqszb9Mo3H2g\nQJiAYemXwTh2kBO7XlBDbsMhO11Tu8FxcWTMdR54vlGv4RoiVh8dJRa06yyiTs+m\njbj/OJwR06mHHwlKYTVT/587NUb+e9QtCK6t/dqpyZ1o7vKSK5PSldZVjwHt292E\nXVxFOQVXi7JazTwpdPww79ECSe8ThCykOYCNkm3RjsKuLuokp7Vzq1hXIoeBJ7z2\ndU8vbgg/JyazsOsTxkVs2nd2i9/QW2SH+sX9X3357+XLSCh/A8p8fv/GeoN7UCXe\n4DWHFJZDlItNFfymiPbQH+omuju8qrfW9ngk1gFeI2mahXFQVu7x0qsaZYioCIrZ\nwq0zPnUGl9u0tLUXQz+ZkInRrEz+JepDVauy5/3QdzMLG420zCj/ygDrFzpBQIrc\n62Z6URueUBJox0UK71K+usxqOrepgw8haFGMvg3STFo34pNYjoK4oKO+h5qZEDFD\nb1n57t6JWUaBocZbJns9RGASq5gih+iMk2+zPLWp1x64yvuLsYVLPLBHxjCxS6lA\ndWcopZHi7R/OsRz+vTT7420CAwEAAQ==\n-----END PUBLIC KEY-----"
|
||||
},
|
||||
"summary": "ActivityRelay bot",
|
||||
"preferredUsername": "relay",
|
||||
"url": "https://relay.mastodon.host/actor"
|
||||
}
|
|
@ -1287,6 +1287,10 @@ defmodule HttpRequestMock do
|
|||
{:ok, %Tesla.Env{status: 404, body: ""}}
|
||||
end
|
||||
|
||||
def get("https://relay.mastodon.host/actor", _, _, _) do
|
||||
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/relay/relay.json")}}
|
||||
end
|
||||
|
||||
def get(url, query, body, headers) do
|
||||
{:error,
|
||||
"Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{
|
||||
|
@ -1299,6 +1303,10 @@ defmodule HttpRequestMock do
|
|||
|
||||
def post(url, query \\ [], body \\ [], headers \\ [])
|
||||
|
||||
def post("https://relay.mastodon.host/inbox", _, _, _) do
|
||||
{:ok, %Tesla.Env{status: 200, body: ""}}
|
||||
end
|
||||
|
||||
def post("http://example.org/needs_refresh", _, _, _) do
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
|
|
|
@ -38,6 +38,9 @@ defmodule Mix.Tasks.Pleroma.RelayTest do
|
|||
assert activity.data["type"] == "Follow"
|
||||
assert activity.data["actor"] == local_user.ap_id
|
||||
assert activity.data["object"] == target_user.ap_id
|
||||
|
||||
:ok = Mix.Tasks.Pleroma.Relay.run(["list"])
|
||||
assert_receive {:mix_shell, :info, ["mastodon.example.org (no Accept received)"]}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -412,7 +412,11 @@ defmodule Pleroma.UserTest do
|
|||
assert activity.actor == welcome_user.ap_id
|
||||
end
|
||||
|
||||
test "it requires an email, name, nickname and password, bio is optional" do
|
||||
clear_config([:instance, :account_activation_required])
|
||||
|
||||
test "it requires an email, name, nickname and password, bio is optional when account_activation_required is enabled" do
|
||||
Pleroma.Config.put([:instance, :account_activation_required], true)
|
||||
|
||||
@full_user_data
|
||||
|> Map.keys()
|
||||
|> Enum.each(fn key ->
|
||||
|
@ -423,6 +427,19 @@ defmodule Pleroma.UserTest do
|
|||
end)
|
||||
end
|
||||
|
||||
test "it requires an name, nickname and password, bio and email are optional when account_activation_required is disabled" do
|
||||
Pleroma.Config.put([:instance, :account_activation_required], false)
|
||||
|
||||
@full_user_data
|
||||
|> Map.keys()
|
||||
|> Enum.each(fn key ->
|
||||
params = Map.delete(@full_user_data, key)
|
||||
changeset = User.register_changeset(%User{}, params)
|
||||
|
||||
assert if key in [:bio, :email], do: changeset.valid?, else: not changeset.valid?
|
||||
end)
|
||||
end
|
||||
|
||||
test "it restricts certain nicknames" do
|
||||
[restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames])
|
||||
|
||||
|
|
|
@ -341,6 +341,44 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
assert "ok" == json_response(conn, 200)
|
||||
assert Instances.reachable?(sender_url)
|
||||
end
|
||||
|
||||
test "accept follow activity", %{conn: conn} do
|
||||
Pleroma.Config.put([:instance, :federating], true)
|
||||
relay = Relay.get_actor()
|
||||
|
||||
assert {:ok, %Activity{} = activity} = Relay.follow("https://relay.mastodon.host/actor")
|
||||
|
||||
followed_relay = Pleroma.User.get_by_ap_id("https://relay.mastodon.host/actor")
|
||||
relay = refresh_record(relay)
|
||||
|
||||
accept =
|
||||
File.read!("test/fixtures/relay/accept-follow.json")
|
||||
|> String.replace("{{ap_id}}", relay.ap_id)
|
||||
|> String.replace("{{activity_id}}", activity.data["id"])
|
||||
|
||||
assert "ok" ==
|
||||
conn
|
||||
|> assign(:valid_signature, true)
|
||||
|> put_req_header("content-type", "application/activity+json")
|
||||
|> post("/inbox", accept)
|
||||
|> json_response(200)
|
||||
|
||||
ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
|
||||
|
||||
assert Pleroma.FollowingRelationship.following?(
|
||||
relay,
|
||||
followed_relay
|
||||
)
|
||||
|
||||
Mix.shell(Mix.Shell.Process)
|
||||
|
||||
on_exit(fn ->
|
||||
Mix.shell(Mix.Shell.IO)
|
||||
end)
|
||||
|
||||
:ok = Mix.Tasks.Pleroma.Relay.run(["list"])
|
||||
assert_receive {:mix_shell, :info, ["relay.mastodon.host"]}
|
||||
end
|
||||
end
|
||||
|
||||
describe "/users/:nickname/inbox" do
|
||||
|
|
|
@ -202,13 +202,15 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
CommonAPI.post(user, %{"status" => ""})
|
||||
end
|
||||
|
||||
test "it returns error when character limit is exceeded" do
|
||||
test "it validates character limits are correctly enforced" do
|
||||
Pleroma.Config.put([:instance, :limit], 5)
|
||||
|
||||
user = insert(:user)
|
||||
|
||||
assert {:error, "The status is over the character limit"} =
|
||||
CommonAPI.post(user, %{"status" => "foobar"})
|
||||
|
||||
assert {:ok, activity} = CommonAPI.post(user, %{"status" => "12345"})
|
||||
end
|
||||
|
||||
test "it can handle activities that expire" do
|
||||
|
|
|
@ -601,6 +601,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
[valid_params: valid_params]
|
||||
end
|
||||
|
||||
clear_config([:instance, :account_activation_required])
|
||||
|
||||
test "Account registration via Application", %{conn: conn} do
|
||||
conn =
|
||||
post(conn, "/api/v1/apps", %{
|
||||
|
@ -685,7 +687,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
assert json_response(res, 200)
|
||||
|
||||
[{127, 0, 0, 1}, {127, 0, 0, 2}, {127, 0, 0, 3}, {127, 0, 0, 4}]
|
||||
|> Stream.zip(valid_params)
|
||||
|> Stream.zip(Map.delete(valid_params, :email))
|
||||
|> Enum.each(fn {ip, {attr, _}} ->
|
||||
res =
|
||||
conn
|
||||
|
@ -697,6 +699,54 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
end)
|
||||
end
|
||||
|
||||
clear_config([:instance, :account_activation_required])
|
||||
|
||||
test "returns bad_request if missing email params when :account_activation_required is enabled",
|
||||
%{conn: conn, valid_params: valid_params} do
|
||||
Pleroma.Config.put([:instance, :account_activation_required], true)
|
||||
|
||||
app_token = insert(:oauth_token, user: nil)
|
||||
conn = put_req_header(conn, "authorization", "Bearer " <> app_token.token)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> Map.put(:remote_ip, {127, 0, 0, 5})
|
||||
|> post("/api/v1/accounts", Map.delete(valid_params, :email))
|
||||
|
||||
assert json_response(res, 400) == %{"error" => "Missing parameters"}
|
||||
|
||||
res =
|
||||
conn
|
||||
|> Map.put(:remote_ip, {127, 0, 0, 6})
|
||||
|> post("/api/v1/accounts", Map.put(valid_params, :email, ""))
|
||||
|
||||
assert json_response(res, 400) == %{"error" => "{\"email\":[\"can't be blank\"]}"}
|
||||
end
|
||||
|
||||
test "allow registration without an email", %{conn: conn, valid_params: valid_params} do
|
||||
app_token = insert(:oauth_token, user: nil)
|
||||
conn = put_req_header(conn, "authorization", "Bearer " <> app_token.token)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> Map.put(:remote_ip, {127, 0, 0, 7})
|
||||
|> post("/api/v1/accounts", Map.delete(valid_params, :email))
|
||||
|
||||
assert json_response(res, 200)
|
||||
end
|
||||
|
||||
test "allow registration with an empty email", %{conn: conn, valid_params: valid_params} do
|
||||
app_token = insert(:oauth_token, user: nil)
|
||||
conn = put_req_header(conn, "authorization", "Bearer " <> app_token.token)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> Map.put(:remote_ip, {127, 0, 0, 8})
|
||||
|> post("/api/v1/accounts", Map.put(valid_params, :email, ""))
|
||||
|
||||
assert json_response(res, 200)
|
||||
end
|
||||
|
||||
test "returns forbidden if token is invalid", %{conn: conn, valid_params: valid_params} do
|
||||
conn = put_req_header(conn, "authorization", "Bearer " <> "invalid-token")
|
||||
|
||||
|
|
Loading…
Reference in a new issue