diff --git a/benchmarks/load_testing/activities.ex b/benchmarks/load_testing/activities.ex
index 482e42fc1..ff0d481a8 100644
--- a/benchmarks/load_testing/activities.ex
+++ b/benchmarks/load_testing/activities.ex
@@ -123,7 +123,7 @@ def generate_tagged_activities(opts \\ []) do
Enum.each(1..activity_count, fn _ ->
random = :rand.uniform()
i = Enum.find_index(intervals, fn {lower, upper} -> lower <= random && upper > random end)
- CommonAPI.post(Enum.random(users), %{"status" => "a post with the tag #tag_#{i}"})
+ CommonAPI.post(Enum.random(users), %{status: "a post with the tag #tag_#{i}"})
end)
end
@@ -137,8 +137,8 @@ defp generate_long_thread(visibility, user, friends, non_friends, _opts) do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "Start of #{visibility} long thread",
- "visibility" => visibility
+ status: "Start of #{visibility} long thread",
+ visibility: visibility
})
Agent.update(:benchmark_state, fn state ->
@@ -186,7 +186,7 @@ defp insert_activity("simple", visibility, group, user, friends, non_friends, _o
{:ok, _activity} =
group
|> get_actor(user, friends, non_friends)
- |> CommonAPI.post(%{"status" => "Simple status", "visibility" => visibility})
+ |> CommonAPI.post(%{status: "Simple status", visibility: visibility})
end
defp insert_activity("emoji", visibility, group, user, friends, non_friends, _opts) do
@@ -194,8 +194,8 @@ defp insert_activity("emoji", visibility, group, user, friends, non_friends, _op
group
|> get_actor(user, friends, non_friends)
|> CommonAPI.post(%{
- "status" => "Simple status with emoji :firefox:",
- "visibility" => visibility
+ status: "Simple status with emoji :firefox:",
+ visibility: visibility
})
end
@@ -213,8 +213,8 @@ defp insert_activity("mentions", visibility, group, user, friends, non_friends,
group
|> get_actor(user, friends, non_friends)
|> CommonAPI.post(%{
- "status" => Enum.join(user_mentions, ", ") <> " simple status with mentions",
- "visibility" => visibility
+ status: Enum.join(user_mentions, ", ") <> " simple status with mentions",
+ visibility: visibility
})
end
@@ -236,8 +236,8 @@ defp insert_activity("hell_thread", visibility, group, user, friends, non_friend
group
|> get_actor(user, friends, non_friends)
|> CommonAPI.post(%{
- "status" => mentions <> " hell thread status",
- "visibility" => visibility
+ status: mentions <> " hell thread status",
+ visibility: visibility
})
end
@@ -262,9 +262,9 @@ defp insert_activity("attachment", visibility, group, user, friends, non_friends
{:ok, _activity} =
CommonAPI.post(actor, %{
- "status" => "Post with attachment",
- "visibility" => visibility,
- "media_ids" => [object.id]
+ status: "Post with attachment",
+ visibility: visibility,
+ media_ids: [object.id]
})
end
@@ -272,7 +272,7 @@ defp insert_activity("tag", visibility, group, user, friends, non_friends, _opts
{:ok, _activity} =
group
|> get_actor(user, friends, non_friends)
- |> CommonAPI.post(%{"status" => "Status with #tag", "visibility" => visibility})
+ |> CommonAPI.post(%{status: "Status with #tag", visibility: visibility})
end
defp insert_activity("like", visibility, group, user, friends, non_friends, opts) do
@@ -312,8 +312,7 @@ defp insert_activity("simple_thread", visibility, group, user, friends, non_frie
actor = get_actor(group, user, friends, non_friends)
tasks = get_reply_tasks(visibility, group)
- {:ok, activity} =
- CommonAPI.post(user, %{"status" => "Simple status", "visibility" => visibility})
+ {:ok, activity} = CommonAPI.post(user, %{status: "Simple status", visibility: visibility})
acc = {activity.id, ["@" <> actor.nickname, "reply to status"]}
insert_replies(tasks, visibility, user, friends, non_friends, acc)
@@ -336,8 +335,8 @@ defp insert_activity("simple_thread", "direct", group, user, friends, non_friend
{:ok, activity} =
CommonAPI.post(actor, %{
- "status" => Enum.join(data, ", ") <> "simple status",
- "visibility" => "direct"
+ status: Enum.join(data, ", ") <> "simple status",
+ visibility: "direct"
})
acc = {activity.id, ["@" <> user.nickname | data] ++ ["reply to status"]}
@@ -527,9 +526,9 @@ defp insert_direct_replies(tasks, user, list, acc) do
defp insert_reply(actor, data, activity_id, visibility) do
{:ok, reply} =
CommonAPI.post(actor, %{
- "status" => Enum.join(data, ", "),
- "visibility" => visibility,
- "in_reply_to_status_id" => activity_id
+ status: Enum.join(data, ", "),
+ visibility: visibility,
+ in_reply_to_status_id: activity_id
})
{reply.id, ["@" <> actor.nickname | data]}
diff --git a/docs/configuration/storing_remote_media.md b/docs/configuration/storing_remote_media.md
new file mode 100644
index 000000000..7e91fe7d9
--- /dev/null
+++ b/docs/configuration/storing_remote_media.md
@@ -0,0 +1,38 @@
+# Storing Remote Media
+
+Pleroma does not store remote/federated media by default. The best way to achieve this is to change Nginx to keep its reverse proxy cache
+for a year and to activate the `MediaProxyWarmingPolicy` MRF policy in Pleroma which will automatically fetch all media through the proxy
+as soon as the post is received by your instance.
+
+## Nginx
+
+```
+ proxy_cache_path /long/term/storage/path/pleroma-media-cache levels=1:2
+ keys_zone=pleroma_media_cache:10m inactive=1y use_temp_path=off;
+
+ location ~ ^/(media|proxy) {
+ proxy_cache pleroma_media_cache;
+ slice 1m;
+ proxy_cache_key $host$uri$is_args$args$slice_range;
+ proxy_set_header Range $slice_range;
+ proxy_http_version 1.1;
+ proxy_cache_valid 206 301 302 304 1h;
+ proxy_cache_valid 200 1y;
+ proxy_cache_use_stale error timeout invalid_header updating;
+ proxy_ignore_client_abort on;
+ proxy_buffering on;
+ chunked_transfer_encoding on;
+ proxy_ignore_headers Cache-Control Expires;
+ proxy_hide_header Cache-Control Expires;
+ proxy_pass http://127.0.0.1:4000;
+ }
+```
+
+## Pleroma
+
+Add to your `prod.secret.exs`:
+
+```
+config :pleroma, :instance,
+ rewrite_policy: [Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy]
+```
diff --git a/lib/pleroma/mfa.ex b/lib/pleroma/mfa.ex
index 2b77f5426..01b743f4f 100644
--- a/lib/pleroma/mfa.ex
+++ b/lib/pleroma/mfa.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors
+# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.MFA do
diff --git a/lib/pleroma/mfa/backup_codes.ex b/lib/pleroma/mfa/backup_codes.ex
index 2b5ec34f8..9875310ff 100644
--- a/lib/pleroma/mfa/backup_codes.ex
+++ b/lib/pleroma/mfa/backup_codes.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors
+# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.MFA.BackupCodes do
diff --git a/lib/pleroma/mfa/changeset.ex b/lib/pleroma/mfa/changeset.ex
index 9b020aa8e..77c4fa202 100644
--- a/lib/pleroma/mfa/changeset.ex
+++ b/lib/pleroma/mfa/changeset.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors
+# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.MFA.Changeset do
diff --git a/lib/pleroma/mfa/settings.ex b/lib/pleroma/mfa/settings.ex
index 2764b889c..de6e2228f 100644
--- a/lib/pleroma/mfa/settings.ex
+++ b/lib/pleroma/mfa/settings.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors
+# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.MFA.Settings do
diff --git a/lib/pleroma/mfa/token.ex b/lib/pleroma/mfa/token.ex
index 25ff7fb29..0b2449971 100644
--- a/lib/pleroma/mfa/token.ex
+++ b/lib/pleroma/mfa/token.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors
+# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.MFA.Token do
diff --git a/lib/pleroma/mfa/totp.ex b/lib/pleroma/mfa/totp.ex
index 1407afc57..d2ea2b3aa 100644
--- a/lib/pleroma/mfa/totp.ex
+++ b/lib/pleroma/mfa/totp.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors
+# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.MFA.TOTP do
diff --git a/lib/pleroma/object.ex b/lib/pleroma/object.ex
index e678fd415..ab16bf2db 100644
--- a/lib/pleroma/object.ex
+++ b/lib/pleroma/object.ex
@@ -138,12 +138,17 @@ def normalize(ap_id, true, options) when is_binary(ap_id) do
def normalize(_, _, _), do: nil
- # Owned objects can only be mutated by their owner
- def authorize_mutation(%Object{data: %{"actor" => actor}}, %User{ap_id: ap_id}),
- do: actor == ap_id
+ # Owned objects can only be accessed by their owner
+ def authorize_access(%Object{data: %{"actor" => actor}}, %User{ap_id: ap_id}) do
+ if actor == ap_id do
+ :ok
+ else
+ {:error, :forbidden}
+ end
+ end
- # Legacy objects can be mutated by anybody
- def authorize_mutation(%Object{}, %User{}), do: true
+ # Legacy objects can be accessed by anybody
+ def authorize_access(%Object{}, %User{}), do: :ok
@spec get_cached_by_ap_id(String.t()) :: Object.t() | nil
def get_cached_by_ap_id(ap_id) do
diff --git a/lib/pleroma/plugs/authentication_plug.ex b/lib/pleroma/plugs/authentication_plug.ex
index 2cdf6c951..057ea42f1 100644
--- a/lib/pleroma/plugs/authentication_plug.ex
+++ b/lib/pleroma/plugs/authentication_plug.ex
@@ -30,6 +30,25 @@ def checkpw(_password, _password_hash) do
false
end
+ def maybe_update_password(%User{password_hash: "$2" <> _} = user, password) do
+ do_update_password(user, password)
+ end
+
+ def maybe_update_password(%User{password_hash: "$6" <> _} = user, password) do
+ do_update_password(user, password)
+ end
+
+ def maybe_update_password(user, _), do: {:ok, user}
+
+ defp do_update_password(user, password) do
+ user
+ |> User.password_update_changeset(%{
+ "password" => password,
+ "password_confirmation" => password
+ })
+ |> Pleroma.Repo.update()
+ end
+
def call(%{assigns: %{user: %User{}}} = conn, _), do: conn
def call(
@@ -42,6 +61,8 @@ def call(
_
) do
if checkpw(password, password_hash) do
+ {:ok, auth_user} = maybe_update_password(auth_user, password)
+
conn
|> assign(:user, auth_user)
|> OAuthScopesPlug.skip_plug()
diff --git a/lib/pleroma/web/api_spec/operations/timeline_operation.ex b/lib/pleroma/web/api_spec/operations/timeline_operation.ex
index cb9d75841..8e19bace7 100644
--- a/lib/pleroma/web/api_spec/operations/timeline_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/timeline_operation.ex
@@ -43,7 +43,7 @@ def direct_operation do
description:
"View statuses with a “direct” privacy, from your account or in your notifications",
deprecated: true,
- parameters: pagination_params(),
+ parameters: [with_muted_param() | pagination_params()],
security: [%{"oAuth" => ["read:statuses"]}],
operationId: "TimelineController.direct",
responses: %{
diff --git a/lib/pleroma/web/auth/pleroma_authenticator.ex b/lib/pleroma/web/auth/pleroma_authenticator.ex
index a8f554aa3..200ca03dc 100644
--- a/lib/pleroma/web/auth/pleroma_authenticator.ex
+++ b/lib/pleroma/web/auth/pleroma_authenticator.ex
@@ -16,7 +16,8 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticator do
def get_user(%Plug.Conn{} = conn) do
with {:ok, {name, password}} <- fetch_credentials(conn),
{_, %User{} = user} <- {:user, fetch_user(name)},
- {_, true} <- {:checkpw, AuthenticationPlug.checkpw(password, user.password_hash)} do
+ {_, true} <- {:checkpw, AuthenticationPlug.checkpw(password, user.password_hash)},
+ {:ok, user} <- AuthenticationPlug.maybe_update_password(user, password) do
{:ok, user}
else
{:error, _reason} = error -> error
diff --git a/lib/pleroma/web/auth/totp_authenticator.ex b/lib/pleroma/web/auth/totp_authenticator.ex
index ce8a76219..1794e407c 100644
--- a/lib/pleroma/web/auth/totp_authenticator.ex
+++ b/lib/pleroma/web/auth/totp_authenticator.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors
+# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Auth.TOTPAuthenticator do
diff --git a/lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex b/lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex
index 0a257f604..8af557b61 100644
--- a/lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex
@@ -20,6 +20,10 @@ def call(conn, {:error, :not_found}) do
render_error(conn, :not_found, "Record not found")
end
+ def call(conn, {:error, :forbidden}) do
+ render_error(conn, :forbidden, "Access denied")
+ end
+
def call(conn, {:error, error_message}) do
conn
|> put_status(:bad_request)
diff --git a/lib/pleroma/web/mastodon_api/controllers/media_controller.ex b/lib/pleroma/web/mastodon_api/controllers/media_controller.ex
index a21233393..513de279f 100644
--- a/lib/pleroma/web/mastodon_api/controllers/media_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/media_controller.ex
@@ -14,7 +14,8 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
plug(Pleroma.Web.ApiSpec.CastAndValidate)
plug(:put_view, Pleroma.Web.MastodonAPI.StatusView)
- plug(OAuthScopesPlug, %{scopes: ["write:media"]})
+ plug(OAuthScopesPlug, %{scopes: ["read:media"]} when action == :show)
+ plug(OAuthScopesPlug, %{scopes: ["write:media"]} when action != :show)
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.MediaOperation
@@ -55,7 +56,7 @@ def create2(_conn, _data), do: {:error, :bad_request}
@doc "PUT /api/v1/media/:id"
def update(%{assigns: %{user: user}, body_params: %{description: description}} = conn, %{id: id}) do
with %Object{} = object <- Object.get_by_id(id),
- true <- Object.authorize_mutation(object, user),
+ :ok <- Object.authorize_access(object, user),
{:ok, %Object{data: data}} <- Object.update_data(object, %{"name" => description}) do
attachment_data = Map.put(data, "id", object.id)
@@ -66,13 +67,14 @@ def update(%{assigns: %{user: user}, body_params: %{description: description}} =
def update(conn, data), do: show(conn, data)
@doc "GET /api/v1/media/:id"
- def show(conn, %{id: id}) do
- with %Object{data: data, id: object_id} <- Object.get_by_id(id) do
+ def show(%{assigns: %{user: user}} = conn, %{id: id}) do
+ with %Object{data: data, id: object_id} = object <- Object.get_by_id(id),
+ :ok <- Object.authorize_access(object, user) do
attachment_data = Map.put(data, "id", object_id)
render(conn, "attachment.json", %{attachment: attachment_data})
end
end
- def get_media(_conn, _data), do: {:error, :bad_request}
+ def show(_conn, _data), do: {:error, :bad_request}
end
diff --git a/lib/pleroma/web/oauth/mfa_controller.ex b/lib/pleroma/web/oauth/mfa_controller.ex
index e52cccd85..53e19f82e 100644
--- a/lib/pleroma/web/oauth/mfa_controller.ex
+++ b/lib/pleroma/web/oauth/mfa_controller.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors
+# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.OAuth.MFAController do
diff --git a/lib/pleroma/web/oauth/mfa_view.ex b/lib/pleroma/web/oauth/mfa_view.ex
index e88e7066b..41d5578dc 100644
--- a/lib/pleroma/web/oauth/mfa_view.ex
+++ b/lib/pleroma/web/oauth/mfa_view.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors
+# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.OAuth.MFAView do
diff --git a/lib/pleroma/web/oauth/token/clean_worker.ex b/lib/pleroma/web/oauth/token/clean_worker.ex
index 2c3bb9ded..e3aa4eb7e 100644
--- a/lib/pleroma/web/oauth/token/clean_worker.ex
+++ b/lib/pleroma/web/oauth/token/clean_worker.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors
+# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.OAuth.Token.CleanWorker do
diff --git a/lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex b/lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex
index eb9989cdf..b86791d09 100644
--- a/lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors
+# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.PleromaAPI.TwoFactorAuthenticationController do
diff --git a/test/plugs/authentication_plug_test.exs b/test/plugs/authentication_plug_test.exs
index c8ede71c0..3c70c1747 100644
--- a/test/plugs/authentication_plug_test.exs
+++ b/test/plugs/authentication_plug_test.exs
@@ -11,6 +11,7 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do
alias Pleroma.User
import ExUnit.CaptureLog
+ import Pleroma.Factory
setup %{conn: conn} do
user = %User{
@@ -50,16 +51,41 @@ test "with a correct password in the credentials, " <>
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"})
-
- ret_conn =
- conn
+ |> assign(:auth_user, user)
+ |> assign(:auth_credentials, %{password: "123"})
|> 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
+
+ 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
diff --git a/test/web/auth/pleroma_authenticator_test.exs b/test/web/auth/pleroma_authenticator_test.exs
index 5a421e5ed..1ba0dfecc 100644
--- a/test/web/auth/pleroma_authenticator_test.exs
+++ b/test/web/auth/pleroma_authenticator_test.exs
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors
+# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Auth.PleromaAuthenticatorTest do
@@ -15,11 +15,16 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticatorTest do
{:ok, [user: user, name: name, password: password]}
end
- test "get_user/authorization", %{user: user, name: name, password: password} do
+ test "get_user/authorization", %{name: name, password: password} do
+ name = name <> "1"
+ user = insert(:user, nickname: name, password_hash: Bcrypt.hash_pwd_salt(password))
+
params = %{"authorization" => %{"name" => name, "password" => password}}
res = PleromaAuthenticator.get_user(%Plug.Conn{params: params})
- assert {:ok, user} == res
+ assert {:ok, returned_user} = res
+ assert returned_user.id == user.id
+ assert "$pbkdf2" <> _ = returned_user.password_hash
end
test "get_user/authorization with invalid password", %{name: name} do
diff --git a/test/web/auth/totp_authenticator_test.exs b/test/web/auth/totp_authenticator_test.exs
index e502e0ae8..84d4cd840 100644
--- a/test/web/auth/totp_authenticator_test.exs
+++ b/test/web/auth/totp_authenticator_test.exs
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors
+# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Auth.TOTPAuthenticatorTest do
diff --git a/test/web/mastodon_api/controllers/media_controller_test.exs b/test/web/mastodon_api/controllers/media_controller_test.exs
index 7ba1727f2..906fd940f 100644
--- a/test/web/mastodon_api/controllers/media_controller_test.exs
+++ b/test/web/mastodon_api/controllers/media_controller_test.exs
@@ -9,9 +9,9 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
- setup do: oauth_access(["write:media"])
-
describe "Upload media" do
+ setup do: oauth_access(["write:media"])
+
setup do
image = %Plug.Upload{
content_type: "image/jpg",
@@ -42,7 +42,7 @@ test "/api/v1/media", %{conn: conn, image: image} do
assert object.data["actor"] == User.ap_id(conn.assigns[:user])
end
- test "/api/v2/media", %{conn: conn, image: image} do
+ test "/api/v2/media", %{conn: conn, user: user, image: image} do
desc = "Description of the image"
response =
@@ -53,6 +53,8 @@ test "/api/v2/media", %{conn: conn, image: image} do
assert media_id = response["id"]
+ %{conn: conn} = oauth_access(["read:media"], user: user)
+
media =
conn
|> get("/api/v1/media/#{media_id}")
@@ -61,12 +63,15 @@ test "/api/v2/media", %{conn: conn, image: image} do
assert media["type"] == "image"
assert media["description"] == desc
assert media["id"]
+
object = Object.get_by_id(media["id"])
- assert object.data["actor"] == User.ap_id(conn.assigns[:user])
+ assert object.data["actor"] == user.ap_id
end
end
describe "Update media description" do
+ setup do: oauth_access(["write:media"])
+
setup %{user: actor} do
file = %Plug.Upload{
content_type: "image/jpg",
@@ -96,7 +101,9 @@ test "/api/v1/media/:id good request", %{conn: conn, object: object} do
end
end
- describe "Get media by id" do
+ describe "Get media by id (/api/v1/media/:id)" do
+ setup do: oauth_access(["read:media"])
+
setup %{user: actor} do
file = %Plug.Upload{
content_type: "image/jpg",
@@ -114,7 +121,7 @@ test "/api/v1/media/:id good request", %{conn: conn, object: object} do
[object: object]
end
- test "/api/v1/media/:id", %{conn: conn, object: object} do
+ test "it returns media object when requested by owner", %{conn: conn, object: object} do
media =
conn
|> get("/api/v1/media/#{object.id}")
@@ -124,5 +131,16 @@ test "/api/v1/media/:id", %{conn: conn, object: object} do
assert media["type"] == "image"
assert media["id"]
end
+
+ test "it returns 403 if media object requested by non-owner", %{object: object, user: user} do
+ %{conn: conn, user: other_user} = oauth_access(["read:media"])
+
+ assert object.data["actor"] == user.ap_id
+ refute user.id == other_user.id
+
+ conn
+ |> get("/api/v1/media/#{object.id}")
+ |> json_response(403)
+ end
end
end