defmodule PlugMicropub.Parser do import Plug.Conn def get_action(conn) do {action, body_params} = Map.pop(conn.body_params, "action") conn = %Plug.Conn{conn | body_params: body_params} case action do nil -> {:ok, :create, conn} action when action in ["delete", "undelete", "update"] -> {:ok, String.to_existing_atom(action), conn} _ -> {:error, :invalid_request, "Invalid action supplied."} end end def get_query(conn) do case Map.fetch(conn.query_params, "q") do {:ok, query} when query in ["config", "source", "syndicate-to"] -> {:ok, String.to_existing_atom(query)} _ -> {:error, :invalid_request, "Invalid query supplied."} end end def get_file(conn) do case Map.fetch(conn.body_params, "file") do {:ok, file} -> {:ok, file} :error -> {:error, :invalid_request, "Invalid file supplied."} end end def get_access_token(conn) do {access_token, body_params} = Map.pop(conn.body_params, "access_token") conn = %Plug.Conn{conn | body_params: body_params} case access_token do nil -> parse_auth_header(conn) access_token -> {:ok, access_token, conn} end end defp parse_auth_header(conn) do with [header] <- get_req_header(conn, "authorization"), "Bearer" <> token <- header, do: {:ok, String.trim(token), conn}, else: (_ -> {:error, :unauthorized, "Authentication from header failed."}) end def parse_create_body("application/json", params) do with {:ok, ["h-" <> type]} <- Map.fetch(params, "type"), {:ok, properties} when is_map(properties) <- Map.fetch(params, "properties") do {:ok, type, Map.new(properties)} else _ -> {:error, :invalid_request} end end def parse_create_body(_, params) do with {type, params} when is_binary(type) <- Map.pop(params, "h") do properties = params |> Enum.map(fn {k, v} -> {k, List.wrap(v)} end) |> Map.new() {:ok, type, properties} else _ -> {:error, :invalid_request} end end def parse_update_properties(properties) do properties = Map.take(properties, ["replace", "add", "delete"]) valid? = Enum.all?(properties, fn {"delete", prop} when is_list(prop) -> Enum.all?(prop, &is_binary/1) {_k, prop} when is_map(prop) -> Enum.all?(prop, fn {_k, v} when is_list(v) -> true _ -> false end) _ -> false end) if valid? do replace = Map.get(properties, "replace", %{}) add = Map.get(properties, "add", %{}) delete = Map.get(properties, "delete", %{}) {:ok, replace, add, delete} else :error end end end