Various typespec and compilation improvements
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -9,17 +9,20 @@ defmodule Mobilizon.Web.Auth.Context do
|
||||
alias Mobilizon.Service.ErrorReporting.Sentry, as: SentryAdapter
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
@spec init(Plug.opts()) :: Plug.opts()
|
||||
def init(opts) do
|
||||
opts
|
||||
end
|
||||
|
||||
@spec call(Plug.Conn.t(), Plug.opts()) :: Plug.Conn.t()
|
||||
def call(%{assigns: %{ip: _}} = conn, _opts), do: conn
|
||||
|
||||
def call(conn, _opts) do
|
||||
set_user_information_in_context(conn)
|
||||
end
|
||||
|
||||
def set_user_information_in_context(conn) do
|
||||
@spec set_user_information_in_context(Plug.Conn.t()) :: Plug.Conn.t()
|
||||
defp set_user_information_in_context(conn) do
|
||||
context = %{ip: conn.remote_ip |> :inet.ntoa() |> to_string()}
|
||||
|
||||
{conn, context} =
|
||||
|
||||
11
lib/web/cache/cache.ex
vendored
11
lib/web/cache/cache.ex
vendored
@@ -4,16 +4,19 @@ defmodule Mobilizon.Web.Cache do
|
||||
"""
|
||||
|
||||
alias Mobilizon.Actors.Actor
|
||||
|
||||
alias Mobilizon.Web.Cache.ActivityPub
|
||||
import Mobilizon.Service.Guards, only: [is_valid_string: 1]
|
||||
|
||||
@caches [:activity_pub, :feed, :ics]
|
||||
|
||||
@type local_actor :: %Actor{domain: nil}
|
||||
|
||||
@doc """
|
||||
Clears all caches for an actor.
|
||||
Clears all caches for a local actor.
|
||||
"""
|
||||
@spec clear_cache(Actor.t()) :: {:ok, true}
|
||||
def clear_cache(%Actor{preferred_username: preferred_username, domain: nil}) do
|
||||
@spec clear_cache(%Actor{domain: nil, preferred_username: String.t()}) :: :ok
|
||||
def clear_cache(%Actor{preferred_username: preferred_username, domain: nil})
|
||||
when is_valid_string(preferred_username) do
|
||||
Enum.each(@caches, &Cachex.del(&1, "actor_" <> preferred_username))
|
||||
end
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ defmodule Mobilizon.Web.GraphQLSocket do
|
||||
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
@spec connect(map, Phoenix.Socket.t()) :: {:ok, Phoenix.Socket.t()} | :error
|
||||
def connect(%{"token" => token}, socket) do
|
||||
with {:ok, authed_socket} <-
|
||||
Guardian.Phoenix.Socket.authenticate(socket, Mobilizon.Web.Auth.Guardian, token),
|
||||
@@ -26,5 +27,6 @@ defmodule Mobilizon.Web.GraphQLSocket do
|
||||
|
||||
def connect(_args, _socket), do: :error
|
||||
|
||||
@spec id(any) :: nil
|
||||
def id(_socket), do: nil
|
||||
end
|
||||
|
||||
@@ -12,7 +12,7 @@ defmodule Mobilizon.Web.Email.Activity do
|
||||
alias Mobilizon.Config
|
||||
alias Mobilizon.Web.Email
|
||||
|
||||
@spec direct_activity(String.t(), list(), String.t()) ::
|
||||
@spec direct_activity(String.t(), list(), Keyword.t()) ::
|
||||
Bamboo.Email.t()
|
||||
def direct_activity(
|
||||
email,
|
||||
|
||||
@@ -5,6 +5,7 @@ defmodule Mobilizon.Web.Email.Mailer do
|
||||
use Bamboo.Mailer, otp_app: :mobilizon
|
||||
alias Mobilizon.Service.ErrorReporting.Sentry
|
||||
|
||||
@spec send_email_later(Bamboo.Email.t()) :: Bamboo.Email.t()
|
||||
def send_email_later(email) do
|
||||
Mobilizon.Web.Email.Mailer.deliver_later!(email)
|
||||
rescue
|
||||
@@ -17,6 +18,7 @@ defmodule Mobilizon.Web.Email.Mailer do
|
||||
reraise error, __STACKTRACE__
|
||||
end
|
||||
|
||||
@spec send_email(Bamboo.Email.t()) :: Bamboo.Email.t() | {Bamboo.Email.t(), any()}
|
||||
def send_email(email) do
|
||||
Mobilizon.Web.Email.Mailer.deliver_now!(email)
|
||||
rescue
|
||||
|
||||
@@ -50,7 +50,6 @@ defmodule Mobilizon.Web.Email.Participation do
|
||||
Bamboo.Email.t()
|
||||
def participation_updated(user, participant, locale \\ "en")
|
||||
|
||||
@spec participation_updated(User.t(), Participant.t(), String.t()) :: Bamboo.Email.t()
|
||||
def participation_updated(
|
||||
%User{email: email},
|
||||
%Participant{} = participant,
|
||||
@@ -58,7 +57,6 @@ defmodule Mobilizon.Web.Email.Participation do
|
||||
),
|
||||
do: participation_updated(email, participant, locale)
|
||||
|
||||
@spec participation_updated(String.t(), Participant.t(), String.t()) :: Bamboo.Email.t()
|
||||
def participation_updated(
|
||||
email,
|
||||
%Participant{event: event, role: :rejected},
|
||||
@@ -79,7 +77,6 @@ defmodule Mobilizon.Web.Email.Participation do
|
||||
|> render(:event_participation_rejected)
|
||||
end
|
||||
|
||||
@spec participation_updated(String.t(), Participant.t(), String.t()) :: Bamboo.Email.t()
|
||||
def participation_updated(
|
||||
email,
|
||||
%Participant{event: %Event{join_options: :free} = event, role: :participant},
|
||||
@@ -100,7 +97,6 @@ defmodule Mobilizon.Web.Email.Participation do
|
||||
|> render(:event_participation_confirmed)
|
||||
end
|
||||
|
||||
@spec participation_updated(String.t(), Participant.t(), String.t()) :: Bamboo.Email.t()
|
||||
def participation_updated(
|
||||
email,
|
||||
%Participant{event: event, role: :participant},
|
||||
|
||||
@@ -57,6 +57,7 @@ defmodule Mobilizon.Web.Email.User do
|
||||
|> render(:password_reset)
|
||||
end
|
||||
|
||||
@spec check_confirmation_token(String.t()) :: {:ok, User.t()} | {:error, :invalid_token}
|
||||
def check_confirmation_token(token) when is_binary(token) do
|
||||
with %User{} = user <- Users.get_user_by_activation_token(token),
|
||||
{:ok, %User{} = user} <-
|
||||
@@ -86,7 +87,7 @@ defmodule Mobilizon.Web.Email.User do
|
||||
end
|
||||
end
|
||||
|
||||
@spec send_confirmation_email(User.t(), String.t()) :: {:ok, Bamboo.Email.t()} | {:error, any()}
|
||||
@spec send_confirmation_email(User.t(), String.t()) :: Bamboo.Email.t()
|
||||
def send_confirmation_email(%User{} = user, locale \\ "en") do
|
||||
user
|
||||
|> Email.User.confirmation_email(locale)
|
||||
@@ -96,7 +97,8 @@ defmodule Mobilizon.Web.Email.User do
|
||||
@doc """
|
||||
Check that the provided token is correct and update provided password
|
||||
"""
|
||||
@spec check_reset_password_token(String.t(), String.t()) :: tuple
|
||||
@spec check_reset_password_token(String.t(), String.t()) ::
|
||||
{:ok, User.t()} | {:error, String.t()}
|
||||
def check_reset_password_token(password, token) do
|
||||
with %User{} = user <- Users.get_user_by_reset_password_token(token),
|
||||
{:ok, %User{} = user} <-
|
||||
|
||||
@@ -21,8 +21,8 @@ defmodule Mobilizon.Web do
|
||||
quote do
|
||||
use Phoenix.Controller, namespace: Mobilizon.Web
|
||||
import Plug.Conn
|
||||
import Mobilizon.Web.Router.Helpers
|
||||
import Mobilizon.Web.Gettext
|
||||
alias Mobilizon.Web.Router.Helpers, as: Routes
|
||||
end
|
||||
end
|
||||
|
||||
@@ -33,14 +33,13 @@ defmodule Mobilizon.Web do
|
||||
pattern: "**/*",
|
||||
namespace: Mobilizon.Web
|
||||
|
||||
# Import convenience functions from controllers
|
||||
import Phoenix.Controller, only: [get_flash: 2, view_module: 1]
|
||||
|
||||
# Use all HTML functionality (forms, tags, etc)
|
||||
use Phoenix.HTML
|
||||
|
||||
import Mobilizon.Web.Router.Helpers
|
||||
import Phoenix.View
|
||||
import Mobilizon.Web.ErrorHelpers
|
||||
import Mobilizon.Web.Gettext
|
||||
alias Mobilizon.Web.Router.Helpers, as: Routes
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -19,12 +19,13 @@ defmodule Mobilizon.Web.Plugs.HTTPSecurityPlug do
|
||||
if Config.get([:http_security, :enabled]) do
|
||||
conn
|
||||
|> merge_resp_headers(headers(options))
|
||||
|> maybe_send_sts_header(Config.get([:http_security, :sts]))
|
||||
|> maybe_send_sts_header(Config.get([:http_security, :sts], false))
|
||||
else
|
||||
conn
|
||||
end
|
||||
end
|
||||
|
||||
@spec headers(Keyword.t()) :: list({String.t(), String.t()})
|
||||
defp headers(options) do
|
||||
referrer_policy =
|
||||
Keyword.get(options, :referrer_policy, Config.get([:http_security, :referrer_policy]))
|
||||
@@ -55,6 +56,7 @@ defmodule Mobilizon.Web.Plugs.HTTPSecurityPlug do
|
||||
@style_src "style-src 'self' "
|
||||
@font_src "font-src 'self' "
|
||||
|
||||
@spec csp_string(Keyword.t()) :: String.t()
|
||||
defp csp_string(options) do
|
||||
scheme = Keyword.get(options, :scheme, Config.get([Pleroma.Web.Endpoint, :url])[:scheme])
|
||||
static_url = Mobilizon.Web.Endpoint.static_url()
|
||||
@@ -115,10 +117,11 @@ defmodule Mobilizon.Web.Plugs.HTTPSecurityPlug do
|
||||
|> to_string()
|
||||
end
|
||||
|
||||
@spec add_csp_param(list(), list(String.t()) | String.t() | nil) :: list()
|
||||
defp add_csp_param(csp_iodata, nil), do: csp_iodata
|
||||
|
||||
defp add_csp_param(csp_iodata, param), do: [[param, ?;] | csp_iodata]
|
||||
|
||||
@spec maybe_send_sts_header(Plug.Conn.t(), boolean()) :: Plug.Conn.t()
|
||||
defp maybe_send_sts_header(conn, true) do
|
||||
max_age_sts = Config.get([:http_security, :sts_max_age])
|
||||
|
||||
@@ -127,8 +130,9 @@ defmodule Mobilizon.Web.Plugs.HTTPSecurityPlug do
|
||||
])
|
||||
end
|
||||
|
||||
defp maybe_send_sts_header(conn, _), do: conn
|
||||
defp maybe_send_sts_header(conn, false), do: conn
|
||||
|
||||
@spec get_csp_config(atom(), Keyword.t()) :: String.t()
|
||||
defp get_csp_config(type, options) do
|
||||
options
|
||||
|> Keyword.get(type, Config.get([:http_security, :csp_policy, type]))
|
||||
|
||||
@@ -16,6 +16,7 @@ defmodule Mobilizon.Web.Plugs.HTTPSignatures do
|
||||
options
|
||||
end
|
||||
|
||||
@spec call(Plug.Conn.t(), any) :: Plug.Conn.t()
|
||||
def call(%{assigns: %{valid_signature: true}} = conn, _opts) do
|
||||
conn
|
||||
end
|
||||
|
||||
@@ -45,11 +45,13 @@ defmodule Mobilizon.Web.Plugs.UploadedMedia do
|
||||
|
||||
config = Config.get([Upload])
|
||||
|
||||
with uploader <- Keyword.fetch!(config, :uploader),
|
||||
proxy_remote = Keyword.get(config, :proxy_remote, false),
|
||||
{:ok, get_method} <- uploader.get_file(file) do
|
||||
get_media(conn, get_method, proxy_remote, opts)
|
||||
else
|
||||
uploader = Keyword.fetch!(config, :uploader)
|
||||
proxy_remote = Keyword.get(config, :proxy_remote, false)
|
||||
|
||||
case uploader.get_file(file) do
|
||||
{:ok, get_method} ->
|
||||
get_media(conn, get_method, proxy_remote, opts)
|
||||
|
||||
_ ->
|
||||
conn
|
||||
|> send_resp(500, "Failed")
|
||||
@@ -59,6 +61,12 @@ defmodule Mobilizon.Web.Plugs.UploadedMedia do
|
||||
|
||||
def call(conn, _opts), do: conn
|
||||
|
||||
@spec get_media(
|
||||
Plug.Conn.t(),
|
||||
{:static_dir, String.t()} | {:url, String.t()} | any(),
|
||||
boolean,
|
||||
any()
|
||||
) :: Plug.Conn.t()
|
||||
defp get_media(conn, {:static_dir, directory}, _, opts) do
|
||||
static_opts =
|
||||
opts
|
||||
|
||||
@@ -381,6 +381,10 @@ defmodule Mobilizon.Web.ReverseProxy do
|
||||
|
||||
defp body_size_constraint(_, _), do: :ok
|
||||
|
||||
@spec check_read_duration(any(), integer()) ::
|
||||
{:ok, {integer(), integer()}}
|
||||
| {:ok, :no_duration_limit, :no_duration_limit}
|
||||
| {:error, :read_duration_exceeded}
|
||||
defp check_read_duration(duration, max)
|
||||
when is_integer(duration) and is_integer(max) and max > 0 do
|
||||
if duration > max do
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
event: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:event,
|
||||
@activity.subject_params["event_uuid"]
|
||||
@@ -20,7 +20,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
event: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:event,
|
||||
@activity.subject_params["event_uuid"]
|
||||
@@ -37,7 +37,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
event: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:event,
|
||||
@activity.subject_params["event_uuid"]
|
||||
@@ -52,7 +52,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
event: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:event,
|
||||
@activity.subject_params["event_uuid"]
|
||||
|
||||
@@ -4,22 +4,22 @@
|
||||
event: @activity.subject_params["event_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% :participation_event_comment -> %><%= dgettext("activity", "%{profile} has posted an announcement under event %{event}.",
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% :participation_event_comment -> %><%= dgettext("activity", "%{profile} has posted an announcement under event %{event}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
event: @activity.subject_params["event_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% :event_new_comment -> %><%= if @activity.subject_params["comment_reply_to"] do %><%=dgettext("activity", "%{profile} has posted a new reply under your event %{event}.",
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% :event_new_comment -> %><%= if @activity.subject_params["comment_reply_to"] do %><%=dgettext("activity", "%{profile} has posted a new reply under your event %{event}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
event: @activity.subject_params["event_title"]
|
||||
}
|
||||
) %>
|
||||
<%= "#{page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode()}#comment-#{@activity.subject_params["comment_reply_to_uuid"]}-#{@activity.subject_params["comment_uuid"]}" %><% else %><%= dgettext("activity", "%{profile} has posted a new comment under your event %{event}.",
|
||||
<%= "#{Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode()}#comment-#{@activity.subject_params["comment_reply_to_uuid"]}-#{@activity.subject_params["comment_uuid"]}" %><% else %><%= dgettext("activity", "%{profile} has posted a new comment under your event %{event}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
event: @activity.subject_params["event_title"]
|
||||
}
|
||||
) %>
|
||||
<%= "#{page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode()}#comment-#{@activity.subject_params["comment_uuid"]}"%><% end %><% end %>
|
||||
<%= "#{Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode()}#comment-#{@activity.subject_params["comment_uuid"]}"%><% end %><% end %>
|
||||
@@ -5,7 +5,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
discussion: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:discussion,
|
||||
Mobilizon.Actors.Actor.preferred_username_and_domain(@activity.group), @activity.subject_params["discussion_slug"]
|
||||
@@ -19,7 +19,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
discussion: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:discussion,
|
||||
Mobilizon.Actors.Actor.preferred_username_and_domain(@activity.group), @activity.subject_params["discussion_slug"]
|
||||
@@ -33,7 +33,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
discussion: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:discussion,
|
||||
Mobilizon.Actors.Actor.preferred_username_and_domain(@activity.group), @activity.subject_params["discussion_slug"]
|
||||
@@ -47,7 +47,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
discussion: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:discussion,
|
||||
Mobilizon.Actors.Actor.preferred_username_and_domain(@activity.group), @activity.subject_params["discussion_slug"]
|
||||
|
||||
@@ -4,25 +4,25 @@
|
||||
discussion: @activity.subject_params["discussion_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :discussion, Mobilizon.Actors.Actor.preferred_username_and_domain(@activity.group), @activity.subject_params["discussion_slug"]) |> URI.decode() %><% :discussion_replied -> %><%= dgettext("activity", "%{profile} replied to the discussion %{discussion}.",
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :discussion, Mobilizon.Actors.Actor.preferred_username_and_domain(@activity.group), @activity.subject_params["discussion_slug"]) |> URI.decode() %><% :discussion_replied -> %><%= dgettext("activity", "%{profile} replied to the discussion %{discussion}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
discussion: @activity.subject_params["discussion_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :discussion, Mobilizon.Actors.Actor.preferred_username_and_domain(@activity.group), @activity.subject_params["discussion_slug"]) |> URI.decode() %><% :discussion_renamed -> %><%= dgettext("activity", "%{profile} renamed the discussion %{discussion}.",
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :discussion, Mobilizon.Actors.Actor.preferred_username_and_domain(@activity.group), @activity.subject_params["discussion_slug"]) |> URI.decode() %><% :discussion_renamed -> %><%= dgettext("activity", "%{profile} renamed the discussion %{discussion}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
discussion: @activity.subject_params["discussion_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :discussion, Mobilizon.Actors.Actor.preferred_username_and_domain(@activity.group), @activity.subject_params["discussion_slug"]) |> URI.decode() %><% :discussion_archived -> %><%= dgettext("activity", "%{profile} archived the discussion %{discussion}.",
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :discussion, Mobilizon.Actors.Actor.preferred_username_and_domain(@activity.group), @activity.subject_params["discussion_slug"]) |> URI.decode() %><% :discussion_archived -> %><%= dgettext("activity", "%{profile} archived the discussion %{discussion}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
discussion: @activity.subject_params["discussion_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :discussion, Mobilizon.Actors.Actor.preferred_username_and_domain(@activity.group), @activity.subject_params["discussion_slug"]) |> URI.decode() %><% :discussion_deleted -> %><%= dgettext("activity", "%{profile} deleted the discussion %{discussion}.",
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :discussion, Mobilizon.Actors.Actor.preferred_username_and_domain(@activity.group), @activity.subject_params["discussion_slug"]) |> URI.decode() %><% :discussion_deleted -> %><%= dgettext("activity", "%{profile} deleted the discussion %{discussion}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
discussion: @activity.subject_params["discussion_title"]
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
event: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:event,
|
||||
@activity.subject_params["event_uuid"]
|
||||
@@ -20,7 +20,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
event: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:event,
|
||||
@activity.subject_params["event_uuid"]
|
||||
@@ -44,7 +44,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
event: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:event,
|
||||
@activity.subject_params["event_uuid"]
|
||||
@@ -59,7 +59,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
event: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:event,
|
||||
@activity.subject_params["event_uuid"]
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
event: @activity.subject_params["event_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% :event_updated -> %><%= dgettext("activity", "The event %{event} was updated by %{profile}.",
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% :event_updated -> %><%= dgettext("activity", "The event %{event} was updated by %{profile}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
event: @activity.subject_params["event_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% :event_deleted -> %><%= dgettext("activity", "The event %{event} was deleted by %{profile}.",
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% :event_deleted -> %><%= dgettext("activity", "The event %{event} was deleted by %{profile}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
event: @activity.subject_params["event_title"]
|
||||
@@ -22,10 +22,10 @@
|
||||
event: @activity.subject_params["event_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% else %><%= dgettext("activity", "%{profile} posted a comment on the event %{event}.",
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% else %><%= dgettext("activity", "%{profile} posted a comment on the event %{event}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
event: @activity.subject_params["event_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% end %><% end %>
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% end %><% end %>
|
||||
@@ -5,7 +5,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
group: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:actor,
|
||||
@activity.subject_params["group_federated_username"]
|
||||
@@ -20,7 +20,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
group: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:actor,
|
||||
@activity.subject_params["group_federated_username"]
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
group: @activity.subject_params["group_name"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :actor, @activity.subject_params["group_federated_username"]) |> URI.decode() %><% :group_updated -> %><%= dgettext("activity", "%{profile} updated the group %{group}.",
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :actor, @activity.subject_params["group_federated_username"]) |> URI.decode() %><% :group_updated -> %><%= dgettext("activity", "%{profile} updated the group %{group}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
group: @activity.subject_params["group_name"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :actor, @activity.subject_params["group_federated_username"]) |> URI.decode() %><% end %>
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :actor, @activity.subject_params["group_federated_username"]) |> URI.decode() %><% end %>
|
||||
@@ -5,7 +5,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
post: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:post,
|
||||
@activity.subject_params["post_slug"]
|
||||
@@ -20,7 +20,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
post: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:post,
|
||||
@activity.subject_params["post_slug"]
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
post: @activity.subject_params["post_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :post, @activity.subject_params["post_slug"]) |> URI.decode() %><% :post_updated -> %><%= dgettext("activity", "The post %{post} was updated by %{profile}.",
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :post, @activity.subject_params["post_slug"]) |> URI.decode() %><% :post_updated -> %><%= dgettext("activity", "The post %{post} was updated by %{profile}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
post: @activity.subject_params["post_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :post, @activity.subject_params["post_slug"]) |> URI.decode() %><% :post_deleted -> %><%= dgettext("activity", "The post %{post} was deleted by %{profile}.",
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :post, @activity.subject_params["post_slug"]) |> URI.decode() %><% :post_deleted -> %><%= dgettext("activity", "The post %{post} was deleted by %{profile}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
post: @activity.subject_params["post_title"]
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
resource: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:resource,
|
||||
@activity.subject_params["resource_uuid"]
|
||||
@@ -21,7 +21,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
resource: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:resource,
|
||||
@activity.subject_params["resource_uuid"]
|
||||
@@ -38,7 +38,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
resource: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:resource,
|
||||
@activity.subject_params["resource_uuid"]
|
||||
@@ -54,7 +54,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
resource: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:resource,
|
||||
@activity.subject_params["resource_uuid"]
|
||||
@@ -72,7 +72,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
resource: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:resource,
|
||||
@activity.subject_params["resource_uuid"]
|
||||
@@ -87,7 +87,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
resource: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:resource,
|
||||
@activity.subject_params["resource_uuid"]
|
||||
|
||||
@@ -5,39 +5,39 @@
|
||||
resource: @activity.subject_params["resource_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :resource, @activity.subject_params["resource_uuid"]) |> URI.decode() %><% else %><%= dgettext("activity", "%{profile} created the resource %{resource}.",
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :resource, @activity.subject_params["resource_uuid"]) |> URI.decode() %><% else %><%= dgettext("activity", "%{profile} created the resource %{resource}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
resource: @activity.subject_params["resource_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :resource, @activity.subject_params["resource_uuid"]) |> URI.decode() %><% end %><% :resource_renamed -> %><%= if @activity.subject_params["is_folder"] do %><%= dgettext("activity", "%{profile} renamed the folder from %{old_resource_title} to %{resource}.",
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :resource, @activity.subject_params["resource_uuid"]) |> URI.decode() %><% end %><% :resource_renamed -> %><%= if @activity.subject_params["is_folder"] do %><%= dgettext("activity", "%{profile} renamed the folder from %{old_resource_title} to %{resource}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
resource: @activity.subject_params["resource_title"],
|
||||
old_resource_title: @activity.subject_params["old_resource_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :resource, @activity.subject_params["resource_uuid"]) |> URI.decode() %><% else %><%= dgettext("activity", "%{profile} renamed the resource from %{old_resource_title} to %{resource}.",
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :resource, @activity.subject_params["resource_uuid"]) |> URI.decode() %><% else %><%= dgettext("activity", "%{profile} renamed the resource from %{old_resource_title} to %{resource}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
resource: @activity.subject_params["resource_title"],
|
||||
old_resource_title: @activity.subject_params["old_resource_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :resource, @activity.subject_params["resource_uuid"]) |> URI.decode() %><% end %><% :resource_moved -> %><%= if @activity.subject_params["is_folder"] do %><%= dgettext("activity", "%{profile} moved the folder %{resource}.",
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :resource, @activity.subject_params["resource_uuid"]) |> URI.decode() %><% end %><% :resource_moved -> %><%= if @activity.subject_params["is_folder"] do %><%= dgettext("activity", "%{profile} moved the folder %{resource}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
resource: @activity.subject_params["resource_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :resource, @activity.subject_params["resource_uuid"]) |> URI.decode() %><% else %><%= dgettext("activity", "%{profile} moved the resource %{resource}.",
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :resource, @activity.subject_params["resource_uuid"]) |> URI.decode() %><% else %><%= dgettext("activity", "%{profile} moved the resource %{resource}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
resource: @activity.subject_params["resource_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :resource, @activity.subject_params["resource_uuid"]) |> URI.decode() %><% end %><% :resource_deleted -> %><%= if @activity.subject_params["is_folder"] do %><%= dgettext("activity", "%{profile} deleted the folder %{resource}.",
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :resource, @activity.subject_params["resource_uuid"]) |> URI.decode() %><% end %><% :resource_deleted -> %><%= if @activity.subject_params["is_folder"] do %><%= dgettext("activity", "%{profile} deleted the folder %{resource}.",
|
||||
%{
|
||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
||||
resource: @activity.subject_params["resource_title"]
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<td bgcolor="#ffffff" align="center" style="padding: 20px 30px 60px 30px;">
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#3C376E"><a href="<%= page_url(Mobilizon.Web.Endpoint, :participation_email_confirmation, @participant.metadata.confirmation_token) %>" target="_blank" style="font-size: 20px; font-family: 'Roboto', Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#3C376E"><a href="<%= Routes.page_url(Mobilizon.Web.Endpoint, :participation_email_confirmation, @participant.metadata.confirmation_token) %>" target="_blank" style="font-size: 20px; font-family: 'Roboto', Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<%= gettext "Confirm my e-mail address" %>
|
||||
</a></td>
|
||||
</tr>
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
==
|
||||
<%= gettext "Hi there! You just registered to join this event: « %{title} ». Please confirm the e-mail address you provided:", title: @participant.event.title %>
|
||||
<%= gettext "If you didn't trigger this email, you may safely ignore it." %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :participation_email_confirmation, @participant.metadata.confirmation_token) %>
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :participation_email_confirmation, @participant.metadata.confirmation_token) %>
|
||||
<%= ngettext "Would you wish to cancel your attendance, visit the event page through the link above and click the « Attending » button.", "Would you wish to cancel your attendance to one or several events, visit the event pages through the links above and click the « Attending » button.", 1 %>
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<td bgcolor="#ffffff" align="center" style="padding: 20px 30px 60px 30px;">
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#3C376E"><a href="<%= page_url(Mobilizon.Web.Endpoint, :event, @participant.event.uuid) %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#3C376E"><a href="<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @participant.event.uuid) %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<%= gettext "Go to event page" %>
|
||||
</a></td>
|
||||
</tr>
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
==
|
||||
<%= gettext "Get ready for %{title}", title: @participant.event.title %>
|
||||
<%= gettext "Go to event page" %>
|
||||
<%= gettext "View the event on: %{link}", link: page_url(Mobilizon.Web.Endpoint, :event, @participant.event.uuid) %>
|
||||
<%= gettext "View the event on: %{link}", link: Routes.page_url(Mobilizon.Web.Endpoint, :event, @participant.event.uuid) %>
|
||||
<%= gettext "If you wish to cancel your attendance, visit the event page through the link above and click the « Attending » button." %>
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
%{
|
||||
profile: "<b>#{Mobilizon.Actors.Actor.display_name_and_username(@activity.author)}</b>",
|
||||
event: "<a href=\"#{
|
||||
page_url(
|
||||
Routes.page_url(
|
||||
Mobilizon.Web.Endpoint,
|
||||
:event,
|
||||
@activity.subject_params["event_uuid"]
|
||||
@@ -63,7 +63,7 @@
|
||||
<td bgcolor="#ffffff" align="center" style="padding: 20px 30px 60px 30px;">
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#3C376E"><a href="<%= page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#3C376E"><a href="<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<%= gettext "Visit event page" %>
|
||||
</a></td>
|
||||
</tr>
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
event: @activity.subject_params["event_title"]
|
||||
}
|
||||
) %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %>
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %>
|
||||
@@ -47,7 +47,7 @@
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#3C376E">
|
||||
<a href="<%= page_url(Mobilizon.Web.Endpoint, :user_email_validation, @token) %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<a href="<%= Routes.page_url(Mobilizon.Web.Endpoint, :user_email_validation, @token) %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<%= gettext "Verify your email address" %>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<%= gettext "Confirm new email" %>
|
||||
==
|
||||
<%= gettext "Hi there! It seems like you wanted to change the email address linked to your account on <b>%{instance}</b>. If you still wish to do so, please click the button below to confirm the change. You will then be able to log in to %{instance} with this new email address.", %{instance: @instance_name} %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :user_email_validation, @token) %>
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :user_email_validation, @token) %>
|
||||
<%= gettext "If you didn't trigger the change yourself, please ignore this message." %>
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
<tr>
|
||||
<%= if hd(group_activities).group.avatar do %>
|
||||
<td width="85">
|
||||
<a href="<%= page_url(Mobilizon.Web.Endpoint, :actor, Mobilizon.Actors.Actor.preferred_username_and_domain(hd(group_activities).group)) |> URI.decode() %>" target="_blank" style="text-decoration: none;">
|
||||
<a href="<%= Routes.page_url(Mobilizon.Web.Endpoint, :actor, Mobilizon.Actors.Actor.preferred_username_and_domain(hd(group_activities).group)) |> URI.decode() %>" target="_blank" style="text-decoration: none;">
|
||||
<img width="80" src="<%= hd(group_activities).group.avatar.url %>" style="width: 80px;max-height: 100px;" style="margin:0; padding:0; border:none; display:block;" border="0" alt="" />
|
||||
</a>
|
||||
</td>
|
||||
@@ -73,7 +73,7 @@
|
||||
<table width="" cellpadding="0" cellspacing="0" border="0" style="max-width: 400px;width: 100%;" align="left">
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="<%= page_url(Mobilizon.Web.Endpoint, :actor, Mobilizon.Actors.Actor.preferred_username_and_domain(hd(group_activities).group)) |> URI.decode() %>" target="_blank" style="text-decoration: none;color: #474467;font-family: 'Roboto', Helvetica, Arial, sans-serif;font-size: 18px;font-weight: bold;line-height: 25px;">
|
||||
<a href="<%= Routes.page_url(Mobilizon.Web.Endpoint, :actor, Mobilizon.Actors.Actor.preferred_username_and_domain(hd(group_activities).group)) |> URI.decode() %>" target="_blank" style="text-decoration: none;color: #474467;font-family: 'Roboto', Helvetica, Arial, sans-serif;font-size: 18px;font-weight: bold;line-height: 25px;">
|
||||
<%= hd(group_activities).group.name || "@#{Mobilizon.Actors.Actor.preferred_username_and_domain(hd(group_activities).group)}" %>
|
||||
</a>
|
||||
</td>
|
||||
@@ -81,7 +81,7 @@
|
||||
<%= if hd(group_activities).group.name do %>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="<%= page_url(Mobilizon.Web.Endpoint, :actor, Mobilizon.Actors.Actor.preferred_username_and_domain(hd(group_activities).group)) |> URI.decode() %>" target="_blank" style="text-decoration: none;display: block;color: #7a7a7a;font-family: 'Roboto', Helvetica, Arial, sans-serif;font-size: 16px;font-weight: 400;line-height: 25px;">
|
||||
<a href="<%= Routes.page_url(Mobilizon.Web.Endpoint, :actor, Mobilizon.Actors.Actor.preferred_username_and_domain(hd(group_activities).group)) |> URI.decode() %>" target="_blank" style="text-decoration: none;display: block;color: #7a7a7a;font-family: 'Roboto', Helvetica, Arial, sans-serif;font-size: 16px;font-weight: 400;line-height: 25px;">
|
||||
@<%= Mobilizon.Actors.Actor.preferred_username_and_domain(hd(group_activities).group) %>
|
||||
</a>
|
||||
</td>
|
||||
@@ -131,7 +131,7 @@
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#3C376E">
|
||||
<a href="<%= page_url(Mobilizon.Web.Endpoint, :actor, Mobilizon.Actors.Actor.preferred_username_and_domain(hd(group_activities).group)) |> URI.decode() %>/timeline" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<a href="<%= Routes.page_url(Mobilizon.Web.Endpoint, :actor, Mobilizon.Actors.Actor.preferred_username_and_domain(hd(group_activities).group)) |> URI.decode() %>/timeline" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<%= dngettext "activity", "View one more activity", "View %{count} more activities", length(group_activities) - 5, %{count: length(group_activities) - 5} %>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<% end %>
|
||||
<%= if length(group_activities) > 5 do %>
|
||||
<%= dngettext "activity", "View one more activity", "View %{count} more activities", length(group_activities) - 5, %{count: length(group_activities) - 5} %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :actor, Mobilizon.Actors.Actor.preferred_username_and_domain(hd(group_activities).group)) |> URI.decode() %>/timeline
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :actor, Mobilizon.Actors.Actor.preferred_username_and_domain(hd(group_activities).group)) |> URI.decode() %>/timeline
|
||||
<% end %>
|
||||
<% end %>
|
||||
<%= dgettext("activity", "Don't want to receive activity notifications? You may change frequency or disable them in your settings.") %>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<td bgcolor="#ffffff" align="center" style="padding: 20px 30px 60px 30px;">
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#3C376E"><a href="<%= page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#3C376E"><a href="<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<%= gettext "Visit event page" %>
|
||||
</a></td>
|
||||
</tr>
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
|
||||
<%= gettext "Good news: one of the event organizers just approved your request. Update your calendar, because you're on the guest list now!" %>
|
||||
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) %>
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) %>
|
||||
|
||||
<%= gettext "Would you wish to update or cancel your attendance, simply access the event page through the link above and click on the Attending button." %>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<td bgcolor="#ffffff" align="center" style="padding: 20px 30px 60px 30px;">
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#3C376E"><a href="<%= page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#3C376E"><a href="<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<%= gettext "Visit event page" %>
|
||||
</a></td>
|
||||
</tr>
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
==
|
||||
<%= gettext "You recently requested to attend %{title}.", title: @event.title %>
|
||||
<%= gettext "You have confirmed your participation. Update your calendar, because you're on the guest list now!" %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) %>
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) %>
|
||||
<%= gettext "Would you wish to update or cancel your attendance, simply access the event page through the link above and click on the Attending button." %>
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
<td bgcolor="#ffffff" align="center" style="padding: 20px 30px 60px 30px;">
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#3C376E"><a href="<%= page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#3C376E"><a href="<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<%= gettext "Visit the updated event page" %>
|
||||
</a></td>
|
||||
</tr>
|
||||
|
||||
@@ -20,5 +20,5 @@
|
||||
<%= if MapSet.member?(@changes, :ends_on) && !is_nil(@event.ends_on) do %>
|
||||
<%= gettext "End %{ends_on}", ends_on: @event.ends_on |> datetime_tz_convert(@timezone) |> datetime_to_string(@locale) %>
|
||||
<% end %>
|
||||
<%= gettext "Visit the updated event page: %{link}", link: page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) %>
|
||||
<%= gettext "Visit the updated event page: %{link}", link: Routes.page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) %>
|
||||
<%= ngettext "Would you wish to cancel your attendance, visit the event page through the link above and click the « Attending » button.", "Would you wish to cancel your attendance to one or several events, visit the event pages through the links above and click the « Attending » button.", 1 %>
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#3C376E">
|
||||
<a href="<%= page_url(Mobilizon.Web.Endpoint, :my_groups) %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<a href="<%= Routes.page_url(Mobilizon.Web.Endpoint, :my_groups) %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<%= gettext "See my groups" %>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
<%= gettext "%{inviter} just invited you to join their group %{group}", group: @group.name, inviter: @inviter.name %>
|
||||
<%= @group.url %>
|
||||
<%= gettext "To accept this invitation, head over to your groups." %>
|
||||
<%= page_url(Mobilizon.Web.Endpoint, :my_groups) %>
|
||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :my_groups) %>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<strong>
|
||||
<%= participation.event.begins_on |> datetime_tz_convert(@timezone) |> datetime_to_string(@locale) %>
|
||||
</strong>
|
||||
<a href="<%= page_url(Mobilizon.Web.Endpoint, :event, participation.event.uuid) %>" target="_blank">
|
||||
<a href="<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, participation.event.uuid) %>" target="_blank">
|
||||
<%= participation.event.title %>
|
||||
</a>
|
||||
</li>
|
||||
@@ -58,7 +58,7 @@
|
||||
<strong>
|
||||
<%= @participation.event.begins_on |> datetime_tz_convert(@timezone) |> datetime_to_string(@locale) %>
|
||||
</strong>
|
||||
<a href="<%= page_url(Mobilizon.Web.Endpoint, :event, @participation.event.uuid) %>" target="_blank">
|
||||
<a href="<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @participation.event.uuid) %>" target="_blank">
|
||||
<%= @participation.event.title %>
|
||||
</a>
|
||||
<% end %>
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
<%= ngettext "You have one event this week:", "You have %{total} events this week:", @total, total: @total %>
|
||||
<%= if @total > 1 do %>
|
||||
<%= for participation <- @participations do %>
|
||||
- <%= participation.event.begins_on |> datetime_tz_convert(@timezone) |> datetime_to_string(@locale) %> - <%= participation.event.title %> <%= page_url(Mobilizon.Web.Endpoint, :event, participation.event.uuid) %>
|
||||
- <%= participation.event.begins_on |> datetime_tz_convert(@timezone) |> datetime_to_string(@locale) %> - <%= participation.event.title %> <%= Routes.page_url(Mobilizon.Web.Endpoint, :event, participation.event.uuid) %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= @participation.event.begins_on |> datetime_tz_convert(@timezone) |> datetime_to_string(@locale) %> - <%= @participation.event.title %> <%= page_url(Mobilizon.Web.Endpoint, :event, @participation.event.uuid) %>
|
||||
<%= @participation.event.begins_on |> datetime_tz_convert(@timezone) |> datetime_to_string(@locale) %> - <%= @participation.event.title %> <%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @participation.event.uuid) %>
|
||||
<% end %>
|
||||
<%= ngettext "Would you wish to cancel your attendance, visit the event page through the link above and click the « Attending » button.", "Would you wish to cancel your attendance to one or several events, visit the event pages through the links above and click the « Attending » button.", @total %>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<strong>
|
||||
<%= participation.event.begins_on |> DateTime.shift_zone!(@timezone) |> datetime_to_time_string(@locale) %>
|
||||
</strong>
|
||||
<a href="<%= page_url(Mobilizon.Web.Endpoint, :event, participation.event.uuid) %>" target="_blank">
|
||||
<a href="<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, participation.event.uuid) %>" target="_blank">
|
||||
<%= participation.event.title %>
|
||||
</a>
|
||||
</li>
|
||||
@@ -58,7 +58,7 @@
|
||||
<strong>
|
||||
<%= @participation.event.begins_on |> DateTime.shift_zone!(@timezone) |> datetime_to_time_string(@locale) %>
|
||||
</strong>
|
||||
<a href="<%= page_url(Mobilizon.Web.Endpoint, :event, @participation.event.uuid) %>" target="_blank">
|
||||
<a href="<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @participation.event.uuid) %>" target="_blank">
|
||||
<%= @participation.event.title %>
|
||||
</a>
|
||||
<% end %>
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
<%= if @total > 1 do %>
|
||||
<%= for participation <- @participations do %>
|
||||
- <%= participation.event.begins_on |> DateTime.shift_zone!(@timezone) |> datetime_to_time_string(@locale) %> - <%= participation.event.title %> <%= page_url(Mobilizon.Web.Endpoint, :event, participation.event.uuid) %>
|
||||
- <%= participation.event.begins_on |> DateTime.shift_zone!(@timezone) |> datetime_to_time_string(@locale) %> - <%= participation.event.title %> <%= Routes.page_url(Mobilizon.Web.Endpoint, :event, participation.event.uuid) %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= DateTime.shift_zone!(@participation.event.begins_on, @timezone) |> datetime_to_time_string(@locale) %> - <%= @participation.event.title %> <%= page_url(Mobilizon.Web.Endpoint, :event, @participation.event.uuid) %>
|
||||
<%= DateTime.shift_zone!(@participation.event.begins_on, @timezone) |> datetime_to_time_string(@locale) %> - <%= @participation.event.title %> <%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @participation.event.uuid) %>
|
||||
<% end %>
|
||||
|
||||
<%= ngettext "Would you wish to cancel your attendance, visit the event page through the link above and click the « Attending » button.", "Would you wish to cancel your attendance to one or several events, visit the event pages through the links above and click the « Attending » button.", @total %>
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#3C376E">
|
||||
<a href="<%= page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) <> "/participations" %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<a href="<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) <> "/participations" %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<%= gettext "Manage pending requests" %>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
|
||||
<%= ngettext "You have one pending attendance request to process:", "You have %{number_participation_requests} attendance requests to process:", @total, number_participation_requests: @total %>
|
||||
|
||||
<%= gettext "Manage pending requests" %> <%= page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) <> "/participations" %>
|
||||
<%= gettext "Manage pending requests" %> <%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) <> "/participations" %>
|
||||
|
||||
<%= gettext "You are receiving this email because you chose to get notifications for pending attendance requests to your events. You can disable or change your notification settings in your user account settings under « Notifications »." %>s
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
<td bgcolor="#ffffff" align="center" style="padding: 20px 30px 60px 30px;">
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#3C376E"><a href="<%= page_url(Mobilizon.Web.Endpoint, :moderation_report, @report.id) %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#3C376E"><a href="<%= Routes.page_url(Mobilizon.Web.Endpoint, :moderation_report, @report.id) %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #3C376E; display: inline-block;">
|
||||
<%= gettext "View report" %>
|
||||
</a></td>
|
||||
</tr>
|
||||
|
||||
@@ -21,4 +21,4 @@
|
||||
<%= gettext "Reason" %>
|
||||
<%= @report.content %>
|
||||
<% end %>
|
||||
<%= gettext "View report:" %> <%= page_url(Mobilizon.Web.Endpoint, :moderation_report, @report.id) %>
|
||||
<%= gettext "View report:" %> <%= Routes.page_url(Mobilizon.Web.Endpoint, :moderation_report, @report.id) %>
|
||||
|
||||
@@ -13,7 +13,7 @@ defmodule Mobilizon.Web.Upload.Filter.AnalyzeMetadata do
|
||||
@behaviour Mobilizon.Web.Upload.Filter
|
||||
|
||||
@spec filter(Upload.t()) ::
|
||||
{:ok, :filtered, Upload.t()} | {:ok, :noop} | {:error, String.t()}
|
||||
{:ok, :filtered, Upload.t()} | {:ok, :noop}
|
||||
def filter(%Upload{tempfile: file, content_type: "image" <> _} = upload) do
|
||||
image =
|
||||
file
|
||||
|
||||
@@ -14,19 +14,27 @@ defmodule Mobilizon.Web.Upload.Filter.AnonymizeFilename do
|
||||
|
||||
alias Mobilizon.Config
|
||||
alias Mobilizon.Web.Upload
|
||||
alias Mobilizon.Web.Upload.Filter
|
||||
import Mobilizon.Service.Guards, only: [is_valid_string: 1]
|
||||
|
||||
@impl Filter
|
||||
@spec filter(any) :: {:ok, :filtered, Upload.t()} | {:ok, :noop}
|
||||
def filter(%Upload{name: name} = upload) do
|
||||
extension = List.last(String.split(name, "."))
|
||||
name = predefined_name(extension) || random(extension)
|
||||
name = predefined_name(extension)
|
||||
name = if is_nil(name), do: random(extension), else: name
|
||||
{:ok, :filtered, %Upload{upload | name: name}}
|
||||
end
|
||||
|
||||
@impl Filter
|
||||
def filter(_), do: {:ok, :noop}
|
||||
|
||||
@spec predefined_name(String.t()) :: String.t() | nil
|
||||
defp predefined_name(extension) do
|
||||
with name when not is_nil(name) <- Config.get([__MODULE__, :text]),
|
||||
do: String.replace(name, "{extension}", extension)
|
||||
case Config.get([__MODULE__, :text]) do
|
||||
name when is_valid_string(name) -> String.replace(name, "{extension}", extension)
|
||||
_ -> nil
|
||||
end
|
||||
end
|
||||
|
||||
defp random(extension) do
|
||||
|
||||
@@ -8,7 +8,7 @@ defmodule Mobilizon.Web.Upload.Filter.BlurHash do
|
||||
@behaviour Mobilizon.Web.Upload.Filter
|
||||
|
||||
@spec filter(Upload.t()) ::
|
||||
{:ok, :filtered, Upload.t()} | {:ok, :noop} | {:error, String.t()}
|
||||
{:ok, :filtered, Upload.t()} | {:ok, :noop}
|
||||
def filter(%Upload{tempfile: file, content_type: "image" <> _} = upload) do
|
||||
{:ok, :filtered, %Upload{upload | blurhash: generate_blurhash(file)}}
|
||||
rescue
|
||||
|
||||
@@ -10,6 +10,7 @@ defmodule Mobilizon.Web.Upload.Filter.Dedupe do
|
||||
@behaviour Mobilizon.Web.Upload.Filter
|
||||
alias Mobilizon.Web.Upload
|
||||
|
||||
@spec filter(Upload.t()) :: {:ok, :filtered, Upload.t()} | {:ok, :noop}
|
||||
def filter(%Upload{name: name, tempfile: tempfile} = upload) do
|
||||
extension = name |> String.split(".") |> List.last()
|
||||
shasum = :crypto.hash(:sha256, File.read!(tempfile)) |> Base.encode16(case: :lower)
|
||||
|
||||
@@ -11,7 +11,7 @@ defmodule Mobilizon.Web.Upload.Filter.Exiftool do
|
||||
|
||||
@behaviour Mobilizon.Web.Upload.Filter
|
||||
|
||||
@spec filter(Upload.t()) :: {:ok, any()} | {:error, String.t()}
|
||||
@spec filter(Upload.t()) :: {:ok, :filtered | :noop} | {:error, String.t()}
|
||||
|
||||
# webp is not compatible with exiftool at this time
|
||||
def filter(%Upload{content_type: "image/webp"}), do: {:ok, :noop}
|
||||
|
||||
@@ -20,11 +20,10 @@ defmodule Mobilizon.Web.Upload.Filter do
|
||||
{:ok, :filtered}
|
||||
| {:ok, :noop}
|
||||
| {:ok, :filtered, Mobilizon.Web.Upload.t()}
|
||||
| {:error, any()}
|
||||
| {:error, String.t() | atom}
|
||||
|
||||
@spec filter([module()], Mobilizon.Web.Upload.t()) ::
|
||||
{:ok, Mobilizon.Web.Upload.t()} | {:error, any()}
|
||||
|
||||
{:ok, Mobilizon.Web.Upload.t()} | {:error, String.t() | atom}
|
||||
def filter([], upload) do
|
||||
{:ok, upload}
|
||||
end
|
||||
|
||||
@@ -15,7 +15,7 @@ defmodule Mobilizon.Web.Upload.Filter.Mogrify do
|
||||
@type conversion :: action :: String.t() | {action :: String.t(), opts :: String.t()}
|
||||
@type conversions :: conversion() | [conversion()]
|
||||
|
||||
@spec filter(Mobilizon.Web.Upload.t()) :: {:ok, :atom} | {:error, String.t()}
|
||||
@spec filter(Mobilizon.Web.Upload.t()) :: {:ok, :filtered | :noop} | {:error, String.t()}
|
||||
def filter(%Mobilizon.Web.Upload{tempfile: file, content_type: "image" <> _}) do
|
||||
do_filter(file, Config.get!([__MODULE__, :args]))
|
||||
{:ok, :filtered}
|
||||
|
||||
@@ -6,6 +6,8 @@ defmodule Mobilizon.Web.Upload.Filter.Optimize do
|
||||
@behaviour Mobilizon.Web.Upload.Filter
|
||||
|
||||
alias Mobilizon.Config
|
||||
alias Mobilizon.Web.Upload
|
||||
require Logger
|
||||
|
||||
@default_optimizers [
|
||||
JpegOptim,
|
||||
@@ -16,24 +18,24 @@ defmodule Mobilizon.Web.Upload.Filter.Optimize do
|
||||
Cwebp
|
||||
]
|
||||
|
||||
def filter(%Mobilizon.Web.Upload{tempfile: file, content_type: "image" <> _}) do
|
||||
@spec filter(Upload.t()) :: {:ok, :filtered | :noop} | {:error, :file_not_found}
|
||||
def filter(%Upload{tempfile: file, content_type: "image" <> _}) do
|
||||
optimizers = Config.get([__MODULE__, :optimizers], @default_optimizers)
|
||||
|
||||
case ExOptimizer.optimize(file, deps: optimizers) do
|
||||
{:ok, _res} ->
|
||||
{:ok, :filtered}
|
||||
|
||||
{:error, err} ->
|
||||
require Logger
|
||||
{:error, :file_not_found} ->
|
||||
Logger.warn("Unable to optimize file #{file}. File was not found")
|
||||
{:error, :file_not_found}
|
||||
|
||||
{:error, err} ->
|
||||
Logger.warn(
|
||||
"Unable to optimize file #{file}. The return from the process was #{inspect(err)}"
|
||||
)
|
||||
|
||||
{:ok, :noop}
|
||||
|
||||
err ->
|
||||
{:error, err}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ defmodule Mobilizon.Web.Upload.Filter.Resize do
|
||||
@maximum_width 1_920
|
||||
@maximum_height 1_080
|
||||
|
||||
@spec filter(Upload.t()) :: {:ok, :filtered, Upload.t()} | {:ok, :noop}
|
||||
def filter(
|
||||
%Upload{
|
||||
tempfile: file,
|
||||
@@ -31,6 +32,7 @@ defmodule Mobilizon.Web.Upload.Filter.Resize do
|
||||
|
||||
def filter(_), do: {:ok, :noop}
|
||||
|
||||
@spec limit_sizes({non_neg_integer, non_neg_integer}) :: {non_neg_integer, non_neg_integer}
|
||||
def limit_sizes({width, height}) when width > @maximum_width do
|
||||
new_height = round(@maximum_width * height / width)
|
||||
limit_sizes({@maximum_width, new_height})
|
||||
@@ -43,5 +45,6 @@ defmodule Mobilizon.Web.Upload.Filter.Resize do
|
||||
|
||||
def limit_sizes({width, height}), do: {width, height}
|
||||
|
||||
@spec string({non_neg_integer, non_neg_integer}) :: String.t()
|
||||
defp string({width, height}), do: "#{width}x#{height}"
|
||||
end
|
||||
|
||||
@@ -10,8 +10,9 @@ defmodule Mobilizon.Web.Upload.MIME do
|
||||
@default "application/octet-stream"
|
||||
@read_bytes 35
|
||||
|
||||
@spec file_mime_type(String.t()) ::
|
||||
@spec file_mime_type(String.t(), String.t()) ::
|
||||
{:ok, content_type :: String.t(), filename :: String.t()} | {:error, any()} | :error
|
||||
@spec file_mime_type(String.t()) :: {:ok, String.t()} | {:error, any()} | :error
|
||||
def file_mime_type(path, filename) do
|
||||
with {:ok, content_type} <- file_mime_type(path),
|
||||
filename when is_binary(filename) <- fix_extension(filename, content_type) do
|
||||
@@ -19,7 +20,6 @@ defmodule Mobilizon.Web.Upload.MIME do
|
||||
end
|
||||
end
|
||||
|
||||
@spec file_mime_type(String.t()) :: {:ok, String.t()} | {:error, any()} | :error
|
||||
def file_mime_type(filename) do
|
||||
File.open(filename, [:read], fn f ->
|
||||
check_mime_type(IO.binread(f, @read_bytes))
|
||||
|
||||
@@ -53,6 +53,7 @@ defmodule Mobilizon.Web.Upload do
|
||||
| {:size_limit, nil | non_neg_integer()}
|
||||
| {:uploader, module()}
|
||||
| {:filters, [module()]}
|
||||
| {:allow_list_mime_types, boolean()}
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
id: String.t(),
|
||||
@@ -65,33 +66,36 @@ defmodule Mobilizon.Web.Upload do
|
||||
height: integer(),
|
||||
blurhash: String.t()
|
||||
}
|
||||
defstruct [:id, :name, :tempfile, :content_type, :path, :size, :width, :height, :blurhash]
|
||||
defstruct [:id, :name, :url, :tempfile, :content_type, :path, :size, :width, :height, :blurhash]
|
||||
|
||||
@spec store(source, options :: [option()]) :: {:ok, map()} | {:error, any()}
|
||||
@typep internal_options :: %{
|
||||
activity_type: String.t() | nil,
|
||||
size_limit: integer(),
|
||||
uploader: module(),
|
||||
filters: [module()],
|
||||
description: String.t(),
|
||||
allow_list_mime_types: list(String.t()),
|
||||
base_url: String.t()
|
||||
}
|
||||
|
||||
@spec store(source, options :: [option()]) ::
|
||||
{:ok, map()} | {:error, String.t()} | {:error, atom()}
|
||||
def store(upload, opts \\ []) do
|
||||
opts = get_opts(opts)
|
||||
|
||||
with {:ok, upload} <- prepare_upload(upload, opts),
|
||||
%__MODULE__{} = upload <- %__MODULE__{
|
||||
upload
|
||||
| path: upload.path || "#{upload.id}/#{upload.name}"
|
||||
},
|
||||
{:ok, upload} <- Filter.filter(opts.filters, upload),
|
||||
{:ok, url_spec} <- Uploader.put_file(opts.uploader, upload) do
|
||||
{:ok,
|
||||
upload
|
||||
|> Map.put(:name, Map.get(opts, :description) || upload.name)
|
||||
|> Map.put(:url, url_from_spec(upload, opts.base_url, url_spec))}
|
||||
else
|
||||
{:error, error} ->
|
||||
Logger.error(
|
||||
"#{__MODULE__} store (using #{inspect(opts.uploader)}) failed: #{inspect(error)}"
|
||||
)
|
||||
case prepare_upload(upload, opts) do
|
||||
{:ok, upload} ->
|
||||
upload
|
||||
|> set_default_upload_path()
|
||||
|> perform_filter_and_put_file(opts)
|
||||
|
||||
{:error, error}
|
||||
{:error, error} ->
|
||||
error
|
||||
end
|
||||
end
|
||||
|
||||
@spec remove(String.t(), Keyword.t()) ::
|
||||
{:ok, String.t()} | {:error, atom} | {:error, String.t()}
|
||||
def remove(url, opts \\ []) do
|
||||
with opts <- get_opts(opts),
|
||||
%URI{path: "/media/" <> path, host: host} <- URI.parse(url),
|
||||
@@ -106,10 +110,52 @@ defmodule Mobilizon.Web.Upload do
|
||||
end
|
||||
end
|
||||
|
||||
def char_unescaped?(char) do
|
||||
@spec char_unescaped?(byte()) :: boolean()
|
||||
defp char_unescaped?(char) do
|
||||
URI.char_unreserved?(char) or char == ?/
|
||||
end
|
||||
|
||||
@spec set_default_upload_path(t) :: t
|
||||
defp set_default_upload_path(%__MODULE__{} = upload) do
|
||||
%__MODULE__{
|
||||
upload
|
||||
| path: upload.path || "#{upload.id}/#{upload.name}"
|
||||
}
|
||||
end
|
||||
|
||||
@spec perform_filter_and_put_file(t, map) ::
|
||||
{:ok, t} | {:error, String.t()} | {:error, atom()}
|
||||
defp perform_filter_and_put_file(%__MODULE__{} = upload, opts) do
|
||||
case Filter.filter(opts.filters, upload) do
|
||||
{:ok, upload} ->
|
||||
perform_put_file(upload, opts)
|
||||
|
||||
{:error, error} ->
|
||||
{:error, error}
|
||||
end
|
||||
end
|
||||
|
||||
@spec perform_put_file(t, map) :: {:ok, t} | {:error, atom()}
|
||||
defp perform_put_file(%__MODULE__{} = upload, opts) do
|
||||
case Uploader.put_file(opts.uploader, upload) do
|
||||
{:ok, url_spec} ->
|
||||
{:ok,
|
||||
%__MODULE__{
|
||||
upload
|
||||
| name: Map.get(opts, :description) || upload.name,
|
||||
url: url_from_spec(upload, opts.base_url, url_spec)
|
||||
}}
|
||||
|
||||
{:error, error} ->
|
||||
Logger.error(
|
||||
"#{__MODULE__} store (using #{inspect(opts.uploader)}) failed: #{inspect(error)}"
|
||||
)
|
||||
|
||||
{:error, error}
|
||||
end
|
||||
end
|
||||
|
||||
@spec get_opts(Keyword.t()) :: internal_options()
|
||||
defp get_opts(opts) do
|
||||
{size_limit, activity_type} =
|
||||
case Keyword.get(opts, :type) do
|
||||
@@ -144,6 +190,7 @@ defmodule Mobilizon.Web.Upload do
|
||||
}
|
||||
end
|
||||
|
||||
@spec prepare_upload(t(), internal_options()) :: {:ok, t()}
|
||||
defp prepare_upload(%Plug.Upload{} = file, opts) do
|
||||
with {:ok, size} <- check_file_size(file.path, opts.size_limit),
|
||||
{:ok, content_type, name} <- MIME.file_mime_type(file.path, file.filename),
|
||||
@@ -159,6 +206,7 @@ defmodule Mobilizon.Web.Upload do
|
||||
end
|
||||
end
|
||||
|
||||
@spec prepare_upload(%{body: String.t(), name: String.t()}, internal_options()) :: {:ok, t()}
|
||||
defp prepare_upload(%{body: body, name: name} = _file, opts) do
|
||||
with :ok <- check_binary_size(body, opts.size_limit),
|
||||
tmp_path <- tempfile_for_image(body),
|
||||
@@ -175,8 +223,10 @@ defmodule Mobilizon.Web.Upload do
|
||||
end
|
||||
end
|
||||
|
||||
@spec check_file_size(String.t(), non_neg_integer()) ::
|
||||
{:ok, non_neg_integer()} | {:error, :file_too_large} | {:error, :file.posix()}
|
||||
defp check_file_size(path, size_limit) when is_integer(size_limit) and size_limit > 0 do
|
||||
with {:ok, %{size: size}} <- File.stat(path),
|
||||
with {:ok, %File.Stat{size: size}} <- File.stat(path),
|
||||
true <- size <= size_limit do
|
||||
{:ok, size}
|
||||
else
|
||||
@@ -185,8 +235,7 @@ defmodule Mobilizon.Web.Upload do
|
||||
end
|
||||
end
|
||||
|
||||
defp check_file_size(_, _), do: :ok
|
||||
|
||||
@spec check_binary_size(String.t(), non_neg_integer()) :: :ok | {:error, :file_too_large}
|
||||
defp check_binary_size(binary, size_limit)
|
||||
when is_integer(size_limit) and size_limit > 0 and byte_size(binary) >= size_limit do
|
||||
{:error, :file_too_large}
|
||||
@@ -196,6 +245,7 @@ defmodule Mobilizon.Web.Upload do
|
||||
|
||||
# Creates a tempfile using the Plug.Upload Genserver which cleans them up
|
||||
# automatically.
|
||||
@spec tempfile_for_image(iodata) :: String.t()
|
||||
defp tempfile_for_image(data) do
|
||||
{:ok, tmp_path} = Plug.Upload.random_file("temp_files")
|
||||
{:ok, tmp_file} = File.open(tmp_path, [:write, :raw, :binary])
|
||||
@@ -204,6 +254,7 @@ defmodule Mobilizon.Web.Upload do
|
||||
tmp_path
|
||||
end
|
||||
|
||||
@spec url_from_spec(t, String.t(), {:file | :url, String.t()}) :: String.t()
|
||||
defp url_from_spec(%__MODULE__{name: name}, base_url, {:file, path}) do
|
||||
path =
|
||||
URI.encode(path, &char_unescaped?/1) <>
|
||||
|
||||
@@ -19,10 +19,24 @@ defmodule Mobilizon.Web.Upload.Uploader.Local do
|
||||
end
|
||||
|
||||
@impl true
|
||||
@spec put_file(Upload.t()) ::
|
||||
:ok | {:ok, {:file, String.t()}} | {:error, :tempfile_no_longer_exists}
|
||||
def put_file(%Upload{path: path, tempfile: tempfile}) do
|
||||
{path, file} = local_path(path)
|
||||
result_file = Path.join(path, file)
|
||||
|
||||
if File.exists?(result_file) do
|
||||
# If the resulting file already exists, it's because of the Dedupe filter
|
||||
:ok
|
||||
else
|
||||
if File.exists?(tempfile) do
|
||||
File.cp!(tempfile, result_file)
|
||||
{:ok, {:file, result_file}}
|
||||
else
|
||||
{:error, :tempfile_no_longer_exists}
|
||||
end
|
||||
end
|
||||
|
||||
with {:result_exists, false} <- {:result_exists, File.exists?(result_file)},
|
||||
{:temp_file_exists, true} <- {:temp_file_exists, File.exists?(tempfile)} do
|
||||
File.cp!(tempfile, result_file)
|
||||
@@ -37,28 +51,54 @@ defmodule Mobilizon.Web.Upload.Uploader.Local do
|
||||
end
|
||||
|
||||
@impl true
|
||||
@spec remove_file(String.t()) ::
|
||||
{:ok, {:file, String.t()}}
|
||||
| {:error, :folder_not_empty}
|
||||
| {:error, :enofile}
|
||||
| {:error, File.posix()}
|
||||
def remove_file(path) do
|
||||
with {path, file} <- local_path(path),
|
||||
full_path <- Path.join(path, file),
|
||||
true <- File.exists?(full_path),
|
||||
:ok <- File.rm(full_path),
|
||||
:ok <- remove_folder(path) do
|
||||
{:ok, path}
|
||||
{path, file} = local_path(path)
|
||||
full_path = Path.join(path, file)
|
||||
|
||||
if File.exists?(full_path) do
|
||||
do_remove_file(path, full_path)
|
||||
else
|
||||
false -> {:error, "File #{path} doesn't exist"}
|
||||
{:error, :enofile}
|
||||
end
|
||||
end
|
||||
|
||||
@spec do_remove_file(String.t(), String.t()) ::
|
||||
{:ok, {:file, String.t()}}
|
||||
| {:error, :folder_not_empty}
|
||||
| {:error, File.posix()}
|
||||
defp do_remove_file(path, full_path) do
|
||||
case File.rm(full_path) do
|
||||
:ok ->
|
||||
case remove_folder(path) do
|
||||
:ok ->
|
||||
{:ok, {:file, path}}
|
||||
|
||||
{:error, err} ->
|
||||
{:error, err}
|
||||
end
|
||||
|
||||
{:error, err} ->
|
||||
{:error, err}
|
||||
end
|
||||
end
|
||||
|
||||
@spec remove_folder(String.t()) :: :ok | {:error, :folder_not_empty} | {:error, File.posix()}
|
||||
defp remove_folder(path) do
|
||||
with {:subfolder, true} <- {:subfolder, path != upload_path()},
|
||||
{:empty_folder, {:ok, [] = _files}} <- {:empty_folder, File.ls(path)} do
|
||||
File.rmdir(path)
|
||||
else
|
||||
{:subfolder, _} -> :ok
|
||||
{:empty_folder, _} -> {:error, "Error: Folder is not empty"}
|
||||
{:empty_folder, _} -> {:error, :folder_not_empty}
|
||||
end
|
||||
end
|
||||
|
||||
@spec local_path(String.t()) :: {String.t(), String.t()}
|
||||
defp local_path(path) do
|
||||
case Enum.reverse(String.split(path, "/", trim: true)) do
|
||||
[file] ->
|
||||
@@ -71,6 +111,7 @@ defmodule Mobilizon.Web.Upload.Uploader.Local do
|
||||
end
|
||||
end
|
||||
|
||||
@spec upload_path :: String.t()
|
||||
def upload_path do
|
||||
Config.get!([__MODULE__, :uploads])
|
||||
end
|
||||
|
||||
@@ -33,9 +33,9 @@ defmodule Mobilizon.Web.Upload.Uploader do
|
||||
"""
|
||||
@type file_spec :: {:file | :url, String.t()}
|
||||
@callback put_file(Mobilizon.Web.Upload.t()) ::
|
||||
:ok | {:ok, file_spec()} | {:error, String.t()} | :wait_callback
|
||||
:ok | {:ok, file_spec()} | {:error, atom()} | :wait_callback
|
||||
|
||||
@callback remove_file(file_spec()) :: :ok | {:ok, file_spec()} | {:error, String.t()}
|
||||
@callback remove_file(file_spec()) :: :ok | {:ok, file_spec()} | {:error, atom()}
|
||||
|
||||
@callback http_callback(Plug.Conn.t(), map()) ::
|
||||
{:ok, Plug.Conn.t()}
|
||||
@@ -43,7 +43,7 @@ defmodule Mobilizon.Web.Upload.Uploader do
|
||||
| {:error, Plug.Conn.t(), String.t()}
|
||||
@optional_callbacks http_callback: 2
|
||||
|
||||
@spec put_file(module(), Mobilizon.Web.Upload.t()) :: {:ok, file_spec()} | {:error, String.t()}
|
||||
@spec put_file(module(), Mobilizon.Web.Upload.t()) :: {:ok, file_spec()} | {:error, atom()}
|
||||
def put_file(uploader, upload) do
|
||||
case uploader.put_file(upload) do
|
||||
:ok -> {:ok, {:file, upload.path}}
|
||||
@@ -53,6 +53,7 @@ defmodule Mobilizon.Web.Upload.Uploader do
|
||||
end
|
||||
end
|
||||
|
||||
@spec remove_file(module(), String.t()) :: {:ok, String.t()} | {:error, atom()}
|
||||
def remove_file(uploader, path) do
|
||||
uploader.remove_file(path)
|
||||
end
|
||||
|
||||
@@ -70,7 +70,18 @@ defmodule Mobilizon.Web.ActivityPub.ActorView do
|
||||
}
|
||||
end
|
||||
|
||||
@spec fetch_collection(atom(), Actor.t(), integer()) :: Page.t()
|
||||
@type collection ::
|
||||
:following
|
||||
| :followers
|
||||
| :members
|
||||
| :resources
|
||||
| :discussions
|
||||
| :posts
|
||||
| :events
|
||||
| :todos
|
||||
| :outbox
|
||||
|
||||
@spec fetch_collection(collection(), Actor.t(), integer()) :: Page.t()
|
||||
defp fetch_collection(:following, actor, page) do
|
||||
Actors.build_followings_for_actor(actor, page)
|
||||
end
|
||||
@@ -103,7 +114,6 @@ defmodule Mobilizon.Web.ActivityPub.ActorView do
|
||||
Todos.get_todo_lists_for_group(actor, page)
|
||||
end
|
||||
|
||||
@spec fetch_collection(atom(), Actor.t(), integer()) :: %{total: integer(), elements: Enum.t()}
|
||||
defp fetch_collection(:outbox, actor, page) do
|
||||
ActivityPub.fetch_public_activities_for_actor(actor, page)
|
||||
end
|
||||
@@ -179,8 +189,7 @@ defmodule Mobilizon.Web.ActivityPub.ActorView do
|
||||
def item(%Event{} = event), do: Convertible.model_to_as(event)
|
||||
def item(%TodoList{} = todo_list), do: Convertible.model_to_as(todo_list)
|
||||
|
||||
defp actor_applicant_group_member?(%Actor{}, nil), do: false
|
||||
|
||||
@spec actor_applicant_group_member?(Actor.t(), Actor.t()) :: boolean()
|
||||
defp actor_applicant_group_member?(%Actor{id: group_id}, %Actor{id: actor_applicant_id}),
|
||||
do:
|
||||
Actors.get_member(actor_applicant_id, group_id, [
|
||||
|
||||
@@ -8,7 +8,7 @@ defmodule Mobilizon.Web.Views.Utils do
|
||||
import Plug.Conn, only: [put_status: 2, halt: 1]
|
||||
|
||||
# sobelow_skip ["Traversal.FileModule"]
|
||||
@spec inject_tags(Enum.t(), String.t()) :: {:ok, {:safe, String.t()}}
|
||||
@spec inject_tags(Enum.t(), String.t()) :: {:ok, {:safe, String.t()}} | {:error, atom()}
|
||||
def inject_tags(tags, locale \\ "en") do
|
||||
with path <- Path.join(Application.app_dir(:mobilizon, "priv/static"), "index.html"),
|
||||
{:exists, true} <- {:exists, File.exists?(path)},
|
||||
@@ -17,6 +17,7 @@ defmodule Mobilizon.Web.Views.Utils do
|
||||
{:ok, {:safe, safe}}
|
||||
else
|
||||
{:exists, false} -> {:error, :index_not_found}
|
||||
{:error, error} when is_atom(error) -> {:error, error}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user