aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/plugs/oauth_scopes_plug_test.exs237
-rw-r--r--test/support/factory.ex1
-rw-r--r--test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs5
-rw-r--r--test/web/oauth/oauth_controller_test.exs6
-rw-r--r--test/web/twitter_api/util_controller_test.exs10
5 files changed, 184 insertions, 75 deletions
diff --git a/test/plugs/oauth_scopes_plug_test.exs b/test/plugs/oauth_scopes_plug_test.exs
index 6a13ea811..be6d1340b 100644
--- a/test/plugs/oauth_scopes_plug_test.exs
+++ b/test/plugs/oauth_scopes_plug_test.exs
@@ -5,24 +5,48 @@
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
- test "proceeds with no op if `assigns[:token]` is nil", %{conn: conn} do
- conn =
- conn
- |> assign(:user, insert(:user))
- |> OAuthScopesPlug.call(%{scopes: ["read"]})
+ setup_with_mocks([{EnsurePublicOrAuthenticatedPlug, [], [call: fn conn, _ -> conn end]}]) do
+ :ok
+ end
- refute conn.halted
- assert conn.assigns[:user]
+ describe "when `assigns[:token]` is nil, " do
+ test "with :skip_instance_privacy_check option, proceeds with no op", %{conn: conn} do
+ conn =
+ conn
+ |> assign(:user, insert(:user))
+ |> OAuthScopesPlug.call(%{scopes: ["read"], skip_instance_privacy_check: true})
+
+ 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
- test "proceeds with no op if `token.scopes` fulfill specified 'any of' conditions", %{
- conn: conn
- } 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 =
@@ -35,9 +59,9 @@ defmodule Pleroma.Plugs.OAuthScopesPlugTest do
assert conn.assigns[:user]
end
- test "proceeds with no op if `token.scopes` fulfill specified 'all of' conditions", %{
- conn: conn
- } do
+ 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 =
@@ -50,73 +74,154 @@ defmodule Pleroma.Plugs.OAuthScopesPlugTest do
assert conn.assigns[:user]
end
- test "proceeds with cleared `assigns[:user]` if `token.scopes` doesn't fulfill specified 'any of' conditions " <>
- "and `fallback: :proceed_unauthenticated` option is specified",
- %{conn: conn} do
- token = insert(:oauth_token, scopes: ["read", "write"]) |> Repo.preload(:user)
+ 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",
+ %{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, :_))
+ end
+ end
- conn =
- conn
- |> assign(:user, token.user)
- |> assign(:token, token)
- |> OAuthScopesPlug.call(%{scopes: ["follow"], fallback: :proceed_unauthenticated})
+ describe "without :fallback option, " 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"]
- refute conn.halted
- refute conn.assigns[:user]
- end
+ conn =
+ conn
+ |> assign(:token, token)
+ |> OAuthScopesPlug.call(%{scopes: any_of_scopes})
- test "proceeds with cleared `assigns[:user]` if `token.scopes` doesn't fulfill specified 'all of' conditions " <>
- "and `fallback: :proceed_unauthenticated` option is specified",
- %{conn: conn} do
- token = insert(:oauth_token, scopes: ["read", "write"]) |> Repo.preload(:user)
+ assert conn.halted
+ assert 403 == conn.status
- conn =
- conn
- |> assign(:user, token.user)
- |> assign(:token, token)
- |> OAuthScopesPlug.call(%{
- scopes: ["read", "follow"],
- op: :&,
- fallback: :proceed_unauthenticated
- })
+ expected_error = "Insufficient permissions: #{Enum.join(any_of_scopes, ", ")}."
+ assert Jason.encode!(%{error: expected_error}) == conn.resp_body
+ end
- refute conn.halted
- refute conn.assigns[:user]
- 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"]
- test "returns 403 and halts in case of no :fallback option and `token.scopes` not fulfilling specified 'any of' conditions",
- %{conn: conn} do
- token = insert(:oauth_token, scopes: ["read", "write"])
- any_of_scopes = ["follow"]
+ conn =
+ conn
+ |> assign(:token, token)
+ |> OAuthScopesPlug.call(%{scopes: all_of_scopes, op: :&})
- conn =
- conn
- |> assign(:token, token)
- |> OAuthScopesPlug.call(%{scopes: any_of_scopes})
+ 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(any_of_scopes, ", ")}."
- assert Jason.encode!(%{error: expected_error}) == conn.resp_body
+ assert Jason.encode!(%{error: expected_error}) == conn.resp_body
+ end
end
- test "returns 403 and halts in case of no :fallback option and `token.scopes` not fulfilling specified 'all of' conditions",
- %{conn: conn} do
- token = insert(:oauth_token, scopes: ["read", "write"])
- all_of_scopes = ["write", "follow"]
+ 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
- conn =
- conn
- |> assign(:token, token)
- |> OAuthScopesPlug.call(%{scopes: all_of_scopes, op: :&})
+ 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 conn.halted
- assert 403 == conn.status
+ assert f.(["read", "write:something", "follow"], ["write", "read"]) ==
+ ["read", "write:something"]
- expected_error =
- "Insufficient permissions: #{Enum.join(all_of_scopes -- token.scopes, ", ")}."
+ assert f.(["admin:read"], ["write", "read"]) == []
- assert Jason.encode!(%{error: expected_error}) == conn.resp_body
+ assert f.(["admin:read"], ["write", "admin"]) == ["admin:read"]
+ end
end
end
diff --git a/test/support/factory.ex b/test/support/factory.ex
index 4f3244025..b180844cd 100644
--- a/test/support/factory.ex
+++ b/test/support/factory.ex
@@ -324,6 +324,7 @@ defmodule Pleroma.Factory do
%Pleroma.Web.OAuth.Token{
token: :crypto.strong_rand_bytes(32) |> Base.url_encode64(),
+ scopes: ["read"],
refresh_token: :crypto.strong_rand_bytes(32) |> Base.url_encode64(),
user: build(:user),
app_id: oauth_app.id,
diff --git a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs
index 599cd61c8..618031b40 100644
--- a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs
+++ b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs
@@ -272,7 +272,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
assert user_response["pleroma"]["background_image"]
end
- test "requires 'write' permission", %{conn: conn} do
+ test "requires 'write:accounts' permission", %{conn: conn} do
token1 = insert(:oauth_token, scopes: ["read"])
token2 = insert(:oauth_token, scopes: ["write", "follow"])
@@ -283,7 +283,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
|> patch("/api/v1/accounts/update_credentials", %{})
if token == token1 do
- assert %{"error" => "Insufficient permissions: write."} == json_response(conn, 403)
+ assert %{"error" => "Insufficient permissions: write:accounts."} ==
+ json_response(conn, 403)
else
assert json_response(conn, 200)
end
diff --git a/test/web/oauth/oauth_controller_test.exs b/test/web/oauth/oauth_controller_test.exs
index 4d0741d14..41aaf6189 100644
--- a/test/web/oauth/oauth_controller_test.exs
+++ b/test/web/oauth/oauth_controller_test.exs
@@ -557,7 +557,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
"password" => "test",
"client_id" => app.client_id,
"redirect_uri" => redirect_uri,
- "scope" => "read write",
+ "scope" => "read:subscope write",
"state" => "statepassed"
}
})
@@ -570,7 +570,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
assert %{"state" => "statepassed", "code" => code} = query
auth = Repo.get_by(Authorization, token: code)
assert auth
- assert auth.scopes == ["read", "write"]
+ assert auth.scopes == ["read:subscope", "write"]
end
test "returns 401 for wrong credentials", %{conn: conn} do
@@ -627,7 +627,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
assert result =~ "This action is outside the authorized scopes"
end
- test "returns 401 for scopes beyond app scopes", %{conn: conn} do
+ test "returns 401 for scopes beyond app scopes hierarchy", %{conn: conn} do
user = insert(:user)
app = insert(:oauth_app, scopes: ["read", "write"])
redirect_uri = OAuthController.default_redirect_uri(app)
diff --git a/test/web/twitter_api/util_controller_test.exs b/test/web/twitter_api/util_controller_test.exs
index 56e318182..9d4cb70f0 100644
--- a/test/web/twitter_api/util_controller_test.exs
+++ b/test/web/twitter_api/util_controller_test.exs
@@ -81,19 +81,21 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
assert response == "job started"
end
- test "requires 'follow' permission", %{conn: conn} do
+ test "requires 'follow' or 'write:follows' permissions", %{conn: conn} do
token1 = insert(:oauth_token, scopes: ["read", "write"])
token2 = insert(:oauth_token, scopes: ["follow"])
+ token3 = insert(:oauth_token, scopes: ["something"])
another_user = insert(:user)
- for token <- [token1, token2] do
+ for token <- [token1, token2, token3] do
conn =
conn
|> put_req_header("authorization", "Bearer #{token.token}")
|> post("/api/pleroma/follow_import", %{"list" => "#{another_user.ap_id}"})
- if token == token1 do
- assert %{"error" => "Insufficient permissions: follow."} == json_response(conn, 403)
+ if token == token3 do
+ assert %{"error" => "Insufficient permissions: follow | write:follows."} ==
+ json_response(conn, 403)
else
assert json_response(conn, 200)
end