mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
feedback 2
This commit is contained in:
@@ -22,12 +22,6 @@ class Delete extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
protected string $teamId;
|
||||
protected string $membershipId;
|
||||
protected Document $user;
|
||||
protected Document $project;
|
||||
protected Database $dbForProject;
|
||||
|
||||
public static function getName()
|
||||
{
|
||||
return 'deleteTeamMembership';
|
||||
@@ -71,17 +65,54 @@ class Delete extends Action
|
||||
|
||||
public function action(string $teamId, string $membershipId, Document $user, Document $project, Response $response, Database $dbForProject, Authorization $authorization, Event $queueForEvents)
|
||||
{
|
||||
$this->teamId = $teamId;
|
||||
$this->membershipId = $membershipId;
|
||||
$this->user = $user;
|
||||
$this->project = $project;
|
||||
$this->dbForProject = $dbForProject;
|
||||
$membership = $dbForProject->getDocument('memberships', $membershipId);
|
||||
if ($membership->isEmpty()) {
|
||||
throw new Exception(Exception::TEAM_INVITE_NOT_FOUND);
|
||||
}
|
||||
|
||||
[
|
||||
'membership' => $membership,
|
||||
'profile' => $profile,
|
||||
'team' => $team,
|
||||
] = $this->loadAndValidateResources();
|
||||
$profile = $dbForProject->getDocument('users', $membership->getAttribute('userId'));
|
||||
if ($profile->isEmpty()) {
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
if ($team->isEmpty()) {
|
||||
throw new Exception(Exception::TEAM_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($membership->getAttribute('teamInternalId') !== $team->getSequence()) {
|
||||
throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH);
|
||||
}
|
||||
|
||||
if ($project->getId() === 'console') {
|
||||
// Quick check:
|
||||
// fetch up to 2 owners to determine if only one exists
|
||||
$ownersCount = $dbForProject->count(
|
||||
collection: 'memberships',
|
||||
queries: [
|
||||
Query::contains('roles', ['owner']),
|
||||
Query::equal('teamInternalId', [$team->getSequence()])
|
||||
],
|
||||
max: 2
|
||||
);
|
||||
|
||||
// Is the deletion being requested by the user on their own membership and they are also the owner?
|
||||
$isSelfOwner =
|
||||
in_array('owner', $membership->getAttribute('roles')) &&
|
||||
$membership->getAttribute('userInternalId') === $user->getSequence();
|
||||
|
||||
if ($ownersCount === 1 && $isSelfOwner) {
|
||||
/**
|
||||
* Prevent removal if the user is the only owner, this is because -
|
||||
*
|
||||
* 1. Other roles [if exists] can neither add a new owner nor delete the organization.
|
||||
* 2. If the only owner is removed, while there were no other members, the organization isn't marked for deletion and stays in a limbo.
|
||||
*/
|
||||
throw new Exception(Exception::MEMBERSHIP_DELETION_PROHIBITED, 'There must be at least one owner in the organization.');
|
||||
}
|
||||
}
|
||||
|
||||
$this->validate($profile, $team, $dbForProject);
|
||||
|
||||
try {
|
||||
$dbForProject->deleteDocument('memberships', $membership->getId());
|
||||
@@ -117,59 +148,8 @@ class Delete extends Action
|
||||
$response->noContent();
|
||||
}
|
||||
|
||||
protected function loadAndValidateResources(): array
|
||||
protected function validate(Document $profile, Document $team, Database $dbForProject): void
|
||||
{
|
||||
$membership = $this->dbForProject->getDocument('memberships', $this->membershipId);
|
||||
if ($membership->isEmpty()) {
|
||||
throw new Exception(Exception::TEAM_INVITE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$profile = $this->dbForProject->getDocument('users', $membership->getAttribute('userId'));
|
||||
if ($profile->isEmpty()) {
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$team = $this->dbForProject->getDocument('teams', $this->teamId);
|
||||
if ($team->isEmpty()) {
|
||||
throw new Exception(Exception::TEAM_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($membership->getAttribute('teamInternalId') !== $team->getSequence()) {
|
||||
throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH);
|
||||
}
|
||||
|
||||
if ($this->project->getId() === 'console') {
|
||||
// Quick check:
|
||||
// fetch up to 2 owners to determine if only one exists
|
||||
$ownersCount = $this->dbForProject->count(
|
||||
collection: 'memberships',
|
||||
queries: [
|
||||
Query::contains('roles', ['owner']),
|
||||
Query::equal('teamInternalId', [$team->getSequence()])
|
||||
],
|
||||
max: 2
|
||||
);
|
||||
|
||||
// Is the deletion being requested by the user on their own membership and they are also the owner?
|
||||
$isSelfOwner =
|
||||
in_array('owner', $membership->getAttribute('roles')) &&
|
||||
$membership->getAttribute('userInternalId') === $this->user->getSequence();
|
||||
|
||||
if ($ownersCount === 1 && $isSelfOwner) {
|
||||
/**
|
||||
* Prevent removal if the user is the only owner, this is because -
|
||||
*
|
||||
* 1. Other roles [if exists] can neither add a new owner nor delete the organization.
|
||||
* 2. If the only owner is removed, while there were no other members, the organization isn't marked for deletion and stays in a limbo.
|
||||
*/
|
||||
throw new Exception(Exception::MEMBERSHIP_DELETION_PROHIBITED, 'There must be at least one owner in the organization.');
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'membership' => $membership,
|
||||
'profile' => $profile,
|
||||
'team' => $team,
|
||||
];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user