Merge branch 'unused' into 'master'

Remove unused functions

See merge request framasoft/mobilizon!1073
This commit is contained in:
Thomas Citharel 2021-10-05 14:37:59 +00:00
commit ba61880e50
47 changed files with 175 additions and 725 deletions

View file

@ -12,7 +12,7 @@ defmodule Mobilizon.Federation.ActivityPub.Utils do
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Medias.Media alias Mobilizon.Medias.Media
alias Mobilizon.Federation.ActivityPub.{Actions, Activity, Federator, Relay} alias Mobilizon.Federation.ActivityPub.{Actions, Activity, Federator}
alias Mobilizon.Federation.ActivityPub.Actor, as: ActivityPubActor alias Mobilizon.Federation.ActivityPub.Actor, as: ActivityPubActor
alias Mobilizon.Federation.ActivityStream.Converter alias Mobilizon.Federation.ActivityStream.Converter
alias Mobilizon.Federation.HTTPSignatures alias Mobilizon.Federation.HTTPSignatures
@ -345,10 +345,6 @@ defmodule Mobilizon.Federation.ActivityPub.Utils do
end end
end end
def make_media_data(%Media{} = media) do
Converter.Media.model_to_as(media)
end
def make_media_data(media) when is_map(media) do def make_media_data(media) when is_map(media) do
with {:ok, %{url: url} = uploaded} <- with {:ok, %{url: url} = uploaded} <-
Mobilizon.Web.Upload.store(media.file), Mobilizon.Web.Upload.store(media.file),
@ -618,16 +614,6 @@ defmodule Mobilizon.Federation.ActivityPub.Utils do
[{:Signature, signature}] [{:Signature, signature}]
end end
@doc """
Sign a request with the instance Relay actor.
"""
@spec sign_fetch_relay(Enum.t(), String.t(), String.t()) :: Enum.t()
def sign_fetch_relay(headers, id, date) do
with %Actor{} = actor <- Relay.get_actor() do
sign_fetch(headers, actor, id, date)
end
end
@doc """ @doc """
Sign a request with an actor. Sign a request with an actor.
""" """

View file

@ -38,14 +38,6 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Utils do
def fetch_mentions(_), do: [] def fetch_mentions(_), do: []
def fetch_address(%{id: id}) do
with {id, ""} <- Integer.parse(id), do: %{id: id}
end
def fetch_address(address) when is_map(address) do
address
end
def fetch_actors(actors) when is_list(actors) do def fetch_actors(actors) when is_list(actors) do
Logger.debug("fetching contacts") Logger.debug("fetching contacts")
actors |> Enum.map(& &1.id) |> Enum.filter(& &1) |> Enum.map(&Actors.get_actor/1) actors |> Enum.map(& &1.id) |> Enum.filter(& &1) |> Enum.map(&Actors.get_actor/1)

View file

