2020-08-20 10:54:58 +02:00
|
|
|
defmodule Mobilizon.Federation.ActivityPub.Types.Members do
|
|
|
|
@moduledoc false
|
|
|
|
alias Mobilizon.Actors
|
2021-09-10 11:27:59 +02:00
|
|
|
alias Mobilizon.Actors.{Actor, Member, MemberRole}
|
2021-09-28 19:40:37 +02:00
|
|
|
alias Mobilizon.Federation.ActivityPub.Actions
|
|
|
|
alias Mobilizon.Federation.ActivityStream
|
2020-08-20 10:54:58 +02:00
|
|
|
alias Mobilizon.Federation.ActivityStream.Convertible
|
2021-02-24 19:06:48 +01:00
|
|
|
alias Mobilizon.Service.Activity.Member, as: MemberActivity
|
2021-03-05 11:23:17 +01:00
|
|
|
alias Mobilizon.Web.Endpoint
|
2020-08-20 10:54:58 +02:00
|
|
|
require Logger
|
|
|
|
import Mobilizon.Federation.ActivityPub.Utils, only: [make_update_data: 2]
|
|
|
|
|
2021-09-24 16:46:42 +02:00
|
|
|
@spec update(Member.t(), map, map) ::
|
|
|
|
{:ok, Member.t(), ActivityStream.t()}
|
|
|
|
| {:error, :member_not_found | :only_admin_left | Ecto.Changeset.t()}
|
2020-08-20 10:54:58 +02:00
|
|
|
def update(
|
2021-03-05 11:23:17 +01:00
|
|
|
%Member{
|
|
|
|
parent: %Actor{id: group_id} = group,
|
|
|
|
id: member_id,
|
|
|
|
role: current_role,
|
|
|
|
actor: %Actor{id: actor_id} = actor
|
|
|
|
} = old_member,
|
2020-08-20 10:54:58 +02:00
|
|
|
%{role: updated_role} = args,
|
2021-02-24 19:06:48 +01:00
|
|
|
%{moderator: %Actor{url: moderator_url, id: moderator_id} = moderator} = additional
|
2020-08-20 10:54:58 +02:00
|
|
|
) do
|
2021-09-24 16:46:42 +02:00
|
|
|
additional = Map.delete(additional, :moderator)
|
|
|
|
|
|
|
|
case Actors.get_member(moderator_id, group_id) do
|
|
|
|
{:error, :member_not_found} ->
|
|
|
|
{:error, :member_not_found}
|
|
|
|
|
|
|
|
{:ok, %Member{role: moderator_role}}
|
|
|
|
when moderator_role in [:moderator, :administrator, :creator] ->
|
|
|
|
if check_admins_left?(member_id, group_id, current_role, updated_role) do
|
|
|
|
{:error, :only_admin_left}
|
|
|
|
else
|
|
|
|
case Actors.update_member(old_member, args) do
|
|
|
|
{:error, %Ecto.Changeset{} = err} ->
|
|
|
|
{:error, err}
|
|
|
|
|
|
|
|
{:ok, %Member{} = member} ->
|
|
|
|
MemberActivity.insert_activity(member,
|
|
|
|
old_member: old_member,
|
|
|
|
moderator: moderator,
|
|
|
|
subject: "member_updated"
|
|
|
|
)
|
|
|
|
|
|
|
|
Absinthe.Subscription.publish(Endpoint, actor,
|
|
|
|
group_membership_changed: [Actor.preferred_username_and_domain(group), actor_id]
|
|
|
|
)
|
|
|
|
|
|
|
|
Cachex.del(:activity_pub, "member_#{member_id}")
|
|
|
|
member_as_data = Convertible.model_to_as(member)
|
|
|
|
|
|
|
|
audience = %{
|
|
|
|
"to" => [member.parent.members_url, member.actor.url],
|
|
|
|
"cc" => [member.parent.url],
|
|
|
|
"actor" => moderator_url,
|
|
|
|
"attributedTo" => [member.parent.url]
|
|
|
|
}
|
|
|
|
|
|
|
|
update_data = make_update_data(member_as_data, Map.merge(audience, additional))
|
|
|
|
{:ok, member, update_data}
|
|
|
|
end
|
|
|
|
end
|
2020-08-20 10:54:58 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-08-27 11:53:24 +02:00
|
|
|
# Used only when a group is suspended
|
2021-09-10 11:27:59 +02:00
|
|
|
@spec delete(Member.t(), Actor.t(), boolean(), map()) :: {:ok, Activity.t(), Member.t()}
|
2020-08-27 11:53:24 +02:00
|
|
|
def delete(
|
|
|
|
%Member{parent: %Actor{} = group, actor: %Actor{} = actor} = _member,
|
|
|
|
%Actor{},
|
|
|
|
local,
|
|
|
|
_additionnal
|
|
|
|
) do
|
|
|
|
Logger.debug("Deleting a member")
|
2021-09-28 19:40:37 +02:00
|
|
|
Actions.Leave.leave(group, actor, local, %{force_member_removal: true})
|
2020-08-27 11:53:24 +02:00
|
|
|
end
|
2020-08-20 10:54:58 +02:00
|
|
|
|
2021-09-10 11:27:59 +02:00
|
|
|
@spec actor(Member.t()) :: Actor.t() | nil
|
2020-08-20 10:54:58 +02:00
|
|
|
def actor(%Member{actor_id: actor_id}),
|
|
|
|
do: Actors.get_actor(actor_id)
|
|
|
|
|
2021-09-10 11:27:59 +02:00
|
|
|
@spec group_actor(Member.t()) :: Actor.t() | nil
|
2020-08-20 10:54:58 +02:00
|
|
|
def group_actor(%Member{parent_id: parent_id}),
|
|
|
|
do: Actors.get_actor(parent_id)
|
|
|
|
|
2021-09-10 11:27:59 +02:00
|
|
|
@spec check_admins_left?(
|
|
|
|
String.t() | integer,
|
|
|
|
String.t() | integer,
|
|
|
|
MemberRole.t(),
|
|
|
|
MemberRole.t()
|
|
|
|
) :: boolean
|
|
|
|
defp check_admins_left?(member_id, group_id, current_role, updated_role) do
|
2020-08-20 10:54:58 +02:00
|
|
|
Actors.is_only_administrator?(member_id, group_id) && current_role == :administrator &&
|
|
|
|
updated_role != :administrator
|
|
|
|
end
|
|
|
|
end
|