diff --git a/CHANGELOG.md b/CHANGELOG.md index fb6148b775..cbb80b9473 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Current ### Features +- [#3311](https://github.com/poanetwork/blockscout/pull/3311) - List of addresses with restricted access option - [#3293](https://github.com/poanetwork/blockscout/pull/3293) - Composite market cap for xDai: TokenBridge + OmniBridge - [#3282](https://github.com/poanetwork/blockscout/pull/3282) - Import bridged tokens custom metadata - [#3281](https://github.com/poanetwork/blockscout/pull/3281) - Write contract: display currently connected address diff --git a/apps/block_scout_web/config/config.exs b/apps/block_scout_web/config/config.exs index 34289b2cb6..f5d6feb38a 100644 --- a/apps/block_scout_web/config/config.exs +++ b/apps/block_scout_web/config/config.exs @@ -37,7 +37,9 @@ config :block_scout_web, external_apps: System.get_env("EXTERNAL_APPS"), multi_token_bridge_mediator: System.get_env("MULTI_TOKEN_BRIDGE_MEDIATOR"), foreign_json_rpc: System.get_env("FOREIGN_JSON_RPC"), - gas_price: System.get_env("GAS_PRICE", nil) + gas_price: System.get_env("GAS_PRICE", nil), + restricted_list: System.get_env("RESTRICTED_LIST", nil), + restricted_list_key: System.get_env("RESTRICTED_LIST_KEY", nil) config :block_scout_web, BlockScoutWeb.Counters.BlocksIndexedCounter, enabled: true diff --git a/apps/block_scout_web/lib/block_scout_web/channels/address_channel.ex b/apps/block_scout_web/lib/block_scout_web/channels/address_channel.ex index cdadd54143..88b51ae7a1 100644 --- a/apps/block_scout_web/lib/block_scout_web/channels/address_channel.ex +++ b/apps/block_scout_web/lib/block_scout_web/channels/address_channel.ex @@ -39,7 +39,7 @@ defmodule BlockScoutWeb.AddressChannel do {:ok, address = %{fetched_coin_balance: balance}} when not is_nil(balance) <- Chain.hash_to_address(casted_address_hash), exchange_rate <- Market.get_exchange_rate(Explorer.coin()) || Token.null(), - {:ok, rendered} <- render_balance_card(address, exchange_rate, socket.assigns.locale) do + {:ok, rendered} <- render_balance_card(address, exchange_rate, socket) do reply = {:ok, %{ @@ -60,7 +60,7 @@ defmodule BlockScoutWeb.AddressChannel do %{address: address, exchange_rate: exchange_rate}, socket ) do - case render_balance_card(address, exchange_rate, socket.assigns.locale) do + case render_balance_card(address, exchange_rate, socket) do {:ok, rendered} -> push(socket, "balance", %{ balance_card: rendered, @@ -190,14 +190,15 @@ defmodule BlockScoutWeb.AddressChannel do {:noreply, socket} end - defp render_balance_card(address, exchange_rate, locale) do - Gettext.put_locale(BlockScoutWeb.Gettext, locale) + defp render_balance_card(address, exchange_rate, socket) do + Gettext.put_locale(BlockScoutWeb.Gettext, socket.assigns.locale) try do rendered = View.render_to_string( AddressView, "_balance_card.html", + conn: socket, address: address, coin_balance_status: :current, exchange_rate: exchange_rate diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_coin_balance_by_day_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_coin_balance_by_day_controller.ex index b440fc7d9f..030f80a88d 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_coin_balance_by_day_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_coin_balance_by_day_controller.ex @@ -5,10 +5,12 @@ defmodule BlockScoutWeb.AddressCoinBalanceByDayController do use BlockScoutWeb, :controller + alias BlockScoutWeb.AccessHelpers alias Explorer.Chain - def index(conn, %{"address_id" => address_hash_string, "type" => "JSON"}) do - with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string) do + def index(conn, %{"address_id" => address_hash_string, "type" => "JSON"} = params) do + with {:ok, address_hash} <- 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() @@ -17,6 +19,9 @@ defmodule BlockScoutWeb.AddressCoinBalanceByDayController do end) json(conn, balances_by_day) + else + _ -> + not_found(conn) end end end diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_coin_balance_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_coin_balance_controller.ex index 538f8fd7f4..8c90d51ada 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_coin_balance_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_coin_balance_controller.ex @@ -7,7 +7,7 @@ defmodule BlockScoutWeb.AddressCoinBalanceController do import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1] - alias BlockScoutWeb.AddressCoinBalanceView + alias BlockScoutWeb.{AccessHelpers, AddressCoinBalanceView} alias Explorer.{Chain, Market} alias Explorer.Chain.Address alias Explorer.ExchangeRates.Token @@ -16,7 +16,8 @@ defmodule BlockScoutWeb.AddressCoinBalanceController do def index(conn, %{"address_id" => address_hash_string, "type" => "JSON"} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - :ok <- Chain.check_address_exists(address_hash) do + :ok <- Chain.check_address_exists(address_hash), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do full_options = paging_options(params) coin_balances_plus_one = Chain.address_to_coin_balances(address_hash, full_options) @@ -49,6 +50,9 @@ defmodule BlockScoutWeb.AddressCoinBalanceController do json(conn, %{items: coin_balances_json, next_page_path: next_page_url}) else + {:restricted_access, _} -> + not_found(conn) + :error -> unprocessable_entity(conn) @@ -57,9 +61,10 @@ defmodule BlockScoutWeb.AddressCoinBalanceController do end end - def index(conn, %{"address_id" => address_hash_string}) do + def index(conn, %{"address_id" => address_hash_string} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - {:ok, address} <- Chain.hash_to_address(address_hash) do + {:ok, address} <- Chain.hash_to_address(address_hash), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do render(conn, "index.html", address: address, coin_balance_status: CoinBalanceOnDemand.trigger_fetch(address), @@ -68,6 +73,9 @@ defmodule BlockScoutWeb.AddressCoinBalanceController do counters_path: address_path(conn, :address_counters, %{"id" => Address.checksum(address_hash)}) ) else + {:restricted_access, _} -> + not_found(conn) + :error -> unprocessable_entity(conn) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex index fcc01d9de0..ab4b8e63de 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex @@ -2,11 +2,12 @@ defmodule BlockScoutWeb.AddressContractController do use BlockScoutWeb, :controller + alias BlockScoutWeb.AccessHelpers alias Explorer.{Chain, Market} alias Explorer.ExchangeRates.Token alias Indexer.Fetcher.CoinBalanceOnDemand - def index(conn, %{"address_id" => address_hash_string}) do + def index(conn, %{"address_id" => address_hash_string} = params) do address_options = [ necessity_by_association: %{ :contracts_creation_internal_transaction => :optional, @@ -18,7 +19,8 @@ defmodule BlockScoutWeb.AddressContractController do ] with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - {:ok, address} <- Chain.find_contract_address(address_hash, address_options, true) do + {:ok, address} <- Chain.find_contract_address(address_hash, address_options, true), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do render( conn, "index.html", @@ -28,6 +30,9 @@ defmodule BlockScoutWeb.AddressContractController do counters_path: address_path(conn, :address_counters, %{"id" => address_hash_string}) ) else + {:restricted_access, _} -> + not_found(conn) + :error -> not_found(conn) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex index 212ee668e5..62587223ac 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex @@ -3,7 +3,7 @@ defmodule BlockScoutWeb.AddressController do import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1] - alias BlockScoutWeb.AddressView + alias BlockScoutWeb.{AccessHelpers, AddressView} alias Explorer.{Chain, Market} alias Explorer.ExchangeRates.Token alias Phoenix.View @@ -67,7 +67,7 @@ defmodule BlockScoutWeb.AddressController do end def show(conn, %{"id" => id}) do - redirect(conn, to: address_transaction_path(conn, :index, id)) + redirect(conn, to: AccessHelpers.get_path(conn, :address_transaction_path, :index, id)) end def address_counters(conn, %{"id" => address_hash_string}) do diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_decompiled_contract_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_decompiled_contract_controller.ex index 2a62020a4f..079d5d9093 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_decompiled_contract_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_decompiled_contract_controller.ex @@ -1,13 +1,15 @@ defmodule BlockScoutWeb.AddressDecompiledContractController do use BlockScoutWeb, :controller + alias BlockScoutWeb.AccessHelpers alias Explorer.{Chain, Market} alias Explorer.ExchangeRates.Token alias Indexer.Fetcher.CoinBalanceOnDemand - def index(conn, %{"address_id" => address_hash_string}) do + def index(conn, %{"address_id" => address_hash_string} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - {:ok, address} <- Chain.find_decompiled_contract_address(address_hash) do + {:ok, address} <- Chain.find_decompiled_contract_address(address_hash), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do render( conn, "index.html", @@ -17,6 +19,9 @@ defmodule BlockScoutWeb.AddressDecompiledContractController do counters_path: address_path(conn, :address_counters, %{"id" => address_hash_string}) ) else + {:restricted_access, _} -> + not_found(conn) + :error -> not_found(conn) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_internal_transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_internal_transaction_controller.ex index 76e5518705..509a83d98b 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_internal_transaction_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_internal_transaction_controller.ex @@ -7,7 +7,7 @@ defmodule BlockScoutWeb.AddressInternalTransactionController do import BlockScoutWeb.Chain, only: [current_filter: 1, paging_options: 1, next_page_params: 3, split_list_by_page: 1] - alias BlockScoutWeb.InternalTransactionView + alias BlockScoutWeb.{AccessHelpers, InternalTransactionView} alias Explorer.{Chain, Market} alias Explorer.ExchangeRates.Token alias Indexer.Fetcher.CoinBalanceOnDemand @@ -15,7 +15,8 @@ defmodule BlockScoutWeb.AddressInternalTransactionController do def index(conn, %{"address_id" => address_hash_string, "type" => "JSON"} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - {:ok, address} <- Chain.hash_to_address(address_hash, [], false) do + {:ok, address} <- Chain.hash_to_address(address_hash, [], false), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do full_options = [ necessity_by_association: %{ @@ -51,6 +52,9 @@ defmodule BlockScoutWeb.AddressInternalTransactionController do json(conn, %{items: internal_transactions_json, next_page_path: next_page_path}) else + {:restricted_access, _} -> + not_found(conn) + :error -> not_found(conn) @@ -61,7 +65,8 @@ defmodule BlockScoutWeb.AddressInternalTransactionController do def index(conn, %{"address_id" => address_hash_string} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - {:ok, address} <- Chain.hash_to_address(address_hash) do + {:ok, address} <- Chain.hash_to_address(address_hash), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do render( conn, "index.html", @@ -73,6 +78,9 @@ defmodule BlockScoutWeb.AddressInternalTransactionController do counters_path: address_path(conn, :address_counters, %{"id" => address_hash_string}) ) else + {:restricted_access, _} -> + not_found(conn) + :error -> not_found(conn) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_logs_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_logs_controller.ex index 2d0c7f342b..51cdf785c3 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_logs_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_logs_controller.ex @@ -5,7 +5,7 @@ defmodule BlockScoutWeb.AddressLogsController do import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1] - alias BlockScoutWeb.AddressLogsView + alias BlockScoutWeb.{AccessHelpers, AddressLogsView} alias Explorer.{Chain, Market} alias Explorer.ExchangeRates.Token alias Indexer.Fetcher.CoinBalanceOnDemand @@ -15,7 +15,8 @@ defmodule BlockScoutWeb.AddressLogsController do def index(conn, %{"address_id" => address_hash_string, "type" => "JSON"} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - :ok <- Chain.check_address_exists(address_hash) do + :ok <- Chain.check_address_exists(address_hash), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do logs_plus_one = Chain.address_to_logs(address_hash, paging_options(params)) {results, next_page} = split_list_by_page(logs_plus_one) @@ -52,9 +53,10 @@ defmodule BlockScoutWeb.AddressLogsController do end end - def index(conn, %{"address_id" => address_hash_string}) do + def index(conn, %{"address_id" => address_hash_string} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - {:ok, address} <- Chain.hash_to_address(address_hash) do + {:ok, address} <- Chain.hash_to_address(address_hash), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do render( conn, "index.html", diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_read_contract_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_read_contract_controller.ex index 4523fbb068..4734b8f0f3 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_read_contract_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_read_contract_controller.ex @@ -8,12 +8,13 @@ defmodule BlockScoutWeb.AddressReadContractController do use BlockScoutWeb, :controller + alias BlockScoutWeb.AccessHelpers alias Explorer.{Chain, Market} alias Explorer.Chain.Address alias Explorer.ExchangeRates.Token alias Indexer.Fetcher.CoinBalanceOnDemand - def index(conn, %{"address_id" => address_hash_string}) do + def index(conn, %{"address_id" => address_hash_string} = params) do address_options = [ necessity_by_association: %{ :contracts_creation_internal_transaction => :optional, @@ -26,7 +27,8 @@ defmodule BlockScoutWeb.AddressReadContractController do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), {:ok, address} <- Chain.find_contract_address(address_hash, address_options, true), - false <- is_nil(address.smart_contract) do + false <- is_nil(address.smart_contract), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do render( conn, "index.html", diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_read_proxy_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_read_proxy_controller.ex index 2429a8a04e..7ed05ef4b4 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_read_proxy_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_read_proxy_controller.ex @@ -2,12 +2,13 @@ defmodule BlockScoutWeb.AddressReadProxyController do use BlockScoutWeb, :controller + alias BlockScoutWeb.AccessHelpers alias Explorer.{Chain, Market} alias Explorer.Chain.Address alias Explorer.ExchangeRates.Token alias Indexer.Fetcher.CoinBalanceOnDemand - def index(conn, %{"address_id" => address_hash_string}) do + def index(conn, %{"address_id" => address_hash_string} = params) do address_options = [ necessity_by_association: %{ :contracts_creation_internal_transaction => :optional, @@ -20,7 +21,8 @@ defmodule BlockScoutWeb.AddressReadProxyController do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), {:ok, address} <- Chain.find_contract_address(address_hash, address_options, true), - false <- is_nil(address.smart_contract) do + false <- is_nil(address.smart_contract), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do render( conn, "index.html", diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_token_balance_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_token_balance_controller.ex index 817a39d1c0..9a0e4809e9 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_token_balance_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_token_balance_controller.ex @@ -1,11 +1,13 @@ defmodule BlockScoutWeb.AddressTokenBalanceController do use BlockScoutWeb, :controller + alias BlockScoutWeb.AccessHelpers alias Explorer.{Chain, Market} - def index(conn, %{"address_id" => address_hash_string}) do + def index(conn, %{"address_id" => address_hash_string} = params) do with true <- ajax?(conn), - {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string) do + {:ok, address_hash} <- 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() diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_token_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_token_controller.ex index b7a445f67b..226130ed1d 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_token_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_token_controller.ex @@ -3,7 +3,7 @@ defmodule BlockScoutWeb.AddressTokenController do import BlockScoutWeb.Chain, only: [next_page_params: 3, paging_options: 1, split_list_by_page: 1] - alias BlockScoutWeb.AddressTokenView + alias BlockScoutWeb.{AccessHelpers, AddressTokenView} alias Explorer.{Chain, Market} alias Explorer.Chain.Address alias Explorer.ExchangeRates.Token @@ -12,7 +12,8 @@ defmodule BlockScoutWeb.AddressTokenController do def index(conn, %{"address_id" => address_hash_string, "type" => "JSON"} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - {:ok, address} <- Chain.hash_to_address(address_hash, [], false) do + {:ok, address} <- Chain.hash_to_address(address_hash, [], false), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do tokens_plus_one = Chain.address_tokens_with_balance(address_hash, paging_options(params)) {tokens, next_page} = split_list_by_page(tokens_plus_one) @@ -46,6 +47,9 @@ defmodule BlockScoutWeb.AddressTokenController do } ) else + {:restricted_access, _} -> + not_found(conn) + :error -> unprocessable_entity(conn) @@ -54,9 +58,10 @@ defmodule BlockScoutWeb.AddressTokenController do end end - def index(conn, %{"address_id" => address_hash_string} = _params) do + def index(conn, %{"address_id" => address_hash_string} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - {:ok, address} <- Chain.hash_to_address(address_hash) do + {:ok, address} <- Chain.hash_to_address(address_hash), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do render( conn, "index.html", @@ -67,6 +72,9 @@ defmodule BlockScoutWeb.AddressTokenController do counters_path: address_path(conn, :address_counters, %{"id" => Address.checksum(address_hash)}) ) else + {:restricted_access, _} -> + not_found(conn) + :error -> unprocessable_entity(conn) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_token_transfer_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_token_transfer_controller.ex index 4af79088b0..d0449fd53e 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_token_transfer_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_token_transfer_controller.ex @@ -1,7 +1,7 @@ defmodule BlockScoutWeb.AddressTokenTransferController do use BlockScoutWeb, :controller - alias BlockScoutWeb.TransactionView + alias BlockScoutWeb.{AccessHelpers, TransactionView} alias Explorer.ExchangeRates.Token alias Explorer.{Chain, Market} alias Explorer.Chain.Address @@ -38,7 +38,8 @@ defmodule BlockScoutWeb.AddressTokenTransferController do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), {:ok, token_hash} <- Chain.string_to_address_hash(token_hash_string), {:ok, address} <- Chain.hash_to_address(address_hash), - {:ok, _} <- Chain.token_from_address_hash(token_hash) do + {:ok, _} <- Chain.token_from_address_hash(token_hash), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do transactions = Chain.address_to_transactions_with_token_transfers( address_hash, @@ -77,6 +78,9 @@ defmodule BlockScoutWeb.AddressTokenTransferController do json(conn, %{items: transfers_json, next_page_path: next_page_path}) else + {:restricted_access, _} -> + not_found(conn) + :error -> unprocessable_entity(conn) @@ -87,12 +91,13 @@ defmodule BlockScoutWeb.AddressTokenTransferController do def index( conn, - %{"address_id" => address_hash_string, "address_token_id" => token_hash_string} + %{"address_id" => address_hash_string, "address_token_id" => token_hash_string} = params ) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), {:ok, token_hash} <- Chain.string_to_address_hash(token_hash_string), {:ok, address} <- Chain.hash_to_address(address_hash), - {:ok, token} <- Chain.token_from_address_hash(token_hash) do + {:ok, token} <- Chain.token_from_address_hash(token_hash), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do render( conn, "index.html", @@ -104,6 +109,9 @@ defmodule BlockScoutWeb.AddressTokenTransferController do counters_path: address_path(conn, :address_counters, %{"id" => Address.checksum(address_hash)}) ) else + {:restricted_access, _} -> + not_found(conn) + :error -> unprocessable_entity(conn) @@ -120,7 +128,8 @@ defmodule BlockScoutWeb.AddressTokenTransferController do } = params ) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - {:ok, address} <- Chain.hash_to_address(address_hash) do + {:ok, address} <- Chain.hash_to_address(address_hash), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do options = @transaction_necessity_by_association |> Keyword.merge(paging_options(params)) @@ -162,6 +171,9 @@ defmodule BlockScoutWeb.AddressTokenTransferController do json(conn, %{items: transfers_json, next_page_path: next_page_path}) else + {:restricted_access, _} -> + not_found(conn) + :error -> unprocessable_entity(conn) @@ -175,7 +187,8 @@ defmodule BlockScoutWeb.AddressTokenTransferController do %{"address_id" => address_hash_string} = params ) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - {:ok, address} <- Chain.hash_to_address(address_hash) do + {:ok, address} <- Chain.hash_to_address(address_hash), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do render( conn, "index.html", @@ -187,6 +200,9 @@ defmodule BlockScoutWeb.AddressTokenTransferController do counters_path: address_path(conn, :address_counters, %{"id" => Address.checksum(address_hash)}) ) else + {:restricted_access, _} -> + not_found(conn) + :error -> unprocessable_entity(conn) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex index f4ede21255..f35d3b508b 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex @@ -7,7 +7,7 @@ defmodule BlockScoutWeb.AddressTransactionController do import BlockScoutWeb.Chain, only: [current_filter: 1, paging_options: 1, next_page_params: 3, split_list_by_page: 1] - alias BlockScoutWeb.TransactionView + alias BlockScoutWeb.{AccessHelpers, TransactionView} alias Explorer.{Chain, Market} alias Explorer.Chain.{AddressTokenTransferCsvExporter, AddressTransactionCsvExporter} alias Explorer.ExchangeRates.Token @@ -30,7 +30,8 @@ defmodule BlockScoutWeb.AddressTransactionController do address_options = [necessity_by_association: %{:names => :optional}] with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - {:ok, address} <- Chain.hash_to_address(address_hash, address_options, false) do + {:ok, address} <- Chain.hash_to_address(address_hash, address_options, false), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do options = @transaction_necessity_by_association |> Keyword.merge(paging_options(params)) @@ -82,6 +83,9 @@ defmodule BlockScoutWeb.AddressTransactionController do :error -> unprocessable_entity(conn) + {:restricted_access, _} -> + not_found(conn) + {:error, :not_found} -> case Chain.Hash.Address.validate(address_hash_string) do {:ok, _} -> @@ -95,7 +99,8 @@ defmodule BlockScoutWeb.AddressTransactionController do def index(conn, %{"address_id" => address_hash_string} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - {:ok, address} <- Chain.hash_to_address(address_hash) do + {:ok, address} <- Chain.hash_to_address(address_hash), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do render( conn, "index.html", @@ -110,6 +115,9 @@ defmodule BlockScoutWeb.AddressTransactionController do :error -> unprocessable_entity(conn) + {:restricted_access, _} -> + not_found(conn) + {:error, :not_found} -> {:ok, address_hash} = Chain.string_to_address_hash(address_hash_string) address = %Chain.Address{hash: address_hash, smart_contract: nil, token: nil} diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_validation_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_validation_controller.ex index 3074471ddf..cf4a5742da 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_validation_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_validation_controller.ex @@ -7,7 +7,7 @@ defmodule BlockScoutWeb.AddressValidationController do import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1] - alias BlockScoutWeb.BlockView + alias BlockScoutWeb.{AccessHelpers, BlockView} alias Explorer.ExchangeRates.Token alias Explorer.{Chain, Market} alias Indexer.Fetcher.CoinBalanceOnDemand @@ -15,7 +15,8 @@ defmodule BlockScoutWeb.AddressValidationController do def index(conn, %{"address_id" => address_hash_string, "type" => "JSON"} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - {:ok, _} <- Chain.find_or_insert_address_from_hash(address_hash, [], false) do + {:ok, _} <- Chain.find_or_insert_address_from_hash(address_hash, [], false), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do full_options = Keyword.merge( [ @@ -59,14 +60,18 @@ defmodule BlockScoutWeb.AddressValidationController do json(conn, %{items: items, next_page_path: next_page_path}) else + {:restricted_access, _} -> + not_found(conn) + :error -> unprocessable_entity(conn) end end - def index(conn, %{"address_id" => address_hash_string}) do + def index(conn, %{"address_id" => address_hash_string} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - {:ok, address} <- Chain.find_or_insert_address_from_hash(address_hash) do + {:ok, address} <- Chain.find_or_insert_address_from_hash(address_hash), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do render( conn, "index.html", @@ -77,6 +82,9 @@ defmodule BlockScoutWeb.AddressValidationController do exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null() ) else + {:restricted_access, _} -> + not_found(conn) + :error -> unprocessable_entity(conn) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_write_contract_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_write_contract_controller.ex index c066914f46..f3b50dd4a2 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_write_contract_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_write_contract_controller.ex @@ -8,12 +8,13 @@ defmodule BlockScoutWeb.AddressWriteContractController do use BlockScoutWeb, :controller + alias BlockScoutWeb.AccessHelpers alias Explorer.{Chain, Market} alias Explorer.Chain.Address alias Explorer.ExchangeRates.Token alias Indexer.Fetcher.CoinBalanceOnDemand - def index(conn, %{"address_id" => address_hash_string}) do + def index(conn, %{"address_id" => address_hash_string} = params) do address_options = [ necessity_by_association: %{ :contracts_creation_internal_transaction => :optional, @@ -26,7 +27,8 @@ defmodule BlockScoutWeb.AddressWriteContractController do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), {:ok, address} <- Chain.find_contract_address(address_hash, address_options, true), - false <- is_nil(address.smart_contract) do + false <- is_nil(address.smart_contract), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do render( conn, "index.html", diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_write_proxy_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_write_proxy_controller.ex index 1e558f7bbb..e82fc17c29 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_write_proxy_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_write_proxy_controller.ex @@ -2,12 +2,13 @@ defmodule BlockScoutWeb.AddressWriteProxyController do use BlockScoutWeb, :controller + alias BlockScoutWeb.AccessHelpers alias Explorer.{Chain, Market} alias Explorer.Chain.Address alias Explorer.ExchangeRates.Token alias Indexer.Fetcher.CoinBalanceOnDemand - def index(conn, %{"address_id" => address_hash_string}) do + def index(conn, %{"address_id" => address_hash_string} = params) do address_options = [ necessity_by_association: %{ :contracts_creation_internal_transaction => :optional, @@ -20,7 +21,8 @@ defmodule BlockScoutWeb.AddressWriteProxyController do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), {:ok, address} <- Chain.find_contract_address(address_hash, address_options, true), - false <- is_nil(address.smart_contract) do + false <- is_nil(address.smart_contract), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do render( conn, "index.html", diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/holder_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/holder_controller.ex index 078aac9e56..e12d14cb77 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/holder_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/holder_controller.ex @@ -1,6 +1,7 @@ defmodule BlockScoutWeb.Tokens.HolderController do use BlockScoutWeb, :controller + alias BlockScoutWeb.AccessHelpers alias BlockScoutWeb.Tokens.HolderView alias Explorer.{Chain, Market} alias Explorer.Chain.Address @@ -16,7 +17,8 @@ defmodule BlockScoutWeb.Tokens.HolderController do def index(conn, %{"token_id" => address_hash_string, "type" => "JSON"} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), {:ok, token} <- Chain.token_from_address_hash(address_hash), - token_balances <- Chain.fetch_token_holders_from_token_hash(address_hash, paging_options(params)) do + token_balances <- Chain.fetch_token_holders_from_token_hash(address_hash, paging_options(params)), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do {token_balances_paginated, next_page} = split_list_by_page(token_balances) next_page_path = @@ -35,6 +37,9 @@ defmodule BlockScoutWeb.Tokens.HolderController do json(conn, %{items: token_balances_json, next_page_path: next_page_path}) else + {:restricted_access, _} -> + not_found(conn) + :error -> not_found(conn) @@ -43,11 +48,12 @@ defmodule BlockScoutWeb.Tokens.HolderController do end end - def index(conn, %{"token_id" => address_hash_string}) do + def index(conn, %{"token_id" => address_hash_string} = params) do options = [necessity_by_association: %{[contract_address: :smart_contract] => :optional}] with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - {:ok, token} <- Chain.token_from_address_hash(address_hash, options) do + {:ok, token} <- Chain.token_from_address_hash(address_hash, options), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do render( conn, "index.html", @@ -56,6 +62,9 @@ defmodule BlockScoutWeb.Tokens.HolderController do counters_path: token_path(conn, :token_counters, %{"id" => Address.checksum(address_hash)}) ) else + {:restricted_access, _} -> + not_found(conn) + :error -> not_found(conn) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/inventory_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/inventory_controller.ex index f257334a07..41f562554b 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/inventory_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/inventory_controller.ex @@ -1,6 +1,7 @@ defmodule BlockScoutWeb.Tokens.InventoryController do use BlockScoutWeb, :controller + alias BlockScoutWeb.AccessHelpers alias BlockScoutWeb.Tokens.InventoryView alias Explorer.{Chain, Market} alias Explorer.Chain.{Address, TokenTransfer} @@ -10,7 +11,8 @@ defmodule BlockScoutWeb.Tokens.InventoryController do def index(conn, %{"token_id" => address_hash_string, "type" => "JSON"} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - {:ok, token} <- Chain.token_from_address_hash(address_hash) do + {:ok, token} <- Chain.token_from_address_hash(address_hash), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do unique_tokens = Chain.address_to_unique_tokens( token.contract_address_hash, @@ -53,6 +55,9 @@ defmodule BlockScoutWeb.Tokens.InventoryController do } ) else + {:restricted_access, _} -> + not_found(conn) + :error -> not_found(conn) @@ -61,11 +66,12 @@ defmodule BlockScoutWeb.Tokens.InventoryController do end end - def index(conn, %{"token_id" => address_hash_string}) do + def index(conn, %{"token_id" => address_hash_string} = params) do options = [necessity_by_association: %{[contract_address: :smart_contract] => :optional}] with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - {:ok, token} <- Chain.token_from_address_hash(address_hash, options) do + {:ok, token} <- Chain.token_from_address_hash(address_hash, options), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do render( conn, "index.html", @@ -74,6 +80,9 @@ defmodule BlockScoutWeb.Tokens.InventoryController do counters_path: token_path(conn, :token_counters, %{"id" => Address.checksum(address_hash)}) ) else + {:restricted_access, _} -> + not_found(conn) + :error -> not_found(conn) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/read_contract_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/read_contract_controller.ex index 96b0cfe23b..9f76a59aff 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/read_contract_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/read_contract_controller.ex @@ -1,15 +1,17 @@ defmodule BlockScoutWeb.Tokens.ReadContractController do use BlockScoutWeb, :controller + alias BlockScoutWeb.AccessHelpers alias Explorer.{Chain, Market} alias Explorer.Chain.Address - def index(conn, %{"token_id" => address_hash_string}) do + def index(conn, %{"token_id" => address_hash_string} = params) do options = [necessity_by_association: %{[contract_address: :smart_contract] => :optional}] with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), :ok <- Chain.check_verified_smart_contract_exists(address_hash), - {:ok, token} <- Chain.token_from_address_hash(address_hash, options) do + {:ok, token} <- Chain.token_from_address_hash(address_hash, options), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do render( conn, "index.html", @@ -19,6 +21,9 @@ defmodule BlockScoutWeb.Tokens.ReadContractController do counters_path: token_path(conn, :token_counters, %{"id" => Address.checksum(address_hash)}) ) else + {:restricted_access, _} -> + not_found(conn) + :not_found -> not_found(conn) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/token_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/token_controller.ex index fb5891d07f..71e66676ab 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/token_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/token_controller.ex @@ -3,10 +3,11 @@ defmodule BlockScoutWeb.Tokens.TokenController do require Logger + alias BlockScoutWeb.AccessHelpers alias Explorer.Chain def show(conn, %{"id" => address_hash_string}) do - redirect(conn, to: token_transfer_path(conn, :index, address_hash_string)) + redirect(conn, to: AccessHelpers.get_path(conn, :token_transfer_path, :index, address_hash_string)) end def token_counters(conn, %{"id" => address_hash_string}) do diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/transfer_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/transfer_controller.ex index fd3579efbd..afc879c212 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/transfer_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/transfer_controller.ex @@ -1,6 +1,7 @@ defmodule BlockScoutWeb.Tokens.TransferController do use BlockScoutWeb, :controller + alias BlockScoutWeb.AccessHelpers alias BlockScoutWeb.Tokens.TransferView alias Explorer.{Chain, Market} alias Explorer.Chain.Address @@ -15,7 +16,8 @@ defmodule BlockScoutWeb.Tokens.TransferController do def index(conn, %{"token_id" => address_hash_string, "type" => "JSON"} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), {:ok, token} <- Chain.token_from_address_hash(address_hash), - token_transfers <- Chain.fetch_token_transfers_from_token_hash(address_hash, paging_options(params)) do + token_transfers <- Chain.fetch_token_transfers_from_token_hash(address_hash, paging_options(params)), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do {token_transfers_paginated, next_page} = split_list_by_page(token_transfers) next_page_path = @@ -46,6 +48,9 @@ defmodule BlockScoutWeb.Tokens.TransferController do json(conn, %{items: transfers_json, next_page_path: next_page_path}) else + {:restricted_access, _} -> + not_found(conn) + :error -> unprocessable_entity(conn) @@ -54,11 +59,12 @@ defmodule BlockScoutWeb.Tokens.TransferController do end end - def index(conn, %{"token_id" => address_hash_string}) do + def index(conn, %{"token_id" => address_hash_string} = params) do options = [necessity_by_association: %{[contract_address: :smart_contract] => :optional}] with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), - {:ok, token} <- Chain.token_from_address_hash(address_hash, options) do + {:ok, token} <- Chain.token_from_address_hash(address_hash, options), + {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params) do render( conn, "index.html", @@ -68,6 +74,9 @@ defmodule BlockScoutWeb.Tokens.TransferController do token_total_supply_status: TokenTotalSupplyOnDemand.trigger_fetch(address_hash) ) else + {:restricted_access, _} -> + not_found(conn) + :error -> not_found(conn) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_controller.ex index 9643a356bd..37c4b2127f 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_controller.ex @@ -3,7 +3,7 @@ defmodule BlockScoutWeb.TransactionController do import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1] - alias BlockScoutWeb.TransactionView + alias BlockScoutWeb.{AccessHelpers, TransactionView} alias Explorer.Chain alias Phoenix.View @@ -69,13 +69,16 @@ defmodule BlockScoutWeb.TransactionController do with {:ok, transaction_hash} <- Chain.string_to_transaction_hash(id), :ok <- Chain.check_transaction_exists(transaction_hash) do if Chain.transaction_has_token_transfers?(transaction_hash) do - redirect(conn, to: transaction_token_transfer_path(conn, :index, id)) + redirect(conn, to: AccessHelpers.get_path(conn, :transaction_token_transfer_path, :index, id)) else - redirect(conn, to: transaction_internal_transaction_path(conn, :index, id)) + redirect(conn, to: AccessHelpers.get_path(conn, :transaction_internal_transaction_path, :index, id)) end else - :error -> conn |> put_status(422) |> render("invalid.html", transaction_hash: id) - :not_found -> conn |> put_status(404) |> render("not_found.html", transaction_hash: id) + :error -> + conn |> put_status(422) |> render("invalid.html", transaction_hash: id) + + :not_found -> + conn |> put_status(404) |> render("not_found.html", transaction_hash: id) end end end diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_internal_transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_internal_transaction_controller.ex index ca154a0136..2e2601f23a 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_internal_transaction_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_internal_transaction_controller.ex @@ -3,14 +3,17 @@ defmodule BlockScoutWeb.TransactionInternalTransactionController do import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1] - alias BlockScoutWeb.{InternalTransactionView, TransactionView} + alias BlockScoutWeb.{AccessHelpers, InternalTransactionView, TransactionView} alias Explorer.{Chain, Market} alias Explorer.ExchangeRates.Token alias Phoenix.View - def index(conn, %{"transaction_id" => hash_string, "type" => "JSON"} = params) do - with {:ok, hash} <- Chain.string_to_transaction_hash(hash_string), - :ok <- Chain.check_transaction_exists(hash) do + def index(conn, %{"transaction_id" => transaction_hash_string, "type" => "JSON"} = params) do + with {:ok, transaction_hash} <- Chain.string_to_transaction_hash(transaction_hash_string), + :ok <- Chain.check_transaction_exists(transaction_hash), + {:ok, transaction} <- 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( [ @@ -24,7 +27,7 @@ defmodule BlockScoutWeb.TransactionInternalTransactionController do paging_options(params) ) - internal_transactions_plus_one = Chain.transaction_to_internal_transactions(hash, full_options) + internal_transactions_plus_one = Chain.transaction_to_internal_transactions(transaction_hash, full_options) {internal_transactions, next_page} = split_list_by_page(internal_transactions_plus_one) @@ -37,7 +40,7 @@ defmodule BlockScoutWeb.TransactionInternalTransactionController do transaction_internal_transaction_path( conn, :index, - hash, + transaction_hash, Map.delete(next_page_params, "type") ) end @@ -60,25 +63,37 @@ defmodule BlockScoutWeb.TransactionInternalTransactionController do } ) else + {:restricted_access, _} -> + conn + |> put_status(404) + |> put_view(TransactionView) + |> render("not_found.html", transaction_hash: transaction_hash_string) + :error -> conn |> put_status(422) |> put_view(TransactionView) - |> render("invalid.html", transaction_hash: hash_string) + |> render("invalid.html", transaction_hash: transaction_hash_string) + + {:error, :not_found} -> + conn + |> put_status(404) + |> put_view(TransactionView) + |> render("not_found.html", transaction_hash: transaction_hash_string) :not_found -> conn |> put_status(404) |> put_view(TransactionView) - |> render("not_found.html", transaction_hash: hash_string) + |> render("not_found.html", transaction_hash: transaction_hash_string) end end - def index(conn, %{"transaction_id" => hash_string}) do - with {:ok, hash} <- Chain.string_to_transaction_hash(hash_string), + def index(conn, %{"transaction_id" => transaction_hash_string} = params) do + with {:ok, transaction_hash} <- Chain.string_to_transaction_hash(transaction_hash_string), {:ok, transaction} <- Chain.hash_to_transaction( - hash, + transaction_hash, necessity_by_association: %{ :block => :optional, [created_contract_address: :names] => :optional, @@ -87,28 +102,36 @@ defmodule BlockScoutWeb.TransactionInternalTransactionController do [to_address: :smart_contract] => :optional, :token_transfers => :optional } - ) do + ), + {: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 render( conn, "index.html", exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(), current_path: current_path(conn), block_height: Chain.block_height(), - show_token_transfers: Chain.transaction_has_token_transfers?(hash), + show_token_transfers: Chain.transaction_has_token_transfers?(transaction_hash), transaction: transaction ) else + {:restricted_access, _} -> + conn + |> put_status(404) + |> put_view(TransactionView) + |> render("not_found.html", transaction_hash: transaction_hash_string) + :error -> conn |> put_status(422) |> put_view(TransactionView) - |> render("invalid.html", transaction_hash: hash_string) + |> render("invalid.html", transaction_hash: transaction_hash_string) {:error, :not_found} -> conn |> put_status(404) |> put_view(TransactionView) - |> render("not_found.html", transaction_hash: hash_string) + |> render("not_found.html", transaction_hash: transaction_hash_string) end end end diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_log_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_log_controller.ex index e076b9ee7b..5fec4bfda4 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_log_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_log_controller.ex @@ -3,7 +3,7 @@ defmodule BlockScoutWeb.TransactionLogController do import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1] - alias BlockScoutWeb.{TransactionLogView, TransactionView} + alias BlockScoutWeb.{AccessHelpers, TransactionLogView, TransactionView} alias Explorer.{Chain, Market} alias Explorer.ExchangeRates.Token alias Phoenix.View @@ -13,7 +13,9 @@ defmodule BlockScoutWeb.TransactionLogController do {:ok, transaction} <- Chain.hash_to_transaction(transaction_hash, necessity_by_association: %{[to_address: :smart_contract] => :optional} - ) do + ), + {: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( [ @@ -57,6 +59,12 @@ defmodule BlockScoutWeb.TransactionLogController do } ) else + {:restricted_access, _} -> + conn + |> put_status(404) + |> put_view(TransactionView) + |> render("not_found.html", transaction_hash: transaction_hash_string) + :error -> conn |> put_status(422) @@ -71,7 +79,7 @@ defmodule BlockScoutWeb.TransactionLogController do end end - def index(conn, %{"transaction_id" => transaction_hash_string}) do + def index(conn, %{"transaction_id" => transaction_hash_string} = params) do with {:ok, transaction_hash} <- Chain.string_to_transaction_hash(transaction_hash_string), {:ok, transaction} <- Chain.hash_to_transaction( @@ -84,7 +92,9 @@ defmodule BlockScoutWeb.TransactionLogController do [to_address: :smart_contract] => :optional, :token_transfers => :optional } - ) do + ), + {: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 render( conn, "index.html", @@ -95,6 +105,12 @@ defmodule BlockScoutWeb.TransactionLogController do exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null() ) else + {:restricted_access, _} -> + conn + |> put_status(404) + |> put_view(TransactionView) + |> render("not_found.html", transaction_hash: transaction_hash_string) + :error -> conn |> put_status(422) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_raw_trace_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_raw_trace_controller.ex index 82f189e9b3..cbf36743b0 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_raw_trace_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_raw_trace_controller.ex @@ -1,14 +1,14 @@ defmodule BlockScoutWeb.TransactionRawTraceController do use BlockScoutWeb, :controller - alias BlockScoutWeb.TransactionView + alias BlockScoutWeb.{AccessHelpers, TransactionView} alias EthereumJSONRPC alias Explorer.{Chain, Market} alias Explorer.Chain.Import alias Explorer.Chain.Import.Runner.InternalTransactions alias Explorer.ExchangeRates.Token - def index(conn, %{"transaction_id" => hash_string}) do + def index(conn, %{"transaction_id" => hash_string} = params) do with {:ok, hash} <- Chain.string_to_transaction_hash(hash_string), {:ok, transaction} <- Chain.hash_to_transaction( @@ -21,7 +21,9 @@ defmodule BlockScoutWeb.TransactionRawTraceController do [to_address: :smart_contract] => :optional, :token_transfers => :optional } - ) do + ), + {: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 internal_transactions = Chain.all_transaction_to_internal_transactions(hash) first_trace_exists = @@ -76,6 +78,12 @@ defmodule BlockScoutWeb.TransactionRawTraceController do transaction: transaction ) else + {:restricted_access, _} -> + conn + |> put_status(404) + |> put_view(TransactionView) + |> render("not_found.html", transaction_hash: hash_string) + :error -> conn |> put_status(422) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_token_transfer_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_token_transfer_controller.ex index afb2fa373e..827e8866aa 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_token_transfer_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_token_transfer_controller.ex @@ -3,7 +3,7 @@ defmodule BlockScoutWeb.TransactionTokenTransferController do import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1] - alias BlockScoutWeb.{TransactionTokenTransferView, TransactionView} + alias BlockScoutWeb.{AccessHelpers, TransactionTokenTransferView, TransactionView} alias Explorer.{Chain, Market} alias Explorer.ExchangeRates.Token alias Phoenix.View @@ -11,9 +11,16 @@ defmodule BlockScoutWeb.TransactionTokenTransferController do {:ok, burn_address_hash} = Chain.string_to_address_hash("0x0000000000000000000000000000000000000000") @burn_address_hash burn_address_hash - def index(conn, %{"transaction_id" => hash_string, "type" => "JSON"} = params) do - with {:ok, hash} <- Chain.string_to_transaction_hash(hash_string), - :ok <- Chain.check_transaction_exists(hash) do + def index(conn, %{"transaction_id" => transaction_hash_string, "type" => "JSON"} = params) do + with {:ok, transaction_hash} <- Chain.string_to_transaction_hash(transaction_hash_string), + :ok <- Chain.check_transaction_exists(transaction_hash), + {:ok, transaction} <- + 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( [ @@ -26,7 +33,7 @@ defmodule BlockScoutWeb.TransactionTokenTransferController do paging_options(params) ) - token_transfers_plus_one = Chain.transaction_to_token_transfers(hash, full_options) + token_transfers_plus_one = Chain.transaction_to_token_transfers(transaction_hash, full_options) {token_transfers, next_page} = split_list_by_page(token_transfers_plus_one) @@ -36,7 +43,7 @@ defmodule BlockScoutWeb.TransactionTokenTransferController do nil next_page_params -> - transaction_token_transfer_path(conn, :index, hash, Map.delete(next_page_params, "type")) + transaction_token_transfer_path(conn, :index, transaction_hash, Map.delete(next_page_params, "type")) end items = @@ -59,25 +66,37 @@ defmodule BlockScoutWeb.TransactionTokenTransferController do } ) else + {:restricted_access, _} -> + conn + |> put_status(404) + |> put_view(TransactionView) + |> render("not_found.html", transaction_hash: transaction_hash_string) + :error -> conn |> put_status(422) |> put_view(TransactionView) - |> render("invalid.html", transaction_hash: hash_string) + |> render("invalid.html", transaction_hash: transaction_hash_string) + + {:error, :not_found} -> + conn + |> put_status(404) + |> put_view(TransactionView) + |> render("not_found.html", transaction_hash: transaction_hash_string) :not_found -> conn |> put_status(404) |> put_view(TransactionView) - |> render("not_found.html", transaction_hash: hash_string) + |> render("not_found.html", transaction_hash: transaction_hash_string) end end - def index(conn, %{"transaction_id" => hash_string}) do - with {:ok, hash} <- Chain.string_to_transaction_hash(hash_string), + def index(conn, %{"transaction_id" => transaction_hash_string} = params) do + with {:ok, transaction_hash} <- Chain.string_to_transaction_hash(transaction_hash_string), {:ok, transaction} <- Chain.hash_to_transaction( - hash, + transaction_hash, necessity_by_association: %{ :block => :optional, [created_contract_address: :names] => :optional, @@ -86,7 +105,9 @@ defmodule BlockScoutWeb.TransactionTokenTransferController do [to_address: :smart_contract] => :optional, :token_transfers => :optional } - ) do + ), + {: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 render( conn, "index.html", @@ -97,17 +118,29 @@ defmodule BlockScoutWeb.TransactionTokenTransferController do transaction: transaction ) else + :not_found -> + conn + |> put_status(404) + |> put_view(TransactionView) + |> render("not_found.html", transaction_hash: transaction_hash_string) + :error -> conn |> put_status(422) |> put_view(TransactionView) - |> render("invalid.html", transaction_hash: hash_string) + |> render("invalid.html", transaction_hash: transaction_hash_string) {:error, :not_found} -> conn |> put_status(404) |> put_view(TransactionView) - |> render("not_found.html", transaction_hash: hash_string) + |> render("not_found.html", transaction_hash: transaction_hash_string) + + {:restricted_access, _} -> + conn + |> put_status(404) + |> put_view(TransactionView) + |> render("not_found.html", transaction_hash: transaction_hash_string) end end end diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/_balance_card.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/_balance_card.html.eex index 08da882238..c8140fb812 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address/_balance_card.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address/_balance_card.html.eex @@ -19,7 +19,7 @@
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/_tabs.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/_tabs.html.eex index 107b4f5e43..103002d81d 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address/_tabs.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address/_tabs.html.eex @@ -2,21 +2,21 @@ <%= link( gettext("Transactions"), class: "card-tab #{tab_status("transactions", @conn.request_path)}", - to: address_transaction_path(@conn, :index, @address.hash) + to: AccessHelpers.get_path(@conn, :address_transaction_path, :index, @address.hash) ) %> <%= if Chain.check_if_token_transfers_at_address(@address.hash) do %> <%= link( gettext("Token Transfers"), class: "card-tab #{tab_status("token-transfers", @conn.request_path)}", "data-test": "token_transfers_tab_link", - to: address_token_transfers_path(@conn, :index, @address.hash) + to: AccessHelpers.get_path(@conn, :address_token_transfers_path, :index, @address.hash) ) %> <% end %> <%= if Chain.check_if_tokens_at_address(@address.hash) do %> <%= link( gettext("Tokens"), class: "card-tab #{tab_status("tokens", @conn.request_path)}", - to: address_token_path(@conn, :index, @address.hash), + to: AccessHelpers.get_path(@conn, :address_token_path, :index, @address.hash), "data-test": "tokens_tab_link" ) %> <% end %> @@ -24,19 +24,19 @@ gettext("Internal Transactions"), class: "card-tab #{tab_status("internal-transactions", @conn.request_path)}", "data-test": "internal_transactions_tab_link", - to: address_internal_transaction_path(@conn, :index, @address.hash) + to: AccessHelpers.get_path(@conn, :address_internal_transaction_path, :index, @address.hash) ) %> <%= link( gettext("Coin Balance History"), class: "card-tab #{tab_status("coin-balances", @conn.request_path)}", "data-test": "coin_balance_tab_link", - to: address_coin_balance_path(@conn, :index, @address.hash) + to: AccessHelpers.get_path(@conn, :address_coin_balance_path, :index, @address.hash) ) %> <%= if Chain.check_if_logs_at_address(@address.hash) do %> <%= link( gettext("Logs"), class: "card-tab #{tab_status("logs", @conn.request_path)}", - to: address_logs_path(@conn, :index, @address.hash) + to: AccessHelpers.get_path(@conn, :address_logs_path, :index, @address.hash) ) %> <% end %> <%= if Chain.check_if_validated_blocks_at_address(@address.hash) do %> @@ -44,12 +44,12 @@ gettext("Blocks Validated"), class: "card-tab #{tab_status("validations", @conn.request_path)}", "data-test": "validations_tab_link", - to: address_validation_path(@conn, :index, @address.hash) + to: AccessHelpers.get_path(@conn, :address_validation_path, :index, @address.hash) ) %> <% end %> <%= if contract?(@address) do %> <%= link( - to: address_contract_path(@conn, :index, @address.hash), + to: AccessHelpers.get_path(@conn, :address_contract_path, :index, @address.hash), class: "card-tab #{tab_status("contracts", @conn.request_path)}") do %> <%= gettext("Code") %> <%= if smart_contract_verified?(@address) do %> @@ -59,7 +59,7 @@ <% end %> <%= if has_decompiled_code?(@address) do %> <%= link( - to: address_decompiled_contract_path(@conn, :index, @address.hash), + to: AccessHelpers.get_path(@conn, :address_decompiled_contract_path, :index, @address.hash), class: "card-tab #{tab_status("decompiled-contracts", @conn.request_path)}") do %> <%= gettext("Decompiled code") %> @@ -68,28 +68,28 @@ <%= if smart_contract_with_read_only_functions?(@address) do %> <%= link( gettext("Read Contract"), - to: address_read_contract_path(@conn, :index, @address.hash), + to: AccessHelpers.get_path(@conn, :address_read_contract_path, :index, @address.hash), class: "card-tab #{tab_status("read-contract", @conn.request_path)}") %> <% end %> <%= if smart_contract_is_proxy?(@address) do %> <%= link( gettext("Read Proxy"), - to: address_read_proxy_path(@conn, :index, @address.hash), + to: AccessHelpers.get_path(@conn, :address_read_proxy_path, :index, @address.hash), class: "card-tab #{tab_status("read-proxy", @conn.request_path)}") %> <% end %> <%= if smart_contract_with_write_functions?(@address) do %> <%= link( gettext("Write Contract"), - to: address_write_contract_path(@conn, :index, @address.hash), + to: AccessHelpers.get_path(@conn, :address_write_contract_path, :index, @address.hash), class: "card-tab #{tab_status("write-contract", @conn.request_path)}") %> <% end %> <%= if smart_contract_with_write_functions?(@address) && smart_contract_is_proxy?(@address) do %> <%= link( gettext("Write Proxy"), - to: address_write_proxy_path(@conn, :index, @address.hash), + to: AccessHelpers.get_path(@conn, :address_write_proxy_path, :index, @address.hash), class: "card-tab #{tab_status("write-proxy", @conn.request_path)}") %> <% end %> diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_coin_balance/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_coin_balance/index.html.eex index 35f00f2d15..a64d1458e4 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address_coin_balance/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address_coin_balance/index.html.eex @@ -27,7 +27,7 @@ <%= gettext("There was a problem loading the chart.") %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_internal_transaction/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_internal_transaction/index.html.eex index be0b86685f..c7cd85e21a 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address_internal_transaction/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address_internal_transaction/index.html.eex @@ -25,29 +25,19 @@