@ -76,10 +76,7 @@ defmodule Mobilizon.Federation.WebFinger do
@doc """ @doc """
Return an `Mobilizon.Actors.Actor` Webfinger representation (as JSON) Return an `Mobilizon.Actors.Actor` Webfinger representation (as JSON)
""" """
@spec represent_actor(Actor.t()) :: map()
@spec represent_actor(Actor.t(), String.t()) :: map() @spec represent_actor(Actor.t(), String.t()) :: map()
def represent_actor(%Actor{} = actor), do: represent_actor(actor, "JSON")
def represent_actor(%Actor{} = actor, "JSON") do def represent_actor(%Actor{} = actor, "JSON") do
links = links =
[ [

View file

@ -29,9 +29,9 @@ defmodule Mobilizon.GraphQL.API.Events do
@doc """ @doc """
Trigger the deletion of an event Trigger the deletion of an event
""" """
@spec delete_event(Event.t(), Actor.t(), boolean()) :: {:ok, Activity.t(), Entity.t()} | any() @spec delete_event(Event.t(), Actor.t()) :: {:ok, Activity.t(), Entity.t()} | any()
def delete_event(%Event{} = event, %Actor{} = actor, federate \\ true) do def delete_event(%Event{} = event, %Actor{} = actor) do
Actions.Delete.delete(event, actor, federate) Actions.Delete.delete(event, actor, true)
end end
@spec prepare_args(map) :: map @spec prepare_args(map) :: map

View file

@ -3,7 +3,7 @@ defmodule Mobilizon.GraphQL.API.Utils do
Utils for API. Utils for API.
""" """
alias Mobilizon.{Config, Medias} alias Mobilizon.Medias
alias Mobilizon.Medias.Media alias Mobilizon.Medias.Media
alias Mobilizon.Service.Formatter alias Mobilizon.Service.Formatter
@ -30,18 +30,6 @@ defmodule Mobilizon.GraphQL.API.Utils do
|> Formatter.linkify(options) |> Formatter.linkify(options)
end end
def make_report_content_text(nil), do: {:ok, nil}
def make_report_content_text(comment) do
max_size = Config.get([:instance, :max_report_comment_size], 1000)
if String.length(comment) <= max_size do
{:ok, Formatter.html_escape(comment, "text/plain")}
else
{:error, "Comment must be up to #{max_size} characters"}
end
end
@doc """ @doc """
Use the data-media-id attributes to extract media from body text Use the data-media-id attributes to extract media from body text
""" """

View file

@ -89,7 +89,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Comment do
end end
end end
def edit_comment(_parent, _args, _context) do def update_comment(_parent, _args, _context) do
{:error, dgettext("errors", "You are not allowed to update a comment if not connected")} {:error, dgettext("errors", "You are not allowed to update a comment if not connected")}
end end

View file

@ -21,17 +21,17 @@ defmodule Mobilizon.GraphQL.Resolvers.Todos do
{:ok, Page.t(TodoList.t())} {:ok, Page.t(TodoList.t())}
def find_todo_lists_for_group( def find_todo_lists_for_group(
%Actor{id: group_id} = group, %Actor{id: group_id} = group,
_args, %{page: page, limit: limit},
%{ %{
context: %{current_actor: %Actor{id: actor_id}} context: %{current_actor: %Actor{id: actor_id}}
} = _resolution } = _resolution
) do ) do
with {:member, true} <- {:member, Actors.is_member?(actor_id, group_id)}, with {:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
%Page{} = page <- Todos.get_todo_lists_for_group(group) do %Page{} = page <- Todos.get_todo_lists_for_group(group, page, limit) do
{:ok, page} {:ok, page}
else else
{:member, _} -> {:member, _} ->
with %Page{} = page <- Todos.get_todo_lists_for_group(group) do with %Page{} = page <- Todos.get_todo_lists_for_group(group, page, limit) do
{:ok, %Page{page | elements: []}} {:ok, %Page{page | elements: []}}
end end
end end
@ -41,17 +41,17 @@ defmodule Mobilizon.GraphQL.Resolvers.Todos do
{:ok, %Page{total: 0, elements: []}} {:ok, %Page{total: 0, elements: []}}
end end
@spec find_todo_lists_for_group(TodoList.t(), map(), Absinthe.Resolution.t()) :: @spec find_todos_for_todo_list(TodoList.t(), map(), Absinthe.Resolution.t()) ::
{:ok, Page.t(Todo.t())} | {:error, String.t()} {:ok, Page.t(Todo.t())} | {:error, String.t()}
def find_todos_for_todo_list( def find_todos_for_todo_list(
%TodoList{actor_id: group_id} = todo_list, %TodoList{actor_id: group_id} = todo_list,
_args, %{page: page, limit: limit},
%{ %{
context: %{current_actor: %Actor{id: actor_id}} context: %{current_actor: %Actor{id: actor_id}}
} = _resolution } = _resolution
) do ) do
with {:member, true} <- {:member, Actors.is_member?(actor_id, group_id)}, with {:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
%Page{} = page <- Todos.get_todos_for_todo_list(todo_list) do %Page{} = page <- Todos.get_todos_for_todo_list(todo_list, page, limit) do
{:ok, page} {:ok, page}
else else
{:member, _} -> {:member, _} ->

View file

@ -129,6 +129,12 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
end end
field :todo_lists, :paginated_todo_list_list do field :todo_lists, :paginated_todo_list_list do
arg(:page, :integer,
default_value: 1,
description: "The page in the paginated todo-lists list"
)
arg(:limit, :integer, default_value: 10, description: "The limit of todo-lists per page")
resolve(&Todos.find_todo_lists_for_group/3) resolve(&Todos.find_todo_lists_for_group/3)
description("A paginated list of the todo lists this group has") description("A paginated list of the todo lists this group has")
end end

View file

@ -17,10 +17,20 @@ defmodule Mobilizon.GraphQL.Schema.Todos.TodoListType do
description: "The actor that owns this todo list" description: "The actor that owns this todo list"
) )
field(:todos, :paginated_todo_list, field :todos, :paginated_todo_list do
resolve: &Todos.find_todos_for_todo_list/3, arg(:page, :integer,
description: "The todo-list's todos" default_value: 1,
) description: "The page in the paginated todos list"
)
arg(:limit, :integer,
default_value: 10,
description: "The limit of todos per page"
)
resolve(&Todos.find_todos_for_todo_list/3)
description("The todo-list's todos")
end
end end
@desc """ @desc """

View file

@ -50,9 +50,9 @@ defmodule Mix.Tasks.Mobilizon.Actors.Utils do
new_person new_person
end end
@spec create_group(Actor.t(), String.t(), String.t(), Keyword.t()) :: @spec create_group(Actor.t(), String.t(), String.t()) ::
{:ok, Actor.t()} | {:error, Ecto.Changeset.t()} {:ok, Actor.t()} | {:error, Ecto.Changeset.t()}
def create_group(%Actor{id: admin_id}, username, name, _options \\ []) do def create_group(%Actor{id: admin_id}, username, name) do
{username, name} = username_and_name(username, name) {username, name} = username_and_name(username, name)
Actors.create_group(%{creator_actor_id: admin_id, preferred_username: username, name: name}) Actors.create_group(%{creator_actor_id: admin_id, preferred_username: username, name: name})

View file

@ -189,12 +189,6 @@ defmodule Mobilizon.Activities do
Repo.preload(activity, @activity_preloads) Repo.preload(activity, @activity_preloads)
end end
@spec object_types :: list(String.t())
def object_types, do: @object_type
@spec subjects :: list(String.t())
def subjects, do: @subjects
@spec activity_types :: list(String.t()) @spec activity_types :: list(String.t())
def activity_types, do: @activity_types def activity_types, do: @activity_types

View file

@ -82,10 +82,10 @@ defmodule Mobilizon.Actors do
|> Repo.one() |> Repo.one()
end end
@spec get_actor_with_preload!(integer | String.t(), boolean) :: Actor.t() @spec get_actor_with_preload!(integer | String.t()) :: Actor.t()
def get_actor_with_preload!(id, include_suspended \\ false) do def get_actor_with_preload!(id) do
id id
|> actor_with_preload_query(include_suspended) |> actor_with_preload_query(false)
|> Repo.one!() |> Repo.one!()
end end
@ -100,14 +100,6 @@ defmodule Mobilizon.Actors do
|> Repo.one() |> Repo.one()
end end
@spec get_remote_actor_with_preload(integer | String.t(), boolean()) :: Actor.t() | nil
def get_remote_actor_with_preload(id, include_suspended \\ false) do
id
|> actor_with_preload_query(include_suspended)
|> filter_external()
|> Repo.one()
end
@doc """ @doc """
Gets an actor by its URL (ActivityPub ID). The `:preload` option allows to Gets an actor by its URL (ActivityPub ID). The `:preload` option allows to
preload the followers relation. preload the followers relation.
@ -131,11 +123,9 @@ defmodule Mobilizon.Actors do
New function to replace `Mobilizon.Actors.get_actor_by_url/1` with New function to replace `Mobilizon.Actors.get_actor_by_url/1` with
better signature better signature
""" """
@spec get_actor_by_url_2(String.t(), boolean) :: Actor.t() | nil @spec get_actor_by_url_2(String.t()) :: Actor.t() | nil
def get_actor_by_url_2(url, preload \\ false) do def get_actor_by_url_2(url) do
Actor Repo.get_by(Actor, url: url)
|> Repo.get_by(url: url)
|> preload_followers(preload)
end end
@doc """ @doc """
@ -495,16 +485,6 @@ defmodule Mobilizon.Actors do
|> Repo.one() |> Repo.one()
end end
@doc """
Gets a local group by its title.
"""
@spec get_local_group_by_title(String.t()) :: Actor.t() | nil
def get_local_group_by_title(title) do
group_query()
|> filter_by_name([title])
|> Repo.one()
end
@doc """ @doc """
Gets a group by its actor id. Gets a group by its actor id.
""" """
@ -575,11 +555,6 @@ defmodule Mobilizon.Actors do
end end
end end
@doc """
Deletes a group.
"""
def delete_group!(%Actor{type: :Group} = group), do: Repo.delete!(group)
@doc """ @doc """
Counts the local groups Counts the local groups
""" """
@ -599,15 +574,6 @@ defmodule Mobilizon.Actors do
|> Repo.aggregate(:count) |> Repo.aggregate(:count)
end end
@doc """
Lists the groups.
"""
@spec list_groups(integer | nil, integer | nil) :: Page.t()
def list_groups(page \\ nil, limit \\ nil) do
groups_query()
|> Page.build_page(page, limit)
end
@doc """ @doc """
Lists the groups. Lists the groups.
""" """
@ -620,10 +586,10 @@ defmodule Mobilizon.Actors do
@doc """ @doc """
Lists the groups. Lists the groups.
""" """
@spec list_external_groups(non_neg_integer()) :: list(Actor.t()) @spec list_external_groups :: list(Actor.t())
def list_external_groups(limit \\ 100) when limit > 0 do def list_external_groups do
external_groups_query() external_groups_query()
|> limit(^limit) |> limit(100)
|> Repo.all() |> Repo.all()
end end
@ -833,30 +799,6 @@ defmodule Mobilizon.Actors do
|> Repo.all() |> Repo.all()
end end
@spec list_local_members_for_group(Actor.t(), integer | nil, integer | nil) ::
Page.t(Member.t())
def list_local_members_for_group(
%Actor{id: group_id, type: :Group} = _group,
page \\ nil,
limit \\ nil
) do
group_id
|> group_internal_member_query()
|> Page.build_page(page, limit)
end
@spec list_remote_members_for_group(Actor.t(), integer | nil, integer | nil) ::
Page.t(Member.t())
def list_remote_members_for_group(
%Actor{id: group_id, type: :Group} = _group,
page \\ nil,
limit \\ nil
) do
group_id
|> group_external_member_query()
|> Page.build_page(page, limit)
end
@doc """ @doc """
Returns a paginated list of members for a group. Returns a paginated list of members for a group.
""" """
@ -888,17 +830,6 @@ defmodule Mobilizon.Actors do
|> Repo.all() |> Repo.all()
end end
@doc """
Returns a paginated list of administrator members for a group.
"""
@spec list_administrator_members_for_group(integer | String.t(), integer | nil, integer | nil) ::
Page.t()
def list_administrator_members_for_group(id, page \\ nil, limit \\ nil) do
id
|> administrator_members_for_group_query()
|> Page.build_page(page, limit)
end
@doc """ @doc """
Returns the complete list of administrator members for a group. Returns the complete list of administrator members for a group.
""" """
@ -1012,12 +943,6 @@ defmodule Mobilizon.Actors do
@spec delete_bot(Bot.t()) :: {:ok, Bot.t()} | {:error, Ecto.Changeset.t()} @spec delete_bot(Bot.t()) :: {:ok, Bot.t()} | {:error, Ecto.Changeset.t()}
def delete_bot(%Bot{} = bot), do: Repo.delete(bot) def delete_bot(%Bot{} = bot), do: Repo.delete(bot)
@doc """
Returns the list of bots.
"""
@spec list_bots :: [Bot.t()]
def list_bots, do: Repo.all(Bot)
@doc """ @doc """
Gets a single follower. Gets a single follower.
""" """
@ -1105,17 +1030,6 @@ defmodule Mobilizon.Actors do
|> Repo.delete() |> Repo.delete()
end end
@doc """
Returns the list of followers for an actor.
If actor A and C both follow actor B, actor B's followers are A and C.
"""
@spec list_followers_actors_for_actor(Actor.t()) :: [Actor.t()]
def list_followers_actors_for_actor(%Actor{id: actor_id}) do
actor_id
|> follower_actors_for_actor_query()
|> Repo.all()
end
@doc """ @doc """
Returns the list of external followers for an actor. Returns the list of external followers for an actor.
""" """
@ -1177,17 +1091,6 @@ defmodule Mobilizon.Actors do
|> Page.build_page(page, limit) |> Page.build_page(page, limit)
end end
@doc """
Returns the list of followings for an actor.
If actor A follows actor B and C, actor A's followings are B and C.
"""
@spec list_followings_for_actor(Actor.t()) :: [Follower.t()]
def list_followings_for_actor(%Actor{id: actor_id}) do
actor_id
|> followings_actors_for_actor_query()
|> Repo.all()
end
@doc """ @doc """
Returns the number of followings for an actor Returns the number of followings for an actor
""" """
@ -1485,16 +1388,6 @@ defmodule Mobilizon.Actors do
|> select([_m, a], a) |> select([_m, a], a)
end end
@spec group_external_member_query(integer()) :: Ecto.Query.t()
defp group_external_member_query(group_id) do
Member
|> where([m], m.parent_id == ^group_id)
|> join(:inner, [m], a in Actor, on: m.actor_id == a.id)
|> where([_m, a], not is_nil(a.domain))
|> preload([m], [:parent, :actor])
|> select([m, _a], m)
end
@spec group_internal_member_actor_query(integer(), list()) :: Ecto.Query.t() @spec group_internal_member_actor_query(integer(), list()) :: Ecto.Query.t()
defp group_internal_member_actor_query(group_id, role) do defp group_internal_member_actor_query(group_id, role) do
Member Member

View file

@ -44,12 +44,12 @@ defmodule Mobilizon.CLI do
end end
end end
@spec migrate(String.t()) :: any() @spec migrate(any()) :: any()
defp migrate(args) do defp migrate(args) do
Migrate.run(args) Migrate.run(args)
end end
@spec rollback(String.t()) :: any() @spec rollback(any()) :: any()
defp rollback(args) do defp rollback(args) do
Rollback.run(args) Rollback.run(args)
end end

View file

@ -223,10 +223,6 @@ defmodule Mobilizon.Config do
:confirmation_required :confirmation_required
] ]
@spec anonymous_participation_email_captcha_required? :: boolean
def anonymous_participation_email_captcha_required?,
do: anonymous_config()[:participation][:validation][:captcha][:enabled]
@spec anonymous_event_creation? :: boolean @spec anonymous_event_creation? :: boolean
def anonymous_event_creation?, def anonymous_event_creation?,
do: anonymous_config()[:event_creation][:allowed] do: anonymous_config()[:event_creation][:allowed]
@ -265,9 +261,6 @@ defmodule Mobilizon.Config do
end) end)
end end
@spec oauth_consumer_enabled? :: boolean()
def oauth_consumer_enabled?, do: oauth_consumer_strategies() != []
@spec ldap_enabled? :: boolean() @spec ldap_enabled? :: boolean()
def ldap_enabled?, do: get([:ldap, :enabled], false) def ldap_enabled?, do: get([:ldap, :enabled], false)

