diff options
Diffstat (limited to 'test/plugs')
26 files changed, 651 insertions, 298 deletions
diff --git a/test/plugs/admin_secret_authentication_plug_test.exs b/test/plugs/admin_secret_authentication_plug_test.exs index e1d4b391f..100016c62 100644 --- a/test/plugs/admin_secret_authentication_plug_test.exs +++ b/test/plugs/admin_secret_authentication_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.AdminSecretAuthenticationPlugTest do @@ -22,21 +22,41 @@ defmodule Pleroma.Plugs.AdminSecretAuthenticationPlugTest do assert conn == ret_conn end - test "with secret set and given in the 'admin_token' parameter, it assigns an admin user", %{ - conn: conn - } do - Pleroma.Config.put(:admin_token, "password123") + describe "when secret set it assigns an admin user" do + setup do: clear_config([:admin_token]) - conn = - %{conn | params: %{"admin_token" => "wrong_password"}} - |> AdminSecretAuthenticationPlug.call(%{}) + test "with `admin_token` query parameter", %{conn: conn} do + Pleroma.Config.put(:admin_token, "password123") - refute conn.assigns[:user] + conn = + %{conn | params: %{"admin_token" => "wrong_password"}} + |> AdminSecretAuthenticationPlug.call(%{}) - conn = - %{conn | params: %{"admin_token" => "password123"}} - |> AdminSecretAuthenticationPlug.call(%{}) + refute conn.assigns[:user] + + conn = + %{conn | params: %{"admin_token" => "password123"}} + |> AdminSecretAuthenticationPlug.call(%{}) + + assert conn.assigns[:user].is_admin + 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] + + conn = + conn + |> put_req_header("x-admin-token", "☕️") + |> AdminSecretAuthenticationPlug.call(%{}) - assert conn.assigns[:user].info.is_admin + assert conn.assigns[:user].is_admin + end end end diff --git a/test/plugs/authentication_plug_test.exs b/test/plugs/authentication_plug_test.exs index 9ae4c506f..3c70c1747 100644 --- a/test/plugs/authentication_plug_test.exs +++ b/test/plugs/authentication_plug_test.exs @@ -1,20 +1,23 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# 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: Comeonin.Pbkdf2.hashpwsalt("guy") + password_hash: Pbkdf2.hash_pwd_salt("guy") } conn = @@ -36,25 +39,53 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do assert ret_conn == conn end - test "with a correct password in the credentials, it assigns the auth_user", %{conn: conn} do + 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 wrong password in the credentials, it does nothing", %{conn: conn} do + 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_credentials, %{password: "wrong"}) + |> assign(:auth_user, user) + |> assign(:auth_credentials, %{password: "123"}) + |> AuthenticationPlug.call(%{}) - ret_conn = + 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 + + 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 == ret_conn + 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 @@ -74,6 +105,13 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do 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" diff --git a/test/plugs/basic_auth_decoder_plug_test.exs b/test/plugs/basic_auth_decoder_plug_test.exs index 4d7728e93..a6063d4f6 100644 --- a/test/plugs/basic_auth_decoder_plug_test.exs +++ b/test/plugs/basic_auth_decoder_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.BasicAuthDecoderPlugTest do diff --git a/test/plugs/cache_control_test.exs b/test/plugs/cache_control_test.exs index 69ce6cc7d..6b567e81d 100644 --- a/test/plugs/cache_control_test.exs +++ b/test/plugs/cache_control_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.CacheControlTest do diff --git a/test/plugs/cache_test.exs b/test/plugs/cache_test.exs index e6e7f409e..8b231c881 100644 --- a/test/plugs/cache_test.exs +++ b/test/plugs/cache_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.CacheTest do diff --git a/test/plugs/ensure_authenticated_plug_test.exs b/test/plugs/ensure_authenticated_plug_test.exs index 37ab5213a..a0667c5e0 100644 --- a/test/plugs/ensure_authenticated_plug_test.exs +++ b/test/plugs/ensure_authenticated_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.EnsureAuthenticatedPlugTest do @@ -8,24 +8,89 @@ defmodule Pleroma.Plugs.EnsureAuthenticatedPlugTest do alias Pleroma.Plugs.EnsureAuthenticatedPlug alias Pleroma.User - test "it halts if no user is assigned", %{conn: conn} do + 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 a user is assigned", %{conn: conn} do + test "it continues if user is assigned and MFA disabled", %{conn: conn} do conn = conn - |> assign(:user, %User{}) - - ret_conn = - conn + |> assign(:user, %User{multi_factor_authentication_settings: %{enabled: false}}) + |> assign(:auth_credentials, %{password: "xd-42"}) |> EnsureAuthenticatedPlug.call(%{}) - assert ret_conn == conn + 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 diff --git a/test/plugs/ensure_public_or_authenticated_plug_test.exs b/test/plugs/ensure_public_or_authenticated_plug_test.exs index bae95e150..fc2934369 100644 --- a/test/plugs/ensure_public_or_authenticated_plug_test.exs +++ b/test/plugs/ensure_public_or_authenticated_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.EnsurePublicOrAuthenticatedPlugTest do @@ -9,7 +9,7 @@ defmodule Pleroma.Plugs.EnsurePublicOrAuthenticatedPlugTest do alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug alias Pleroma.User - clear_config([:instance, :public]) + 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) @@ -29,7 +29,7 @@ defmodule Pleroma.Plugs.EnsurePublicOrAuthenticatedPlugTest do conn |> EnsurePublicOrAuthenticatedPlug.call(%{}) - assert ret_conn == conn + refute ret_conn.halted end test "it continues if a user is assigned, even if not public", %{conn: conn} do @@ -43,6 +43,6 @@ defmodule Pleroma.Plugs.EnsurePublicOrAuthenticatedPlugTest do conn |> EnsurePublicOrAuthenticatedPlug.call(%{}) - assert ret_conn == conn + refute ret_conn.halted end end diff --git a/test/plugs/ensure_user_key_plug_test.exs b/test/plugs/ensure_user_key_plug_test.exs index 6a9627f6a..633c05447 100644 --- a/test/plugs/ensure_user_key_plug_test.exs +++ b/test/plugs/ensure_user_key_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.EnsureUserKeyPlugTest do diff --git a/test/plugs/http_security_plug_test.exs b/test/plugs/http_security_plug_test.exs index 9c1c20541..84e4c274f 100644 --- a/test/plugs/http_security_plug_test.exs +++ b/test/plugs/http_security_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.Plugs.HTTPSecurityPlugTest do @@ -7,8 +7,9 @@ defmodule Pleroma.Web.Plugs.HTTPSecurityPlugTest do alias Pleroma.Config alias Plug.Conn - clear_config([:http_securiy, :enabled]) - clear_config([:http_security, :sts]) + setup do: clear_config([:http_securiy, :enabled]) + setup do: clear_config([:http_security, :sts]) + setup do: clear_config([:http_security, :referrer_policy]) describe "http security enabled" do setup do diff --git a/test/plugs/http_signature_plug_test.exs b/test/plugs/http_signature_plug_test.exs index d8ace36da..e6cbde803 100644 --- a/test/plugs/http_signature_plug_test.exs +++ b/test/plugs/http_signature_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.Plugs.HTTPSignaturePlugTest do @@ -7,6 +7,7 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlugTest do 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 @@ -20,10 +21,69 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlugTest do "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 diff --git a/test/plugs/idempotency_plug_test.exs b/test/plugs/idempotency_plug_test.exs index ac1735f13..21fa0fbcf 100644 --- a/test/plugs/idempotency_plug_test.exs +++ b/test/plugs/idempotency_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.IdempotencyPlugTest do diff --git a/test/plugs/instance_static_test.exs b/test/plugs/instance_static_test.exs index 9b27246fa..b8f070d6a 100644 --- a/test/plugs/instance_static_test.exs +++ b/test/plugs/instance_static_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.RuntimeStaticPlugTest do @@ -12,9 +12,7 @@ defmodule Pleroma.Web.RuntimeStaticPlugTest do on_exit(fn -> File.rm_rf(@dir) end) end - clear_config([:instance, :static_dir]) do - Pleroma.Config.put([:instance, :static_dir], @dir) - end + setup do: clear_config([:instance, :static_dir], @dir) test "overrides index" do bundled_index = get(build_conn(), "/") diff --git a/test/plugs/legacy_authentication_plug_test.exs b/test/plugs/legacy_authentication_plug_test.exs index 568ef5abd..3b8c07627 100644 --- a/test/plugs/legacy_authentication_plug_test.exs +++ b/test/plugs/legacy_authentication_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.LegacyAuthenticationPlugTest do @@ -8,6 +8,8 @@ defmodule Pleroma.Plugs.LegacyAuthenticationPlugTest do import Pleroma.Factory alias Pleroma.Plugs.LegacyAuthenticationPlug + alias Pleroma.Plugs.OAuthScopesPlug + alias Pleroma.Plugs.PlugHelper alias Pleroma.User setup do @@ -36,7 +38,8 @@ defmodule Pleroma.Plugs.LegacyAuthenticationPlugTest do end @tag :skip_on_mac - test "it authenticates the auth_user if present and password is correct and resets the password", + 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 @@ -49,6 +52,7 @@ defmodule Pleroma.Plugs.LegacyAuthenticationPlugTest do conn = LegacyAuthenticationPlug.call(conn, %{}) assert conn.assigns.user.id == user.id + assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug) end @tag :skip_on_mac diff --git a/test/plugs/mapped_identity_to_signature_plug_test.exs b/test/plugs/mapped_identity_to_signature_plug_test.exs index 6b9d3649d..0ad3c2929 100644 --- a/test/plugs/mapped_identity_to_signature_plug_test.exs +++ b/test/plugs/mapped_identity_to_signature_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.Plugs.MappedSignatureToIdentityPlugTest do diff --git a/test/plugs/oauth_plug_test.exs b/test/plugs/oauth_plug_test.exs index dea11cdb0..f74c068cd 100644 --- a/test/plugs/oauth_plug_test.exs +++ b/test/plugs/oauth_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.OAuthPlugTest do @@ -38,7 +38,7 @@ defmodule Pleroma.Plugs.OAuthPlugTest do assert conn.assigns[:user] == opts[:user] end - test "with valid token(downcase) in url parameters, it assings the user", opts do + test "with valid token(downcase) in url parameters, it assigns the user", opts do conn = :get |> build_conn("/?access_token=#{opts[:token]}") diff --git a/test/plugs/oauth_scopes_plug_test.exs b/test/plugs/oauth_scopes_plug_test.exs index be6d1340b..884de7b4d 100644 --- a/test/plugs/oauth_scopes_plug_test.exs +++ b/test/plugs/oauth_scopes_plug_test.exs @@ -1,46 +1,25 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.OAuthScopesPlugTest do use Pleroma.Web.ConnCase, async: true - alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.Repo import Mock import Pleroma.Factory - setup_with_mocks([{EnsurePublicOrAuthenticatedPlug, [], [call: fn conn, _ -> conn end]}]) do - :ok - end - - describe "when `assigns[:token]` is nil, " do - test "with :skip_instance_privacy_check option, proceeds with no op", %{conn: conn} do + test "is not performed if marked as skipped", %{conn: conn} do + with_mock OAuthScopesPlug, [:passthrough], perform: &passthrough([&1, &2]) do conn = conn - |> assign(:user, insert(:user)) - |> OAuthScopesPlug.call(%{scopes: ["read"], skip_instance_privacy_check: true}) + |> OAuthScopesPlug.skip_plug() + |> OAuthScopesPlug.call(%{scopes: ["random_scope"]}) + refute called(OAuthScopesPlug.perform(:_, :_)) refute conn.halted - assert conn.assigns[:user] - - refute called(EnsurePublicOrAuthenticatedPlug.call(conn, :_)) - end - - test "without :skip_instance_privacy_check option, calls EnsurePublicOrAuthenticatedPlug", %{ - conn: conn - } do - conn = - conn - |> assign(:user, insert(:user)) - |> OAuthScopesPlug.call(%{scopes: ["read"]}) - - refute conn.halted - assert conn.assigns[:user] - - assert called(EnsurePublicOrAuthenticatedPlug.call(conn, :_)) end end @@ -75,64 +54,27 @@ defmodule Pleroma.Plugs.OAuthScopesPlugTest do end describe "with `fallback: :proceed_unauthenticated` option, " do - test "if `token.scopes` doesn't fulfill specified 'any of' conditions, " <> - "clears `assigns[:user]` and calls EnsurePublicOrAuthenticatedPlug", - %{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: ["follow"], fallback: :proceed_unauthenticated}) - - refute conn.halted - refute conn.assigns[:user] - - assert called(EnsurePublicOrAuthenticatedPlug.call(conn, :_)) - end - - test "if `token.scopes` doesn't fulfill specified 'all of' conditions, " <> - "clears `assigns[:user] and calls EnsurePublicOrAuthenticatedPlug", - %{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", "follow"], - op: :&, - fallback: :proceed_unauthenticated - }) - - refute conn.halted - refute conn.assigns[:user] - - assert called(EnsurePublicOrAuthenticatedPlug.call(conn, :_)) - end - - test "with :skip_instance_privacy_check option, " <> - "if `token.scopes` doesn't fulfill specified conditions, " <> - "clears `assigns[:user]` and does not call EnsurePublicOrAuthenticatedPlug", + test "if `token.scopes` doesn't fulfill specified conditions, " <> + "clears :user and :token assigns", %{conn: conn} do - token = insert(:oauth_token, scopes: ["read:statuses", "write"]) |> Repo.preload(:user) - - conn = - conn - |> assign(:user, token.user) - |> assign(:token, token) - |> OAuthScopesPlug.call(%{ - scopes: ["read"], - fallback: :proceed_unauthenticated, - skip_instance_privacy_check: true - }) - - refute conn.halted - refute conn.assigns[:user] - - refute called(EnsurePublicOrAuthenticatedPlug.call(conn, :_)) + 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 @@ -140,39 +82,42 @@ defmodule Pleroma.Plugs.OAuthScopesPlugTest do test "if `token.scopes` does not fulfill specified 'any of' conditions, " <> "returns 403 and halts", %{conn: conn} do - token = insert(:oauth_token, scopes: ["read", "write"]) - any_of_scopes = ["follow"] + for token <- [insert(:oauth_token, scopes: ["read", "write"]), nil] do + any_of_scopes = ["follow", "push"] - conn = - conn - |> assign(:token, token) - |> OAuthScopesPlug.call(%{scopes: any_of_scopes}) + ret_conn = + conn + |> assign(:token, token) + |> OAuthScopesPlug.call(%{scopes: any_of_scopes}) - assert conn.halted - assert 403 == conn.status + assert ret_conn.halted + assert 403 == ret_conn.status - expected_error = "Insufficient permissions: #{Enum.join(any_of_scopes, ", ")}." - assert Jason.encode!(%{error: expected_error}) == conn.resp_body + 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 - token = insert(:oauth_token, scopes: ["read", "write"]) - all_of_scopes = ["write", "follow"] + 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: :&}) + conn = + conn + |> assign(:token, token) + |> OAuthScopesPlug.call(%{scopes: all_of_scopes, op: :&}) - assert conn.halted - assert 403 == conn.status + assert conn.halted + assert 403 == conn.status - expected_error = - "Insufficient permissions: #{Enum.join(all_of_scopes -- token.scopes, ", ")}." + expected_error = + "Insufficient permissions: #{Enum.join(all_of_scopes -- token_scopes, " & ")}." - assert Jason.encode!(%{error: expected_error}) == conn.resp_body + assert Jason.encode!(%{error: expected_error}) == conn.resp_body + end end end @@ -224,4 +169,42 @@ defmodule Pleroma.Plugs.OAuthScopesPlugTest do 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 diff --git a/test/plugs/rate_limiter_test.exs b/test/plugs/rate_limiter_test.exs index 395095079..4d3d694f4 100644 --- a/test/plugs/rate_limiter_test.exs +++ b/test/plugs/rate_limiter_test.exs @@ -1,174 +1,263 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.RateLimiterTest do - use ExUnit.Case, async: true - use Plug.Test + 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 "init/1" do - limiter_name = :test_init - Pleroma.Config.put([:rate_limit, limiter_name], {1, 1}) + 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 - assert {limiter_name, {1, 1}, []} == RateLimiter.init(limiter_name) - assert nil == RateLimiter.init(:foo) + test "it is enabled if remote ip found" do + refute RateLimiter.disabled?(Conn.assign(build_conn(), :remote_ip_found, true)) end - test "ip/1" do - assert "127.0.0.1" == RateLimiter.ip(%{remote_ip: {127, 0, 0, 1}}) + test "it is enabled if remote_ip_found flag doesn't exist" do + refute RateLimiter.disabled?(build_conn()) end - test "it restricts by opts" do - limiter_name = :test_opts - scale = 1000 + test "it restricts based on config values" do + limiter_name = :test_plug_opts + scale = 80 limit = 5 - Pleroma.Config.put([:rate_limit, limiter_name], {scale, limit}) + Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8}) + Config.put([:rate_limit, limiter_name], {scale, limit}) - opts = RateLimiter.init(limiter_name) - conn = conn(:get, "/") - bucket_name = "#{limiter_name}:#{RateLimiter.ip(conn)}" + plug_opts = RateLimiter.init(name: limiter_name) + conn = build_conn(:get, "/") - conn = RateLimiter.call(conn, opts) - assert {1, 4, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit) + 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, opts) - assert {2, 3, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit) + conn = RateLimiter.call(conn, plug_opts) + assert %{"error" => "Throttled"} = ConnTest.json_response(conn, :too_many_requests) + assert conn.halted - conn = RateLimiter.call(conn, opts) - assert {3, 2, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit) + Process.sleep(50) - conn = RateLimiter.call(conn, opts) - assert {4, 1, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit) + conn = build_conn(:get, "/") - conn = RateLimiter.call(conn, opts) - assert {5, 0, to_reset, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit) + conn = RateLimiter.call(conn, plug_opts) + assert {1, 4} = RateLimiter.inspect_bucket(conn, limiter_name, plug_opts) - conn = RateLimiter.call(conn, opts) + refute conn.status == Conn.Status.code(:too_many_requests) + refute conn.resp_body + refute conn.halted + end - assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests) - assert conn.halted + describe "options" do + test "`bucket_name` option overrides default bucket name" do + limiter_name = :test_bucket_name - Process.sleep(to_reset) + Config.put([:rate_limit, limiter_name], {1000, 5}) + Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8}) - conn = conn(:get, "/") + base_bucket_name = "#{limiter_name}:group1" + plug_opts = RateLimiter.init(name: limiter_name, bucket_name: base_bucket_name) - conn = RateLimiter.call(conn, opts) - assert {1, 4, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit) + conn = build_conn(:get, "/") - refute conn.status == Plug.Conn.Status.code(:too_many_requests) - refute conn.resp_body - refute conn.halted - end + 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 "`bucket_name` option overrides default bucket name" do - limiter_name = :test_bucket_name - scale = 1000 - limit = 5 + 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}) - Pleroma.Config.put([:rate_limit, limiter_name], {scale, limit}) - base_bucket_name = "#{limiter_name}:group1" - opts = RateLimiter.init({limiter_name, bucket_name: base_bucket_name}) + plug_opts = RateLimiter.init(name: limiter_name, params: ["id"]) - conn = conn(:get, "/") - default_bucket_name = "#{limiter_name}:#{RateLimiter.ip(conn)}" - customized_bucket_name = "#{base_bucket_name}:#{RateLimiter.ip(conn)}" + conn = build_conn(:get, "/?id=1") + conn = Conn.fetch_query_params(conn) + conn_2 = build_conn(:get, "/?id=2") - RateLimiter.call(conn, opts) - assert {1, 4, _, _, _} = ExRated.inspect_bucket(customized_bucket_name, scale, limit) - assert {0, 5, _, _, _} = ExRated.inspect_bucket(default_bucket_name, scale, limit) - end + 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 "`params` option appends specified params' values to bucket name" do - limiter_name = :test_params - scale = 1000 - limit = 5 + 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" - Pleroma.Config.put([:rate_limit, limiter_name], {scale, limit}) - opts = RateLimiter.init({limiter_name, params: ["id"]}) - id = "1" + plug_opts = + RateLimiter.init(name: limiter_name, bucket_name: base_bucket_name, params: ["id"]) - conn = conn(:get, "/?id=#{id}") - conn = Plug.Conn.fetch_query_params(conn) + id = "100" - default_bucket_name = "#{limiter_name}:#{RateLimiter.ip(conn)}" - parametrized_bucket_name = "#{limiter_name}:#{id}:#{RateLimiter.ip(conn)}" + conn = build_conn(:get, "/?id=#{id}") + conn = Conn.fetch_query_params(conn) + conn_2 = build_conn(:get, "/?id=#{101}") - RateLimiter.call(conn, opts) - assert {1, 4, _, _, _} = ExRated.inspect_bucket(parametrized_bucket_name, scale, limit) - assert {0, 5, _, _, _} = ExRated.inspect_bucket(default_bucket_name, scale, limit) + 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 - test "it supports combination of options modifying bucket name" do - limiter_name = :test_options_combo - scale = 1000 - limit = 5 + 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) - Pleroma.Config.put([:rate_limit, limiter_name], {scale, limit}) - base_bucket_name = "#{limiter_name}:group1" - opts = RateLimiter.init({limiter_name, bucket_name: base_bucket_name, params: ["id"]}) - id = "100" + conn = %{build_conn(:get, "/") | remote_ip: {127, 0, 0, 2}} + conn_2 = %{build_conn(:get, "/") | remote_ip: {127, 0, 0, 3}} - conn = conn(:get, "/?id=#{id}") - conn = Plug.Conn.fetch_query_params(conn) + 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 - default_bucket_name = "#{limiter_name}:#{RateLimiter.ip(conn)}" - parametrized_bucket_name = "#{base_bucket_name}:#{id}:#{RateLimiter.ip(conn)}" + conn = RateLimiter.call(conn, plug_opts) - RateLimiter.call(conn, opts) - assert {1, 4, _, _, _} = ExRated.inspect_bucket(parametrized_bucket_name, scale, limit) - assert {0, 5, _, _, _} = ExRated.inspect_bucket(default_bucket_name, scale, limit) + 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 "optional limits for authenticated users" do - limiter_name = :test_authenticated - Ecto.Adapters.SQL.Sandbox.checkout(Pleroma.Repo) + describe "authenticated users" do + setup do + Ecto.Adapters.SQL.Sandbox.checkout(Pleroma.Repo) - scale = 1000 - limit = 5 - Pleroma.Config.put([:rate_limit, limiter_name], [{1, 10}, {scale, limit}]) + :ok + end - opts = RateLimiter.init(limiter_name) + test "can have limits separate from unauthenticated connections" do + limiter_name = :test_authenticated1 - user = insert(:user) - conn = conn(:get, "/") |> assign(:user, user) - bucket_name = "#{limiter_name}:#{user.id}" + 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}]) - conn = RateLimiter.call(conn, opts) - assert {1, 4, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit) + plug_opts = RateLimiter.init(name: limiter_name) - conn = RateLimiter.call(conn, opts) - assert {2, 3, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit) + user = insert(:user) + conn = build_conn(:get, "/") |> assign(:user, user) - conn = RateLimiter.call(conn, opts) - assert {3, 2, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit) + 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, opts) - assert {4, 1, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit) + conn = RateLimiter.call(conn, plug_opts) - conn = RateLimiter.call(conn, opts) - assert {5, 0, to_reset, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit) + assert %{"error" => "Throttled"} = ConnTest.json_response(conn, :too_many_requests) + assert conn.halted + end - conn = RateLimiter.call(conn, opts) + 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}) - assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests) - assert conn.halted + plug_opts = RateLimiter.init(name: limiter_name) - Process.sleep(to_reset) + user = insert(:user) + conn = build_conn(:get, "/") |> assign(:user, user) - conn = conn(:get, "/") |> assign(:user, user) + user_2 = insert(:user) + conn_2 = build_conn(:get, "/") |> assign(:user, user_2) - conn = RateLimiter.call(conn, opts) - assert {1, 4, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit) + for i <- 1..5 do + conn = RateLimiter.call(conn, plug_opts) + assert {^i, _} = RateLimiter.inspect_bucket(conn, limiter_name, plug_opts) + end - refute conn.status == Plug.Conn.Status.code(:too_many_requests) - refute conn.resp_body - refute conn.halted + 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 diff --git a/test/plugs/remote_ip_test.exs b/test/plugs/remote_ip_test.exs index d120c588b..752ab32e7 100644 --- a/test/plugs/remote_ip_test.exs +++ b/test/plugs/remote_ip_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.RemoteIpTest do @@ -8,6 +8,9 @@ defmodule Pleroma.Plugs.RemoteIpTest do alias Pleroma.Plugs.RemoteIp + import Pleroma.Tests.Helpers, only: [clear_config: 1, clear_config: 2] + setup do: clear_config(RemoteIp) + test "disabled" do Pleroma.Config.put(RemoteIp, enabled: false) diff --git a/test/plugs/session_authentication_plug_test.exs b/test/plugs/session_authentication_plug_test.exs index 0000f4258..0949ecfed 100644 --- a/test/plugs/session_authentication_plug_test.exs +++ b/test/plugs/session_authentication_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.SessionAuthenticationPlugTest do diff --git a/test/plugs/set_format_plug_test.exs b/test/plugs/set_format_plug_test.exs index 27c026fdd..7a1dfe9bf 100644 --- a/test/plugs/set_format_plug_test.exs +++ b/test/plugs/set_format_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.SetFormatPlugTest do diff --git a/test/plugs/set_locale_plug_test.exs b/test/plugs/set_locale_plug_test.exs index 0aaeedc1e..7114b1557 100644 --- a/test/plugs/set_locale_plug_test.exs +++ b/test/plugs/set_locale_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.SetLocalePlugTest do diff --git a/test/plugs/set_user_session_id_plug_test.exs b/test/plugs/set_user_session_id_plug_test.exs index f8bfde039..7f1a1e98b 100644 --- a/test/plugs/set_user_session_id_plug_test.exs +++ b/test/plugs/set_user_session_id_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.SetUserSessionIdPlugTest do diff --git a/test/plugs/uploaded_media_plug_test.exs b/test/plugs/uploaded_media_plug_test.exs index 5ba963139..20b13dfac 100644 --- a/test/plugs/uploaded_media_plug_test.exs +++ b/test/plugs/uploaded_media_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.UploadedMediaPlugTest do diff --git a/test/plugs/user_enabled_plug_test.exs b/test/plugs/user_enabled_plug_test.exs index c0fafcab1..b219d8abf 100644 --- a/test/plugs/user_enabled_plug_test.exs +++ b/test/plugs/user_enabled_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.UserEnabledPlugTest do @@ -8,6 +8,8 @@ defmodule Pleroma.Plugs.UserEnabledPlugTest do 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 @@ -16,8 +18,22 @@ defmodule Pleroma.Plugs.UserEnabledPlugTest do 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, info: %{deactivated: true}) + user = insert(:user, deactivated: true) conn = conn diff --git a/test/plugs/user_fetcher_plug_test.exs b/test/plugs/user_fetcher_plug_test.exs index 262eb8d93..0496f14dd 100644 --- a/test/plugs/user_fetcher_plug_test.exs +++ b/test/plugs/user_fetcher_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.UserFetcherPlugTest do diff --git a/test/plugs/user_is_admin_plug_test.exs b/test/plugs/user_is_admin_plug_test.exs index 9e05fff18..fd6a50e53 100644 --- a/test/plugs/user_is_admin_plug_test.exs +++ b/test/plugs/user_is_admin_plug_test.exs @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.UserIsAdminPlugTest do @@ -8,36 +8,112 @@ defmodule Pleroma.Plugs.UserIsAdminPlugTest do alias Pleroma.Plugs.UserIsAdminPlug import Pleroma.Factory - test "accepts a user that is admin" do - user = insert(:user, info: %{is_admin: true}) + describe "unless [:auth, :enforce_oauth_admin_scope_usage]," do + setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false) - conn = - build_conn() - |> assign(:user, user) + test "accepts a user that is an admin" do + user = insert(:user, is_admin: true) - ret_conn = - conn - |> UserIsAdminPlug.call(%{}) + conn = assign(build_conn(), :user, user) - assert conn == ret_conn - end + ret_conn = UserIsAdminPlug.call(conn, %{}) + + assert conn == ret_conn + end + + test "denies a user that isn't an admin" do + user = insert(:user) - test "denies a user that isn't admin" do - user = insert(:user) + conn = + build_conn() + |> assign(:user, user) + |> UserIsAdminPlug.call(%{}) - conn = - build_conn() - |> assign(:user, user) - |> UserIsAdminPlug.call(%{}) + assert conn.status == 403 + end - assert conn.status == 403 + test "denies when a user isn't set" do + conn = UserIsAdminPlug.call(build_conn(), %{}) + + assert conn.status == 403 + end end - test "denies when a user isn't set" do - conn = - build_conn() - |> UserIsAdminPlug.call(%{}) + describe "with [:auth, :enforce_oauth_admin_scope_usage]," do + setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], true) + + setup do + admin_user = insert(:user, is_admin: true) + non_admin_user = insert(:user, is_admin: false) + blank_user = nil + + {:ok, %{users: [admin_user, non_admin_user, blank_user]}} + end + + test "if token has any of admin scopes, accepts a user that is an admin", %{conn: conn} do + user = insert(:user, is_admin: true) + token = insert(:oauth_token, user: user, scopes: ["admin:something"]) + + conn = + conn + |> assign(:user, user) + |> assign(:token, token) + + ret_conn = UserIsAdminPlug.call(conn, %{}) + + assert conn == ret_conn + end + + test "if token has any of admin scopes, denies a user that isn't an admin", %{conn: conn} do + user = insert(:user, is_admin: false) + token = insert(:oauth_token, user: user, scopes: ["admin:something"]) + + conn = + conn + |> assign(:user, user) + |> assign(:token, token) + |> UserIsAdminPlug.call(%{}) + + assert conn.status == 403 + end + + test "if token has any of admin scopes, denies when a user isn't set", %{conn: conn} do + token = insert(:oauth_token, scopes: ["admin:something"]) + + conn = + conn + |> assign(:user, nil) + |> assign(:token, token) + |> UserIsAdminPlug.call(%{}) + + assert conn.status == 403 + end + + test "if token lacks admin scopes, denies users regardless of is_admin flag", + %{users: users} do + for user <- users do + token = insert(:oauth_token, user: user) + + conn = + build_conn() + |> assign(:user, user) + |> assign(:token, token) + |> UserIsAdminPlug.call(%{}) + + assert conn.status == 403 + end + end + + test "if token is missing, denies users regardless of is_admin flag", %{users: users} do + for user <- users do + conn = + build_conn() + |> assign(:user, user) + |> assign(:token, nil) + |> UserIsAdminPlug.call(%{}) - assert conn.status == 403 + assert conn.status == 403 + end + end end end |