You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
asciinema.org/lib/asciinema_web/controllers/api/asciicast_controller.ex

75 lines
2.4 KiB
Elixir

defmodule AsciinemaWeb.Api.AsciicastController do
use AsciinemaWeb, :controller
import AsciinemaWeb.Auth, only: [get_basic_auth: 1, put_basic_auth: 3]
alias Asciinema.{Asciicasts, Users}
alias Asciinema.Users.User
plug :parse_v0_params
plug :authenticate
def create(conn, %{"asciicast" => %Plug.Upload{} = upload}) do
do_create(conn, upload)
end
def create(conn, %{"asciicast" => %{"meta" => %{},
"stdout" => %Plug.Upload{},
"stdout_timing" => %Plug.Upload{}} = asciicast_params}) do
do_create(conn, asciicast_params)
end
defp do_create(conn, params) do
user = conn.assigns.current_user
user_agent = conn |> get_req_header("user-agent") |> List.first
case Asciicasts.create_asciicast(user, params, %{user_agent: user_agent}) do
{:ok, asciicast} ->
url = asciicast_url(conn, :show, asciicast)
conn
|> put_status(:created)
|> put_resp_header("location", url)
|> text(url)
{:error, :parse_error} ->
conn
|> put_status(:bad_request)
|> text("This doesn't look like a valid asciicast file")
{:error, :unknown_format} ->
conn
|> put_status(:unsupported_media_type)
|> text("Format not supported")
{:error, %Ecto.Changeset{} = changeset} ->
conn
|> put_status(:unprocessable_entity)
|> render("error.json", changeset: changeset)
end
end
defp parse_v0_params(%Plug.Conn{params: %{"asciicast" => %{"meta" => %Plug.Upload{path: meta_path}}}} = conn, _) do
with {:ok, json} <- File.read(meta_path),
{:ok, attrs} <- Poison.decode(json) do
conn
|> put_param(["asciicast", "meta"], Map.put(attrs, "version", 0))
|> put_basic_auth(attrs["username"], attrs["user_token"])
else
{:error, :invalid} ->
send_resp(conn, 400, "")
end
end
defp parse_v0_params(conn, _), do: conn
defp put_param(%Plug.Conn{params: params} = conn, path, value) do
params = put_in(params, path, value)
%{conn | params: params}
end
defp authenticate(conn, _opts) do
with {username, api_token} <- get_basic_auth(conn),
{:ok, %User{} = user} <- Users.get_user_with_api_token(api_token, username) do
assign(conn, :current_user, user)
else
_otherwise ->
conn
|> send_resp(401, "Invalid or revoked recorder token")
|> halt()
end
end
end