tests consistency
This commit is contained in:
parent
6bf85440b3
commit
7dffaef479
258 changed files with 38 additions and 37 deletions
|
|
@ -1,75 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.AdminSecretAuthenticationPlugTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Mock
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Plugs.AdminSecretAuthenticationPlug
|
||||
alias Pleroma.Plugs.OAuthScopesPlug
|
||||
alias Pleroma.Plugs.PlugHelper
|
||||
alias Pleroma.Plugs.RateLimiter
|
||||
|
||||
test "does nothing if a user is assigned", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|
||||
ret_conn =
|
||||
conn
|
||||
|> AdminSecretAuthenticationPlug.call(%{})
|
||||
|
||||
assert conn == ret_conn
|
||||
end
|
||||
|
||||
describe "when secret set it assigns an admin user" do
|
||||
setup do: clear_config([:admin_token])
|
||||
|
||||
setup_with_mocks([{RateLimiter, [:passthrough], []}]) do
|
||||
:ok
|
||||
end
|
||||
|
||||
test "with `admin_token` query parameter", %{conn: conn} do
|
||||
Pleroma.Config.put(:admin_token, "password123")
|
||||
|
||||
conn =
|
||||
%{conn | params: %{"admin_token" => "wrong_password"}}
|
||||
|> AdminSecretAuthenticationPlug.call(%{})
|
||||
|
||||
refute conn.assigns[:user]
|
||||
assert called(RateLimiter.call(conn, name: :authentication))
|
||||
|
||||
conn =
|
||||
%{conn | params: %{"admin_token" => "password123"}}
|
||||
|> AdminSecretAuthenticationPlug.call(%{})
|
||||
|
||||
assert conn.assigns[:user].is_admin
|
||||
assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug)
|
||||
end
|
||||
|
||||
test "with `x-admin-token` HTTP header", %{conn: conn} do
|
||||
Pleroma.Config.put(:admin_token, "☕️")
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("x-admin-token", "🥛")
|
||||
|> AdminSecretAuthenticationPlug.call(%{})
|
||||
|
||||
refute conn.assigns[:user]
|
||||
assert called(RateLimiter.call(conn, name: :authentication))
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("x-admin-token", "☕️")
|
||||
|> AdminSecretAuthenticationPlug.call(%{})
|
||||
|
||||
assert conn.assigns[:user].is_admin
|
||||
assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.AuthenticationPlugTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
alias Pleroma.Plugs.AuthenticationPlug
|
||||
alias Pleroma.Plugs.OAuthScopesPlug
|
||||
alias Pleroma.Plugs.PlugHelper
|
||||
alias Pleroma.User
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
import Pleroma.Factory
|
||||
|
||||
setup %{conn: conn} do
|
||||
user = %User{
|
||||
id: 1,
|
||||
name: "dude",
|
||||
password_hash: Pbkdf2.hash_pwd_salt("guy")
|
||||
}
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:auth_user, user)
|
||||
|
||||
%{user: user, conn: conn}
|
||||
end
|
||||
|
||||
test "it does nothing if a user is assigned", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, %User{})
|
||||
|
||||
ret_conn =
|
||||
conn
|
||||
|> AuthenticationPlug.call(%{})
|
||||
|
||||
assert ret_conn == conn
|
||||
end
|
||||
|
||||
test "with a correct password in the credentials, " <>
|
||||
"it assigns the auth_user and marks OAuthScopesPlug as skipped",
|
||||
%{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> assign(:auth_credentials, %{password: "guy"})
|
||||
|> AuthenticationPlug.call(%{})
|
||||
|
||||
assert conn.assigns.user == conn.assigns.auth_user
|
||||
assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug)
|
||||
end
|
||||
|
||||
test "with a bcrypt hash, it updates to a pkbdf2 hash", %{conn: conn} do
|
||||
user = insert(:user, password_hash: Bcrypt.hash_pwd_salt("123"))
|
||||
assert "$2" <> _ = user.password_hash
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:auth_user, user)
|
||||
|> assign(:auth_credentials, %{password: "123"})
|
||||
|> AuthenticationPlug.call(%{})
|
||||
|
||||
assert conn.assigns.user.id == conn.assigns.auth_user.id
|
||||
assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug)
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert "$pbkdf2" <> _ = user.password_hash
|
||||
end
|
||||
|
||||
@tag :skip_on_mac
|
||||
test "with a crypt hash, it updates to a pkbdf2 hash", %{conn: conn} do
|
||||
user =
|
||||
insert(:user,
|
||||
password_hash:
|
||||
"$6$9psBWV8gxkGOZWBz$PmfCycChoxeJ3GgGzwvhlgacb9mUoZ.KUXNCssekER4SJ7bOK53uXrHNb2e4i8yPFgSKyzaW9CcmrDXWIEMtD1"
|
||||
)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:auth_user, user)
|
||||
|> assign(:auth_credentials, %{password: "password"})
|
||||
|> AuthenticationPlug.call(%{})
|
||||
|
||||
assert conn.assigns.user.id == conn.assigns.auth_user.id
|
||||
assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug)
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert "$pbkdf2" <> _ = user.password_hash
|
||||
end
|
||||
|
||||
describe "checkpw/2" do
|
||||
test "check pbkdf2 hash" do
|
||||
hash =
|
||||
"$pbkdf2-sha512$160000$loXqbp8GYls43F0i6lEfIw$AY.Ep.2pGe57j2hAPY635sI/6w7l9Q9u9Bp02PkPmF3OrClDtJAI8bCiivPr53OKMF7ph6iHhN68Rom5nEfC2A"
|
||||
|
||||
assert AuthenticationPlug.checkpw("test-password", hash)
|
||||
refute AuthenticationPlug.checkpw("test-password1", hash)
|
||||
end
|
||||
|
||||
@tag :skip_on_mac
|
||||
test "check sha512-crypt hash" do
|
||||
hash =
|
||||
"$6$9psBWV8gxkGOZWBz$PmfCycChoxeJ3GgGzwvhlgacb9mUoZ.KUXNCssekER4SJ7bOK53uXrHNb2e4i8yPFgSKyzaW9CcmrDXWIEMtD1"
|
||||
|
||||
assert AuthenticationPlug.checkpw("password", hash)
|
||||
end
|
||||
|
||||
test "check bcrypt hash" do
|
||||
hash = "$2a$10$uyhC/R/zoE1ndwwCtMusK.TLVzkQ/Ugsbqp3uXI.CTTz0gBw.24jS"
|
||||
|
||||
assert AuthenticationPlug.checkpw("password", hash)
|
||||
refute AuthenticationPlug.checkpw("password1", hash)
|
||||
end
|
||||
|
||||
test "it returns false when hash invalid" do
|
||||
hash =
|
||||
"psBWV8gxkGOZWBz$PmfCycChoxeJ3GgGzwvhlgacb9mUoZ.KUXNCssekER4SJ7bOK53uXrHNb2e4i8yPFgSKyzaW9CcmrDXWIEMtD1"
|
||||
|
||||
assert capture_log(fn ->
|
||||
refute Pleroma.Plugs.AuthenticationPlug.checkpw("password", hash)
|
||||
end) =~ "[error] Password hash not recognized"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.BasicAuthDecoderPlugTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
alias Pleroma.Plugs.BasicAuthDecoderPlug
|
||||
|
||||
defp basic_auth_enc(username, password) do
|
||||
"Basic " <> Base.encode64("#{username}:#{password}")
|
||||
end
|
||||
|
||||
test "it puts the decoded credentials into the assigns", %{conn: conn} do
|
||||
header = basic_auth_enc("moonman", "iloverobek")
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("authorization", header)
|
||||
|> BasicAuthDecoderPlug.call(%{})
|
||||
|
||||
assert conn.assigns[:auth_credentials] == %{
|
||||
username: "moonman",
|
||||
password: "iloverobek"
|
||||
}
|
||||
end
|
||||
|
||||
test "without a authorization header it doesn't do anything", %{conn: conn} do
|
||||
ret_conn =
|
||||
conn
|
||||
|> BasicAuthDecoderPlug.call(%{})
|
||||
|
||||
assert conn == ret_conn
|
||||
end
|
||||
end
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.CacheControlTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
alias Plug.Conn
|
||||
|
||||
test "Verify Cache-Control header on static assets", %{conn: conn} do
|
||||
conn = get(conn, "/index.html")
|
||||
|
||||
assert Conn.get_resp_header(conn, "cache-control") == ["public, no-cache"]
|
||||
end
|
||||
|
||||
test "Verify Cache-Control header on the API", %{conn: conn} do
|
||||
conn = get(conn, "/api/v1/instance")
|
||||
|
||||
assert Conn.get_resp_header(conn, "cache-control") == ["max-age=0, private, must-revalidate"]
|
||||
end
|
||||
end
|
||||
|
|
@ -1,186 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.CacheTest do
|
||||
use ExUnit.Case, async: true
|
||||
use Plug.Test
|
||||
|
||||
alias Pleroma.Plugs.Cache
|
||||
|
||||
@miss_resp {200,
|
||||
[
|
||||
{"cache-control", "max-age=0, private, must-revalidate"},
|
||||
{"content-type", "cofe/hot; charset=utf-8"},
|
||||
{"x-cache", "MISS from Pleroma"}
|
||||
], "cofe"}
|
||||
|
||||
@hit_resp {200,
|
||||
[
|
||||
{"cache-control", "max-age=0, private, must-revalidate"},
|
||||
{"content-type", "cofe/hot; charset=utf-8"},
|
||||
{"x-cache", "HIT from Pleroma"}
|
||||
], "cofe"}
|
||||
|
||||
@ttl 5
|
||||
|
||||
setup do
|
||||
Cachex.clear(:web_resp_cache)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "caches a response" do
|
||||
assert @miss_resp ==
|
||||
conn(:get, "/")
|
||||
|> Cache.call(%{query_params: false, ttl: nil})
|
||||
|> put_resp_content_type("cofe/hot")
|
||||
|> send_resp(:ok, "cofe")
|
||||
|> sent_resp()
|
||||
|
||||
assert_raise(Plug.Conn.AlreadySentError, fn ->
|
||||
conn(:get, "/")
|
||||
|> Cache.call(%{query_params: false, ttl: nil})
|
||||
|> put_resp_content_type("cofe/hot")
|
||||
|> send_resp(:ok, "cofe")
|
||||
|> sent_resp()
|
||||
end)
|
||||
|
||||
assert @hit_resp ==
|
||||
conn(:get, "/")
|
||||
|> Cache.call(%{query_params: false, ttl: nil})
|
||||
|> sent_resp()
|
||||
end
|
||||
|
||||
test "ttl is set" do
|
||||
assert @miss_resp ==
|
||||
conn(:get, "/")
|
||||
|> Cache.call(%{query_params: false, ttl: @ttl})
|
||||
|> put_resp_content_type("cofe/hot")
|
||||
|> send_resp(:ok, "cofe")
|
||||
|> sent_resp()
|
||||
|
||||
assert @hit_resp ==
|
||||
conn(:get, "/")
|
||||
|> Cache.call(%{query_params: false, ttl: @ttl})
|
||||
|> sent_resp()
|
||||
|
||||
:timer.sleep(@ttl + 1)
|
||||
|
||||
assert @miss_resp ==
|
||||
conn(:get, "/")
|
||||
|> Cache.call(%{query_params: false, ttl: @ttl})
|
||||
|> put_resp_content_type("cofe/hot")
|
||||
|> send_resp(:ok, "cofe")
|
||||
|> sent_resp()
|
||||
end
|
||||
|
||||
test "set ttl via conn.assigns" do
|
||||
assert @miss_resp ==
|
||||
conn(:get, "/")
|
||||
|> Cache.call(%{query_params: false, ttl: nil})
|
||||
|> put_resp_content_type("cofe/hot")
|
||||
|> assign(:cache_ttl, @ttl)
|
||||
|> send_resp(:ok, "cofe")
|
||||
|> sent_resp()
|
||||
|
||||
assert @hit_resp ==
|
||||
conn(:get, "/")
|
||||
|> Cache.call(%{query_params: false, ttl: nil})
|
||||
|> sent_resp()
|
||||
|
||||
:timer.sleep(@ttl + 1)
|
||||
|
||||
assert @miss_resp ==
|
||||
conn(:get, "/")
|
||||
|> Cache.call(%{query_params: false, ttl: nil})
|
||||
|> put_resp_content_type("cofe/hot")
|
||||
|> send_resp(:ok, "cofe")
|
||||
|> sent_resp()
|
||||
end
|
||||
|
||||
test "ignore query string when `query_params` is false" do
|
||||
assert @miss_resp ==
|
||||
conn(:get, "/?cofe")
|
||||
|> Cache.call(%{query_params: false, ttl: nil})
|
||||
|> put_resp_content_type("cofe/hot")
|
||||
|> send_resp(:ok, "cofe")
|
||||
|> sent_resp()
|
||||
|
||||
assert @hit_resp ==
|
||||
conn(:get, "/?cofefe")
|
||||
|> Cache.call(%{query_params: false, ttl: nil})
|
||||
|> sent_resp()
|
||||
end
|
||||
|
||||
test "take query string into account when `query_params` is true" do
|
||||
assert @miss_resp ==
|
||||
conn(:get, "/?cofe")
|
||||
|> Cache.call(%{query_params: true, ttl: nil})
|
||||
|> put_resp_content_type("cofe/hot")
|
||||
|> send_resp(:ok, "cofe")
|
||||
|> sent_resp()
|
||||
|
||||
assert @miss_resp ==
|
||||
conn(:get, "/?cofefe")
|
||||
|> Cache.call(%{query_params: true, ttl: nil})
|
||||
|> put_resp_content_type("cofe/hot")
|
||||
|> send_resp(:ok, "cofe")
|
||||
|> sent_resp()
|
||||
end
|
||||
|
||||
test "take specific query params into account when `query_params` is list" do
|
||||
assert @miss_resp ==
|
||||
conn(:get, "/?a=1&b=2&c=3&foo=bar")
|
||||
|> fetch_query_params()
|
||||
|> Cache.call(%{query_params: ["a", "b", "c"], ttl: nil})
|
||||
|> put_resp_content_type("cofe/hot")
|
||||
|> send_resp(:ok, "cofe")
|
||||
|> sent_resp()
|
||||
|
||||
assert @hit_resp ==
|
||||
conn(:get, "/?bar=foo&c=3&b=2&a=1")
|
||||
|> fetch_query_params()
|
||||
|> Cache.call(%{query_params: ["a", "b", "c"], ttl: nil})
|
||||
|> sent_resp()
|
||||
|
||||
assert @miss_resp ==
|
||||
conn(:get, "/?bar=foo&c=3&b=2&a=2")
|
||||
|> fetch_query_params()
|
||||
|> Cache.call(%{query_params: ["a", "b", "c"], ttl: nil})
|
||||
|> put_resp_content_type("cofe/hot")
|
||||
|> send_resp(:ok, "cofe")
|
||||
|> sent_resp()
|
||||
end
|
||||
|
||||
test "ignore not GET requests" do
|
||||
expected =
|
||||
{200,
|
||||
[
|
||||
{"cache-control", "max-age=0, private, must-revalidate"},
|
||||
{"content-type", "cofe/hot; charset=utf-8"}
|
||||
], "cofe"}
|
||||
|
||||
assert expected ==
|
||||
conn(:post, "/")
|
||||
|> Cache.call(%{query_params: true, ttl: nil})
|
||||
|> put_resp_content_type("cofe/hot")
|
||||
|> send_resp(:ok, "cofe")
|
||||
|> sent_resp()
|
||||
end
|
||||
|
||||
test "ignore non-successful responses" do
|
||||
expected =
|
||||
{418,
|
||||
[
|
||||
{"cache-control", "max-age=0, private, must-revalidate"},
|
||||
{"content-type", "tea/iced; charset=utf-8"}
|
||||
], "🥤"}
|
||||
|
||||
assert expected ==
|
||||
conn(:get, "/cofe")
|
||||
|> Cache.call(%{query_params: true, ttl: nil})
|
||||
|> put_resp_content_type("tea/iced")
|
||||
|> send_resp(:im_a_teapot, "🥤")
|
||||
|> sent_resp()
|
||||
end
|
||||
end
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.EnsureAuthenticatedPlugTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
alias Pleroma.Plugs.EnsureAuthenticatedPlug
|
||||
alias Pleroma.User
|
||||
|
||||
describe "without :if_func / :unless_func options" do
|
||||
test "it halts if user is NOT assigned", %{conn: conn} do
|
||||
conn = EnsureAuthenticatedPlug.call(conn, %{})
|
||||
|
||||
assert conn.status == 403
|
||||
assert conn.halted == true
|
||||
end
|
||||
|
||||
test "it continues if a user is assigned", %{conn: conn} do
|
||||
conn = assign(conn, :user, %User{})
|
||||
ret_conn = EnsureAuthenticatedPlug.call(conn, %{})
|
||||
|
||||
refute ret_conn.halted
|
||||
end
|
||||
end
|
||||
|
||||
test "it halts if user is assigned and MFA enabled", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, %User{multi_factor_authentication_settings: %{enabled: true}})
|
||||
|> assign(:auth_credentials, %{password: "xd-42"})
|
||||
|> EnsureAuthenticatedPlug.call(%{})
|
||||
|
||||
assert conn.status == 403
|
||||
assert conn.halted == true
|
||||
|
||||
assert conn.resp_body ==
|
||||
"{\"error\":\"Two-factor authentication enabled, you must use a access token.\"}"
|
||||
end
|
||||
|
||||
test "it continues if user is assigned and MFA disabled", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, %User{multi_factor_authentication_settings: %{enabled: false}})
|
||||
|> assign(:auth_credentials, %{password: "xd-42"})
|
||||
|> EnsureAuthenticatedPlug.call(%{})
|
||||
|
||||
refute conn.status == 403
|
||||
refute conn.halted
|
||||
end
|
||||
|
||||
describe "with :if_func / :unless_func options" do
|
||||
setup do
|
||||
%{
|
||||
true_fn: fn _conn -> true end,
|
||||
false_fn: fn _conn -> false end
|
||||
}
|
||||
end
|
||||
|
||||
test "it continues if a user is assigned", %{conn: conn, true_fn: true_fn, false_fn: false_fn} do
|
||||
conn = assign(conn, :user, %User{})
|
||||
refute EnsureAuthenticatedPlug.call(conn, if_func: true_fn).halted
|
||||
refute EnsureAuthenticatedPlug.call(conn, if_func: false_fn).halted
|
||||
refute EnsureAuthenticatedPlug.call(conn, unless_func: true_fn).halted
|
||||
refute EnsureAuthenticatedPlug.call(conn, unless_func: false_fn).halted
|
||||
end
|
||||
|
||||
test "it continues if a user is NOT assigned but :if_func evaluates to `false`",
|
||||
%{conn: conn, false_fn: false_fn} do
|
||||
ret_conn = EnsureAuthenticatedPlug.call(conn, if_func: false_fn)
|
||||
refute ret_conn.halted
|
||||
end
|
||||
|
||||
test "it continues if a user is NOT assigned but :unless_func evaluates to `true`",
|
||||
%{conn: conn, true_fn: true_fn} do
|
||||
ret_conn = EnsureAuthenticatedPlug.call(conn, unless_func: true_fn)
|
||||
refute ret_conn.halted
|
||||
end
|
||||
|
||||
test "it halts if a user is NOT assigned and :if_func evaluates to `true`",
|
||||
%{conn: conn, true_fn: true_fn} do
|
||||
conn = EnsureAuthenticatedPlug.call(conn, if_func: true_fn)
|
||||
|
||||
assert conn.status == 403
|
||||
assert conn.halted == true
|
||||
end
|
||||
|
||||
test "it halts if a user is NOT assigned and :unless_func evaluates to `false`",
|
||||
%{conn: conn, false_fn: false_fn} do
|
||||
conn = EnsureAuthenticatedPlug.call(conn, unless_func: false_fn)
|
||||
|
||||
assert conn.status == 403
|
||||
assert conn.halted == true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.EnsurePublicOrAuthenticatedPlugTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
|
||||
alias Pleroma.User
|
||||
|
||||
setup do: clear_config([:instance, :public])
|
||||
|
||||
test "it halts if not public and no user is assigned", %{conn: conn} do
|
||||
Config.put([:instance, :public], false)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> EnsurePublicOrAuthenticatedPlug.call(%{})
|
||||
|
||||
assert conn.status == 403
|
||||
assert conn.halted == true
|
||||
end
|
||||
|
||||
test "it continues if public", %{conn: conn} do
|
||||
Config.put([:instance, :public], true)
|
||||
|
||||
ret_conn =
|
||||
conn
|
||||
|> EnsurePublicOrAuthenticatedPlug.call(%{})
|
||||
|
||||
refute ret_conn.halted
|
||||
end
|
||||
|
||||
test "it continues if a user is assigned, even if not public", %{conn: conn} do
|
||||
Config.put([:instance, :public], false)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, %User{})
|
||||
|
||||
ret_conn =
|
||||
conn
|
||||
|> EnsurePublicOrAuthenticatedPlug.call(%{})
|
||||
|
||||
refute ret_conn.halted
|
||||
end
|
||||
end
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.EnsureUserKeyPlugTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
alias Pleroma.Plugs.EnsureUserKeyPlug
|
||||
|
||||
test "if the conn has a user key set, it does nothing", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, 1)
|
||||
|
||||
ret_conn =
|
||||
conn
|
||||
|> EnsureUserKeyPlug.call(%{})
|
||||
|
||||
assert conn == ret_conn
|
||||
end
|
||||
|
||||
test "if the conn has no key set, it sets it to nil", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> EnsureUserKeyPlug.call(%{})
|
||||
|
||||
assert Map.has_key?(conn.assigns, :user)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Plugs.HTTPSecurityPlugTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Config
|
||||
alias Plug.Conn
|
||||
|
||||
describe "http security enabled" do
|
||||
setup do: clear_config([:http_security, :enabled], true)
|
||||
|
||||
test "it sends CSP headers when enabled", %{conn: conn} do
|
||||
conn = get(conn, "/api/v1/instance")
|
||||
|
||||
refute Conn.get_resp_header(conn, "x-xss-protection") == []
|
||||
refute Conn.get_resp_header(conn, "x-permitted-cross-domain-policies") == []
|
||||
refute Conn.get_resp_header(conn, "x-frame-options") == []
|
||||
refute Conn.get_resp_header(conn, "x-content-type-options") == []
|
||||
refute Conn.get_resp_header(conn, "x-download-options") == []
|
||||
refute Conn.get_resp_header(conn, "referrer-policy") == []
|
||||
refute Conn.get_resp_header(conn, "content-security-policy") == []
|
||||
end
|
||||
|
||||
test "it sends STS headers when enabled", %{conn: conn} do
|
||||
clear_config([:http_security, :sts], true)
|
||||
|
||||
conn = get(conn, "/api/v1/instance")
|
||||
|
||||
refute Conn.get_resp_header(conn, "strict-transport-security") == []
|
||||
refute Conn.get_resp_header(conn, "expect-ct") == []
|
||||
end
|
||||
|
||||
test "it does not send STS headers when disabled", %{conn: conn} do
|
||||
clear_config([:http_security, :sts], false)
|
||||
|
||||
conn = get(conn, "/api/v1/instance")
|
||||
|
||||
assert Conn.get_resp_header(conn, "strict-transport-security") == []
|
||||
assert Conn.get_resp_header(conn, "expect-ct") == []
|
||||
end
|
||||
|
||||
test "referrer-policy header reflects configured value", %{conn: conn} do
|
||||
resp = get(conn, "/api/v1/instance")
|
||||
|
||||
assert Conn.get_resp_header(resp, "referrer-policy") == ["same-origin"]
|
||||
|
||||
clear_config([:http_security, :referrer_policy], "no-referrer")
|
||||
|
||||
resp = get(conn, "/api/v1/instance")
|
||||
|
||||
assert Conn.get_resp_header(resp, "referrer-policy") == ["no-referrer"]
|
||||
end
|
||||
|
||||
test "it sends `report-to` & `report-uri` CSP response headers", %{conn: conn} do
|
||||
conn = get(conn, "/api/v1/instance")
|
||||
|
||||
[csp] = Conn.get_resp_header(conn, "content-security-policy")
|
||||
|
||||
assert csp =~ ~r|report-uri https://endpoint.com;report-to csp-endpoint;|
|
||||
|
||||
[reply_to] = Conn.get_resp_header(conn, "reply-to")
|
||||
|
||||
assert reply_to ==
|
||||
"{\"endpoints\":[{\"url\":\"https://endpoint.com\"}],\"group\":\"csp-endpoint\",\"max-age\":10886400}"
|
||||
end
|
||||
|
||||
test "default values for img-src and media-src with disabled media proxy", %{conn: conn} do
|
||||
conn = get(conn, "/api/v1/instance")
|
||||
|
||||
[csp] = Conn.get_resp_header(conn, "content-security-policy")
|
||||
assert csp =~ "media-src 'self' https:;"
|
||||
assert csp =~ "img-src 'self' data: blob: https:;"
|
||||
end
|
||||
end
|
||||
|
||||
describe "img-src and media-src" do
|
||||
setup do
|
||||
clear_config([:http_security, :enabled], true)
|
||||
clear_config([:media_proxy, :enabled], true)
|
||||
clear_config([:media_proxy, :proxy_opts, :redirect_on_failure], false)
|
||||
end
|
||||
|
||||
test "media_proxy with base_url", %{conn: conn} do
|
||||
url = "https://example.com"
|
||||
clear_config([:media_proxy, :base_url], url)
|
||||
assert_media_img_src(conn, url)
|
||||
end
|
||||
|
||||
test "upload with base url", %{conn: conn} do
|
||||
url = "https://example2.com"
|
||||
clear_config([Pleroma.Upload, :base_url], url)
|
||||
assert_media_img_src(conn, url)
|
||||
end
|
||||
|
||||
test "with S3 public endpoint", %{conn: conn} do
|
||||
url = "https://example3.com"
|
||||
clear_config([Pleroma.Uploaders.S3, :public_endpoint], url)
|
||||
assert_media_img_src(conn, url)
|
||||
end
|
||||
|
||||
test "with captcha endpoint", %{conn: conn} do
|
||||
clear_config([Pleroma.Captcha.Mock, :endpoint], "https://captcha.com")
|
||||
assert_media_img_src(conn, "https://captcha.com")
|
||||
end
|
||||
|
||||
test "with media_proxy whitelist", %{conn: conn} do
|
||||
clear_config([:media_proxy, :whitelist], ["https://example6.com", "https://example7.com"])
|
||||
assert_media_img_src(conn, "https://example7.com https://example6.com")
|
||||
end
|
||||
|
||||
# TODO: delete after removing support bare domains for media proxy whitelist
|
||||
test "with media_proxy bare domains whitelist (deprecated)", %{conn: conn} do
|
||||
clear_config([:media_proxy, :whitelist], ["example4.com", "example5.com"])
|
||||
assert_media_img_src(conn, "example5.com example4.com")
|
||||
end
|
||||
end
|
||||
|
||||
defp assert_media_img_src(conn, url) do
|
||||
conn = get(conn, "/api/v1/instance")
|
||||
[csp] = Conn.get_resp_header(conn, "content-security-policy")
|
||||
assert csp =~ "media-src 'self' #{url};"
|
||||
assert csp =~ "img-src 'self' data: blob: #{url};"
|
||||
end
|
||||
|
||||
test "it does not send CSP headers when disabled", %{conn: conn} do
|
||||
clear_config([:http_security, :enabled], false)
|
||||
|
||||
conn = get(conn, "/api/v1/instance")
|
||||
|
||||
assert Conn.get_resp_header(conn, "x-xss-protection") == []
|
||||
assert Conn.get_resp_header(conn, "x-permitted-cross-domain-policies") == []
|
||||
assert Conn.get_resp_header(conn, "x-frame-options") == []
|
||||
assert Conn.get_resp_header(conn, "x-content-type-options") == []
|
||||
assert Conn.get_resp_header(conn, "x-download-options") == []
|
||||
assert Conn.get_resp_header(conn, "referrer-policy") == []
|
||||
assert Conn.get_resp_header(conn, "content-security-policy") == []
|
||||
end
|
||||
end
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Plugs.HTTPSignaturePlugTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
alias Pleroma.Web.Plugs.HTTPSignaturePlug
|
||||
|
||||
import Plug.Conn
|
||||
import Phoenix.Controller, only: [put_format: 2]
|
||||
import Mock
|
||||
|
||||
test "it call HTTPSignatures to check validity if the actor sighed it" do
|
||||
params = %{"actor" => "http://mastodon.example.org/users/admin"}
|
||||
conn = build_conn(:get, "/doesntmattter", params)
|
||||
|
||||
with_mock HTTPSignatures, validate_conn: fn _ -> true end do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header(
|
||||
"signature",
|
||||
"keyId=\"http://mastodon.example.org/users/admin#main-key"
|
||||
)
|
||||
|> put_format("activity+json")
|
||||
|> HTTPSignaturePlug.call(%{})
|
||||
|
||||
assert conn.assigns.valid_signature == true
|
||||
assert conn.halted == false
|
||||
assert called(HTTPSignatures.validate_conn(:_))
|
||||
end
|
||||
end
|
||||
|
||||
describe "requires a signature when `authorized_fetch_mode` is enabled" do
|
||||
setup do
|
||||
Pleroma.Config.put([:activitypub, :authorized_fetch_mode], true)
|
||||
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put([:activitypub, :authorized_fetch_mode], false)
|
||||
end)
|
||||
|
||||
params = %{"actor" => "http://mastodon.example.org/users/admin"}
|
||||
conn = build_conn(:get, "/doesntmattter", params) |> put_format("activity+json")
|
||||
|
||||
[conn: conn]
|
||||
end
|
||||
|
||||
test "when signature header is present", %{conn: conn} do
|
||||
with_mock HTTPSignatures, validate_conn: fn _ -> false end do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header(
|
||||
"signature",
|
||||
"keyId=\"http://mastodon.example.org/users/admin#main-key"
|
||||
)
|
||||
|> HTTPSignaturePlug.call(%{})
|
||||
|
||||
assert conn.assigns.valid_signature == false
|
||||
assert conn.halted == true
|
||||
assert conn.status == 401
|
||||
assert conn.state == :sent
|
||||
assert conn.resp_body == "Request not signed"
|
||||
assert called(HTTPSignatures.validate_conn(:_))
|
||||
end
|
||||
|
||||
with_mock HTTPSignatures, validate_conn: fn _ -> true end do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header(
|
||||
"signature",
|
||||
"keyId=\"http://mastodon.example.org/users/admin#main-key"
|
||||
)
|
||||
|> HTTPSignaturePlug.call(%{})
|
||||
|
||||
assert conn.assigns.valid_signature == true
|
||||
assert conn.halted == false
|
||||
assert called(HTTPSignatures.validate_conn(:_))
|
||||
end
|
||||
end
|
||||
|
||||
test "halts the connection when `signature` header is not present", %{conn: conn} do
|
||||
conn = HTTPSignaturePlug.call(conn, %{})
|
||||
assert conn.assigns[:valid_signature] == nil
|
||||
assert conn.halted == true
|
||||
assert conn.status == 401
|
||||
assert conn.state == :sent
|
||||
assert conn.resp_body == "Request not signed"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.IdempotencyPlugTest do
|
||||
use ExUnit.Case, async: true
|
||||
use Plug.Test
|
||||
|
||||
alias Pleroma.Plugs.IdempotencyPlug
|
||||
alias Plug.Conn
|
||||
|
||||
test "returns result from cache" do
|
||||
key = "test1"
|
||||
orig_request_id = "test1"
|
||||
second_request_id = "test2"
|
||||
body = "testing"
|
||||
status = 200
|
||||
|
||||
:post
|
||||
|> conn("/cofe")
|
||||
|> put_req_header("idempotency-key", key)
|
||||
|> Conn.put_resp_header("x-request-id", orig_request_id)
|
||||
|> Conn.put_resp_content_type("application/json")
|
||||
|> IdempotencyPlug.call([])
|
||||
|> Conn.send_resp(status, body)
|
||||
|
||||
conn =
|
||||
:post
|
||||
|> conn("/cofe")
|
||||
|> put_req_header("idempotency-key", key)
|
||||
|> Conn.put_resp_header("x-request-id", second_request_id)
|
||||
|> Conn.put_resp_content_type("application/json")
|
||||
|> IdempotencyPlug.call([])
|
||||
|
||||
assert_raise Conn.AlreadySentError, fn ->
|
||||
Conn.send_resp(conn, :im_a_teapot, "no cofe")
|
||||
end
|
||||
|
||||
assert conn.resp_body == body
|
||||
assert conn.status == status
|
||||
|
||||
assert [^second_request_id] = Conn.get_resp_header(conn, "x-request-id")
|
||||
assert [^orig_request_id] = Conn.get_resp_header(conn, "x-original-request-id")
|
||||
assert [^key] = Conn.get_resp_header(conn, "idempotency-key")
|
||||
assert ["true"] = Conn.get_resp_header(conn, "idempotent-replayed")
|
||||
assert ["application/json; charset=utf-8"] = Conn.get_resp_header(conn, "content-type")
|
||||
end
|
||||
|
||||
test "pass conn downstream if the cache not found" do
|
||||
key = "test2"
|
||||
orig_request_id = "test3"
|
||||
body = "testing"
|
||||
status = 200
|
||||
|
||||
conn =
|
||||
:post
|
||||
|> conn("/cofe")
|
||||
|> put_req_header("idempotency-key", key)
|
||||
|> Conn.put_resp_header("x-request-id", orig_request_id)
|
||||
|> Conn.put_resp_content_type("application/json")
|
||||
|> IdempotencyPlug.call([])
|
||||
|> Conn.send_resp(status, body)
|
||||
|
||||
assert conn.resp_body == body
|
||||
assert conn.status == status
|
||||
|
||||
assert [] = Conn.get_resp_header(conn, "idempotent-replayed")
|
||||
assert [^key] = Conn.get_resp_header(conn, "idempotency-key")
|
||||
end
|
||||
|
||||
test "passes conn downstream if idempotency is not present in headers" do
|
||||
orig_request_id = "test4"
|
||||
body = "testing"
|
||||
status = 200
|
||||
|
||||
conn =
|
||||
:post
|
||||
|> conn("/cofe")
|
||||
|> Conn.put_resp_header("x-request-id", orig_request_id)
|
||||
|> Conn.put_resp_content_type("application/json")
|
||||
|> IdempotencyPlug.call([])
|
||||
|> Conn.send_resp(status, body)
|
||||
|
||||
assert [] = Conn.get_resp_header(conn, "idempotency-key")
|
||||
end
|
||||
|
||||
test "doesn't work with GET/DELETE" do
|
||||
key = "test3"
|
||||
body = "testing"
|
||||
status = 200
|
||||
|
||||
conn =
|
||||
:get
|
||||
|> conn("/cofe")
|
||||
|> put_req_header("idempotency-key", key)
|
||||
|> IdempotencyPlug.call([])
|
||||
|> Conn.send_resp(status, body)
|
||||
|
||||
assert [] = Conn.get_resp_header(conn, "idempotency-key")
|
||||
|
||||
conn =
|
||||
:delete
|
||||
|> conn("/cofe")
|
||||
|> put_req_header("idempotency-key", key)
|
||||
|> IdempotencyPlug.call([])
|
||||
|> Conn.send_resp(status, body)
|
||||
|
||||
assert [] = Conn.get_resp_header(conn, "idempotency-key")
|
||||
end
|
||||
end
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.InstanceStaticPlugTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
@dir "test/tmp/instance_static"
|
||||
|
||||
setup do
|
||||
File.mkdir_p!(@dir)
|
||||
on_exit(fn -> File.rm_rf(@dir) end)
|
||||
end
|
||||
|
||||
setup do: clear_config([:instance, :static_dir], @dir)
|
||||
|
||||
test "overrides index" do
|
||||
bundled_index = get(build_conn(), "/")
|
||||
refute html_response(bundled_index, 200) == "hello world"
|
||||
|
||||
File.write!(@dir <> "/index.html", "hello world")
|
||||
|
||||
index = get(build_conn(), "/")
|
||||
assert html_response(index, 200) == "hello world"
|
||||
end
|
||||
|
||||
test "also overrides frontend files", %{conn: conn} do
|
||||
name = "pelmora"
|
||||
ref = "uguu"
|
||||
|
||||
clear_config([:frontends, :primary], %{"name" => name, "ref" => ref})
|
||||
|
||||
bundled_index = get(conn, "/")
|
||||
refute html_response(bundled_index, 200) == "from frontend plug"
|
||||
|
||||
path = "#{@dir}/frontends/#{name}/#{ref}"
|
||||
File.mkdir_p!(path)
|
||||
File.write!("#{path}/index.html", "from frontend plug")
|
||||
|
||||
index = get(conn, "/")
|
||||
assert html_response(index, 200) == "from frontend plug"
|
||||
|
||||
File.write!(@dir <> "/index.html", "from instance static")
|
||||
|
||||
index = get(conn, "/")
|
||||
assert html_response(index, 200) == "from instance static"
|
||||
end
|
||||
|
||||
test "overrides any file in static/static" do
|
||||
bundled_index = get(build_conn(), "/static/terms-of-service.html")
|
||||
|
||||
assert html_response(bundled_index, 200) ==
|
||||
File.read!("priv/static/static/terms-of-service.html")
|
||||
|
||||
File.mkdir!(@dir <> "/static")
|
||||
File.write!(@dir <> "/static/terms-of-service.html", "plz be kind")
|
||||
|
||||
index = get(build_conn(), "/static/terms-of-service.html")
|
||||
assert html_response(index, 200) == "plz be kind"
|
||||
|
||||
File.write!(@dir <> "/static/kaniini.html", "<h1>rabbit hugs as a service</h1>")
|
||||
index = get(build_conn(), "/static/kaniini.html")
|
||||
assert html_response(index, 200) == "<h1>rabbit hugs as a service</h1>"
|
||||
end
|
||||
end
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.LegacyAuthenticationPlugTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Plugs.LegacyAuthenticationPlug
|
||||
alias Pleroma.Plugs.OAuthScopesPlug
|
||||
alias Pleroma.Plugs.PlugHelper
|
||||
alias Pleroma.User
|
||||
|
||||
setup do
|
||||
user =
|
||||
insert(:user,
|
||||
password: "password",
|
||||
password_hash:
|
||||
"$6$9psBWV8gxkGOZWBz$PmfCycChoxeJ3GgGzwvhlgacb9mUoZ.KUXNCssekER4SJ7bOK53uXrHNb2e4i8yPFgSKyzaW9CcmrDXWIEMtD1"
|
||||
)
|
||||
|
||||
%{user: user}
|
||||
end
|
||||
|
||||
test "it does nothing if a user is assigned", %{conn: conn, user: user} do
|
||||
conn =
|
||||
conn
|
||||
|> assign(:auth_credentials, %{username: "dude", password: "password"})
|
||||
|> assign(:auth_user, user)
|
||||
|> assign(:user, %User{})
|
||||
|
||||
ret_conn =
|
||||
conn
|
||||
|> LegacyAuthenticationPlug.call(%{})
|
||||
|
||||
assert ret_conn == conn
|
||||
end
|
||||
|
||||
@tag :skip_on_mac
|
||||
test "if `auth_user` is present and password is correct, " <>
|
||||
"it authenticates the user, resets the password, marks OAuthScopesPlug as skipped",
|
||||
%{
|
||||
conn: conn,
|
||||
user: user
|
||||
} do
|
||||
conn =
|
||||
conn
|
||||
|> assign(:auth_credentials, %{username: "dude", password: "password"})
|
||||
|> assign(:auth_user, user)
|
||||
|
||||
conn = LegacyAuthenticationPlug.call(conn, %{})
|
||||
|
||||
assert conn.assigns.user.id == user.id
|
||||
assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug)
|
||||
end
|
||||
|
||||
@tag :skip_on_mac
|
||||
test "it does nothing if the password is wrong", %{
|
||||
conn: conn,
|
||||
user: user
|
||||
} do
|
||||
conn =
|
||||
conn
|
||||
|> assign(:auth_credentials, %{username: "dude", password: "wrong_password"})
|
||||
|> assign(:auth_user, user)
|
||||
|
||||
ret_conn =
|
||||
conn
|
||||
|> LegacyAuthenticationPlug.call(%{})
|
||||
|
||||
assert conn == ret_conn
|
||||
end
|
||||
|
||||
test "with no credentials or user it does nothing", %{conn: conn} do
|
||||
ret_conn =
|
||||
conn
|
||||
|> LegacyAuthenticationPlug.call(%{})
|
||||
|
||||
assert ret_conn == conn
|
||||
end
|
||||
end
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Plugs.MappedSignatureToIdentityPlugTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
alias Pleroma.Web.Plugs.MappedSignatureToIdentityPlug
|
||||
|
||||
import Tesla.Mock
|
||||
import Plug.Conn
|
||||
|
||||
setup do
|
||||
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
defp set_signature(conn, key_id) do
|
||||
conn
|
||||
|> put_req_header("signature", "keyId=\"#{key_id}\"")
|
||||
|> assign(:valid_signature, true)
|
||||
end
|
||||
|
||||
test "it successfully maps a valid identity with a valid signature" do
|
||||
conn =
|
||||
build_conn(:get, "/doesntmattter")
|
||||
|> set_signature("http://mastodon.example.org/users/admin")
|
||||
|> MappedSignatureToIdentityPlug.call(%{})
|
||||
|
||||
refute is_nil(conn.assigns.user)
|
||||
end
|
||||
|
||||
test "it successfully maps a valid identity with a valid signature with payload" do
|
||||
conn =
|
||||
build_conn(:post, "/doesntmattter", %{"actor" => "http://mastodon.example.org/users/admin"})
|
||||
|> set_signature("http://mastodon.example.org/users/admin")
|
||||
|> MappedSignatureToIdentityPlug.call(%{})
|
||||
|
||||
refute is_nil(conn.assigns.user)
|
||||
end
|
||||
|
||||
test "it considers a mapped identity to be invalid when it mismatches a payload" do
|
||||
conn =
|
||||
build_conn(:post, "/doesntmattter", %{"actor" => "http://mastodon.example.org/users/admin"})
|
||||
|> set_signature("https://niu.moe/users/rye")
|
||||
|> MappedSignatureToIdentityPlug.call(%{})
|
||||
|
||||
assert %{valid_signature: false} == conn.assigns
|
||||
end
|
||||
|
||||
@tag skip: "known breakage; the testsuite presently depends on it"
|
||||
test "it considers a mapped identity to be invalid when the identity cannot be found" do
|
||||
conn =
|
||||
build_conn(:post, "/doesntmattter", %{"actor" => "http://mastodon.example.org/users/admin"})
|
||||
|> set_signature("http://niu.moe/users/rye")
|
||||
|> MappedSignatureToIdentityPlug.call(%{})
|
||||
|
||||
assert %{valid_signature: false} == conn.assigns
|
||||
end
|
||||
end
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.OAuthPlugTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
alias Pleroma.Plugs.OAuthPlug
|
||||
import Pleroma.Factory
|
||||
|
||||
@session_opts [
|
||||
store: :cookie,
|
||||
key: "_test",
|
||||
signing_salt: "cooldude"
|
||||
]
|
||||
|
||||
setup %{conn: conn} do
|
||||
user = insert(:user)
|
||||
{:ok, %{token: token}} = Pleroma.Web.OAuth.Token.create(insert(:oauth_app), user)
|
||||
%{user: user, token: token, conn: conn}
|
||||
end
|
||||
|
||||
test "with valid token(uppercase), it assigns the user", %{conn: conn} = opts do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("authorization", "BEARER #{opts[:token]}")
|
||||
|> OAuthPlug.call(%{})
|
||||
|
||||
assert conn.assigns[:user] == opts[:user]
|
||||
end
|
||||
|
||||
test "with valid token(downcase), it assigns the user", %{conn: conn} = opts do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("authorization", "bearer #{opts[:token]}")
|
||||
|> OAuthPlug.call(%{})
|
||||
|
||||
assert conn.assigns[:user] == opts[:user]
|
||||
end
|
||||
|
||||
test "with valid token(downcase) in url parameters, it assigns the user", opts do
|
||||
conn =
|
||||
:get
|
||||
|> build_conn("/?access_token=#{opts[:token]}")
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> fetch_query_params()
|
||||
|> OAuthPlug.call(%{})
|
||||
|
||||
assert conn.assigns[:user] == opts[:user]
|
||||
end
|
||||
|
||||
test "with valid token(downcase) in body parameters, it assigns the user", opts do
|
||||
conn =
|
||||
:post
|
||||
|> build_conn("/api/v1/statuses", access_token: opts[:token], status: "test")
|
||||
|> OAuthPlug.call(%{})
|
||||
|
||||
assert conn.assigns[:user] == opts[:user]
|
||||
end
|
||||
|
||||
test "with invalid token, it not assigns the user", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("authorization", "bearer TTTTT")
|
||||
|> OAuthPlug.call(%{})
|
||||
|
||||
refute conn.assigns[:user]
|
||||
end
|
||||
|
||||
test "when token is missed but token in session, it assigns the user", %{conn: conn} = opts do
|
||||
conn =
|
||||
conn
|
||||
|> Plug.Session.call(Plug.Session.init(@session_opts))
|
||||
|> fetch_session()
|
||||
|> put_session(:oauth_token, opts[:token])
|
||||
|> OAuthPlug.call(%{})
|
||||
|
||||
assert conn.assigns[:user] == opts[:user]
|
||||
end
|
||||
end
|
||||
|
|
@ -1,210 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.OAuthScopesPlugTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Plugs.OAuthScopesPlug
|
||||
alias Pleroma.Repo
|
||||
|
||||
import Mock
|
||||
import Pleroma.Factory
|
||||
|
||||
test "is not performed if marked as skipped", %{conn: conn} do
|
||||
with_mock OAuthScopesPlug, [:passthrough], perform: &passthrough([&1, &2]) do
|
||||
conn =
|
||||
conn
|
||||
|> OAuthScopesPlug.skip_plug()
|
||||
|> OAuthScopesPlug.call(%{scopes: ["random_scope"]})
|
||||
|
||||
refute called(OAuthScopesPlug.perform(:_, :_))
|
||||
refute conn.halted
|
||||
end
|
||||
end
|
||||
|
||||
test "if `token.scopes` fulfills specified 'any of' conditions, " <>
|
||||
"proceeds with no op",
|
||||
%{conn: conn} do
|
||||
token = insert(:oauth_token, scopes: ["read", "write"]) |> Repo.preload(:user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, token.user)
|
||||
|> assign(:token, token)
|
||||
|> OAuthScopesPlug.call(%{scopes: ["read"]})
|
||||
|
||||
refute conn.halted
|
||||
assert conn.assigns[:user]
|
||||
end
|
||||
|
||||
test "if `token.scopes` fulfills specified 'all of' conditions, " <>
|
||||
"proceeds with no op",
|
||||
%{conn: conn} do
|
||||
token = insert(:oauth_token, scopes: ["scope1", "scope2", "scope3"]) |> Repo.preload(:user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, token.user)
|
||||
|> assign(:token, token)
|
||||
|> OAuthScopesPlug.call(%{scopes: ["scope2", "scope3"], op: :&})
|
||||
|
||||
refute conn.halted
|
||||
assert conn.assigns[:user]
|
||||
end
|
||||
|
||||
describe "with `fallback: :proceed_unauthenticated` option, " do
|
||||
test "if `token.scopes` doesn't fulfill specified conditions, " <>
|
||||
"clears :user and :token assigns",
|
||||
%{conn: conn} do
|
||||
user = insert(:user)
|
||||
token1 = insert(:oauth_token, scopes: ["read", "write"], user: user)
|
||||
|
||||
for token <- [token1, nil], op <- [:|, :&] do
|
||||
ret_conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> assign(:token, token)
|
||||
|> OAuthScopesPlug.call(%{
|
||||
scopes: ["follow"],
|
||||
op: op,
|
||||
fallback: :proceed_unauthenticated
|
||||
})
|
||||
|
||||
refute ret_conn.halted
|
||||
refute ret_conn.assigns[:user]
|
||||
refute ret_conn.assigns[:token]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "without :fallback option, " do
|
||||
test "if `token.scopes` does not fulfill specified 'any of' conditions, " <>
|
||||
"returns 403 and halts",
|
||||
%{conn: conn} do
|
||||
for token <- [insert(:oauth_token, scopes: ["read", "write"]), nil] do
|
||||
any_of_scopes = ["follow", "push"]
|
||||
|
||||
ret_conn =
|
||||
conn
|
||||
|> assign(:token, token)
|
||||
|> OAuthScopesPlug.call(%{scopes: any_of_scopes})
|
||||
|
||||
assert ret_conn.halted
|
||||
assert 403 == ret_conn.status
|
||||
|
||||
expected_error = "Insufficient permissions: #{Enum.join(any_of_scopes, " | ")}."
|
||||
assert Jason.encode!(%{error: expected_error}) == ret_conn.resp_body
|
||||
end
|
||||
end
|
||||
|
||||
test "if `token.scopes` does not fulfill specified 'all of' conditions, " <>
|
||||
"returns 403 and halts",
|
||||
%{conn: conn} do
|
||||
for token <- [insert(:oauth_token, scopes: ["read", "write"]), nil] do
|
||||
token_scopes = (token && token.scopes) || []
|
||||
all_of_scopes = ["write", "follow"]
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:token, token)
|
||||
|> OAuthScopesPlug.call(%{scopes: all_of_scopes, op: :&})
|
||||
|
||||
assert conn.halted
|
||||
assert 403 == conn.status
|
||||
|
||||
expected_error =
|
||||
"Insufficient permissions: #{Enum.join(all_of_scopes -- token_scopes, " & ")}."
|
||||
|
||||
assert Jason.encode!(%{error: expected_error}) == conn.resp_body
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "with hierarchical scopes, " do
|
||||
test "if `token.scopes` fulfills specified 'any of' conditions, " <>
|
||||
"proceeds with no op",
|
||||
%{conn: conn} do
|
||||
token = insert(:oauth_token, scopes: ["read", "write"]) |> Repo.preload(:user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, token.user)
|
||||
|> assign(:token, token)
|
||||
|> OAuthScopesPlug.call(%{scopes: ["read:something"]})
|
||||
|
||||
refute conn.halted
|
||||
assert conn.assigns[:user]
|
||||
end
|
||||
|
||||
test "if `token.scopes` fulfills specified 'all of' conditions, " <>
|
||||
"proceeds with no op",
|
||||
%{conn: conn} do
|
||||
token = insert(:oauth_token, scopes: ["scope1", "scope2", "scope3"]) |> Repo.preload(:user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, token.user)
|
||||
|> assign(:token, token)
|
||||
|> OAuthScopesPlug.call(%{scopes: ["scope1:subscope", "scope2:subscope"], op: :&})
|
||||
|
||||
refute conn.halted
|
||||
assert conn.assigns[:user]
|
||||
end
|
||||
end
|
||||
|
||||
describe "filter_descendants/2" do
|
||||
test "filters scopes which directly match or are ancestors of supported scopes" do
|
||||
f = fn scopes, supported_scopes ->
|
||||
OAuthScopesPlug.filter_descendants(scopes, supported_scopes)
|
||||
end
|
||||
|
||||
assert f.(["read", "follow"], ["write", "read"]) == ["read"]
|
||||
|
||||
assert f.(["read", "write:something", "follow"], ["write", "read"]) ==
|
||||
["read", "write:something"]
|
||||
|
||||
assert f.(["admin:read"], ["write", "read"]) == []
|
||||
|
||||
assert f.(["admin:read"], ["write", "admin"]) == ["admin:read"]
|
||||
end
|
||||
end
|
||||
|
||||
describe "transform_scopes/2" do
|
||||
setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage])
|
||||
|
||||
setup do
|
||||
{:ok, %{f: &OAuthScopesPlug.transform_scopes/2}}
|
||||
end
|
||||
|
||||
test "with :admin option, prefixes all requested scopes with `admin:` " <>
|
||||
"and [optionally] keeps only prefixed scopes, " <>
|
||||
"depending on `[:auth, :enforce_oauth_admin_scope_usage]` setting",
|
||||
%{f: f} do
|
||||
Pleroma.Config.put([:auth, :enforce_oauth_admin_scope_usage], false)
|
||||
|
||||
assert f.(["read"], %{admin: true}) == ["admin:read", "read"]
|
||||
|
||||
assert f.(["read", "write"], %{admin: true}) == [
|
||||
"admin:read",
|
||||
"read",
|
||||
"admin:write",
|
||||
"write"
|
||||
]
|
||||
|
||||
Pleroma.Config.put([:auth, :enforce_oauth_admin_scope_usage], true)
|
||||
|
||||
assert f.(["read:accounts"], %{admin: true}) == ["admin:read:accounts"]
|
||||
|
||||
assert f.(["read", "write:reports"], %{admin: true}) == [
|
||||
"admin:read",
|
||||
"admin:write:reports"
|
||||
]
|
||||
end
|
||||
|
||||
test "with no supported options, returns unmodified scopes", %{f: f} do
|
||||
assert f.(["read"], %{}) == ["read"]
|
||||
assert f.(["read", "write"], %{}) == ["read", "write"]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,263 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.RateLimiterTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Phoenix.ConnTest
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Plugs.RateLimiter
|
||||
alias Plug.Conn
|
||||
|
||||
import Pleroma.Factory
|
||||
import Pleroma.Tests.Helpers, only: [clear_config: 1, clear_config: 2]
|
||||
|
||||
# Note: each example must work with separate buckets in order to prevent concurrency issues
|
||||
setup do: clear_config([Pleroma.Web.Endpoint, :http, :ip])
|
||||
setup do: clear_config(:rate_limit)
|
||||
|
||||
describe "config" do
|
||||
@limiter_name :test_init
|
||||
setup do: clear_config([Pleroma.Plugs.RemoteIp, :enabled])
|
||||
|
||||
test "config is required for plug to work" do
|
||||
Config.put([:rate_limit, @limiter_name], {1, 1})
|
||||
Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
|
||||
|
||||
assert %{limits: {1, 1}, name: :test_init, opts: [name: :test_init]} ==
|
||||
[name: @limiter_name]
|
||||
|> RateLimiter.init()
|
||||
|> RateLimiter.action_settings()
|
||||
|
||||
assert nil ==
|
||||
[name: :nonexisting_limiter]
|
||||
|> RateLimiter.init()
|
||||
|> RateLimiter.action_settings()
|
||||
end
|
||||
end
|
||||
|
||||
test "it is disabled if it remote ip plug is enabled but no remote ip is found" do
|
||||
assert RateLimiter.disabled?(Conn.assign(build_conn(), :remote_ip_found, false))
|
||||
end
|
||||
|
||||
test "it is enabled if remote ip found" do
|
||||
refute RateLimiter.disabled?(Conn.assign(build_conn(), :remote_ip_found, true))
|
||||
end
|
||||
|
||||
test "it is enabled if remote_ip_found flag doesn't exist" do
|
||||
refute RateLimiter.disabled?(build_conn())
|
||||
end
|
||||
|
||||
test "it restricts based on config values" do
|
||||
limiter_name = :test_plug_opts
|
||||
scale = 80
|
||||
limit = 5
|
||||
|
||||
Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
|
||||
Config.put([:rate_limit, limiter_name], {scale, limit})
|
||||
|
||||
plug_opts = RateLimiter.init(name: limiter_name)
|
||||
conn = build_conn(:get, "/")
|
||||
|
||||
for i <- 1..5 do
|
||||
conn = RateLimiter.call(conn, plug_opts)
|
||||
assert {^i, _} = RateLimiter.inspect_bucket(conn, limiter_name, plug_opts)
|
||||
Process.sleep(10)
|
||||
end
|
||||
|
||||
conn = RateLimiter.call(conn, plug_opts)
|
||||
assert %{"error" => "Throttled"} = ConnTest.json_response(conn, :too_many_requests)
|
||||
assert conn.halted
|
||||
|
||||
Process.sleep(50)
|
||||
|
||||
conn = build_conn(:get, "/")
|
||||
|
||||
conn = RateLimiter.call(conn, plug_opts)
|
||||
assert {1, 4} = RateLimiter.inspect_bucket(conn, limiter_name, plug_opts)
|
||||
|
||||
refute conn.status == Conn.Status.code(:too_many_requests)
|
||||
refute conn.resp_body
|
||||
refute conn.halted
|
||||
end
|
||||
|
||||
describe "options" do
|
||||
test "`bucket_name` option overrides default bucket name" do
|
||||
limiter_name = :test_bucket_name
|
||||
|
||||
Config.put([:rate_limit, limiter_name], {1000, 5})
|
||||
Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
|
||||
|
||||
base_bucket_name = "#{limiter_name}:group1"
|
||||
plug_opts = RateLimiter.init(name: limiter_name, bucket_name: base_bucket_name)
|
||||
|
||||
conn = build_conn(:get, "/")
|
||||
|
||||
RateLimiter.call(conn, plug_opts)
|
||||
assert {1, 4} = RateLimiter.inspect_bucket(conn, base_bucket_name, plug_opts)
|
||||
assert {:error, :not_found} = RateLimiter.inspect_bucket(conn, limiter_name, plug_opts)
|
||||
end
|
||||
|
||||
test "`params` option allows different queries to be tracked independently" do
|
||||
limiter_name = :test_params
|
||||
Config.put([:rate_limit, limiter_name], {1000, 5})
|
||||
Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
|
||||
|
||||
plug_opts = RateLimiter.init(name: limiter_name, params: ["id"])
|
||||
|
||||
conn = build_conn(:get, "/?id=1")
|
||||
conn = Conn.fetch_query_params(conn)
|
||||
conn_2 = build_conn(:get, "/?id=2")
|
||||
|
||||
RateLimiter.call(conn, plug_opts)
|
||||
assert {1, 4} = RateLimiter.inspect_bucket(conn, limiter_name, plug_opts)
|
||||
assert {0, 5} = RateLimiter.inspect_bucket(conn_2, limiter_name, plug_opts)
|
||||
end
|
||||
|
||||
test "it supports combination of options modifying bucket name" do
|
||||
limiter_name = :test_options_combo
|
||||
Config.put([:rate_limit, limiter_name], {1000, 5})
|
||||
Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
|
||||
|
||||
base_bucket_name = "#{limiter_name}:group1"
|
||||
|
||||
plug_opts =
|
||||
RateLimiter.init(name: limiter_name, bucket_name: base_bucket_name, params: ["id"])
|
||||
|
||||
id = "100"
|
||||
|
||||
conn = build_conn(:get, "/?id=#{id}")
|
||||
conn = Conn.fetch_query_params(conn)
|
||||
conn_2 = build_conn(:get, "/?id=#{101}")
|
||||
|
||||
RateLimiter.call(conn, plug_opts)
|
||||
assert {1, 4} = RateLimiter.inspect_bucket(conn, base_bucket_name, plug_opts)
|
||||
assert {0, 5} = RateLimiter.inspect_bucket(conn_2, base_bucket_name, plug_opts)
|
||||
end
|
||||
end
|
||||
|
||||
describe "unauthenticated users" do
|
||||
test "are restricted based on remote IP" do
|
||||
limiter_name = :test_unauthenticated
|
||||
Config.put([:rate_limit, limiter_name], [{1000, 5}, {1, 10}])
|
||||
Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
|
||||
|
||||
plug_opts = RateLimiter.init(name: limiter_name)
|
||||
|
||||
conn = %{build_conn(:get, "/") | remote_ip: {127, 0, 0, 2}}
|
||||
conn_2 = %{build_conn(:get, "/") | remote_ip: {127, 0, 0, 3}}
|
||||
|
||||
for i <- 1..5 do
|
||||
conn = RateLimiter.call(conn, plug_opts)
|
||||
assert {^i, _} = RateLimiter.inspect_bucket(conn, limiter_name, plug_opts)
|
||||
refute conn.halted
|
||||
end
|
||||
|
||||
conn = RateLimiter.call(conn, plug_opts)
|
||||
|
||||
assert %{"error" => "Throttled"} = ConnTest.json_response(conn, :too_many_requests)
|
||||
assert conn.halted
|
||||
|
||||
conn_2 = RateLimiter.call(conn_2, plug_opts)
|
||||
assert {1, 4} = RateLimiter.inspect_bucket(conn_2, limiter_name, plug_opts)
|
||||
|
||||
refute conn_2.status == Conn.Status.code(:too_many_requests)
|
||||
refute conn_2.resp_body
|
||||
refute conn_2.halted
|
||||
end
|
||||
end
|
||||
|
||||
describe "authenticated users" do
|
||||
setup do
|
||||
Ecto.Adapters.SQL.Sandbox.checkout(Pleroma.Repo)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "can have limits separate from unauthenticated connections" do
|
||||
limiter_name = :test_authenticated1
|
||||
|
||||
scale = 50
|
||||
limit = 5
|
||||
Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
|
||||
Config.put([:rate_limit, limiter_name], [{1000, 1}, {scale, limit}])
|
||||
|
||||
plug_opts = RateLimiter.init(name: limiter_name)
|
||||
|
||||
user = insert(:user)
|
||||
conn = build_conn(:get, "/") |> assign(:user, user)
|
||||
|
||||
for i <- 1..5 do
|
||||
conn = RateLimiter.call(conn, plug_opts)
|
||||
assert {^i, _} = RateLimiter.inspect_bucket(conn, limiter_name, plug_opts)
|
||||
refute conn.halted
|
||||
end
|
||||
|
||||
conn = RateLimiter.call(conn, plug_opts)
|
||||
|
||||
assert %{"error" => "Throttled"} = ConnTest.json_response(conn, :too_many_requests)
|
||||
assert conn.halted
|
||||
end
|
||||
|
||||
test "different users are counted independently" do
|
||||
limiter_name = :test_authenticated2
|
||||
Config.put([:rate_limit, limiter_name], [{1, 10}, {1000, 5}])
|
||||
Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
|
||||
|
||||
plug_opts = RateLimiter.init(name: limiter_name)
|
||||
|
||||
user = insert(:user)
|
||||
conn = build_conn(:get, "/") |> assign(:user, user)
|
||||
|
||||
user_2 = insert(:user)
|
||||
conn_2 = build_conn(:get, "/") |> assign(:user, user_2)
|
||||
|
||||
for i <- 1..5 do
|
||||
conn = RateLimiter.call(conn, plug_opts)
|
||||
assert {^i, _} = RateLimiter.inspect_bucket(conn, limiter_name, plug_opts)
|
||||
end
|
||||
|
||||
conn = RateLimiter.call(conn, plug_opts)
|
||||
assert %{"error" => "Throttled"} = ConnTest.json_response(conn, :too_many_requests)
|
||||
assert conn.halted
|
||||
|
||||
conn_2 = RateLimiter.call(conn_2, plug_opts)
|
||||
assert {1, 4} = RateLimiter.inspect_bucket(conn_2, limiter_name, plug_opts)
|
||||
refute conn_2.status == Conn.Status.code(:too_many_requests)
|
||||
refute conn_2.resp_body
|
||||
refute conn_2.halted
|
||||
end
|
||||
end
|
||||
|
||||
test "doesn't crash due to a race condition when multiple requests are made at the same time and the bucket is not yet initialized" do
|
||||
limiter_name = :test_race_condition
|
||||
Pleroma.Config.put([:rate_limit, limiter_name], {1000, 5})
|
||||
Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
|
||||
|
||||
opts = RateLimiter.init(name: limiter_name)
|
||||
|
||||
conn = build_conn(:get, "/")
|
||||
conn_2 = build_conn(:get, "/")
|
||||
|
||||
%Task{pid: pid1} =
|
||||
task1 =
|
||||
Task.async(fn ->
|
||||
receive do
|
||||
:process2_up ->
|
||||
RateLimiter.call(conn, opts)
|
||||
end
|
||||
end)
|
||||
|
||||
task2 =
|
||||
Task.async(fn ->
|
||||
send(pid1, :process2_up)
|
||||
RateLimiter.call(conn_2, opts)
|
||||
end)
|
||||
|
||||
Task.await(task1)
|
||||
Task.await(task2)
|
||||
|
||||
refute {:err, :not_found} == RateLimiter.inspect_bucket(conn, limiter_name, opts)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.RemoteIpTest do
|
||||
use ExUnit.Case
|
||||
use Plug.Test
|
||||
|
||||
alias Pleroma.Plugs.RemoteIp
|
||||
|
||||
import Pleroma.Tests.Helpers, only: [clear_config: 2]
|
||||
|
||||
setup do:
|
||||
clear_config(RemoteIp,
|
||||
enabled: true,
|
||||
headers: ["x-forwarded-for"],
|
||||
proxies: [],
|
||||
reserved: [
|
||||
"127.0.0.0/8",
|
||||
"::1/128",
|
||||
"fc00::/7",
|
||||
"10.0.0.0/8",
|
||||
"172.16.0.0/12",
|
||||
"192.168.0.0/16"
|
||||
]
|
||||
)
|
||||
|
||||
test "disabled" do
|
||||
Pleroma.Config.put(RemoteIp, enabled: false)
|
||||
|
||||
%{remote_ip: remote_ip} = conn(:get, "/")
|
||||
|
||||
conn =
|
||||
conn(:get, "/")
|
||||
|> put_req_header("x-forwarded-for", "1.1.1.1")
|
||||
|> RemoteIp.call(nil)
|
||||
|
||||
assert conn.remote_ip == remote_ip
|
||||
end
|
||||
|
||||
test "enabled" do
|
||||
conn =
|
||||
conn(:get, "/")
|
||||
|> put_req_header("x-forwarded-for", "1.1.1.1")
|
||||
|> RemoteIp.call(nil)
|
||||
|
||||
assert conn.remote_ip == {1, 1, 1, 1}
|
||||
end
|
||||
|
||||
test "custom headers" do
|
||||
Pleroma.Config.put(RemoteIp, enabled: true, headers: ["cf-connecting-ip"])
|
||||
|
||||
conn =
|
||||
conn(:get, "/")
|
||||
|> put_req_header("x-forwarded-for", "1.1.1.1")
|
||||
|> RemoteIp.call(nil)
|
||||
|
||||
refute conn.remote_ip == {1, 1, 1, 1}
|
||||
|
||||
conn =
|
||||
conn(:get, "/")
|
||||
|> put_req_header("cf-connecting-ip", "1.1.1.1")
|
||||
|> RemoteIp.call(nil)
|
||||
|
||||
assert conn.remote_ip == {1, 1, 1, 1}
|
||||
end
|
||||
|
||||
test "custom proxies" do
|
||||
conn =
|
||||
conn(:get, "/")
|
||||
|> put_req_header("x-forwarded-for", "173.245.48.1, 1.1.1.1, 173.245.48.2")
|
||||
|> RemoteIp.call(nil)
|
||||
|
||||
refute conn.remote_ip == {1, 1, 1, 1}
|
||||
|
||||
Pleroma.Config.put([RemoteIp, :proxies], ["173.245.48.0/20"])
|
||||
|
||||
conn =
|
||||
conn(:get, "/")
|
||||
|> put_req_header("x-forwarded-for", "173.245.48.1, 1.1.1.1, 173.245.48.2")
|
||||
|> RemoteIp.call(nil)
|
||||
|
||||
assert conn.remote_ip == {1, 1, 1, 1}
|
||||
end
|
||||
|
||||
test "proxies set without CIDR format" do
|
||||
Pleroma.Config.put([RemoteIp, :proxies], ["173.245.48.1"])
|
||||
|
||||
conn =
|
||||
conn(:get, "/")
|
||||
|> put_req_header("x-forwarded-for", "173.245.48.1, 1.1.1.1")
|
||||
|> RemoteIp.call(nil)
|
||||
|
||||
assert conn.remote_ip == {1, 1, 1, 1}
|
||||
end
|
||||
|
||||
test "proxies set `nonsensical` CIDR" do
|
||||
Pleroma.Config.put([RemoteIp, :reserved], ["127.0.0.0/8"])
|
||||
Pleroma.Config.put([RemoteIp, :proxies], ["10.0.0.3/24"])
|
||||
|
||||
conn =
|
||||
conn(:get, "/")
|
||||
|> put_req_header("x-forwarded-for", "10.0.0.3, 1.1.1.1")
|
||||
|> RemoteIp.call(nil)
|
||||
|
||||
assert conn.remote_ip == {1, 1, 1, 1}
|
||||
end
|
||||
end
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.SessionAuthenticationPlugTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
alias Pleroma.Plugs.SessionAuthenticationPlug
|
||||
alias Pleroma.User
|
||||
|
||||
setup %{conn: conn} do
|
||||
session_opts = [
|
||||
store: :cookie,
|
||||
key: "_test",
|
||||
signing_salt: "cooldude"
|
||||
]
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> Plug.Session.call(Plug.Session.init(session_opts))
|
||||
|> fetch_session
|
||||
|> assign(:auth_user, %User{id: 1})
|
||||
|
||||
%{conn: conn}
|
||||
end
|
||||
|
||||
test "it does nothing if a user is assigned", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, %User{})
|
||||
|
||||
ret_conn =
|
||||
conn
|
||||
|> SessionAuthenticationPlug.call(%{})
|
||||
|
||||
assert ret_conn == conn
|
||||
end
|
||||
|
||||
test "if the auth_user has the same id as the user_id in the session, it assigns the user", %{
|
||||
conn: conn
|
||||
} do
|
||||
conn =
|
||||
conn
|
||||
|> put_session(:user_id, conn.assigns.auth_user.id)
|
||||
|> SessionAuthenticationPlug.call(%{})
|
||||
|
||||
assert conn.assigns.user == conn.assigns.auth_user
|
||||
end
|
||||
|
||||
test "if the auth_user has a different id as the user_id in the session, it does nothing", %{
|
||||
conn: conn
|
||||
} do
|
||||
conn =
|
||||
conn
|
||||
|> put_session(:user_id, -1)
|
||||
|
||||
ret_conn =
|
||||
conn
|
||||
|> SessionAuthenticationPlug.call(%{})
|
||||
|
||||
assert ret_conn == conn
|
||||
end
|
||||
end
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.SetFormatPlugTest do
|
||||
use ExUnit.Case, async: true
|
||||
use Plug.Test
|
||||
|
||||
alias Pleroma.Plugs.SetFormatPlug
|
||||
|
||||
test "set format from params" do
|
||||
conn =
|
||||
:get
|
||||
|> conn("/cofe?_format=json")
|
||||
|> SetFormatPlug.call([])
|
||||
|
||||
assert %{format: "json"} == conn.assigns
|
||||
end
|
||||
|
||||
test "set format from header" do
|
||||
conn =
|
||||
:get
|
||||
|> conn("/cofe")
|
||||
|> put_private(:phoenix_format, "xml")
|
||||
|> SetFormatPlug.call([])
|
||||
|
||||
assert %{format: "xml"} == conn.assigns
|
||||
end
|
||||
|
||||
test "doesn't set format" do
|
||||
conn =
|
||||
:get
|
||||
|> conn("/cofe")
|
||||
|> SetFormatPlug.call([])
|
||||
|
||||
refute conn.assigns[:format]
|
||||
end
|
||||
end
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.SetLocalePlugTest do
|
||||
use ExUnit.Case, async: true
|
||||
use Plug.Test
|
||||
|
||||
alias Pleroma.Plugs.SetLocalePlug
|
||||
alias Plug.Conn
|
||||
|
||||
test "default locale is `en`" do
|
||||
conn =
|
||||
:get
|
||||
|> conn("/cofe")
|
||||
|> SetLocalePlug.call([])
|
||||
|
||||
assert "en" == Gettext.get_locale()
|
||||
assert %{locale: "en"} == conn.assigns
|
||||
end
|
||||
|
||||
test "use supported locale from `accept-language`" do
|
||||
conn =
|
||||
:get
|
||||
|> conn("/cofe")
|
||||
|> Conn.put_req_header(
|
||||
"accept-language",
|
||||
"ru, fr-CH, fr;q=0.9, en;q=0.8, *;q=0.5"
|
||||
)
|
||||
|> SetLocalePlug.call([])
|
||||
|
||||
assert "ru" == Gettext.get_locale()
|
||||
assert %{locale: "ru"} == conn.assigns
|
||||
end
|
||||
|
||||
test "use default locale if locale from `accept-language` is not supported" do
|
||||
conn =
|
||||
:get
|
||||
|> conn("/cofe")
|
||||
|> Conn.put_req_header("accept-language", "tlh")
|
||||
|> SetLocalePlug.call([])
|
||||
|
||||
assert "en" == Gettext.get_locale()
|
||||
assert %{locale: "en"} == conn.assigns
|
||||
end
|
||||
end
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.SetUserSessionIdPlugTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
alias Pleroma.Plugs.SetUserSessionIdPlug
|
||||
alias Pleroma.User
|
||||
|
||||
setup %{conn: conn} do
|
||||
session_opts = [
|
||||
store: :cookie,
|
||||
key: "_test",
|
||||
signing_salt: "cooldude"
|
||||
]
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> Plug.Session.call(Plug.Session.init(session_opts))
|
||||
|> fetch_session
|
||||
|
||||
%{conn: conn}
|
||||
end
|
||||
|
||||
test "doesn't do anything if the user isn't set", %{conn: conn} do
|
||||
ret_conn =
|
||||
conn
|
||||
|> SetUserSessionIdPlug.call(%{})
|
||||
|
||||
assert ret_conn == conn
|
||||
end
|
||||
|
||||
test "sets the user_id in the session to the user id of the user assign", %{conn: conn} do
|
||||
Code.ensure_compiled(Pleroma.User)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, %User{id: 1})
|
||||
|> SetUserSessionIdPlug.call(%{})
|
||||
|
||||
id = get_session(conn, :user_id)
|
||||
assert id == 1
|
||||
end
|
||||
end
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.UploadedMediaPlugTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
alias Pleroma.Upload
|
||||
|
||||
defp upload_file(context) do
|
||||
Pleroma.DataCase.ensure_local_uploader(context)
|
||||
File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
|
||||
|
||||
file = %Plug.Upload{
|
||||
content_type: "image/jpg",
|
||||
path: Path.absname("test/fixtures/image_tmp.jpg"),
|
||||
filename: "nice_tf.jpg"
|
||||
}
|
||||
|
||||
{:ok, data} = Upload.store(file)
|
||||
[%{"href" => attachment_url} | _] = data["url"]
|
||||
[attachment_url: attachment_url]
|
||||
end
|
||||
|
||||
setup_all :upload_file
|
||||
|
||||
test "does not send Content-Disposition header when name param is not set", %{
|
||||
attachment_url: attachment_url
|
||||
} do
|
||||
conn = get(build_conn(), attachment_url)
|
||||
refute Enum.any?(conn.resp_headers, &(elem(&1, 0) == "content-disposition"))
|
||||
end
|
||||
|
||||
test "sends Content-Disposition header when name param is set", %{
|
||||
attachment_url: attachment_url
|
||||
} do
|
||||
conn = get(build_conn(), attachment_url <> "?name=\"cofe\".gif")
|
||||
|
||||
assert Enum.any?(
|
||||
conn.resp_headers,
|
||||
&(&1 == {"content-disposition", "filename=\"\\\"cofe\\\".gif\""})
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.UserEnabledPlugTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
alias Pleroma.Plugs.UserEnabledPlug
|
||||
import Pleroma.Factory
|
||||
|
||||
setup do: clear_config([:instance, :account_activation_required])
|
||||
|
||||
test "doesn't do anything if the user isn't set", %{conn: conn} do
|
||||
ret_conn =
|
||||
conn
|
||||
|> UserEnabledPlug.call(%{})
|
||||
|
||||
assert ret_conn == conn
|
||||
end
|
||||
|
||||
test "with a user that's not confirmed and a config requiring confirmation, it removes that user",
|
||||
%{conn: conn} do
|
||||
Pleroma.Config.put([:instance, :account_activation_required], true)
|
||||
|
||||
user = insert(:user, confirmation_pending: true)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> UserEnabledPlug.call(%{})
|
||||
|
||||
assert conn.assigns.user == nil
|
||||
end
|
||||
|
||||
test "with a user that is deactivated, it removes that user", %{conn: conn} do
|
||||
user = insert(:user, deactivated: true)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> UserEnabledPlug.call(%{})
|
||||
|
||||
assert conn.assigns.user == nil
|
||||
end
|
||||
|
||||
test "with a user that is not deactivated, it does nothing", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|
||||
ret_conn =
|
||||
conn
|
||||
|> UserEnabledPlug.call(%{})
|
||||
|
||||
assert conn == ret_conn
|
||||
end
|
||||
end
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.UserFetcherPlugTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
alias Pleroma.Plugs.UserFetcherPlug
|
||||
import Pleroma.Factory
|
||||
|
||||
setup do
|
||||
user = insert(:user)
|
||||
%{user: user}
|
||||
end
|
||||
|
||||
test "if an auth_credentials assign is present, it tries to fetch the user and assigns it", %{
|
||||
conn: conn,
|
||||
user: user
|
||||
} do
|
||||
conn =
|
||||
conn
|
||||
|> assign(:auth_credentials, %{
|
||||
username: user.nickname,
|
||||
password: nil
|
||||
})
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> UserFetcherPlug.call(%{})
|
||||
|
||||
assert conn.assigns[:auth_user] == user
|
||||
end
|
||||
|
||||
test "without a credential assign it doesn't do anything", %{conn: conn} do
|
||||
ret_conn =
|
||||
conn
|
||||
|> UserFetcherPlug.call(%{})
|
||||
|
||||
assert conn == ret_conn
|
||||
end
|
||||
end
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Plugs.UserIsAdminPlugTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
alias Pleroma.Plugs.UserIsAdminPlug
|
||||
import Pleroma.Factory
|
||||
|
||||
test "accepts a user that is an admin" do
|
||||
user = insert(:user, is_admin: true)
|
||||
|
||||
conn = assign(build_conn(), :user, user)
|
||||
|
||||
ret_conn = UserIsAdminPlug.call(conn, %{})
|
||||
|
||||
assert conn == ret_conn
|
||||
end
|
||||
|
||||
test "denies a user that isn't an admin" do
|
||||
user = insert(:user)
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, user)
|
||||
|> UserIsAdminPlug.call(%{})
|
||||
|
||||
assert conn.status == 403
|
||||
end
|
||||
|
||||
test "denies when a user isn't set" do
|
||||
conn = UserIsAdminPlug.call(build_conn(), %{})
|
||||
|
||||
assert conn.status == 403
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue