all developments of milestone 1
This commit is contained in:
@@ -9,7 +9,8 @@ defmodule Mobilizon.Admin do
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.{Admin, Users}
|
||||
alias Mobilizon.Admin.ActionLog
|
||||
alias Mobilizon.Admin.Setting
|
||||
alias Mobilizon.Admin.{Setting, SettingMedia}
|
||||
alias Mobilizon.Medias.Media
|
||||
alias Mobilizon.Storage.{Page, Repo}
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
@@ -78,9 +79,47 @@ defmodule Mobilizon.Admin do
|
||||
|
||||
defp stringify_struct(struct), do: struct
|
||||
|
||||
@spec get_all_admin_settings :: list(Setting.t())
|
||||
@spec get_all_admin_settings :: map()
|
||||
def get_all_admin_settings do
|
||||
Repo.all(Setting)
|
||||
medias =
|
||||
SettingMedia
|
||||
|> Repo.all()
|
||||
|> Repo.preload(:media)
|
||||
|> Enum.map(fn %SettingMedia{group: group, name: name, media: media} ->
|
||||
{group, name, media}
|
||||
end)
|
||||
|
||||
values =
|
||||
Setting
|
||||
|> Repo.all()
|
||||
|> Enum.map(fn %Setting{group: group, name: name, value: value} ->
|
||||
{group, name, get_setting_value(value)}
|
||||
end)
|
||||
|
||||
all_settings = Enum.concat(values, medias)
|
||||
|
||||
Enum.reduce(
|
||||
all_settings,
|
||||
%{},
|
||||
# For each {group,name,value}
|
||||
fn {group, name, value}, acc ->
|
||||
# We update the %{group: map} in the accumulator
|
||||
{_, new_acc} =
|
||||
Map.get_and_update(
|
||||
acc,
|
||||
group,
|
||||
# We put the %{name: value} into the %{group: map}
|
||||
fn group_map ->
|
||||
{
|
||||
group_map,
|
||||
Map.put(group_map || %{}, name, value)
|
||||
}
|
||||
end
|
||||
)
|
||||
|
||||
new_acc
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
@spec get_admin_setting_value(String.t(), String.t(), String.t() | nil) ::
|
||||
@@ -119,21 +158,40 @@ defmodule Mobilizon.Admin do
|
||||
end
|
||||
end
|
||||
|
||||
@spec get_admin_setting_media(String.t(), String.t(), String.t() | nil) ::
|
||||
{:ok, Media.t()} | {:error, :not_found} | nil
|
||||
def get_admin_setting_media(group, name, fallback \\ nil)
|
||||
when is_binary(group) and is_binary(name) do
|
||||
case SettingMedia
|
||||
|> where(group: ^group)
|
||||
|> where(name: ^name)
|
||||
|> preload(:media)
|
||||
|> Repo.one() do
|
||||
nil ->
|
||||
fallback
|
||||
|
||||
%SettingMedia{media: media} ->
|
||||
media
|
||||
|
||||
%SettingMedia{} ->
|
||||
fallback
|
||||
end
|
||||
end
|
||||
|
||||
@spec save_settings(String.t(), map()) :: {:ok, any} | {:error, any}
|
||||
def save_settings(group, args) do
|
||||
{medias, values} = Map.split(args, [:instance_logo, :instance_favicon, :default_picture])
|
||||
|
||||
Multi.new()
|
||||
|> do_save_setting(group, args)
|
||||
|> do_save_media_setting(group, medias)
|
||||
|> do_save_value_setting(group, values)
|
||||
|> Repo.transaction()
|
||||
end
|
||||
|
||||
def clear_settings(group) do
|
||||
Setting |> where([s], s.group == ^group) |> Repo.delete_all()
|
||||
end
|
||||
@spec do_save_value_setting(Ecto.Multi.t(), String.t(), map()) :: Ecto.Multi.t()
|
||||
defp do_save_value_setting(transaction, _group, args) when args == %{}, do: transaction
|
||||
|
||||
@spec do_save_setting(Ecto.Multi.t(), String.t(), map()) :: Ecto.Multi.t()
|
||||
defp do_save_setting(transaction, _group, args) when args == %{}, do: transaction
|
||||
|
||||
defp do_save_setting(transaction, group, args) do
|
||||
defp do_save_value_setting(transaction, group, args) do
|
||||
key = hd(Map.keys(args))
|
||||
{val, rest} = Map.pop(args, key)
|
||||
|
||||
@@ -150,7 +208,40 @@ defmodule Mobilizon.Admin do
|
||||
conflict_target: [:group, :name]
|
||||
)
|
||||
|
||||
do_save_setting(transaction, group, rest)
|
||||
do_save_value_setting(transaction, group, rest)
|
||||
end
|
||||
|
||||
@spec do_save_media_setting(Ecto.Multi.t(), String.t(), map()) :: Ecto.Multi.t()
|
||||
defp do_save_media_setting(transaction, _group, args) when args == %{}, do: transaction
|
||||
|
||||
defp do_save_media_setting(transaction, group, args) do
|
||||
key = hd(Map.keys(args))
|
||||
{val, rest} = Map.pop(args, key)
|
||||
|
||||
transaction =
|
||||
case val do
|
||||
val ->
|
||||
Multi.insert(
|
||||
transaction,
|
||||
key,
|
||||
SettingMedia.changeset(%SettingMedia{}, %{
|
||||
group: group,
|
||||
name: Atom.to_string(key),
|
||||
media: val
|
||||
}),
|
||||
on_conflict: :replace_all,
|
||||
conflict_target: [:group, :name]
|
||||
)
|
||||
end
|
||||
|
||||
do_save_media_setting(transaction, group, rest)
|
||||
end
|
||||
|
||||
def clear_settings(group) do
|
||||
Multi.new()
|
||||
|> Multi.delete_all(:settings, Setting |> where([s], s.group == ^group))
|
||||
|> Multi.delete_all(:settings_medias, SettingMedia |> where([s], s.group == ^group))
|
||||
|> Repo.transaction()
|
||||
end
|
||||
|
||||
@spec convert_to_string(any()) :: String.t()
|
||||
|
||||
@@ -4,6 +4,7 @@ defmodule Mobilizon.Admin.Setting do
|
||||
"""
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
alias Ecto.Changeset
|
||||
|
||||
@required_attrs [:group, :name]
|
||||
@optional_attrs [:value]
|
||||
@@ -32,3 +33,93 @@ defmodule Mobilizon.Admin.Setting do
|
||||
|> unique_constraint(:group, name: :admin_settings_group_name_index)
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Mobilizon.Admin.SettingMedia do
|
||||
@moduledoc """
|
||||
A Key-Value settings table for media settings
|
||||
"""
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
alias Ecto.Changeset
|
||||
alias Mobilizon.Federation.ActivityPub.Relay
|
||||
alias Mobilizon.Medias
|
||||
alias Mobilizon.Medias.Media
|
||||
alias Mobilizon.Storage.Repo
|
||||
|
||||
@required_attrs [:group, :name]
|
||||
|
||||
@type t :: %{
|
||||
group: String.t(),
|
||||
name: String.t(),
|
||||
media: Media.t()
|
||||
}
|
||||
|
||||
schema "admin_settings_medias" do
|
||||
field(:group, :string)
|
||||
field(:name, :string)
|
||||
belongs_to(:media, Media, on_replace: :delete)
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
||||
@doc false
|
||||
@spec changeset(t | Ecto.Schema.t(), map) :: Ecto.Changeset.t()
|
||||
def changeset(setting_media, attrs) do
|
||||
setting_media
|
||||
|> Repo.preload(:media)
|
||||
|> cast(attrs, @required_attrs)
|
||||
|> put_media(attrs)
|
||||
|> validate_required(@required_attrs)
|
||||
|> unique_constraint(:group, name: :admin_settings_medias_group_name_index)
|
||||
end
|
||||
|
||||
# # In case the provided media is an existing one
|
||||
@spec put_media(Changeset.t(), map) :: Changeset.t()
|
||||
defp put_media(%Changeset{} = changeset, %{media: %{media_id: id}}) do
|
||||
%Media{} = media = Medias.get_media!(id)
|
||||
put_assoc(changeset, :media, media)
|
||||
end
|
||||
|
||||
# In case it's a new media
|
||||
defp put_media(%Changeset{} = changeset, %{media: %{media: media}}) do
|
||||
{:ok, media} = upload_media(media)
|
||||
put_assoc(changeset, :media, media)
|
||||
end
|
||||
|
||||
# In case there is no media
|
||||
defp put_media(%Changeset{} = changeset, _media) do
|
||||
put_assoc(changeset, :media, nil)
|
||||
end
|
||||
|
||||
import Mobilizon.Web.Gettext
|
||||
@spec upload_media(map) :: {:ok, Media.t()} | {:error, any}
|
||||
defp upload_media(%{file: %Plug.Upload{} = file} = args) do
|
||||
with {:ok,
|
||||
%{
|
||||
name: _name,
|
||||
url: url,
|
||||
content_type: content_type,
|
||||
size: size
|
||||
} = uploaded} <-
|
||||
Mobilizon.Web.Upload.store(file),
|
||||
args <-
|
||||
args
|
||||
|> Map.put(:url, url)
|
||||
|> Map.put(:size, size)
|
||||
|> Map.put(:content_type, content_type),
|
||||
{:ok, media = %Media{}} <-
|
||||
Medias.create_media(%{
|
||||
file: args,
|
||||
actor_id: Map.get(args, :actor_id, Relay.get_actor().id),
|
||||
metadata: Map.take(uploaded, [:width, :height, :blurhash])
|
||||
}) do
|
||||
{:ok, media}
|
||||
else
|
||||
{:error, :mime_type_not_allowed} ->
|
||||
{:error, dgettext("errors", "File doesn't have an allowed MIME type.")}
|
||||
|
||||
error ->
|
||||
{:error, error}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user