104 lines
2.7 KiB
Elixir
104 lines
2.7 KiB
Elixir
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
|