defmodule NervesBackdoor.Endpoint do use Plug.Router plug(:auth) defp auth(conn, _opts) do username = NervesBackdoor.name() password = NervesBackdoor.password(:current) #disable password check by uploading empty password file case String.length(password) do 0 -> conn _ -> Plug.BasicAuth.basic_auth(conn, username: username, password: password) end end plug(:match) # curl http://localhost:31680/tmp/test.txt plug(Plug.Static, at: "/tmp", from: "/tmp") # curl http://localhost:31680/data/test.txt # curl http://nerves.local:31680/data/lvnbe.db3 --output /tmp/lvnbe.db3 plug(Plug.Static, at: "/data", from: "/data") plug(Plug.Parsers, parsers: [:urlencoded, :multipart], pass: ["*/*"]) plug(Plug.Parsers, parsers: [:json], pass: ["application/json"], json_decoder: Jason) # curl http://localhost:31680/ping # curl http://nerves.local:31680/ping get "/ping" do respond(conn, {:ok, %{ping: "pong"}}) end # curl -F 'file=@/tmp/test.txt' http://localhost:31680/upload?path=/tmp/testup.txt # curl -F 'file=@/tmp/test.txt' http://nerves.local:31680/upload?path=/tmp/testup.txt post "/upload" do {:ok, upload} = Map.fetch(conn.params, "file") {:ok, path} = Map.fetch(conn.query_params, "path") result = File.copy(upload.path, path) File.rm(upload.path) respond(conn, result) end # curl -X DELETE http://localhost:31680/delete?path=/tmp/testup.txt # curl -X DELETE http://nerves.local:31680/delete?path=/tmp/testup.txt delete "/delete" do {:ok, path} = Map.fetch(conn.query_params, "path") result = File.rm(path) respond(conn, result) end # curl http://localhost:31680/net/all # curl http://nerves.local:31680/net/all get "/net/all" do result = NervesBackdoor.Vintage.all_interfaces() respond(conn, result) end # VintageNet.info # VintageNet.get_configuration("eth0") # VintageNet.get(["interface", "eth0", "type"]) # VintageNet.get(["interface", "eth0", "state"]) # VintageNet.get(["interface", "eth0", "connection"]) # curl http://localhost:31680/net/state/eth0 # curl http://nerves.local:31680/net/state/eth0 get "/net/state/:interface" do {:ok, interface} = Map.fetch(conn.path_params, "interface") result = NervesBackdoor.Vintage.get_configuration(interface) respond(conn, result) end # VintageNet.configure("eth0", %{type: VintageNetEthernet, ipv4: %{method: :dhcp}}) # VintageNet.configure("eth0", %{type: VintageNetEthernet, ipv4: %{method: :static, address: "10.77.4.100", prefix_length: 8, gateway: "10.77.0.1", name_servers: ["10.77.0.1"]}}) # curl -X POST http://localhost:31680/net/setup/eth0 -H "Content-Type: application/json" -d '{"method":"dhcp"}' # curl -X POST http://nerves.local:31680/net/setup/eth0 -H "Content-Type: application/json" -d '{"method":"dhcp"}' # curl -X POST http://localhost:31680/net/setup/eth0 -H "Content-Type: application/json" -d '{"method":"static", "address":"10.77.4.100", "prefix_length":8, "gateway":"10.77.0.1", "name_servers":["10.77.0.1"]}' # curl -X POST http://nerves.local:31680/net/setup/eth0 -H "Content-Type: application/json" -d '{"method":"static", "address":"10.77.4.100", "prefix_length":8, "gateway":"10.77.0.1", "name_servers":["10.77.0.1"]}' post "/net/setup/:interface" do {:ok, interface} = Map.fetch(conn.path_params, "interface") result = NervesBackdoor.Vintage.configure(interface, conn.body_params) respond(conn, result) end # Application.started_applications # Application.loaded_applications # Application.get_all_env :nss # curl -X POST http://localhost:31680/app/start/nss # curl -X POST http://nerves.local:31680/app/start/nss post "/app/start/:app" do {:ok, app} = Map.fetch(conn.path_params, "app") result = case app_loaded(app) do nil -> {:error, "App not found #{app}"} {appa, _desc, _ver} -> Application.start(appa, :permanent) end respond(conn, result) end # curl -X POST http://localhost:31680/app/stop/nss # curl -X POST http://nerves.local:31680/app/stop/nss post "/app/stop/:app" do {:ok, app} = Map.fetch(conn.path_params, "app") result = case app_loaded(app) do nil -> {:error, "App not found #{app}"} {appa, _desc, _ver} -> Application.stop(appa) end respond(conn, result) end defp app_loaded(app) do Enum.find(Application.loaded_applications(), fn tuple -> {atom, _desc, _ver} = tuple Atom.to_string(atom) == app end) end defp respond(conn, result) do conn = put_resp_content_type(conn, "application/json") case result do :ok -> send_resp(conn, 200, Jason.encode!(%{result: "ok"})) {:ok, message} -> send_resp(conn, 200, Jason.encode!(%{result: "ok", message: message})) {:error, message} -> send_resp(conn, 500, Jason.encode!(%{result: "error", message: message})) end end alias Jason.Encoder defimpl Encoder, for: Tuple do def encode(data, options) when is_tuple(data) do data |> Tuple.to_list() |> Encoder.List.encode(options) end end plug(:dispatch) match _ do send_resp(conn, 404, Jason.encode!(%{result: "error", message: "not found"})) end end