Browse Source

account visibility

merge-requests/2720/head
Alexander Strizhakov 4 years ago
parent
commit
e7bc2f980c
No known key found for this signature in database GPG Key ID: 22896A53AEF1381
6 changed files with 104 additions and 46 deletions
  1. +32
    -18
      lib/pleroma/user.ex
  2. +6
    -2
      lib/pleroma/web/api_spec/operations/account_operation.ex
  3. +17
    -4
      lib/pleroma/web/mastodon_api/controllers/account_controller.ex
  4. +1
    -1
      lib/pleroma/web/mastodon_api/views/account_view.ex
  5. +5
    -5
      test/user_test.exs
  6. +43
    -16
      test/web/mastodon_api/controllers/account_controller_test.exs

+ 32
- 18
lib/pleroma/user.ex View File

@@ -262,37 +262,51 @@ defmodule Pleroma.User do
def account_status(%User{password_reset_pending: true}), do: :password_reset_pending

def account_status(%User{confirmation_pending: true}) do
case Config.get([:instance, :account_activation_required]) do
true -> :confirmation_pending
_ -> :active
if Config.get([:instance, :account_activation_required]) do
:confirmation_pending
else
:active
end
end

def account_status(%User{}), do: :active

@spec visible_for?(User.t(), User.t() | nil) :: boolean()
def visible_for?(user, for_user \\ nil)
@spec visible_for(User.t(), User.t() | nil) ::
boolean()
| :invisible
| :restricted_unauthenticated
| :deactivated
| :confirmation_pending
def visible_for(user, for_user \\ nil)

def visible_for?(%User{invisible: true}, _), do: false
def visible_for(%User{invisible: true}, _), do: :invisible

def visible_for?(%User{id: user_id}, %User{id: user_id}), do: true
def visible_for(%User{id: user_id}, %User{id: user_id}), do: true

def visible_for?(%User{local: local} = user, nil) do
cfg_key =
if local,
do: :local,
else: :remote
def visible_for(%User{} = user, nil) do
if restrict_unauthenticated?(user) do
:restrict_unauthenticated
else
visible_account_status(user)
end
end

if Config.get([:restrict_unauthenticated, :profiles, cfg_key]),
do: false,
else: account_status(user) == :active
def visible_for(%User{} = user, for_user) do
superuser?(for_user) || visible_account_status(user)
end

def visible_for?(%User{} = user, for_user) do
account_status(user) == :active || superuser?(for_user)
def visible_for(_, _), do: false

defp restrict_unauthenticated?(%User{local: local}) do
config_key = if local, do: :local, else: :remote

Config.get([:restrict_unauthenticated, :profiles, config_key], false)
end

def visible_for?(_, _), do: false
defp visible_account_status(user) do
status = account_status(user)
status in [:active, :password_reset_pending] || status
end

@spec superuser?(User.t()) :: boolean()
def superuser?(%User{local: true, is_admin: true}), do: true


+ 6
- 2
lib/pleroma/web/api_spec/operations/account_operation.ex View File

@@ -102,7 +102,9 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
responses: %{
200 => Operation.response("Account", "application/json", Account),
404 => Operation.response("Error", "application/json", ApiError)
401 => Operation.response("Error", "application/json", ApiError),
404 => Operation.response("Error", "application/json", ApiError),
410 => Operation.response("Error", "application/json", ApiError)
}
}
end
@@ -142,7 +144,9 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
] ++ pagination_params(),
responses: %{
200 => Operation.response("Statuses", "application/json", array_of_statuses()),
404 => Operation.response("Error", "application/json", ApiError)
401 => Operation.response("Error", "application/json", ApiError),
404 => Operation.response("Error", "application/json", ApiError),
410 => Operation.response("Error", "application/json", ApiError)
}
}
end


+ 17
- 4
lib/pleroma/web/mastodon_api/controllers/account_controller.ex View File

@@ -221,17 +221,17 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
@doc "GET /api/v1/accounts/:id"
def show(%{assigns: %{user: for_user}} = conn, %{id: nickname_or_id}) do
with %User{} = user <- User.get_cached_by_nickname_or_id(nickname_or_id, for: for_user),
true <- User.visible_for?(user, for_user) do
true <- User.visible_for(user, for_user) do
render(conn, "show.json", user: user, for: for_user)
else
_e -> render_error(conn, :not_found, "Can't find user")
error -> user_visibility_error(conn, error)
end
end

@doc "GET /api/v1/accounts/:id/statuses"
def statuses(%{assigns: %{user: reading_user}} = conn, params) do
with %User{} = user <- User.get_cached_by_nickname_or_id(params.id, for: reading_user),
true <- User.visible_for?(user, reading_user) do
true <- User.visible_for(user, reading_user) do
params =
params
|> Map.delete(:tagged)
@@ -250,7 +250,20 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
as: :activity
)
else
_e -> render_error(conn, :not_found, "Can't find user")
error -> user_visibility_error(conn, error)
end
end

defp user_visibility_error(conn, error) do
case error do
:deactivated ->
render_error(conn, :gone, "")

:restrict_unauthenticated ->
render_error(conn, :unauthorized, "This API requires an authenticated user")

_ ->
render_error(conn, :not_found, "Can't find user")
end
end



+ 1
- 1
lib/pleroma/web/mastodon_api/views/account_view.ex View File

@@ -35,7 +35,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
end

def render("show.json", %{user: user} = opts) do
if User.visible_for?(user, opts[:for]) do
if User.visible_for(user, opts[:for]) == true do
do_render("show.json", opts)
else
%{}