View file

@ -125,13 +125,6 @@ defmodule Mobilizon.Discussions do
@spec get_comment_from_url(String.t()) :: Comment.t() | nil @spec get_comment_from_url(String.t()) :: Comment.t() | nil
def get_comment_from_url(url), do: Repo.get_by(Comment, url: url) def get_comment_from_url(url), do: Repo.get_by(Comment, url: url)
@doc """
Gets a comment by its URL.
Raises `Ecto.NoResultsError` if the comment does not exist.
"""
@spec get_comment_from_url!(String.t()) :: Comment.t()
def get_comment_from_url!(url), do: Repo.get_by!(Comment, url: url)
@doc """ @doc """
Gets a comment by its URL, with all associations loaded. Gets a comment by its URL, with all associations loaded.
""" """
@ -175,19 +168,6 @@ defmodule Mobilizon.Discussions do
|> Repo.preload(@comment_preloads) |> Repo.preload(@comment_preloads)
end end
@doc """
Get all comment threads under an event
"""
@spec get_threads(String.t() | integer()) :: [Comment.t()]
def get_threads(event_id) do
Comment
|> where([c, _], c.event_id == ^event_id and is_nil(c.origin_comment_id))
|> join(:left, [c], r in Comment, on: r.origin_comment_id == c.id)
|> group_by([c], c.id)
|> select([c, r], %{c | total_replies: count(r.id)})
|> Repo.all()
end
@doc """ @doc """
Gets paginated replies for root comment Gets paginated replies for root comment
""" """
@ -198,17 +178,6 @@ defmodule Mobilizon.Discussions do
|> Repo.all() |> Repo.all()
end end
@doc """
Get a comment or create it
"""
@spec get_or_create_comment(map()) :: {:ok, Comment.t()}
def get_or_create_comment(%{"url" => url} = attrs) do
case Repo.get_by(Comment, url: url) do
%Comment{} = comment -> {:ok, Repo.preload(comment, @comment_preloads)}
nil -> create_comment(attrs)
end
end
@doc """ @doc """
Creates a comment. Creates a comment.
""" """
@ -253,14 +222,6 @@ defmodule Mobilizon.Discussions do
end end
end end
@doc """
Returns the list of public comments.
"""
@spec list_comments :: [Comment.t()]
def list_comments do
Repo.all(from(c in Comment, where: c.visibility == ^:public))
end
@doc """ @doc """
Returns a paginated list of local comments Returns a paginated list of local comments
""" """

View file

