Add restricted access check to API v2

pull/6544/head
Никита Поздняков 2 years ago
parent 5b30b3ce99
commit a5bd6b82d7
No known key found for this signature in database
GPG Key ID: F344106F9804FE5F
  1. 36
      apps/block_scout_web/lib/block_scout_web/controllers/api/v2/address_controller.ex
  2. 7
      apps/block_scout_web/lib/block_scout_web/controllers/api/v2/fallback_controller.ex
  3. 11
      apps/block_scout_web/lib/block_scout_web/controllers/api/v2/token_controller.ex
  4. 29
      apps/block_scout_web/lib/block_scout_web/controllers/api/v2/transaction_controller.ex
  5. 18
      apps/block_scout_web/test/block_scout_web/controllers/api/v2/transaction_controller_test.exs

@ -12,6 +12,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
import BlockScoutWeb.PagingHelper,
only: [delete_parameters_from_next_page_params: 1, token_transfers_types_options: 1]
alias BlockScoutWeb.AccessHelpers
alias BlockScoutWeb.API.V2.{AddressView, BlockView, TransactionView}
alias Explorer.{Chain, Market}
alias Indexer.Fetcher.TokenBalanceOnDemand
@ -38,8 +39,9 @@ defmodule BlockScoutWeb.API.V2.AddressController do
action_fallback(BlockScoutWeb.API.V2.FallbackController)
def address(conn, %{"address_hash" => address_hash_string}) do
def address(conn, %{"address_hash" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params),
{:not_found, {:ok, address}} <- {:not_found, Chain.hash_to_address(address_hash)} do
conn
|> put_status(200)
@ -47,8 +49,9 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
end
def counters(conn, %{"address_hash" => address_hash_string}) do
def counters(conn, %{"address_hash" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params),
{:not_found, {:ok, address}} <- {:not_found, Chain.hash_to_address(address_hash)} do
{validation_count} = Chain.address_counters(address)
@ -65,8 +68,9 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
end
def token_balances(conn, %{"address_hash" => address_hash_string}) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)} do
def token_balances(conn, %{"address_hash" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do
token_balances =
address_hash
|> Chain.fetch_last_token_balances()
@ -86,7 +90,8 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
def transactions(conn, %{"address_hash" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)} do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do
options =
@transaction_necessity_by_association
|> Keyword.merge(paging_options(params))
@ -106,7 +111,8 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
def token_transfers(conn, %{"address_hash" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)} do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do
options =
@token_transfer_necessity_by_association
|> Keyword.merge(paging_options(params))
@ -132,7 +138,8 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
def internal_transactions(conn, %{"address_hash" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)} do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do
full_options =
[
necessity_by_association: %{
@ -164,7 +171,8 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
def logs(conn, %{"address_hash" => address_hash_string, "topic" => topic} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)} do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do
prepared_topic = String.trim(topic)
formatted_topic = if String.starts_with?(prepared_topic, "0x"), do: prepared_topic, else: "0x" <> prepared_topic
@ -183,7 +191,8 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
def logs(conn, %{"address_hash" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)} do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do
results_plus_one = Chain.address_to_logs(address_hash, paging_options(params))
{logs, next_page} = split_list_by_page(results_plus_one)
@ -197,7 +206,8 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
def blocks_validated(conn, %{"address_hash" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)} do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do
full_options =
Keyword.merge(
[
@ -225,6 +235,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
def coin_balance_history(conn, %{"address_hash" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params),
{:not_found, {:ok, _address}, _} <-
{:not_found, Chain.hash_to_address(address_hash), :empty_items_with_next_page_params} do
full_options = paging_options(params)
@ -243,8 +254,9 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
end
def coin_balance_history_by_day(conn, %{"address_hash" => address_hash_string}) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)} do
def coin_balance_history_by_day(conn, %{"address_hash" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do
balances_by_day =
address_hash
|> Chain.address_to_balances_by_day(true)

@ -40,4 +40,11 @@ defmodule BlockScoutWeb.API.V2.FallbackController do
conn
|> call({:not_found, nil})
end
def call(conn, {:restricted_access, true}) do
conn
|> put_status(:forbidden)
|> put_view(ApiView)
|> render(:message, %{message: "Restricted access"})
end
end

@ -1,6 +1,7 @@
defmodule BlockScoutWeb.API.V2.TokenController do
use BlockScoutWeb, :controller
alias BlockScoutWeb.AccessHelpers
alias BlockScoutWeb.API.V2.TransactionView
alias Explorer.Chain
@ -9,8 +10,9 @@ defmodule BlockScoutWeb.API.V2.TokenController do
action_fallback(BlockScoutWeb.API.V2.FallbackController)
def token(conn, %{"address_hash" => address_hash_string}) do
def token(conn, %{"address_hash" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params),
{:not_found, {:ok, token}} <- {:not_found, Chain.token_from_address_hash(address_hash)} do
conn
|> put_status(200)
@ -18,8 +20,9 @@ defmodule BlockScoutWeb.API.V2.TokenController do
end
end
def counters(conn, %{"address_hash" => address_hash_string}) do
def counters(conn, %{"address_hash" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params),
{:not_found, {:ok, _}} <- {:not_found, Chain.token_from_address_hash(address_hash)} do
{transfer_count, token_holder_count} = Chain.fetch_token_counters(address_hash, 30_000)
@ -28,7 +31,8 @@ defmodule BlockScoutWeb.API.V2.TokenController do
end
def transfers(conn, %{"address_hash" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)} do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do
results_plus_one = Chain.fetch_token_transfers_from_token_hash(address_hash, paging_options(params))
{token_transfers, next_page} = split_list_by_page(results_plus_one)
@ -47,6 +51,7 @@ defmodule BlockScoutWeb.API.V2.TokenController do
from_api = true
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params),
{:not_found, {:ok, token}, _} <-
{:not_found, Chain.token_from_address_hash(address_hash), :empty_items_with_next_page_params} do
results_plus_one = Chain.fetch_token_holders_from_token_hash(address_hash, from_api, paging_options(params))

@ -13,6 +13,7 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
type_filter_options: 1
]
alias BlockScoutWeb.AccessHelpers
alias Explorer.Chain
alias Explorer.Chain.Import
alias Explorer.Chain.Import.Runner.InternalTransactions
@ -59,7 +60,7 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
}
]
def transaction(conn, %{"transaction_hash" => transaction_hash_string}) do
def transaction(conn, %{"transaction_hash" => transaction_hash_string} = params) do
with {:format, {:ok, transaction_hash}} <- {:format, Chain.string_to_transaction_hash(transaction_hash_string)},
{:not_found, {:ok, transaction}} <-
{:not_found,
@ -67,6 +68,8 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
transaction_hash,
necessity_by_association: @transaction_necessity_by_association
)},
{:ok, false} <- AccessHelpers.restricted_access?(to_string(transaction.from_address_hash), params),
{:ok, false} <- AccessHelpers.restricted_access?(to_string(transaction.to_address_hash), params),
preloaded <-
Chain.preload_token_transfers(transaction, @token_transfers_in_tx_neccessity_by_association, false) do
conn
@ -97,10 +100,12 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
|> render(:transactions, %{transactions: transactions, next_page_params: next_page_params})
end
def raw_trace(conn, %{"transaction_hash" => transaction_hash_string}) do
def raw_trace(conn, %{"transaction_hash" => transaction_hash_string} = params) do
with {:format, {:ok, transaction_hash}} <- {:format, Chain.string_to_transaction_hash(transaction_hash_string)},
{:not_found, {:ok, transaction}} <-
{:not_found, Chain.hash_to_transaction(transaction_hash)} do
{:not_found, Chain.hash_to_transaction(transaction_hash)},
{:ok, false} <- AccessHelpers.restricted_access?(to_string(transaction.from_address_hash), params),
{:ok, false} <- AccessHelpers.restricted_access?(to_string(transaction.to_address_hash), params) do
if is_nil(transaction.block_number) do
conn
|> put_status(200)
@ -158,7 +163,11 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
end
def token_transfers(conn, %{"transaction_hash" => transaction_hash_string} = params) do
with {:format, {:ok, transaction_hash}} <- {:format, Chain.string_to_transaction_hash(transaction_hash_string)} do
with {:format, {:ok, transaction_hash}} <- {:format, Chain.string_to_transaction_hash(transaction_hash_string)},
{:not_found, {:ok, transaction}} <-
{:not_found, Chain.hash_to_transaction(transaction_hash)},
{:ok, false} <- AccessHelpers.restricted_access?(to_string(transaction.from_address_hash), params),
{:ok, false} <- AccessHelpers.restricted_access?(to_string(transaction.to_address_hash), params) do
full_options =
[necessity_by_association: @token_transfers_neccessity_by_association]
|> Keyword.merge(paging_options(params))
@ -180,7 +189,11 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
end
def internal_transactions(conn, %{"transaction_hash" => transaction_hash_string} = params) do
with {:format, {:ok, transaction_hash}} <- {:format, Chain.string_to_transaction_hash(transaction_hash_string)} do
with {:format, {:ok, transaction_hash}} <- {:format, Chain.string_to_transaction_hash(transaction_hash_string)},
{:not_found, {:ok, transaction}} <-
{:not_found, Chain.hash_to_transaction(transaction_hash)},
{:ok, false} <- AccessHelpers.restricted_access?(to_string(transaction.from_address_hash), params),
{:ok, false} <- AccessHelpers.restricted_access?(to_string(transaction.to_address_hash), params) do
full_options =
Keyword.merge(
@internal_transaction_neccessity_by_association,
@ -206,7 +219,11 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
end
def logs(conn, %{"transaction_hash" => transaction_hash_string} = params) do
with {:format, {:ok, transaction_hash}} <- {:format, Chain.string_to_transaction_hash(transaction_hash_string)} do
with {:format, {:ok, transaction_hash}} <- {:format, Chain.string_to_transaction_hash(transaction_hash_string)},
{:not_found, {:ok, transaction}} <-
{:not_found, Chain.hash_to_transaction(transaction_hash)},
{:ok, false} <- AccessHelpers.restricted_access?(to_string(transaction.from_address_hash), params),
{:ok, false} <- AccessHelpers.restricted_access?(to_string(transaction.to_address_hash), params) do
full_options =
Keyword.merge(
[

@ -117,13 +117,11 @@ defmodule BlockScoutWeb.API.V2.TransactionControllerTest do
end
describe "/transactions/{tx_hash}/internal-transactions" do
test "return empty list on non existing tx", %{conn: conn} do
test "return 404 on non existing tx", %{conn: conn} do
tx = build(:transaction)
request = get(conn, "/api/v2/transactions/#{to_string(tx.hash)}/internal-transactions")
assert response = json_response(request, 200)
assert response["items"] == []
assert response["next_page_params"] == nil
assert %{"message" => "Not found"} = json_response(request, 404)
end
test "return 422 on invalid tx hash", %{conn: conn} do
@ -236,13 +234,11 @@ defmodule BlockScoutWeb.API.V2.TransactionControllerTest do
end
describe "/transactions/{tx_hash}/logs" do
test "return empty list on non existing tx", %{conn: conn} do
test "return 404 on non existing tx", %{conn: conn} do
tx = build(:transaction)
request = get(conn, "/api/v2/transactions/#{to_string(tx.hash)}/logs")
assert response = json_response(request, 200)
assert response["items"] == []
assert response["next_page_params"] == nil
assert %{"message" => "Not found"} = json_response(request, 404)
end
test "return 422 on invalid tx hash", %{conn: conn} do
@ -330,13 +326,11 @@ defmodule BlockScoutWeb.API.V2.TransactionControllerTest do
end
describe "/transactions/{tx_hash}/token-transfers" do
test "return empty list on non existing tx", %{conn: conn} do
test "return 404 on non existing tx", %{conn: conn} do
tx = build(:transaction)
request = get(conn, "/api/v2/transactions/#{to_string(tx.hash)}/token-transfers")
assert response = json_response(request, 200)
assert response["items"] == []
assert response["next_page_params"] == nil
assert %{"message" => "Not found"} = json_response(request, 404)
end
test "return 422 on invalid tx hash", %{conn: conn} do

Loading…
Cancel
Save