Set RPCTranslator to check writing and reading functions

pull/2376/head
saneery 5 years ago
parent 67ff28ad8e
commit 843800f3f7
  1. 58
      apps/block_scout_web/lib/block_scout_web/api_router.ex
  2. 15
      apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/rpc_translator.ex
  3. 12
      apps/block_scout_web/lib/block_scout_web/router.ex

@ -18,42 +18,56 @@ defmodule BlockScoutWeb.ApiRouter do
plug(:accepts, ["json"]) plug(:accepts, ["json"])
end end
scope "/v1", as: :api_v1 do scope "/v1", BlockScoutWeb.API.V1, as: :api_v1 do
pipe_through(:api) pipe_through(:api)
get("/health", HealthController, :health)
if Application.get_env(:block_scout_web, __MODULE__)[:writing_enabled] do
post("/decompiled_smart_contract", DecompiledSmartContractController, :create)
post("/verified_smart_contracts", VerifiedSmartContractController, :create)
end
end
if Application.get_env(:block_scout_web, __MODULE__)[:reading_enabled] do
scope "/" do scope "/" do
alias BlockScoutWeb.API.{RPC, V1} alias BlockScoutWeb.API.{RPC, V1}
get("/supply", V1.SupplyController, :supply) pipe_through(:api)
post("/eth_rpc", RPC.EthController, :eth_request) scope "/v1", as: :api_v1 do
get("/supply", V1.SupplyController, :supply)
post("/eth_rpc", RPC.EthController, :eth_request)
end
forward("/", RPC.RPCTranslator, %{ # For backward compatibility. Should be removed
"block" => RPC.BlockController, post("/eth_rpc", RPC.EthController, :eth_request)
"account" => RPC.AddressController,
"logs" => RPC.LogsController,
"token" => RPC.TokenController,
"stats" => RPC.StatsController,
"contract" => RPC.ContractController,
"transaction" => RPC.TransactionController
})
end end
end end
# For backward compatibility. Should be removed
scope "/" do scope "/" do
alias BlockScoutWeb.API.RPC
pipe_through(:api) pipe_through(:api)
alias BlockScoutWeb.API.RPC
post("/eth_rpc", RPC.EthController, :eth_request) scope "/v1", as: :api_v1 do
forward("/", RPC.RPCTranslator, %{
"block" => {RPC.BlockController, []},
"account" => {RPC.AddressController, []},
"logs" => {RPC.LogsController, []},
"token" => {RPC.TokenController, []},
"stats" => {RPC.StatsController, []},
"contract" => {RPC.ContractController, [:verify]},
"transaction" => {RPC.TransactionController, []}
})
end
# For backward compatibility. Should be removed
forward("/", RPCTranslatorForwarder, %{ forward("/", RPCTranslatorForwarder, %{
"block" => RPC.BlockController, "block" => {RPC.BlockController, []},
"account" => RPC.AddressController, "account" => {RPC.AddressController, []},
"logs" => RPC.LogsController, "logs" => {RPC.LogsController, []},
"token" => RPC.TokenController, "token" => {RPC.TokenController, []},
"stats" => RPC.StatsController, "stats" => {RPC.StatsController, []},
"contract" => RPC.ContractController, "contract" => {RPC.ContractController, [:verify]},
"transaction" => RPC.TransactionController "transaction" => {RPC.TransactionController, []}
}) })
end end
end end

@ -25,8 +25,9 @@ defmodule BlockScoutWeb.API.RPC.RPCTranslator do
def init(opts), do: opts def init(opts), do: opts
def call(%Conn{params: %{"module" => module, "action" => action}} = conn, translations) do def call(%Conn{params: %{"module" => module, "action" => action}} = conn, translations) do
with {:ok, controller} <- translate_module(translations, module), with {:ok, {controller, write_actions}} <- translate_module(translations, module),
{:ok, action} <- translate_action(action), {:ok, action} <- translate_action(action),
true <- action_accessed?(action, write_actions),
{:ok, conn} <- call_controller(conn, controller, action) do {:ok, conn} <- call_controller(conn, controller, action) do
conn conn
else else
@ -64,7 +65,7 @@ defmodule BlockScoutWeb.API.RPC.RPCTranslator do
end end
@doc false @doc false
@spec translate_module(map(), String.t()) :: {:ok, module()} | {:error, :no_action} @spec translate_module(map(), String.t()) :: {:ok, {module(), list(atom())}} | {:error, :no_action}
defp translate_module(translations, module) do defp translate_module(translations, module) do
module_lowercase = String.downcase(module) module_lowercase = String.downcase(module)
@ -83,6 +84,16 @@ defmodule BlockScoutWeb.API.RPC.RPCTranslator do
ArgumentError -> {:error, :no_action} ArgumentError -> {:error, :no_action}
end end
defp action_accessed?(action, write_actions) do
conf = Application.get_env(:block_scout_web, BlockScoutWeb.ApiRouter)
if action in write_actions do
conf[:writing_enabled] || {:error, :no_action}
else
conf[:reading_enabled] || {:error, :no_action}
end
end
@doc false @doc false
@spec call_controller(Conn.t(), module(), atom()) :: {:ok, Conn.t()} | {:error, :no_action} | {:error, Exception.t()} @spec call_controller(Conn.t(), module(), atom()) :: {:ok, Conn.t()} | {:error, :no_action} | {:error, Exception.t()}
defp call_controller(conn, controller, action) do defp call_controller(conn, controller, action) do

@ -19,19 +19,9 @@ defmodule BlockScoutWeb.Router do
plug(:accepts, ["json"]) plug(:accepts, ["json"])
end end
scope "/api/v1", BlockScoutWeb.API.V1, as: :api_v1 do forward("/api", ApiRouter)
pipe_through(:api)
get("/health", HealthController, :health)
if Application.get_env(:block_scout_web, ApiRouter)[:writing_enabled] do
post("/decompiled_smart_contract", DecompiledSmartContractController, :create)
post("/verified_smart_contracts", VerifiedSmartContractController, :create)
end
end
if Application.get_env(:block_scout_web, ApiRouter)[:reading_enabled] do if Application.get_env(:block_scout_web, ApiRouter)[:reading_enabled] do
forward("/api", ApiRouter)
# Needs to be 200 to support the schema introspection for graphiql # Needs to be 200 to support the schema introspection for graphiql
@max_complexity 200 @max_complexity 200

Loading…
Cancel
Save