Refactor Mobilizon.Federation.ActivityPub and add typespecs
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -5,6 +5,7 @@ defmodule Mobilizon.Web.Auth.ErrorHandler do
|
||||
import Plug.Conn
|
||||
|
||||
# sobelow_skip ["XSS.SendResp"]
|
||||
@spec auth_error(Plug.Conn.t(), any(), any()) :: Plug.Conn.t()
|
||||
def auth_error(conn, {type, _reason}, _opts) do
|
||||
body = Jason.encode!(%{message: to_string(type)})
|
||||
send_resp(conn, 401, body)
|
||||
|
||||
@@ -15,6 +15,7 @@ defmodule Mobilizon.Web.Auth.Guardian do
|
||||
|
||||
require Logger
|
||||
|
||||
@spec subject_for_token(any(), any()) :: {:ok, String.t()} | {:error, :unknown_resource}
|
||||
def subject_for_token(%User{} = user, _claims) do
|
||||
{:ok, "User:" <> to_string(user.id)}
|
||||
end
|
||||
@@ -45,30 +46,35 @@ defmodule Mobilizon.Web.Auth.Guardian do
|
||||
{:error, :no_claims}
|
||||
end
|
||||
|
||||
@spec after_encode_and_sign(any(), any(), any(), any()) :: {:ok, String.t()}
|
||||
def after_encode_and_sign(resource, claims, token, _options) do
|
||||
with {:ok, _} <- Guardian.DB.after_encode_and_sign(resource, claims["typ"], claims, token) do
|
||||
{:ok, token}
|
||||
end
|
||||
end
|
||||
|
||||
@spec on_verify(any(), any(), any()) :: {:ok, any()}
|
||||
def on_verify(claims, token, _options) do
|
||||
with {:ok, _} <- Guardian.DB.on_verify(claims, token) do
|
||||
{:ok, claims}
|
||||
end
|
||||
end
|
||||
|
||||
@spec on_revoke(any(), any(), any()) :: {:ok, any()}
|
||||
def on_revoke(claims, token, _options) do
|
||||
with {:ok, _} <- Guardian.DB.on_revoke(claims, token) do
|
||||
{:ok, claims}
|
||||
end
|
||||
end
|
||||
|
||||
@spec on_refresh({any(), any()}, {any(), any()}, any()) :: {:ok, {any(), any()}, {any(), any()}}
|
||||
def on_refresh({old_token, old_claims}, {new_token, new_claims}, _options) do
|
||||
with {:ok, _, _} <- Guardian.DB.on_refresh({old_token, old_claims}, {new_token, new_claims}) do
|
||||
{:ok, {old_token, old_claims}, {new_token, new_claims}}
|
||||
end
|
||||
end
|
||||
|
||||
@spec on_exchange(any(), any(), any()) :: {:ok, {any(), any()}, {any(), any()}}
|
||||
def on_exchange(old_stuff, new_stuff, options), do: on_refresh(old_stuff, new_stuff, options)
|
||||
|
||||
# def build_claims(claims, _resource, opts) do
|
||||
|
||||
@@ -9,6 +9,7 @@ defmodule Mobilizon.Web.AuthController do
|
||||
|
||||
plug(Ueberauth)
|
||||
|
||||
@spec request(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
||||
def request(conn, %{"provider" => provider_name} = _params) do
|
||||
case provider_config(provider_name) do
|
||||
{:ok, provider_config} ->
|
||||
@@ -20,6 +21,7 @@ defmodule Mobilizon.Web.AuthController do
|
||||
end
|
||||
end
|
||||
|
||||
@spec callback(Plug.Conn.t(), map()) :: Plug.Conn.t() | {:error, any()}
|
||||
def callback(
|
||||
%{assigns: %{ueberauth_failure: fails}} = conn,
|
||||
%{"provider" => provider} = _params
|
||||
@@ -85,6 +87,7 @@ defmodule Mobilizon.Web.AuthController do
|
||||
|
||||
# Github only give public emails as part of the user profile,
|
||||
# so we explicitely request all user emails and filter on the primary one
|
||||
@spec email_from_ueberauth(Ueberauth.Auth.t()) :: String.t() | nil
|
||||
defp email_from_ueberauth(%Ueberauth.Auth{
|
||||
strategy: Ueberauth.Strategy.Github,
|
||||
extra: %Ueberauth.Auth.Extra{raw_info: %{user: %{"emails" => emails}}}
|
||||
@@ -100,6 +103,7 @@ defmodule Mobilizon.Web.AuthController do
|
||||
|
||||
defp email_from_ueberauth(_), do: nil
|
||||
|
||||
@spec provider_config(String.t()) :: {:ok, any()} | {:error, :not_supported | :unknown_error}
|
||||
defp provider_config(provider_name) do
|
||||
with ueberauth when is_list(ueberauth) <- Application.get_env(:ueberauth, Ueberauth),
|
||||
providers when is_list(providers) <- Keyword.get(ueberauth, :providers),
|
||||
|
||||
@@ -6,6 +6,7 @@ defmodule Mobilizon.Web.FallbackController do
|
||||
"""
|
||||
use Mobilizon.Web, :controller
|
||||
|
||||
@spec call(Plug.Conn.t(), {:error, :not_found}) :: Plug.Conn.t()
|
||||
def call(conn, {:error, :not_found}) do
|
||||
conn
|
||||
|> put_status(:not_found)
|
||||
|
||||
@@ -7,6 +7,7 @@ defmodule Mobilizon.Web.FeedController do
|
||||
action_fallback(Mobilizon.Web.FallbackController)
|
||||
alias Mobilizon.Config
|
||||
|
||||
@spec instance(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
||||
def instance(conn, %{"format" => format}) do
|
||||
if Config.get([:instance, :enable_instance_feeds], false) do
|
||||
return_data(conn, format, "instance", Config.instance_name())
|
||||
@@ -15,6 +16,7 @@ defmodule Mobilizon.Web.FeedController do
|
||||
end
|
||||
end
|
||||
|
||||
@spec actor(Plug.Conn.t(), map()) :: Plug.Conn.t() | {:error, :not_found}
|
||||
def actor(conn, %{"format" => format, "name" => name}) do
|
||||
return_data(conn, format, "actor_" <> name, name)
|
||||
end
|
||||
@@ -23,14 +25,17 @@ defmodule Mobilizon.Web.FeedController do
|
||||
{:error, :not_found}
|
||||
end
|
||||
|
||||
@spec event(Plug.Conn.t(), map()) :: Plug.Conn.t() | {:error, :not_found}
|
||||
def event(conn, %{"uuid" => uuid, "format" => "ics"}) do
|
||||
return_data(conn, "ics", "event_" <> uuid, "event")
|
||||
end
|
||||
|
||||
@spec instance(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
||||
def event(_conn, _) do
|
||||
{:error, :not_found}
|
||||
end
|
||||
|
||||
@spec going(Plug.Conn.t(), map()) :: Plug.Conn.t() | {:error, :not_found}
|
||||
def going(conn, %{"token" => token, "format" => format}) do
|
||||
return_data(conn, format, "token_" <> token, "events")
|
||||
end
|
||||
@@ -39,6 +44,8 @@ defmodule Mobilizon.Web.FeedController do
|
||||
{:error, :not_found}
|
||||
end
|
||||
|
||||
@spec return_data(Plug.Conn.t(), String.t(), String.t(), String.t()) ::
|
||||
Plug.Conn.t() | {:error, :not_found}
|
||||
defp return_data(conn, "atom", type, filename) do
|
||||
case Cachex.fetch(:feed, type) do
|
||||
{status, data} when status in [:commit, :ok] ->
|
||||
|
||||
@@ -10,6 +10,7 @@ defmodule Mobilizon.Web.MediaProxyController do
|
||||
alias Plug.Conn
|
||||
|
||||
# sobelow_skip ["XSS.SendResp"]
|
||||
@spec remote(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
||||
def remote(conn, %{"sig" => sig64, "url" => url64}) do
|
||||
with {_, true} <- {:enabled, MediaProxy.enabled?()},
|
||||
{:ok, url} <- MediaProxy.decode_url(sig64, url64),
|
||||
@@ -27,6 +28,7 @@ defmodule Mobilizon.Web.MediaProxyController do
|
||||
end
|
||||
end
|
||||
|
||||
@spec media_proxy_opts :: Keyword.t()
|
||||
defp media_proxy_opts do
|
||||
Config.get([:media_proxy, :proxy_opts], [])
|
||||
end
|
||||
|
||||
@@ -15,6 +15,7 @@ defmodule Mobilizon.Web.NodeInfoController do
|
||||
@node_info_supported_versions ["2.0", "2.1"]
|
||||
@node_info_schema_uri "http://nodeinfo.diaspora.software/ns/schema/"
|
||||
|
||||
@spec schemas(Plug.Conn.t(), any) :: Plug.Conn.t()
|
||||
def schemas(conn, _params) do
|
||||
links =
|
||||
@node_info_supported_versions
|
||||
@@ -31,6 +32,7 @@ defmodule Mobilizon.Web.NodeInfoController do
|
||||
end
|
||||
|
||||
# Schema definition: https://github.com/jhass/nodeinfo/blob/master/schemas/2.1/schema.json
|
||||
@spec nodeinfo(Plug.Conn.t(), any()) :: Plug.Conn.t()
|
||||
def nodeinfo(conn, %{"version" => version}) when version in @node_info_supported_versions do
|
||||
response = %{
|
||||
version: version,
|
||||
|
||||
@@ -14,15 +14,26 @@ defmodule Mobilizon.Web.PageController do
|
||||
plug(:put_layout, false)
|
||||
action_fallback(Mobilizon.Web.FallbackController)
|
||||
|
||||
@spec my_events(Plug.Conn.t(), any) :: Plug.Conn.t()
|
||||
defdelegate my_events(conn, params), to: PageController, as: :index
|
||||
@spec create_event(Plug.Conn.t(), any) :: Plug.Conn.t()
|
||||
defdelegate create_event(conn, params), to: PageController, as: :index
|
||||
@spec list_events(Plug.Conn.t(), any) :: Plug.Conn.t()
|
||||
defdelegate list_events(conn, params), to: PageController, as: :index
|
||||
@spec edit_event(Plug.Conn.t(), any) :: Plug.Conn.t()
|
||||
defdelegate edit_event(conn, params), to: PageController, as: :index
|
||||
@spec moderation_report(Plug.Conn.t(), any) :: Plug.Conn.t()
|
||||
defdelegate moderation_report(conn, params), to: PageController, as: :index
|
||||
@spec participation_email_confirmation(Plug.Conn.t(), any) :: Plug.Conn.t()
|
||||
defdelegate participation_email_confirmation(conn, params), to: PageController, as: :index
|
||||
@spec user_email_validation(Plug.Conn.t(), any) :: Plug.Conn.t()
|
||||
defdelegate user_email_validation(conn, params), to: PageController, as: :index
|
||||
@spec my_groups(Plug.Conn.t(), any) :: Plug.Conn.t()
|
||||
defdelegate my_groups(conn, params), to: PageController, as: :index
|
||||
|
||||
@typep object_type ::
|
||||
:actor | :event | :comment | :resource | :post | :discussion | :todo_list | :todo
|
||||
|
||||
@spec index(Plug.Conn.t(), any) :: Plug.Conn.t()
|
||||
def index(conn, _params), do: render(conn, :index)
|
||||
|
||||
@@ -62,38 +73,45 @@ defmodule Mobilizon.Web.PageController do
|
||||
render_or_error(conn, &checks?/3, status, :discussion, discussion)
|
||||
end
|
||||
|
||||
def resources(conn, %{"name" => _name}) do
|
||||
handle_collection_route(conn, :resources)
|
||||
end
|
||||
|
||||
def posts(conn, %{"name" => _name}) do
|
||||
handle_collection_route(conn, :posts)
|
||||
end
|
||||
|
||||
def discussions(conn, %{"name" => _name}) do
|
||||
handle_collection_route(conn, :discussions)
|
||||
end
|
||||
|
||||
def events(conn, %{"name" => _name}) do
|
||||
handle_collection_route(conn, :events)
|
||||
end
|
||||
|
||||
def todos(conn, %{"name" => _name}) do
|
||||
handle_collection_route(conn, :todos)
|
||||
end
|
||||
|
||||
@spec todo_list(Plug.Conn.t(), map) :: {:error, :not_found} | Plug.Conn.t()
|
||||
@spec todo_list(Plug.Conn.t(), map) :: Plug.Conn.t() | {:error, :not_found}
|
||||
def todo_list(conn, %{"uuid" => uuid}) do
|
||||
{status, todo_list} = Cache.get_todo_list_by_uuid_with_preload(uuid)
|
||||
render_or_error(conn, &checks?/3, status, :todo_list, todo_list)
|
||||
end
|
||||
|
||||
@spec todo(Plug.Conn.t(), map) :: {:error, :not_found} | Plug.Conn.t()
|
||||
@spec todo(Plug.Conn.t(), map) :: Plug.Conn.t() | {:error, :not_found}
|
||||
def todo(conn, %{"uuid" => uuid}) do
|
||||
{status, todo} = Cache.get_todo_by_uuid_with_preload(uuid)
|
||||
render_or_error(conn, &checks?/3, status, :todo, todo)
|
||||
end
|
||||
|
||||
@typep collections :: :resources | :posts | :discussions | :events | :todos
|
||||
|
||||
@spec resources(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
||||
def resources(conn, %{"name" => _name}) do
|
||||
handle_collection_route(conn, :resources)
|
||||
end
|
||||
|
||||
@spec posts(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
||||
def posts(conn, %{"name" => _name}) do
|
||||
handle_collection_route(conn, :posts)
|
||||
end
|
||||
|
||||
@spec discussions(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
||||
def discussions(conn, %{"name" => _name}) do
|
||||
handle_collection_route(conn, :discussions)
|
||||
end
|
||||
|
||||
@spec events(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
||||
def events(conn, %{"name" => _name}) do
|
||||
handle_collection_route(conn, :events)
|
||||
end
|
||||
|
||||
@spec todos(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
||||
def todos(conn, %{"name" => _name}) do
|
||||
handle_collection_route(conn, :todos)
|
||||
end
|
||||
|
||||
@spec interact(Plug.Conn.t(), map()) :: Plug.Conn.t() | {:error, :not_found}
|
||||
def interact(conn, %{"uri" => uri}) do
|
||||
case ActivityPub.fetch_object_from_url(uri) do
|
||||
@@ -103,6 +121,7 @@ defmodule Mobilizon.Web.PageController do
|
||||
end
|
||||
end
|
||||
|
||||
@spec handle_collection_route(Plug.Conn.t(), collections()) :: Plug.Conn.t()
|
||||
defp handle_collection_route(conn, collection) do
|
||||
case get_format(conn) do
|
||||
"html" ->
|
||||
@@ -113,6 +132,8 @@ defmodule Mobilizon.Web.PageController do
|
||||
end
|
||||
end
|
||||
|
||||
@spec render_or_error(Plug.Conn.t(), function(), cache_status(), object_type(), any()) ::
|
||||
Plug.Conn.t() | {:error, :not_found}
|
||||
defp render_or_error(conn, check_fn, status, object_type, object) do
|
||||
case check_fn.(conn, status, object) do
|
||||
true ->
|
||||
@@ -136,12 +157,17 @@ defmodule Mobilizon.Web.PageController do
|
||||
end
|
||||
end
|
||||
|
||||
@spec is_visible?(map) :: boolean()
|
||||
defp is_visible?(%{visibility: v}), do: v in [:public, :unlisted]
|
||||
defp is_visible?(%Tombstone{}), do: true
|
||||
defp is_visible?(_), do: true
|
||||
|
||||
@spec ok_status?(cache_status) :: boolean()
|
||||
defp ok_status?(status), do: status in [:ok, :commit]
|
||||
|
||||
@typep cache_status :: :ok | :commit | :ignore
|
||||
|
||||
@spec ok_status_and_is_visible?(Plug.Conn.t(), cache_status, map()) :: boolean()
|
||||
defp ok_status_and_is_visible?(_conn, status, o),
|
||||
do: ok_status?(status) and is_visible?(o)
|
||||
|
||||
@@ -158,9 +184,11 @@ defmodule Mobilizon.Web.PageController do
|
||||
end
|
||||
end
|
||||
|
||||
@spec is_local?(map()) :: boolean | :remote
|
||||
defp is_local?(%{local: local}), do: if(local, do: true, else: :remote)
|
||||
defp is_local?(_), do: false
|
||||
|
||||
@spec maybe_add_noindex_header(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
||||
defp maybe_add_noindex_header(conn, %{visibility: visibility})
|
||||
when visibility != :public do
|
||||
put_resp_header(conn, "x-robots-tag", "noindex")
|
||||
@@ -168,6 +196,7 @@ defmodule Mobilizon.Web.PageController do
|
||||
|
||||
defp maybe_add_noindex_header(conn, _), do: conn
|
||||
|
||||
@spec is_person?(Actor.t()) :: boolean()
|
||||
defp is_person?(%Actor{type: :Person}), do: true
|
||||
defp is_person?(_), do: false
|
||||
end
|
||||
|
||||
@@ -17,6 +17,7 @@ defmodule Mobilizon.Web.WebFingerController do
|
||||
@doc """
|
||||
Provides /.well-known/host-meta
|
||||
"""
|
||||
@spec host_meta(Plug.Conn.t(), any()) :: Plug.Conn.t() | no_return
|
||||
def host_meta(conn, _params) do
|
||||
xml = WebFinger.host_meta()
|
||||
|
||||
@@ -28,6 +29,7 @@ defmodule Mobilizon.Web.WebFingerController do
|
||||
@doc """
|
||||
Provides /.well-known/webfinger
|
||||
"""
|
||||
@spec webfinger(Plug.Conn.t(), any()) :: Plug.Conn.t() | no_return
|
||||
def webfinger(conn, %{"resource" => resource}) do
|
||||
case WebFinger.webfinger(resource, "JSON") do
|
||||
{:ok, response} -> json(conn, response)
|
||||
|
||||
@@ -49,6 +49,7 @@ defmodule Mobilizon.Web.Email.Event do
|
||||
|> render(:event_updated)
|
||||
end
|
||||
|
||||
@spec calculate_event_diff_and_send_notifications(Event.t(), Event.t(), map()) :: {:ok, :ok}
|
||||
def calculate_event_diff_and_send_notifications(
|
||||
%Event{} = old_event,
|
||||
%Event{id: event_id} = event,
|
||||
@@ -75,6 +76,12 @@ defmodule Mobilizon.Web.Email.Event do
|
||||
end
|
||||
end
|
||||
|
||||
@spec send_notification_for_event_update_to_participant(
|
||||
{Participant.t(), Actor.t(), User.t() | nil, Setting.t() | nil},
|
||||
Event.t(),
|
||||
Event.t(),
|
||||
MapSet.t()
|
||||
) :: Bamboo.Email.t()
|
||||
defp send_notification_for_event_update_to_participant(
|
||||
{%Participant{} = _participant, %Actor{} = actor,
|
||||
%User{locale: locale, email: email} = _user, %Setting{timezone: timezone}},
|
||||
@@ -131,6 +138,15 @@ defmodule Mobilizon.Web.Email.Event do
|
||||
)
|
||||
end
|
||||
|
||||
@spec do_send_notification_for_event_update_to_participant(
|
||||
String.t(),
|
||||
Actor.t(),
|
||||
Event.t(),
|
||||
Event.t(),
|
||||
MapSet.t(),
|
||||
String.t(),
|
||||
String.t()
|
||||
) :: Bamboo.Email.t()
|
||||
defp do_send_notification_for_event_update_to_participant(
|
||||
email,
|
||||
actor,
|
||||
|
||||
@@ -34,6 +34,8 @@ defmodule Mobilizon.Web.Email.Notification do
|
||||
|> render(:before_event_notification)
|
||||
end
|
||||
|
||||
@spec on_day_notification(User.t(), list(Participant.t()), pos_integer(), String.t()) ::
|
||||
Bamboo.Email.t()
|
||||
def on_day_notification(
|
||||
%User{email: email, settings: %Setting{timezone: timezone}},
|
||||
participations,
|
||||
@@ -58,6 +60,8 @@ defmodule Mobilizon.Web.Email.Notification do
|
||||
|> render(:on_day_notification)
|
||||
end
|
||||
|
||||
@spec weekly_notification(User.t(), list(Participant.t()), pos_integer(), String.t()) ::
|
||||
Bamboo.Email.t()
|
||||
def weekly_notification(
|
||||
%User{email: email, settings: %Setting{timezone: timezone}},
|
||||
participations,
|
||||
@@ -82,6 +86,7 @@ defmodule Mobilizon.Web.Email.Notification do
|
||||
|> render(:notification_each_week)
|
||||
end
|
||||
|
||||
@spec pending_participation_notification(User.t(), Event.t(), pos_integer()) :: Bamboo.Email.t()
|
||||
def pending_participation_notification(
|
||||
%User{locale: locale, email: email},
|
||||
%Event{} = event,
|
||||
|
||||
@@ -11,6 +11,7 @@ defmodule Mobilizon.Web.MediaProxy do
|
||||
|
||||
@base64_opts [padding: false]
|
||||
|
||||
@spec url(String.t() | nil) :: String.t() | nil
|
||||
def url(url) when is_nil(url) or url == "", do: nil
|
||||
def url("/" <> _ = url), do: url
|
||||
|
||||
@@ -27,10 +28,12 @@ defmodule Mobilizon.Web.MediaProxy do
|
||||
not local?(url)
|
||||
end
|
||||
|
||||
@spec enabled? :: boolean()
|
||||
def enabled?, do: Config.get([:media_proxy, :enabled], false)
|
||||
|
||||
def local?(url), do: String.starts_with?(url, Web.Endpoint.url())
|
||||
|
||||
@spec base64_sig64(String.t()) :: {String.t(), String.t()}
|
||||
defp base64_sig64(url) do
|
||||
base64 = Base.url_encode64(url, @base64_opts)
|
||||
|
||||
@@ -42,12 +45,14 @@ defmodule Mobilizon.Web.MediaProxy do
|
||||
{base64, sig64}
|
||||
end
|
||||
|
||||
@spec encode_url(String.t()) :: String.t()
|
||||
def encode_url(url) do
|
||||
{base64, sig64} = base64_sig64(url)
|
||||
|
||||
build_url(sig64, base64, filename(url))
|
||||
end
|
||||
|
||||
@spec decode_url(String.t(), String.t()) :: {:ok, String.t()} | {:error, :invalid_signature}
|
||||
def decode_url(sig, url) do
|
||||
with {:ok, sig} <- Base.url_decode64(sig, @base64_opts),
|
||||
signature when signature == sig <- signed_url(url) do
|
||||
@@ -57,10 +62,12 @@ defmodule Mobilizon.Web.MediaProxy do
|
||||
end
|
||||
end
|
||||
|
||||
@spec signed_url(String.t()) :: String.t()
|
||||
defp signed_url(url) do
|
||||
sha_hmac(Config.get([Web.Endpoint, :secret_key_base]), url)
|
||||
end
|
||||
|
||||
@spec sha_hmac(String.t(), String.t()) :: String.t()
|
||||
@compile {:no_warn_undefined, {:crypto, :mac, 4}}
|
||||
@compile {:no_warn_undefined, {:crypto, :hmac, 3}}
|
||||
defp sha_hmac(key, url) do
|
||||
@@ -73,14 +80,17 @@ defmodule Mobilizon.Web.MediaProxy do
|
||||
end
|
||||
end
|
||||
|
||||
@spec filename(String.t()) :: String.t() | nil
|
||||
def filename(url_or_path) do
|
||||
if path = URI.parse(url_or_path).path, do: Path.basename(path)
|
||||
end
|
||||
|
||||
@spec base_url :: String.t()
|
||||
def base_url do
|
||||
Web.Endpoint.url()
|
||||
end
|
||||
|
||||
@spec proxy_url(String.t(), String.t(), String.t(), String.t() | nil) :: String.t()
|
||||
defp proxy_url(path, sig_base64, url_base64, filename) do
|
||||
[
|
||||
base_url(),
|
||||
@@ -93,10 +103,13 @@ defmodule Mobilizon.Web.MediaProxy do
|
||||
|> Path.join()
|
||||
end
|
||||
|
||||
@spec build_url(String.t(), String.t(), String.t() | nil) :: String.t()
|
||||
def build_url(sig_base64, url_base64, filename \\ nil) do
|
||||
proxy_url("proxy", sig_base64, url_base64, filename)
|
||||
end
|
||||
|
||||
@spec verify_request_path_and_url(Plug.Conn.t() | String.t(), String.t()) ::
|
||||
:ok | {:wrong_filename, String.t()}
|
||||
def verify_request_path_and_url(
|
||||
%Plug.Conn{params: %{"filename" => _}, request_path: request_path},
|
||||
url
|
||||
@@ -116,6 +129,7 @@ defmodule Mobilizon.Web.MediaProxy do
|
||||
|
||||
def verify_request_path_and_url(_, _), do: :ok
|
||||
|
||||
@spec basename_matches?(String.t(), String.t()) :: boolean()
|
||||
defp basename_matches?(path, filename) do
|
||||
basename = Path.basename(path)
|
||||
basename == filename or URI.decode(basename) == filename or URI.encode(basename) == filename
|
||||
|
||||
@@ -11,19 +11,23 @@ defmodule Mobilizon.Web.Plugs.DetectLocalePlug do
|
||||
import Plug.Conn, only: [get_req_header: 2, assign: 3]
|
||||
alias Mobilizon.Web.Gettext, as: GettextBackend
|
||||
|
||||
@spec init(any()) :: any()
|
||||
def init(_), do: nil
|
||||
|
||||
@spec call(Plug.Conn.t(), Keyword.t()) :: Plug.Conn.t()
|
||||
def call(conn, _) do
|
||||
locale = get_locale_from_header(conn)
|
||||
assign(conn, :detected_locale, locale)
|
||||
end
|
||||
|
||||
@spec get_locale_from_header(Plug.Conn.t()) :: String.t()
|
||||
defp get_locale_from_header(conn) do
|
||||
conn
|
||||
|> extract_accept_language()
|
||||
|> Enum.find(&supported_locale?/1)
|
||||
end
|
||||
|
||||
@spec extract_accept_language(Plug.Conn.t()) :: list(String.t())
|
||||
defp extract_accept_language(conn) do
|
||||
case get_req_header(conn, "accept-language") do
|
||||
[value | _] ->
|
||||
@@ -40,12 +44,14 @@ defmodule Mobilizon.Web.Plugs.DetectLocalePlug do
|
||||
end
|
||||
end
|
||||
|
||||
@spec supported_locale?(String.t()) :: boolean()
|
||||
defp supported_locale?(locale) do
|
||||
GettextBackend
|
||||
|> Gettext.known_locales()
|
||||
|> Enum.member?(locale)
|
||||
end
|
||||
|
||||
@spec parse_language_option(String.t()) :: %{tag: String.t(), quality: float()}
|
||||
defp parse_language_option(string) do
|
||||
captures = Regex.named_captures(~r/^\s?(?<tag>[\w\-]+)(?:;q=(?<quality>[\d\.]+))?$/i, string)
|
||||
|
||||
@@ -58,6 +64,7 @@ defmodule Mobilizon.Web.Plugs.DetectLocalePlug do
|
||||
%{tag: captures["tag"], quality: quality}
|
||||
end
|
||||
|
||||
@spec ensure_language_fallbacks(list(String.t())) :: list(String.t())
|
||||
defp ensure_language_fallbacks(tags) do
|
||||
Enum.flat_map(tags, fn tag ->
|
||||
[language | _] = String.split(tag, "-")
|
||||
|
||||
@@ -10,10 +10,12 @@ defmodule Mobilizon.Web.Plugs.Federating do
|
||||
|
||||
import Plug.Conn
|
||||
|
||||
@spec init(any()) :: any()
|
||||
def init(options) do
|
||||
options
|
||||
end
|
||||
|
||||
@spec call(Plug.Conn.t(), Keyword.t()) :: Plug.Conn.t()
|
||||
def call(conn, _opts) do
|
||||
if Mobilizon.Config.get([:instance, :federating]) do
|
||||
conn
|
||||
|
||||
@@ -13,8 +13,10 @@ defmodule Mobilizon.Web.Plugs.HTTPSecurityPlug do
|
||||
|
||||
require Logger
|
||||
|
||||
@spec init(any()) :: any()
|
||||
def init(opts), do: opts
|
||||
|
||||
@spec call(Plug.Conn.t(), Keyword.t()) :: Plug.Conn.t()
|
||||
def call(conn, options \\ []) do
|
||||
if Config.get([:http_security, :enabled]) do
|
||||
conn
|
||||
|
||||
@@ -18,6 +18,7 @@ defmodule Mobilizon.Web.Plugs.MappedSignatureToIdentity do
|
||||
|
||||
require Logger
|
||||
|
||||
@spec init(any()) :: any()
|
||||
def init(options), do: options
|
||||
|
||||
@spec key_id_from_conn(Plug.Conn.t()) :: String.t() | nil
|
||||
@@ -42,6 +43,7 @@ defmodule Mobilizon.Web.Plugs.MappedSignatureToIdentity do
|
||||
end
|
||||
end
|
||||
|
||||
@spec call(Plug.Conn.t(), any()) :: Plug.Conn.t()
|
||||
def call(%{assigns: %{actor: _}} = conn, _opts), do: conn
|
||||
|
||||
# if this has payload make sure it is signed by the same actor that made it
|
||||
|
||||
@@ -21,6 +21,7 @@ defmodule Mobilizon.Web.Plugs.UploadedMedia do
|
||||
# no slashes
|
||||
@path "media"
|
||||
|
||||
@spec init(any()) :: map()
|
||||
def init(_opts) do
|
||||
static_plug_opts =
|
||||
[]
|
||||
@@ -31,6 +32,7 @@ defmodule Mobilizon.Web.Plugs.UploadedMedia do
|
||||
%{static_plug_opts: static_plug_opts}
|
||||
end
|
||||
|
||||
@spec call(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
||||
def call(%{request_path: <<"/", @path, "/", file::binary>>} = conn, opts) do
|
||||
conn =
|
||||
case fetch_query_params(conn) do
|
||||
|
||||
Reference in New Issue
Block a user