mirror of
https://github.com/zoldar/jenot.git
synced 2026-01-06 23:32:54 +00:00
197 lines
4.6 KiB
Elixir
197 lines
4.6 KiB
Elixir
defmodule Jenot.Web do
|
|
@moduledoc """
|
|
Web server
|
|
"""
|
|
|
|
use Plug.Router
|
|
|
|
alias Jenot.Accounts
|
|
alias Jenot.Notes
|
|
|
|
@template_dir "lib/jenot/templates"
|
|
|
|
@templates @template_dir
|
|
|> File.ls!()
|
|
|> Enum.map(fn file ->
|
|
{
|
|
String.replace_suffix(file, ".html.heex", ".html"),
|
|
File.read!(Path.join(@template_dir, file))
|
|
}
|
|
end)
|
|
|> Map.new()
|
|
|
|
if Mix.env() == :dev do
|
|
plug PlugLiveReload
|
|
end
|
|
|
|
plug Plug.Logger
|
|
|
|
plug :service_worker_header
|
|
|
|
plug Plug.Static,
|
|
at: "/",
|
|
only: ~w(img js index.html test.html site.webmanifest style.css),
|
|
from: {:jenot, "priv/static"}
|
|
|
|
plug Plug.Parsers,
|
|
parsers: [:urlencoded, :json],
|
|
pass: ["*/*"],
|
|
json_decoder: Jason
|
|
|
|
plug :put_secret_key_base
|
|
|
|
plug :match
|
|
plug :dispatch
|
|
|
|
get "/" do
|
|
conn
|
|
|> resp(:found, "")
|
|
|> put_resp_header("location", "/index.html")
|
|
end
|
|
|
|
post "/account/new" do
|
|
case Accounts.new() do
|
|
{:ok, %{code: code, account: account}} ->
|
|
conn
|
|
|> Accounts.set_cookie(account.id)
|
|
|> render("new_account.html", name: account.name, code: code)
|
|
|
|
{:error, _} ->
|
|
conn
|
|
|> Accounts.clear_cookie()
|
|
|> resp(:found, "")
|
|
|> put_resp_header("location", "/index.html")
|
|
end
|
|
end
|
|
|
|
get "/account/authenticate" do
|
|
render(conn, "account_authenticate.html", error: nil)
|
|
end
|
|
|
|
post "/account/authenticate" do
|
|
case Accounts.authenticate(conn.params["name"], conn.params["code"]) do
|
|
{:ok, account} ->
|
|
conn
|
|
|> Accounts.set_cookie(account.id)
|
|
|> resp(:found, "")
|
|
|> put_resp_header("location", "/index.html?reset-meta")
|
|
|
|
{:error, _} ->
|
|
conn
|
|
|> put_status(422)
|
|
|> render("account_authenticate.html", error: "Account not found")
|
|
end
|
|
end
|
|
|
|
post "/account/logout" do
|
|
conn
|
|
|> Accounts.clear_cookie()
|
|
|> resp(:found, "")
|
|
|> put_resp_header("location", "/index.html?reset-meta")
|
|
end
|
|
|
|
get "/api" do
|
|
send_resp(conn, 200, """
|
|
Jenot API says hi!
|
|
""")
|
|
end
|
|
|
|
get "/api/latest" do
|
|
{:ok, account} = Accounts.get_by_cookie(conn)
|
|
|
|
send_resp(conn, 200, Jason.encode!(%{notes: Notes.latest_change(account)}))
|
|
end
|
|
|
|
get "/api/notes" do
|
|
{:ok, account} = Accounts.get_by_cookie(conn)
|
|
|
|
notes =
|
|
account
|
|
|> Notes.all(conn.params["since"], conn.params["deleted"] == "true")
|
|
|> Enum.map(&Notes.serialize/1)
|
|
|
|
send_resp(conn, 200, Jason.encode!(notes))
|
|
end
|
|
|
|
get "/api/notes/:internal_id" do
|
|
{:ok, account} = Accounts.get_by_cookie(conn)
|
|
|
|
case Notes.note_by_internal_id(account, internal_id) do
|
|
{:ok, note} ->
|
|
note = Notes.serialize(note)
|
|
send_resp(conn, 200, Jason.encode!(note))
|
|
|
|
{:error, :note_not_found} ->
|
|
send_resp(conn, 404, Jason.encode!(%{error: "Note not found"}))
|
|
end
|
|
end
|
|
|
|
post "/api/notes" do
|
|
{:ok, account} = Accounts.get_by_cookie(conn)
|
|
|
|
case Notes.add(account, conn.params) do
|
|
{:ok, note} ->
|
|
send_resp(conn, 200, Jason.encode!(Notes.serialize(note)))
|
|
|
|
{:error, _} ->
|
|
send_resp(conn, 422, Jason.encode!(%{error: "Invalid input data"}))
|
|
end
|
|
end
|
|
|
|
put "/api/notes/:internal_id" do
|
|
{:ok, account} = Accounts.get_by_cookie(conn)
|
|
|
|
case Notes.update(account, internal_id, conn.params) do
|
|
{:ok, note} ->
|
|
send_resp(conn, 200, Jason.encode!(Notes.serialize(note)))
|
|
|
|
{:error, :note_not_found} ->
|
|
send_resp(conn, 422, Jason.encode!(%{error: "Note does not exist"}))
|
|
|
|
{:error, :invalid_data} ->
|
|
send_resp(conn, 422, Jason.encode!(%{error: "Invalid input data"}))
|
|
end
|
|
end
|
|
|
|
delete "/api/notes/:internal_id" do
|
|
{:ok, account} = Accounts.get_by_cookie(conn)
|
|
|
|
:ok = Notes.delete(account, internal_id)
|
|
|
|
send_resp(conn, 200, Jason.encode!(%{deleted: true}))
|
|
end
|
|
|
|
get "/api/push/public-key" do
|
|
public_key = Application.fetch_env!(:web_push_elixir, :vapid_public_key)
|
|
send_resp(conn, 200, Jason.encode!(%{public_key: public_key}))
|
|
end
|
|
|
|
post "/api/push/subscribe" do
|
|
send_resp(conn, 200, "")
|
|
end
|
|
|
|
post "/api/push/unsubscribe" do
|
|
send_resp(conn, 200, "")
|
|
end
|
|
|
|
match _ do
|
|
send_resp(conn, 404, "not found")
|
|
end
|
|
|
|
defp service_worker_header(conn, _opts) do
|
|
put_resp_header(conn, "service-worker-allowed", "/")
|
|
end
|
|
|
|
defp render(%{status: status} = conn, template, assigns) do
|
|
body =
|
|
@templates
|
|
|> Map.fetch!(template)
|
|
|> EEx.eval_string(assigns)
|
|
|
|
send_resp(conn, status || 200, body)
|
|
end
|
|
|
|
def put_secret_key_base(conn, _) do
|
|
put_in(conn.secret_key_base, Application.fetch_env!(:jenot, :secret_key_base))
|
|
end
|
|
end
|