<%= label f, :password, "Password" %>
<%= password_input f, :password %>
diff --git a/lib/pleroma/web/templates/twitter_api/util/password_reset_failed.html.eex b/lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex
similarity index 100%
rename from lib/pleroma/web/templates/twitter_api/util/password_reset_failed.html.eex
rename to lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex
diff --git a/lib/pleroma/web/templates/twitter_api/util/password_reset_success.html.eex b/lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex
similarity index 100%
rename from lib/pleroma/web/templates/twitter_api/util/password_reset_success.html.eex
rename to lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex
diff --git a/lib/pleroma/web/twitter_api/controllers/password_controller.ex b/lib/pleroma/web/twitter_api/controllers/password_controller.ex
new file mode 100644
index 000000000..1941e6143
--- /dev/null
+++ b/lib/pleroma/web/twitter_api/controllers/password_controller.ex
@@ -0,0 +1,37 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.TwitterAPI.PasswordController do
+ @moduledoc """
+ The module containts functions for reset password.
+ """
+
+ use Pleroma.Web, :controller
+
+ require Logger
+
+ alias Pleroma.PasswordResetToken
+ alias Pleroma.Repo
+ alias Pleroma.User
+
+ def reset(conn, %{"token" => token}) do
+ with %{used: false} = token <- Repo.get_by(PasswordResetToken, %{token: token}),
+ %User{} = user <- User.get_cached_by_id(token.user_id) do
+ render(conn, "reset.html", %{
+ token: token,
+ user: user
+ })
+ else
+ _e -> render(conn, "invalid_token.html")
+ end
+ end
+
+ def do_reset(conn, %{"data" => data}) do
+ with {:ok, _} <- PasswordResetToken.reset_password(data["token"], data) do
+ render(conn, "reset_success.html")
+ else
+ _e -> render(conn, "reset_failed.html")
+ end
+ end
+end
diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
index 489170d80..b1863528f 100644
--- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex
+++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
@@ -11,8 +11,6 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
alias Pleroma.Activity
alias Pleroma.Emoji
alias Pleroma.Notification
- alias Pleroma.PasswordResetToken
- alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web
alias Pleroma.Web.ActivityPub.ActivityPub
@@ -20,26 +18,6 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
alias Pleroma.Web.OStatus
alias Pleroma.Web.WebFinger
- def show_password_reset(conn, %{"token" => token}) do
- with %{used: false} = token <- Repo.get_by(PasswordResetToken, %{token: token}),
- %User{} = user <- User.get_cached_by_id(token.user_id) do
- render(conn, "password_reset.html", %{
- token: token,
- user: user
- })
- else
- _e -> render(conn, "invalid_token.html")
- end
- end
-
- def password_reset(conn, %{"data" => data}) do
- with {:ok, _} <- PasswordResetToken.reset_password(data["token"], data) do
- render(conn, "password_reset_success.html")
- else
- _e -> render(conn, "password_reset_failed.html")
- end
- end
-
def help_test(conn, _params) do
json(conn, "ok")
end
diff --git a/lib/pleroma/web/twitter_api/views/password_view.ex b/lib/pleroma/web/twitter_api/views/password_view.ex
new file mode 100644
index 000000000..b166b925d
--- /dev/null
+++ b/lib/pleroma/web/twitter_api/views/password_view.ex
@@ -0,0 +1,8 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.TwitterAPI.PasswordView do
+ use Pleroma.Web, :view
+ import Phoenix.HTML.Form
+end
diff --git a/mix.exs b/mix.exs
index 7f8e36cbb..5484c43ef 100644
--- a/mix.exs
+++ b/mix.exs
@@ -37,14 +37,14 @@ def project do
pleroma: [
include_executables_for: [:unix],
applications: [ex_syslogger: :load, syslog: :load],
- steps: [:assemble, ©_pleroma_ctl/1]
+ steps: [:assemble, ©_files/1]
]
]
]
end
- def copy_pleroma_ctl(%{path: target_path} = release) do
- File.cp!("./rel/pleroma_ctl", Path.join([target_path, "bin", "pleroma_ctl"]))
+ def copy_files(%{path: target_path} = release) do
+ File.cp_r!("./rel/files", target_path)
release
end
@@ -108,7 +108,7 @@ defp deps do
{:ex_aws, "~> 2.0"},
{:ex_aws_s3, "~> 2.0"},
{:earmark, "~> 1.3"},
- {:bbcode, "~> 0.1"},
+ {:bbcode, "~> 0.1.1"},
{:ex_machina, "~> 2.3", only: :test},
{:credo, "~> 0.9.3", only: [:dev, :test]},
{:mock, "~> 0.3.3", only: :test},
@@ -209,10 +209,11 @@ defp version(version) do
branch_name =
with {branch_name, 0} <- System.cmd("git", ["rev-parse", "--abbrev-ref", "HEAD"]),
+ branch_name <- System.get_env("PLEROMA_BUILD_BRANCH") || branch_name,
true <- branch_name != "master" do
branch_name =
String.trim(branch_name)
- |> String.replace(~r/\W+/, "-")
+ |> String.replace(~r/[^0-9a-z\-\.]+/i, "-")
"-" <> branch_name
end
diff --git a/mix.lock b/mix.lock
index 6528db98d..cae8d7d84 100644
--- a/mix.lock
+++ b/mix.lock
@@ -2,7 +2,7 @@
"accept": {:hex, :accept, "0.3.5", "b33b127abca7cc948bbe6caa4c263369abf1347cfa9d8e699c6d214660f10cd1", [:rebar3], [], "hexpm"},
"auto_linker": {:git, "https://git.pleroma.social/pleroma/auto_linker.git", "95e8188490e97505c56636c1379ffdf036c1fdde", [ref: "95e8188490e97505c56636c1379ffdf036c1fdde"]},
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm"},
- "bbcode": {:hex, :bbcode, "0.1.0", "400e618b640b635261611d7fb7f79d104917fc5b084aae371ab6b08477cb035b", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
+ "bbcode": {:hex, :bbcode, "0.1.1", "0023e2c7814119b2e620b7add67182e3f6019f92bfec9a22da7e99821aceba70", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
"benchee": {:hex, :benchee, "1.0.1", "66b211f9bfd84bd97e6d1beaddf8fc2312aaabe192f776e8931cb0c16f53a521", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}], "hexpm"},
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"},
"cachex": {:hex, :cachex, "3.0.2", "1351caa4e26e29f7d7ec1d29b53d6013f0447630bbf382b4fb5d5bad0209f203", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm"},
diff --git a/priv/repo/migrations/20190622151019_add_group_key_to_config.exs b/priv/repo/migrations/20190622151019_add_group_key_to_config.exs
new file mode 100644
index 000000000..d7a3785d0
--- /dev/null
+++ b/priv/repo/migrations/20190622151019_add_group_key_to_config.exs
@@ -0,0 +1,12 @@
+defmodule Pleroma.Repo.Migrations.AddGroupKeyToConfig do
+ use Ecto.Migration
+
+ def change do
+ alter table("config") do
+ add(:group, :string)
+ end
+
+ drop(unique_index("config", :key))
+ create(unique_index("config", [:group, :key]))
+ end
+end
diff --git a/priv/static/adminfe/static/css/app.cea15678.css b/priv/static/adminfe/app.34fc670f.css
similarity index 100%
rename from priv/static/adminfe/static/css/app.cea15678.css
rename to priv/static/adminfe/app.34fc670f.css
diff --git a/priv/static/adminfe/static/css/chunk-18e1.6aaab273.css b/priv/static/adminfe/chunk-18e1.6aaab273.css
similarity index 100%
rename from priv/static/adminfe/static/css/chunk-18e1.6aaab273.css
rename to priv/static/adminfe/chunk-18e1.6aaab273.css
diff --git a/priv/static/adminfe/chunk-56c9.c27dac5e.css b/priv/static/adminfe/chunk-56c9.c27dac5e.css
new file mode 100644
index 000000000..2b4283ec5
Binary files /dev/null and b/priv/static/adminfe/chunk-56c9.c27dac5e.css differ
diff --git a/priv/static/adminfe/chunk-5eaf.1a04e979.css b/priv/static/adminfe/chunk-5eaf.1a04e979.css
new file mode 100644
index 000000000..a09287f58
Binary files /dev/null and b/priv/static/adminfe/chunk-5eaf.1a04e979.css differ
diff --git a/priv/static/adminfe/static/css/chunk-8b70.9ba0945c.css b/priv/static/adminfe/chunk-8b70.9ba0945c.css
similarity index 100%
rename from priv/static/adminfe/static/css/chunk-8b70.9ba0945c.css
rename to priv/static/adminfe/chunk-8b70.9ba0945c.css
diff --git a/priv/static/adminfe/chunk-elementUI.f74c256b.css b/priv/static/adminfe/chunk-elementUI.f74c256b.css
new file mode 100644
index 000000000..c8d56344e
Binary files /dev/null and b/priv/static/adminfe/chunk-elementUI.f74c256b.css differ
diff --git a/priv/static/adminfe/static/css/chunk-f018.0d22684d.css b/priv/static/adminfe/chunk-f018.0d22684d.css
similarity index 100%
rename from priv/static/adminfe/static/css/chunk-f018.0d22684d.css
rename to priv/static/adminfe/chunk-f018.0d22684d.css
diff --git a/priv/static/adminfe/static/css/chunk-libs.bd17d456.css b/priv/static/adminfe/chunk-libs.4e8c4664.css
similarity index 100%
rename from priv/static/adminfe/static/css/chunk-libs.bd17d456.css
rename to priv/static/adminfe/chunk-libs.4e8c4664.css
diff --git a/priv/static/adminfe/index.html b/priv/static/adminfe/index.html
index 44a58a44e..2ef6362ba 100644
--- a/priv/static/adminfe/index.html
+++ b/priv/static/adminfe/index.html
@@ -1 +1 @@
-
Admin FE
\ No newline at end of file
+
Admin FE
\ No newline at end of file
diff --git a/priv/static/adminfe/static/css/chunk-50cf.1db1ed5b.css b/priv/static/adminfe/static/css/chunk-50cf.1db1ed5b.css
deleted file mode 100644
index 2a2fbd8e4..000000000
Binary files a/priv/static/adminfe/static/css/chunk-50cf.1db1ed5b.css and /dev/null differ
diff --git a/priv/static/adminfe/static/css/chunk-elementUI.4296cedf.css b/priv/static/adminfe/static/css/chunk-elementUI.4296cedf.css
deleted file mode 100644
index fbd926db1..000000000
Binary files a/priv/static/adminfe/static/css/chunk-elementUI.4296cedf.css and /dev/null differ
diff --git a/priv/static/adminfe/static/js/app.25699e3d.js b/priv/static/adminfe/static/js/app.25699e3d.js
deleted file mode 100644
index 54694bf5e..000000000
Binary files a/priv/static/adminfe/static/js/app.25699e3d.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/app.4137ad8f.js b/priv/static/adminfe/static/js/app.4137ad8f.js
new file mode 100644
index 000000000..bb4b6ec49
Binary files /dev/null and b/priv/static/adminfe/static/js/app.4137ad8f.js differ
diff --git a/priv/static/adminfe/static/js/chunk-02a0.db6ec114.js b/priv/static/adminfe/static/js/chunk-02a0.db6ec114.js
new file mode 100644
index 000000000..6f8dd4d13
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-02a0.db6ec114.js differ
diff --git a/priv/static/adminfe/static/js/chunk-0620.c765c190.js b/priv/static/adminfe/static/js/chunk-0620.c765c190.js
new file mode 100644
index 000000000..aa8ddedce
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-0620.c765c190.js differ
diff --git a/priv/static/adminfe/static/js/chunk-50cf.b9b1df43.js b/priv/static/adminfe/static/js/chunk-50cf.b9b1df43.js
deleted file mode 100644
index 1b5614639..000000000
Binary files a/priv/static/adminfe/static/js/chunk-50cf.b9b1df43.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-56c9.28e35fc3.js b/priv/static/adminfe/static/js/chunk-56c9.28e35fc3.js
new file mode 100644
index 000000000..6f92e0e72
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-56c9.28e35fc3.js differ
diff --git a/priv/static/adminfe/static/js/chunk-5eaf.5b76e416.js b/priv/static/adminfe/static/js/chunk-5eaf.5b76e416.js
new file mode 100644
index 000000000..56f1b6891
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-5eaf.5b76e416.js differ
diff --git a/priv/static/adminfe/static/js/chunk-elementUI.1fa5434b.js b/priv/static/adminfe/static/js/chunk-elementUI.1fa5434b.js
new file mode 100644
index 000000000..8f6f193b7
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-elementUI.1fa5434b.js differ
diff --git a/priv/static/adminfe/static/js/chunk-elementUI.d388c21d.js b/priv/static/adminfe/static/js/chunk-elementUI.d388c21d.js
deleted file mode 100644
index 1f40d7e84..000000000
Binary files a/priv/static/adminfe/static/js/chunk-elementUI.d388c21d.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-libs.48e79a9e.js b/priv/static/adminfe/static/js/chunk-libs.d5609760.js
similarity index 79%
rename from priv/static/adminfe/static/js/chunk-libs.48e79a9e.js
rename to priv/static/adminfe/static/js/chunk-libs.d5609760.js
index db0b5dc97..5fa09cf69 100644
Binary files a/priv/static/adminfe/static/js/chunk-libs.48e79a9e.js and b/priv/static/adminfe/static/js/chunk-libs.d5609760.js differ
diff --git a/priv/static/adminfe/static/js/runtime.7144b2cf.js b/priv/static/adminfe/static/js/runtime.7144b2cf.js
deleted file mode 100644
index 0a58ac351..000000000
Binary files a/priv/static/adminfe/static/js/runtime.7144b2cf.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/runtime.d8d12c12.js b/priv/static/adminfe/static/js/runtime.d8d12c12.js
new file mode 100644
index 000000000..6d8ac5af6
Binary files /dev/null and b/priv/static/adminfe/static/js/runtime.d8d12c12.js differ
diff --git a/lib/mix/tasks/pleroma/robots_txt.eex b/priv/templates/robots_txt.eex
similarity index 100%
rename from lib/mix/tasks/pleroma/robots_txt.eex
rename to priv/templates/robots_txt.eex
diff --git a/lib/mix/tasks/pleroma/sample_config.eex b/priv/templates/sample_config.eex
similarity index 88%
rename from lib/mix/tasks/pleroma/sample_config.eex
rename to priv/templates/sample_config.eex
index 73d9217be..2d4a49328 100644
--- a/lib/mix/tasks/pleroma/sample_config.eex
+++ b/priv/templates/sample_config.eex
@@ -3,7 +3,11 @@
# NOTE: This file should not be committed to a repo or otherwise made public
# without removing sensitive information.
-use Mix.Config
+<%= if Code.ensure_loaded?(Config) or not Code.ensure_loaded?(Mix.Config) do
+ "import Config"
+else
+ "use Mix.Config"
+end %>
config :pleroma, Pleroma.Web.Endpoint,
url: [host: "<%= domain %>", scheme: "https", port: <%= port %>],
@@ -16,7 +20,6 @@ config :pleroma, :instance,
notify_email: "<%= notify_email %>",
limit: 5000,
registrations_open: true,
- dedupe_media: false,
dynamic_configuration: <%= db_configurable? %>
config :pleroma, :media_proxy,
@@ -38,6 +41,10 @@ config :web_push_encryption, :vapid_details,
public_key: "<%= web_push_public_key %>",
private_key: "<%= web_push_private_key %>"
+config :pleroma, :database, rum_enabled: <%= rum_enabled %>
+config :pleroma, :instance, static_dir: "<%= static_dir %>"
+config :pleroma, Pleroma.Uploaders.Local, uploads: "<%= uploads_dir %>"
+
# Enable Strict-Transport-Security once SSL is working:
# config :pleroma, :http_security,
# sts: true
diff --git a/lib/mix/tasks/pleroma/sample_psql.eex b/priv/templates/sample_psql.eex
similarity index 80%
rename from lib/mix/tasks/pleroma/sample_psql.eex
rename to priv/templates/sample_psql.eex
index f0ac05e57..627839a68 100644
--- a/lib/mix/tasks/pleroma/sample_psql.eex
+++ b/priv/templates/sample_psql.eex
@@ -5,3 +5,8 @@ CREATE DATABASE <%= dbname %> OWNER <%= dbuser %>;
CREATE EXTENSION IF NOT EXISTS citext;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
+<%= if rum_enabled do
+ "CREATE EXTENSION IF NOT EXISTS rum;"
+else
+""
+end %>
diff --git a/rel/files/bin/pleroma_ctl b/rel/files/bin/pleroma_ctl
new file mode 100755
index 000000000..b0e1874a9
--- /dev/null
+++ b/rel/files/bin/pleroma_ctl
@@ -0,0 +1,118 @@
+#!/bin/sh
+# XXX: This should be removed when elixir's releases get custom command support
+
+detect_flavour() {
+ arch="$(arch)"
+ if [ "$arch" = "x86_64" ]; then
+ arch="amd64"
+ elif [ "$arch" = "armv7l" ]; then
+ arch="arm"
+ elif [ "$arch" = "aarch64" ]; then
+ arch="arm64"
+ else
+ echo "Unsupported arch: $arch" >&2
+ exit 1
+ fi
+
+ if getconf GNU_LIBC_VERSION >/dev/null; then
+ libc_postfix=""
+ elif [ "$(ldd 2>&1 | head -c 9)" = "musl libc" ]; then
+ libc_postfix="-musl"
+ elif [ "$(find /lib/libc.musl* | wc -l)" ]; then
+ libc_postfix="-musl"
+ else
+ echo "Unsupported libc" >&2
+ exit 1
+ fi
+
+ echo "$arch$libc_postfix"
+}
+
+detect_branch() {
+ version="$(cut -d' ' -f2 <"$RELEASE_ROOT"/releases/start_erl.data)"
+ branch="$(echo "$version" | cut -d'-' -f 4)"
+ if [ "$branch" = "develop" ]; then
+ echo "develop"
+ elif [ "$branch" = "" ]; then
+ echo "master"
+ else
+ echo "Releases are built only for master and develop branches" >&2
+ exit 1
+ fi
+}
+update() {
+ set -e
+ RELEASE_ROOT=$(dirname "$SCRIPTPATH")
+ uri="${PLEROMA_CTL_URI:-https://git.pleroma.social}"
+ project_id="${PLEROMA_CTL_PROJECT_ID:-2}"
+ project_branch="$(detect_branch)"
+ flavour="${PLEROMA_CTL_FLAVOUR:-$(detect_flavour)}"
+ echo "Detected flavour: $flavour"
+ tmp="${PLEROMA_CTL_TMP_DIR:-/tmp}"
+ artifact="$tmp/pleroma.zip"
+ full_uri="${uri}/api/v4/projects/${project_id}/jobs/artifacts/${project_branch}/download?job=${flavour}"
+ echo "Downloading the artifact from ${full_uri} to ${artifact}"
+ curl "$full_uri" -o "${artifact}"
+ echo "Unpacking ${artifact} to ${tmp}"
+ unzip -q "$artifact" -d "$tmp"
+ echo "Copying files over to $RELEASE_ROOT"
+ if [ "$1" != "--no-rm" ]; then
+ rm -r "${RELEASE_ROOT:-?}"/*
+ fi
+ cp -rf "$tmp/release"/* "$RELEASE_ROOT"
+ echo "Removing temporary files"
+ rm -r "$tmp/release"
+ rm "$artifact"
+ echo "Done! Please refer to the changelog/release notes for changes and update instructions"
+ set +e
+}
+
+if [ -z "$1" ] || [ "$1" = "help" ]; then
+ # TODO: Just list the commands on `pleroma_ctl help` and output help for the individual command on `pleroma_ctl help $COMMAND`
+ echo "Usage: $(basename "$0") COMMAND [ARGS]
+
+ The known commands are:
+
+ create
+ Create database schema (needs to be executed only once)
+
+ migrate
+ Execute database migrations (needs to be done after updates)
+
+ rollback [VERSION]
+ Rollback database migrations (needs to be done before downgrading)
+
+ update [OPTIONS]
+ Update the instance using the latest CI artifact for the current branch.
+
+ The only supported option is --no-rm, when set the script won't delete the whole directory, but
+ just force copy over files from the new release. This wastes more space, but may be useful if
+ some files are stored inside of the release directories (although you really shouldn't store them
+ there), or if you want to be able to quickly revert a broken update.
+
+ The script will try to detect your architecture and ABI and set a flavour automatically,
+ but if it is wrong, you can overwrite it by setting PLEROMA_CTL_FLAVOUR to the desired flavour.
+
+ By default the artifact will be downloaded from https://git.pleroma.social for pleroma/pleroma (project id: 2)
+ to /tmp/, you can overwrite these settings by setting PLEROMA_CTL_URI, PLEROMA_CTL_PROJECT_ID and PLEROMA_CTL_TMP_DIR
+ respectively.
+
+
+ and any mix tasks under Pleroma namespace, for example \`mix pleroma.user COMMAND\` is
+ equivalent to \`$(basename "$0") user COMMAND\`
+
+ By default pleroma_ctl will try calling into a running instance to execute non migration-related commands,
+ if for some reason this is undesired, set PLEROMA_CTL_RPC_DISABLED environment variable
+"
+else
+ SCRIPT=$(readlink -f "$0")
+ SCRIPTPATH=$(dirname "$SCRIPT")
+
+ if [ "$1" = "update" ]; then
+ update "$2"
+ elif [ "$1" = "migrate" ] || [ "$1" = "rollback" ] || [ "$1" = "create" ] || [ "$1 $2" = "instance gen" ] || [ -n "$PLEROMA_CTL_RPC_DISABLED" ]; then
+ "$SCRIPTPATH"/pleroma eval 'Pleroma.ReleaseTasks.run("'"$*"'")'
+ else
+ "$SCRIPTPATH"/pleroma rpc 'Pleroma.ReleaseTasks.run("'"$*"'")'
+ fi
+fi
diff --git a/rel/pleroma_ctl b/rel/pleroma_ctl
deleted file mode 100755
index ac7339762..000000000
--- a/rel/pleroma_ctl
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/sh
-# XXX: This should be removed when elixir's releases get custom command support
-if [ -z "$1" ] || [ "$1" = "help" ]; then
- echo "Usage: $(basename "$0") COMMAND [ARGS]
-
- The known commands are:
-
- create Create database schema (needs to be executed only once)
- migrate Execute database migrations (needs to be done after updates)
- rollback [VERSION] Rollback database migrations (needs to be done before downgrading)
-
- and any mix tasks under Pleroma namespace, for example \`mix pleroma.user COMMAND\` is
- equivalent to \`$(basename "$0") user COMMAND\`
-
- By default pleroma_ctl will try calling into a running instance to execute non migration-related commands,
- if for some reason this is undesired, set PLEROMA_CTL_RPC_DISABLED environment variable
-"
-else
- SCRIPT=$(readlink -f "$0")
- SCRIPTPATH=$(dirname "$SCRIPT")
- if [ "$1" = "migrate" ] || [ "$1" = "rollback" ] || [ "$1" = "create" ] || [ -n "$PLEROMA_CTL_RPC_DISABLED" ]; then
- "$SCRIPTPATH"/pleroma eval 'Pleroma.ReleaseTasks.run("'"$*"'")'
- else
- "$SCRIPTPATH"/pleroma rpc 'Pleroma.ReleaseTasks.run("'"$*"'")'
- fi
-fi
diff --git a/test/config/transfer_task_test.exs b/test/config/transfer_task_test.exs
index 9b8a8dd45..c0e433263 100644
--- a/test/config/transfer_task_test.exs
+++ b/test/config/transfer_task_test.exs
@@ -13,19 +13,37 @@ defmodule Pleroma.Config.TransferTaskTest do
test "transfer config values from db to env" do
refute Application.get_env(:pleroma, :test_key)
- Pleroma.Web.AdminAPI.Config.create(%{key: "test_key", value: [live: 2, com: 3]})
+ refute Application.get_env(:idna, :test_key)
+
+ Pleroma.Web.AdminAPI.Config.create(%{
+ group: "pleroma",
+ key: "test_key",
+ value: [live: 2, com: 3]
+ })
+
+ Pleroma.Web.AdminAPI.Config.create(%{
+ group: "idna",
+ key: "test_key",
+ value: [live: 15, com: 35]
+ })
Pleroma.Config.TransferTask.start_link()
assert Application.get_env(:pleroma, :test_key) == [live: 2, com: 3]
+ assert Application.get_env(:idna, :test_key) == [live: 15, com: 35]
on_exit(fn ->
Application.delete_env(:pleroma, :test_key)
+ Application.delete_env(:idna, :test_key)
end)
end
test "non existing atom" do
- Pleroma.Web.AdminAPI.Config.create(%{key: "undefined_atom_key", value: [live: 2, com: 3]})
+ Pleroma.Web.AdminAPI.Config.create(%{
+ group: "pleroma",
+ key: "undefined_atom_key",
+ value: [live: 2, com: 3]
+ })
assert ExUnit.CaptureLog.capture_log(fn ->
Pleroma.Config.TransferTask.start_link()
diff --git a/test/fixtures/rich_media/non_ogp_embed.html b/test/fixtures/rich_media/non_ogp_embed.html
new file mode 100644
index 000000000..62a1d677a
--- /dev/null
+++ b/test/fixtures/rich_media/non_ogp_embed.html
@@ -0,0 +1,1479 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
BlueAngelLove's Homepage on MyFreeCams.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ My Most Recent Pictures
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About Me
+
+
+
+
+
+
+ Username:
+
+
+
+ BlueAngelLove
+
+
+
+
+
+
+
+
+
+
+
+ Gender:
+
+
+
+ Female
+
+
+
+
+
+
+
+
+ Body Type:
+
+
+
+ Athletic
+
+
+
+
+
+
+
+
+ Ethnicity:
+
+
+
+ Other
+
+
+
+
+
+
+
+
+ Hair:
+
+
+
+ Brown
+
+
+
+
+
+
+
+
+ Eyes:
+
+
+
+ Blue
+
+
+
+
+
+
+
+
+ Weight:
+
+
+
+ 45 kilos
+
+
+
+
+
+
+
+
+ Height:
+
+
+
+ 165 centimeters
+
+
+
+
+
+
+
+
+ Age:
+
+
+
+ 34
+
+
+
+
+
+
+
+
+ City:
+
+
+
+ Mountains
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Sexual Preference:
+
+
+
+ Bisexual
+
+
+
+
+
+
+
+
+ Smoke:
+
+
+
+ Non Smoker
+
+
+
+
+
+
+
+
+ Drink:
+
+
+
+ Non Drinker
+
+
+
+
+
+
+
+
+ Drugs:
+
+
+
+ Never
+
+
+
+
+
+
+
+
+
+
+
+ Occupation/Major:
+
+
+
+ Guide
+
+
+
+
+
+
+
+
+
+
+
+ Favorite Food:
+
+
+
+ Chocolate
+
+
+
+
+
+
+
+
+ Pets:
+
+
+
+ I dont like pets
+
+
+
+
+
+
+
+
+ Automobile:
+
+
+
+ Ford
+
+
+
+
+
+
+
+
+ About Me:
+
+
+
+
+
+
+
BlueAngelLove
+
+
June Month Contestst-Top 3 tippers Get A gift mailed,videos,pictures and will my right hand full month and room helpers as well (be my men for a month or who knows...maybe forever) ***
+Love Ya Angels*** We are currently ranked #2200 overall
+
Get Listed on My Wall of Fame
+
+
+
+
ElmosEgo 6570 Tks
+
Rw2lite 4800 Tks
+
Toastboi 2093 Tks
+
Acoolahole 1850 Tks
+
Gonodog 1299 Tks
+
Pumpy_G 800 Tks
+
Fowser 690 Tks
+
Aquanautic 600 Tks
+
Daveonthelake 535 Tks
+
Wildpervert2 500 Tks
+
Cloud10101 350 Tks
+
Branson102 337 Tks
+
TheCopperhead 329 Tks
+
Mouche99 250 Tks
+
The88drummer 233 Tks
+
Stringtrees86 199 Tks
+
Blazegordon 183 Tks
+
Waiting_4 183 Tks
+
Sam_mie 170 Tks
+
UtterTripe 150 Tks
+
Darth_penguin 150 Tks
+
Playfullpurv 120 Tks
+
Jordnsprings 103 Tks
+
Travelinlover 100 Tks
+
Da884 100 Tks
+
+
+
+
+
May Contest winners - Each month Top 3 tippers Get A gift mailed, videos and pictures - Love Ya Angels
+
Get Listed on My Wall of Fame
+
+
+
Rw2lite
+
ElmosEgo
+
TJuonesWoah
+
+
+
+
+
Menu Per Day
+
LOVE YA ANGELS
+
+
+
Monday - Outfits Strip
+
Tusday - Raffle
+
Wensday - Gamblers Night
+
Thusday - Orgasmic Vibra or Dildos
+
Friday - Wheel/Treat or Trick
+
Saturday - Phrase
+
Sunday - Keno and Boyfriend choice
+
+
+
+
+
You have to tip to get listed above so do your best to get on my exclusive Top Tippers List
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Let's Fun Laugh Live I am Jullia from Transylvania and is a pleasure to have u around Enjoy me and my room BlueAngelLove I am good, but not an angel. I do sin, but I am not the devil. I am just a girl in a big world trying to find someone to love and be loved
+
+ ~~~Live~Laugh~Love~~~
+
+
+
+
+
+
+
+
+
+ Tags:
+
+
+
+ natural, blue eyes, toys, funny, oil, shower, fetish, costume, sex, natural, masturbation, finger, dp, anal, girl next door, romantic, naughty, pervert, open mind, play roles, horny, playful, smiley, lover, sweet, sexy, beautiful, hot, shaved, friendly, pussy, skype
+
+
+
+
+
+
+
+
+
+ Friends
+
+
+
+
+ Average Rating:
+
+
+
+
+
+
+
+
+
+ Rate BlueAngelLove:
+
+
+
+
+ You must
login to rate.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Password Protected Galleries
+
+
+
+
+
+
+
+
+
+ 17 Photos
+
+
+
+
+
+
+
+
+
+ 37 Photos
+
+
+
+
+
+
+
+
+
+ 15 Photos
+
+
+
+
+
+
+
+
+
+ 97 Photos
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Photo Galleries
+
+
+
+
+
+
+
+
+
+ 1 Photo
+
+
+
+
+
+
+
+
+
+ 68 Photos
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Recent Photo
+
+
+
+
+
+
+
+ jullia
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ My Schedule
+
+
+
+ Sunday
+
+
+
+ I'm
+ Always
+ online from
+ 3:30 am
+ until
+ 7:00 am
+
+
+
+
+ Monday
+
+
+
+ I'm
+ Always
+ online from
+ 3:30 pm
+ until
+ 7:00 am
+
+
+
+
+ Tuesday
+
+
+
+ I'm
+ Always
+ online from
+ 3:30 pm
+ until
+ 7:00 am
+
+
+
+
+ Wednesday
+
+
+
+ I'm
+ Always
+ online from
+ 3:30 pm
+ until
+ 7:00 am
+
+
+
+
+ Thursday
+
+
+
+ I'm
+ Always
+ online from
+ 3:30 pm
+ until
+ 7:00 am
+
+
+
+
+ Friday
+
+
+
+ I'm
+ Always
+ online from
+ 3:30 pm
+ until
+ 7:00 am
+
+
+
+
+ Saturday
+
+
+
+ I'm
+ Always
+ online from
+ 3:30 pm
+ until
+ 7:00 am
+
+
+
+ The times shown above have been adjusted relative to your timezone ( ).
+
+
+
+
+
+
+
+
+
+
+
+ Interests & Hobbies
+
+
+
+
+
+
+ Meaning of Life:
+
+
+
+ Meaning of Life .To Love and Be Loved and keep what i have and who i have in my life right now
+
+
+
+
+
+
+
+
+ Five Things I Can't Live Without:
+
+
+
+ -family
+-phone
+-sex
+-love
+-money
+
+
+
+
+
+
+
+
+ Favorite Books:
+
+
+
+ My fav. book was Count of Monte Cristo
+
+
+
+
+
+
+
+
+ What I Like To Do For Fun:
+
+
+
+ In my free time I dance, play games , go out and travel
+
+
+
+
+
+
+
+
+ Favorite Songs:
+
+
+
+ VIDEO<script type="text/javascript">function execute_YTvideo(){return youtube.query({ids:"channel==MINE",startDate:"2018-01-01",endDate:"2018-12-31",metrics:"views,estimatedMinutesWatched,averageViewDuration,averageViewPercentage,subscribersGained",dimensions:"day",sort:"day"}).then(function(e){},function(e){console.error("Execute error",e)})}</script>Powered by Embed YouTube Video
+
+
+
+
+
+
+
+
+ Favorite Movies:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Talents:
+
+
+
+ i love to Dance , Travel and Cook
+
+
+
+
+
+
+
+
+ Perfect Mate:
+
+
+
+ Perfect mate is Magic Mike
+
+
+
+
+
+
+
+
+ Perfect Date:
+
+
+
+ Perfect Date .You and Me , romatic dinner and wild sex
+
+
+
+
+
+
+
+
+ Turn Ons/Offs:
+
+
+
+ I hate Liers and Rude Peoples
+
+
+
+
+
+
+
+
+ Best Reason to Get to Know Me:
+
+
+
+ My dear men, please dont put a label on medont make me a category before you get to know me!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/plugs/rate_limiter_test.exs b/test/plugs/rate_limiter_test.exs
index b3798bf03..b8d6aff89 100644
--- a/test/plugs/rate_limiter_test.exs
+++ b/test/plugs/rate_limiter_test.exs
@@ -20,7 +20,7 @@ test "ip/1" do
end
test "it restricts by opts" do
- scale = 100
+ scale = 1000
limit = 5
Pleroma.Config.put([:rate_limit, @limiter_name], {scale, limit})
@@ -64,7 +64,7 @@ test "it restricts by opts" do
test "optional limits for authenticated users" do
Ecto.Adapters.SQL.Sandbox.checkout(Pleroma.Repo)
- scale = 100
+ scale = 1000
limit = 5
Pleroma.Config.put([:rate_limit, @limiter_name], [{1, 10}, {scale, limit}])
diff --git a/test/support/factory.ex b/test/support/factory.ex
index 5be34660e..c2812e8f7 100644
--- a/test/support/factory.ex
+++ b/test/support/factory.ex
@@ -314,6 +314,7 @@ def registration_factory do
def config_factory do
%Pleroma.Web.AdminAPI.Config{
key: sequence(:key, &"some_key_#{&1}"),
+ group: "pleroma",
value:
sequence(
:value,
diff --git a/test/tasks/config_test.exs b/test/tasks/config_test.exs
index 7d3b1860c..9c9a31bf4 100644
--- a/test/tasks/config_test.exs
+++ b/test/tasks/config_test.exs
@@ -5,7 +5,7 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do
setup_all do
Mix.shell(Mix.Shell.Process)
- temp_file = "config/temp.migrated.secret.exs"
+ temp_file = "config/temp.exported_from_db.secret.exs"
dynamic = Pleroma.Config.get([:instance, :dynamic_configuration])
@@ -30,17 +30,26 @@ test "settings are migrated to db" do
Mix.Tasks.Pleroma.Config.run(["migrate_to_db"])
- first_db = Config.get_by_key("first_setting")
- second_db = Config.get_by_key("second_setting")
- refute Config.get_by_key("Pleroma.Repo")
+ first_db = Config.get_by_params(%{group: "pleroma", key: "first_setting"})
+ second_db = Config.get_by_params(%{group: "pleroma", key: "second_setting"})
+ refute Config.get_by_params(%{group: "pleroma", key: "Pleroma.Repo"})
assert Config.from_binary(first_db.value) == [key: "value", key2: [Pleroma.Repo]]
assert Config.from_binary(second_db.value) == [key: "value2", key2: [Pleroma.Activity]]
end
test "settings are migrated to file and deleted from db", %{temp_file: temp_file} do
- Config.create(%{key: "setting_first", value: [key: "value", key2: [Pleroma.Activity]]})
- Config.create(%{key: "setting_second", value: [key: "valu2", key2: [Pleroma.Repo]]})
+ Config.create(%{
+ group: "pleroma",
+ key: "setting_first",
+ value: [key: "value", key2: [Pleroma.Activity]]
+ })
+
+ Config.create(%{
+ group: "pleroma",
+ key: "setting_second",
+ value: [key: "valu2", key2: [Pleroma.Repo]]
+ })
Mix.Tasks.Pleroma.Config.run(["migrate_from_db", "temp"])
diff --git a/test/tasks/user_test.exs b/test/tasks/user_test.exs
index 6fd7c7113..3d4b08fba 100644
--- a/test/tasks/user_test.exs
+++ b/test/tasks/user_test.exs
@@ -89,8 +89,7 @@ test "user is deleted" do
assert_received {:mix_shell, :info, [message]}
assert message =~ " deleted"
- user = User.get_cached_by_nickname(user.nickname)
- assert user.info.deactivated
+ refute User.get_by_nickname(user.nickname)
end
test "no user to delete" do
diff --git a/test/user_test.exs b/test/user_test.exs
index a8176025c..198a97fae 100644
--- a/test/user_test.exs
+++ b/test/user_test.exs
@@ -920,42 +920,44 @@ test ".delete_user_activities deletes all create activities" do
{:ok, activity} = CommonAPI.post(user, %{"status" => "2hu"})
- Ecto.Adapters.SQL.Sandbox.unboxed_run(Repo, fn ->
- {:ok, _} = User.delete_user_activities(user)
- # TODO: Remove favorites, repeats, delete activities.
- refute Activity.get_by_id(activity.id)
- end)
+ {:ok, _} = User.delete_user_activities(user)
+
+ # TODO: Remove favorites, repeats, delete activities.
+ refute Activity.get_by_id(activity.id)
end
- test ".delete deactivates a user, all follow relationships and all create activities" do
+ test ".delete deactivates a user, all follow relationships and all activities" do
user = insert(:user)
- followed = insert(:user)
follower = insert(:user)
- {:ok, user} = User.follow(user, followed)
{:ok, follower} = User.follow(follower, user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "2hu"})
{:ok, activity_two} = CommonAPI.post(follower, %{"status" => "3hu"})
- {:ok, _, _} = CommonAPI.favorite(activity_two.id, user)
- {:ok, _, _} = CommonAPI.favorite(activity.id, follower)
- {:ok, _, _} = CommonAPI.repeat(activity.id, follower)
+ {:ok, like, _} = CommonAPI.favorite(activity_two.id, user)
+ {:ok, like_two, _} = CommonAPI.favorite(activity.id, follower)
+ {:ok, repeat, _} = CommonAPI.repeat(activity_two.id, user)
{:ok, _} = User.delete(user)
- followed = User.get_cached_by_id(followed.id)
follower = User.get_cached_by_id(follower.id)
- user = User.get_cached_by_id(user.id)
- assert user.info.deactivated
+ refute User.following?(follower, user)
+ refute User.get_by_id(user.id)
- refute User.following?(user, followed)
- refute User.following?(followed, follower)
+ user_activities =
+ user.ap_id
+ |> Activity.query_by_actor()
+ |> Repo.all()
+ |> Enum.map(fn act -> act.data["type"] end)
- # TODO: Remove favorites, repeats, delete activities.
+ assert Enum.all?(user_activities, fn act -> act in ~w(Delete Undo) end)
refute Activity.get_by_id(activity.id)
+ refute Activity.get_by_id(like.id)
+ refute Activity.get_by_id(like_two.id)
+ refute Activity.get_by_id(repeat.id)
end
test "get_public_key_for_ap_id fetches a user that's not in the db" do
diff --git a/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs b/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs
new file mode 100644
index 000000000..03dc299ec
--- /dev/null
+++ b/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs
@@ -0,0 +1,145 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2019 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
+ use Pleroma.DataCase
+ import Pleroma.Factory
+ import ExUnit.CaptureLog
+
+ alias Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy
+
+ @linkless_message %{
+ "type" => "Create",
+ "object" => %{
+ "content" => "hi world!"
+ }
+ }
+
+ @linkful_message %{
+ "type" => "Create",
+ "object" => %{
+ "content" => "
hi world! "
+ }
+ }
+
+ @response_message %{
+ "type" => "Create",
+ "object" => %{
+ "name" => "yes",
+ "type" => "Answer"
+ }
+ }
+
+ describe "with new user" do
+ test "it allows posts without links" do
+ user = insert(:user)
+
+ assert user.info.note_count == 0
+
+ message =
+ @linkless_message
+ |> Map.put("actor", user.ap_id)
+
+ {:ok, _message} = AntiLinkSpamPolicy.filter(message)
+ end
+
+ test "it disallows posts with links" do
+ user = insert(:user)
+
+ assert user.info.note_count == 0
+
+ message =
+ @linkful_message
+ |> Map.put("actor", user.ap_id)
+
+ {:reject, _} = AntiLinkSpamPolicy.filter(message)
+ end
+ end
+
+ describe "with old user" do
+ test "it allows posts without links" do
+ user = insert(:user, info: %{note_count: 1})
+
+ assert user.info.note_count == 1
+
+ message =
+ @linkless_message
+ |> Map.put("actor", user.ap_id)
+
+ {:ok, _message} = AntiLinkSpamPolicy.filter(message)
+ end
+
+ test "it allows posts with links" do
+ user = insert(:user, info: %{note_count: 1})
+
+ assert user.info.note_count == 1
+
+ message =
+ @linkful_message
+ |> Map.put("actor", user.ap_id)
+
+ {:ok, _message} = AntiLinkSpamPolicy.filter(message)
+ end
+ end
+
+ describe "with followed new user" do
+ test "it allows posts without links" do
+ user = insert(:user, info: %{follower_count: 1})
+
+ assert user.info.follower_count == 1
+
+ message =
+ @linkless_message
+ |> Map.put("actor", user.ap_id)
+
+ {:ok, _message} = AntiLinkSpamPolicy.filter(message)
+ end
+
+ test "it allows posts with links" do
+ user = insert(:user, info: %{follower_count: 1})
+
+ assert user.info.follower_count == 1
+
+ message =
+ @linkful_message
+ |> Map.put("actor", user.ap_id)
+
+ {:ok, _message} = AntiLinkSpamPolicy.filter(message)
+ end
+ end
+
+ describe "with unknown actors" do
+ test "it rejects posts without links" do
+ message =
+ @linkless_message
+ |> Map.put("actor", "http://invalid.actor")
+
+ assert capture_log(fn ->
+ {:reject, _} = AntiLinkSpamPolicy.filter(message)
+ end) =~ "[error] Could not decode user at fetch http://invalid.actor"
+ end
+
+ test "it rejects posts with links" do
+ message =
+ @linkful_message
+ |> Map.put("actor", "http://invalid.actor")
+
+ assert capture_log(fn ->
+ {:reject, _} = AntiLinkSpamPolicy.filter(message)
+ end) =~ "[error] Could not decode user at fetch http://invalid.actor"
+ end
+ end
+
+ describe "with contentless-objects" do
+ test "it does not reject them or error out" do
+ user = insert(:user, info: %{note_count: 1})
+
+ message =
+ @response_message
+ |> Map.put("actor", user.ap_id)
+
+ {:ok, _message} = AntiLinkSpamPolicy.filter(message)
+ end
+ end
+end
diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs
index 18f64f2b7..4278ac59d 100644
--- a/test/web/admin_api/admin_api_controller_test.exs
+++ b/test/web/admin_api/admin_api_controller_test.exs
@@ -1334,7 +1334,7 @@ test "with settings in db", %{conn: conn} do
setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true})
- temp_file = "config/test.migrated.secret.exs"
+ temp_file = "config/test.exported_from_db.secret.exs"
on_exit(fn ->
Application.delete_env(:pleroma, :key1)
@@ -1343,6 +1343,8 @@ test "with settings in db", %{conn: conn} do
Application.delete_env(:pleroma, :key4)
Application.delete_env(:pleroma, :keyaa1)
Application.delete_env(:pleroma, :keyaa2)
+ Application.delete_env(:pleroma, Pleroma.Web.Endpoint.NotReal)
+ Application.delete_env(:pleroma, Pleroma.Captcha.NotReal)
:ok = File.rm(temp_file)
end)
@@ -1361,8 +1363,9 @@ test "create new config setting in db", %{conn: conn} do
conn =
post(conn, "/api/pleroma/admin/config", %{
configs: [
- %{key: "key1", value: "value1"},
+ %{group: "pleroma", key: "key1", value: "value1"},
%{
+ group: "pleroma",
key: "key2",
value: %{
"nested_1" => "nested_value1",
@@ -1373,6 +1376,7 @@ test "create new config setting in db", %{conn: conn} do
}
},
%{
+ group: "pleroma",
key: "key3",
value: [
%{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
@@ -1380,8 +1384,14 @@ test "create new config setting in db", %{conn: conn} do
]
},
%{
+ group: "pleroma",
key: "key4",
value: %{"nested_5" => ":upload", "endpoint" => "https://example.com"}
+ },
+ %{
+ group: "idna",
+ key: "key5",
+ value: %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
}
]
})
@@ -1389,10 +1399,12 @@ test "create new config setting in db", %{conn: conn} do
assert json_response(conn, 200) == %{
"configs" => [
%{
+ "group" => "pleroma",
"key" => "key1",
"value" => "value1"
},
%{
+ "group" => "pleroma",
"key" => "key2",
"value" => [
%{"nested_1" => "nested_value1"},
@@ -1405,6 +1417,7 @@ test "create new config setting in db", %{conn: conn} do
]
},
%{
+ "group" => "pleroma",
"key" => "key3",
"value" => [
[%{"nested_3" => "nested_3"}, %{"nested_33" => "nested_33"}],
@@ -1412,8 +1425,14 @@ test "create new config setting in db", %{conn: conn} do
]
},
%{
+ "group" => "pleroma",
"key" => "key4",
"value" => [%{"endpoint" => "https://example.com"}, %{"nested_5" => "upload"}]
+ },
+ %{
+ "group" => "idna",
+ "key" => "key5",
+ "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
}
]
}
@@ -1437,6 +1456,8 @@ test "create new config setting in db", %{conn: conn} do
endpoint: "https://example.com",
nested_5: :upload
]
+
+ assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
end
test "update config setting & delete", %{conn: conn} do
@@ -1446,14 +1467,15 @@ test "update config setting & delete", %{conn: conn} do
conn =
post(conn, "/api/pleroma/admin/config", %{
configs: [
- %{key: config1.key, value: "another_value"},
- %{key: config2.key, delete: "true"}
+ %{group: config1.group, key: config1.key, value: "another_value"},
+ %{group: config2.group, key: config2.key, delete: "true"}
]
})
assert json_response(conn, 200) == %{
"configs" => [
%{
+ "group" => "pleroma",
"key" => config1.key,
"value" => "another_value"
}
@@ -1463,5 +1485,152 @@ test "update config setting & delete", %{conn: conn} do
assert Application.get_env(:pleroma, :keyaa1) == "another_value"
refute Application.get_env(:pleroma, :keyaa2)
end
+
+ test "common config example", %{conn: conn} do
+ conn =
+ post(conn, "/api/pleroma/admin/config", %{
+ configs: [
+ %{
+ "group" => "pleroma",
+ "key" => "Pleroma.Captcha.NotReal",
+ "value" => %{
+ "enabled" => ":false",
+ "method" => "Pleroma.Captcha.Kocaptcha",
+ "seconds_valid" => "i:60"
+ }
+ }
+ ]
+ })
+
+ assert json_response(conn, 200) == %{
+ "configs" => [
+ %{
+ "group" => "pleroma",
+ "key" => "Pleroma.Captcha.NotReal",
+ "value" => [
+ %{"enabled" => false},
+ %{"method" => "Pleroma.Captcha.Kocaptcha"},
+ %{"seconds_valid" => 60}
+ ]
+ }
+ ]
+ }
+ end
+
+ test "tuples with more than two values", %{conn: conn} do
+ conn =
+ post(conn, "/api/pleroma/admin/config", %{
+ configs: [
+ %{
+ "group" => "pleroma",
+ "key" => "Pleroma.Web.Endpoint.NotReal",
+ "value" => [
+ %{
+ "http" => %{
+ "dispatch" => [
+ %{
+ "tuple" => [
+ ":_",
+ [
+ %{
+ "tuple" => [
+ "/api/v1/streaming",
+ "Pleroma.Web.MastodonAPI.WebsocketHandler",
+ []
+ ]
+ },
+ %{
+ "tuple" => [
+ "/websocket",
+ "Phoenix.Endpoint.CowboyWebSocket",
+ %{
+ "tuple" => [
+ "Phoenix.Transports.WebSocket",
+ %{
+ "tuple" => [
+ "Pleroma.Web.Endpoint",
+ "Pleroma.Web.UserSocket",
+ []
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ %{
+ "tuple" => [
+ ":_",
+ "Phoenix.Endpoint.Cowboy2Handler",
+ %{
+ "tuple" => ["Pleroma.Web.Endpoint", []]
+ }
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ })
+
+ assert json_response(conn, 200) == %{
+ "configs" => [
+ %{
+ "group" => "pleroma",
+ "key" => "Pleroma.Web.Endpoint.NotReal",
+ "value" => [
+ %{
+ "http" => %{
+ "dispatch" => %{
+ "_" => [
+ %{
+ "tuple" => [
+ "/api/v1/streaming",
+ "Pleroma.Web.MastodonAPI.WebsocketHandler",
+ []
+ ]
+ },
+ %{
+ "tuple" => [
+ "/websocket",
+ "Phoenix.Endpoint.CowboyWebSocket",
+ %{
+ "Elixir.Phoenix.Transports.WebSocket" => %{
+ "tuple" => [
+ "Pleroma.Web.Endpoint",
+ "Pleroma.Web.UserSocket",
+ []
+ ]
+ }
+ }
+ ]
+ },
+ %{
+ "tuple" => [
+ "_",
+ "Phoenix.Endpoint.Cowboy2Handler",
+ %{"Elixir.Pleroma.Web.Endpoint" => []}
+ ]
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ end
end
end
+
+# Needed for testing
+defmodule Pleroma.Web.Endpoint.NotReal do
+end
+
+defmodule Pleroma.Captcha.NotReal do
+end
diff --git a/test/web/admin_api/config_test.exs b/test/web/admin_api/config_test.exs
index a2fedca40..10cb3b68a 100644
--- a/test/web/admin_api/config_test.exs
+++ b/test/web/admin_api/config_test.exs
@@ -7,18 +7,18 @@ test "get_by_key/1" do
config = insert(:config)
insert(:config)
- assert config == Config.get_by_key(config.key)
+ assert config == Config.get_by_params(%{group: config.group, key: config.key})
end
test "create/1" do
- {:ok, config} = Config.create(%{key: "some_key", value: "some_value"})
- assert config == Config.get_by_key("some_key")
+ {:ok, config} = Config.create(%{group: "pleroma", key: "some_key", value: "some_value"})
+ assert config == Config.get_by_params(%{group: "pleroma", key: "some_key"})
end
test "update/1" do
config = insert(:config)
{:ok, updated} = Config.update(config, %{value: "some_value"})
- loaded = Config.get_by_key(config.key)
+ loaded = Config.get_by_params(%{group: config.group, key: config.key})
assert loaded == updated
end
@@ -27,8 +27,8 @@ test "update_or_create/1" do
key2 = "another_key"
params = [
- %{key: key2, value: "another_value"},
- %{key: config.key, value: "new_value"}
+ %{group: "pleroma", key: key2, value: "another_value"},
+ %{group: config.group, key: config.key, value: "new_value"}
]
assert Repo.all(Config) |> length() == 1
@@ -37,8 +37,8 @@ test "update_or_create/1" do
assert Repo.all(Config) |> length() == 2
- config1 = Config.get_by_key(config.key)
- config2 = Config.get_by_key(key2)
+ config1 = Config.get_by_params(%{group: config.group, key: config.key})
+ config2 = Config.get_by_params(%{group: "pleroma", key: key2})
assert config1.value == Config.transform("new_value")
assert config2.value == Config.transform("another_value")
@@ -46,8 +46,8 @@ test "update_or_create/1" do
test "delete/1" do
config = insert(:config)
- {:ok, _} = Config.delete(config.key)
- refute Config.get_by_key(config.key)
+ {:ok, _} = Config.delete(%{key: config.key, group: config.group})
+ refute Config.get_by_params(%{key: config.key, group: config.group})
end
describe "transform/1" do
@@ -179,5 +179,80 @@ test "complex map with sigil" do
assert Config.from_binary(binary) ==
[federated_timeline_removal: [], reject: [~r/comp[lL][aA][iI][nN]er/], replace: []]
end
+
+ test "complex map with tuples with more than 2 values" do
+ binary =
+ Config.transform(%{
+ "http" => %{
+ "dispatch" => [
+ %{
+ "tuple" => [
+ ":_",
+ [
+ %{
+ "tuple" => [
+ "/api/v1/streaming",
+ "Pleroma.Web.MastodonAPI.WebsocketHandler",
+ []
+ ]
+ },
+ %{
+ "tuple" => [
+ "/websocket",
+ "Phoenix.Endpoint.CowboyWebSocket",
+ %{
+ "tuple" => [
+ "Phoenix.Transports.WebSocket",
+ %{"tuple" => ["Pleroma.Web.Endpoint", "Pleroma.Web.UserSocket", []]}
+ ]
+ }
+ ]
+ },
+ %{
+ "tuple" => [
+ ":_",
+ "Phoenix.Endpoint.Cowboy2Handler",
+ %{
+ "tuple" => ["Pleroma.Web.Endpoint", []]
+ }
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ }
+ })
+
+ assert binary ==
+ :erlang.term_to_binary(
+ http: [
+ dispatch: [
+ _: [
+ {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
+ {"/websocket", Phoenix.Endpoint.CowboyWebSocket,
+ {Phoenix.Transports.WebSocket,
+ {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, []}}},
+ {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
+ ]
+ ]
+ ]
+ )
+
+ assert Config.from_binary(binary) == [
+ http: [
+ dispatch: [
+ {:_,
+ [
+ {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
+ {"/websocket", Phoenix.Endpoint.CowboyWebSocket,
+ {Phoenix.Transports.WebSocket,
+ {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, []}}},
+ {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
+ ]}
+ ]
+ ]
+ ]
+ end
end
end
diff --git a/test/web/oauth/oauth_controller_test.exs b/test/web/oauth/oauth_controller_test.exs
index 242b7fdb3..aae34804d 100644
--- a/test/web/oauth/oauth_controller_test.exs
+++ b/test/web/oauth/oauth_controller_test.exs
@@ -10,6 +10,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
alias Pleroma.Registration
alias Pleroma.Repo
alias Pleroma.Web.OAuth.Authorization
+ alias Pleroma.Web.OAuth.OAuthController
alias Pleroma.Web.OAuth.Token
@oauth_config_path [:oauth2, :issue_new_refresh_token]
@@ -49,7 +50,7 @@ test "GET /oauth/authorize renders auth forms, including OAuth consumer form", %
%{
"response_type" => "code",
"client_id" => app.client_id,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => OAuthController.default_redirect_uri(app),
"scope" => "read"
}
)
@@ -72,7 +73,7 @@ test "GET /oauth/prepare_request encodes parameters as `state` and redirects", %
"authorization" => %{
"scope" => "read follow",
"client_id" => app.client_id,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => OAuthController.default_redirect_uri(app),
"state" => "a_state"
}
}
@@ -98,11 +99,12 @@ test "GET /oauth/prepare_request encodes parameters as `state` and redirects", %
test "with user-bound registration, GET /oauth/
/callback redirects to `redirect_uri` with `code`",
%{app: app, conn: conn} do
registration = insert(:registration)
+ redirect_uri = OAuthController.default_redirect_uri(app)
state_params = %{
"scope" => Enum.join(app.scopes, " "),
"client_id" => app.client_id,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => redirect_uri,
"state" => ""
}
@@ -121,7 +123,7 @@ test "with user-bound registration, GET /oauth//callback redirects to
)
assert response = html_response(conn, 302)
- assert redirected_to(conn) =~ ~r/#{app.redirect_uris}\?code=.+/
+ assert redirected_to(conn) =~ ~r/#{redirect_uri}\?code=.+/
end
end
@@ -132,7 +134,7 @@ test "with user-unbound registration, GET /oauth//callback renders reg
state_params = %{
"scope" => "read write",
"client_id" => app.client_id,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => OAuthController.default_redirect_uri(app),
"state" => "a_state"
}
@@ -165,7 +167,7 @@ test "on authentication error, GET /oauth//callback redirects to `redi
state_params = %{
"scope" => Enum.join(app.scopes, " "),
"client_id" => app.client_id,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => OAuthController.default_redirect_uri(app),
"state" => ""
}
@@ -199,7 +201,7 @@ test "GET /oauth/registration_details renders registration details form", %{
"authorization" => %{
"scopes" => app.scopes,
"client_id" => app.client_id,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => OAuthController.default_redirect_uri(app),
"state" => "a_state",
"nickname" => nil,
"email" => "john@doe.com"
@@ -218,6 +220,7 @@ test "with valid params, POST /oauth/register?op=register redirects to `redirect
conn: conn
} do
registration = insert(:registration, user: nil, info: %{"nickname" => nil, "email" => nil})
+ redirect_uri = OAuthController.default_redirect_uri(app)
conn =
conn
@@ -229,7 +232,7 @@ test "with valid params, POST /oauth/register?op=register redirects to `redirect
"authorization" => %{
"scopes" => app.scopes,
"client_id" => app.client_id,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => redirect_uri,
"state" => "a_state",
"nickname" => "availablenick",
"email" => "available@email.com"
@@ -238,7 +241,36 @@ test "with valid params, POST /oauth/register?op=register redirects to `redirect
)
assert response = html_response(conn, 302)
- assert redirected_to(conn) =~ ~r/#{app.redirect_uris}\?code=.+/
+ assert redirected_to(conn) =~ ~r/#{redirect_uri}\?code=.+/
+ end
+
+ test "with unlisted `redirect_uri`, POST /oauth/register?op=register results in HTTP 401",
+ %{
+ app: app,
+ conn: conn
+ } do
+ registration = insert(:registration, user: nil, info: %{"nickname" => nil, "email" => nil})
+ unlisted_redirect_uri = "http://cross-site-request.com"
+
+ conn =
+ conn
+ |> put_session(:registration_id, registration.id)
+ |> post(
+ "/oauth/register",
+ %{
+ "op" => "register",
+ "authorization" => %{
+ "scopes" => app.scopes,
+ "client_id" => app.client_id,
+ "redirect_uri" => unlisted_redirect_uri,
+ "state" => "a_state",
+ "nickname" => "availablenick",
+ "email" => "available@email.com"
+ }
+ }
+ )
+
+ assert response = html_response(conn, 401)
end
test "with invalid params, POST /oauth/register?op=register renders registration_details page",
@@ -254,7 +286,7 @@ test "with invalid params, POST /oauth/register?op=register renders registration
"authorization" => %{
"scopes" => app.scopes,
"client_id" => app.client_id,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => OAuthController.default_redirect_uri(app),
"state" => "a_state",
"nickname" => "availablenickname",
"email" => "available@email.com"
@@ -286,6 +318,7 @@ test "with valid params, POST /oauth/register?op=connect redirects to `redirect_
} do
user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt("testpassword"))
registration = insert(:registration, user: nil)
+ redirect_uri = OAuthController.default_redirect_uri(app)
conn =
conn
@@ -297,7 +330,7 @@ test "with valid params, POST /oauth/register?op=connect redirects to `redirect_
"authorization" => %{
"scopes" => app.scopes,
"client_id" => app.client_id,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => redirect_uri,
"state" => "a_state",
"name" => user.nickname,
"password" => "testpassword"
@@ -306,7 +339,37 @@ test "with valid params, POST /oauth/register?op=connect redirects to `redirect_
)
assert response = html_response(conn, 302)
- assert redirected_to(conn) =~ ~r/#{app.redirect_uris}\?code=.+/
+ assert redirected_to(conn) =~ ~r/#{redirect_uri}\?code=.+/
+ end
+
+ test "with unlisted `redirect_uri`, POST /oauth/register?op=connect results in HTTP 401`",
+ %{
+ app: app,
+ conn: conn
+ } do
+ user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt("testpassword"))
+ registration = insert(:registration, user: nil)
+ unlisted_redirect_uri = "http://cross-site-request.com"
+
+ conn =
+ conn
+ |> put_session(:registration_id, registration.id)
+ |> post(
+ "/oauth/register",
+ %{
+ "op" => "connect",
+ "authorization" => %{
+ "scopes" => app.scopes,
+ "client_id" => app.client_id,
+ "redirect_uri" => unlisted_redirect_uri,
+ "state" => "a_state",
+ "name" => user.nickname,
+ "password" => "testpassword"
+ }
+ }
+ )
+
+ assert response = html_response(conn, 401)
end
test "with invalid params, POST /oauth/register?op=connect renders registration_details page",
@@ -322,7 +385,7 @@ test "with invalid params, POST /oauth/register?op=connect renders registration_
"authorization" => %{
"scopes" => app.scopes,
"client_id" => app.client_id,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => OAuthController.default_redirect_uri(app),
"state" => "a_state",
"name" => user.nickname,
"password" => "wrong password"
@@ -358,7 +421,7 @@ test "renders authentication page", %{app: app, conn: conn} do
%{
"response_type" => "code",
"client_id" => app.client_id,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => OAuthController.default_redirect_uri(app),
"scope" => "read"
}
)
@@ -378,7 +441,7 @@ test "properly handles internal calls with `authorization`-wrapped params", %{
"authorization" => %{
"response_type" => "code",
"client_id" => app.client_id,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => OAuthController.default_redirect_uri(app),
"scope" => "read"
}
}
@@ -399,7 +462,7 @@ test "renders authentication page if user is already authenticated but `force_lo
%{
"response_type" => "code",
"client_id" => app.client_id,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => OAuthController.default_redirect_uri(app),
"scope" => "read",
"force_login" => "true"
}
@@ -423,7 +486,7 @@ test "with existing authentication and non-OOB `redirect_uri`, redirects to app
%{
"response_type" => "code",
"client_id" => app.client_id,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => OAuthController.default_redirect_uri(app),
"state" => "specific_client_state",
"scope" => "read"
}
@@ -433,6 +496,31 @@ test "with existing authentication and non-OOB `redirect_uri`, redirects to app
"https://redirect.url?access_token=#{token.token}&state=specific_client_state"
end
+ test "with existing authentication and unlisted non-OOB `redirect_uri`, redirects without credentials",
+ %{
+ app: app,
+ conn: conn
+ } do
+ unlisted_redirect_uri = "http://cross-site-request.com"
+ token = insert(:oauth_token, app_id: app.id)
+
+ conn =
+ conn
+ |> put_session(:oauth_token, token.token)
+ |> get(
+ "/oauth/authorize",
+ %{
+ "response_type" => "code",
+ "client_id" => app.client_id,
+ "redirect_uri" => unlisted_redirect_uri,
+ "state" => "specific_client_state",
+ "scope" => "read"
+ }
+ )
+
+ assert redirected_to(conn) == unlisted_redirect_uri
+ end
+
test "with existing authentication and OOB `redirect_uri`, redirects to app with `token` and `state` params",
%{
app: app,
@@ -461,6 +549,7 @@ test "with existing authentication and OOB `redirect_uri`, redirects to app with
test "redirects with oauth authorization" do
user = insert(:user)
app = insert(:oauth_app, scopes: ["read", "write", "follow"])
+ redirect_uri = OAuthController.default_redirect_uri(app)
conn =
build_conn()
@@ -469,14 +558,14 @@ test "redirects with oauth authorization" do
"name" => user.nickname,
"password" => "test",
"client_id" => app.client_id,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => redirect_uri,
"scope" => "read write",
"state" => "statepassed"
}
})
target = redirected_to(conn)
- assert target =~ app.redirect_uris
+ assert target =~ redirect_uri
query = URI.parse(target).query |> URI.query_decoder() |> Map.new()
@@ -489,6 +578,7 @@ test "redirects with oauth authorization" do
test "returns 401 for wrong credentials", %{conn: conn} do
user = insert(:user)
app = insert(:oauth_app)
+ redirect_uri = OAuthController.default_redirect_uri(app)
result =
conn
@@ -497,7 +587,7 @@ test "returns 401 for wrong credentials", %{conn: conn} do
"name" => user.nickname,
"password" => "wrong",
"client_id" => app.client_id,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => redirect_uri,
"state" => "statepassed",
"scope" => Enum.join(app.scopes, " ")
}
@@ -506,7 +596,7 @@ test "returns 401 for wrong credentials", %{conn: conn} do
# Keep the details
assert result =~ app.client_id
- assert result =~ app.redirect_uris
+ assert result =~ redirect_uri
# Error message
assert result =~ "Invalid Username/Password"
@@ -515,6 +605,7 @@ test "returns 401 for wrong credentials", %{conn: conn} do
test "returns 401 for missing scopes", %{conn: conn} do
user = insert(:user)
app = insert(:oauth_app)
+ redirect_uri = OAuthController.default_redirect_uri(app)
result =
conn
@@ -523,7 +614,7 @@ test "returns 401 for missing scopes", %{conn: conn} do
"name" => user.nickname,
"password" => "test",
"client_id" => app.client_id,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => redirect_uri,
"state" => "statepassed",
"scope" => ""
}
@@ -532,7 +623,7 @@ test "returns 401 for missing scopes", %{conn: conn} do
# Keep the details
assert result =~ app.client_id
- assert result =~ app.redirect_uris
+ assert result =~ redirect_uri
# Error message
assert result =~ "This action is outside the authorized scopes"
@@ -541,6 +632,7 @@ test "returns 401 for missing scopes", %{conn: conn} do
test "returns 401 for scopes beyond app scopes", %{conn: conn} do
user = insert(:user)
app = insert(:oauth_app, scopes: ["read", "write"])
+ redirect_uri = OAuthController.default_redirect_uri(app)
result =
conn
@@ -549,7 +641,7 @@ test "returns 401 for scopes beyond app scopes", %{conn: conn} do
"name" => user.nickname,
"password" => "test",
"client_id" => app.client_id,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => redirect_uri,
"state" => "statepassed",
"scope" => "read write follow"
}
@@ -558,7 +650,7 @@ test "returns 401 for scopes beyond app scopes", %{conn: conn} do
# Keep the details
assert result =~ app.client_id
- assert result =~ app.redirect_uris
+ assert result =~ redirect_uri
# Error message
assert result =~ "This action is outside the authorized scopes"
@@ -577,7 +669,7 @@ test "issues a token for an all-body request" do
|> post("/oauth/token", %{
"grant_type" => "authorization_code",
"code" => auth.token,
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => OAuthController.default_redirect_uri(app),
"client_id" => app.client_id,
"client_secret" => app.client_secret
})
@@ -631,7 +723,7 @@ test "issues a token for request with HTTP basic auth client credentials" do
|> post("/oauth/token", %{
"grant_type" => "authorization_code",
"code" => auth.token,
- "redirect_uri" => app.redirect_uris
+ "redirect_uri" => OAuthController.default_redirect_uri(app)
})
assert %{"access_token" => token, "scope" => scope} = json_response(conn, 200)
@@ -676,7 +768,7 @@ test "rejects token exchange with invalid client credentials" do
|> post("/oauth/token", %{
"grant_type" => "authorization_code",
"code" => auth.token,
- "redirect_uri" => app.redirect_uris
+ "redirect_uri" => OAuthController.default_redirect_uri(app)
})
assert resp = json_response(conn, 400)
@@ -755,7 +847,7 @@ test "rejects an invalid authorization code" do
|> post("/oauth/token", %{
"grant_type" => "authorization_code",
"code" => "Imobviouslyinvalid",
- "redirect_uri" => app.redirect_uris,
+ "redirect_uri" => OAuthController.default_redirect_uri(app),
"client_id" => app.client_id,
"client_secret" => app.client_secret
})
diff --git a/test/web/rich_media/parser_test.exs b/test/web/rich_media/parser_test.exs
index a49ba9549..bc48341ca 100644
--- a/test/web/rich_media/parser_test.exs
+++ b/test/web/rich_media/parser_test.exs
@@ -9,6 +9,12 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
} ->
%Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/ogp.html")}
+ %{
+ method: :get,
+ url: "http://example.com/non-ogp"
+ } ->
+ %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/non_ogp_embed.html")}
+
%{
method: :get,
url: "http://example.com/ogp-missing-title"
@@ -47,6 +53,11 @@ test "returns error when no metadata present" do
assert {:error, _} = Pleroma.Web.RichMedia.Parser.parse("http://example.com/empty")
end
+ test "doesn't just add a title" do
+ assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/non-ogp") ==
+ {:error, "Found metadata was invalid or incomplete: %{}"}
+ end
+
test "parses ogp" do
assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/ogp") ==
{:ok,
diff --git a/test/web/streamer_test.exs b/test/web/streamer_test.exs
index 648e28712..4633d7765 100644
--- a/test/web/streamer_test.exs
+++ b/test/web/streamer_test.exs
@@ -356,4 +356,110 @@ test "it doesn't send muted reblogs" do
Task.await(task)
end
+
+ describe "direct streams" do
+ setup do
+ GenServer.start(Streamer, %{}, name: Streamer)
+
+ on_exit(fn ->
+ if pid = Process.whereis(Streamer) do
+ Process.exit(pid, :kill)
+ end
+ end)
+
+ :ok
+ end
+
+ test "it sends conversation update to the 'direct' stream", %{} do
+ user = insert(:user)
+ another_user = insert(:user)
+
+ task =
+ Task.async(fn ->
+ assert_receive {:text, _received_event}, 4_000
+ end)
+
+ Streamer.add_socket(
+ "direct",
+ %{transport_pid: task.pid, assigns: %{user: user}}
+ )
+
+ {:ok, _create_activity} =
+ CommonAPI.post(another_user, %{
+ "status" => "hey @#{user.nickname}",
+ "visibility" => "direct"
+ })
+
+ Task.await(task)
+ end
+
+ test "it doesn't send conversation update to the 'direct' streamj when the last message in the conversation is deleted" do
+ user = insert(:user)
+ another_user = insert(:user)
+
+ {:ok, create_activity} =
+ CommonAPI.post(another_user, %{
+ "status" => "hi @#{user.nickname}",
+ "visibility" => "direct"
+ })
+
+ task =
+ Task.async(fn ->
+ assert_receive {:text, received_event}, 4_000
+ assert %{"event" => "delete", "payload" => _} = Jason.decode!(received_event)
+
+ refute_receive {:text, _}, 4_000
+ end)
+
+ Streamer.add_socket(
+ "direct",
+ %{transport_pid: task.pid, assigns: %{user: user}}
+ )
+
+ {:ok, _} = CommonAPI.delete(create_activity.id, another_user)
+
+ Task.await(task)
+ end
+
+ test "it sends conversation update to the 'direct' stream when a message is deleted" do
+ user = insert(:user)
+ another_user = insert(:user)
+
+ {:ok, create_activity} =
+ CommonAPI.post(another_user, %{
+ "status" => "hi @#{user.nickname}",
+ "visibility" => "direct"
+ })
+
+ {:ok, create_activity2} =
+ CommonAPI.post(another_user, %{
+ "status" => "hi @#{user.nickname}",
+ "in_reply_to_status_id" => create_activity.id,
+ "visibility" => "direct"
+ })
+
+ task =
+ Task.async(fn ->
+ assert_receive {:text, received_event}, 4_000
+ assert %{"event" => "delete", "payload" => _} = Jason.decode!(received_event)
+
+ assert_receive {:text, received_event}, 4_000
+
+ assert %{"event" => "conversation", "payload" => received_payload} =
+ Jason.decode!(received_event)
+
+ assert %{"last_status" => last_status} = Jason.decode!(received_payload)
+ assert last_status["id"] == to_string(create_activity.id)
+ end)
+
+ Streamer.add_socket(
+ "direct",
+ %{transport_pid: task.pid, assigns: %{user: user}}
+ )
+
+ {:ok, _} = CommonAPI.delete(create_activity2.id, another_user)
+
+ Task.await(task)
+ end
+ end
end
diff --git a/test/web/twitter_api/password_controller_test.exs b/test/web/twitter_api/password_controller_test.exs
new file mode 100644
index 000000000..6b9da8204
--- /dev/null
+++ b/test/web/twitter_api/password_controller_test.exs
@@ -0,0 +1,56 @@
+defmodule Pleroma.Web.TwitterAPI.PasswordControllerTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.PasswordResetToken
+ alias Pleroma.Web.OAuth.Token
+ import Pleroma.Factory
+
+ describe "GET /api/pleroma/password_reset/token" do
+ test "it returns error when token invalid", %{conn: conn} do
+ response =
+ conn
+ |> get("/api/pleroma/password_reset/token")
+ |> html_response(:ok)
+
+ assert response =~ "Invalid Token "
+ end
+
+ test "it shows password reset form", %{conn: conn} do
+ user = insert(:user)
+ {:ok, token} = PasswordResetToken.create_token(user)
+
+ response =
+ conn
+ |> get("/api/pleroma/password_reset/#{token.token}")
+ |> html_response(:ok)
+
+ assert response =~ "Password Reset for #{user.nickname} "
+ end
+ end
+
+ describe "POST /api/pleroma/password_reset" do
+ test "it returns HTTP 200", %{conn: conn} do
+ user = insert(:user)
+ {:ok, token} = PasswordResetToken.create_token(user)
+ {:ok, _access_token} = Token.create_token(insert(:oauth_app), user, %{})
+
+ params = %{
+ "password" => "test",
+ password_confirmation: "test",
+ token: token.token
+ }
+
+ response =
+ conn
+ |> assign(:user, user)
+ |> post("/api/pleroma/password_reset", %{data: params})
+ |> html_response(:ok)
+
+ assert response =~ "Password changed! "
+
+ user = refresh_record(user)
+ assert Comeonin.Pbkdf2.checkpw("test", user.password_hash)
+ assert length(Token.get_user_tokens(user)) == 0
+ end
+ end
+end