Various typespec and compilation improvements
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -15,12 +15,13 @@ defmodule Mobilizon.GraphQL.API.Reports do
|
||||
@doc """
|
||||
Create a report/flag on an actor, and optionally on an event or on comments.
|
||||
"""
|
||||
@spec report(map()) :: {:ok, Activity.t(), Report.t()} | {:error, any()}
|
||||
def report(args) do
|
||||
case {:make_activity, ActivityPub.flag(args, Map.get(args, :forward, false) == true)} do
|
||||
{:make_activity, {:ok, %Activity{} = activity, %Report{} = report}} ->
|
||||
case ActivityPub.flag(args, Map.get(args, :forward, false) == true) do
|
||||
{:ok, %Activity{} = activity, %Report{} = report} ->
|
||||
{:ok, activity, report}
|
||||
|
||||
{:make_activity, err} ->
|
||||
err ->
|
||||
{:error, err}
|
||||
end
|
||||
end
|
||||
@@ -28,10 +29,12 @@ defmodule Mobilizon.GraphQL.API.Reports do
|
||||
@doc """
|
||||
Update the state of a report
|
||||
"""
|
||||
@spec update_report_status(Actor.t(), Report.t(), ReportStatus.t()) ::
|
||||
{:ok, Report.t()} | {:error, String.t()}
|
||||
def update_report_status(%Actor{} = actor, %Report{} = report, state) do
|
||||
with {:valid_state, true} <-
|
||||
{:valid_state, ReportStatus.valid_value?(state)},
|
||||
{:ok, report} <- ReportsAction.update_report(report, %{"status" => state}),
|
||||
{:ok, %Report{} = report} <- ReportsAction.update_report(report, %{"status" => state}),
|
||||
{:ok, _} <- Admin.log_action(actor, "update", report) do
|
||||
{:ok, report}
|
||||
else
|
||||
@@ -42,7 +45,8 @@ defmodule Mobilizon.GraphQL.API.Reports do
|
||||
@doc """
|
||||
Create a note on a report
|
||||
"""
|
||||
@spec create_report_note(Report.t(), Actor.t(), String.t()) :: {:ok, Note.t()}
|
||||
@spec create_report_note(Report.t(), Actor.t(), String.t()) ::
|
||||
{:ok, Note.t()} | {:error, String.t()}
|
||||
def create_report_note(
|
||||
%Report{id: report_id},
|
||||
%Actor{id: moderator_id, user_id: user_id} = moderator,
|
||||
@@ -67,7 +71,7 @@ defmodule Mobilizon.GraphQL.API.Reports do
|
||||
@doc """
|
||||
Delete a report note
|
||||
"""
|
||||
@spec delete_report_note(Note.t(), Actor.t()) :: {:ok, Note.t()}
|
||||
@spec delete_report_note(Note.t(), Actor.t()) :: {:ok, Note.t()} | {:error, String.t()}
|
||||
def delete_report_note(
|
||||
%Note{moderator_id: note_moderator_id} = note,
|
||||
%Actor{id: moderator_id, user_id: user_id} = moderator
|
||||
|
||||
@@ -10,7 +10,7 @@ defmodule Mobilizon.GraphQL.API.Utils do
|
||||
@doc """
|
||||
Creates HTML content from text and mentions
|
||||
"""
|
||||
@spec make_content_html(String.t(), list(), String.t()) :: String.t()
|
||||
@spec make_content_html(String.t(), list(), String.t()) :: {String.t(), list(), list()}
|
||||
def make_content_html(text, additional_tags, content_type) do
|
||||
with {text, mentions, tags} <- format_input(text, content_type, []) do
|
||||
{text, mentions, additional_tags ++ Enum.map(tags, fn {_, tag} -> tag end)}
|
||||
|
||||
@@ -66,7 +66,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Comment do
|
||||
with {:actor, %Actor{id: actor_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
|
||||
%CommentModel{actor_id: comment_actor_id} = comment <-
|
||||
Mobilizon.Discussions.get_comment_with_preload(comment_id),
|
||||
true <- actor_id === comment_actor_id,
|
||||
true <- actor_id == comment_actor_id,
|
||||
{:ok, _, %CommentModel{} = comment} <- Comments.update_comment(comment, %{text: text}) do
|
||||
{:ok, comment}
|
||||
end
|
||||
|
||||
@@ -6,7 +6,10 @@ defmodule Mobilizon.GraphQL.Resolvers.Event.Utils do
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Federation.ActivityPub.Permission
|
||||
import Mobilizon.Service.Guards, only: [is_valid_string: 1]
|
||||
|
||||
@spec can_event_be_updated_by?(%Event{id: String.t()}, Actor.t()) ::
|
||||
boolean
|
||||
def can_event_be_updated_by?(
|
||||
%Event{attributed_to: %Actor{type: :Group}} = event,
|
||||
%Actor{} = actor_member
|
||||
@@ -21,10 +24,13 @@ defmodule Mobilizon.GraphQL.Resolvers.Event.Utils do
|
||||
Event.can_be_managed_by?(event, actor_member_id)
|
||||
end
|
||||
|
||||
@spec can_event_be_deleted_by?(%Event{id: String.t(), url: String.t()}, Actor.t()) ::
|
||||
boolean
|
||||
def can_event_be_deleted_by?(
|
||||
%Event{attributed_to: %Actor{type: :Group}} = event,
|
||||
%Event{attributed_to: %Actor{type: :Group}, id: event_id, url: event_url} = event,
|
||||
%Actor{} = actor_member
|
||||
) do
|
||||
)
|
||||
when is_valid_string(event_id) and is_valid_string(event_url) do
|
||||
Permission.can_delete_group_object?(actor_member, event)
|
||||
end
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Member do
|
||||
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
|
||||
%Member{actor: %Actor{id: member_actor_id}} = member <-
|
||||
Actors.get_member(member_id),
|
||||
{:is_same_actor, true} <- {:is_same_actor, member_actor_id === actor_id},
|
||||
{:is_same_actor, true} <- {:is_same_actor, member_actor_id == actor_id},
|
||||
{:ok, _activity, %Member{} = member} <-
|
||||
ActivityPub.accept(
|
||||
:invite,
|
||||
@@ -119,7 +119,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Member do
|
||||
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
|
||||
{:invitation_exists, %Member{actor: %Actor{id: member_actor_id}} = member} <-
|
||||
{:invitation_exists, Actors.get_member(member_id)},
|
||||
{:is_same_actor, true} <- {:is_same_actor, member_actor_id === actor_id},
|
||||
{:is_same_actor, true} <- {:is_same_actor, member_actor_id == actor_id},
|
||||
{:ok, _activity, %Member{} = member} <-
|
||||
ActivityPub.reject(
|
||||
:invite,
|
||||
|
||||
@@ -95,6 +95,9 @@ defmodule Mobilizon.GraphQL.Resolvers.Todos do
|
||||
ActivityPub.create(:todo_list, Map.put(args, :actor_id, group_id), true, %{}) do
|
||||
{:ok, todo_list}
|
||||
else
|
||||
{:actor, nil} ->
|
||||
{:error, dgettext("errors", "No profile found for user")}
|
||||
|
||||
{:member, _} ->
|
||||
{:error, dgettext("errors", "Profile is not member of group")}
|
||||
end
|
||||
@@ -187,6 +190,9 @@ defmodule Mobilizon.GraphQL.Resolvers.Todos do
|
||||
ActivityPub.create(:todo, Map.put(args, :creator_id, actor_id), true, %{}) do
|
||||
{:ok, todo}
|
||||
else
|
||||
{:actor, nil} ->
|
||||
{:error, dgettext("errors", "No profile found for user")}
|
||||
|
||||
{:todo_list, _} ->
|
||||
{:error, dgettext("errors", "Todo list doesn't exist")}
|
||||
|
||||
@@ -212,6 +218,9 @@ defmodule Mobilizon.GraphQL.Resolvers.Todos do
|
||||
ActivityPub.update(todo, args, true, %{}) do
|
||||
{:ok, todo}
|
||||
else
|
||||
{:actor, nil} ->
|
||||
{:error, dgettext("errors", "No profile found for user")}
|
||||
|
||||
{:todo_list, _} ->
|
||||
{:error, dgettext("errors", "Todo list doesn't exist")}
|
||||
|
||||
|
||||
@@ -65,9 +65,8 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
||||
refresh_token: _refresh_token,
|
||||
user: %User{} = user
|
||||
} = user_and_tokens} <- Authenticator.authenticate(email, password),
|
||||
{:ok, %User{} = user} <- update_user_login_information(user, context),
|
||||
user_and_tokens <- Map.put(user_and_tokens, :user, user) do
|
||||
{:ok, user_and_tokens}
|
||||
{:ok, %User{} = user} <- update_user_login_information(user, context) do
|
||||
{:ok, %{user_and_tokens | user: user}}
|
||||
else
|
||||
{:error, :user_not_found} ->
|
||||
{:error, :user_not_found}
|
||||
@@ -133,7 +132,7 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
||||
- create the user
|
||||
- send a validation email to the user
|
||||
"""
|
||||
@spec create_user(any, map, any) :: tuple
|
||||
@spec create_user(any, %{email: String.t()}, any) :: tuple
|
||||
def create_user(_parent, %{email: email} = args, _resolution) do
|
||||
with :registration_ok <- check_registration_config(email),
|
||||
:not_deny_listed <- check_registration_denylist(email),
|
||||
@@ -160,20 +159,21 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
||||
end
|
||||
end
|
||||
|
||||
@spec check_registration_config(map) :: atom
|
||||
@spec check_registration_config(String.t()) :: atom
|
||||
defp check_registration_config(email) do
|
||||
cond do
|
||||
Config.instance_registrations_open?() ->
|
||||
:registration_ok
|
||||
|
||||
Config.instance_registrations_allowlist?() ->
|
||||
check_allow_listed_email?(email)
|
||||
check_allow_listed_email(email)
|
||||
|
||||
true ->
|
||||
:registration_closed
|
||||
end
|
||||
end
|
||||
|
||||
@spec check_registration_denylist(String.t()) :: :deny_listed | :not_deny_listed
|
||||
defp check_registration_denylist(email) do
|
||||
# Remove everything behind the +
|
||||
email = String.replace(email, ~r/(\+.*)(?=\@)/, "")
|
||||
@@ -183,8 +183,8 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
||||
else: :not_deny_listed
|
||||
end
|
||||
|
||||
@spec check_allow_listed_email?(String.t()) :: :registration_ok | :not_allowlisted
|
||||
defp check_allow_listed_email?(email) do
|
||||
@spec check_allow_listed_email(String.t()) :: :registration_ok | :not_allowlisted
|
||||
defp check_allow_listed_email(email) do
|
||||
if email_in_list(email, Config.instance_registrations_allowlist()),
|
||||
do: :registration_ok,
|
||||
else: :not_allowlisted
|
||||
@@ -199,12 +199,14 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
||||
@doc """
|
||||
Validate an user, get its actor and a token
|
||||
"""
|
||||
@spec validate_user(map(), %{token: String.t()}, map()) :: {:ok, map()}
|
||||
def validate_user(_parent, %{token: token}, _resolution) do
|
||||
with {:check_confirmation_token, {:ok, %User{} = user}} <-
|
||||
{:check_confirmation_token, Email.User.check_confirmation_token(token)},
|
||||
{:get_actor, actor} <- {:get_actor, Users.get_actor_for_user(user)},
|
||||
{:ok, %{access_token: access_token, refresh_token: refresh_token}} <-
|
||||
Authenticator.generate_tokens(user) do
|
||||
{:get_actor, actor} <- {:get_actor, Users.get_actor_for_user(user)} do
|
||||
{:ok, %{access_token: access_token, refresh_token: refresh_token}} =
|
||||
Authenticator.generate_tokens(user)
|
||||
|
||||
{:ok,
|
||||
%{
|
||||
access_token: access_token,
|
||||
@@ -267,12 +269,16 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
||||
@doc """
|
||||
Reset the password from an user
|
||||
"""
|
||||
@spec reset_password(map(), %{password: String.t(), token: String.t()}, map()) ::
|
||||
{:ok, map()} | {:error, String.t()}
|
||||
def reset_password(_parent, %{password: password, token: token}, _resolution) do
|
||||
with {:ok, %User{email: email} = user} <-
|
||||
Email.User.check_reset_password_token(password, token),
|
||||
{:ok, %{access_token: access_token, refresh_token: refresh_token}} <-
|
||||
Authenticator.authenticate(email, password) do
|
||||
{:ok, %{access_token: access_token, refresh_token: refresh_token, user: user}}
|
||||
case Email.User.check_reset_password_token(password, token) do
|
||||
{:ok, %User{email: email} = user} ->
|
||||
{:ok, tokens} = Authenticator.authenticate(email, password)
|
||||
{:ok, Map.put(tokens, :user, user)}
|
||||
|
||||
{:error, error} ->
|
||||
{:error, error}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -369,6 +375,9 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
||||
|> Repo.update() do
|
||||
{:ok, user}
|
||||
else
|
||||
{:can_change_password, false} ->
|
||||
{:error, dgettext("errors", "You cannot change your password.")}
|
||||
|
||||
{:current_password, _} ->
|
||||
{:error, dgettext("errors", "The current password is invalid")}
|
||||
|
||||
@@ -408,14 +417,18 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
||||
|
||||
{:ok, user}
|
||||
else
|
||||
{:current_password, _} ->
|
||||
{:current_password, {:error, _}} ->
|
||||
{:error, dgettext("errors", "The password provided is invalid")}
|
||||
|
||||
{:same_email, true} ->
|
||||
{:error, dgettext("errors", "The new email must be different")}
|
||||
|
||||
{:email_valid, _} ->
|
||||
{:email_valid, false} ->
|
||||
{:error, dgettext("errors", "The new email doesn't seem to be valid")}
|
||||
|
||||
{:error, %Ecto.Changeset{} = err} ->
|
||||
Logger.debug(inspect(err))
|
||||
{:error, dgettext("errors", "Failed to update user email")}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -423,12 +436,21 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
||||
{:error, dgettext("errors", "You need to be logged-in to change your email")}
|
||||
end
|
||||
|
||||
@spec validate_email(map(), %{token: String.t()}, map()) ::
|
||||
{:ok, User.t()} | {:error, String.t()}
|
||||
def validate_email(_parent, %{token: token}, _resolution) do
|
||||
with {:get, %User{} = user} <- {:get, Users.get_user_by_activation_token(token)},
|
||||
{:ok, %User{} = user} <- Users.validate_email(user) do
|
||||
{:ok, user}
|
||||
else
|
||||
{:get, nil} ->
|
||||
case Users.get_user_by_activation_token(token) do
|
||||
%User{} = user ->
|
||||
case Users.validate_email(user) do
|
||||
{:ok, %User{} = user} ->
|
||||
{:ok, user}
|
||||
|
||||
{:error, %Ecto.Changeset{} = err} ->
|
||||
Logger.debug(inspect(err))
|
||||
{:error, dgettext("errors", "Failed to validate user email")}
|
||||
end
|
||||
|
||||
nil ->
|
||||
{:error, dgettext("errors", "Invalid activation token")}
|
||||
end
|
||||
end
|
||||
@@ -547,12 +569,17 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
||||
def update_locale(_parent, %{locale: locale}, %{
|
||||
context: %{current_user: %User{locale: current_locale} = user}
|
||||
}) do
|
||||
with true <- current_locale != locale,
|
||||
{:ok, %User{} = updated_user} <- Users.update_user(user, %{locale: locale}) do
|
||||
{:ok, updated_user}
|
||||
if current_locale != locale do
|
||||
case Users.update_user(user, %{locale: locale}) do
|
||||
{:ok, %User{} = updated_user} ->
|
||||
{:ok, updated_user}
|
||||
|
||||
{:error, %Ecto.Changeset{} = err} ->
|
||||
Logger.debug(err)
|
||||
{:error, dgettext("errors", "Error while updating locale")}
|
||||
end
|
||||
else
|
||||
false ->
|
||||
{:ok, user}
|
||||
{:ok, user}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ defmodule Mobilizon.GraphQL.Schema.TagType do
|
||||
object :tag_queries do
|
||||
@desc "Get the list of tags"
|
||||
field :tags, non_null(list_of(:tag)) do
|
||||
arg(:filter, :string, description: "The filter to apply to the search")
|
||||
arg(:page, :integer, default_value: 1, description: "The page in the paginated tags list")
|
||||
arg(:limit, :integer, default_value: 10, description: "The limit of tags per page")
|
||||
resolve(&Tag.list_tags/3)
|
||||
|
||||
Reference in New Issue
Block a user