Merge branch 'fix-credo-warnings' into 'master'

Fix credo warnings

See merge request framasoft/mobilizon!188
This commit is contained in:
Thomas Citharel 2019-09-26 18:28:43 +02:00
commit 7b37399f5e
99 changed files with 784 additions and 639 deletions

View File

@ -4,7 +4,9 @@
# Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/lib/mix/tasks/pleroma/common.ex # Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/lib/mix/tasks/pleroma/common.ex
defmodule Mix.Tasks.Mobilizon.Common do defmodule Mix.Tasks.Mobilizon.Common do
@moduledoc "Common functions to be reused in mix tasks" @moduledoc """
Common functions to be reused in mix tasks
"""
def get_option(options, opt, prompt, defval \\ nil, defname \\ nil) do def get_option(options, opt, prompt, defval \\ nil, defname \\ nil) do
display = if defname || defval, do: "#{prompt} [#{defname || defval}]", else: "#{prompt}" display = if defname || defval, do: "#{prompt} [#{defname || defval}]", else: "#{prompt}"
@ -13,17 +15,21 @@ defmodule Mix.Tasks.Mobilizon.Common do
case Mix.shell().prompt(display) do case Mix.shell().prompt(display) do
"\n" -> "\n" ->
case defval do case defval do
nil -> get_option(options, opt, prompt, defval) nil ->
defval -> defval get_option(options, opt, prompt, defval)
defval ->
defval
end end
opt -> opt ->
opt |> String.trim() String.trim(opt)
end end
end end
def start_mobilizon do def start_mobilizon do
Application.put_env(:phoenix, :serve_endpoints, false, persistent: true) Application.put_env(:phoenix, :serve_endpoints, false, persistent: true)
{:ok, _} = Application.ensure_all_started(:mobilizon) {:ok, _} = Application.ensure_all_started(:mobilizon)
end end

View File

@ -1,13 +1,14 @@
defmodule Mix.Tasks.Mobilizon.CreateBot do defmodule Mix.Tasks.Mobilizon.CreateBot do
@moduledoc """ @moduledoc """
Creates a bot from a source Creates a bot from a source.
""" """
use Mix.Task use Mix.Task
alias Mobilizon.Actors
alias Mobilizon.Users alias Mobilizon.{Actors, Users}
alias Mobilizon.Actors.Bot alias Mobilizon.Actors.Bot
alias Mobilizon.Users.User alias Mobilizon.Users.User
require Logger require Logger
@shortdoc "Register user" @shortdoc "Register user"
@ -25,7 +26,8 @@ defmodule Mix.Tasks.Mobilizon.CreateBot do
}) do }) do
bot bot
else else
e -> Logger.error(inspect(e)) error ->
Logger.error(inspect(error))
end end
end end
end end

View File

