Merge pull request #2786 from appwrite/feat-update-realtime-events
storage realtime event refactor
This commit is contained in:
commit
f045adb654
4 changed files with 25 additions and 30 deletions
|
@ -358,15 +358,17 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
||||||
->inject('user')
|
->inject('user')
|
||||||
->inject('audits')
|
->inject('audits')
|
||||||
->inject('usage')
|
->inject('usage')
|
||||||
|
->inject('events')
|
||||||
->inject('mode')
|
->inject('mode')
|
||||||
->inject('deviceFiles')
|
->inject('deviceFiles')
|
||||||
->inject('deviceLocal')
|
->inject('deviceLocal')
|
||||||
->action(function ($bucketId, $fileId, $file, $read, $write, $request, $response, $dbForProject, $user, $audits, $usage, $mode, $deviceFiles, $deviceLocal) {
|
->action(function ($bucketId, $fileId, $file, $read, $write, $request, $response, $dbForProject, $user, $audits, $usage, $events, $mode, $deviceFiles, $deviceLocal) {
|
||||||
/** @var Utopia\Swoole\Request $request */
|
/** @var Utopia\Swoole\Request $request */
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Utopia\Database\Database $dbForProject */
|
/** @var Utopia\Database\Database $dbForProject */
|
||||||
/** @var Utopia\Database\Document $user */
|
/** @var Utopia\Database\Document $user */
|
||||||
/** @var Appwrite\Event\Event $audits */
|
/** @var Appwrite\Event\Event $audits */
|
||||||
|
/** @var Appwrite\Event\Event $events */
|
||||||
/** @var Appwrite\Stats\Stats $usage */
|
/** @var Appwrite\Stats\Stats $usage */
|
||||||
/** @var Utopia\Storage\Device $deviceFiles */
|
/** @var Utopia\Storage\Device $deviceFiles */
|
||||||
/** @var Utopia\Storage\Device $deviceLocal */
|
/** @var Utopia\Storage\Device $deviceLocal */
|
||||||
|
@ -673,6 +675,8 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$events->setParam('bucket', $bucket->getArrayCopy());
|
||||||
|
|
||||||
$metadata = null; // was causing leaks as it was passed by reference
|
$metadata = null; // was causing leaks as it was passed by reference
|
||||||
|
|
||||||
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||||
|
@ -1339,12 +1343,14 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
|
||||||
->inject('audits')
|
->inject('audits')
|
||||||
->inject('usage')
|
->inject('usage')
|
||||||
->inject('mode')
|
->inject('mode')
|
||||||
->action(function ($bucketId, $fileId, $read, $write, $response, $dbForProject, $user, $audits, $usage, $mode) {
|
->inject('events')
|
||||||
|
->action(function ($bucketId, $fileId, $read, $write, $response, $dbForProject, $user, $audits, $usage, $mode, $events) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Utopia\Database\Database $dbForProject */
|
/** @var Utopia\Database\Database $dbForProject */
|
||||||
/** @var Utopia\Database\Document $user */
|
/** @var Utopia\Database\Document $user */
|
||||||
/** @var Appwrite\Event\Event $audits */
|
/** @var Appwrite\Event\Event $audits */
|
||||||
/** @var Appwrite\Stats\Stats $usage */
|
/** @var Appwrite\Stats\Stats $usage */
|
||||||
|
/** @var Appwirte\Event\Event $events */
|
||||||
/** @var string $mode */
|
/** @var string $mode */
|
||||||
|
|
||||||
$bucket = $dbForProject->getDocument('buckets', $bucketId);
|
$bucket = $dbForProject->getDocument('buckets', $bucketId);
|
||||||
|
@ -1406,6 +1412,8 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$events->setParam('bucket', $bucket->getArrayCopy());
|
||||||
|
|
||||||
$audits
|
$audits
|
||||||
->setParam('event', 'storage.files.update')
|
->setParam('event', 'storage.files.update')
|
||||||
->setParam('resource', 'file/' . $file->getId())
|
->setParam('resource', 'file/' . $file->getId())
|
||||||
|
@ -1521,6 +1529,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
|
||||||
|
|
||||||
$events
|
$events
|
||||||
->setParam('eventData', $response->output($file, Response::MODEL_FILE))
|
->setParam('eventData', $response->output($file, Response::MODEL_FILE))
|
||||||
|
->setParam('bucket', $bucket->getArrayCopy())
|
||||||
;
|
;
|
||||||
|
|
||||||
$response->noContent();
|
$response->noContent();
|
||||||
|
|
|
@ -217,12 +217,14 @@ App::shutdown(function ($utopia, $request, $response, $project, $events, $audits
|
||||||
if ($project->getId() !== 'console') {
|
if ($project->getId() !== 'console') {
|
||||||
$payload = new Document($response->getPayload());
|
$payload = new Document($response->getPayload());
|
||||||
$collection = new Document($events->getParam('collection') ?? []);
|
$collection = new Document($events->getParam('collection') ?? []);
|
||||||
|
$bucket = new Document($events->getParam('bucket') ?? []);
|
||||||
|
|
||||||
$target = Realtime::fromPayload(
|
$target = Realtime::fromPayload(
|
||||||
event: $events->getParam('event'),
|
event: $events->getParam('event'),
|
||||||
payload: $payload,
|
payload: $payload,
|
||||||
project: $project,
|
project: $project,
|
||||||
collection: $collection
|
collection: $collection,
|
||||||
|
bucket: $bucket,
|
||||||
);
|
);
|
||||||
|
|
||||||
Realtime::send(
|
Realtime::send(
|
||||||
|
|
|
@ -240,7 +240,7 @@ class Realtime extends Adapter
|
||||||
* @param Document|null $project
|
* @param Document|null $project
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function fromPayload(string $event, Document $payload, Document $project = null, Document $collection = null): array
|
public static function fromPayload(string $event, Document $payload, Document $project = null, Document $collection = null, Document $bucket = null): array
|
||||||
{
|
{
|
||||||
$channels = [];
|
$channels = [];
|
||||||
$roles = [];
|
$roles = [];
|
||||||
|
@ -285,7 +285,7 @@ class Realtime extends Adapter
|
||||||
break;
|
break;
|
||||||
case strpos($event, 'database.documents.') === 0:
|
case strpos($event, 'database.documents.') === 0:
|
||||||
if ($collection->isEmpty()) {
|
if ($collection->isEmpty()) {
|
||||||
throw new \Exception('Collection need to be passed to to Realtime for Document events in the Database.');
|
throw new \Exception('Collection needs to be passed to Realtime for Document events in the Database.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$channels[] = 'documents';
|
$channels[] = 'documents';
|
||||||
|
@ -294,17 +294,14 @@ class Realtime extends Adapter
|
||||||
|
|
||||||
$roles = ($collection->getAttribute('permission') === 'collection') ? $collection->getRead() : $payload->getRead();
|
$roles = ($collection->getAttribute('permission') === 'collection') ? $collection->getRead() : $payload->getRead();
|
||||||
|
|
||||||
break;
|
|
||||||
case strpos($event, 'storage.buckets.') === 0:
|
|
||||||
$channels[] = 'buckets';
|
|
||||||
$channels[] = 'buckets.' . $payload->getId();
|
|
||||||
$roles = $payload->getRead();
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case strpos($event, 'storage.files') === 0:
|
case strpos($event, 'storage.files') === 0:
|
||||||
|
if($bucket->isEmpty()) {
|
||||||
|
throw new \Exception('Bucket needs to be pased to Realtime for File events in the Storage.');
|
||||||
|
}
|
||||||
$channels[] = 'files';
|
$channels[] = 'files';
|
||||||
$channels[] = 'buckets.' . $payload->getAttribute('bucketId') . '.files';
|
$channels[] = 'buckets.' . $payload->getAttribute('bucketId') . '.files';
|
||||||
$channels[] = 'files.' . $payload->getId();
|
$channels[] = 'buckets.' . $payload->getAttribute('bucketId') . '.files.' . $payload->getId();
|
||||||
$roles = $payload->getRead();
|
$roles = $payload->getRead();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -851,7 +851,7 @@ class RealtimeCustomClientTest extends Scope
|
||||||
$session = $user['session'] ?? '';
|
$session = $user['session'] ?? '';
|
||||||
$projectId = $this->getProject()['$id'];
|
$projectId = $this->getProject()['$id'];
|
||||||
|
|
||||||
$client = $this->getWebsocket(['files', 'buckets'], [
|
$client = $this->getWebsocket(['files'], [
|
||||||
'origin' => 'http://localhost',
|
'origin' => 'http://localhost',
|
||||||
'cookie' => 'a_session_'.$projectId.'=' . $session
|
'cookie' => 'a_session_'.$projectId.'=' . $session
|
||||||
]);
|
]);
|
||||||
|
@ -861,9 +861,8 @@ class RealtimeCustomClientTest extends Scope
|
||||||
$this->assertArrayHasKey('data', $response);
|
$this->assertArrayHasKey('data', $response);
|
||||||
$this->assertEquals('connected', $response['type']);
|
$this->assertEquals('connected', $response['type']);
|
||||||
$this->assertNotEmpty($response['data']);
|
$this->assertNotEmpty($response['data']);
|
||||||
$this->assertCount(2, $response['data']['channels']);
|
$this->assertCount(1, $response['data']['channels']);
|
||||||
$this->assertContains('files', $response['data']['channels']);
|
$this->assertContains('files', $response['data']['channels']);
|
||||||
$this->assertContains('buckets', $response['data']['channels']);
|
|
||||||
$this->assertNotEmpty($response['data']['user']);
|
$this->assertNotEmpty($response['data']['user']);
|
||||||
$this->assertEquals($user['$id'], $response['data']['user']['$id']);
|
$this->assertEquals($user['$id'], $response['data']['user']['$id']);
|
||||||
|
|
||||||
|
@ -881,18 +880,7 @@ class RealtimeCustomClientTest extends Scope
|
||||||
'write' => ['role:all'],
|
'write' => ['role:all'],
|
||||||
'permission' => 'bucket'
|
'permission' => 'bucket'
|
||||||
]);
|
]);
|
||||||
$response = json_decode($client->receive(), true);
|
|
||||||
|
|
||||||
$this->assertArrayHasKey('type', $response);
|
|
||||||
$this->assertArrayHasKey('data', $response);
|
|
||||||
$this->assertEquals('event', $response['type']);
|
|
||||||
$this->assertNotEmpty($response['data']);
|
|
||||||
$this->assertArrayHasKey('timestamp', $response['data']);
|
|
||||||
$this->assertCount(2, $response['data']['channels']);
|
|
||||||
$this->assertContains('buckets', $response['data']['channels']);
|
|
||||||
$this->assertContains('buckets.' . $bucket1['body']['$id'], $response['data']['channels']);
|
|
||||||
$this->assertEquals('storage.buckets.create', $response['data']['event']);
|
|
||||||
$this->assertNotEmpty($response['data']['payload']);
|
|
||||||
$data = ['bucketId' => $bucket1['body']['$id']];
|
$data = ['bucketId' => $bucket1['body']['$id']];
|
||||||
/**
|
/**
|
||||||
* Test File Create
|
* Test File Create
|
||||||
|
@ -905,7 +893,6 @@ class RealtimeCustomClientTest extends Scope
|
||||||
'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'),
|
'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'),
|
||||||
'read' => ['role:all'],
|
'read' => ['role:all'],
|
||||||
'write' => ['role:all'],
|
'write' => ['role:all'],
|
||||||
'folderId' => 'xyz',
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$response = json_decode($client->receive(), true);
|
$response = json_decode($client->receive(), true);
|
||||||
|
@ -917,7 +904,7 @@ class RealtimeCustomClientTest extends Scope
|
||||||
$this->assertArrayHasKey('timestamp', $response['data']);
|
$this->assertArrayHasKey('timestamp', $response['data']);
|
||||||
$this->assertCount(3, $response['data']['channels']);
|
$this->assertCount(3, $response['data']['channels']);
|
||||||
$this->assertContains('files', $response['data']['channels']);
|
$this->assertContains('files', $response['data']['channels']);
|
||||||
$this->assertContains('files.' . $file['body']['$id'], $response['data']['channels']);
|
$this->assertContains('buckets.' . $data['bucketId'] . '.files.' . $file['body']['$id'], $response['data']['channels']);
|
||||||
$this->assertContains('buckets.' . $data['bucketId'] . '.files', $response['data']['channels']);
|
$this->assertContains('buckets.' . $data['bucketId'] . '.files', $response['data']['channels']);
|
||||||
$this->assertEquals('storage.files.create', $response['data']['event']);
|
$this->assertEquals('storage.files.create', $response['data']['event']);
|
||||||
$this->assertNotEmpty($response['data']['payload']);
|
$this->assertNotEmpty($response['data']['payload']);
|
||||||
|
@ -944,7 +931,7 @@ class RealtimeCustomClientTest extends Scope
|
||||||
$this->assertArrayHasKey('timestamp', $response['data']);
|
$this->assertArrayHasKey('timestamp', $response['data']);
|
||||||
$this->assertCount(3, $response['data']['channels']);
|
$this->assertCount(3, $response['data']['channels']);
|
||||||
$this->assertContains('files', $response['data']['channels']);
|
$this->assertContains('files', $response['data']['channels']);
|
||||||
$this->assertContains('files.' . $file['body']['$id'], $response['data']['channels']);
|
$this->assertContains('buckets.' . $data['bucketId'] . '.files.' . $file['body']['$id'], $response['data']['channels']);
|
||||||
$this->assertContains('buckets.' . $data['bucketId'] . '.files', $response['data']['channels']);
|
$this->assertContains('buckets.' . $data['bucketId'] . '.files', $response['data']['channels']);
|
||||||
$this->assertEquals('storage.files.update', $response['data']['event']);
|
$this->assertEquals('storage.files.update', $response['data']['event']);
|
||||||
$this->assertNotEmpty($response['data']['payload']);
|
$this->assertNotEmpty($response['data']['payload']);
|
||||||
|
@ -966,7 +953,7 @@ class RealtimeCustomClientTest extends Scope
|
||||||
$this->assertArrayHasKey('timestamp', $response['data']);
|
$this->assertArrayHasKey('timestamp', $response['data']);
|
||||||
$this->assertCount(3, $response['data']['channels']);
|
$this->assertCount(3, $response['data']['channels']);
|
||||||
$this->assertContains('files', $response['data']['channels']);
|
$this->assertContains('files', $response['data']['channels']);
|
||||||
$this->assertContains('files.' . $file['body']['$id'], $response['data']['channels']);
|
$this->assertContains('buckets.' . $data['bucketId'] . '.files.' . $file['body']['$id'], $response['data']['channels']);
|
||||||
$this->assertContains('buckets.' . $data['bucketId'] . '.files', $response['data']['channels']);
|
$this->assertContains('buckets.' . $data['bucketId'] . '.files', $response['data']['channels']);
|
||||||
$this->assertEquals('storage.files.delete', $response['data']['event']);
|
$this->assertEquals('storage.files.delete', $response['data']['event']);
|
||||||
$this->assertNotEmpty($response['data']['payload']);
|
$this->assertNotEmpty($response['data']['payload']);
|
||||||
|
|
Loading…
Reference in a new issue