@ -159,34 +159,11 @@ defmodule Mobilizon.Events do
|> Repo.one!() |> Repo.one!()
end end
@doc """
Gets an event by its URL, with all associations loaded.
"""
@spec get_public_event_by_url_with_preload(String.t()) ::
{:ok, Event.t()} | {:error, :event_not_found}
def get_public_event_by_url_with_preload(url) do
event =
url
|> event_by_url_query()
|> filter_unlisted_and_public_visibility()
|> filter_draft()
|> preload_for_event()
|> Repo.one()
case event do
%Event{} = event ->
{:ok, event}
nil ->
{:error, :event_not_found}
end
end
@doc """ @doc """
Gets an event by its URL, with all associations loaded. Gets an event by its URL, with all associations loaded.
Raises `Ecto.NoResultsError` if the event does not exist. Raises `Ecto.NoResultsError` if the event does not exist.
""" """
@spec get_public_event_by_url_with_preload(String.t()) :: Event.t() @spec get_public_event_by_url_with_preload!(String.t()) :: Event.t()
def get_public_event_by_url_with_preload!(url) do def get_public_event_by_url_with_preload!(url) do
url url
|> event_by_url_query() |> event_by_url_query()
@ -228,18 +205,6 @@ defmodule Mobilizon.Events do
|> Repo.one() |> Repo.one()
end end
@doc """
Gets an event by its UUID, with all associations loaded.
"""
@spec get_own_event_by_uuid_with_preload(String.t(), integer()) :: Event.t() | nil
def get_own_event_by_uuid_with_preload(uuid, user_id) do
uuid
|> event_by_uuid_query()
|> user_events_query(user_id)
|> preload_for_event()
|> Repo.one()
end
@doc """ @doc """
Gets an actor's eventual upcoming public event. Gets an actor's eventual upcoming public event.
""" """
@ -253,13 +218,6 @@ defmodule Mobilizon.Events do
|> Repo.one() |> Repo.one()
end end
def get_or_create_event(%{"url" => url} = attrs) do
case Repo.get_by(Event, url: url) do
%Event{} = event -> {:ok, Repo.preload(event, @event_preloads)}
nil -> create_event(attrs)
end
end
@doc """ @doc """
Creates an event. Creates an event.
""" """
@ -502,9 +460,9 @@ defmodule Mobilizon.Events do
Finds close events to coordinates. Finds close events to coordinates.
Radius is in meters and defaults to 50km. Radius is in meters and defaults to 50km.
""" """
@spec find_close_events(number, number, number, number) :: [Event.t()] @spec find_close_events(float(), float(), non_neg_integer()) :: [Event.t()]
def find_close_events(lon, lat, radius \\ 50_000, srid \\ 4326) do def find_close_events(lon, lat, radius \\ 50_000) do
"SRID=#{srid};POINT(#{lon} #{lat})" "SRID=#{4326};POINT(#{lon} #{lat})"
|> Geo.WKT.decode!() |> Geo.WKT.decode!()
|> close_events_query(radius) |> close_events_query(radius)
|> filter_draft() |> filter_draft()
@ -585,33 +543,6 @@ defmodule Mobilizon.Events do
|> Repo.one() |> Repo.one()
end end
@doc """
Gets an existing tag or creates the new one.
From a map containing a %{"name" => "#mytag"} or a direct binary
"""
@spec get_or_create_tag(map) :: {:ok, Tag.t()} | {:error, Changeset.t()}
def get_or_create_tag(%{"name" => "#" <> title}) do
case Repo.get_by(Tag, title: title) do
%Tag{} = tag ->
{:ok, tag}
nil ->
create_tag(%{"title" => title})
end
end
@spec get_or_create_tag(String.t()) :: {:ok, Tag.t()} | {:error, Changeset.t()}
def get_or_create_tag(title) do
case Repo.get_by(Tag, title: title) do
%Tag{} = tag ->
{:ok, tag}
nil ->
create_tag(%{"title" => title})
end
end
@doc """ @doc """
Creates a tag. Creates a tag.
""" """
@ -663,8 +594,8 @@ defmodule Mobilizon.Events do
@doc """ @doc """
Checks whether two tags are linked or not. Checks whether two tags are linked or not.
""" """
@spec are_tags_linked(Tag.t(), Tag.t()) :: boolean @spec are_tags_linked?(Tag.t(), Tag.t()) :: boolean
def are_tags_linked(%Tag{id: tag1_id}, %Tag{id: tag2_id}) do def are_tags_linked?(%Tag{id: tag1_id}, %Tag{id: tag2_id}) do
tag_relation = tag_relation =
tag1_id tag1_id
|> tags_linked_query(tag2_id) |> tags_linked_query(tag2_id)
@ -833,8 +764,6 @@ defmodule Mobilizon.Events do
|> Repo.one() |> Repo.one()
end end
@moderator_roles [:moderator, :administrator, :creator]
@doc """ @doc """
Returns the number of participations for all local events Returns the number of participations for all local events
""" """
@ -894,28 +823,6 @@ defmodule Mobilizon.Events do
|> Page.build_page(page, limit) |> Page.build_page(page, limit)
end end
@doc """
Returns the list of moderator participants for an event.
## Examples
iex> moderator_for_event?(5, 3)
true
"""
@spec moderator_for_event?(integer, integer) :: boolean
def moderator_for_event?(event_id, actor_id) do
!(Repo.one(
from(
p in Participant,
where:
p.event_id == ^event_id and
p.actor_id ==
^actor_id and p.role in ^@moderator_roles
)
) == nil)
end
@doc """ @doc """
Returns the list of organizers participants for an event. Returns the list of organizers participants for an event.
@ -957,17 +864,6 @@ defmodule Mobilizon.Events do
|> Page.build_page(page, limit) |> Page.build_page(page, limit)
end end
@doc """
Counts approved participants.
"""
@spec count_approved_participants(integer | String.t()) :: integer
def count_approved_participants(event_id) do
event_id
|> count_participants_query()
|> filter_approved_role()
|> Repo.aggregate(:count, :id)
end
@doc """ @doc """
Counts participant participants (participants with no extra role) Counts participant participants (participants with no extra role)
""" """
@ -979,17 +875,6 @@ defmodule Mobilizon.Events do
|> Repo.aggregate(:count, :id) |> Repo.aggregate(:count, :id)
end end
@doc """
Counts rejected participants.
"""
@spec count_rejected_participants(integer | String.t()) :: integer
def count_rejected_participants(event_id) do
event_id
|> count_participants_query()
|> filter_rejected_role()
|> Repo.aggregate(:count, :id)
end
@doc """ @doc """
Gets the default participant role depending on the event join options. Gets the default participant role depending on the event join options.
""" """
@ -1221,17 +1106,6 @@ defmodule Mobilizon.Events do
|> Repo.one() |> Repo.one()
end end
@doc """
Gets a single feed token.
Raises `Ecto.NoResultsError` if the feed token does not exist.
"""
@spec get_feed_token!(String.t()) :: FeedToken.t()
def get_feed_token!(token) do
token
|> feed_token_query()
|> Repo.one!()
end
@doc """ @doc """
Creates a feed token. Creates a feed token.
""" """
@ -1244,17 +1118,6 @@ defmodule Mobilizon.Events do
|> Repo.insert() |> Repo.insert()
end end
@doc """
Updates a feed token.
"""
@spec update_feed_token(FeedToken.t(), map) ::
{:ok, FeedToken.t()} | {:error, Changeset.t()}
def update_feed_token(%FeedToken{} = feed_token, attrs) do
feed_token
|> FeedToken.changeset(attrs)
|> Repo.update()
end
@doc """ @doc """
Deletes a feed token. Deletes a feed token.
""" """
@ -1746,21 +1609,11 @@ defmodule Mobilizon.Events do
) )
end end
@spec filter_approved_role(Ecto.Queryable.t()) :: Ecto.Query.t()
defp filter_approved_role(query) do
filter_role(query, [:not_approved, :rejected])
end
@spec filter_participant_role(Ecto.Queryable.t()) :: Ecto.Query.t() @spec filter_participant_role(Ecto.Queryable.t()) :: Ecto.Query.t()
defp filter_participant_role(query) do defp filter_participant_role(query) do
filter_role(query, :participant) filter_role(query, :participant)
end end
@spec filter_rejected_role(Ecto.Queryable.t()) :: Ecto.Query.t()
defp filter_rejected_role(query) do
filter_role(query, :rejected)
end
@spec filter_role(Ecto.Queryable.t(), list(atom()) | atom()) :: Ecto.Query.t() @spec filter_role(Ecto.Queryable.t(), list(atom()) | atom()) :: Ecto.Query.t()
def filter_role(query, []), do: query def filter_role(query, []), do: query

View file

@ -52,16 +52,6 @@ defmodule Mobilizon.Medias do
|> Repo.all() |> Repo.all()
end end
@doc """
List the paginated media for an actor
"""
@spec medias_for_actor(integer | String.t(), integer | nil, integer | nil) :: Page.t()
def medias_for_actor(actor_id, page, limit) do
actor_id
|> medias_for_actor_query()
|> Page.build_page(page, limit)
end
@doc """ @doc """
List the paginated media for user List the paginated media for user
""" """
@ -109,16 +99,6 @@ defmodule Mobilizon.Medias do
|> Repo.insert() |> Repo.insert()
end end
@doc """
Updates a media.
"""
@spec update_media(Media.t(), map) :: {:ok, Media.t()} | {:error, Ecto.Changeset.t()}
def update_media(%Media{} = media, attrs) do
media
|> Media.changeset(attrs)
|> Repo.update()
end
@doc """ @doc """
Deletes a media. Deletes a media.
""" """

View file

@ -69,10 +69,6 @@ defmodule Mobilizon.Posts do
|> Repo.preload(@post_preloads) |> Repo.preload(@post_preloads)
end end
@spec get_post_by_slug(String.t()) :: Post.t() | nil
def get_post_by_slug(nil), do: nil
def get_post_by_slug(slug), do: Repo.get_by(Post, slug: slug)
@spec get_post_by_slug_with_preloads(String.t()) :: Post.t() | nil @spec get_post_by_slug_with_preloads(String.t()) :: Post.t() | nil
def get_post_by_slug_with_preloads(slug) do def get_post_by_slug_with_preloads(slug) do
Post Post

View file

@ -23,27 +23,6 @@ defmodule Mobilizon.Reports do
|> Repo.preload([:reported, :reporter, :manager, :event, :comments, :notes]) |> Repo.preload([:reported, :reporter, :manager, :event, :comments, :notes])
end end
@doc """
Gets a single report.
Raises `Ecto.NoResultsError` if the report does not exist.
"""
@spec get_report!(integer | String.t()) :: Report.t()
def get_report!(id) do
Report
|> Repo.get!(id)
|> Repo.preload([:reported, :reporter, :manager, :event, :comments, :notes])
end
@doc """
Get a report by its URL
"""
@spec get_report_by_url(String.t()) :: Report.t() | nil
def get_report_by_url(url) do
url
|> report_by_url_query()
|> Repo.one()
end
@doc """ @doc """
Creates a report. Creates a report.
""" """
@ -67,12 +46,6 @@ defmodule Mobilizon.Reports do
|> Repo.update() |> Repo.update()
end end
@doc """
Deletes a report.
"""
@spec delete_report(Report.t()) :: {:ok, Report.t()} | {:error, Ecto.Changeset.t()}
def delete_report(%Report{} = report), do: Repo.delete(report)
@doc """ @doc """
Returns the list of reports. Returns the list of reports.
""" """
@ -104,13 +77,6 @@ defmodule Mobilizon.Reports do
@spec get_note(integer | String.t()) :: Note.t() | nil @spec get_note(integer | String.t()) :: Note.t() | nil
def get_note(id), do: Repo.get(Note, id) def get_note(id), do: Repo.get(Note, id)
@doc """
Gets a single note.
Raises `Ecto.NoResultsError` if the Note does not exist.
"""
@spec get_note!(integer | String.t()) :: Note.t()
def get_note!(id), do: Repo.get!(Note, id)
@doc """ @doc """
Creates a note. Creates a note.
""" """
@ -130,21 +96,6 @@ defmodule Mobilizon.Reports do
@spec delete_note(Note.t()) :: {:ok, Note.t()} | {:error, Ecto.Changeset.t()} @spec delete_note(Note.t()) :: {:ok, Note.t()} | {:error, Ecto.Changeset.t()}
def delete_note(%Note{} = note), do: Repo.delete(note) def delete_note(%Note{} = note), do: Repo.delete(note)
@doc """
Returns the list of notes for a report.
"""
@spec list_notes_for_report(Report.t()) :: [Note.t()]
def list_notes_for_report(%Report{id: report_id}) do
report_id
|> list_notes_for_report_query()
|> Repo.all()
end
@spec report_by_url_query(String.t()) :: Ecto.Query.t()
defp report_by_url_query(url) do
from(r in Report, where: r.uri == ^url)
end
@spec list_reports_query(ReportStatus.t()) :: Ecto.Query.t() @spec list_reports_query(ReportStatus.t()) :: Ecto.Query.t()
defp list_reports_query(status) do defp list_reports_query(status) do
from( from(
@ -158,13 +109,4 @@ defmodule Mobilizon.Reports do
defp count_reports_query do defp count_reports_query do
from(r in Report, where: r.status == ^:open) from(r in Report, where: r.status == ^:open)
end end
@spec list_notes_for_report_query(integer | String.t()) :: Ecto.Query.t()
defp list_notes_for_report_query(report_id) do
from(
n in Note,
where: n.report_id == ^report_id,
preload: [:report, :moderator]
)
end
end end

View file

@ -27,13 +27,6 @@ defmodule Mobilizon.Resources do
|> Page.build_page(page, limit) |> Page.build_page(page, limit)
end end
@doc """
Returns the list of top-level resources for a group
"""
def get_top_level_resources_for_group(%Actor{id: group_id}, page \\ nil, limit \\ nil) do
get_resources_for_folder(%Resource{id: "root_something", actor_id: group_id}, page, limit)
end
@doc """ @doc """
Returns the list of resources for a resource folder. Returns the list of resources for a resource folder.
""" """

View file

@ -188,13 +188,6 @@ defmodule Mobilizon.Users.User do
|> hash_password() |> hash_password()
end end
@doc """
Checks whether an user is confirmed.
"""
@spec is_confirmed(t) :: boolean
def is_confirmed(%__MODULE__{confirmed_at: nil}), do: false
def is_confirmed(%__MODULE__{}), do: true
@doc """ @doc """
Returns whether an user owns an actor. Returns whether an user owns an actor.
""" """

View file

@ -91,19 +91,6 @@ defmodule Mobilizon.Users do
end end
end end
@doc """
Gets an user by its email.
"""
@spec get_user_by_email!(String.t(), Keyword.t()) :: User.t()
def get_user_by_email!(email, options \\ []) do
activated = Keyword.get(options, :activated, nil)
unconfirmed = Keyword.get(options, :unconfirmed, true)
email
|> user_by_email_query(activated, unconfirmed)
|> Repo.one!()
end
@doc """ @doc """
Get an user by its activation token. Get an user by its activation token.
""" """
@ -326,22 +313,6 @@ defmodule Mobilizon.Users do
@spec count_users :: integer @spec count_users :: integer
def count_users, do: Repo.one(from(u in User, select: count(u.id), where: u.disabled == false)) def count_users, do: Repo.one(from(u in User, select: count(u.id), where: u.disabled == false))
@doc """
Gets a settings for an user.
Raises `Ecto.NoResultsError` if the Setting does not exist.
## Examples
iex> get_setting!(123)
%Setting{}
iex> get_setting!(456)
** (Ecto.NoResultsError)
"""
def get_setting!(user_id), do: Repo.get!(Setting, user_id)
@spec get_setting(User.t()) :: Setting.t() | nil @spec get_setting(User.t()) :: Setting.t() | nil
def get_setting(%User{id: user_id}), do: get_setting(user_id) def get_setting(%User{id: user_id}), do: get_setting(user_id)
@ -388,35 +359,6 @@ defmodule Mobilizon.Users do
|> Repo.update() |> Repo.update()
end end
@doc """
Deletes a setting.
## Examples
iex> delete_setting(setting)
{:ok, %Setting{}}
iex> delete_setting(setting)
{:error, %Ecto.Changeset{}}
"""
def delete_setting(%Setting{} = setting) do
Repo.delete(setting)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking setting changes.
## Examples
iex> change_setting(setting)
%Ecto.Changeset{source: %Setting{}}
"""
def change_setting(%Setting{} = setting) do
Setting.changeset(setting, %{})
end
@doc """ @doc """
Get a paginated list of all of a user's subscriptions Get a paginated list of all of a user's subscriptions
""" """
@ -458,24 +400,6 @@ defmodule Mobilizon.Users do
|> Repo.insert() |> Repo.insert()
end end
@doc """
Updates a push subscription.
## Examples
iex> update_push_subscription(push_subscription, %{field: new_value})
{:ok, %PushSubscription{}}
iex> update_push_subscription(push_subscription, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_push_subscription(%PushSubscription{} = push_subscription, attrs) do
push_subscription
|> PushSubscription.changeset(attrs)
|> Repo.update()
end
@doc """ @doc """
Deletes a push subscription. Deletes a push subscription.

View file

@ -1,25 +0,0 @@
# Portions of this file are derived from Pleroma:
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Mobilizon.Utils do
@moduledoc """
Module that provide generic utils functions for Mobilizon
"""
@doc """
POSIX-compliant check if command is available in the system
## Examples
iex> command_available?("git")
true
iex> command_available?("wrongcmd")
false
"""
@spec command_available?(String.t()) :: boolean()
def command_available?(command) do
match?({_output, 0}, System.cmd("sh", ["-c", "command -v #{command}"]))
end
end

View file

@ -16,11 +16,6 @@ defmodule Mobilizon.Service.Activity do
do_get_object(object_type, object_id) do_get_object(object_type, object_id)
end end
@spec has_object?(Activity.t()) :: boolean()
def has_object?(%Activity{} = activity) do
!is_nil(object(activity))
end
defp do_get_object(_, nil), do: nil defp do_get_object(_, nil), do: nil
defp do_get_object(:event, event_id) do defp do_get_object(:event, event_id) do

View file

@ -102,7 +102,7 @@ defmodule Mobilizon.Service.Export.Common do
end end
@spec fetch_actor_private_events(Actor.t(), integer()) :: list(Event.t()) @spec fetch_actor_private_events(Actor.t(), integer()) :: list(Event.t())
def fetch_actor_private_events(%Actor{} = actor, limit) do defp fetch_actor_private_events(%Actor{} = actor, limit) do
actor |> fetch_identity_participations(limit) |> participations_to_events() actor |> fetch_identity_participations(limit) |> participations_to_events()
end end

View file

@ -3,7 +3,6 @@ defmodule Mobilizon.Service.Export.ICalendar do
Export an event to iCalendar format. Export an event to iCalendar format.
""" """
alias Mobilizon.Actors.Actor
alias Mobilizon.Addresses.Address alias Mobilizon.Addresses.Address
alias Mobilizon.{Config, Events} alias Mobilizon.{Config, Events}
alias Mobilizon.Events.Event alias Mobilizon.Events.Event
@ -79,14 +78,11 @@ defmodule Mobilizon.Service.Export.ICalendar do
def export_public_event(%Event{}), do: {:error, :event_not_public} def export_public_event(%Event{}), do: {:error, :event_not_public}
@doc """ # Export a public actor's events to iCalendar format.
Export a public actor's events to iCalendar format. # The actor must have a visibility of `:public` or `:unlisted`, as well as the events
The actor must have a visibility of `:public` or `:unlisted`, as well as the events
"""
@spec export_public_actor(String.t()) :: @spec export_public_actor(String.t()) ::
{:ok, String.t()} | {:error, :actor_not_public | :actor_not_found} {:ok, String.t()} | {:error, :actor_not_public | :actor_not_found}
def export_public_actor(name, limit \\ @item_limit) do defp export_public_actor(name, limit \\ @item_limit) do
case Common.fetch_actor_event_feed(name, limit) do case Common.fetch_actor_event_feed(name, limit) do
{:ok, _actor, events, _posts} -> {:ok, _actor, events, _posts} ->
{:ok, events_to_ics(events)} {:ok, events_to_ics(events)}
@ -96,12 +92,6 @@ defmodule Mobilizon.Service.Export.ICalendar do
end end
end end
@spec export_private_actor(Actor.t(), integer()) :: {:ok, String.t()}
def export_private_actor(%Actor{} = actor, limit \\ @item_limit) do
events = Common.fetch_actor_private_events(actor, limit)
{:ok, events_to_ics(events)}
end
@spec fetch_events_from_token(String.t(), integer()) :: @spec fetch_events_from_token(String.t(), integer()) ::
{:ok, String.t()} | {:error, :actor_not_public | :actor_not_found} {:ok, String.t()} | {:error, :actor_not_public | :actor_not_found}
defp fetch_events_from_token(token, limit \\ @item_limit) do defp fetch_events_from_token(token, limit \\ @item_limit) do

View file

@ -28,12 +28,12 @@ defmodule Mobilizon.Service.HTTP.ActivityPub do
Tesla.client(middleware, {adapter, opts}) Tesla.client(middleware, {adapter, opts})
end end
@spec get(Tesla.Client.t(), String.t()) :: Tesla.Env.t() @spec get(Tesla.Client.t(), String.t()) :: Tesla.Env.result()
def get(client, url) do def get(client, url) do
Tesla.get(client, url) Tesla.get(client, url)
end end
@spec post(Tesla.Client.t(), String.t(), map() | String.t()) :: Tesla.Env.t() @spec post(Tesla.Client.t(), String.t(), map() | String.t()) :: Tesla.Env.result()
def post(client, url, data) do def post(client, url, data) do
Tesla.post(client, url, data) Tesla.post(client, url, data)
end end

View file

@ -25,19 +25,29 @@ defmodule Mobilizon.Service.RichMedia.Parsers.TwitterCard do
Logger.debug("Using Twitter card parser") Logger.debug("Using Twitter card parser")
with {:ok, data} <- parse_name_attrs(data, html), with {:ok, data} <- parse_name_attrs(data, html),
{:ok, data} <- parse_property_attrs(data, html), {:ok, data} <- parse_property_attrs(data, html) do
data <- transform_tags(data) do data = transform_tags(data)
Logger.debug("Data found with Twitter card parser") Logger.debug("Data found with Twitter card parser")
Logger.debug(inspect(data)) Logger.debug(inspect(data))
data data
end end
end end
@spec parse_name_attrs(map(), String.t()) :: {:ok, map()} | {:error, String.t()}
defp parse_name_attrs(data, html) do defp parse_name_attrs(data, html) do
MetaTagsParser.parse(html, data, "twitter", %{}, :name, :content, [:"twitter:card"]) MetaTagsParser.parse(
html,
data,
"twitter",
"No twitter card metadata found",
:name,
:content,
[:"twitter:card"]
)
end end
defp parse_property_attrs({_, data}, html) do @spec parse_property_attrs(map(), String.t()) :: {:ok, map()} | {:error, String.t()}
defp parse_property_attrs(data, html) do
MetaTagsParser.parse( MetaTagsParser.parse(
html, html,
data, data,
@ -49,6 +59,7 @@ defmodule Mobilizon.Service.RichMedia.Parsers.TwitterCard do
) )
end end
@spec transform_tags(map()) :: map()
defp transform_tags(data) do defp transform_tags(data) do
data data
|> Enum.reject(fn {_, v} -> is_nil(v) end) |> Enum.reject(fn {_, v} -> is_nil(v) end)

View file

@ -10,21 +10,9 @@ defmodule Mobilizon.Web.Cache do
alias Mobilizon.Resources.Resource alias Mobilizon.Resources.Resource
alias Mobilizon.Todos.{Todo, TodoList} alias Mobilizon.Todos.{Todo, TodoList}
alias Mobilizon.Web.Cache.ActivityPub alias Mobilizon.Web.Cache.ActivityPub
import Mobilizon.Service.Guards, only: [is_valid_string: 1]
@caches [:activity_pub, :feed, :ics]
@type local_actor :: %Actor{domain: nil} @type local_actor :: %Actor{domain: nil}
@doc """
Clears all caches for a local actor.
"""
@spec clear_cache(%Actor{domain: nil, preferred_username: String.t()}) :: :ok
def clear_cache(%Actor{preferred_username: preferred_username, domain: nil})
when is_valid_string(preferred_username) do
Enum.each(@caches, &Cachex.del(&1, "actor_" <> preferred_username))
end
@spec get_actor_by_name(binary) :: {:commit, Actor.t()} | {:ignore, nil} @spec get_actor_by_name(binary) :: {:commit, Actor.t()} | {:ignore, nil}
defdelegate get_actor_by_name(name), to: ActivityPub defdelegate get_actor_by_name(name), to: ActivityPub
@spec get_local_actor_by_name(binary) :: {:commit, Actor.t()} | {:ignore, nil} @spec get_local_actor_by_name(binary) :: {:commit, Actor.t()} | {:ignore, nil}

View file

@ -30,7 +30,6 @@ defmodule Mobilizon.Web.FeedController do
return_data(conn, "ics", "event_" <> uuid, "event") return_data(conn, "ics", "event_" <> uuid, "event")
end end
@spec instance(Plug.Conn.t(), map()) :: Plug.Conn.t()
def event(_conn, _) do def event(_conn, _) do
{:error, :not_found} {:error, :not_found}
end end

View file

@ -15,9 +15,9 @@ defmodule Mobilizon.Web.Email.Admin do
alias Mobilizon.Web.Email alias Mobilizon.Web.Email
@spec report(User.t(), Report.t(), String.t()) :: Bamboo.Email.t() @spec report(User.t(), Report.t()) :: Bamboo.Email.t()
def report(%User{email: email} = user, %Report{} = report, default_locale \\ "en") do def report(%User{email: email} = user, %Report{} = report) do
locale = Map.get(user, :locale, default_locale) locale = Map.get(user, :locale, "en")
Gettext.put_locale(locale) Gettext.put_locale(locale)
subject = subject =

View file

@ -11,11 +11,11 @@ defmodule Mobilizon.Web.Email.Checker do
@spec valid?(String.t()) :: boolean @spec valid?(String.t()) :: boolean
def valid?(email), do: email =~ @email_regex def valid?(email), do: email =~ @email_regex
@spec validate_changeset(Ecto.Changeset.t(), atom()) :: Ecto.Changeset.t() @spec validate_changeset(Ecto.Changeset.t()) :: Ecto.Changeset.t()
def validate_changeset(%Ecto.Changeset{} = changeset, key \\ :email) do def validate_changeset(%Ecto.Changeset{} = changeset) do
changeset = Ecto.Changeset.validate_length(changeset, :email, min: 3, max: 250) changeset = Ecto.Changeset.validate_length(changeset, :email, min: 3, max: 250)
case Ecto.Changeset.fetch_change(changeset, key) do case Ecto.Changeset.fetch_change(changeset, :email) do
{:ok, email} -> {:ok, email} ->
if valid?(email), if valid?(email),
do: changeset, do: changeset,

View file

@ -15,17 +15,15 @@ defmodule Mobilizon.Web.Email.Group do
@doc """ @doc """
Send emails to local user Send emails to local user
""" """
@spec send_invite_to_user(Member.t(), String.t()) :: :ok @spec send_invite_to_user(Member.t()) :: :ok
def send_invite_to_user(member, locale \\ "en") def send_invite_to_user(%Member{actor: %Actor{user_id: nil}}), do: :ok
def send_invite_to_user(%Member{actor: %Actor{user_id: nil}}, _locale), do: :ok
def send_invite_to_user( def send_invite_to_user(
%Member{actor: %Actor{user_id: user_id}, parent: %Actor{} = group, role: :invited} = %Member{actor: %Actor{user_id: user_id}, parent: %Actor{} = group, role: :invited} =
member, member
locale
) do ) do
with %User{email: email} = user <- Users.get_user!(user_id) do with %User{email: email} = user <- Users.get_user!(user_id) do
locale = Map.get(user, :locale, locale) locale = Map.get(user, :locale, "en")
Gettext.put_locale(locale) Gettext.put_locale(locale)
%Actor{name: invited_by_name} = inviter = Actors.get_actor(member.invited_by_id) %Actor{name: invited_by_name} = inviter = Actors.get_actor(member.invited_by_id)

View file

@ -144,10 +144,11 @@ defmodule Mobilizon.Web.Email.User do
end end
end end
def send_email_reset_old_email( def send_email_reset_old_email(%User{
%User{locale: user_locale, email: email, unconfirmed_email: unconfirmed_email} = _user, locale: user_locale,
_locale \\ "en" email: email,
) do unconfirmed_email: unconfirmed_email
}) do
Gettext.put_locale(user_locale) Gettext.put_locale(user_locale)
subject = subject =
@ -163,14 +164,11 @@ defmodule Mobilizon.Web.Email.User do
|> render(:email_changed_old) |> render(:email_changed_old)
end end
def send_email_reset_new_email( def send_email_reset_new_email(%User{
%User{ locale: user_locale,
locale: user_locale, unconfirmed_email: unconfirmed_email,
unconfirmed_email: unconfirmed_email, confirmation_token: confirmation_token
confirmation_token: confirmation_token }) do
} = _user,
_locale \\ "en"
) do
Gettext.put_locale(user_locale) Gettext.put_locale(user_locale)
subject = subject =

View file

@ -17,9 +17,6 @@ defmodule Mobilizon.Web.ReverseProxy do
@max_body_length :infinity @max_body_length :infinity
@methods ~w(GET HEAD) @methods ~w(GET HEAD)
def max_read_duration_default, do: @max_read_duration
def default_cache_control_header, do: @default_cache_control_header
@moduledoc """ @moduledoc """
A reverse proxy. A reverse proxy.

View file

@ -36,22 +36,6 @@ defmodule Mobilizon.Web.Upload.MIME do
end) end)
end end
def bin_mime_type(binary, filename) do
with {:ok, content_type} <- bin_mime_type(binary),
filename <- fix_extension(filename, content_type) do
{:ok, content_type, filename}
end
end
@spec bin_mime_type(binary()) :: {:ok, String.t()} | {:error, :unknown_mime}
def bin_mime_type(<<head::binary-size(@read_bytes), _::binary>>) do
{:ok, check_mime_type(head)}
end
def bin_mime_type(_), do: {:error, :unknown_mime}
def mime_type(<<_::binary>>), do: {:ok, @default}
defp fix_extension(filename, content_type) defp fix_extension(filename, content_type)
when is_binary(filename) and is_binary(content_type) do when is_binary(filename) and is_binary(content_type) do
parts = String.split(filename, ".") parts = String.split(filename, ".")

View file

@ -94,19 +94,21 @@ defmodule Mobilizon.Web.Upload do
end end
end end
@spec remove(String.t(), Keyword.t()) :: @spec remove(String.t()) :: {:ok, String.t()} | {:error, atom}
{:ok, String.t()} | {:error, atom} | {:error, String.t()} def remove(url) do
def remove(url, opts \\ []) do %{uploader: uploader} = get_opts([])
with opts <- get_opts(opts),
%URI{path: "/media/" <> path, host: host} <- URI.parse(url),
{:same_host, true} <- {:same_host, host == Endpoint.host()} do
Uploader.remove_file(opts.uploader, path)
else
%URI{} = _uri ->
{:error, "URL doesn't match pattern"}
{:same_host, _} -> case URI.parse(url) do
Logger.error("Media can't be deleted because its URL doesn't match current host") %URI{path: "/media/" <> path, host: host} ->
if host == Endpoint.host() do
Uploader.remove_file(uploader, path)
else
Logger.error("Media can't be deleted because its URL doesn't match current host")
{:error, :not_same_host}
end
%URI{} = _uri ->
{:error, :url_invalid}
end end
end end

43
mix.exs
View file

@ -9,7 +9,7 @@ defmodule Mobilizon.Mixfile do
version: @version, version: @version,
elixir: "~> 1.11", elixir: "~> 1.11",
elixirc_paths: elixirc_paths(Mix.env()), elixirc_paths: elixirc_paths(Mix.env()),
compilers: [:gettext] ++ Mix.compilers(), compilers: [:gettext, :unused] ++ Mix.compilers(),
xref: [exclude: [:eldap]], xref: [exclude: [:eldap]],
start_permanent: Mix.env() == :prod, start_permanent: Mix.env() == :prod,
aliases: aliases(), aliases: aliases(),
@ -37,6 +37,44 @@ defmodule Mobilizon.Mixfile do
config_providers: [{Mobilizon.ConfigProvider, "/etc/mobilizon/config.exs"}], config_providers: [{Mobilizon.ConfigProvider, "/etc/mobilizon/config.exs"}],
steps: [:assemble, &copy_files/1, &copy_config/1] steps: [:assemble, &copy_files/1, &copy_config/1]
] ]
],
unused: [
ignore: [
Mobilizon.Storage.Repo,
Mobilizon.Storage.PostgresTypes,
Mobilizon.Factory,
Mobilizon.Web.Router.Helpers,
Mobilizon.Web.Email.Mailer,
Mobilizon.Web.Auth.Guardian.Plug,
Mobilizon.Web.Gettext,
Mobilizon.Web.Endpoint,
Mobilizon.Web.Auth.Guardian,
Mobilizon.Web,
Mobilizon.GraphQL.Schema.Compiled,
Mobilizon.GraphQL.Schema,
Mobilizon.Web.Router,
Mobilizon.Users.Setting.Location,
{:_, :start_link, 1},
{:_, :child_spec, 1},
{:_, :__impl__, 1},
{:_, :__schema__, :_},
{:_, :__struct__, 0..1},
{:_, :__changeset__, 0},
{:_, :create_type, 0},
{:_, :drop_type, 0},
{:_, :schema, 0},
{:_, :schemaless_type, 0},
{:_, :valid_value?, 0..1},
{:_, :__enum_map__, 0},
{:_, :__absinthe_blueprint__, :_},
{:_, :__absinthe_function__, :_},
{~r/^Mobilizon.Web.*Controller/, :_, 2},
{~r/^Mobilizon.Web.*View/, :_, :_},
{~r/^Mobilizon.Web.Email.*/, :render, 3},
{~r/^Mobilizon.Service.HTTP.*Client/, :_, :_},
{~r/^Mobilizon.Cldr.*/, :_, :_},
{Mobilizon.Web.GraphQLSocket, :__channel__, 1}
]
] ]
] ]
end end
@ -183,7 +221,8 @@ defmodule Mobilizon.Mixfile do
{:mox, "~> 1.0", only: :test}, {:mox, "~> 1.0", only: :test},
{:junit_formatter, "~> 3.1", only: [:test]}, {:junit_formatter, "~> 3.1", only: [:test]},
{:sobelow, "~> 0.8", only: [:dev, :test]}, {:sobelow, "~> 0.8", only: [:dev, :test]},
{:doctor, "~> 0.18.0", only: :dev} {:doctor, "~> 0.18.0", only: :dev},
{:mix_unused, "~> 0.2.0"}
] ++ oauth_deps() ] ++ oauth_deps()
end end

View file

@ -94,6 +94,7 @@
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
"mimetype_parser": {:hex, :mimetype_parser, "0.1.3", "628ac9fe56aa7edcedb534d68397dd66674ab82493c8ebe39acb9a19b666099d", [:mix], [], "hexpm", "7d8f80c567807ce78cd93c938e7f4b0a20b1aaaaab914bf286f68457d9f7a852"}, "mimetype_parser": {:hex, :mimetype_parser, "0.1.3", "628ac9fe56aa7edcedb534d68397dd66674ab82493c8ebe39acb9a19b666099d", [:mix], [], "hexpm", "7d8f80c567807ce78cd93c938e7f4b0a20b1aaaaab914bf286f68457d9f7a852"},
"mix_test_watch": {:hex, :mix_test_watch, "1.1.0", "330bb91c8ed271fe408c42d07e0773340a7938d8a0d281d57a14243eae9dc8c3", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm", "52b6b1c476cbb70fd899ca5394506482f12e5f6b0d6acff9df95c7f1e0812ec3"}, "mix_test_watch": {:hex, :mix_test_watch, "1.1.0", "330bb91c8ed271fe408c42d07e0773340a7938d8a0d281d57a14243eae9dc8c3", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm", "52b6b1c476cbb70fd899ca5394506482f12e5f6b0d6acff9df95c7f1e0812ec3"},
"mix_unused": {:hex, :mix_unused, "0.2.0", "430d011f7c86eec8e4824c66fb69127f192ca3b2b2dd0e0f8f58bf535d319167", [:mix], [], "hexpm", "f3eb53bf416d89be1db801865b3f2a6c8c084e138ad290c82b5136a31e5622ad"},
"mmdb2_decoder": {:hex, :mmdb2_decoder, "3.0.0", "54828676a36e75e9a25bc9a0bb0598d4c7fcc767bf0b40674850b22e05b7b6cc", [:mix], [], "hexpm", "359dc9242915538d1dceb9f6d96c72201dca76ce62e49d22e2ed1e86f20bea8e"}, "mmdb2_decoder": {:hex, :mmdb2_decoder, "3.0.0", "54828676a36e75e9a25bc9a0bb0598d4c7fcc767bf0b40674850b22e05b7b6cc", [:mix], [], "hexpm", "359dc9242915538d1dceb9f6d96c72201dca76ce62e49d22e2ed1e86f20bea8e"},
"mock": {:hex, :mock, "0.3.7", "75b3bbf1466d7e486ea2052a73c6e062c6256fb429d6797999ab02fa32f29e03", [:mix], [{:meck, "~> 0.9.2", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "4da49a4609e41fd99b7836945c26f373623ea968cfb6282742bcb94440cf7e5c"}, "mock": {:hex, :mock, "0.3.7", "75b3bbf1466d7e486ea2052a73c6e062c6256fb429d6797999ab02fa32f29e03", [:mix], [{:meck, "~> 0.9.2", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "4da49a4609e41fd99b7836945c26f373623ea968cfb6282742bcb94440cf7e5c"},
"mogrify": {:hex, :mogrify, "0.9.1", "a26f107c4987477769f272bd0f7e3ac4b7b75b11ba597fd001b877beffa9c068", [:mix], [], "hexpm", "134edf189337d2125c0948bf0c228fdeef975c594317452d536224069a5b7f05"}, "mogrify": {:hex, :mogrify, "0.9.1", "a26f107c4987477769f272bd0f7e3ac4b7b75b11ba597fd001b877beffa9c068", [:mix], [], "hexpm", "134edf189337d2125c0948bf0c228fdeef975c594317452d536224069a5b7f05"},

View file

@ -413,12 +413,6 @@ defmodule Mobilizon.ActorsTest do
@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}
test "list_bots/0 returns all bots" do
bot = insert(:bot)
bot_found_id = Actors.list_bots() |> hd |> Map.get(:id)
assert bot_found_id == bot.id
end
test "get_bot!/1 returns the bot with given id" do test "get_bot!/1 returns the bot with given id" do
%Bot{id: bot_id} = bot = insert(:bot) %Bot{id: bot_id} = bot = insert(:bot)
assert bot_id == Actors.get_bot!(bot.id).id assert bot_id == Actors.get_bot!(bot.id).id

View file

@ -12,12 +12,6 @@ defmodule Mobilizon.DiscussionsTest do
@update_attrs %{text: "some updated text"} @update_attrs %{text: "some updated text"}
@invalid_attrs %{text: nil, url: nil} @invalid_attrs %{text: nil, url: nil}
test "list_comments/0 returns all comments" do
%Comment{id: comment_id} = insert(:comment)
comment_ids = Discussions.list_comments() |> Enum.map(& &1.id)
assert comment_ids == [comment_id]
end
test "get_comment!/1 returns the comment with given id" do test "get_comment!/1 returns the comment with given id" do
%Comment{id: comment_id} = insert(:comment) %Comment{id: comment_id} = insert(:comment)
comment_fetched = Discussions.get_comment!(comment_id) comment_fetched = Discussions.get_comment!(comment_id)

View file

@ -301,8 +301,8 @@ defmodule Mobilizon.EventsTest do
assert {:ok, %TagRelation{}} = assert {:ok, %TagRelation{}} =
Events.create_tag_relation(%{tag_id: tag1_id, link_id: tag2_id}) Events.create_tag_relation(%{tag_id: tag1_id, link_id: tag2_id})
assert Events.are_tags_linked(tag1, tag2) assert Events.are_tags_linked?(tag1, tag2)
assert Events.are_tags_linked(tag2, tag1) assert Events.are_tags_linked?(tag2, tag1)
end end
test "create_tag_relation/1 with invalid data returns error changeset", %{ test "create_tag_relation/1 with invalid data returns error changeset", %{
@ -312,7 +312,7 @@ defmodule Mobilizon.EventsTest do
assert {:error, %Ecto.Changeset{}} = assert {:error, %Ecto.Changeset{}} =
Events.create_tag_relation(%{tag_id: nil, link_id: nil}) Events.create_tag_relation(%{tag_id: nil, link_id: nil})
refute Events.are_tags_linked(tag1, tag2) refute Events.are_tags_linked?(tag1, tag2)
end end
test "delete_tag_relation/1 deletes the tag relation" do test "delete_tag_relation/1 deletes the tag relation" do

View file

@ -17,12 +17,6 @@ defmodule Mobilizon.MediaTest do
name: "something old" name: "something old"
} }
} }
@update_attrs %{
file: %{
url: "https://something.tld/media/something_updated",
name: "something new"
}
}
test "get_media!/1 returns the media with given id" do test "get_media!/1 returns the media with given id" do
media = insert(:media) media = insert(:media)
@ -36,18 +30,6 @@ defmodule Mobilizon.MediaTest do
assert media.file.name == "something old" assert media.file.name == "something old"
end end
test "update_media/2 with valid data updates the media" do
media = insert(:media)
assert {:ok, %Media{} = media} =
Medias.update_media(
media,
Map.put(@update_attrs, :actor_id, insert(:actor).id)
)
assert media.file.name == "something new"
end
test "delete_media/1 deletes the media" do test "delete_media/1 deletes the media" do
media = insert(:media) media = insert(:media)

View file

@ -128,12 +128,6 @@ defmodule Mobilizon.UsersTest do
setting setting
end end
test "get_setting!/1 returns the setting with given id" do
%User{id: user_id} = insert(:user)
setting = setting_fixture(user_id: user_id)
assert Users.get_setting!(setting.user_id) == setting
end
test "create_setting/1 with valid data creates a setting" do test "create_setting/1 with valid data creates a setting" do
%User{id: user_id} = insert(:user) %User{id: user_id} = insert(:user)
@ -155,18 +149,5 @@ defmodule Mobilizon.UsersTest do
assert setting.timezone == "Atlantic/Cape_Verde" assert setting.timezone == "Atlantic/Cape_Verde"
assert setting.notification_each_week == false assert setting.notification_each_week == false
end end
test "delete_setting/1 deletes the setting" do
%User{id: user_id} = insert(:user)
setting = setting_fixture(user_id: user_id)
assert {:ok, %Setting{}} = Users.delete_setting(setting)
assert_raise Ecto.NoResultsError, fn -> Users.get_setting!(setting.user_id) end
end
test "change_setting/1 returns a setting changeset" do
%User{id: user_id} = insert(:user)
setting = setting_fixture(user_id: user_id)
assert %Ecto.Changeset{} = Users.change_setting(setting)
end
end end
end end

View file

@ -74,6 +74,21 @@ defmodule Mobilizon.DataCase do
:ok :ok
end end
@doc """
POSIX-compliant check if command is available in the system
## Examples
iex> command_available?("git")
true
iex> command_available?("wrongcmd")
false
"""
@spec command_available?(String.t()) :: boolean()
def command_available?(command) do
match?({_output, 0}, System.cmd("sh", ["-c", "command -v #{command}"]))
end
Mox.defmock(Mobilizon.Service.HTTP.ActivityPub.Mock, for: Tesla.Adapter) Mox.defmock(Mobilizon.Service.HTTP.ActivityPub.Mock, for: Tesla.Adapter)
Mox.defmock(Mobilizon.Service.HTTP.GeospatialClient.Mock, Mox.defmock(Mobilizon.Service.HTTP.GeospatialClient.Mock,

View file

@ -31,7 +31,7 @@ defmodule Mobilizon.Web.WebFingerControllerTest do
test "GET /.well-known/webfinger with local actor", %{conn: conn} do test "GET /.well-known/webfinger with local actor", %{conn: conn} do
%Actor{preferred_username: username} = actor = insert(:actor) %Actor{preferred_username: username} = actor = insert(:actor)
conn = get(conn, "/.well-known/webfinger?resource=acct:#{username}@mobilizon.test") conn = get(conn, "/.well-known/webfinger?resource=acct:#{username}@mobilizon.test")
assert json_response(conn, 200) == WebFinger.represent_actor(actor) assert json_response(conn, 200) == WebFinger.represent_actor(actor, "JSON")
end end
test "GET /.well-known/webfinger with non existent actor", %{conn: conn} do test "GET /.well-known/webfinger with non existent actor", %{conn: conn} do

View file

@ -8,9 +8,15 @@ defmodule Mobilizon.Web.Upload.Filter.ExiftoolTest do
alias Mobilizon.Web.Upload alias Mobilizon.Web.Upload
alias Mobilizon.Web.Upload.Filter alias Mobilizon.Web.Upload.Filter
test "apply exiftool filter" do setup do
assert Mobilizon.Utils.command_available?("exiftool") if command_available?("exiftool") do
{:ok, skip: true}
else
:ok
end
end
test "apply exiftool filter" do
File.cp!( File.cp!(
"test/fixtures/DSCN0010.jpg", "test/fixtures/DSCN0010.jpg",
"test/fixtures/DSCN0010_tmp.jpg" "test/fixtures/DSCN0010_tmp.jpg"