@ -4,11 +4,6 @@
# Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/lib/mix/tasks/pleroma/instance.ex # Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/lib/mix/tasks/pleroma/instance.ex
defmodule Mix.Tasks.Mobilizon.Instance do defmodule Mix.Tasks.Mobilizon.Instance do
use Mix.Task
alias Mix.Tasks.Mobilizon.Common
@shortdoc "Generates a new config"
@preferred_cli_env "prod"
@moduledoc """ @moduledoc """
Generates a new config Generates a new config
@ -31,6 +26,13 @@ defmodule Mix.Tasks.Mobilizon.Instance do
- `--dbpass DBPASS` - the password to use for the database connection - `--dbpass DBPASS` - the password to use for the database connection
""" """
use Mix.Task
alias Mix.Tasks.Mobilizon.Common
@preferred_cli_env "prod"
@shortdoc "Generates a new config"
def run(["gen" | options]) do def run(["gen" | options]) do
{options, [], []} = {options, [], []} =
OptionParser.parse( OptionParser.parse(

View File

@ -4,11 +4,6 @@
# Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/lib/mix/tasks/pleroma/relay.ex # Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/lib/mix/tasks/pleroma/relay.ex
defmodule Mix.Tasks.Mobilizon.Relay do defmodule Mix.Tasks.Mobilizon.Relay do
use Mix.Task
alias Mobilizon.Service.ActivityPub.Relay
alias Mix.Tasks.Mobilizon.Common
@shortdoc "Manages remote relays"
@moduledoc """ @moduledoc """
Manages remote relays Manages remote relays
@ -24,6 +19,13 @@ defmodule Mix.Tasks.Mobilizon.Relay do
Example: ``mix mobilizon.relay unfollow https://example.org/relay`` Example: ``mix mobilizon.relay unfollow https://example.org/relay``
""" """
use Mix.Task
alias Mix.Tasks.Mobilizon.Common
alias Mobilizon.Service.ActivityPub.Relay
@shortdoc "Manages remote relays"
def run(["follow", target]) do def run(["follow", target]) do
Common.start_mobilizon() Common.start_mobilizon()

View File

@ -1,16 +1,19 @@
defmodule Mix.Tasks.Mobilizon.Toot do defmodule Mix.Tasks.Mobilizon.Toot do
@moduledoc """ @moduledoc """
Creates a bot from a source Creates a bot from a source.
""" """
use Mix.Task use Mix.Task
alias MobilizonWeb.API
require Logger require Logger
@shortdoc "Toot to an user" @shortdoc "Toot to an user"
def run([from, content]) do def run([from, content]) do
Mix.Task.run("app.start") Mix.Task.run("app.start")
case MobilizonWeb.API.Comments.create_comment(from, content) do case API.Comments.create_comment(from, content) do
{:ok, _, _} -> {:ok, _, _} ->
Mix.shell().info("Tooted") Mix.shell().info("Tooted")

View File

@ -23,7 +23,7 @@ defmodule Mobilizon do
@spec named_version :: String.t() @spec named_version :: String.t()
def named_version, do: "#{@name} #{@version}" def named_version, do: "#{@name} #{@version}"
@spec user_agent :: String.t(:w) @spec user_agent :: String.t()
def user_agent do def user_agent do
info = "#{MobilizonWeb.Endpoint.url()} <#{Config.get([:instance, :email], "")}>" info = "#{MobilizonWeb.Endpoint.url()} <#{Config.get([:instance, :email], "")}>"

View File

@ -11,11 +11,11 @@ defmodule Mobilizon.Actors.Actor do
alias Mobilizon.Actors.{ActorOpenness, ActorType, ActorVisibility, Follower, Member} alias Mobilizon.Actors.{ActorOpenness, ActorType, ActorVisibility, Follower, Member}
alias Mobilizon.Events.{Event, FeedToken} alias Mobilizon.Events.{Event, FeedToken}
alias Mobilizon.Media.File alias Mobilizon.Media.File
alias Mobilizon.Reports.{Report, Note} alias Mobilizon.Reports.{Note, Report}
alias Mobilizon.Users.User alias Mobilizon.Users.User
alias MobilizonWeb.Router.Helpers, as: Routes
alias MobilizonWeb.Endpoint alias MobilizonWeb.Endpoint
alias MobilizonWeb.Router.Helpers, as: Routes
require Logger require Logger

View File

@ -10,8 +10,8 @@ defmodule Mobilizon.Events.Comment do
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Events.{Comment, CommentVisibility, Event} alias Mobilizon.Events.{Comment, CommentVisibility, Event}
alias MobilizonWeb.Router.Helpers, as: Routes
alias MobilizonWeb.Endpoint alias MobilizonWeb.Endpoint
alias MobilizonWeb.Router.Helpers, as: Routes
@type t :: %__MODULE__{ @type t :: %__MODULE__{
text: String.t(), text: String.t(),

View File

@ -16,8 +16,8 @@ defmodule Mobilizon.Events.Event do
EventVisibility, EventVisibility,
JoinOptions, JoinOptions,
Participant, Participant,
Tag,
Session, Session,
Tag,
Track Track
} }

View File

@ -8,9 +8,9 @@ defmodule Mobilizon.Events.EventOptions do
import Ecto.Changeset import Ecto.Changeset
alias Mobilizon.Events.{ alias Mobilizon.Events.{
CommentModeration,
EventOffer, EventOffer,
EventParticipationCondition, EventParticipationCondition
CommentModeration
} }
@type t :: %__MODULE__{ @type t :: %__MODULE__{

View File

@ -7,8 +7,8 @@ defmodule Mobilizon.Events.Tag do
import Ecto.Changeset import Ecto.Changeset
alias Mobilizon.Events.TagRelation
alias Mobilizon.Events.Tag.TitleSlug alias Mobilizon.Events.Tag.TitleSlug
alias Mobilizon.Events.TagRelation
@type t :: %__MODULE__{ @type t :: %__MODULE__{
title: String.t(), title: String.t(),

View File

@ -1,6 +1,6 @@
defmodule MobilizonWeb.API.Comments do defmodule MobilizonWeb.API.Comments do
@moduledoc """ @moduledoc """
API for Comments API for Comments.
""" """
alias Mobilizon.Actors alias Mobilizon.Actors
@ -8,6 +8,7 @@ defmodule MobilizonWeb.API.Comments do
alias Mobilizon.Events.Comment alias Mobilizon.Events.Comment
alias Mobilizon.Service.ActivityPub alias Mobilizon.Service.ActivityPub
alias Mobilizon.Service.ActivityPub.Utils, as: ActivityPubUtils alias Mobilizon.Service.ActivityPub.Utils, as: ActivityPubUtils
alias MobilizonWeb.API.Utils alias MobilizonWeb.API.Utils
@doc """ @doc """

View File

@ -1,12 +1,14 @@
defmodule MobilizonWeb.API.Events do defmodule MobilizonWeb.API.Events do
@moduledoc """ @moduledoc """
API for Events API for Events.
""" """
alias Mobilizon.Events.Event alias Mobilizon.Events.Event
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Service.ActivityPub alias Mobilizon.Service.ActivityPub
alias Mobilizon.Service.ActivityPub.Utils, as: ActivityPubUtils
alias Mobilizon.Service.ActivityPub.Activity alias Mobilizon.Service.ActivityPub.Activity
alias Mobilizon.Service.ActivityPub.Utils, as: ActivityPubUtils
alias MobilizonWeb.API.Utils alias MobilizonWeb.API.Utils
@doc """ @doc """

View File

@ -6,6 +6,7 @@ defmodule MobilizonWeb.API.Follows do
alias Mobilizon.Actors alias Mobilizon.Actors
alias Mobilizon.Actors.{Actor, Follower} alias Mobilizon.Actors.{Actor, Follower}
alias Mobilizon.Service.ActivityPub alias Mobilizon.Service.ActivityPub
require Logger require Logger
def follow(%Actor{} = follower, %Actor{} = followed) do def follow(%Actor{} = follower, %Actor{} = followed) do

View File

@ -1,12 +1,14 @@
defmodule MobilizonWeb.API.Groups do defmodule MobilizonWeb.API.Groups do
@moduledoc """ @moduledoc """
API for Events API for Groups.
""" """
alias Mobilizon.Actors alias Mobilizon.Actors
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Users.User
alias Mobilizon.Service.ActivityPub alias Mobilizon.Service.ActivityPub
alias Mobilizon.Service.ActivityPub.Utils, as: ActivityPubUtils alias Mobilizon.Service.ActivityPub.Utils, as: ActivityPubUtils
alias Mobilizon.Users.User
alias MobilizonWeb.API.Utils alias MobilizonWeb.API.Utils
@doc """ @doc """

View File

@ -1,6 +1,6 @@
defmodule MobilizonWeb.API.Participations do defmodule MobilizonWeb.API.Participations do
@moduledoc """ @moduledoc """
Common API to join events and groups Common API to join events and groups.
""" """
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor

View File

@ -1,18 +1,19 @@
defmodule MobilizonWeb.API.Reports do defmodule MobilizonWeb.API.Reports do
@moduledoc """ @moduledoc """
API for Reports API for Reports.
""" """
import MobilizonWeb.API.Utils
import Mobilizon.Service.Admin.ActionLogService import Mobilizon.Service.Admin.ActionLogService
import MobilizonWeb.API.Utils
alias Mobilizon.Actors alias Mobilizon.Actors
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Events alias Mobilizon.Events
alias Mobilizon.Service.ActivityPub.Activity
alias Mobilizon.Reports, as: ReportsAction alias Mobilizon.Reports, as: ReportsAction
alias Mobilizon.Reports.{Report, Note} alias Mobilizon.Reports.{Note, Report, ReportStatus}
alias Mobilizon.Service.ActivityPub alias Mobilizon.Service.ActivityPub
alias Mobilizon.Service.ActivityPub.Activity
alias Mobilizon.Users alias Mobilizon.Users
alias Mobilizon.Users.User alias Mobilizon.Users.User
@ -62,7 +63,7 @@ defmodule MobilizonWeb.API.Reports do
""" """
def update_report_status(%Actor{} = actor, %Report{} = report, state) do def update_report_status(%Actor{} = actor, %Report{} = report, state) do
with {:valid_state, true} <- with {:valid_state, true} <-
{:valid_state, Mobilizon.Reports.ReportStatus.valid_value?(state)}, {:valid_state, ReportStatus.valid_value?(state)},
{:ok, report} <- ReportsAction.update_report(report, %{"status" => state}), {:ok, report} <- ReportsAction.update_report(report, %{"status" => state}),
{:ok, _} <- log_action(actor, "update", report) do {:ok, _} <- log_action(actor, "update", report) do
{:ok, report} {:ok, report}
@ -73,7 +74,7 @@ defmodule MobilizonWeb.API.Reports do
defp get_report_comments(%Actor{id: actor_id}, comment_ids) do defp get_report_comments(%Actor{id: actor_id}, comment_ids) do
{:get_report_comments, {:get_report_comments,
Events.list_comments_by_actor_and_ids(actor_id, comment_ids) |> Enum.map(& &1.url)} actor_id |> Events.list_comments_by_actor_and_ids(comment_ids) |> Enum.map(& &1.url)}
end end
defp get_report_comments(_, _), do: {:get_report_comments, nil} defp get_report_comments(_, _), do: {:get_report_comments, nil}

View File

@ -1,6 +1,6 @@
defmodule MobilizonWeb.API.Utils do defmodule MobilizonWeb.API.Utils do
@moduledoc """ @moduledoc """
Utils for API Utils for API.
""" """
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor

View File

@ -6,6 +6,7 @@ defmodule MobilizonWeb.Cache.ActivityPub do
alias Mobilizon.{Actors, Events, Service} alias Mobilizon.{Actors, Events, Service}
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Events.{Comment, Event} alias Mobilizon.Events.{Comment, Event}
alias Service.ActivityPub
@cache :activity_pub @cache :activity_pub
@ -65,6 +66,6 @@ defmodule MobilizonWeb.Cache.ActivityPub do
""" """
@spec get_relay :: {:commit, Actor.t()} | {:ignore, nil} @spec get_relay :: {:commit, Actor.t()} | {:ignore, nil}
def get_relay do def get_relay do
Cachex.fetch(@cache, "relay_actor", &Service.ActivityPub.Relay.get_actor/0) Cachex.fetch(@cache, "relay_actor", &ActivityPub.Relay.get_actor/0)
end end
end end

View File

@ -6,10 +6,12 @@
defmodule MobilizonWeb.MediaProxyController do defmodule MobilizonWeb.MediaProxyController do
use MobilizonWeb, :controller use MobilizonWeb, :controller
alias Plug.Conn
alias Mobilizon.Config alias Mobilizon.Config
alias MobilizonWeb.ReverseProxy
alias MobilizonWeb.MediaProxy alias MobilizonWeb.MediaProxy
alias MobilizonWeb.ReverseProxy
@default_proxy_opts [max_body_length: 25 * 1_048_576, http: [follow_redirect: true]] @default_proxy_opts [max_body_length: 25 * 1_048_576, http: [follow_redirect: true]]
@ -21,10 +23,10 @@ defmodule MobilizonWeb.MediaProxyController do
ReverseProxy.call(conn, url, Keyword.get(config, :proxy_opts, @default_proxy_opts)) ReverseProxy.call(conn, url, Keyword.get(config, :proxy_opts, @default_proxy_opts))
else else
false -> false ->
send_resp(conn, 404, Plug.Conn.Status.reason_phrase(404)) send_resp(conn, 404, Conn.Status.reason_phrase(404))
{:error, :invalid_signature} -> {:error, :invalid_signature} ->
send_resp(conn, 403, Plug.Conn.Status.reason_phrase(403)) send_resp(conn, 403, Conn.Status.reason_phrase(403))
{:wrong_filename, filename} -> {:wrong_filename, filename} ->
redirect(conn, external: MediaProxy.build_url(sig64, url64, filename)) redirect(conn, external: MediaProxy.build_url(sig64, url64, filename))

View File

@ -9,6 +9,9 @@ defmodule MobilizonWeb.NodeInfoController do
alias Mobilizon.Config alias Mobilizon.Config
alias Mobilizon.Service.Statistics alias Mobilizon.Service.Statistics
alias MobilizonWeb.Endpoint
alias MobilizonWeb.Router.Helpers, as: Routes
@node_info_supported_versions ["2.0", "2.1"] @node_info_supported_versions ["2.0", "2.1"]
@node_info_schema_uri "http://nodeinfo.diaspora.software/ns/schema/" @node_info_schema_uri "http://nodeinfo.diaspora.software/ns/schema/"
@ -18,8 +21,7 @@ defmodule MobilizonWeb.NodeInfoController do
|> Enum.map(fn version -> |> Enum.map(fn version ->
%{ %{
rel: @node_info_schema_uri <> version, rel: @node_info_schema_uri <> version,
href: href: Routes.node_info_url(Endpoint, :nodeinfo, version)
MobilizonWeb.Router.Helpers.node_info_url(MobilizonWeb.Endpoint, :nodeinfo, version)
} }
end) end)

View File

@ -47,7 +47,7 @@ defmodule MobilizonWeb.MIME do
new_filename = new_filename =
if length(parts) > 1 do if length(parts) > 1 do
Enum.drop(parts, -1) |> Enum.join(".") parts |> Enum.drop(-1) |> Enum.join(".")
else else
Enum.join(parts) Enum.join(parts)
end end
@ -60,7 +60,9 @@ defmodule MobilizonWeb.MIME do
new_filename <> "." <> ext new_filename <> "." <> ext
true -> true ->
Enum.join([new_filename, String.split(content_type, "/") |> List.last()], ".") extension = content_type |> String.split("/") |> List.last()
Enum.join([new_filename, extension], ".")
end end
end end

View File

@ -60,7 +60,8 @@ defmodule MobilizonWeb.Plugs.UploadedMedia do
defp get_media(conn, {:static_dir, directory}, _, opts) do defp get_media(conn, {:static_dir, directory}, _, opts) do
static_opts = static_opts =
Map.get(opts, :static_plug_opts) opts
|> Map.get(:static_plug_opts)
|> Map.put(:at, [@path]) |> Map.put(:at, [@path])
|> Map.put(:from, directory) |> Map.put(:from, directory)

View File

@ -12,7 +12,7 @@ defmodule MobilizonWeb.Resolvers.Address do
""" """
@spec search(map(), map(), map()) :: {:ok, list(Address.t())} @spec search(map(), map(), map()) :: {:ok, list(Address.t())}
def search(_parent, %{query: query, page: _page, limit: _limit}, %{context: %{ip: ip}}) do def search(_parent, %{query: query, page: _page, limit: _limit}, %{context: %{ip: ip}}) do
country = Geolix.lookup(ip) |> Map.get(:country, nil) country = ip |> Geolix.lookup() |> Map.get(:country, nil)
local_addresses = Task.async(fn -> Addresses.search_addresses(query, country: country) end) local_addresses = Task.async(fn -> Addresses.search_addresses(query, country: country) end)
@ -40,7 +40,7 @@ defmodule MobilizonWeb.Resolvers.Address do
""" """
@spec reverse_geocode(map(), map(), map()) :: {:ok, list(Address.t())} @spec reverse_geocode(map(), map(), map()) :: {:ok, list(Address.t())}
def reverse_geocode(_parent, %{longitude: longitude, latitude: latitude}, %{context: %{ip: ip}}) do def reverse_geocode(_parent, %{longitude: longitude, latitude: latitude}, %{context: %{ip: ip}}) do
country = Geolix.lookup(ip) |> Map.get(:country, nil) country = ip |> Geolix.lookup() |> Map.get(:country, nil)
local_addresses = local_addresses =
Task.async(fn -> Addresses.reverse_geocode(longitude, latitude, country: country) end) Task.async(fn -> Addresses.reverse_geocode(longitude, latitude, country: country) end)

View File

@ -1,35 +1,36 @@
defmodule MobilizonWeb.Resolvers.Admin do defmodule MobilizonWeb.Resolvers.Admin do
@moduledoc """ @moduledoc """
Handles the report-related GraphQL calls Handles the report-related GraphQL calls.
""" """
alias Mobilizon.Events
alias Mobilizon.Users.User
import Mobilizon.Users.Guards
alias Mobilizon.Admin.ActionLog
alias Mobilizon.Reports.{Report, Note}
alias Mobilizon.Events.Event
alias Mobilizon.Service.Statistics
def list_action_logs(_parent, %{page: page, limit: limit}, %{ import Mobilizon.Users.Guards
context: %{current_user: %User{role: role}}
}) alias Mobilizon.Admin.ActionLog
alias Mobilizon.Events
alias Mobilizon.Events.Event
alias Mobilizon.Reports.{Note, Report}
alias Mobilizon.Service.Statistics
alias Mobilizon.Users.User
def list_action_logs(
_parent,
%{page: page, limit: limit},
%{context: %{current_user: %User{role: role}}}
)
when is_moderator(role) do when is_moderator(role) do
with action_logs <- Mobilizon.Admin.list_action_logs(page, limit) do with action_logs <- Mobilizon.Admin.list_action_logs(page, limit) do
action_logs = action_logs =
Enum.map(action_logs, fn %ActionLog{ action_logs
target_type: target_type, |> Enum.map(fn %ActionLog{
action: action, target_type: target_type,
actor: actor, action: action,
id: id, actor: actor,
inserted_at: inserted_at id: id,
} = action_log -> inserted_at: inserted_at
} = action_log ->
with data when is_map(data) <- with data when is_map(data) <-
transform_action_log(String.to_existing_atom(target_type), action, action_log) do transform_action_log(String.to_existing_atom(target_type), action, action_log) do
Map.merge(data, %{ Map.merge(data, %{actor: actor, id: id, inserted_at: inserted_at})
actor: actor,
id: id,
inserted_at: inserted_at
})
end end
end) end)
|> Enum.filter(& &1) |> Enum.filter(& &1)

View File

@ -1,11 +1,12 @@
defmodule MobilizonWeb.Resolvers.Comment do defmodule MobilizonWeb.Resolvers.Comment do
@moduledoc """ @moduledoc """
Handles the comment-related GraphQL calls Handles the comment-related GraphQL calls.
""" """
alias Mobilizon.Events.Comment alias Mobilizon.Events.Comment
alias Mobilizon.Users.User
alias Mobilizon.Service.ActivityPub.Activity alias Mobilizon.Service.ActivityPub.Activity
alias Mobilizon.Users.User
alias MobilizonWeb.API.Comments alias MobilizonWeb.API.Comments
require Logger require Logger

View File

@ -1,19 +1,22 @@
defmodule MobilizonWeb.Resolvers.Event do defmodule MobilizonWeb.Resolvers.Event do
@moduledoc """ @moduledoc """
Handles the event-related GraphQL calls Handles the event-related GraphQL calls.
""" """
import Mobilizon.Service.Admin.ActionLogService
alias Mobilizon.Actors
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Addresses alias Mobilizon.Addresses
alias Mobilizon.Addresses.Address alias Mobilizon.Addresses.Address
alias Mobilizon.Events alias Mobilizon.Events
alias Mobilizon.Events.{Event, Participant} alias Mobilizon.Events.{Event, Participant}
alias Mobilizon.Media.Picture alias Mobilizon.Media.Picture
alias Mobilizon.Users.User
alias Mobilizon.Actors
alias Mobilizon.Actors.Actor
alias MobilizonWeb.Resolvers.Person
alias Mobilizon.Service.ActivityPub.Activity alias Mobilizon.Service.ActivityPub.Activity
import Mobilizon.Service.Admin.ActionLogService alias Mobilizon.Users.User
alias MobilizonWeb.API
alias MobilizonWeb.Resolvers.Person
# We limit the max number of events that can be retrieved # We limit the max number of events that can be retrieved
@event_max_limit 100 @event_max_limit 100
@ -142,7 +145,7 @@ defmodule MobilizonWeb.Resolvers.Event do
{:has_event, {:ok, %Event{} = event}} <- {:has_event, {:ok, %Event{} = event}} <-
{:has_event, Mobilizon.Events.get_event_with_preload(event_id)}, {:has_event, Mobilizon.Events.get_event_with_preload(event_id)},
{:error, :participant_not_found} <- Mobilizon.Events.get_participant(event_id, actor_id), {:error, :participant_not_found} <- Mobilizon.Events.get_participant(event_id, actor_id),
{:ok, _activity, participant} <- MobilizonWeb.API.Participations.join(event, actor), {:ok, _activity, participant} <- API.Participations.join(event, actor),
participant <- participant <-
participant participant
|> Map.put(:event, event) |> Map.put(:event, event)
@ -178,7 +181,7 @@ defmodule MobilizonWeb.Resolvers.Event do
with {:is_owned, %Actor{} = actor} <- User.owns_actor(user, actor_id), with {:is_owned, %Actor{} = actor} <- User.owns_actor(user, actor_id),
{:has_event, {:ok, %Event{} = event}} <- {:has_event, {:ok, %Event{} = event}} <-
{:has_event, Mobilizon.Events.get_event_with_preload(event_id)}, {:has_event, Mobilizon.Events.get_event_with_preload(event_id)},
{:ok, _activity, _participant} <- MobilizonWeb.API.Participations.leave(event, actor) do {:ok, _activity, _participant} <- API.Participations.leave(event, actor) do
{:ok, %{event: %{id: event_id}, actor: %{id: actor_id}}} {:ok, %{event: %{id: event_id}, actor: %{id: actor_id}}}
else else
{:has_event, _} -> {:has_event, _} ->

View File

@ -1,11 +1,13 @@
defmodule MobilizonWeb.Resolvers.FeedToken do defmodule MobilizonWeb.Resolvers.FeedToken do
@moduledoc """ @moduledoc """
Handles the feed tokens-related GraphQL calls Handles the feed tokens-related GraphQL calls.
""" """
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Users.User
alias Mobilizon.Events alias Mobilizon.Events
alias Mobilizon.Events.FeedToken alias Mobilizon.Events.FeedToken
alias Mobilizon.Users.User
require Logger require Logger
@doc """ @doc """

View File

@ -1,13 +1,15 @@
defmodule MobilizonWeb.Resolvers.Group do defmodule MobilizonWeb.Resolvers.Group do
@moduledoc """ @moduledoc """
Handles the group-related GraphQL calls Handles the group-related GraphQL calls.
""" """
alias Mobilizon.Actors alias Mobilizon.Actors
alias Mobilizon.Actors.{Actor, Member} alias Mobilizon.Actors.{Actor, Member}
alias Mobilizon.Service.ActivityPub
alias Mobilizon.Service.ActivityPub.Activity alias Mobilizon.Service.ActivityPub.Activity
alias Mobilizon.Users.User alias Mobilizon.Users.User
alias Mobilizon.Service.ActivityPub
alias MobilizonWeb.API
alias MobilizonWeb.Resolvers.Person alias MobilizonWeb.Resolvers.Person
require Logger require Logger
@ -31,7 +33,8 @@ defmodule MobilizonWeb.Resolvers.Group do
def list_groups(_parent, %{page: page, limit: limit}, _resolution) do def list_groups(_parent, %{page: page, limit: limit}, _resolution) do
{ {
:ok, :ok,
Actors.list_groups(page, limit) page
|> Actors.list_groups(limit)
|> Enum.map(fn actor -> Person.proxify_pictures(actor) end) |> Enum.map(fn actor -> Person.proxify_pictures(actor) end)
} }
end end
@ -49,7 +52,7 @@ defmodule MobilizonWeb.Resolvers.Group do
%Activity{data: %{"object" => %{"type" => "Group"} = _object}}, %Activity{data: %{"object" => %{"type" => "Group"} = _object}},
%Actor{} = group %Actor{} = group
} <- } <-
MobilizonWeb.API.Groups.create_group( API.Groups.create_group(
user, user,
%{ %{
preferred_username: args.preferred_username, preferred_username: args.preferred_username,

View File

@ -1,15 +1,18 @@
defmodule MobilizonWeb.Resolvers.Report do defmodule MobilizonWeb.Resolvers.Report do
@moduledoc """ @moduledoc """
Handles the report-related GraphQL calls Handles the report-related GraphQL calls.
""" """
alias Mobilizon.Reports
alias Mobilizon.Reports.{Report, Note}
alias Mobilizon.Actors.Actor
alias Mobilizon.Actors
alias Mobilizon.Users.User
alias MobilizonWeb.API.Reports, as: ReportsAPI
import Mobilizon.Users.Guards import Mobilizon.Users.Guards
alias Mobilizon.Actors
alias Mobilizon.Actors.Actor
alias Mobilizon.Reports
alias Mobilizon.Reports.{Note, Report}
alias Mobilizon.Users.User
alias MobilizonWeb.API.Reports, as: ReportsAPI
def list_reports( def list_reports(
_parent, _parent,
%{page: page, limit: limit, status: status}, %{page: page, limit: limit, status: status},

View File

@ -1,16 +1,16 @@
defmodule MobilizonWeb.Resolvers.User do defmodule MobilizonWeb.Resolvers.User do
@moduledoc """ @moduledoc """
Handles the user-related GraphQL calls Handles the user-related GraphQL calls.
""" """
import Mobilizon.Users.Guards
alias Mobilizon.{Actors, Config, Users, Events} alias Mobilizon.{Actors, Config, Users, Events}
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Service.Users.{ResetPassword, Activation} alias Mobilizon.Service.Users.{Activation, ResetPassword}
alias Mobilizon.Users.User alias Mobilizon.Users.User
alias Mobilizon.Storage.Repo alias Mobilizon.Storage.Repo
import Mobilizon.Users.Guards
require Logger require Logger
@doc """ @doc """

View File

@ -4,12 +4,11 @@
# Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/lib/pleroma/reverse_proxy.ex # Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/lib/pleroma/reverse_proxy.ex
defmodule MobilizonWeb.ReverseProxy do defmodule MobilizonWeb.ReverseProxy do
@keep_req_headers ~w(accept user-agent accept-encoding cache-control if-modified-since) ++ @keep_req_headers ~w(accept user-agent accept-encoding cache-control
~w(if-unmodified-since if-none-match if-range range) if-modified-since if-unmodified-since if-none-match if-range range)
@resp_cache_headers ~w(etag date last-modified cache-control) @resp_cache_headers ~w(etag date last-modified cache-control)
@keep_resp_headers @resp_cache_headers ++ @keep_resp_headers @resp_cache_headers ++ ~w(content-type content-disposition
~w(content-type content-disposition content-encoding content-range) ++ content-encoding content-range accept-ranges vary)
~w(accept-ranges vary)
@default_cache_control_header "public, max-age=1209600" @default_cache_control_header "public, max-age=1209600"
@valid_resp_codes [200, 206, 304] @valid_resp_codes [200, 206, 304]
@max_read_duration :timer.seconds(30) @max_read_duration :timer.seconds(30)
@ -21,9 +20,11 @@ defmodule MobilizonWeb.ReverseProxy do
MobilizonWeb.ReverseProxy.call(conn, url, options) MobilizonWeb.ReverseProxy.call(conn, url, options)
It is not meant to be added into a plug pipeline, but to be called from another plug or controller. It is not meant to be added into a plug pipeline, but to be called from another
plug or controller.
Supports `#{inspect(@methods)}` HTTP methods, and only allows `#{inspect(@valid_resp_codes)}` status codes. Supports `#{inspect(@methods)}` HTTP methods, and only allows
`#{inspect(@valid_resp_codes)}` status codes.
Responses are chunked to the client while downloading from the upstream. Responses are chunked to the client while downloading from the upstream.
@ -32,34 +33,54 @@ defmodule MobilizonWeb.ReverseProxy do
* request: `#{inspect(@keep_req_headers)}` * request: `#{inspect(@keep_req_headers)}`
* response: `#{inspect(@keep_resp_headers)}` * response: `#{inspect(@keep_resp_headers)}`
If no caching headers (`#{inspect(@resp_cache_headers)}`) are returned by upstream, `cache-control` will be If no caching headers (`#{inspect(@resp_cache_headers)}`) are returned by
set to `#{inspect(@default_cache_control_header)}`. upstream, `cache-control` will be set to `#{inspect(@default_cache_control_header)}`.
Options: Options:
* `redirect_on_failure` (default `false`). Redirects the client to the real remote URL if there's any HTTP * `redirect_on_failure` (default `false`). Redirects the client to the real
errors. Any error during body processing will not be redirected as the response is chunked. This may expose remote URL if there's any HTTP errors. Any error during body processing will
remote URL, clients IPs, . not be redirected as the response is chunked. This may expose remote URL,
clients IPs, .
* `max_body_length` (default `#{inspect(@max_body_length)}`): limits the content length to be approximately the * `max_body_length` (default `#{inspect(@max_body_length)}`): limits the
specified length. It is validated with the `content-length` header and also verified when proxying. content length to be approximately the specified length. It is validated with
the `content-length` header and also verified when proxying.
* `max_read_duration` (default `#{inspect(@max_read_duration)}` ms): the total time the connection is allowed to * `max_read_duration` (default `#{inspect(@max_read_duration)}` ms): the total
read from the remote upstream. time the connection is allowed to read from the remote upstream.
* `inline_content_types`: * `inline_content_types`:
* `true` will not alter `content-disposition` (up to the upstream), * `true` will not alter `content-disposition` (up to the upstream),
* `false` will add `content-disposition: attachment` to any request, * `false` will add `content-disposition: attachment` to any request,
* a list of whitelisted content types * a list of whitelisted content types
* `keep_user_agent` will forward the client's user-agent to the upstream. This may be useful if the upstream is * `keep_user_agent` will forward the client's user-agent to the upstream.
doing content transformation (encoding, ) depending on the request. This may be useful if the upstream is doing content transformation
(encoding, ) depending on the request.
* `req_headers`, `resp_headers` additional headers. * `req_headers`, `resp_headers` additional headers.
* `http`: options for [hackney](https://github.com/benoitc/hackney). * `http`: options for [hackney](https://github.com/benoitc/hackney).
""" """
import Plug.Conn
alias Plug.Conn
require Logger
@type option ::
{:keep_user_agent, boolean}
| {:max_read_duration, :timer.time() | :infinity}
| {:max_body_length, non_neg_integer | :infinity}
| {:http, []}
| {:req_headers, [{String.t(), String.t()}]}
| {:resp_headers, [{String.t(), String.t()}]}
| {:inline_content_types, boolean | [String.t()]}
| {:redirect_on_failure, boolean}
@hackney Application.get_env(:mobilizon, :hackney, :hackney) @hackney Application.get_env(:mobilizon, :hackney, :hackney)
@httpoison Application.get_env(:mobilizon, :httpoison, HTTPoison) @httpoison Application.get_env(:mobilizon, :httpoison, HTTPoison)
@ -78,20 +99,7 @@ defmodule MobilizonWeb.ReverseProxy do
"video/quicktime" "video/quicktime"
] ]
require Logger @spec call(Plug.Conn.t(), url :: String.t(), [option]) :: Plug.Conn.t()
import Plug.Conn
@type option() ::
{:keep_user_agent, boolean}
| {:max_read_duration, :timer.time() | :infinity}
| {:max_body_length, non_neg_integer() | :infinity}
| {:http, []}
| {:req_headers, [{String.t(), String.t()}]}
| {:resp_headers, [{String.t(), String.t()}]}
| {:inline_content_types, boolean() | [String.t()]}
| {:redirect_on_failure, boolean()}
@spec call(Plug.Conn.t(), url :: String.t(), [option()]) :: Plug.Conn.t()
def call(_conn, _url, _opts \\ []) def call(_conn, _url, _opts \\ [])
def call(conn = %{method: method}, url, opts) when method in @methods do def call(conn = %{method: method}, url, opts) when method in @methods do
@ -114,7 +122,8 @@ defmodule MobilizonWeb.ReverseProxy do
response(conn, client, url, code, headers, opts) response(conn, client, url, code, headers, opts)
else else
{:ok, code, headers} -> {:ok, code, headers} ->
head_response(conn, url, code, headers, opts) conn
|> head_response(url, code, headers, opts)
|> halt() |> halt()
{:error, {:invalid_http_response, code}} -> {:error, {:invalid_http_response, code}} ->
@ -124,7 +133,7 @@ defmodule MobilizonWeb.ReverseProxy do
|> error_or_redirect( |> error_or_redirect(
url, url,
code, code,
"Request failed: " <> Plug.Conn.Status.reason_phrase(code), "Request failed: " <> Conn.Status.reason_phrase(code),
opts opts
) )
|> halt() |> halt()
@ -140,7 +149,7 @@ defmodule MobilizonWeb.ReverseProxy do
def call(conn, _, _) do def call(conn, _, _) do
conn conn
|> send_resp(400, Plug.Conn.Status.reason_phrase(400)) |> send_resp(400, Conn.Status.reason_phrase(400))
|> halt() |> halt()
end end

View File

@ -1,12 +1,13 @@
defmodule MobilizonWeb.Schema do defmodule MobilizonWeb.Schema do
@moduledoc """ @moduledoc """
GraphQL schema representation GraphQL schema representation.
""" """
use Absinthe.Schema use Absinthe.Schema
alias Mobilizon.{Actors, Events, Users, Addresses, Media, Reports} alias Mobilizon.{Actors, Addresses, Events, Media, Reports, Users}
alias Mobilizon.Actors.{Actor, Follower, Member} alias Mobilizon.Actors.{Actor, Follower, Member}
alias Mobilizon.Events.{Event, Comment, Participant} alias Mobilizon.Events.{Comment, Event, Participant}
alias Mobilizon.Storage.Repo alias Mobilizon.Storage.Repo
import_types(MobilizonWeb.Schema.Custom.UUID) import_types(MobilizonWeb.Schema.Custom.UUID)

View File

@ -1,13 +1,18 @@
defmodule MobilizonWeb.Schema.Actors.GroupType do defmodule MobilizonWeb.Schema.Actors.GroupType do
@moduledoc """ @moduledoc """
Schema representation for Group Schema representation for Group.
""" """
use Absinthe.Schema.Notation use Absinthe.Schema.Notation
import Absinthe.Resolution.Helpers, only: [dataloader: 1] import Absinthe.Resolution.Helpers, only: [dataloader: 1]
import_types(MobilizonWeb.Schema.Actors.MemberType)
alias MobilizonWeb.Resolvers.{Member, Group}
alias Mobilizon.Events alias Mobilizon.Events
alias MobilizonWeb.Resolvers.{Group, Member}
import_types(MobilizonWeb.Schema.Actors.MemberType)
@desc """ @desc """
Represents a group of actors Represents a group of actors
""" """

View File

@ -1,11 +1,14 @@
defmodule MobilizonWeb.Schema.AdminType do defmodule MobilizonWeb.Schema.AdminType do
@moduledoc """ @moduledoc """
Schema representation for ActionLog Schema representation for ActionLog.
""" """
use Absinthe.Schema.Notation use Absinthe.Schema.Notation
alias MobilizonWeb.Resolvers.Admin
alias Mobilizon.Reports.{Report, Note}
alias Mobilizon.Events.Event alias Mobilizon.Events.Event
alias Mobilizon.Reports.{Note, Report}
alias MobilizonWeb.Resolvers.Admin
@desc "An action log" @desc "An action log"
object :action_log do object :action_log do

View File

@ -1,14 +1,19 @@
defmodule MobilizonWeb.Schema.EventType do defmodule MobilizonWeb.Schema.EventType do
@moduledoc """ @moduledoc """
Schema representation for Event Schema representation for Event.
""" """
use Absinthe.Schema.Notation use Absinthe.Schema.Notation
alias Mobilizon.{Actors, Addresses}
import Absinthe.Resolution.Helpers, only: [dataloader: 1] import Absinthe.Resolution.Helpers, only: [dataloader: 1]
alias Mobilizon.{Actors, Addresses}
alias MobilizonWeb.Resolvers.{Event, Picture, Tag}
import_types(MobilizonWeb.Schema.AddressType) import_types(MobilizonWeb.Schema.AddressType)
import_types(MobilizonWeb.Schema.Events.ParticipantType) import_types(MobilizonWeb.Schema.Events.ParticipantType)
import_types(MobilizonWeb.Schema.TagType) import_types(MobilizonWeb.Schema.TagType)
alias MobilizonWeb.Resolvers.{Picture, Event, Tag}
@desc "An event" @desc "An event"
object :event do object :event do

View File

@ -1,12 +1,15 @@
defmodule MobilizonWeb.Schema.Events.FeedTokenType do defmodule MobilizonWeb.Schema.Events.FeedTokenType do
@moduledoc """ @moduledoc """
Schema representation for Participant Schema representation for Participant.
""" """
use Absinthe.Schema.Notation use Absinthe.Schema.Notation
import Absinthe.Resolution.Helpers, only: [dataloader: 1] import Absinthe.Resolution.Helpers, only: [dataloader: 1]
alias Mobilizon.{Actors, Users}
alias MobilizonWeb.Resolvers alias MobilizonWeb.Resolvers
alias Mobilizon.Users
alias Mobilizon.Actors
@desc "Represents a participant to an event" @desc "Represents a participant to an event"
object :feed_token do object :feed_token do

View File

@ -1,12 +1,15 @@
defmodule MobilizonWeb.Schema.Events.ParticipantType do defmodule MobilizonWeb.Schema.Events.ParticipantType do
@moduledoc """ @moduledoc """
Schema representation for Participant Schema representation for Participant.
""" """
use Absinthe.Schema.Notation use Absinthe.Schema.Notation
import Absinthe.Resolution.Helpers, only: [dataloader: 1] import Absinthe.Resolution.Helpers, only: [dataloader: 1]
alias Mobilizon.{Actors, Events}
alias MobilizonWeb.Resolvers alias MobilizonWeb.Resolvers
alias Mobilizon.Events
alias Mobilizon.Actors
@desc "Represents a participant to an event" @desc "Represents a participant to an event"
object :participant do object :participant do

View File

@ -36,7 +36,7 @@ defmodule MobilizonWeb.Upload do
alias Mobilizon.Config alias Mobilizon.Config
alias MobilizonWeb.MIME alias MobilizonWeb.{MIME, Upload, Uploaders}
require Logger require Logger
@ -69,8 +69,8 @@ defmodule MobilizonWeb.Upload do
with {:ok, upload} <- prepare_upload(upload, opts), with {:ok, upload} <- prepare_upload(upload, opts),
upload = %__MODULE__{upload | path: upload.path || "#{upload.id}/#{upload.name}"}, upload = %__MODULE__{upload | path: upload.path || "#{upload.id}/#{upload.name}"},
{:ok, upload} <- MobilizonWeb.Upload.Filter.filter(opts.filters, upload), {:ok, upload} <- Upload.Filter.filter(opts.filters, upload),
{:ok, url_spec} <- MobilizonWeb.Uploaders.Uploader.put_file(opts.uploader, upload) do {:ok, url_spec} <- Uploaders.Uploader.put_file(opts.uploader, upload) do
{:ok, {:ok,
%{ %{
"type" => opts.activity_type || get_type(upload.content_type), "type" => opts.activity_type || get_type(upload.content_type),
@ -98,7 +98,7 @@ defmodule MobilizonWeb.Upload do
with opts <- get_opts(opts), with opts <- get_opts(opts),
%URI{path: "/media/" <> path, host: host} <- URI.parse(url), %URI{path: "/media/" <> path, host: host} <- URI.parse(url),
{:same_host, true} <- {:same_host, host == MobilizonWeb.Endpoint.host()} do {:same_host, true} <- {:same_host, host == MobilizonWeb.Endpoint.host()} do
MobilizonWeb.Uploaders.Uploader.remove_file(opts.uploader, path) Uploaders.Uploader.remove_file(opts.uploader, path)
else else
%URI{} = _uri -> %URI{} = _uri ->
{:error, "URL doesn't match pattern"} {:error, "URL doesn't match pattern"}

View File

@ -11,9 +11,10 @@ defmodule MobilizonWeb.Upload.Filter.Dedupe do
alias MobilizonWeb.Upload alias MobilizonWeb.Upload
def filter(%Upload{name: name} = upload) do def filter(%Upload{name: name} = upload) do
extension = String.split(name, ".") |> List.last() extension = name |> String.split(".") |> List.last()
shasum = :crypto.hash(:sha256, File.read!(upload.tempfile)) |> Base.encode16(case: :lower) shasum = :crypto.hash(:sha256, File.read!(upload.tempfile)) |> Base.encode16(case: :lower)
filename = shasum <> "." <> extension filename = shasum <> "." <> extension
{:ok, %Upload{upload | id: shasum, path: filename}} {:ok, %Upload{upload | id: shasum, path: filename}}
end end
end end

View File

@ -3,14 +3,13 @@ defmodule MobilizonWeb.ActivityPub.ActorView do
alias Mobilizon.Actors alias Mobilizon.Actors
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Service.ActivityPub.Activity
alias Mobilizon.Service.ActivityPub alias Mobilizon.Service.ActivityPub
alias Mobilizon.Service.ActivityPub.Utils alias Mobilizon.Service.ActivityPub.{Activity, Utils}
@private_visibility_empty_collection %{elements: [], total: 0} @private_visibility_empty_collection %{elements: [], total: 0}
def render("actor.json", %{actor: actor}) do def render("actor.json", %{actor: actor}) do
public_key = Mobilizon.Service.ActivityPub.Utils.pem_to_public_key_pem(actor.keys) public_key = Utils.pem_to_public_key_pem(actor.keys)
%{ %{
"id" => actor.url, "id" => actor.url,

View File

@ -1,9 +1,10 @@
defmodule MobilizonWeb.JsonLD.ObjectView do defmodule MobilizonWeb.JsonLD.ObjectView do
use MobilizonWeb, :view use MobilizonWeb, :view
alias Mobilizon.Events.Event
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Addresses.Address alias Mobilizon.Addresses.Address
alias Mobilizon.Events.Event
alias MobilizonWeb.JsonLD.ObjectView alias MobilizonWeb.JsonLD.ObjectView
alias MobilizonWeb.MediaProxy alias MobilizonWeb.MediaProxy

View File

@ -4,12 +4,12 @@ defmodule MobilizonWeb.PageView do
""" """
use MobilizonWeb, :view use MobilizonWeb, :view
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Service.ActivityPub.Utils alias Mobilizon.Service.ActivityPub.{Converter, Utils}
alias Mobilizon.Service.Metadata alias Mobilizon.Service.Metadata
alias Mobilizon.Service.MetadataUtils alias Mobilizon.Service.MetadataUtils
def render("actor.activity-json", %{conn: %{assigns: %{object: actor}}}) do def render("actor.activity-json", %{conn: %{assigns: %{object: actor}}}) do
public_key = Mobilizon.Service.ActivityPub.Utils.pem_to_public_key_pem(actor.keys) public_key = Utils.pem_to_public_key_pem(actor.keys)
%{ %{
"id" => Actor.build_url(actor.preferred_username, :page), "id" => Actor.build_url(actor.preferred_username, :page),
@ -47,12 +47,12 @@ defmodule MobilizonWeb.PageView do
def render("event.activity-json", %{conn: %{assigns: %{object: event}}}) do def render("event.activity-json", %{conn: %{assigns: %{object: event}}}) do
event event
|> Mobilizon.Service.ActivityPub.Converters.Event.model_to_as() |> Converter.Event.model_to_as()
|> Map.merge(Utils.make_json_ld_header()) |> Map.merge(Utils.make_json_ld_header())
end end
def render("comment.activity-json", %{conn: %{assigns: %{object: comment}}}) do def render("comment.activity-json", %{conn: %{assigns: %{object: comment}}}) do
comment = Mobilizon.Service.ActivityPub.Converters.Comment.model_to_as(comment) comment = Converter.Comment.model_to_as(comment)
%{ %{
"actor" => comment["actor"], "actor" => comment["actor"],
@ -84,7 +84,7 @@ defmodule MobilizonWeb.PageView do
end end
end end
defp index_file_path() do defp index_file_path do
Path.join(Application.app_dir(:mobilizon, "priv/static"), "index.html") Path.join(Application.app_dir(:mobilizon, "priv/static"), "index.html")
end end
end end

View File

@ -5,28 +5,19 @@
defmodule Mobilizon.Service.ActivityPub do defmodule Mobilizon.Service.ActivityPub do
@moduledoc """ @moduledoc """
# ActivityPub # ActivityPub context.
Every ActivityPub method
""" """
alias Mobilizon.Config import Mobilizon.Service.ActivityPub.{Utils, Visibility}
alias Mobilizon.Events
alias Mobilizon.Events.{Event, Comment, Participant}
alias Mobilizon.Service.ActivityPub.Transmogrifier
alias Mobilizon.Service.WebFinger
alias Mobilizon.Actors alias Mobilizon.{Actors, Config, Events}
alias Mobilizon.Actors.{Actor, Follower} alias Mobilizon.Actors.{Actor, Follower}
alias Mobilizon.Events.{Comment, Event, Participant}
alias Mobilizon.Service.Federator alias Mobilizon.Service.ActivityPub.{Activity, Converter, Convertible, Relay, Transmogrifier}
alias Mobilizon.Service.{Federator, WebFinger}
alias Mobilizon.Service.HTTPSignatures.Signature alias Mobilizon.Service.HTTPSignatures.Signature
alias Mobilizon.Service.ActivityPub.{Activity, Convertible}
require Logger require Logger
import Mobilizon.Service.ActivityPub.Utils
import Mobilizon.Service.ActivityPub.Visibility
@doc """ @doc """
Get recipients for an activity or object Get recipients for an activity or object
@ -452,7 +443,8 @@ defmodule Mobilizon.Service.ActivityPub do
def leave(object, actor, local \\ true) def leave(object, actor, local \\ true)
# TODO: If we want to use this for exclusion we need to have an extra field for the actor that excluded the participant # TODO: If we want to use this for exclusion we need to have an extra field
# for the actor that excluded the participant
def leave( def leave(
%Event{id: event_id, url: event_url} = event, %Event{id: event_id, url: event_url} = event,
%Actor{id: actor_id, url: actor_url} = _actor, %Actor{id: actor_id, url: actor_url} = _actor,
@ -543,7 +535,8 @@ defmodule Mobilizon.Service.ActivityPub do
if public && !is_delete_activity?(activity) && Config.get([:instance, :allow_relay]) do if public && !is_delete_activity?(activity) && Config.get([:instance, :allow_relay]) do
Logger.info(fn -> "Relaying #{activity.data["id"]} out" end) Logger.info(fn -> "Relaying #{activity.data["id"]} out" end)
Mobilizon.Service.ActivityPub.Relay.publish(activity)
Relay.publish(activity)
end end
followers = followers =
@ -702,7 +695,7 @@ defmodule Mobilizon.Service.ActivityPub do
%Activity{ %Activity{
recipients: ["https://www.w3.org/ns/activitystreams#Public"], recipients: ["https://www.w3.org/ns/activitystreams#Public"],
actor: event.organizer_actor.url, actor: event.organizer_actor.url,
data: event |> Mobilizon.Service.ActivityPub.Converters.Event.model_to_as(), data: Converter.Event.model_to_as(event),
local: local local: local
} }
end end
@ -713,7 +706,7 @@ defmodule Mobilizon.Service.ActivityPub do
%Activity{ %Activity{
recipients: ["https://www.w3.org/ns/activitystreams#Public"], recipients: ["https://www.w3.org/ns/activitystreams#Public"],
actor: comment.actor.url, actor: comment.actor.url,
data: comment |> Mobilizon.Service.ActivityPub.Converters.Comment.model_to_as(), data: Converter.Comment.model_to_as(comment),
local: local local: local
} }
end end

View File

@ -1,16 +1,11 @@
defmodule Mobilizon.Service.ActivityPub.Converter do defmodule Mobilizon.Service.ActivityPub.Converter do
@moduledoc """ @moduledoc """
Converter behaviour Converter behaviour.
This module allows to convert from ActivityStream format to our own internal one, and back This module allows to convert from ActivityStream format to our own internal
one, and back.
""" """
@callback as_to_model_data(map()) :: map()
@callback model_to_as(struct()) :: map()
end
defprotocol Mobilizon.Service.ActivityPub.Convertible do @callback as_to_model_data(map) :: map
@type activitystreams :: map() @callback model_to_as(struct) :: map
@spec model_to_as(t) :: activitystreams
def model_to_as(convertible)
end end

View File

@ -1,19 +1,27 @@
defmodule Mobilizon.Service.ActivityPub.Converters.Actor do defmodule Mobilizon.Service.ActivityPub.Converter.Actor do
@moduledoc """ @moduledoc """
Actor converter Actor converter.
This module allows to convert events from ActivityStream format to our own internal one, and back This module allows to convert events from ActivityStream format to our own
internal one, and back.
""" """
alias Mobilizon.Actors.Actor, as: ActorModel alias Mobilizon.Actors.Actor, as: ActorModel
alias Mobilizon.Service.ActivityPub.Converter alias Mobilizon.Service.ActivityPub.{Converter, Convertible}
@behaviour Converter @behaviour Converter
defimpl Convertible, for: ActorModel do
alias Mobilizon.Service.ActivityPub.Converter.Actor, as: ActorConverter
defdelegate model_to_as(actor), to: ActorConverter
end
@doc """ @doc """
Converts an AP object data to our internal data structure Converts an AP object data to our internal data structure.
""" """
@impl Converter @impl Converter
@spec as_to_model_data(map()) :: map() @spec as_to_model_data(map) :: map
def as_to_model_data(object) do def as_to_model_data(object) do
avatar = avatar =
object["icon"]["url"] && object["icon"]["url"] &&
@ -43,10 +51,10 @@ defmodule Mobilizon.Service.ActivityPub.Converters.Actor do
end end
@doc """ @doc """
Convert an actor struct to an ActivityStream representation Convert an actor struct to an ActivityStream representation.
""" """
@impl Converter @impl Converter
@spec model_to_as(ActorModel.t()) :: map() @spec model_to_as(ActorModel.t()) :: map
def model_to_as(%ActorModel{} = actor) do def model_to_as(%ActorModel{} = actor) do
%{ %{
"type" => Atom.to_string(actor.type), "type" => Atom.to_string(actor.type),
@ -63,9 +71,3 @@ defmodule Mobilizon.Service.ActivityPub.Converters.Actor do
} }
end end
end end
defimpl Mobilizon.Service.ActivityPub.Convertible, for: Mobilizon.Actors.Actor do
alias Mobilizon.Service.ActivityPub.Converters.Actor, as: ActorConverter
defdelegate model_to_as(actor), to: ActorConverter
end

View File

@ -1,21 +1,21 @@
defmodule Mobilizon.Service.ActivityPub.Converters.Address do defmodule Mobilizon.Service.ActivityPub.Converter.Address do
@moduledoc """ @moduledoc """
Flag converter Address converter.
This module allows to convert reports from ActivityStream format to our own internal one, and back. This module allows to convert reports from ActivityStream format to our own
internal one, and back.
Note: Reports are named Flag in AS.
""" """
alias Mobilizon.Addresses.Address, as: AddressModel alias Mobilizon.Addresses.Address, as: AddressModel
alias Mobilizon.Service.ActivityPub.Converter alias Mobilizon.Service.ActivityPub.Converter
@behaviour Converter @behaviour Converter
@doc """ @doc """
Converts an AP object data to our internal data structure Converts an AP object data to our internal data structure.
""" """
@impl Converter @impl Converter
@spec as_to_model_data(map()) :: map() @spec as_to_model_data(map) :: map
def as_to_model_data(object) do def as_to_model_data(object) do
res = %{ res = %{
"description" => object["name"], "description" => object["name"],
@ -48,10 +48,10 @@ defmodule Mobilizon.Service.ActivityPub.Converters.Address do
end end
@doc """ @doc """
Convert an event struct to an ActivityStream representation Convert an event struct to an ActivityStream representation.
""" """
@impl Converter @impl Converter
@spec model_to_as(AddressModel.t()) :: map() @spec model_to_as(AddressModel.t()) :: map
def model_to_as(%AddressModel{} = address) do def model_to_as(%AddressModel{} = address) do
res = %{ res = %{
"type" => "Place", "type" => "Place",

View File

@ -1,25 +1,35 @@
defmodule Mobilizon.Service.ActivityPub.Converters.Comment do defmodule Mobilizon.Service.ActivityPub.Converter.Comment do
@moduledoc """ @moduledoc """
Comment converter Comment converter.
This module allows to convert events from ActivityStream format to our own internal one, and back This module allows to convert events from ActivityStream format to our own
internal one, and back.
""" """
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Events.Comment, as: CommentModel alias Mobilizon.Events.Comment, as: CommentModel
alias Mobilizon.Events.Event alias Mobilizon.Events.Event
alias Mobilizon.Service.ActivityPub.Converter
alias Mobilizon.Service.ActivityPub alias Mobilizon.Service.ActivityPub
alias Mobilizon.Service.ActivityPub.{Converter, Convertible}
require Logger require Logger
@behaviour Converter @behaviour Converter
defimpl Convertible, for: CommentModel do
alias Mobilizon.Service.ActivityPub.Converter.Comment, as: CommentConverter
defdelegate model_to_as(comment), to: CommentConverter
end
@doc """ @doc """
Converts an AP object data to our internal data structure Converts an AP object data to our internal data structure.
""" """
@impl Converter @impl Converter
@spec as_to_model_data(map()) :: map() @spec as_to_model_data(map) :: map
def as_to_model_data(object) do def as_to_model_data(object) do
{:ok, %Actor{id: actor_id}} = ActivityPub.get_or_fetch_by_url(object["actor"]) {:ok, %Actor{id: actor_id}} = ActivityPub.get_or_fetch_by_url(object["actor"])
Logger.debug("Inserting full comment") Logger.debug("Inserting full comment")
Logger.debug(inspect(object)) Logger.debug(inspect(object))
@ -62,6 +72,7 @@ defmodule Mobilizon.Service.ActivityPub.Converters.Comment do
end end
else else
Logger.debug("No parent object for this comment") Logger.debug("No parent object for this comment")
data data
end end
@ -72,7 +83,7 @@ defmodule Mobilizon.Service.ActivityPub.Converters.Comment do
Make an AS comment object from an existing `Comment` structure. Make an AS comment object from an existing `Comment` structure.
""" """
@impl Converter @impl Converter
@spec model_to_as(CommentModel.t()) :: map() @spec model_to_as(CommentModel.t()) :: map
def model_to_as(%CommentModel{} = comment) do def model_to_as(%CommentModel{} = comment) do
object = %{ object = %{
"type" => "Note", "type" => "Note",
@ -91,9 +102,3 @@ defmodule Mobilizon.Service.ActivityPub.Converters.Comment do
end end
end end
end end
defimpl Mobilizon.Service.ActivityPub.Convertible, for: Mobilizon.Events.Comment do
alias Mobilizon.Service.ActivityPub.Converters.Comment, as: CommentConverter
defdelegate model_to_as(comment), to: CommentConverter
end

View File

@ -1,31 +1,36 @@
defmodule Mobilizon.Service.ActivityPub.Converters.Event do defmodule Mobilizon.Service.ActivityPub.Converter.Event do
@moduledoc """ @moduledoc """
Event converter Event converter.
This module allows to convert events from ActivityStream format to our own internal one, and back This module allows to convert events from ActivityStream format to our own
internal one, and back.
""" """
alias Mobilizon.Actors
alias Mobilizon.Media
alias Mobilizon.Media.Picture
alias Mobilizon.Actors.Actor
alias Mobilizon.Events.Event, as: EventModel
alias Mobilizon.Service.ActivityPub.Converter
alias Mobilizon.Service.ActivityPub.Converters.Address, as: AddressConverter
alias Mobilizon.Service.ActivityPub.Utils
alias Mobilizon.Events
alias Mobilizon.Events.Tag
alias Mobilizon.Addresses
alias Mobilizon.Addresses.Address
@behaviour Converter alias Mobilizon.{Actors, Addresses, Events, Media}
alias Mobilizon.Actors.Actor
alias Mobilizon.Addresses.Address
alias Mobilizon.Events.Event, as: EventModel
alias Mobilizon.Events.{EventOptions, Tag}
alias Mobilizon.Media.Picture
alias Mobilizon.Service.ActivityPub.{Converter, Convertible, Utils}
alias Mobilizon.Service.ActivityPub.Converter.Address, as: AddressConverter
alias Mobilizon.Service.ActivityPub.Converter.Picture, as: PictureConverter
require Logger require Logger
@behaviour Converter
defimpl Convertible, for: EventModel do
alias Mobilizon.Service.ActivityPub.Converter.Event, as: EventConverter
defdelegate model_to_as(event), to: EventConverter
end
@doc """ @doc """
Converts an AP object data to our internal data structure Converts an AP object data to our internal data structure.
""" """
@impl Converter @impl Converter
@spec as_to_model_data(map()) :: map() @spec as_to_model_data(map) :: map
def as_to_model_data(object) do def as_to_model_data(object) do
Logger.debug("event as_to_model_data") Logger.debug("event as_to_model_data")
Logger.debug(inspect(object)) Logger.debug(inspect(object))
@ -73,15 +78,58 @@ defmodule Mobilizon.Service.ActivityPub.Converters.Event do
{:ok, Map.put(entity, "options", options)} {:ok, Map.put(entity, "options", options)}
else else
err -> error ->
{:error, err} {:error, error}
end end
end end
@doc """
Convert an event struct to an ActivityStream representation.
"""
@impl Converter
@spec model_to_as(EventModel.t()) :: map
def model_to_as(%EventModel{} = event) do
to =
if event.visibility == :public,
do: ["https://www.w3.org/ns/activitystreams#Public"],
else: [event.organizer_actor.followers_url]
res = %{
"type" => "Event",
"to" => to,
"cc" => [],
"attributedTo" => event.organizer_actor.url,
"name" => event.title,
"actor" => event.organizer_actor.url,
"uuid" => event.uuid,
"category" => event.category,
"content" => event.description,
"publish_at" => (event.publish_at || event.inserted_at) |> date_to_string(),
"updated_at" => event.updated_at |> date_to_string(),
"mediaType" => "text/html",
"startTime" => event.begins_on |> date_to_string(),
"joinOptions" => to_string(event.join_options),
"endTime" => event.ends_on |> date_to_string(),
"tag" => event.tags |> build_tags(),
"id" => event.url,
"url" => event.url
}
res =
if is_nil(event.physical_address),
do: res,
else: Map.put(res, "location", AddressConverter.model_to_as(event.physical_address))
if is_nil(event.picture),
do: res,
else: Map.put(res, "attachment", [PictureConverter.model_to_as(event.picture)])
end
# Get only elements that we have in EventOptions # Get only elements that we have in EventOptions
@spec get_options(map) :: map
defp get_options(object) do defp get_options(object) do
keys = keys =
Mobilizon.Events.EventOptions EventOptions
|> struct |> struct
|> Map.keys() |> Map.keys()
|> List.delete(:__struct__) |> List.delete(:__struct__)
@ -93,6 +141,7 @@ defmodule Mobilizon.Service.ActivityPub.Converters.Event do
end) end)
end end
@spec get_address(map | binary | nil) :: integer | nil
defp get_address(address_url) when is_bitstring(address_url) do defp get_address(address_url) when is_bitstring(address_url) do
get_address(%{"id" => address_url}) get_address(%{"id" => address_url})
end end
@ -117,8 +166,9 @@ defmodule Mobilizon.Service.ActivityPub.Converters.Event do
defp get_address(nil), do: nil defp get_address(nil), do: nil
@spec do_get_address(map) :: integer | nil
defp do_get_address(map) do defp do_get_address(map) do
map = Mobilizon.Service.ActivityPub.Converters.Address.as_to_model_data(map) map = Mobilizon.Service.ActivityPub.Converter.Address.as_to_model_data(map)
case Addresses.create_address(map) do case Addresses.create_address(map) do
{:ok, %Address{id: address_id}} -> {:ok, %Address{id: address_id}} ->
@ -129,6 +179,7 @@ defmodule Mobilizon.Service.ActivityPub.Converters.Event do
end end
end end
@spec fetch_tags([String.t()]) :: [String.t()]
defp fetch_tags(tags) do defp fetch_tags(tags) do
Logger.debug("fetching tags") Logger.debug("fetching tags")
@ -143,6 +194,7 @@ defmodule Mobilizon.Service.ActivityPub.Converters.Event do
end) end)
end end
@spec build_tags([String.t()]) :: String.t()
defp build_tags(tags) do defp build_tags(tags) do
Enum.map(tags, fn %Tag{} = tag -> Enum.map(tags, fn %Tag{} = tag ->
%{ %{
@ -163,54 +215,7 @@ defmodule Mobilizon.Service.ActivityPub.Converters.Event do
end end
end end
@doc """ @spec date_to_string(DateTime.t() | nil) :: String.t()
Convert an event struct to an ActivityStream representation
"""
@impl Converter
@spec model_to_as(EventModel.t()) :: map()
def model_to_as(%EventModel{} = event) do
to =
if event.visibility == :public,
do: ["https://www.w3.org/ns/activitystreams#Public"],
else: [event.organizer_actor.followers_url]
res = %{
"type" => "Event",
"to" => to,
"cc" => [],
"attributedTo" => event.organizer_actor.url,
"name" => event.title,
"actor" => event.organizer_actor.url,
"uuid" => event.uuid,
"category" => event.category,
"content" => event.description,
"publish_at" => (event.publish_at || event.inserted_at) |> date_to_string(),
"updated_at" => event.updated_at |> date_to_string(),
"mediaType" => "text/html",
"startTime" => event.begins_on |> date_to_string(),
"endTime" => event.ends_on |> date_to_string(),
"joinOptions" => to_string(event.join_options),
"tag" => event.tags |> build_tags(),
"id" => event.url,
"url" => event.url
}
res =
if is_nil(event.physical_address),
do: res,
else: Map.put(res, "location", AddressConverter.model_to_as(event.physical_address))
if is_nil(event.picture),
do: res,
else: Map.put(res, "attachment", [Utils.make_picture_data(event.picture)])
end
defp date_to_string(nil), do: nil defp date_to_string(nil), do: nil
defp date_to_string(date), do: DateTime.to_iso8601(date) defp date_to_string(%DateTime{} = date), do: DateTime.to_iso8601(date)
end
defimpl Mobilizon.Service.ActivityPub.Convertible, for: Mobilizon.Events.Event do
alias Mobilizon.Service.ActivityPub.Converters.Event, as: EventConverter
defdelegate model_to_as(event), to: EventConverter
end end

View File

@ -1,11 +1,13 @@
defmodule Mobilizon.Service.ActivityPub.Converters.Flag do defmodule Mobilizon.Service.ActivityPub.Converter.Flag do
@moduledoc """ @moduledoc """
Flag converter Flag converter.
This module allows to convert reports from ActivityStream format to our own internal one, and back. This module allows to convert reports from ActivityStream format to our own
internal one, and back.
Note: Reports are named Flag in AS. Note: Reports are named Flag in AS.
""" """
alias Mobilizon.Actors alias Mobilizon.Actors
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Events alias Mobilizon.Events
@ -16,10 +18,10 @@ defmodule Mobilizon.Service.ActivityPub.Converters.Flag do
@behaviour Converter @behaviour Converter
@doc """ @doc """
Converts an AP object data to our internal data structure Converts an AP object data to our internal data structure.
""" """
@impl Converter @impl Converter
@spec as_to_model_data(map()) :: map() @spec as_to_model_data(map) :: map
def as_to_model_data(object) do def as_to_model_data(object) do
with params <- as_to_model(object) do with params <- as_to_model(object) do
%{ %{
@ -33,6 +35,21 @@ defmodule Mobilizon.Service.ActivityPub.Converters.Flag do
end end
end end
@doc """
Convert an event struct to an ActivityStream representation
"""
@impl Converter
@spec model_to_as(EventModel.t()) :: map
def model_to_as(%Report{} = report) do
%{
"type" => "Flag",
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
"actor" => report.reporter.url,
"id" => report.url
}
end
@spec as_to_model(map) :: map
def as_to_model(%{"object" => objects} = object) do def as_to_model(%{"object" => objects} = object) do
with {:ok, %Actor{} = reporter} <- Actors.get_actor_by_url(object["actor"]), with {:ok, %Actor{} = reporter} <- Actors.get_actor_by_url(object["actor"]),
%Actor{} = reported <- %Actor{} = reported <-
@ -72,18 +89,4 @@ defmodule Mobilizon.Service.ActivityPub.Converters.Flag do
} }
end end
end end
@doc """
Convert an event struct to an ActivityStream representation
"""
@impl Converter
@spec model_to_as(EventModel.t()) :: map()
def model_to_as(%Report{} = report) do
%{
"type" => "Flag",
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
"actor" => report.reporter.url,
"id" => report.url
}
end
end end

View File

@ -0,0 +1,31 @@
defmodule Mobilizon.Service.ActivityPub.Converter.Participant do
@moduledoc """
Participant converter.
This module allows to convert reports from ActivityStream format to our own
internal one, and back.
"""
alias Mobilizon.Events.Participant, as: ParticipantModel
alias Mobilizon.Service.ActivityPub.Convertible
defimpl Convertible, for: ParticipantModel do
alias Mobilizon.Service.ActivityPub.Converter.Participant, as: ParticipantConverter
defdelegate model_to_as(participant), to: ParticipantConverter
end
@doc """
Convert an event struct to an ActivityStream representation.
"""
@spec model_to_as(ParticipantModel.t()) :: map
def model_to_as(%ParticipantModel{} = participant) do
%{
"type" => "Join",
"id" => participant.url,
"actor" => participant.actor.url,
"object" => participant.event.url
}
end
end

View File

@ -0,0 +1,28 @@
defmodule Mobilizon.Service.ActivityPub.Converter.Picture do
@moduledoc """
Picture converter.
This module allows to convert events from ActivityStream format to our own
internal one, and back.
"""
alias Mobilizon.Media.Picture, as: PictureModel
@doc """
Convert a picture struct to an ActivityStream representation.
"""
@spec model_to_as(PictureModel.t()) :: map
def model_to_as(%PictureModel{file: file}) do
%{
"type" => "Document",
"url" => [
%{
"type" => "Link",
"mediaType" => file.content_type,
"href" => file.url
}
],
"name" => file.name
}
end
end

View File

@ -1,29 +0,0 @@
defmodule Mobilizon.Service.ActivityPub.Converters.Participant do
@moduledoc """
Flag converter
This module allows to convert reports from ActivityStream format to our own internal one, and back.
Note: Reports are named Flag in AS.
"""
alias Mobilizon.Events.Participant, as: ParticipantModel
@doc """
Convert an event struct to an ActivityStream representation
"""
@spec model_to_as(ParticipantModel.t()) :: map()
def model_to_as(%ParticipantModel{} = participant) do
%{
"type" => "Join",
"id" => participant.url,
"actor" => participant.actor.url,
"object" => participant.event.url
}
end
defimpl Mobilizon.Service.ActivityPub.Convertible, for: Mobilizon.Events.Participant do
alias Mobilizon.Service.ActivityPub.Converters.Participant, as: ParticipantConverter
defdelegate model_to_as(event), to: ParticipantConverter
end
end

View File

@ -0,0 +1,10 @@
defprotocol Mobilizon.Service.ActivityPub.Convertible do
@moduledoc """
Convertible protocol.
"""
@type activity_streams :: map
@spec model_to_as(t) :: activity_streams
def model_to_as(convertible)
end

View File

@ -5,13 +5,13 @@
defmodule Mobilizon.Service.ActivityPub.Relay do defmodule Mobilizon.Service.ActivityPub.Relay do
@moduledoc """ @moduledoc """
Handles following and unfollowing relays and instances Handles following and unfollowing relays and instances.
""" """
alias Mobilizon.Actors alias Mobilizon.Actors
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Service.ActivityPub.Activity
alias Mobilizon.Service.ActivityPub alias Mobilizon.Service.ActivityPub
alias Mobilizon.Service.ActivityPub.{Activity, Transmogrifier}
alias MobilizonWeb.API.Follows alias MobilizonWeb.API.Follows
@ -72,9 +72,7 @@ defmodule Mobilizon.Service.ActivityPub.Relay do
def publish(%Activity{data: %{"object" => object}} = _activity) do def publish(%Activity{data: %{"object" => object}} = _activity) do
with %Actor{id: actor_id} = actor <- get_actor(), with %Actor{id: actor_id} = actor <- get_actor(),
{:ok, object} <- {:ok, object} <-
Mobilizon.Service.ActivityPub.Transmogrifier.fetch_obj_helper_as_activity_streams( Transmogrifier.fetch_obj_helper_as_activity_streams(object) do
object
) do
ActivityPub.announce(actor, object, "#{object["id"]}/announces/#{actor_id}", true, false) ActivityPub.announce(actor, object, "#{object["id"]}/announces/#{actor_id}", true, false)
else else
e -> e ->

View File

@ -7,12 +7,13 @@ defmodule Mobilizon.Service.ActivityPub.Transmogrifier do
@moduledoc """ @moduledoc """
A module to handle coding from internal to wire ActivityPub and back. A module to handle coding from internal to wire ActivityPub and back.
""" """
alias Mobilizon.Actors alias Mobilizon.Actors
alias Mobilizon.Actors.{Actor, Follower} alias Mobilizon.Actors.{Actor, Follower}
alias Mobilizon.Events alias Mobilizon.Events
alias Mobilizon.Events.{Event, Comment, Participant} alias Mobilizon.Events.{Comment, Event, Participant}
alias Mobilizon.Service.ActivityPub alias Mobilizon.Service.ActivityPub
alias Mobilizon.Service.ActivityPub.{Visibility, Utils} alias Mobilizon.Service.ActivityPub.{Converter, Convertible, Utils, Visibility}
require Logger require Logger
@ -24,7 +25,8 @@ defmodule Mobilizon.Service.ActivityPub.Transmogrifier do
if is_binary(Enum.at(actor, 0)) do if is_binary(Enum.at(actor, 0)) do
Enum.at(actor, 0) Enum.at(actor, 0)
else else
Enum.find(actor, fn %{"type" => type} -> type in ["Person", "Service", "Application"] end) actor
|> Enum.find(fn %{"type" => type} -> type in ["Person", "Service", "Application"] end)
|> Map.get("id") |> Map.get("id")
end end
end end
@ -120,7 +122,7 @@ defmodule Mobilizon.Service.ActivityPub.Transmogrifier do
def handle_incoming(%{"id" => ""}), do: :error def handle_incoming(%{"id" => ""}), do: :error
def handle_incoming(%{"type" => "Flag"} = data) do def handle_incoming(%{"type" => "Flag"} = data) do
with params <- Mobilizon.Service.ActivityPub.Converters.Flag.as_to_model(data) do with params <- Converter.Flag.as_to_model(data) do
params = %{ params = %{
reporter_url: params["reporter"].url, reporter_url: params["reporter"].url,
reported_actor_url: params["reported"].url, reported_actor_url: params["reported"].url,
@ -866,7 +868,7 @@ defmodule Mobilizon.Service.ActivityPub.Transmogrifier do
def fetch_obj_helper_as_activity_streams(object) do def fetch_obj_helper_as_activity_streams(object) do
with {:ok, object} <- fetch_obj_helper(object) do with {:ok, object} <- fetch_obj_helper(object) do
{:ok, Mobilizon.Service.ActivityPub.Convertible.model_to_as(object)} {:ok, Convertible.model_to_as(object)}
end end
end end
end end

View File

@ -5,25 +5,20 @@
defmodule Mobilizon.Service.ActivityPub.Utils do defmodule Mobilizon.Service.ActivityPub.Utils do
@moduledoc """ @moduledoc """
# Utils # Various ActivityPub related utils.
Various utils
""" """
alias Ecto.Changeset alias Ecto.Changeset
alias Mobilizon.Addresses alias Mobilizon.{Actors, Addresses, Events, Reports, Users}
alias Mobilizon.Addresses.Address
alias Mobilizon.Actors
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Events alias Mobilizon.Addresses.Address
alias Mobilizon.Events.{Comment, Event} alias Mobilizon.Events.{Comment, Event}
alias Mobilizon.Media.Picture alias Mobilizon.Media.Picture
alias Mobilizon.Reports
alias Mobilizon.Reports.Report alias Mobilizon.Reports.Report
alias Mobilizon.Service.ActivityPub.{Activity, Converters} alias Mobilizon.Service.ActivityPub.{Activity, Converter}
alias Mobilizon.Service.Federator
alias Mobilizon.Storage.Repo alias Mobilizon.Storage.Repo
alias Mobilizon.Users
alias MobilizonWeb.{Email, Endpoint} alias MobilizonWeb.{Email, Endpoint}
alias MobilizonWeb.Router.Helpers, as: Routes alias MobilizonWeb.Router.Helpers, as: Routes
@ -70,7 +65,8 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
_ -> 5 _ -> 5
end end
Mobilizon.Service.Federator.enqueue(:publish, activity, priority) Federator.enqueue(:publish, activity, priority)
:ok :ok
end end
@ -125,7 +121,7 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
def insert_full_object(%{"object" => %{"type" => "Event"} = object_data, "type" => "Create"}) def insert_full_object(%{"object" => %{"type" => "Event"} = object_data, "type" => "Create"})
when is_map(object_data) do when is_map(object_data) do
with {:ok, object_data} <- with {:ok, object_data} <-
Converters.Event.as_to_model_data(object_data), Converter.Event.as_to_model_data(object_data),
{:ok, %Event{} = event} <- Events.create_event(object_data) do {:ok, %Event{} = event} <- Events.create_event(object_data) do
{:ok, event} {:ok, event}
end end
@ -145,7 +141,7 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
""" """
def insert_full_object(%{"object" => %{"type" => "Note"} = object_data, "type" => "Create"}) def insert_full_object(%{"object" => %{"type" => "Note"} = object_data, "type" => "Create"})
when is_map(object_data) do when is_map(object_data) do
with data <- Converters.Comment.as_to_model_data(object_data), with data <- Converter.Comment.as_to_model_data(object_data),
{:ok, %Comment{} = comment} <- Events.create_comment(data) do {:ok, %Comment{} = comment} <- Events.create_comment(data) do
{:ok, comment} {:ok, comment}
else else
@ -161,7 +157,7 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
""" """
def insert_full_object(%{"type" => "Flag"} = object_data) def insert_full_object(%{"type" => "Flag"} = object_data)
when is_map(object_data) do when is_map(object_data) do
with data <- Converters.Flag.as_to_model_data(object_data), with data <- Converter.Flag.as_to_model_data(object_data),
{:ok, %Report{} = report} <- Reports.create_report(data) do {:ok, %Report{} = report} <- Reports.create_report(data) do
Enum.each(Users.list_moderators(), fn moderator -> Enum.each(Users.list_moderators(), fn moderator ->
moderator moderator
@ -193,7 +189,7 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
when is_map(object_data) do when is_map(object_data) do
with {:event_not_found, %Event{} = event} <- with {:event_not_found, %Event{} = event} <-
{:event_not_found, Events.get_event_by_url(event_url)}, {:event_not_found, Events.get_event_by_url(event_url)},
{:ok, object_data} <- Converters.Event.as_to_model_data(object_data), {:ok, object_data} <- Converter.Event.as_to_model_data(object_data),
{:ok, %Event{} = event} <- Events.update_event(event, object_data) do {:ok, %Event{} = event} <- Events.update_event(event, object_data) do
{:ok, event} {:ok, event}
end end
@ -205,7 +201,7 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
}) })
when is_map(object_data) and type_actor in @actor_types do when is_map(object_data) and type_actor in @actor_types do
with {:ok, %Actor{} = actor} <- Actors.get_actor_by_url(actor_url), with {:ok, %Actor{} = actor} <- Actors.get_actor_by_url(actor_url),
object_data <- Converters.Actor.as_to_model_data(object_data), object_data <- Converter.Actor.as_to_model_data(object_data),
{:ok, %Actor{} = actor} <- Actors.update_actor(actor, object_data) do {:ok, %Actor{} = actor} <- Actors.update_actor(actor, object_data) do
{:ok, actor} {:ok, actor}
end end
@ -251,21 +247,10 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
end end
@doc """ @doc """
Convert a picture model into an AS Link representation Convert a picture model into an AS Link representation.
""" """
# TODO: Move me to Mobilizon.Service.ActivityPub.Converters def make_picture_data(%Picture{} = picture) do
def make_picture_data(%Picture{file: file} = _picture) do Converter.Picture.model_to_as(picture)
%{
"type" => "Document",
"url" => [
%{
"type" => "Link",
"mediaType" => file.content_type,
"href" => file.url
}
],
"name" => file.name
}
end end
@doc """ @doc """
@ -274,7 +259,7 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
def make_picture_data(picture) when is_map(picture) do def make_picture_data(picture) when is_map(picture) do
with {:ok, %{"url" => [%{"href" => url, "mediaType" => content_type}], "size" => size}} <- with {:ok, %{"url" => [%{"href" => url, "mediaType" => content_type}], "size" => size}} <-
MobilizonWeb.Upload.store(picture.file), MobilizonWeb.Upload.store(picture.file),
{:ok, %Picture{file: _file} = pic} <- {:ok, %Picture{file: _file} = picture} <-
Mobilizon.Media.create_picture(%{ Mobilizon.Media.create_picture(%{
"file" => %{ "file" => %{
"url" => url, "url" => url,
@ -284,7 +269,7 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
}, },
"actor_id" => picture.actor_id "actor_id" => picture.actor_id
}) do }) do
make_picture_data(pic) Converter.Picture.model_to_as(picture)
end end
end end
@ -348,7 +333,7 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
if is_nil(metadata.options) do if is_nil(metadata.options) do
res res
else else
options = struct(Mobilizon.Events.EventOptions, metadata.options) |> Map.from_struct() options = Events.EventOptions |> struct(metadata.options) |> Map.from_struct()
Enum.reduce(options, res, fn {key, value}, acc -> Enum.reduce(options, res, fn {key, value}, acc ->
(value && Map.put(acc, camelize(key), value)) || (value && Map.put(acc, camelize(key), value)) ||

View File

@ -1,13 +1,13 @@
defmodule Mobilizon.Service.Admin.ActionLogService do defmodule Mobilizon.Service.Admin.ActionLogService do
@moduledoc """ @moduledoc """
Module to handle action log creations Module to handle action log creations.
""" """
alias Mobilizon.Users
alias Mobilizon.Users.User
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Admin alias Mobilizon.Admin
alias Mobilizon.Admin.ActionLog alias Mobilizon.Admin.ActionLog
alias Mobilizon.Users
alias Mobilizon.Users.User
@doc """ @doc """
Log an admin action Log an admin action

View File

@ -1,15 +1,14 @@
defmodule Mobilizon.Service.EmailChecker do defmodule Mobilizon.Service.EmailChecker do
@moduledoc """ @moduledoc """
Provides a function to test emails against a "not so bad" regex Provides a function to test emails against a "not so bad" regex.
""" """
# TODO: simplify me!
@email_regex ~r/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ @email_regex ~r/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
@doc """ @doc """
Returns whether the email is valid Returns whether the email is valid.
""" """
@spec valid?(String.t()) :: boolean() @spec valid?(String.t()) :: boolean
def valid?(email) do def valid?(email), do: email =~ @email_regex
email =~ @email_regex
end
end end

View File

@ -1,23 +1,24 @@
defmodule Mobilizon.Service.Export.Feed do defmodule Mobilizon.Service.Export.Feed do
@moduledoc """ @moduledoc """
Serve Atom Syndication Feeds Serve Atom Syndication Feeds.
""" """
alias Mobilizon.Users.User
alias Mobilizon.Users
alias Mobilizon.Actors
alias Mobilizon.Actors.Actor
alias Mobilizon.Events
alias Mobilizon.Events.{Event, FeedToken}
alias Atomex.{Feed, Entry}
import MobilizonWeb.Gettext import MobilizonWeb.Gettext
alias Atomex.{Entry, Feed}
alias Mobilizon.{Actors, Events, Users}
alias Mobilizon.Actors.Actor
alias Mobilizon.Events.{Event, FeedToken}
alias Mobilizon.Users.User
alias MobilizonWeb.{Endpoint, MediaProxy}
alias MobilizonWeb.Router.Helpers, as: Routes alias MobilizonWeb.Router.Helpers, as: Routes
alias MobilizonWeb.Endpoint
alias MobilizonWeb.MediaProxy
require Logger require Logger
@version Mix.Project.config()[:version] @version Mix.Project.config()[:version]
def version(), do: @version def version, do: @version
@spec create_cache(String.t()) :: {:commit, String.t()} | {:ignore, any()} @spec create_cache(String.t()) :: {:commit, String.t()} | {:ignore, any()}
def create_cache("actor_" <> name) do def create_cache("actor_" <> name) do
@ -57,7 +58,11 @@ defmodule Mobilizon.Service.Export.Feed do
@spec build_actor_feed(Actor.t(), list(), boolean()) :: String.t() @spec build_actor_feed(Actor.t(), list(), boolean()) :: String.t()
defp build_actor_feed(%Actor{} = actor, events, public \\ true) do defp build_actor_feed(%Actor{} = actor, events, public \\ true) do
display_name = Actor.display_name(actor) display_name = Actor.display_name(actor)
self_url = Routes.feed_url(Endpoint, :actor, actor.preferred_username, "atom") |> URI.decode()
self_url =
Endpoint
|> Routes.feed_url(:actor, actor.preferred_username, "atom")
|> URI.decode()
title = title =
if public, if public,
@ -66,8 +71,8 @@ defmodule Mobilizon.Service.Export.Feed do
# Title uses default instance language # Title uses default instance language
feed = feed =
Feed.new( self_url
self_url, |> Feed.new(
DateTime.utc_now(), DateTime.utc_now(),
Gettext.gettext(MobilizonWeb.Gettext, title, actor: display_name) Gettext.gettext(MobilizonWeb.Gettext, title, actor: display_name)
) )
@ -102,7 +107,8 @@ defmodule Mobilizon.Service.Export.Feed do
description = event.description || "" description = event.description || ""
entry = entry =
Entry.new(event.url, event.publish_at || event.inserted_at, event.title) event.url
|> Entry.new(event.publish_at || event.inserted_at, event.title)
|> Entry.link(event.url, rel: "alternate", type: "text/html") |> Entry.link(event.url, rel: "alternate", type: "text/html")
|> Entry.content({:cdata, description}, type: "html") |> Entry.content({:cdata, description}, type: "html")
|> Entry.published(event.publish_at || event.inserted_at) |> Entry.published(event.publish_at || event.inserted_at)
@ -156,14 +162,11 @@ defmodule Mobilizon.Service.Export.Feed do
# Build an atom feed from actor and it's public events # Build an atom feed from actor and it's public events
@spec build_user_feed(list(), User.t(), String.t()) :: String.t() @spec build_user_feed(list(), User.t(), String.t()) :: String.t()
defp build_user_feed(events, %User{email: email}, token) do defp build_user_feed(events, %User{email: email}, token) do
self_url = Routes.feed_url(Endpoint, :going, token, "atom") |> URI.decode() self_url = Endpoint |> Routes.feed_url(:going, token, "atom") |> URI.decode()
# Title uses default instance language # Title uses default instance language
Feed.new( self_url
self_url, |> Feed.new(DateTime.utc_now(), gettext("Feed for %{email} on Mobilizon", email: email))
DateTime.utc_now(),
gettext("Feed for %{email} on Mobilizon", email: email)
)
|> Feed.link(self_url, rel: "self") |> Feed.link(self_url, rel: "self")
|> Feed.generator("Mobilizon", uri: "https://joinmobilizon.org", version: version()) |> Feed.generator("Mobilizon", uri: "https://joinmobilizon.org", version: version())
|> Feed.entries(Enum.map(events, &get_entry/1)) |> Feed.entries(Enum.map(events, &get_entry/1))

View File

@ -1,14 +1,12 @@
defmodule Mobilizon.Service.Export.ICalendar do defmodule Mobilizon.Service.Export.ICalendar do
@moduledoc """ @moduledoc """
Export an event to iCalendar format Export an event to iCalendar format.
""" """
alias Mobilizon.Events.{Event, FeedToken} alias Mobilizon.{Actors, Events, Users}
alias Mobilizon.Events
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Actors alias Mobilizon.Events.{Event, FeedToken}
alias Mobilizon.Users.User alias Mobilizon.Users.User
alias Mobilizon.Users
@doc """ @doc """
Export a public event to iCalendar format. Export a public event to iCalendar format.

View File

@ -5,10 +5,11 @@
defmodule Mobilizon.Service.Formatter do defmodule Mobilizon.Service.Formatter do
@moduledoc """ @moduledoc """
Formats input text to structured data, extracts mentions and hashtags Formats input text to structured data, extracts mentions and hashtags.
""" """
alias Mobilizon.Actors.Actor
alias Mobilizon.Actors alias Mobilizon.Actors
alias Mobilizon.Actors.Actor
alias Mobilizon.Service.HTML alias Mobilizon.Service.HTML
@link_regex ~r"((?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~%:/?#[\]@!\$&'\(\)\*\+,;=.]+)|[0-9a-z+\-\.]+:[0-9a-z$-_.+!*'(),]+"ui @link_regex ~r"((?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~%:/?#[\]@!\$&'\(\)\*\+,;=.]+)|[0-9a-z+\-\.]+:[0-9a-z$-_.+!*'(),]+"ui
@ -93,7 +94,8 @@ defmodule Mobilizon.Service.Formatter do
end end
def html_escape(text, "text/plain") do def html_escape(text, "text/plain") do
Regex.split(@link_regex, text, include_captures: true) @link_regex
|> Regex.split(text, include_captures: true)
|> Enum.map_every(2, fn chunk -> |> Enum.map_every(2, fn chunk ->
{:safe, part} = Phoenix.HTML.html_escape(chunk) {:safe, part} = Phoenix.HTML.html_escape(chunk)
part part

View File

@ -2,9 +2,11 @@ defmodule Mobilizon.Service.Geospatial.Addok do
@moduledoc """ @moduledoc """
[Addok](https://github.com/addok/addok) backend. [Addok](https://github.com/addok/addok) backend.
""" """
alias Mobilizon.Service.Geospatial.Provider
require Logger
alias Mobilizon.Addresses.Address alias Mobilizon.Addresses.Address
alias Mobilizon.Service.Geospatial.Provider
require Logger
@behaviour Provider @behaviour Provider
@ -68,7 +70,7 @@ defmodule Mobilizon.Service.Geospatial.Addok do
region: Map.get(properties, "state"), region: Map.get(properties, "state"),
description: Map.get(properties, "name") || street_address(properties), description: Map.get(properties, "name") || street_address(properties),
floor: Map.get(properties, "floor"), floor: Map.get(properties, "floor"),
geom: Map.get(geometry, "coordinates") |> Provider.coordinates(), geom: geometry |> Map.get("coordinates") |> Provider.coordinates(),
postal_code: Map.get(properties, "postcode"), postal_code: Map.get(properties, "postcode"),
street: properties |> street_address() street: properties |> street_address()
} }

View File

@ -1,15 +1,17 @@
defmodule Mobilizon.Service.Geospatial do defmodule Mobilizon.Service.Geospatial do
@moduledoc """ @moduledoc """
Module to load the service adapter defined inside the configuration Module to load the service adapter defined inside the configuration.
See `Mobilizon.Service.Geospatial.Provider` See `Mobilizon.Service.Geospatial.Provider`.
""" """
@doc """ @doc """
Returns the appropriate service adapter Returns the appropriate service adapter.
According to the config behind `config :mobilizon, Mobilizon.Service.Geospatial, service: Mobilizon.Service.Geospatial.Module` According to the config behind
`config :mobilizon, Mobilizon.Service.Geospatial,
service: Mobilizon.Service.Geospatial.Module`
""" """
@spec service() :: module() @spec service :: module
def service(), do: Application.get_env(:mobilizon, __MODULE__) |> get_in([:service]) def service, do: get_in(Application.get_env(:mobilizon, __MODULE__), [:service])
end end

View File

@ -1,11 +1,13 @@
defmodule Mobilizon.Service.Geospatial.GoogleMaps do defmodule Mobilizon.Service.Geospatial.GoogleMaps do
@moduledoc """ @moduledoc """
Google Maps [Geocoding service](https://developers.google.com/maps/documentation/geocoding/intro) Google Maps [Geocoding service](https://developers.google.com/maps/documentation/geocoding/intro).
Note: Endpoint is hardcoded to Google Maps API Note: Endpoint is hardcoded to Google Maps API.
""" """
alias Mobilizon.Service.Geospatial.Provider
alias Mobilizon.Addresses.Address alias Mobilizon.Addresses.Address
alias Mobilizon.Service.Geospatial.Provider
require Logger require Logger
@behaviour Provider @behaviour Provider

View File

@ -8,8 +8,10 @@ defmodule Mobilizon.Service.Geospatial.MapQuest do
* `:open_data` Whether to use [Open Data or Licenced Data](https://developer.mapquest.com/documentation/open/). * `:open_data` Whether to use [Open Data or Licenced Data](https://developer.mapquest.com/documentation/open/).
Defaults to `true` Defaults to `true`
""" """
alias Mobilizon.Service.Geospatial.Provider
alias Mobilizon.Addresses.Address alias Mobilizon.Addresses.Address
alias Mobilizon.Service.Geospatial.Provider
require Logger require Logger
@behaviour Provider @behaviour Provider

View File

@ -2,8 +2,10 @@ defmodule Mobilizon.Service.Geospatial.Nominatim do
@moduledoc """ @moduledoc """
[Nominatim](https://wiki.openstreetmap.org/wiki/Nominatim) backend. [Nominatim](https://wiki.openstreetmap.org/wiki/Nominatim) backend.
""" """
alias Mobilizon.Service.Geospatial.Provider
alias Mobilizon.Addresses.Address alias Mobilizon.Addresses.Address
alias Mobilizon.Service.Geospatial.Provider
require Logger require Logger
@behaviour Provider @behaviour Provider
@ -66,23 +68,22 @@ defmodule Mobilizon.Service.Geospatial.Nominatim do
@spec process_data(map()) :: Address.t() @spec process_data(map()) :: Address.t()
defp process_data(%{"address" => address} = body) do defp process_data(%{"address" => address} = body) do
try do %Address{
%Address{ country: Map.get(address, "country"),
country: Map.get(address, "country"), locality: Map.get(address, "city"),
locality: Map.get(address, "city"), region: Map.get(address, "state"),
region: Map.get(address, "state"), description: description(body),
description: description(body), floor: Map.get(address, "floor"),
floor: Map.get(address, "floor"), geom: [Map.get(body, "lon"), Map.get(body, "lat")] |> Provider.coordinates(),
geom: [Map.get(body, "lon"), Map.get(body, "lat")] |> Provider.coordinates(), postal_code: Map.get(address, "postcode"),
postal_code: Map.get(address, "postcode"), street: street_address(address),
street: street_address(address), origin_id: "osm:" <> to_string(Map.get(body, "osm_id"))
origin_id: "osm:" <> to_string(Map.get(body, "osm_id")) }
} rescue
rescue error in ArgumentError ->
e in ArgumentError -> Logger.warn(inspect(error))
Logger.warn(inspect(e))
nil nil
end
end end
@spec street_address(map()) :: String.t() @spec street_address(map()) :: String.t()

View File

@ -2,9 +2,11 @@ defmodule Mobilizon.Service.Geospatial.Photon do
@moduledoc """ @moduledoc """
[Photon](https://photon.komoot.de) backend. [Photon](https://photon.komoot.de) backend.
""" """
alias Mobilizon.Service.Geospatial.Provider
require Logger
alias Mobilizon.Addresses.Address alias Mobilizon.Addresses.Address
alias Mobilizon.Service.Geospatial.Provider
require Logger
@behaviour Provider @behaviour Provider
@ -70,7 +72,7 @@ defmodule Mobilizon.Service.Geospatial.Photon do
region: Map.get(properties, "state"), region: Map.get(properties, "state"),
description: Map.get(properties, "name") || street_address(properties), description: Map.get(properties, "name") || street_address(properties),
floor: Map.get(properties, "floor"), floor: Map.get(properties, "floor"),
geom: Map.get(geometry, "coordinates") |> Provider.coordinates(), geom: geometry |> Map.get("coordinates") |> Provider.coordinates(),
postal_code: Map.get(properties, "postcode"), postal_code: Map.get(properties, "postcode"),
street: properties |> street_address() street: properties |> street_address()
} }

View File

@ -14,11 +14,13 @@ defmodule Mobilizon.Service.Geospatial.Provider do
## Shared options ## Shared options
* `:user_agent` User-Agent string to send to the backend. Defaults to `"Mobilizon"` * `:user_agent` User-Agent string to send to the backend. Defaults to `"Mobilizon"`
* `:lang` Lang in which to prefer results. Used as a request parameter or through an `Accept-Language` HTTP header. * `:lang` Lang in which to prefer results. Used as a request parameter or
Defaults to `"en"`. through an `Accept-Language` HTTP header. Defaults to `"en"`.
* `:limit` Maximum limit for the number of results returned by the backend. Defaults to `10` * `:limit` Maximum limit for the number of results returned by the backend.
* `:api_key` Allows to override the API key (if the backend requires one) set inside the configuration. Defaults to `10`
* `:endpoint` Allows to override the endpoint set inside the configuration * `:api_key` Allows to override the API key (if the backend requires one) set
inside the configuration.
* `:endpoint` Allows to override the endpoint set inside the configuration.
""" """
alias Mobilizon.Addresses.Address alias Mobilizon.Addresses.Address
@ -35,38 +37,40 @@ defmodule Mobilizon.Service.Geospatial.Provider do
iex> geocode(48.11, -1.77) iex> geocode(48.11, -1.77)
%Address{} %Address{}
""" """
@callback geocode(longitude :: number(), latitude :: number(), options :: keyword()) :: @callback geocode(longitude :: number, latitude :: number, options :: keyword) :: [Address.t()]
list(Address.t())
@doc """ @doc """
Search for an address Search for an address
## Options ## Options
In addition to [the shared options](#module-shared-options), `c:search/2` also accepts the following options: In addition to [the shared options](#module-shared-options), `c:search/2` also
accepts the following options:
* `coords` Map of coordinates (ex: `%{lon: 48.11, lat: -1.77}`) allowing to give a geographic priority to the search. * `coords` Map of coordinates (ex: `%{lon: 48.11, lat: -1.77}`) allowing to
Defaults to `nil` give a geographic priority to the search. Defaults to `nil`.
## Examples ## Examples
iex> search("10 rue Jangot") iex> search("10 rue Jangot")
%Address{} %Address{}
""" """
@callback search(address :: String.t(), options :: keyword()) :: list(Address.t()) @callback search(address :: String.t(), options :: keyword) :: [Address.t()]
@doc """ @doc """
Returns a `Geo.Point` for given coordinates Returns a `Geo.Point` for given coordinates
""" """
@spec coordinates(list(number()), number()) :: Geo.Point.t() @spec coordinates([number], number) :: Geo.Point.t()
def coordinates(coords, srid \\ 4326) def coordinates(coords, srid \\ 4326)
def coordinates([x, y], srid) when is_number(x) and is_number(y), def coordinates([x, y], srid) when is_number(x) and is_number(y) do
do: %Geo.Point{coordinates: {x, y}, srid: srid} %Geo.Point{coordinates: {x, y}, srid: srid}
end
def coordinates([x, y], srid) when is_bitstring(x) and is_bitstring(y), def coordinates([x, y], srid) when is_bitstring(x) and is_bitstring(y) do
do: %Geo.Point{coordinates: {String.to_float(x), String.to_float(y)}, srid: srid} %Geo.Point{coordinates: {String.to_float(x), String.to_float(y)}, srid: srid}
end
@spec coordinates(any()) :: nil @spec coordinates(any) :: nil
def coordinates(_, _), do: nil def coordinates(_, _), do: nil
end end

View File

@ -1,9 +1,9 @@
defmodule Mobilizon.Service.Users.Activation do defmodule Mobilizon.Service.Users.Activation do
@moduledoc false @moduledoc false
alias Mobilizon.Service.Users.Tools
alias Mobilizon.Users alias Mobilizon.Users
alias Mobilizon.Users.User alias Mobilizon.Users.User
alias Mobilizon.Service.Users.Tools
alias MobilizonWeb.Email alias MobilizonWeb.Email

View File

@ -6,7 +6,7 @@ defmodule Mobilizon.ActorsTest do
import Mobilizon.Factory import Mobilizon.Factory
alias Mobilizon.{Actors, Config, Users} alias Mobilizon.{Actors, Config, Users}
alias Mobilizon.Actors.{Actor, Member, Follower, Bot} alias Mobilizon.Actors.{Actor, Bot, Follower, Member}
alias Mobilizon.Media.File, as: FileModel alias Mobilizon.Media.File, as: FileModel
alias Mobilizon.Service.ActivityPub alias Mobilizon.Service.ActivityPub
alias Mobilizon.Storage.Page alias Mobilizon.Storage.Page
@ -311,9 +311,6 @@ defmodule Mobilizon.ActorsTest do
end end
describe "groups" do describe "groups" do
alias Mobilizon.Actors
alias Mobilizon.Actors.Actor
@valid_attrs %{ @valid_attrs %{
summary: "some description", summary: "some description",
suspended: true, suspended: true,
@ -356,11 +353,7 @@ defmodule Mobilizon.ActorsTest do
end end
end end
alias Mobilizon.Actors
describe "bots" do describe "bots" do
alias Mobilizon.Actors.Bot
@valid_attrs %{source: "some source", type: "some type"} @valid_attrs %{source: "some source", type: "some type"}
@update_attrs %{source: "some updated source", type: "some updated type"} @update_attrs %{source: "some updated source", type: "some updated type"}
@invalid_attrs %{source: nil, type: nil} @invalid_attrs %{source: nil, type: nil}
@ -419,9 +412,6 @@ defmodule Mobilizon.ActorsTest do
end end
describe "followers" do describe "followers" do
alias Mobilizon.Actors.Follower
alias Mobilizon.Actors.Actor
@valid_attrs %{approved: true} @valid_attrs %{approved: true}
@update_attrs %{approved: false} @update_attrs %{approved: false}
@invalid_attrs %{approved: nil} @invalid_attrs %{approved: nil}
@ -529,9 +519,6 @@ defmodule Mobilizon.ActorsTest do
end end
describe "members" do describe "members" do
alias Mobilizon.Actors.Member
alias Mobilizon.Actors.Actor
@valid_attrs %{role: :member} @valid_attrs %{role: :member}
@update_attrs %{role: :not_approved} @update_attrs %{role: :not_approved}
@invalid_attrs %{role: nil} @invalid_attrs %{role: nil}

View File

@ -3,7 +3,9 @@ defmodule Mobilizon.EventsTest do
import Mobilizon.Factory import Mobilizon.Factory
alias Mobilizon.Actors.Actor
alias Mobilizon.Events alias Mobilizon.Events
alias Mobilizon.Events.{Comment, Event, Participant, Session, Tag, TagRelation, Track}
alias Mobilizon.Storage.Page alias Mobilizon.Storage.Page
@event_valid_attrs %{ @event_valid_attrs %{
@ -17,8 +19,6 @@ defmodule Mobilizon.EventsTest do
} }
describe "events" do describe "events" do
alias Mobilizon.Events.Event
setup do setup do
actor = insert(:actor) actor = insert(:actor)
event = insert(:event, organizer_actor: actor, visibility: :public) event = insert(:event, organizer_actor: actor, visibility: :public)
@ -176,8 +176,6 @@ defmodule Mobilizon.EventsTest do
end end
describe "tags" do describe "tags" do
alias Mobilizon.Events.Tag
@valid_attrs %{title: "some title"} @valid_attrs %{title: "some title"}
@update_attrs %{title: "some updated title"} @update_attrs %{title: "some updated title"}
@invalid_attrs %{title: nil} @invalid_attrs %{title: nil}
@ -227,9 +225,6 @@ defmodule Mobilizon.EventsTest do
end end
describe "tags_relations" do describe "tags_relations" do
alias Mobilizon.Events.TagRelation
alias Mobilizon.Events.Tag
setup do setup do
tag1 = insert(:tag) tag1 = insert(:tag)
tag2 = insert(:tag) tag2 = insert(:tag)
@ -302,9 +297,6 @@ defmodule Mobilizon.EventsTest do
end end
describe "participants" do describe "participants" do
alias Mobilizon.Events.{Participant, Event}
alias Mobilizon.Actors.Actor
@valid_attrs %{role: :creator} @valid_attrs %{role: :creator}
@update_attrs %{role: :moderator} @update_attrs %{role: :moderator}
@invalid_attrs %{role: :no_such_role} @invalid_attrs %{role: :no_such_role}
@ -369,8 +361,6 @@ defmodule Mobilizon.EventsTest do
end end
describe "sessions" do describe "sessions" do
alias Mobilizon.Events.Session
@valid_attrs %{ @valid_attrs %{
audios_urls: "some audios_urls", audios_urls: "some audios_urls",
language: "some language", language: "some language",
@ -463,8 +453,6 @@ defmodule Mobilizon.EventsTest do
end end
describe "tracks" do describe "tracks" do
alias Mobilizon.Events.Track
@valid_attrs %{color: "some color", description: "some description", name: "some name"} @valid_attrs %{color: "some color", description: "some description", name: "some name"}
@update_attrs %{ @update_attrs %{
color: "some updated color", color: "some updated color",
@ -525,8 +513,6 @@ defmodule Mobilizon.EventsTest do
end end
describe "comments" do describe "comments" do
alias Mobilizon.Events.Comment
@valid_attrs %{text: "some text"} @valid_attrs %{text: "some text"}
@update_attrs %{text: "some updated text"} @update_attrs %{text: "some updated text"}
@invalid_attrs %{text: nil, url: nil} @invalid_attrs %{text: nil, url: nil}

View File

@ -4,17 +4,22 @@
# Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/test/web/activity_pub/activity_pub_test.exs # Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/test/web/activity_pub/activity_pub_test.exs
defmodule Mobilizon.Service.ActivityPub.ActivityPubTest do defmodule Mobilizon.Service.ActivityPub.ActivityPubTest do
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
use Mobilizon.DataCase use Mobilizon.DataCase
import Mock
import Mobilizon.Factory import Mobilizon.Factory
alias Mobilizon.Actors.Actor
alias Mobilizon.Events alias Mobilizon.Events
alias Mobilizon.Events.Event alias Mobilizon.Events.Event
alias Mobilizon.Actors.Actor
alias Mobilizon.Service.HTTPSignatures.Signature
alias Mobilizon.Service.ActivityPub alias Mobilizon.Service.ActivityPub
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney alias Mobilizon.Service.ActivityPub.Converter
import Mock alias Mobilizon.Service.HTTPSignatures.Signature
alias MobilizonWeb.ActivityPub.ActorView
setup_all do setup_all do
HTTPoison.start() HTTPoison.start()
@ -28,7 +33,7 @@ defmodule Mobilizon.Service.ActivityPub.ActivityPubTest do
Signature.sign(actor, %{ Signature.sign(actor, %{
host: "example.com", host: "example.com",
"content-length": 15, "content-length": 15,
digest: Jason.encode!(%{id: "my_id"}) |> Signature.build_digest(), digest: %{id: "my_id"} |> Jason.encode!() |> Signature.build_digest(),
"(request-target)": Signature.generate_request_target("POST", "/inbox"), "(request-target)": Signature.generate_request_target("POST", "/inbox"),
date: Signature.generate_date_header() date: Signature.generate_date_header()
}) })
@ -160,7 +165,7 @@ defmodule Mobilizon.Service.ActivityPub.ActivityPubTest do
test "it creates an update activity with the new actor data" do test "it creates an update activity with the new actor data" do
actor = insert(:actor) actor = insert(:actor)
actor_data = MobilizonWeb.ActivityPub.ActorView.render("actor.json", %{actor: actor}) actor_data = ActorView.render("actor.json", %{actor: actor})
actor_data = Map.put(actor_data, "summary", @updated_actor_summary) actor_data = Map.put(actor_data, "summary", @updated_actor_summary)
{:ok, update, updated_actor} = {:ok, update, updated_actor} =
@ -189,7 +194,7 @@ defmodule Mobilizon.Service.ActivityPub.ActivityPubTest do
test "it creates an update activity with the new event data" do test "it creates an update activity with the new event data" do
actor = insert(:actor) actor = insert(:actor)
event = insert(:event, organizer_actor: actor) event = insert(:event, organizer_actor: actor)
event_data = Mobilizon.Service.ActivityPub.Converters.Event.model_to_as(event) event_data = Converter.Event.model_to_as(event)
event_data = Map.put(event_data, "startTime", @updated_start_time) event_data = Map.put(event_data, "startTime", @updated_start_time)
{:ok, update, updated_event} = {:ok, update, updated_event} =

View File

@ -1,7 +1,8 @@
defmodule Mobilizon.Service.ActivityPub.Converters.ActorTest do defmodule Mobilizon.Service.ActivityPub.Converter.ActorTest do
use Mobilizon.DataCase use Mobilizon.DataCase
alias Mobilizon.Service.ActivityPub.Converters.Actor, as: ActorConverter
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Service.ActivityPub.Converter.Actor, as: ActorConverter
describe "actor to AS" do describe "actor to AS" do
test "valid actor to as" do test "valid actor to as" do

View File

@ -4,6 +4,8 @@
# Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/test/web/activity_pub/transmogrifier_test.exs # Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/test/web/activity_pub/transmogrifier_test.exs
defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
use Mobilizon.DataCase use Mobilizon.DataCase
import Mobilizon.Factory import Mobilizon.Factory
@ -13,9 +15,10 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
alias Mobilizon.Events alias Mobilizon.Events
alias Mobilizon.Events.{Comment, Event, Participant} alias Mobilizon.Events.{Comment, Event, Participant}
alias Mobilizon.Service.ActivityPub alias Mobilizon.Service.ActivityPub
alias Mobilizon.Service.ActivityPub.{Utils, Activity} alias Mobilizon.Service.ActivityPub.{Activity, Utils}
alias Mobilizon.Service.ActivityPub.Transmogrifier alias Mobilizon.Service.ActivityPub.Transmogrifier
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
alias MobilizonWeb.API
setup_all do setup_all do
HTTPoison.start() HTTPoison.start()
@ -784,7 +787,9 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
assert :error == Transmogrifier.handle_incoming(reject_data) assert :error == Transmogrifier.handle_incoming(reject_data)
# Organiser is not present since we use factories directly # Organiser is not present since we use factories directly
assert Events.list_participants_for_event(event.id) |> Enum.map(& &1.id) == assert event.id
|> Events.list_participants_for_event()
|> Enum.map(& &1.id) ==
[] []
end end
@ -812,9 +817,10 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
assert activity.data["actor"] == participant_url assert activity.data["actor"] == participant_url
# The only participant left is the organizer # The only participant left is the organizer
assert Events.list_participants_for_event(event.id) |> Enum.map(& &1.id) == [ assert event.id
organizer_participation.id |> Events.list_participants_for_event()
] |> Enum.map(& &1.id) ==
[organizer_participation.id]
end end
test "it refuses Leave activities when actor is the only organizer" do test "it refuses Leave activities when actor is the only organizer" do
@ -841,7 +847,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
other_actor = insert(:actor) other_actor = insert(:actor)
{:ok, activity, _} = {:ok, activity, _} =
MobilizonWeb.API.Comments.create_comment( API.Comments.create_comment(
actor.preferred_username, actor.preferred_username,
"hey, @#{other_actor.preferred_username}, how are ya? #2hu" "hey, @#{other_actor.preferred_username}, how are ya? #2hu"
) )
@ -877,8 +883,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
test "it adds the json-ld context and the conversation property" do test "it adds the json-ld context and the conversation property" do
actor = insert(:actor) actor = insert(:actor)
{:ok, activity, _} = {:ok, activity, _} = API.Comments.create_comment(actor.preferred_username, "hey")
MobilizonWeb.API.Comments.create_comment(actor.preferred_username, "hey")
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data) {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
@ -888,8 +893,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
test "it sets the 'attributedTo' property to the actor of the object if it doesn't have one" do test "it sets the 'attributedTo' property to the actor of the object if it doesn't have one" do
actor = insert(:actor) actor = insert(:actor)
{:ok, activity, _} = {:ok, activity, _} = API.Comments.create_comment(actor.preferred_username, "hey")
MobilizonWeb.API.Comments.create_comment(actor.preferred_username, "hey")
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data) {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
@ -899,8 +903,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
test "it strips internal hashtag data" do test "it strips internal hashtag data" do
actor = insert(:actor) actor = insert(:actor)
{:ok, activity, _} = {:ok, activity, _} = API.Comments.create_comment(actor.preferred_username, "#2hu")
MobilizonWeb.API.Comments.create_comment(actor.preferred_username, "#2hu")
expected_tag = %{ expected_tag = %{
"href" => MobilizonWeb.Endpoint.url() <> "/tags/2hu", "href" => MobilizonWeb.Endpoint.url() <> "/tags/2hu",
@ -916,8 +919,7 @@ defmodule Mobilizon.Service.ActivityPub.TransmogrifierTest do
test "it strips internal fields" do test "it strips internal fields" do
actor = insert(:actor) actor = insert(:actor)
{:ok, activity, _} = {:ok, activity, _} = API.Comments.create_comment(actor.preferred_username, "#2hu")
MobilizonWeb.API.Comments.create_comment(actor.preferred_username, "#2hu")
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data) {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)

View File

@ -1,10 +1,14 @@
defmodule Mobilizon.Service.ActivityPub.UtilsTest do defmodule Mobilizon.Service.ActivityPub.UtilsTest do
use Mobilizon.DataCase
import Mobilizon.Factory
alias Mobilizon.Service.ActivityPub.Utils
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
alias MobilizonWeb.Router.Helpers, as: Routes
use Mobilizon.DataCase
import Mobilizon.Factory
alias Mobilizon.Service.ActivityPub.{Converter, Utils}
alias MobilizonWeb.Endpoint alias MobilizonWeb.Endpoint
alias MobilizonWeb.Router.Helpers, as: Routes
setup_all do setup_all do
HTTPoison.start() HTTPoison.start()
@ -24,7 +28,7 @@ defmodule Mobilizon.Service.ActivityPub.UtilsTest do
"id" => Routes.page_url(Endpoint, :comment, reply.uuid), "id" => Routes.page_url(Endpoint, :comment, reply.uuid),
"inReplyTo" => comment.url, "inReplyTo" => comment.url,
"attributedTo" => reply.actor.url "attributedTo" => reply.actor.url
} == Mobilizon.Service.ActivityPub.Converters.Comment.model_to_as(reply) } == Converter.Comment.model_to_as(reply)
end end
test "comment data from map" do test "comment data from map" do

View File

@ -1,12 +1,15 @@
defmodule Mobilizon.Service.Admin.ActionLogServiceTest do defmodule Mobilizon.Service.Admin.ActionLogServiceTest do
@moduledoc """ @moduledoc """
Test the ActionLogService module Test the ActionLogService module.
""" """
use Mobilizon.DataCase use Mobilizon.DataCase
import Mobilizon.Service.Admin.ActionLogService
alias Mobilizon.Reports.{Report, Note}
alias Mobilizon.Admin.ActionLog
import Mobilizon.Factory import Mobilizon.Factory
import Mobilizon.Service.Admin.ActionLogService
alias Mobilizon.Admin.ActionLog
alias Mobilizon.Reports.{Note, Report}
setup do setup do
moderator_user = insert(:user, role: :moderator) moderator_user = insert(:user, role: :moderator)

View File

@ -1,13 +1,14 @@
defmodule Mobilizon.Service.Geospatial.AddokTest do defmodule Mobilizon.Service.Geospatial.AddokTest do
use Mobilizon.DataCase, async: false
alias Mobilizon.Service.Geospatial.Addok
alias Mobilizon.Addresses.Address
import Mock
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
@endpoint Application.get_env(:mobilizon, Mobilizon.Service.Geospatial.Addok) use Mobilizon.DataCase, async: false
|> get_in([:endpoint])
import Mock
alias Mobilizon.Addresses.Address
alias Mobilizon.Service.Geospatial.Addok
@endpoint get_in(Application.get_env(:mobilizon, Addok), [:endpoint])
@fake_endpoint "https://domain.tld" @fake_endpoint "https://domain.tld"
describe "search address" do describe "search address" do

View File

@ -1,10 +1,12 @@
defmodule Mobilizon.Service.Geospatial.GoogleMapsTest do defmodule Mobilizon.Service.Geospatial.GoogleMapsTest do
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
use Mobilizon.DataCase, async: false use Mobilizon.DataCase, async: false
alias Mobilizon.Service.Geospatial.GoogleMaps
alias Mobilizon.Addresses.Address
import Mock import Mock
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
alias Mobilizon.Addresses.Address
alias Mobilizon.Service.Geospatial.GoogleMaps
describe "search address" do describe "search address" do
test "without API Key triggers an error" do test "without API Key triggers an error" do

View File

@ -1,10 +1,12 @@
defmodule Mobilizon.Service.Geospatial.MapQuestTest do defmodule Mobilizon.Service.Geospatial.MapQuestTest do
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
use Mobilizon.DataCase, async: false use Mobilizon.DataCase, async: false
alias Mobilizon.Service.Geospatial.MapQuest
alias Mobilizon.Addresses.Address
import Mock import Mock
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
alias Mobilizon.Addresses.Address
alias Mobilizon.Service.Geospatial.MapQuest
describe "search address" do describe "search address" do
test "without API Key triggers an error" do test "without API Key triggers an error" do

View File

@ -1,10 +1,12 @@
defmodule Mobilizon.Service.Geospatial.NominatimTest do defmodule Mobilizon.Service.Geospatial.NominatimTest do
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
use Mobilizon.DataCase, async: false use Mobilizon.DataCase, async: false
alias Mobilizon.Service.Geospatial.Nominatim
alias Mobilizon.Addresses.Address
import Mock import Mock
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
alias Mobilizon.Addresses.Address
alias Mobilizon.Service.Geospatial.Nominatim
describe "search address" do describe "search address" do
test "produces a valid search address with options" do test "produces a valid search address with options" do

View File

@ -1,10 +1,12 @@
defmodule Mobilizon.Service.Geospatial.PhotonTest do defmodule Mobilizon.Service.Geospatial.PhotonTest do
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
use Mobilizon.DataCase, async: false use Mobilizon.DataCase, async: false
alias Mobilizon.Service.Geospatial.Photon
alias Mobilizon.Addresses.Address
import Mock import Mock
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
alias Mobilizon.Addresses.Address
alias Mobilizon.Service.Geospatial.Photon
describe "search address" do describe "search address" do
test "produces a valid search address with options" do test "produces a valid search address with options" do

View File

@ -5,10 +5,11 @@ defmodule MobilizonWeb.API.ReportTest do
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Events.{Comment, Event} alias Mobilizon.Events.{Comment, Event}
alias Mobilizon.Reports.{Report, Note} alias Mobilizon.Reports.{Note, Report}
alias Mobilizon.Service.ActivityPub.Activity
alias Mobilizon.Service.Formatter
alias Mobilizon.Users alias Mobilizon.Users
alias Mobilizon.Users.User alias Mobilizon.Users.User
alias Mobilizon.Service.ActivityPub.Activity
alias MobilizonWeb.API.Reports alias MobilizonWeb.API.Reports
@ -86,7 +87,7 @@ defmodule MobilizonWeb.API.ReportTest do
_comment_2 = insert(:comment, actor: reported) _comment_2 = insert(:comment, actor: reported)
comment = "This is really not acceptable, remote admin I don't know" comment = "This is really not acceptable, remote admin I don't know"
encoded_comment = Mobilizon.Service.Formatter.html_escape(comment, "text/plain") encoded_comment = Formatter.html_escape(comment, "text/plain")
assert {:ok, %Activity{} = flag_activity, _} = assert {:ok, %Activity{} = flag_activity, _} =
Reports.report(%{ Reports.report(%{

View File

@ -1,17 +1,17 @@
defmodule MobilizonWeb.API.SearchTest do defmodule MobilizonWeb.API.SearchTest do
use ExUnit.Case, async: false use ExUnit.Case, async: false
alias Mobilizon.Events import Mock
alias Mobilizon.Events.Event
alias Mobilizon.Actors alias Mobilizon.Actors
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Events
alias Mobilizon.Events.Event
alias Mobilizon.Service.ActivityPub alias Mobilizon.Service.ActivityPub
alias Mobilizon.Storage.Page alias Mobilizon.Storage.Page
alias MobilizonWeb.API.Search alias MobilizonWeb.API.Search
import Mock
test "search an user by username" do test "search an user by username" do
with_mock ActivityPub, with_mock ActivityPub,
find_or_make_actor_from_nickname: fn "toto@domain.tld" -> {:ok, %Actor{id: 42}} end do find_or_make_actor_from_nickname: fn "toto@domain.tld" -> {:ok, %Actor{id: 42}} end do

View File

@ -4,16 +4,20 @@
# Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/test/web/web_finger/web_finger_controller_test.exs # Upstream: https://git.pleroma.social/pleroma/pleroma/blob/develop/test/web/web_finger/web_finger_controller_test.exs
defmodule MobilizonWeb.ActivityPubControllerTest do defmodule MobilizonWeb.ActivityPubControllerTest do
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
use MobilizonWeb.ConnCase use MobilizonWeb.ConnCase
import Mobilizon.Factory import Mobilizon.Factory
alias MobilizonWeb.ActivityPub.ActorView
alias MobilizonWeb.PageView
alias Mobilizon.{Actors, Config} alias Mobilizon.{Actors, Config}
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Service.ActivityPub alias Mobilizon.Service.ActivityPub
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
alias MobilizonWeb.Router.Helpers, as: Routes alias MobilizonWeb.ActivityPub.ActorView
alias MobilizonWeb.Endpoint alias MobilizonWeb.Endpoint
alias MobilizonWeb.PageView
alias MobilizonWeb.Router.Helpers, as: Routes
setup do setup do
conn = build_conn() |> put_req_header("accept", "application/activity+json") conn = build_conn() |> put_req_header("accept", "application/activity+json")

View File

@ -1,8 +1,10 @@
defmodule MobilizonWeb.FeedControllerTest do defmodule MobilizonWeb.FeedControllerTest do
use MobilizonWeb.ConnCase use MobilizonWeb.ConnCase
import Mobilizon.Factory import Mobilizon.Factory
alias MobilizonWeb.Router.Helpers, as: Routes
alias MobilizonWeb.Endpoint alias MobilizonWeb.Endpoint
alias MobilizonWeb.Router.Helpers, as: Routes
describe "/@:preferred_username/feed/atom" do describe "/@:preferred_username/feed/atom" do
test "it returns an RSS representation of the actor's public events if the actor is publicly visible", test "it returns an RSS representation of the actor's public events if the actor is publicly visible",
@ -16,7 +18,8 @@ defmodule MobilizonWeb.FeedControllerTest do
conn = conn =
conn conn
|> get( |> get(
Routes.feed_url(Endpoint, :actor, actor.preferred_username, "atom") Endpoint
|> Routes.feed_url(:actor, actor.preferred_username, "atom")
|> URI.decode() |> URI.decode()
) )
@ -48,7 +51,8 @@ defmodule MobilizonWeb.FeedControllerTest do
conn = conn =
conn conn
|> get( |> get(
Routes.feed_url(Endpoint, :actor, actor.preferred_username, "atom") Endpoint
|> Routes.feed_url(:actor, actor.preferred_username, "atom")
|> URI.decode() |> URI.decode()
) )
@ -63,7 +67,8 @@ defmodule MobilizonWeb.FeedControllerTest do
conn conn
|> put_req_header("accept", "application/atom+xml") |> put_req_header("accept", "application/atom+xml")
|> get( |> get(
Routes.feed_url(Endpoint, :actor, actor.preferred_username, "atom") Endpoint
|> Routes.feed_url(:actor, actor.preferred_username, "atom")
|> URI.decode() |> URI.decode()
) )
@ -93,7 +98,8 @@ defmodule MobilizonWeb.FeedControllerTest do
conn = conn =
conn conn
|> get( |> get(
Routes.feed_url(Endpoint, :actor, actor.preferred_username, "ics") Endpoint
|> Routes.feed_url(:actor, actor.preferred_username, "ics")
|> URI.decode() |> URI.decode()
) )
@ -121,7 +127,8 @@ defmodule MobilizonWeb.FeedControllerTest do
conn = conn =
conn conn
|> get( |> get(
Routes.feed_url(Endpoint, :actor, actor.preferred_username, "ics") Endpoint
|> Routes.feed_url(:actor, actor.preferred_username, "ics")
|> URI.decode() |> URI.decode()
) )
@ -136,7 +143,8 @@ defmodule MobilizonWeb.FeedControllerTest do
conn conn
|> put_req_header("accept", "text/calendar") |> put_req_header("accept", "text/calendar")
|> get( |> get(
Routes.feed_url(Endpoint, :actor, actor.preferred_username, "ics") Endpoint
|> Routes.feed_url(:actor, actor.preferred_username, "ics")
|> URI.decode() |> URI.decode()
) )
@ -163,7 +171,8 @@ defmodule MobilizonWeb.FeedControllerTest do
conn = conn =
conn conn
|> get( |> get(
Routes.feed_url(Endpoint, :event, event1.uuid, "ics") Endpoint
|> Routes.feed_url(:event, event1.uuid, "ics")
|> URI.decode() |> URI.decode()
) )
@ -194,7 +203,8 @@ defmodule MobilizonWeb.FeedControllerTest do
conn = conn =
conn conn
|> get( |> get(
Routes.feed_url(Endpoint, :going, feed_token.token, "atom") Endpoint
|> Routes.feed_url(:going, feed_token.token, "atom")
|> URI.decode() |> URI.decode()
) )
@ -228,7 +238,8 @@ defmodule MobilizonWeb.FeedControllerTest do
conn conn
|> put_req_header("accept", "application/atom+xml") |> put_req_header("accept", "application/atom+xml")
|> get( |> get(
Routes.feed_url(Endpoint, :going, feed_token.token, "atom") Endpoint
|> Routes.feed_url(:going, feed_token.token, "atom")
|> URI.decode() |> URI.decode()
) )
@ -247,7 +258,8 @@ defmodule MobilizonWeb.FeedControllerTest do
conn = conn =
conn conn
|> get( |> get(
Routes.feed_url(Endpoint, :going, "not existing", "atom") Endpoint
|> Routes.feed_url(:going, "not existing", "atom")
|> URI.decode() |> URI.decode()
) )
@ -272,7 +284,8 @@ defmodule MobilizonWeb.FeedControllerTest do
conn conn
|> put_req_header("accept", "text/calendar") |> put_req_header("accept", "text/calendar")
|> get( |> get(
Routes.feed_url(Endpoint, :going, feed_token.token, "ics") Endpoint
|> Routes.feed_url(:going, feed_token.token, "ics")
|> URI.decode() |> URI.decode()
) )
@ -302,7 +315,8 @@ defmodule MobilizonWeb.FeedControllerTest do
conn conn
|> put_req_header("accept", "text/calendar") |> put_req_header("accept", "text/calendar")
|> get( |> get(
Routes.feed_url(Endpoint, :going, feed_token.token, "ics") Endpoint
|> Routes.feed_url(:going, feed_token.token, "ics")
|> URI.decode() |> URI.decode()
) )
@ -318,7 +332,8 @@ defmodule MobilizonWeb.FeedControllerTest do
conn = conn =
conn conn
|> get( |> get(
Routes.feed_url(Endpoint, :going, "not existing", "ics") Endpoint
|> Routes.feed_url(:going, "not existing", "ics")
|> URI.decode() |> URI.decode()
) )

View File

@ -3,27 +3,20 @@ defmodule MobilizonWeb.NodeInfoControllerTest do
alias Mobilizon.Config alias Mobilizon.Config
alias MobilizonWeb.Endpoint
alias MobilizonWeb.Router.Helpers, as: Routes
test "Get node info schemas", %{conn: conn} do test "Get node info schemas", %{conn: conn} do
conn = get(conn, node_info_path(conn, :schemas)) conn = get(conn, node_info_path(conn, :schemas))
assert json_response(conn, 200) == %{ assert json_response(conn, 200) == %{
"links" => [ "links" => [
%{ %{
"href" => "href" => Routes.node_info_url(Endpoint, :nodeinfo, "2.0"),
MobilizonWeb.Router.Helpers.node_info_url(
MobilizonWeb.Endpoint,
:nodeinfo,
"2.0"
),
"rel" => "http://nodeinfo.diaspora.software/ns/schema/2.0" "rel" => "http://nodeinfo.diaspora.software/ns/schema/2.0"
}, },
%{ %{
"href" => "href" => Routes.node_info_url(Endpoint, :nodeinfo, "2.1"),
MobilizonWeb.Router.Helpers.node_info_url(
MobilizonWeb.Endpoint,
:nodeinfo,
"2.1"
),
"rel" => "http://nodeinfo.diaspora.software/ns/schema/2.1" "rel" => "http://nodeinfo.diaspora.software/ns/schema/2.1"
} }
] ]

View File

@ -1,9 +1,12 @@
defmodule MobilizonWeb.PageControllerTest do defmodule MobilizonWeb.PageControllerTest do
use MobilizonWeb.ConnCase use MobilizonWeb.ConnCase
import Mobilizon.Factory import Mobilizon.Factory
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias MobilizonWeb.Router.Helpers, as: Routes
alias MobilizonWeb.Endpoint alias MobilizonWeb.Endpoint
alias MobilizonWeb.Router.Helpers, as: Routes
setup do setup do
conn = build_conn() |> put_req_header("accept", "text/html") conn = build_conn() |> put_req_header("accept", "text/html")

View File

@ -1,12 +1,15 @@
defmodule MobilizonWeb.Resolvers.AdminResolverTest do defmodule MobilizonWeb.Resolvers.AdminResolverTest do
alias MobilizonWeb.AbsintheHelpers
use MobilizonWeb.ConnCase use MobilizonWeb.ConnCase
import Mobilizon.Factory import Mobilizon.Factory
alias Mobilizon.Events.Event
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Events.Event
alias Mobilizon.Reports.{Note, Report}
alias Mobilizon.Users.User alias Mobilizon.Users.User
alias Mobilizon.Reports.{Report, Note}
alias MobilizonWeb.AbsintheHelpers
alias MobilizonWeb.API
describe "Resolver: List the action logs" do describe "Resolver: List the action logs" do
@note_content "This a note on a report" @note_content "This a note on a report"
@ -18,12 +21,11 @@ defmodule MobilizonWeb.Resolvers.AdminResolverTest do
%Actor{} = moderator_2 = insert(:actor, user: user_moderator_2) %Actor{} = moderator_2 = insert(:actor, user: user_moderator_2)
%Report{} = report = insert(:report) %Report{} = report = insert(:report)
MobilizonWeb.API.Reports.update_report_status(moderator, report, "resolved") API.Reports.update_report_status(moderator, report, "resolved")
{:ok, %Note{} = note} = {:ok, %Note{} = note} = API.Reports.create_report_note(report, moderator_2, @note_content)
MobilizonWeb.API.Reports.create_report_note(report, moderator_2, @note_content)
MobilizonWeb.API.Reports.delete_report_note(note, moderator_2) API.Reports.delete_report_note(note, moderator_2)
query = """ query = """
{ {

View File

@ -1,12 +1,14 @@
defmodule MobilizonWeb.Resolvers.ReportResolverTest do defmodule MobilizonWeb.Resolvers.ReportResolverTest do
alias MobilizonWeb.AbsintheHelpers
use MobilizonWeb.ConnCase use MobilizonWeb.ConnCase
import Mobilizon.Factory import Mobilizon.Factory
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Users.User
alias Mobilizon.Events.Event alias Mobilizon.Events.Event
alias Mobilizon.Reports.{Report, Note} alias Mobilizon.Reports.{Note, Report}
alias Mobilizon.Users.User
alias MobilizonWeb.AbsintheHelpers
describe "Resolver: Report a content" do describe "Resolver: Report a content" do
test "create_report/3 creates a report", %{conn: conn} do test "create_report/3 creates a report", %{conn: conn} do

View File

@ -33,7 +33,8 @@ defmodule MobilizonWeb.Resolvers.TagResolverTest do
tags = json_response(res, 200)["data"]["tags"] tags = json_response(res, 200)["data"]["tags"]
assert tags |> length == 3 assert tags |> length == 3
assert Enum.filter(tags, fn tag -> tag["slug"] == tag1.slug end) assert tags
|> Enum.filter(fn tag -> tag["slug"] == tag1.slug end)
|> hd |> hd
|> Map.get("related") |> Map.get("related")
|> Enum.map(fn tag -> tag["slug"] end) |> Enum.map(fn tag -> tag["slug"] end)

View File

@ -9,8 +9,8 @@ defmodule MobilizonWeb.Resolvers.UserResolverTest do
alias Mobilizon.{Actors, Config, Users} alias Mobilizon.{Actors, Config, Users}
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Service.Users.ResetPassword alias Mobilizon.Service.Users.ResetPassword
alias Mobilizon.Users.User
alias Mobilizon.Users alias Mobilizon.Users
alias Mobilizon.Users.User
alias MobilizonWeb.{AbsintheHelpers, Email} alias MobilizonWeb.{AbsintheHelpers, Email}

View File

@ -198,7 +198,7 @@ defmodule Mobilizon.UploadTest do
end end
end end
defp upload() do defp upload do
File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg") File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
file = %Plug.Upload{ file = %Plug.Upload{

View File

@ -15,6 +15,10 @@ defmodule MobilizonWeb.ChannelCase do
use ExUnit.CaseTemplate use ExUnit.CaseTemplate
alias Ecto.Adapters.SQL.Sandbox, as: Adapter
alias Mobilizon.Storage.Repo
using do using do
quote do quote do
# Import conveniences for testing with channels # Import conveniences for testing with channels
@ -26,11 +30,9 @@ defmodule MobilizonWeb.ChannelCase do
end end
setup tags do setup tags do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(Mobilizon.Storage.Repo) :ok = Adapter.checkout(Repo)
unless tags[:async] do unless tags[:async], do: Adapter.mode(Repo, {:shared, self()})
Ecto.Adapters.SQL.Sandbox.mode(Mobilizon.Storage.Repo, {:shared, self()})
end
:ok :ok
end end

View File

@ -15,6 +15,11 @@ defmodule MobilizonWeb.ConnCase do
use ExUnit.CaseTemplate use ExUnit.CaseTemplate
alias Ecto.Adapters.SQL.Sandbox, as: Adapter
alias Mobilizon.Storage.Repo
alias Mobilizon.Users.User
using do using do
quote do quote do
# Import conveniences for testing with connections # Import conveniences for testing with connections
@ -24,7 +29,7 @@ defmodule MobilizonWeb.ConnCase do
# The default endpoint for testing # The default endpoint for testing
@endpoint MobilizonWeb.Endpoint @endpoint MobilizonWeb.Endpoint
def auth_conn(%Plug.Conn{} = conn, %Mobilizon.Users.User{} = user) do def auth_conn(%Plug.Conn{} = conn, %User{} = user) do
{:ok, token, _claims} = MobilizonWeb.Guardian.encode_and_sign(user) {:ok, token, _claims} = MobilizonWeb.Guardian.encode_and_sign(user)
conn conn
@ -35,11 +40,9 @@ defmodule MobilizonWeb.ConnCase do
end end
setup tags do setup tags do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(Mobilizon.Storage.Repo) :ok = Adapter.checkout(Repo)
unless tags[:async] do unless tags[:async], do: Adapter.mode(Repo, {:shared, self()})
Ecto.Adapters.SQL.Sandbox.mode(Mobilizon.Storage.Repo, {:shared, self()})
end
{:ok, conn: Phoenix.ConnTest.build_conn()} {:ok, conn: Phoenix.ConnTest.build_conn()}
end end

View File

@ -14,7 +14,10 @@ defmodule Mobilizon.DataCase do
use ExUnit.CaseTemplate use ExUnit.CaseTemplate
alias Ecto.Adapters.SQL.Sandbox, as: Adapter
alias Mobilizon.Config alias Mobilizon.Config
alias Mobilizon.Storage.Repo
using do using do
quote do quote do
@ -28,11 +31,9 @@ defmodule Mobilizon.DataCase do
end end
setup tags do setup tags do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(Mobilizon.Storage.Repo) :ok = Adapter.checkout(Repo)
unless tags[:async] do unless tags[:async], do: Adapter.mode(Repo, {:shared, self()})
Ecto.Adapters.SQL.Sandbox.mode(Mobilizon.Storage.Repo, {:shared, self()})
end
:ok :ok
end end

View File

@ -8,8 +8,8 @@ defmodule Mobilizon.Factory do
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Crypto alias Mobilizon.Crypto
alias MobilizonWeb.Router.Helpers, as: Routes
alias MobilizonWeb.Endpoint alias MobilizonWeb.Endpoint
alias MobilizonWeb.Router.Helpers, as: Routes
alias MobilizonWeb.Upload alias MobilizonWeb.Upload
def user_factory do def user_factory do

View File

@ -1,9 +1,10 @@
defmodule Mobilizon.Service.Geospatial.Mock do defmodule Mobilizon.Service.Geospatial.Mock do
@moduledoc """ @moduledoc """
Mock for Geospatial Provider implementations Mock for Geospatial Provider implementations.
""" """
alias Mobilizon.Service.Geospatial.Provider
alias Mobilizon.Addresses.Address alias Mobilizon.Addresses.Address
alias Mobilizon.Service.Geospatial.Provider
@behaviour Provider @behaviour Provider

View File

@ -3,12 +3,14 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Mix.Tasks.Mobilizon.RelayTest do defmodule Mix.Tasks.Mobilizon.RelayTest do
alias Mobilizon.Actors.{Actor, Follower}
alias Mobilizon.Actors
alias Mobilizon.Service.ActivityPub.Relay
use Mobilizon.DataCase
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
use Mobilizon.DataCase
alias Mobilizon.Actors
alias Mobilizon.Actors.{Actor, Follower}
alias Mobilizon.Service.ActivityPub.Relay
describe "running follow" do describe "running follow" do
test "relay is followed" do test "relay is followed" do
use_cassette "relay/fetch_relay_follow" do use_cassette "relay/fetch_relay_follow" do