[#1234] Defined admin OAuth scopes, refined other scopes. Added tests.
This commit is contained in:
parent
efbc2edba1
commit
76068873db
3 changed files with 210 additions and 111 deletions
|
|
@ -6,23 +6,47 @@ defmodule Pleroma.Plugs.OAuthScopesPlugTest do
|
|||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
alias Pleroma.Plugs.OAuthScopesPlug
|
||||
alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
|
||||
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"]})
|
||||
|
||||
refute conn.halted
|
||||
assert conn.assigns[:user]
|
||||
setup_with_mocks([{EnsurePublicOrAuthenticatedPlug, [], [call: fn conn, _ -> conn end]}]) do
|
||||
:ok
|
||||
end
|
||||
|
||||
test "proceeds with no op if `token.scopes` fulfill specified 'any of' conditions", %{
|
||||
conn: conn
|
||||
} do
|
||||
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 "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,82 +74,112 @@ 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})
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, token.user)
|
||||
|> assign(:token, token)
|
||||
|> OAuthScopesPlug.call(%{scopes: ["follow"], fallback: :proceed_unauthenticated})
|
||||
|
||||
refute conn.halted
|
||||
refute conn.assigns[:user]
|
||||
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
|
||||
|
||||
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)
|
||||
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"]
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, token.user)
|
||||
|> assign(:token, token)
|
||||
|> OAuthScopesPlug.call(%{
|
||||
scopes: ["read", "follow"],
|
||||
op: :&,
|
||||
fallback: :proceed_unauthenticated
|
||||
})
|
||||
conn =
|
||||
conn
|
||||
|> assign(:token, token)
|
||||
|> OAuthScopesPlug.call(%{scopes: any_of_scopes})
|
||||
|
||||
refute conn.halted
|
||||
refute conn.assigns[:user]
|
||||
end
|
||||
assert conn.halted
|
||||
assert 403 == conn.status
|
||||
|
||||
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"]
|
||||
expected_error = "Insufficient permissions: #{Enum.join(any_of_scopes, ", ")}."
|
||||
assert Jason.encode!(%{error: expected_error}) == conn.resp_body
|
||||
end
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:token, token)
|
||||
|> OAuthScopesPlug.call(%{scopes: any_of_scopes})
|
||||
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"]
|
||||
|
||||
assert conn.halted
|
||||
assert 403 == conn.status
|
||||
conn =
|
||||
conn
|
||||
|> assign(:token, token)
|
||||
|> OAuthScopesPlug.call(%{scopes: all_of_scopes, op: :&})
|
||||
|
||||
expected_error = "Insufficient permissions: #{Enum.join(any_of_scopes, ", ")}."
|
||||
assert Jason.encode!(%{error: expected_error}) == conn.resp_body
|
||||
end
|
||||
assert conn.halted
|
||||
assert 403 == conn.status
|
||||
|
||||
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"]
|
||||
expected_error =
|
||||
"Insufficient permissions: #{Enum.join(all_of_scopes -- token.scopes, ", ")}."
|
||||
|
||||
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
|
||||
assert Jason.encode!(%{error: expected_error}) == conn.resp_body
|
||||
end
|
||||
end
|
||||
|
||||
describe "with hierarchical scopes, " do
|
||||
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 =
|
||||
|
|
@ -138,9 +192,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 =
|
||||
|
|
@ -153,4 +207,21 @@ defmodule Pleroma.Plugs.OAuthScopesPlugTest do
|
|||
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
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue