defmodule Sukaato.StandardQueries do alias Sukaato.{Repo, User, Post} alias SukaatoWeb.Marker import Ecto.Changeset import Ecto.Query @rel_proj_root "../.." @site_config_file Path.expand(@rel_proj_root <> "/site.toml", __DIR__) @site_config Toml.decode_file(@site_config_file) @admin_username elem(@site_config, 1)["site"]["username"] @markdown_user_root Path.expand("../../lib/sukaato_web/controllers/page_md/users", __DIR__) @tables %{ user: User, post: Post } def add_entry(schema, type \\ :user) do case type do :user -> entry = @tables.user.changeset(%User{}, schema) result = Repo.insert(entry, on_conflict: {:replace_all_except, [:id, :slug, :inserted_at, :updated_at]}) result end end def get_admin() do query = from u in @tables.user, select: {u.username, u.perms} results = Repo.all(query) results = Enum.filter(results, fn r -> Enum.at(elem(r, 1), length(elem(r, 1)) - 1) == 15 end) results = Enum.map(results, fn r -> elem(r, 0) end) results end @doc """ Gets the GPG public keys of the given user. """ def get_pubkeys(username \\ @admin_username, gpg_id \\ "") do query = from u in @tables.user, select: u.pub_keys, where: u.username == ^username pubkeys = Repo.all(query) if pubkeys != nil do if length(pubkeys) > 0 do if gpg_id != "" do pubkeys = Enum.filter(pubkeys, fn k -> Map.has_key?(k, gpg_id) end) if length(pubkeys) > 0 do pubkeys = Enum.map(pubkeys, fn k -> {gpg_id, k[gpg_id]} end) {:ok, pubkeys} else {:ok, [{gpg_id, pubkeys}]} end else key_choices = Enum.map(pubkeys, fn k -> Enum.random(Map.keys(k)) end) selection = Enum.zip([key_choices, pubkeys]) pubkeys = Enum.map(selection, fn s -> {elem(s, 0), elem(s, 1)[elem(s, 0)]} end) {:ok, pubkeys} end else {:ok, [{gpg_id, ""}]} end else {:ok, [{gpg_id, ""}]} end # {:ok, {username, gpg_id, ""}} end @doc """ Gets and compiles a list of affiliate links or protocol addresses for the givn user. """ def get_inboxes(username \\ @admin_username, filter_protocols \\ [], method \\ :reject) do query = from u in @tables.user, select: u.email, where: u.username == ^username emails = Repo.all(query) query = from u in @tables.user, select: u.affil, where: u.username == ^username addresses = Repo.all(query) # @TODO create a database changeset schema for this in 'lib/sukaato/vschemas.ex' emails = Enum.map(emails, fn e -> %{"name" => "EMAIL", "address" => e, "protocol" => "mailto", "scheme_postfix" => ":", "icon_uri" => "", "icon_name" => "envelope-solid"} end) if length(filter_protocols) > 0 do filter = filter_protocols addresses = if method == :reject, do: Enum.filter(addresses, fn a -> !Enum.member?(filter, a.protocol) end), else: Enum.filter(addresses, fn a -> Enum.member?(filter, a.protocol) end) inboxes = [emails | addresses] # inboxes = Enum.map(inboxes, fn i -> for {k, v} <- i, into: %{}, do: {String.to_atom(k), v} end) {:ok, inboxes} else inboxes = [emails | addresses] # inboxes = addresses {:ok, inboxes} end end def verify_login_token(token) when is_binary(token) do token = String.split(token, ":", parts: 2) username = Enum.at(token, 0) query = from u in @tables.user, select: u.user_token, where: u.username == ^username db_token = Repo.one(query) if is_nil(db_token) do false else match_token = Enum.at(token, 1) match_token == db_token end end def absorb_login_token(token) when is_binary(token) do token = String.split(token, ":", parts: 2) username = Enum.at(token, 0) query = from u in @tables.user, where: u.username == ^username result = Repo.one(query) if is_nil(result) do {:ok, result} else token = Enum.at(token, 1) demand = change(result, user_token: token) result = Repo.update(demand) {:ok, result} end end def dump_login_token(token) when is_binary(token) do token = String.split(token, ":", parts: 2) username = Enum.at(token, 0) query = from u in @tables.user, where: u.username == ^username result = Repo.one(query) demand = if is_nil(result), do: result, else: change(result, user_token: nil) result = if is_nil(demand), do: demand, else: Repo.update(demand) result end defp synchronize_posts(for_user, path \\ "") do user_posts = if path != "", do: Path.wildcard(path), else: Path.wildcard(@markdown_user_root <> "/" <> for_user <> "/posts/*.md") if length(user_posts) > 0 do # user_posts = if !is_list(user_posts), do: [user_posts], else: user_posts user_posts = Enum.map(user_posts, fn p -> Path.basename(p) end) user_posts = Enum.map(user_posts, fn p -> Marker.render_mark(p, :markdown_post, for_user) end) user_posts = Enum.filter(user_posts, fn p -> elem(p, 0) == :ok end) user_posts = Enum.map(user_posts, fn p -> Map.put(elem(p, 1), "content", elem(p, 2)) end) user_posts = Enum.map(user_posts, fn p -> if Map.has_key?(p, "ledit"), do: Map.put(p, "ledit", Date.from_iso8601!(p["ledit"])), else: p end) # user_posts = Enum.map(user_posts, fn p -> if Map.has_key?(p, "auth_id"), do: Map.put(p, "auth_id", elem(Integer.parse(p["auth_id"]), 0)), else: p end) # user_posts = Enum.map(user_posts, fn p -> if Map.has_key?(p, "rev_id"), do: Map.put(p, "rev_id", elem(Integer.parse(p["auth_id"]), 0)), else: p end) user_posts = Map.new(user_posts, fn {k, v} -> {String.to_atom(k), v} end) # @TODO push user_posts to database user_posts = Enum.map(user_posts, fn p -> @tables.post.changeset(%Post{}, p) end) results = Repo.insert_all(@tables.post, user_posts, on_conflict: {:replace_all_except, [:id, :slug, :inserted_at, :updated_at]}) results else {:ok, user_posts} end end def synchronize(sync_source \\ :storage, for_user \\ @admin_username) do if is_atom(sync_source) do case sync_source do :storage -> results = synchronize_posts(for_user) results end end if is_binary(sync_source) do results = synchronize_posts(for_user, sync_source) results end end end