@@ -1536,6 +1536,24 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do | |||
assert user_response = json_response(conn, 200) | |||
assert user_response["header"] != User.banner_url(user) | |||
end | |||
test "requires 'write' permission", %{conn: conn} do | |||
token1 = insert(:oauth_token, scopes: ["read"]) | |||
token2 = insert(:oauth_token, scopes: ["write", "follow"]) | |||
for token <- [token1, token2] do | |||
conn = | |||
conn | |||
|> put_req_header("authorization", "Bearer #{token.token}") | |||
|> patch("/api/v1/accounts/update_credentials", %{}) | |||
if token == token1 do | |||
assert %{"error" => "Insufficient permissions: write."} == json_response(conn, 403) | |||
else | |||
assert json_response(conn, 200) | |||
end | |||
end | |||
end | |||
end | |||
test "get instance information", %{conn: conn} do | |||
@@ -8,36 +8,37 @@ defmodule Pleroma.Web.OAuth.AuthorizationTest do | |||
alias Pleroma.Web.OAuth.App | |||
import Pleroma.Factory | |||
test "create an authorization token for a valid app" do | |||
setup do | |||
{:ok, app} = | |||
Repo.insert( | |||
App.register_changeset(%App{}, %{ | |||
client_name: "client", | |||
scopes: ["scope"], | |||
scopes: ["read", "write"], | |||
redirect_uris: "url" | |||
}) | |||
) | |||
%{app: app} | |||
end | |||
test "create an authorization token for a valid app", %{app: app} do | |||
user = insert(:user) | |||
{:ok, auth} = Authorization.create_authorization(app, user) | |||
{:ok, auth1} = Authorization.create_authorization(app, user) | |||
assert auth1.scopes == app.scopes | |||
assert auth.user_id == user.id | |||
assert auth.app_id == app.id | |||
assert String.length(auth.token) > 10 | |||
assert auth.used == false | |||
end | |||
{:ok, auth2} = Authorization.create_authorization(app, user, ["read"]) | |||
assert auth2.scopes == ["read"] | |||
test "use up a token" do | |||
{:ok, app} = | |||
Repo.insert( | |||
App.register_changeset(%App{}, %{ | |||
client_name: "client", | |||
scopes: ["scope"], | |||
redirect_uris: "url" | |||
}) | |||
) | |||
for auth <- [auth1, auth2] do | |||
assert auth.user_id == user.id | |||
assert auth.app_id == app.id | |||
assert String.length(auth.token) > 10 | |||
assert auth.used == false | |||
end | |||
end | |||
test "use up a token", %{app: app} do | |||
user = insert(:user) | |||
{:ok, auth} = Authorization.create_authorization(app, user) | |||
@@ -61,16 +62,7 @@ defmodule Pleroma.Web.OAuth.AuthorizationTest do | |||
assert {:error, "token expired"} == Authorization.use_token(expired_auth) | |||
end | |||
test "delete authorizations" do | |||
{:ok, app} = | |||
Repo.insert( | |||
App.register_changeset(%App{}, %{ | |||
client_name: "client", | |||
scopes: ["scope"], | |||
redirect_uris: "url" | |||
}) | |||
) | |||
test "delete authorizations", %{app: app} do | |||
user = insert(:user) | |||
{:ok, auth} = Authorization.create_authorization(app, user) | |||
@@ -12,7 +12,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do | |||
test "redirects with oauth authorization" do | |||
user = insert(:user) | |||
app = insert(:oauth_app) | |||
app = insert(:oauth_app, scopes: ["read", "write", "follow"]) | |||
conn = | |||
build_conn() | |||
@@ -22,7 +22,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do | |||
"password" => "test", | |||
"client_id" => app.client_id, | |||
"redirect_uri" => app.redirect_uris, | |||
"scope" => Enum.join(app.scopes, " "), | |||
"scope" => "read write", | |||
"state" => "statepassed" | |||
} | |||
}) | |||
@@ -33,10 +33,12 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do | |||
query = URI.parse(target).query |> URI.query_decoder() |> Map.new() | |||
assert %{"state" => "statepassed", "code" => code} = query | |||
assert Repo.get_by(Authorization, token: code) | |||
auth = Repo.get_by(Authorization, token: code) | |||
assert auth | |||
assert auth.scopes == ["read", "write"] | |||
end | |||
test "correctly handles wrong credentials", %{conn: conn} do | |||
test "returns 401 for wrong credentials", %{conn: conn} do | |||
user = insert(:user) | |||
app = insert(:oauth_app) | |||
@@ -48,7 +50,8 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do | |||
"password" => "wrong", | |||
"client_id" => app.client_id, | |||
"redirect_uri" => app.redirect_uris, | |||
"state" => "statepassed" | |||
"state" => "statepassed", | |||
"scope" => Enum.join(app.scopes, " ") | |||
} | |||
}) | |||
|> html_response(:unauthorized) | |||
@@ -58,14 +61,66 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do | |||
assert result =~ app.redirect_uris | |||
# Error message | |||
assert result =~ "Invalid" | |||
assert result =~ "Invalid Username/Password" | |||
end | |||
test "issues a token for an all-body request" do | |||
test "returns 401 for missing scopes", %{conn: conn} do | |||
user = insert(:user) | |||
app = insert(:oauth_app) | |||
{:ok, auth} = Authorization.create_authorization(app, user) | |||
result = | |||
conn | |||
|> post("/oauth/authorize", %{ | |||
"authorization" => %{ | |||
"name" => user.nickname, | |||
"password" => "test", | |||
"client_id" => app.client_id, | |||
"redirect_uri" => app.redirect_uris, | |||
"state" => "statepassed", | |||
"scope" => "" | |||
} | |||
}) | |||
|> html_response(:unauthorized) | |||
# Keep the details | |||
assert result =~ app.client_id | |||
assert result =~ app.redirect_uris | |||
# Error message | |||
assert result =~ "Permissions not specified" | |||
end | |||
test "returns 401 for scopes beyond app scopes", %{conn: conn} do | |||
user = insert(:user) | |||
app = insert(:oauth_app, scopes: ["read", "write"]) | |||
result = | |||
conn | |||
|> post("/oauth/authorize", %{ | |||
"authorization" => %{ | |||
"name" => user.nickname, | |||
"password" => "test", | |||
"client_id" => app.client_id, | |||
"redirect_uri" => app.redirect_uris, | |||
"state" => "statepassed", | |||
"scope" => "read write follow" | |||
} | |||
}) | |||
|> html_response(:unauthorized) | |||
# Keep the details | |||
assert result =~ app.client_id | |||
assert result =~ app.redirect_uris | |||
# Error message | |||
assert result =~ "Permissions not specified" | |||
end | |||
test "issues a token for an all-body request" do | |||
user = insert(:user) | |||
app = insert(:oauth_app, scopes: ["read", "write"]) | |||
{:ok, auth} = Authorization.create_authorization(app, user, ["write"]) | |||
conn = | |||
build_conn() | |||
@@ -78,15 +133,19 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do | |||
}) | |||
assert %{"access_token" => token} = json_response(conn, 200) | |||
assert Repo.get_by(Token, token: token) | |||
token = Repo.get_by(Token, token: token) | |||
assert token | |||
assert token.scopes == auth.scopes | |||
end | |||
test "issues a token for `password` grant_type with valid credentials" do | |||
test "issues a token for `password` grant_type with valid credentials, with full permissions by default" do | |||
password = "testpassword" | |||
user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password)) | |||
app = insert(:oauth_app) | |||
app = insert(:oauth_app, scopes: ["read", "write"]) | |||
# Note: "scope" param is intentionally omitted | |||
conn = | |||
build_conn() | |||
|> post("/oauth/token", %{ | |||
@@ -98,14 +157,18 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do | |||
}) | |||
assert %{"access_token" => token} = json_response(conn, 200) | |||
assert Repo.get_by(Token, token: token) | |||
token = Repo.get_by(Token, token: token) | |||
assert token | |||
assert token.scopes == app.scopes | |||
end | |||
test "issues a token for request with HTTP basic auth client credentials" do | |||
user = insert(:user) | |||
app = insert(:oauth_app) | |||
app = insert(:oauth_app, scopes: ["scope1", "scope2"]) | |||
{:ok, auth} = Authorization.create_authorization(app, user) | |||
{:ok, auth} = Authorization.create_authorization(app, user, ["scope2"]) | |||
assert auth.scopes == ["scope2"] | |||
app_encoded = | |||
(URI.encode_www_form(app.client_id) <> ":" <> URI.encode_www_form(app.client_secret)) | |||
@@ -121,7 +184,10 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do | |||
}) | |||
assert %{"access_token" => token} = json_response(conn, 200) | |||
assert Repo.get_by(Token, token: token) | |||
token = Repo.get_by(Token, token: token) | |||
assert token | |||
assert token.scopes == ["scope2"] | |||
end | |||
test "rejects token exchange with invalid client credentials" do | |||
@@ -11,24 +11,26 @@ defmodule Pleroma.Web.OAuth.TokenTest do | |||
import Pleroma.Factory | |||
test "exchanges a auth token for an access token" do | |||
test "exchanges a auth token for an access token, preserving `scopes`" do | |||
{:ok, app} = | |||
Repo.insert( | |||
App.register_changeset(%App{}, %{ | |||
client_name: "client", | |||
scopes: ["scope"], | |||
scopes: ["read", "write"], | |||
redirect_uris: "url" | |||
}) | |||
) | |||
user = insert(:user) | |||
{:ok, auth} = Authorization.create_authorization(app, user) | |||
{:ok, auth} = Authorization.create_authorization(app, user, ["read"]) | |||
assert auth.scopes == ["read"] | |||
{:ok, token} = Token.exchange_token(app, auth) | |||
assert token.app_id == app.id | |||
assert token.user_id == user.id | |||
assert token.scopes == auth.scopes | |||
assert String.length(token.token) > 10 | |||
assert String.length(token.refresh_token) > 10 | |||
@@ -1690,6 +1690,24 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do | |||
assert [relationship] = json_response(conn, 200) | |||
assert other_user.id == relationship["id"] | |||
end | |||
test "requires 'read' permission", %{conn: conn} do | |||
token1 = insert(:oauth_token, scopes: ["write"]) | |||
token2 = insert(:oauth_token, scopes: ["read"]) | |||
for token <- [token1, token2] do | |||
conn = | |||
conn | |||
|> put_req_header("authorization", "Bearer #{token.token}") | |||
|> get("/api/pleroma/friend_requests") | |||
if token == token1 do | |||
assert %{"error" => "Insufficient permissions: read."} == json_response(conn, 403) | |||
else | |||
assert json_response(conn, 200) | |||
end | |||
end | |||
end | |||
end | |||
describe "POST /api/pleroma/friendships/approve" do | |||
@@ -16,6 +16,25 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do | |||
assert response == "job started" | |||
end | |||
test "requires 'follow' permission", %{conn: conn} do | |||
token1 = insert(:oauth_token, scopes: ["read", "write"]) | |||
token2 = insert(:oauth_token, scopes: ["follow"]) | |||
another_user = insert(:user) | |||
for token <- [token1, token2] 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) | |||
else | |||
assert json_response(conn, 200) | |||
end | |||
end | |||
end | |||
end | |||
describe "POST /api/pleroma/blocks_import" do | |||