mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15be697b7c | ||
|
|
ff58b8d402 | ||
|
|
967db09d10 | ||
|
|
73e9668a9c | ||
|
|
3261777fcd | ||
|
|
ab8617f8a9 |
@@ -1,3 +1,5 @@
|
||||
- Added ability to transfer project between organizations [#4935](https://github.com/appwrite/appwrite/pull/4935)
|
||||
|
||||
# Version 1.2.0
|
||||
## Features
|
||||
- Added GraphQL API [#974](https://github.com/appwrite/appwrite/pull/974)
|
||||
|
||||
@@ -197,6 +197,11 @@ return [
|
||||
'description' => 'Team with the requested ID could not be found.',
|
||||
'code' => 404,
|
||||
],
|
||||
Exception::PROJECT_TEAM_ALREADY_MATCHES => [
|
||||
'name' => Exception::PROJECT_TEAM_ALREADY_MATCHES,
|
||||
'description' => 'Project already owned by this team.',
|
||||
'code' => 400,
|
||||
],
|
||||
Exception::TEAM_INVITE_ALREADY_EXISTS => [
|
||||
'name' => Exception::TEAM_INVITE_ALREADY_EXISTS,
|
||||
'description' => 'User has already been invited or is already a member of this team',
|
||||
|
||||
@@ -84,7 +84,7 @@ return [
|
||||
],
|
||||
Auth::USER_ROLE_OWNER => [
|
||||
'label' => 'Owner',
|
||||
'scopes' => \array_merge($member, $admins, []),
|
||||
'scopes' => \array_merge($member, $admins, [ 'projects.transfer' ]),
|
||||
],
|
||||
Auth::USER_ROLE_APPS => [
|
||||
'label' => 'Applications',
|
||||
|
||||
@@ -108,6 +108,19 @@ return [
|
||||
'optional' => false,
|
||||
'icon' => '',
|
||||
],
|
||||
'project' => [
|
||||
'key' => 'project',
|
||||
'name' => 'Project',
|
||||
'subtitle' => 'The Project service allows you to manage all the projects in your Appwrite server.',
|
||||
'description' => '',
|
||||
'controller' => 'api/project.php',
|
||||
'sdk' => true,
|
||||
'docs' => true,
|
||||
'docsUrl' => '',
|
||||
'tests' => false,
|
||||
'optional' => false,
|
||||
'icon' => '',
|
||||
],
|
||||
'storage' => [
|
||||
'key' => 'storage',
|
||||
'name' => 'Storage',
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
use Appwrite\Event\Delete;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\App;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\UID;
|
||||
|
||||
App::patch('/v1/project/:projectId/team')
|
||||
->desc('Update Project Team')
|
||||
->groups(['api', 'project'])
|
||||
->label('scope', 'projects.transfer')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'project')
|
||||
->label('sdk.method', 'updateTeam')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_PROJECT)
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('teamId', '', new UID(), 'New Team ID.')
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
->inject('dbForConsole')
|
||||
->inject('deletes')
|
||||
->action(function (string $projectId, string $teamId, Response $response, Document $user, Database $dbForConsole, Delete $deletes) {
|
||||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$team = $dbForConsole->getDocument('teams', $teamId);
|
||||
|
||||
if ($team->isEmpty()) {
|
||||
throw new Exception(Exception::TEAM_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($team->getInternalId() === $project->getAttribute('teamInternalId')) {
|
||||
throw new Exception(Exception::PROJECT_TEAM_ALREADY_MATCHES);
|
||||
}
|
||||
|
||||
$project
|
||||
->setAttribute('teamId', $team->getId())
|
||||
->setAttribute('teamInternalId', $team->getInternalId())
|
||||
;
|
||||
|
||||
$project = $dbForConsole->updateDocument('projects', $project->getId(), $project);
|
||||
|
||||
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||
});
|
||||
@@ -76,6 +76,7 @@ class Exception extends \Exception
|
||||
|
||||
/** Teams */
|
||||
public const TEAM_NOT_FOUND = 'team_not_found';
|
||||
public const PROJECT_TEAM_ALREADY_MATCHES = 'project_team_already_matches';
|
||||
public const TEAM_INVITE_ALREADY_EXISTS = 'team_invite_already_exists';
|
||||
public const TEAM_INVITE_NOT_FOUND = 'team_invite_not_found';
|
||||
public const TEAM_INVALID_SECRET = 'team_invalid_secret';
|
||||
|
||||
@@ -2721,4 +2721,183 @@ class ProjectsConsoleClientTest extends Scope
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function testUpdateProjectTeam(): void
|
||||
{
|
||||
// Create two teams
|
||||
$team1 = $this->client->call(Client::METHOD_POST, '/teams', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'teamId' => ID::unique(),
|
||||
'name' => 'Team 1'
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $team1['headers']['status-code']);
|
||||
|
||||
$team1Id = $team1['body']['$id'];
|
||||
|
||||
$team2 = $this->client->call(Client::METHOD_POST, '/teams', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'teamId' => ID::unique(),
|
||||
'name' => 'Team 2'
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $team1['headers']['status-code']);
|
||||
|
||||
$team2Id = $team2['body']['$id'];
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, "/teams/{$team1Id}/memberships", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), []);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(1, $response['body']['total']);
|
||||
|
||||
$membership1Id = $response['body']['memberships'][0]['$id'];
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, "/teams/{$team2Id}/memberships", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), []);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(1, $response['body']['total']);
|
||||
|
||||
$membership2Id = $response['body']['memberships'][0]['$id'];
|
||||
|
||||
// Create project in team 1
|
||||
$project = $this->client->call(Client::METHOD_POST, '/projects', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'projectId' => ID::unique(),
|
||||
'name' => 'Transfer Project',
|
||||
'teamId' => $team1Id,
|
||||
'region' => 'default'
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $project['headers']['status-code']);
|
||||
$this->assertEquals($team1Id, $project['body']['teamId']);
|
||||
|
||||
$projectId = $project['body']['$id'];
|
||||
|
||||
// Test list projects
|
||||
$response = $this->client->call(Client::METHOD_GET, '/projects', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("teamId", "' . $team1Id . '")' ],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(1, $response['body']['total']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/projects', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("teamId", "' . $team2Id . '")' ],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(0, $response['body']['total']);
|
||||
|
||||
// Transfer project
|
||||
$project = $this->client->call(Client::METHOD_PATCH, "/project/{$projectId}/team", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $projectId,
|
||||
'x-appwrite-mode' => 'admin'
|
||||
], $this->getHeaders()), [
|
||||
'teamId' => $team2Id
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $project['headers']['status-code']);
|
||||
$this->assertEquals($team2Id, $project['body']['teamId']);
|
||||
|
||||
$project = $this->client->call(Client::METHOD_GET, "/projects/{$projectId}", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), []);
|
||||
|
||||
$this->assertEquals(200, $project['headers']['status-code']);
|
||||
$this->assertEquals($team2Id, $project['body']['teamId']);
|
||||
|
||||
// Test list projects again
|
||||
$response = $this->client->call(Client::METHOD_GET, '/projects', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("teamId", "' . $team2Id . '")' ],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(1, $response['body']['total']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/projects', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("teamId", "' . $team1Id . '")' ],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(0, $response['body']['total']);
|
||||
|
||||
// Test failures
|
||||
$project = $this->client->call(Client::METHOD_PATCH, "/project/nonExistingProjectId/team", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $projectId,
|
||||
'x-appwrite-mode' => 'admin'
|
||||
], $this->getHeaders()), [
|
||||
'teamId' => $team1Id
|
||||
]);
|
||||
|
||||
$this->assertEquals(404, $project['headers']['status-code']);
|
||||
|
||||
$project = $this->client->call(Client::METHOD_PATCH, "/project/{$projectId}/team", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $projectId,
|
||||
'x-appwrite-mode' => 'admin'
|
||||
], $this->getHeaders()), [
|
||||
'teamId' => 'nonExistingTeamId'
|
||||
]);
|
||||
|
||||
$this->assertEquals(404, $project['headers']['status-code']);
|
||||
|
||||
$project = $this->client->call(Client::METHOD_PATCH, "/project/{$projectId}/team", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $projectId,
|
||||
'x-appwrite-mode' => 'admin'
|
||||
], $this->getHeaders()), [
|
||||
'teamId' => $team2Id
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $project['headers']['status-code']);
|
||||
|
||||
$project = $this->client->call(Client::METHOD_PATCH, "/teams/{$team2Id}/memberships/{$membership2Id}", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'roles' => ['member']
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $project['headers']['status-code']);
|
||||
$this->assertCount(1, $project['body']['roles']);
|
||||
$this->assertContains('member', $project['body']['roles']);
|
||||
$this->assertNotContains('owner', $project['body']['roles']);
|
||||
|
||||
$project = $this->client->call(Client::METHOD_PATCH, "/project/{$projectId}/team", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $projectId,
|
||||
'x-appwrite-mode' => 'admin'
|
||||
], $this->getHeaders()), [
|
||||
'teamId' => $team1Id
|
||||
]);
|
||||
|
||||
$this->assertEquals(401, $project['headers']['status-code']);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user