+ 5
- 5
test/user_test.exs View File

@@ -1289,11 +1289,11 @@ defmodule Pleroma.UserTest do
end
end

describe "visible_for?/2" do
describe "visible_for/2" do
test "returns true when the account is itself" do
user = insert(:user, local: true)

assert User.visible_for?(user, user)
assert User.visible_for(user, user)
end

test "returns false when the account is unauthenticated and auth is required" do
@@ -1302,14 +1302,14 @@ defmodule Pleroma.UserTest do
user = insert(:user, local: true, confirmation_pending: true)
other_user = insert(:user, local: true)

refute User.visible_for?(user, other_user)
refute User.visible_for(user, other_user) == true
end

test "returns true when the account is unauthenticated and auth is not required" do
user = insert(:user, local: true, confirmation_pending: true)
other_user = insert(:user, local: true)

assert User.visible_for?(user, other_user)
assert User.visible_for(user, other_user)
end

test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do
@@ -1318,7 +1318,7 @@ defmodule Pleroma.UserTest do
user = insert(:user, local: true, confirmation_pending: true)
other_user = insert(:user, local: true, is_admin: true)

assert User.visible_for?(user, other_user)
assert User.visible_for(user, other_user)
end
end



+ 43
- 16
test/web/mastodon_api/controllers/account_controller_test.exs View File

@@ -127,6 +127,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> get("/api/v1/accounts/internal.fetch")
|> json_response_and_validate_schema(404)
end

test "returns 401 for deactivated user", %{conn: conn} do
user = insert(:user, deactivated: true)

assert %{} =
conn
|> get("/api/v1/accounts/#{user.id}")
|> json_response_and_validate_schema(:gone)
end
end

defp local_and_remote_users do
@@ -143,15 +152,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
setup do: clear_config([:restrict_unauthenticated, :profiles, :remote], true)

test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
assert %{"error" => "Can't find user"} ==
assert %{"error" => "This API requires an authenticated user"} ==
conn
|> get("/api/v1/accounts/#{local.id}")
|> json_response_and_validate_schema(:not_found)
|> json_response_and_validate_schema(:unauthorized)

assert %{"error" => "Can't find user"} ==
assert %{"error" => "This API requires an authenticated user"} ==
conn
|> get("/api/v1/accounts/#{remote.id}")
|> json_response_and_validate_schema(:not_found)
|> json_response_and_validate_schema(:unauthorized)
end

test "if user is authenticated", %{local: local, remote: remote} do
@@ -173,8 +182,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
res_conn = get(conn, "/api/v1/accounts/#{local.id}")

assert json_response_and_validate_schema(res_conn, :not_found) == %{
"error" => "Can't find user"
assert json_response_and_validate_schema(res_conn, :unauthorized) == %{
"error" => "This API requires an authenticated user"
}

res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
@@ -203,8 +212,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do

res_conn = get(conn, "/api/v1/accounts/#{remote.id}")

assert json_response_and_validate_schema(res_conn, :not_found) == %{
"error" => "Can't find user"
assert json_response_and_validate_schema(res_conn, :unauthorized) == %{
"error" => "This API requires an authenticated user"
}
end

@@ -249,6 +258,24 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
assert id == announce.id
end

test "deactivated user", %{conn: conn} do
user = insert(:user, deactivated: true)

assert %{} ==
conn
|> get("/api/v1/accounts/#{user.id}/statuses")
|> json_response_and_validate_schema(:gone)
end

test "returns 404 when user is invisible", %{conn: conn} do
user = insert(:user, %{invisible: true})

assert %{"error" => "Can't find user"} =
conn
|> get("/api/v1/accounts/#{user.id}")
|> json_response_and_validate_schema(404)
end

test "respects blocks", %{user: user_one, conn: conn} do
user_two = insert(:user)
user_three = insert(:user)
@@ -422,15 +449,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
setup do: clear_config([:restrict_unauthenticated, :profiles, :remote], true)

test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
assert %{"error" => "Can't find user"} ==
assert %{"error" => "This API requires an authenticated user"} ==
conn
|> get("/api/v1/accounts/#{local.id}/statuses")
|> json_response_and_validate_schema(:not_found)
|> json_response_and_validate_schema(:unauthorized)

assert %{"error" => "Can't find user"} ==
assert %{"error" => "This API requires an authenticated user"} ==
conn
|> get("/api/v1/accounts/#{remote.id}/statuses")
|> json_response_and_validate_schema(:not_found)
|> json_response_and_validate_schema(:unauthorized)
end

test "if user is authenticated", %{local: local, remote: remote} do
@@ -451,10 +478,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
setup do: clear_config([:restrict_unauthenticated, :profiles, :local], true)

test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
assert %{"error" => "Can't find user"} ==
assert %{"error" => "This API requires an authenticated user"} ==
conn
|> get("/api/v1/accounts/#{local.id}/statuses")
|> json_response_and_validate_schema(:not_found)
|> json_response_and_validate_schema(:unauthorized)

res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
assert length(json_response_and_validate_schema(res_conn, 200)) == 1
@@ -481,10 +508,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
assert length(json_response_and_validate_schema(res_conn, 200)) == 1

assert %{"error" => "Can't find user"} ==
assert %{"error" => "This API requires an authenticated user"} ==
conn
|> get("/api/v1/accounts/#{remote.id}/statuses")
|> json_response_and_validate_schema(:not_found)
|> json_response_and_validate_schema(:unauthorized)
end

test "if user is authenticated", %{local: local, remote: remote} do


Loading…
Cancel
Save