Add ability to delete a group
This commit is contained in:
parent
c0628a1566
commit
8388240957
|
@ -242,6 +242,13 @@ defmodule Mobilizon.Actors do
|
|||
|> Repo.insert()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Delete a group
|
||||
"""
|
||||
def delete_group!(%Actor{type: :Group} = group) do
|
||||
Repo.delete!(group)
|
||||
end
|
||||
|
||||
alias Mobilizon.Actors.User
|
||||
|
||||
@doc """
|
||||
|
@ -551,6 +558,16 @@ defmodule Mobilizon.Actors do
|
|||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Find a group by its actor id
|
||||
"""
|
||||
def find_group_by_actor_id(actor_id) do
|
||||
case Repo.get_by(Actor, id: actor_id, type: :Group) do
|
||||
nil -> {:error, :group_not_found}
|
||||
actor -> {:ok, actor}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Authenticate user
|
||||
"""
|
||||
|
|
|
@ -6,6 +6,7 @@ defmodule Mobilizon.Actors.Member do
|
|||
import Ecto.Changeset
|
||||
alias Mobilizon.Actors.Member
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Repo
|
||||
|
||||
schema "members" do
|
||||
field(:approved, :boolean, default: true)
|
||||
|
@ -24,4 +25,22 @@ defmodule Mobilizon.Actors.Member do
|
|||
|> validate_required([:parent_id, :actor_id])
|
||||
|> unique_constraint(:parent_id, name: :members_actor_parent_unique_index)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single member of an actor (for example a group)
|
||||
"""
|
||||
def get_member(actor_id, parent_id) do
|
||||
case Repo.get_by(Member, actor_id: actor_id, parent_id: parent_id) do
|
||||
nil -> {:error, :member_not_found}
|
||||
member -> {:ok, member}
|
||||
end
|
||||
end
|
||||
|
||||
def is_administrator(%Member{role: 2} = member) do
|
||||
{:is_admin, true}
|
||||
end
|
||||
|
||||
def is_administrator(%Member{}) do
|
||||
{:is_admin, false}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -144,4 +144,16 @@ defmodule Mobilizon.Actors.User do
|
|||
def is_confirmed(%User{} = user) do
|
||||
{:ok, user}
|
||||
end
|
||||
|
||||
def owns_actor(%User{default_actor_id: default_actor_id} = user, %Actor{id: actor_id})
|
||||
when default_actor_id == actor_id do
|
||||
{:is_owned, true}
|
||||
end
|
||||
|
||||
def owns_actor(%User{actors: actors} = user, actor_id) do
|
||||
case Enum.any?(actors, fn a -> a.id == actor_id end) do
|
||||
true -> {:is_owned, true}
|
||||
_ -> {:is_owned, false}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ defmodule MobilizonWeb.Resolvers.Group do
|
|||
Handles the group-related GraphQL calls
|
||||
"""
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Actors.{Actor}
|
||||
alias Mobilizon.Actors.{Actor, User, Member}
|
||||
alias Mobilizon.Service.ActivityPub
|
||||
alias Mobilizon.Activity
|
||||
require Logger
|
||||
|
@ -68,4 +68,41 @@ defmodule MobilizonWeb.Resolvers.Group do
|
|||
def create_group(_parent, _args, _resolution) do
|
||||
{:error, "You need to be logged-in to create a group"}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Delete an existing group
|
||||
"""
|
||||
def delete_group(
|
||||
_parent,
|
||||
%{group_id: group_id, actor_id: actor_id},
|
||||
%{
|
||||
context: %{
|
||||
current_user: user
|
||||
}
|
||||
}
|
||||
) do
|
||||
with {:ok, %Actor{} = group} <- Actors.find_group_by_actor_id(group_id),
|
||||
{:is_owned, true} <- User.owns_actor(user, actor_id),
|
||||
{:ok, %Member{} = member} <- Member.get_member(actor_id, group.id),
|
||||
{:is_admin, true} <- Member.is_administrator(member),
|
||||
group <- Actors.delete_group!(group) do
|
||||
{:ok, %{id: group.id}}
|
||||
else
|
||||
{:error, :group_not_found} ->
|
||||
{:error, "Group with preferred username not found"}
|
||||
|
||||
{:is_owned, false} ->
|
||||
{:error, "Actor id is not owned by authenticated user"}
|
||||
|
||||
{:error, :member_not_found} ->
|
||||
{:error, "Actor id is not a member of this group"}
|
||||
|
||||
{:is_admin, false} ->
|
||||
{:error, "User is not an administrator of the selected group"}
|
||||
end
|
||||
end
|
||||
|
||||
def delete_group(_parent, _args, _resolution) do
|
||||
{:error, "You need to be logged-in to delete a group"}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,6 +20,11 @@ defmodule MobilizonWeb.Schema do
|
|||
|
||||
alias MobilizonWeb.Resolvers
|
||||
|
||||
@desc "A struct containing the id of the deleted object"
|
||||
object :deleted_object do
|
||||
field(:id, :integer)
|
||||
end
|
||||
|
||||
@desc "A JWT and the associated user ID"
|
||||
object :login do
|
||||
field(:token, non_null(:string), description: "A JWT Token for this session")
|
||||
|
@ -301,6 +306,14 @@ defmodule MobilizonWeb.Schema do
|
|||
resolve(&Resolvers.Group.create_group/3)
|
||||
end
|
||||
|
||||
@desc "Delete a group"
|
||||
field :delete_group, :deleted_object do
|
||||
arg(:group_id, non_null(:integer))
|
||||
arg(:actor_id, non_null(:integer))
|
||||
|
||||
resolve(&Resolvers.Group.delete_group/3)
|
||||
end
|
||||
|
||||
# @desc "Upload a picture"
|
||||
# field :upload_picture, :picture do
|
||||
# arg(:file, non_null(:upload))
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
defmodule Mobilizon.Repo.Migrations.GroupDeleteMembersCascade do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
drop constraint(:members, "members_account_id_fkey")
|
||||
drop constraint(:members, "members_parent_id_fkey")
|
||||
|
||||
alter table(:members) do
|
||||
modify :actor_id, references(:actors, on_delete: :delete_all)
|
||||
modify :parent_id, references(:actors, on_delete: :delete_all)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -114,5 +114,36 @@ defmodule MobilizonWeb.Resolvers.GroupResolverTest do
|
|||
assert hd(json_response(res, 200)["errors"])["message"] ==
|
||||
"Group with name #{@non_existent_username} not found"
|
||||
end
|
||||
|
||||
test "delete_group/3 deletes a group", %{conn: conn, user: user, actor: actor} do
|
||||
group = insert(:group)
|
||||
insert(:member, parent: group, actor: actor, role: 2)
|
||||
|
||||
mutation = """
|
||||
mutation {
|
||||
deleteGroup(
|
||||
actor_id: #{actor.id},
|
||||
group_id: #{group.id}
|
||||
) {
|
||||
id
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> post("/api", AbsintheHelpers.mutation_skeleton(mutation))
|
||||
|
||||
assert json_response(res, 200)["errors"] == nil
|
||||
assert json_response(res, 200)["data"]["deleteGroup"]["id"] == group.id
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> post("/api", AbsintheHelpers.mutation_skeleton(mutation))
|
||||
|
||||
assert hd(json_response(res, 200)["errors"])["message"] =~ "not found"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -148,7 +148,8 @@ defmodule Mobilizon.Factory do
|
|||
def member_factory do
|
||||
%Mobilizon.Actors.Member{
|
||||
parent: build(:actor),
|
||||
actor: build(:actor)
|
||||
actor: build(:actor),
|
||||
role: 0
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue