1
0
Fork 0
mirror of synced 2024-06-01 18:39:57 +12:00

fix: realtime, tests and webhooks

This commit is contained in:
Torsten Dittmann 2022-04-18 18:21:45 +02:00
parent 8ec435ed1f
commit 7790d72c0c
30 changed files with 1620 additions and 759 deletions

View file

@ -281,11 +281,5 @@ return [
'description' => 'This event triggers when a team memberships is deleted.',
'model' => Response::MODEL_MEMBERSHIP,
'note' => 'version >= 0.7',
],
'users.*' => [
'description' => 'This event triggers when a team memberships is deleted.',
'model' => Response::MODEL_MEMBERSHIP,
'note' => 'version >= 0.7',
],
]
];

View file

@ -734,16 +734,13 @@ App::post('/v1/account/sessions/magic-url')
->trigger()
;
$events
->setParam('eventData',
$response->output($token->setAttribute('secret', $loginSecret),
$events->setParam('eventData', $response->output(
$token->setAttribute('secret', $loginSecret),
Response::MODEL_TOKEN
))
;
));
$token // Hide secret for clients
->setAttribute('secret',
($isPrivilegedUser || $isAppUser) ? $loginSecret : '');
// Hide secret for clients
$token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $loginSecret : '');
$audits
->setResource('user/'.$user->getId())
@ -1907,21 +1904,18 @@ App::post('/v1/account/recovery')
$events
->setParam('userId', $profile->getId())
->setParam('tokenId', $recovery->getId())
->setUser($profile)
->setPayload($response->output(
$recovery->setAttribute('secret', $secret),
Response::MODEL_TOKEN
))
;
$recovery // Hide secret for clients, sp
->setAttribute('secret',
($isPrivilegedUser || $isAppUser) ? $secret : '');
// Hide secret for clients
$recovery->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $secret : '');
$audits->setResource('user/' . $profile->getId());
$usage
->setParam('users.update', 1)
;
$usage->setParam('users.update', 1);
$response->setStatusCode(Response::STATUS_CODE_CREATED);
$response->dynamic($recovery, Response::MODEL_TOKEN);
@ -2094,9 +2088,8 @@ App::post('/v1/account/verification')
))
;
$verification // Hide secret for clients, sp
->setAttribute('secret',
($isPrivilegedUser || $isAppUser) ? $verificationSecret : '');
// Hide secret for clients
$verification->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $verificationSecret : '');
$audits->setResource('user/' . $user->getId());
$usage->setParam('users.update', 1);

View file

@ -124,7 +124,7 @@ function createAttribute(string $collectionId, Document $attribute, Response $re
;
$events
->setTrigger($collection)
->setContext($collection)
->setParam('collectionId', $collection->getId())
->setParam('attributeId', $attribute->getId())
;
@ -1315,7 +1315,7 @@ App::delete('/v1/database/collections/:collectionId/attributes/:key')
$events
->setParam('collectionId', $collection->getId())
->setParam('attributeId', $attribute->getId())
->setTrigger($collection)
->setContext($collection)
->setPayload($response->output($attribute, $model))
;
@ -1429,7 +1429,7 @@ App::post('/v1/database/collections/:collectionId/indexes')
$events
->setParam('collectionId', $collection->getId())
->setParam('indexId', $index->getId())
->setTrigger($collection)
->setContext($collection)
;
$audits
@ -1577,7 +1577,7 @@ App::delete('/v1/database/collections/:collectionId/indexes/:key')
$events
->setParam('collectionId', $collection->getId())
->setParam('indexId', $index->getId())
->setTrigger($collection)
->setContext($collection)
->setPayload($response->output($index, Response::MODEL_INDEX))
;
@ -1694,7 +1694,7 @@ App::post('/v1/database/collections/:collectionId/documents')
$events
->setParam('collectionId', $collection->getId())
->setParam('documentId', $document->getId())
->setTrigger($collection)
->setContext($collection)
;
$usage
@ -2092,7 +2092,7 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
$events
->setParam('collectionId', $collection->getId())
->setParam('documentId', $document->getId())
->setTrigger($collection)
->setContext($collection)
;
$usage
@ -2193,7 +2193,7 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId')
$events
->setParam('collectionId', $collection->getId())
->setParam('documentId', $document->getId())
->setTrigger($collection)
->setContext($collection)
->setPayload($response->output($document, Response::MODEL_DOCUMENT))
;

View file

@ -939,7 +939,7 @@ App::post('/v1/functions/:functionId/executions')
$events
->setParam('functionId', $function->getId())
->setParam('executionId', $execution->getId())
->setTrigger($function);
->setContext($function);
if ($async) {
$event = new Func();

View file

@ -682,7 +682,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
$events
->setParam('bucketId', $bucket->getId())
->setParam('fileId', $file->getId())
->setTrigger($bucket)
->setContext($bucket)
;
$metadata = null; // was causing leaks as it was passed by reference
@ -1413,7 +1413,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
$events
->setParam('bucketId', $bucket->getId())
->setParam('fileId', $file->getId())
->setTrigger($bucket)
->setContext($bucket)
;
$audits->setResource('file/' . $file->getId());
@ -1522,7 +1522,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
$events
->setParam('bucketId', $bucket->getId())
->setParam('fileId', $file->getId())
->setTrigger($bucket)
->setContext($bucket)
->setPayload($response->output($file, Response::MODEL_FILE))
;

View file

@ -7,14 +7,8 @@ use Utopia\App;
use Appwrite\Extend\Exception;
use Utopia\Abuse\Abuse;
use Utopia\Abuse\Adapters\TimeLimit;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Storage\Device\DOSpaces;
use Utopia\Database\Validator\Authorization;
use Utopia\Storage\Device\Local;
use Utopia\Storage\Device\S3;
use Utopia\Storage\Storage;
App::init(function ($utopia, $request, $response, $project, $user, $events, $audits, $mails, $usage, $deletes, $database, $dbForProject, $mode) {
/** @var Utopia\App $utopia */
@ -193,13 +187,16 @@ App::shutdown(function ($utopia, $request, $response, $project, $events, $audits
/** @var Utopia\Database\Database $dbForProject */
if (!empty($events->getEvent())) {
if (empty($events->getPayload())) {
$events->setPayload($response->getPayload());
}
/**
* Trigger functions.
*/
$events
->setClass(Event::FUNCTIONS_CLASS_NAME)
->setQueue(Event::FUNCTIONS_QUEUE_NAME)
->setPayload($response->getPayload())
->setPayload($events->getPayload())
->trigger();
/**
@ -208,16 +205,17 @@ App::shutdown(function ($utopia, $request, $response, $project, $events, $audits
$events
->setClass(Event::WEBHOOK_CLASS_NAME)
->setQueue(Event::WEBHOOK_QUEUE_NAME)
->setPayload($response->getPayload())
->setPayload($events->getPayload())
->trigger();
var_dump($events->getEvent());
/**
* Trigger realtime.
*/
if ($project->getId() !== 'console') {
$allEvents = Event::generateEvents($events->getEvent(), $events->getParams());
$payload = new Document($response->getPayload());
$trigger = $events->getTrigger() ?? false;
$payload = new Document($events->getPayload());
$trigger = $events->getContext() ?? false;
$collection = ($trigger && $trigger->getCollection() === 'collections') ? $trigger : null;
$bucket = ($trigger && $trigger->getCollection() === 'buckets') ? $trigger : null;
@ -231,12 +229,12 @@ App::shutdown(function ($utopia, $request, $response, $project, $events, $audits
);
Realtime::send(
$target['projectId'] ?? $project->getId(),
$response->getPayload(),
$allEvents[0],
$target['channels'],
$target['roles'],
[
projectId: $target['projectId'] ?? $project->getId(),
payload: $events->getPayload(),
events: $allEvents,
channels: $target['channels'],
roles: $target['roles'],
options: [
'permissionsChanged' => $target['permissionsChanged'],
'userId' => $events->getParam('userId')
]

View file

@ -165,7 +165,7 @@ App::get('/console/webhooks')
$page
->setParam('events', Config::getParam('events', []))
;
$layout
->setParam('title', APP_NAME.' - Webhooks')
->setParam('body', $page);

View file

@ -1,7 +1,9 @@
<?php
use Appwrite\Event\Event;
use Appwrite\Messaging\Adapter\Realtime;
use Appwrite\Resque\Worker;
use Appwrite\Utopia\Response\Model\Deployment;
use Cron\CronExpression;
use Executor\Executor;
use Utopia\Database\Validator\Authorization;
@ -110,12 +112,33 @@ class BuildsV1 extends Worker
$build->setAttribute('status', 'building');
$build = $dbForProject->updateDocument('builds', $buildId, $build);
/** Send realtime event */
$target = Realtime::fromPayload('functions.deployments.update', $build, $project);
/** Trigger Webhook */
$deploymentModel = new Deployment();
$deploymentUpdate = new Event(Event::WEBHOOK_QUEUE_NAME, Event::WEBHOOK_CLASS_NAME);
$deploymentUpdate
->setProject($project)
->setEvent('functions.[functionId].deployments.[deploymentId].update')
->setParam('functionId', $function->getId())
->setParam('deploymentId', $deployment->getId())
->setPayload($deployment->getArrayCopy(array_keys($deploymentModel->getRules())))
->trigger();
/** Trigger Functions */
$deploymentUpdate
->setClass(Event::FUNCTIONS_CLASS_NAME)
->setQueue(Event::FUNCTIONS_QUEUE_NAME)
->trigger();
/** Trigger Realtime */
$allEvents = Event::generateEvents('functions.[functionId].deployments.[deploymentId].update', [
'functionId' => $function->getId(),
'deploymentId' => $deployment->getId()
]);
$target = Realtime::fromPayload($allEvents[0], $build, $project);
Realtime::send(
projectId: 'console',
payload: $build->getArrayCopy(),
event: 'functions.deployments.update',
events: $allEvents,
channels: $target['channels'],
roles: $target['roles']
);
@ -179,11 +202,11 @@ class BuildsV1 extends Worker
/**
* Send realtime Event
*/
$target = Realtime::fromPayload('functions.deployments.update', $build, $project);
$target = Realtime::fromPayload($allEvents[0], $build, $project);
Realtime::send(
projectId: 'console',
payload: $build->getArrayCopy(),
event: 'functions.deployments.update',
events: $allEvents,
channels: $target['channels'],
roles: $target['roles']
);

View file

@ -1,5 +1,6 @@
<?php
use Appwrite\Event\Event;
use Appwrite\Messaging\Adapter\Realtime;
use Appwrite\Resque\Worker;
use Utopia\CLI\Console;
@ -70,7 +71,10 @@ class DatabaseV1 extends Worker
$dbForConsole = $this->getConsoleDB();
$dbForProject = $this->getProjectDB($projectId);
$event = 'database.attributes.update';
$events = Event::generateEvents('collections.[collectionId].attributes.[attributeId].update', [
'collectionId' => $collection->getId(),
'attributeId' => $attribute->getId()
]);
$collectionId = $collection->getId();
$key = $attribute->getAttribute('key', '');
$type = $attribute->getAttribute('type', '');
@ -93,12 +97,12 @@ class DatabaseV1 extends Worker
Console::error($th->getMessage());
$dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'failed'));
} finally {
$target = Realtime::fromPayload($event, $attribute, $project);
$target = Realtime::fromPayload($events[0], $attribute, $project);
Realtime::send(
projectId: 'console',
payload: $attribute->getArrayCopy(),
event: $event,
events: $events,
channels: $target['channels'],
roles: $target['roles'],
options: [
@ -121,7 +125,10 @@ class DatabaseV1 extends Worker
$dbForConsole = $this->getConsoleDB();
$dbForProject = $this->getProjectDB($projectId);
$event = 'database.attributes.delete';
$events = Event::generateEvents('collections.[collectionId].attributes.[attributeId].delete', [
'collectionId' => $collection->getId(),
'attributeId' => $attribute->getId()
]);
$collectionId = $collection->getId();
$key = $attribute->getAttribute('key', '');
$status = $attribute->getAttribute('status', '');
@ -142,12 +149,12 @@ class DatabaseV1 extends Worker
Console::error($th->getMessage());
$dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'stuck'));
} finally {
$target = Realtime::fromPayload($event, $attribute, $project);
$target = Realtime::fromPayload($events[0], $attribute, $project);
Realtime::send(
projectId: 'console',
payload: $attribute->getArrayCopy(),
event: $event,
events: $events,
channels: $target['channels'],
roles: $target['roles'],
options: [
@ -222,7 +229,10 @@ class DatabaseV1 extends Worker
$dbForConsole = $this->getConsoleDB();
$dbForProject = $this->getProjectDB($projectId);
$event = 'database.indexes.update';
$events = Event::generateEvents('collections.[collectionId].indexes.[indexId].update', [
'collectionId' => $collection->getId(),
'indexId' => $index->getId()
]);
$collectionId = $collection->getId();
$key = $index->getAttribute('key', '');
$type = $index->getAttribute('type', '');
@ -240,12 +250,12 @@ class DatabaseV1 extends Worker
Console::error($th->getMessage());
$dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'failed'));
} finally {
$target = Realtime::fromPayload($event, $index, $project);
$target = Realtime::fromPayload($events[0], $index, $project);
Realtime::send(
projectId: 'console',
payload: $index->getArrayCopy(),
event: $event,
events: $events,
channels: $target['channels'],
roles: $target['roles'],
options: [
@ -268,10 +278,12 @@ class DatabaseV1 extends Worker
$dbForConsole = $this->getConsoleDB();
$dbForProject = $this->getProjectDB($projectId);
$collectionId = $collection->getId();
$events = Event::generateEvents('collections.[collectionId].indexes.[indexId].delete', [
'collectionId' => $collection->getId(),
'indexId' => $index->getId()
]);
$key = $index->getAttribute('key');
$status = $index->getAttribute('status', '');
$event = 'database.indexes.delete';
$project = $dbForConsole->getDocument('projects', $projectId);
try {
@ -283,12 +295,12 @@ class DatabaseV1 extends Worker
Console::error($th->getMessage());
$dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'stuck'));
} finally {
$target = Realtime::fromPayload($event, $index, $project);
$target = Realtime::fromPayload($events[0], $index, $project);
Realtime::send(
projectId: 'console',
payload: $index->getArrayCopy(),
event: $event,
events: $events,
channels: $target['channels'],
roles: $target['roles'],
options: [
@ -298,6 +310,6 @@ class DatabaseV1 extends Worker
);
}
$dbForProject->deleteCachedDocument('collections', $collectionId);
$dbForProject->deleteCachedDocument('collections', $collection->getId());
}
}

View file

@ -71,13 +71,13 @@ class FunctionsV1 extends Worker
Console::success('Iterating function: ' . $function->getAttribute('name'));
$this->execute(
projectId: $project->getId(),
project: $project,
function: $function,
dbForProject: $database,
trigger: 'event',
event: $events[0],
eventData: $payload,
userId: $user->getId()
user: $user
);
Console::success('Triggered function: ' . $events[0]);
@ -102,13 +102,13 @@ class FunctionsV1 extends Worker
$function = Authorization::skip(fn () => $database->getDocument('functions', $execution->getAttribute('functionId')));
$this->execute(
projectId: $project->getId(),
project: $project,
function: $function,
dbForProject: $database,
executionId: $execution->getId(),
trigger: 'http',
data: $data,
userId: $user->getId(),
user: $user,
jwt: $jwt
);
@ -170,7 +170,7 @@ class FunctionsV1 extends Worker
$reschedule->schedule($next);
$this->execute(
projectId: $project->getId(),
project: $project,
function: $function,
dbForProject: $database,
trigger: 'schedule'
@ -181,7 +181,7 @@ class FunctionsV1 extends Worker
}
private function execute(
string $projectId,
Document $project,
Document $function,
Database $dbForProject,
string $trigger,
@ -189,7 +189,7 @@ class FunctionsV1 extends Worker
string $event = null,
string $eventData = null,
string $data = null,
string $userId = null,
?Document $user = null,
string $jwt = null
) {
@ -227,13 +227,13 @@ class FunctionsV1 extends Worker
$runtime = $runtimes[$function->getAttribute('runtime')];
/** Create execution or update execution status */
$execution = Authorization::skip(function () use ($dbForProject, &$executionId, $functionId, $deploymentId, $trigger, $userId) {
$execution = Authorization::skip(function () use ($dbForProject, &$executionId, $functionId, $deploymentId, $trigger, $user) {
$execution = $dbForProject->getDocument('executions', $executionId);
if ($execution->isEmpty()) {
$executionId = $dbForProject->getId();
$execution = $dbForProject->createDocument('executions', new Document([
'$id' => $executionId,
'$read' => $userId ? ['user:' . $userId] : [],
'$read' => $user->getId() ? ['user:' . $user->getId()] : [],
'$write' => [],
'dateCreated' => time(),
'functionId' => $functionId,
@ -268,8 +268,8 @@ class FunctionsV1 extends Worker
'APPWRITE_FUNCTION_EVENT' => $event,
'APPWRITE_FUNCTION_EVENT_DATA' => $eventData,
'APPWRITE_FUNCTION_DATA' => $data,
'APPWRITE_FUNCTION_PROJECT_ID' => $projectId,
'APPWRITE_FUNCTION_USER_ID' => $userId,
'APPWRITE_FUNCTION_PROJECT_ID' => $project->getId(),
'APPWRITE_FUNCTION_USER_ID' => $user->getId(),
'APPWRITE_FUNCTION_JWT' => $jwt,
];
$vars = \array_merge($function->getAttribute('vars', []), $vars);
@ -277,7 +277,7 @@ class FunctionsV1 extends Worker
/** Execute function */
try {
$executionResponse = $this->executor->createExecution(
projectId: $projectId,
projectId: $project->getId(),
deploymentId: $deploymentId,
path: $build->getAttribute('outputPath', ''),
vars: $vars,
@ -304,30 +304,43 @@ class FunctionsV1 extends Worker
}
$execution = Authorization::skip(fn () => $dbForProject->updateDocument('executions', $executionId, $execution));
/** @var Document $execution */
/** Trigger Webhook */
$executionModel = new Execution();
$executionUpdate = new Event(Event::WEBHOOK_QUEUE_NAME, Event::WEBHOOK_CLASS_NAME);
$executionUpdate
->setParam('projectId', $projectId)
->setParam('userId', $userId)
->setParam('event', 'functions.executions.update')
->setParam('eventData', $execution->getArrayCopy(array_keys($executionModel->getRules())))
->setProject($project)
->setUser($user)
->setEvent('functions.[functionId].executions.[executionId].update')
->setParam('functionId', $function->getId())
->setParam('executionId', $execution->getId())
->setPayload($execution->getArrayCopy(array_keys($executionModel->getRules())))
->trigger();
/** Trigger Functions */
$executionUpdate
->setClass(Event::FUNCTIONS_CLASS_NAME)
->setQueue(Event::FUNCTIONS_QUEUE_NAME)
->trigger();
/** Trigger realtime event */
$target = Realtime::fromPayload('functions.executions.update', $execution);
$allEvents = Event::generateEvents('functions.[functionId].executions.[executionId].update', [
'functionId' => $function->getId(),
'executionId' => $execution->getId()
]);
$target = Realtime::fromPayload($allEvents[0], $execution);
Realtime::send(
projectId: 'console',
payload: $execution->getArrayCopy(),
event: 'functions.executions.update',
events: $allEvents,
channels: $target['channels'],
roles: $target['roles']
);
Realtime::send(
projectId: $projectId,
projectId: $project->getId(),
payload: $execution->getArrayCopy(),
event: 'functions.executions.update',
events: $allEvents,
channels: $target['channels'],
roles: $target['roles']
);
@ -338,7 +351,7 @@ class FunctionsV1 extends Worker
$statsd = $register->get('statsd');
$usage = new Stats($statsd);
$usage
->setParam('projectId', $projectId)
->setParam('projectId', $project->getId())
->setParam('functionId', $function->getId())
->setParam('functionExecution', 1)
->setParam('functionStatus', $execution->getAttribute('status', ''))

View file

@ -32,6 +32,11 @@ class WebhooksV1 extends Worker
foreach ($project->getAttribute('webhooks', []) as $webhook) {
if (array_intersect($webhook->getAttribute('events', []), $events)) {
Console::log("");
Console::log("");
Console::log(var_export($events, true));
Console::log("");
Console::log("");
$this->execute($events, $payload, $webhook, $user, $project);
}
}
@ -68,7 +73,7 @@ class WebhooksV1 extends Worker
'X-' . APP_NAME . '-Webhook-Name: ' . $webhook->getAttribute('name', ''),
'X-' . APP_NAME . '-Webhook-User-Id: ' . $user->getId(),
'X-' . APP_NAME . '-Webhook-Project-Id: ' . $project->getId(),
'X-' . APP_NAME . '-Webhook-Signature: ' . $webhook->getAttribute('signature') ?? 'not-yet-implemented',
'X-' . APP_NAME . '-Webhook-Signature: ' . $webhook->getAttribute('signature', 'not-yet-implemented'),
]
);

View file

@ -16,6 +16,12 @@ class Audit extends Event
parent::__construct(Event::AUDITS_QUEUE_NAME, Event::AUDITS_CLASS_NAME);
}
/**
* Set resource for this audit event.
*
* @param string $resource
* @return self
*/
public function setResource(string $resource): self
{
$this->resource = $resource;
@ -23,11 +29,22 @@ class Audit extends Event
return $this;
}
/**
* Returns the set audit resource.
*
* @return string
*/
public function getResource(): string
{
return $this->resource;
}
/**
* Set mode for this audit event
*
* @param string $mode
* @return self
*/
public function setMode(string $mode): self
{
$this->mode = $mode;
@ -35,11 +52,22 @@ class Audit extends Event
return $this;
}
/**
* Returns the set audit mode.
*
* @return string
*/
public function getMode(): string
{
return $this->mode;
}
/**
* Set user agent for this audit event.
*
* @param string $userAgent
* @return self
*/
public function setUserAgent(string $userAgent): self
{
$this->userAgent = $userAgent;
@ -47,11 +75,22 @@ class Audit extends Event
return $this;
}
/**
* Returns the set audit user agent.
*
* @return string
*/
public function getUserAgent(): string
{
return $this->userAgent;
}
/**
* Set IP for this audit event.
*
* @param string $userAgent
* @return self
*/
public function setIP(string $ip): self
{
$this->ip = $ip;
@ -59,18 +98,28 @@ class Audit extends Event
return $this;
}
/**
* Returns the set audit IP.
*
* @return string
*/
public function getIP(): string
{
return $this->ip;
}
/**
* Executes the event and sends it to the audit worker.
*
* @return string|bool
* @throws \InvalidArgumentException
*/
public function trigger(): string|bool
{
return Resque::enqueue($this->queue, $this->class, [
'project' => $this->project,
'user' => $this->user,
'payload' => $this->payload,
'trigger' => $this->trigger,
'resource' => $this->resource,
'mode' => $this->mode,
'ip' => $this->ip,

View file

@ -7,15 +7,21 @@ use Utopia\Database\Document;
class Certificate extends Event
{
protected ?Document $domain = null;
protected bool $validateTarget = false;
protected bool $validateCNAME = false;
protected ?Document $domain = null;
public function __construct()
{
parent::__construct(Event::CERTIFICATES_QUEUE_NAME, Event::CERTIFICATES_CLASS_NAME);
}
/**
* Set domain for this certificates event.
*
* @param \Utopia\Database\Document $domain
* @return self
*/
public function setDomain(Document $domain): self
{
$this->domain = $domain;
@ -23,11 +29,22 @@ class Certificate extends Event
return $this;
}
/**
* Returns the set domain for this certificate event.
*
* @return null|\Utopia\Database\Document
*/
public function getDomain(): ?Document
{
return $this->domain;
}
/**
* Set if the target needs be validated.
*
* @param bool $validateTarget
* @return self
*/
public function setValidateTarget(bool $validateTarget): self
{
$this->validateTarget = $validateTarget;
@ -35,11 +52,22 @@ class Certificate extends Event
return $this;
}
/**
* Return if the domain target will be validated.
*
* @return bool
*/
public function getValidateTarget(): bool
{
return $this->validateTarget;
}
/**
* Set if the CNAME needs to be validated.
*
* @param bool $validateCNAME
* @return self
*/
public function setValidateCNAME(bool $validateCNAME): self
{
$this->validateCNAME = $validateCNAME;
@ -47,11 +75,22 @@ class Certificate extends Event
return $this;
}
/**
* Return if the CNAME will be validated.
*
* @return bool
*/
public function getValidateCNAME(): bool
{
return $this->validateCNAME;
}
/**
* Executes the event and sends it to the certificates worker.
*
* @return string|bool
* @throws \InvalidArgumentException
*/
public function trigger(): string|bool
{
return Resque::enqueue($this->queue, $this->class, [
@ -61,4 +100,4 @@ class Certificate extends Event
'validateCNAME' => $this->validateCNAME
]);
}
}
}

View file

@ -16,6 +16,12 @@ class Database extends Event
parent::__construct(Event::DATABASE_QUEUE_NAME, Event::DATABASE_CLASS_NAME);
}
/**
* Sets the type for this database event (use the constants starting with DATABASE_TYPE_*).
*
* @param string $type
* @return self
*/
public function setType(string $type): self
{
$this->type = $type;
@ -23,11 +29,21 @@ class Database extends Event
return $this;
}
/**
* Returns the set type for the database event.
* @return string
*/
public function getType(): string
{
return $this->type;
}
/**
* Set the collection for this database event.
*
* @param \Utopia\Database\Document $collection
* @return self
*/
public function setCollection(Document $collection): self
{
$this->collection = $collection;
@ -35,11 +51,22 @@ class Database extends Event
return $this;
}
public function getCollection(): Document
/**
* Returns set collection for this event.
*
* @return null|\Utopia\Database\Document
*/
public function getCollection(): ?Document
{
return $this->collection;
}
/**
* Set the document for this database event.
*
* @param \Utopia\Database\Document $document
* @return self
*/
public function setDocument(Document $document): self
{
$this->document = $document;
@ -47,11 +74,21 @@ class Database extends Event
return $this;
}
public function getDocument(): Document
/**
* Returns set document for this database event.
* @return null|\Utopia\Database\Document
*/
public function getDocument(): ?Document
{
return $this->document;
}
/**
* Executes the event and send it to the database worker.
*
* @return string|bool
* @throws \InvalidArgumentException
*/
public function trigger(): string|bool
{
return Resque::enqueue($this->queue, $this->class, [

View file

@ -15,6 +15,12 @@ class Delete extends Event
parent::__construct(Event::DELETE_QUEUE_NAME, Event::DELETE_CLASS_NAME);
}
/**
* Sets the type for the delete event (use the constants starting with DELETE_TYPE_*).
*
* @param string $type
* @return self
*/
public function setType(string $type): self
{
$this->type = $type;
@ -22,11 +28,22 @@ class Delete extends Event
return $this;
}
/**
* Returns the set type for the delete event.
*
* @return string
*/
public function getType(): string
{
return $this->type;
}
/**
* Sets the document for the delete event.
*
* @param \Utopia\Database\Document $document
* @return self
*/
public function setDocument(Document $document): self
{
$this->document = $document;
@ -34,11 +51,22 @@ class Delete extends Event
return $this;
}
public function getDocument(): Document
/**
* Returns the set document for the delete event.
*
* @return null|\Utopia\Database\Document
*/
public function getDocument(): ?Document
{
return $this->document;
}
/**
* Executes this event and sends it to the deletes worker.
*
* @return string|bool
* @throws \InvalidArgumentException
*/
public function trigger(): string|bool
{
return Resque::enqueue($this->queue, $this->class, [
@ -47,4 +75,4 @@ class Delete extends Event
'document' => $this->document,
]);
}
}
}

View file

@ -43,7 +43,7 @@ class Event
protected array $payload = [];
protected ?Document $project = null;
protected ?Document $user = null;
protected ?Document $trigger = null;
protected ?Document $context = null;
/**
* @param string $queue
@ -137,16 +137,16 @@ class Event
return $this->payload;
}
public function setTrigger(Document $trigger): self
public function setContext(Document $context): self
{
$this->trigger = $trigger;
$this->context = $context;
return $this;
}
public function getTrigger(): ?Document
public function getContext(): ?Document
{
return $this->trigger;
return $this->context;
}
/**
@ -218,7 +218,7 @@ class Event
'project' => $this->project,
'user' => $this->user,
'payload' => $this->payload,
'trigger' => $this->trigger,
'context' => $this->context,
'events' => Event::generateEvents($this->getEvent(), $this->getParams())
]);
}
@ -235,6 +235,12 @@ class Event
return $this;
}
/**
* Parses event pattern and returns the parts in their respective section.
*
* @param string $pattern
* @return array
*/
public static function parseEventPattern(string $pattern): array
{
$parts = \explode('.', $pattern);
@ -278,6 +284,14 @@ class Event
];
}
/**
* Generates all possible events from a pattern.
*
* @param string $pattern
* @param array $params
* @return array
* @throws \InvalidArgumentException
*/
static function generateEvents(string $pattern, array $params = []): array
{
$params = \array_filter($params, fn($param) => !\is_array($param));
@ -313,16 +327,16 @@ class Event
$patterns[] = \implode('.', [$type, $resource, $subType, $subResource, $action]);
$patterns[] = \implode('.', [$type, $resource, $subType, $subResource]);
} else {
if ($attribute) {
$patterns[] = \implode('.', [$type, $resource, $action, $attribute]);
}
$patterns[] = \implode('.', [$type, $resource, $action]);
$patterns[] = \implode('.', [$type, $resource]);
}
if ($attribute) {
$patterns[] = \implode('.', [$type, $resource, $action, $attribute]);
}
}
if ($subResource) {
$patterns[] = \implode('.', [$type, $resource, $subType, $subResource]);
}
$patterns[] = \implode('.', [$type, $resource]);
/**
* Removes all duplicates.

View file

@ -9,17 +9,23 @@ use Utopia\Database\Document;
class Func extends Event
{
protected ?Document $function = null;
protected ?Document $execution = null;
protected string $jwt = '';
protected string $type = '';
protected string $data = '';
protected ?Document $function = null;
protected ?Document $execution = null;
public function __construct()
{
parent::__construct(Event::FUNCTIONS_QUEUE_NAME, Event::FUNCTIONS_CLASS_NAME);
}
/**
* Sets function document for the function event.
*
* @param \Utopia\Database\Document $function
* @return self
*/
public function setFunction(Document $function): self
{
$this->function = $function;
@ -27,11 +33,22 @@ class Func extends Event
return $this;
}
/**
* Returns set function document for the function event.
*
* @return null|\Utopia\Database\Document
*/
public function getFunction(): ?Document
{
return $this->function;
}
/**
* Sets execution for the function event.
*
* @param \Utopia\Database\Document $execution
* @return self
*/
public function setExecution(Document $execution): self
{
$this->execution = $execution;
@ -39,11 +56,22 @@ class Func extends Event
return $this;
}
/**
* Returns set execution for the function event.
*
* @return null|\Utopia\Database\Document
*/
public function getExecution(): ?Document
{
return $this->execution;
}
/**
* Sets type for the function event.
*
* @param string $type Can be `schedule`, `event` or `http`.
* @return self
*/
public function setType(string $type): self
{
$this->type = $type;
@ -51,11 +79,22 @@ class Func extends Event
return $this;
}
/**
* Returns set type for the function event.
*
* @return string
*/
public function getType(): string
{
return $this->type;
}
/**
* Sets custom data for the function event.
*
* @param string $data
* @return self
*/
public function setData(string $data): self
{
$this->data = $data;
@ -63,11 +102,22 @@ class Func extends Event
return $this;
}
/**
* Returns set custom data for the function event.
*
* @return string
*/
public function getData(): string
{
return $this->data;
}
/**
* Sets JWT for the function event.
*
* @param string $jwt
* @return self
*/
public function setJWT(string $jwt): self
{
$this->jwt = $jwt;
@ -75,11 +125,22 @@ class Func extends Event
return $this;
}
/**
* Returns set JWT for the function event.
*
* @return string
*/
public function getJWT(): string
{
return $this->jwt;
}
/**
* Executes the function event and sends it to the functions worker.
*
* @return string|bool
* @throws \InvalidArgumentException
*/
public function trigger(): string|bool
{
return Resque::enqueue($this->queue, $this->class, [
@ -94,6 +155,14 @@ class Func extends Event
]);
}
/**
* Schedules the function event and schedules it in the functions worker queue.
*
* @param \DateTime|int $at
* @return void
* @throws \Resque_Exception
* @throws \ResqueScheduler_InvalidTimestampException
*/
public function schedule(DateTime|int $at): void
{
ResqueScheduler::enqueueAt($at, $this->queue, $this->class, [
@ -106,4 +175,4 @@ class Func extends Event
'data' => $this->data
]);
}
}
}

View file

@ -19,6 +19,12 @@ class Mail extends Event
parent::__construct(Event::MAILS_QUEUE_NAME, Event::MAILS_CLASS_NAME);
}
/**
* Sets team for the mail event.
*
* @param \Utopia\Database\Document $team
* @return self
*/
public function setTeam(Document $team): self
{
$this->team = $team;
@ -26,11 +32,22 @@ class Mail extends Event
return $this;
}
public function getTeam(): Document
/**
* Returns set team for the mail event.
*
* @return null|\Utopia\Database\Document
*/
public function getTeam(): ?Document
{
return $this->team;
}
/**
* Sets recipient for the mail event.
*
* @param string $recipient
* @return self
*/
public function setRecipient(string $recipient): self
{
$this->recipient = $recipient;
@ -38,11 +55,22 @@ class Mail extends Event
return $this;
}
/**
* Returns set recipient for mail event.
*
* @return string
*/
public function getRecipient(): string
{
return $this->recipient;
}
/**
* Sets url for the mail event.
*
* @param string $url
* @return self
*/
public function setUrl(string $url): self
{
$this->url = $url;
@ -50,11 +78,22 @@ class Mail extends Event
return $this;
}
/**
* Returns set url for the mail event.
*
* @return string
*/
public function getURL(): string
{
return $this->url;
}
/**
* Sets type for the mail event (use the constants starting with MAIL_TYPE_*).
*
* @param string $type
* @return self
*/
public function setType(string $type): self
{
$this->type = $type;
@ -62,11 +101,22 @@ class Mail extends Event
return $this;
}
/**
* Returns set type for the mail event.
*
* @return string
*/
public function getType(): string
{
return $this->type;
}
/**
* Sets name for the mail event.
*
* @param string $name
* @return self
*/
public function setName(string $name): self
{
$this->name = $name;
@ -74,11 +124,22 @@ class Mail extends Event
return $this;
}
/**
* Returns set name for the mail event.
*
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* Sets locale for the mail event.
*
* @param string $locale
* @return self
*/
public function setLocale(string $locale): self
{
$this->locale = $locale;
@ -86,18 +147,28 @@ class Mail extends Event
return $this;
}
/**
* Returns set locale for the mail event.
*
* @return string
*/
public function getLocale(): string
{
return $this->locale;
}
/**
* Executes the event and sends it to the mails worker.
*
* @return string|bool
* @throws \InvalidArgumentException
*/
public function trigger(): string|bool
{
return Resque::enqueue($this->queue, $this->class, [
'project' => $this->project,
'user' => $this->user,
'payload' => $this->payload,
'trigger' => $this->trigger,
'recipient' => $this->recipient,
'url' => $this->url,
'locale' => $this->locale,
@ -107,4 +178,4 @@ class Mail extends Event
'events' => Event::generateEvents($this->getEvent(), $this->getParams())
]);
}
}
}

View file

@ -4,11 +4,6 @@ namespace Appwrite\Event\Validator;
use Utopia\Validator;
/**
* Password.
*
* Validates user password string
*/
class Event extends Validator
{
protected array $types = [
@ -60,6 +55,7 @@ class Event extends Validator
'update',
'delete'
];
/**
* Get Description.
*
@ -69,7 +65,7 @@ class Event extends Validator
*/
public function getDescription(): string
{
return 'Password must be at least 8 characters';
return 'Event is not valid.';
}
/**
@ -89,7 +85,7 @@ class Event extends Validator
}
/**
* Identify all sestions of the pattern.
* Identify all sections of the pattern.
*/
$type = $parts[0] ?? false;
$resource = $parts[1] ?? false;
@ -114,6 +110,7 @@ class Event extends Validator
$subType ??= false;
$subResource ??= false;
$attribute ??= false;
$action = match (true) {
!$hasSubResource && $count > 2 => $parts[2],
$hasSubResource && $count > 4 => $parts[4],

View file

@ -6,5 +6,5 @@ abstract class Adapter
{
public abstract function subscribe(string $projectId, mixed $identifier, array $roles, array $channels): void;
public abstract function unsubscribe(mixed $identifier): void;
public static abstract function send(string $projectId, array $payload, string $event, array $channels, array $roles, array $options): void;
public static abstract function send(string $projectId, array $payload, array $events, array $channels, array $roles, array $options): void;
}

View file

@ -127,7 +127,7 @@ class Realtime extends Adapter
* @param array $options
* @return void
*/
public static function send(string $projectId, array $payload, string $event, array $channels, array $roles, array $options = []): void
public static function send(string $projectId, array $payload, array $events, array $channels, array $roles, array $options = []): void
{
if (empty($channels) || empty($roles) || empty($projectId)) return;
@ -142,7 +142,7 @@ class Realtime extends Adapter
'permissionsChanged' => $permissionsChanged,
'userId' => $userId,
'data' => [
'event' => $event,
'events' => $events,
'channels' => $channels,
'timestamp' => time(),
'payload' => $payload
@ -287,13 +287,13 @@ class Realtime extends Adapter
break;
case 'buckets':
if ($parts[2] === 'files') {
if($bucket->isEmpty()) {
if ($bucket->isEmpty()) {
throw new \Exception('Bucket needs to be pased to Realtime for File events in the Storage.');
}
$channels[] = 'files';
$channels[] = 'buckets.' . $payload->getAttribute('bucketId') . '.files';
$channels[] = 'buckets.' . $payload->getAttribute('bucketId') . '.files.' . $payload->getId();
$roles = ($bucket->getAttribute('permission') === 'collection') ? $bucket->getRead() : $payload->getRead();
$roles = ($bucket->getAttribute('permission') === 'bucket') ? $bucket->getRead() : $payload->getRead();
}
break;

File diff suppressed because it is too large Load diff

View file

@ -2,17 +2,10 @@
namespace Tests\E2E\Services\Realtime;
use Exception;
use SebastianBergmann\RecursionContext\InvalidArgumentException;
use PHPUnit\Framework\ExpectationFailedException;
use PHPUnit\Framework\Exception as FrameworkException;
use Tests\E2E\Client;
use Tests\E2E\Scopes\Scope;
use Tests\E2E\Scopes\ProjectCustom;
use Tests\E2E\Scopes\SideConsole;
use WebSocket\BadOpcodeException;
use WebSocket\ConnectionException;
use WebSocket\TimeoutException;
class RealtimeConsoleClientTest extends Scope
{
@ -23,12 +16,11 @@ class RealtimeConsoleClientTest extends Scope
public function testAttributes()
{
$user = $this->getUser();
$session = $user['session'] ?? '';
$projectId = 'console';
$client = $this->getWebsocket(['console'], [
'origin' => 'http://localhost',
'cookie' => 'a_session_console='. $this->getRoot()['session'],
'cookie' => 'a_session_console=' . $this->getRoot()['session'],
], $projectId);
$response = json_decode($client->receive(), true);
@ -55,9 +47,9 @@ class RealtimeConsoleClientTest extends Scope
'permission' => 'collection'
]);
$data = ['actorsId' => $actors['body']['$id']];
$actorsId = $actors['body']['$id'];
$name = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['actorsId'] . '/attributes/string', array_merge([
$name = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actorsId . '/attributes/string', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -66,6 +58,8 @@ class RealtimeConsoleClientTest extends Scope
'required' => true,
]);
$attributeKey = $name['body']['key'];
$this->assertEquals($name['headers']['status-code'], 201);
$this->assertEquals($name['body']['key'], 'name');
$this->assertEquals($name['body']['type'], 'string');
@ -81,7 +75,16 @@ class RealtimeConsoleClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(1, $response['data']['channels']);
$this->assertContains('console', $response['data']['channels']);
$this->assertEquals('database.attributes.create', $response['data']['event']);
$this->assertContains("collections.{$actorsId}.attributes.{$actorsId}_{$attributeKey}.create", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.attributes.*.create", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.attributes.{$actorsId}_{$attributeKey}", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.attributes.*", $response['data']['events']);
$this->assertContains("collections.{$actorsId}", $response['data']['events']);
$this->assertContains("collections.*.attributes.{$actorsId}_{$attributeKey}.create", $response['data']['events']);
$this->assertContains("collections.*.attributes.*.create", $response['data']['events']);
$this->assertContains("collections.*.attributes.{$actorsId}_{$attributeKey}", $response['data']['events']);
$this->assertContains("collections.*.attributes.*", $response['data']['events']);
$this->assertContains("collections.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$this->assertEquals('processing', $response['data']['payload']['status']);
@ -94,12 +97,23 @@ class RealtimeConsoleClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(1, $response['data']['channels']);
$this->assertContains('console', $response['data']['channels']);
$this->assertEquals('database.attributes.update', $response['data']['event']);
$this->assertContains("collections.{$actorsId}.attributes.{$actorsId}_{$attributeKey}.update", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.attributes.*.update", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.attributes.{$actorsId}_{$attributeKey}", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.attributes.*", $response['data']['events']);
$this->assertContains("collections.{$actorsId}", $response['data']['events']);
$this->assertContains("collections.*.attributes.{$actorsId}_{$attributeKey}.update", $response['data']['events']);
$this->assertContains("collections.*.attributes.*.update", $response['data']['events']);
$this->assertContains("collections.*.attributes.{$actorsId}_{$attributeKey}", $response['data']['events']);
$this->assertContains("collections.*.attributes.*", $response['data']['events']);
$this->assertContains("collections.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$this->assertEquals('available', $response['data']['payload']['status']);
$client->close();
$data = ['actorsId' => $actorsId];
return $data;
}
@ -108,13 +122,11 @@ class RealtimeConsoleClientTest extends Scope
*/
public function testIndexes(array $data)
{
$user = $this->getUser();
$session = $user['session'] ?? '';
$projectId = 'console';
$actorsId = $data['actorsId'];
$client = $this->getWebsocket(['console'], [
'origin' => 'http://localhost',
'cookie' => 'a_session_console='. $this->getRoot()['session'],
'cookie' => 'a_session_console=' . $this->getRoot()['session'],
], $projectId);
$response = json_decode($client->receive(), true);
@ -130,7 +142,7 @@ class RealtimeConsoleClientTest extends Scope
/**
* Test Indexes
*/
$index = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['actorsId'] . '/indexes', array_merge([
$index = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actorsId . '/indexes', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -142,6 +154,7 @@ class RealtimeConsoleClientTest extends Scope
]);
$this->assertEquals($index['headers']['status-code'], 201);
$indexKey = $index['body']['key'];
$response = json_decode($client->receive(), true);
@ -152,7 +165,16 @@ class RealtimeConsoleClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(1, $response['data']['channels']);
$this->assertContains('console', $response['data']['channels']);
$this->assertEquals('database.indexes.create', $response['data']['event']);
$this->assertContains("collections.{$actorsId}.indexes.{$actorsId}_{$indexKey}.create", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.indexes.*.create", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.indexes.{$actorsId}_{$indexKey}", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.indexes.*", $response['data']['events']);
$this->assertContains("collections.{$actorsId}", $response['data']['events']);
$this->assertContains("collections.*.indexes.{$actorsId}_{$indexKey}.create", $response['data']['events']);
$this->assertContains("collections.*.indexes.*.create", $response['data']['events']);
$this->assertContains("collections.*.indexes.{$actorsId}_{$indexKey}", $response['data']['events']);
$this->assertContains("collections.*.indexes.*", $response['data']['events']);
$this->assertContains("collections.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$this->assertEquals('processing', $response['data']['payload']['status']);
@ -165,7 +187,16 @@ class RealtimeConsoleClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(1, $response['data']['channels']);
$this->assertContains('console', $response['data']['channels']);
$this->assertEquals('database.indexes.update', $response['data']['event']);
$this->assertContains("collections.{$actorsId}.indexes.{$actorsId}_{$indexKey}.update", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.indexes.*.update", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.indexes.{$actorsId}_{$indexKey}", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.indexes.*", $response['data']['events']);
$this->assertContains("collections.{$actorsId}", $response['data']['events']);
$this->assertContains("collections.*.indexes.{$actorsId}_{$indexKey}.update", $response['data']['events']);
$this->assertContains("collections.*.indexes.*.update", $response['data']['events']);
$this->assertContains("collections.*.indexes.{$actorsId}_{$indexKey}", $response['data']['events']);
$this->assertContains("collections.*.indexes.*", $response['data']['events']);
$this->assertContains("collections.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$this->assertEquals('available', $response['data']['payload']['status']);
@ -179,13 +210,12 @@ class RealtimeConsoleClientTest extends Scope
*/
public function testDeleteIndex(array $data)
{
$user = $this->getUser();
$session = $user['session'] ?? '';
$actorsId = $data['actorsId'];
$projectId = 'console';
$client = $this->getWebsocket(['console'], [
'origin' => 'http://localhost',
'cookie' => 'a_session_console='. $this->getRoot()['session'],
'cookie' => 'a_session_console=' . $this->getRoot()['session'],
], $projectId);
$response = json_decode($client->receive(), true);
@ -201,13 +231,13 @@ class RealtimeConsoleClientTest extends Scope
/**
* Test Delete Index
*/
$attribute = $this->client->call(Client::METHOD_DELETE, '/database/collections/' . $data['actorsId'] . '/indexes/key_name', array_merge([
$attribute = $this->client->call(Client::METHOD_DELETE, '/database/collections/' . $actorsId . '/indexes/key_name', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
$this->assertEquals($attribute['headers']['status-code'], 204);
$indexKey = 'key_name';
$response = json_decode($client->receive(), true);
$this->assertArrayHasKey('type', $response);
@ -217,7 +247,16 @@ class RealtimeConsoleClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(1, $response['data']['channels']);
$this->assertContains('console', $response['data']['channels']);
$this->assertEquals('database.indexes.delete', $response['data']['event']);
$this->assertContains("collections.{$actorsId}.indexes.{$actorsId}_{$indexKey}.delete", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.indexes.*.delete", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.indexes.{$actorsId}_{$indexKey}", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.indexes.*", $response['data']['events']);
$this->assertContains("collections.{$actorsId}", $response['data']['events']);
$this->assertContains("collections.*.indexes.{$actorsId}_{$indexKey}.delete", $response['data']['events']);
$this->assertContains("collections.*.indexes.*.delete", $response['data']['events']);
$this->assertContains("collections.*.indexes.{$actorsId}_{$indexKey}", $response['data']['events']);
$this->assertContains("collections.*.indexes.*", $response['data']['events']);
$this->assertContains("collections.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$client->close();
@ -230,13 +269,12 @@ class RealtimeConsoleClientTest extends Scope
*/
public function testDeleteAttribute(array $data)
{
$user = $this->getUser();
$session = $user['session'] ?? '';
$actorsId = $data['actorsId'];
$projectId = 'console';
$client = $this->getWebsocket(['console'], [
'origin' => 'http://localhost',
'cookie' => 'a_session_console='. $this->getRoot()['session'],
'cookie' => 'a_session_console=' . $this->getRoot()['session'],
], $projectId);
$response = json_decode($client->receive(), true);
@ -258,7 +296,7 @@ class RealtimeConsoleClientTest extends Scope
], $this->getHeaders()));
$this->assertEquals($attribute['headers']['status-code'], 204);
$attributeKey = 'name';
$response = json_decode($client->receive(), true);
$this->assertArrayHasKey('type', $response);
@ -268,9 +306,18 @@ class RealtimeConsoleClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(1, $response['data']['channels']);
$this->assertContains('console', $response['data']['channels']);
$this->assertEquals('database.attributes.delete', $response['data']['event']);
$this->assertContains("collections.{$actorsId}.attributes.{$actorsId}_{$attributeKey}.delete", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.attributes.*.delete", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.attributes.{$actorsId}_{$attributeKey}", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.attributes.*", $response['data']['events']);
$this->assertContains("collections.{$actorsId}", $response['data']['events']);
$this->assertContains("collections.*.attributes.{$actorsId}_{$attributeKey}.delete", $response['data']['events']);
$this->assertContains("collections.*.attributes.*.delete", $response['data']['events']);
$this->assertContains("collections.*.attributes.{$actorsId}_{$attributeKey}", $response['data']['events']);
$this->assertContains("collections.*.attributes.*", $response['data']['events']);
$this->assertContains("collections.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$client->close();
}
}
}

View file

@ -25,7 +25,7 @@ class RealtimeCustomClientTest extends Scope
$headers = [
'origin' => 'http://localhost',
'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session
];
$client = $this->getWebsocket(['documents'], $headers);
@ -240,7 +240,7 @@ class RealtimeCustomClientTest extends Scope
$client = $this->getWebsocket(['account'], [
'origin' => 'http://localhost',
'cookie' => 'a_session_'.$projectId.'=' . $session
'cookie' => 'a_session_' . $projectId . '=' . $session
]);
$response = json_decode($client->receive(), true);
@ -278,7 +278,12 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertContains('account', $response['data']['channels']);
$this->assertContains('account.' . $userId, $response['data']['channels']);
$this->assertEquals("users.{$userId}.update.name", $response['data']['event']);
$this->assertContains("users.{$userId}.update.name", $response['data']['events']);
$this->assertContains("users.{$userId}.update", $response['data']['events']);
$this->assertContains("users.{$userId}", $response['data']['events']);
$this->assertContains("users.*.update.name", $response['data']['events']);
$this->assertContains("users.*.update", $response['data']['events']);
$this->assertContains("users.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$this->assertEquals($name, $response['data']['payload']['name']);
@ -291,7 +296,7 @@ class RealtimeCustomClientTest extends Scope
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'cookie' => 'a_session_'.$projectId.'=' . $session,
'cookie' => 'a_session_' . $projectId . '=' . $session,
]), [
'password' => 'new-password',
'oldPassword' => 'password',
@ -307,7 +312,12 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertContains('account', $response['data']['channels']);
$this->assertContains('account.' . $userId, $response['data']['channels']);
$this->assertEquals("users.{$userId}.update.password", $response['data']['event']);
$this->assertContains("users.{$userId}.update.password", $response['data']['events']);
$this->assertContains("users.{$userId}.update", $response['data']['events']);
$this->assertContains("users.{$userId}", $response['data']['events']);
$this->assertContains("users.*.update.password", $response['data']['events']);
$this->assertContains("users.*.update", $response['data']['events']);
$this->assertContains("users.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$this->assertEquals($name, $response['data']['payload']['name']);
@ -319,7 +329,7 @@ class RealtimeCustomClientTest extends Scope
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'cookie' => 'a_session_'.$projectId.'=' . $session,
'cookie' => 'a_session_' . $projectId . '=' . $session,
]), [
'email' => 'torsten@appwrite.io',
'password' => 'new-password',
@ -335,9 +345,13 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertContains('account', $response['data']['channels']);
$this->assertContains('account.' . $userId, $response['data']['channels']);
$this->assertEquals("users.{$userId}.update.email", $response['data']['event']);
$this->assertContains("users.{$userId}.update.email", $response['data']['events']);
$this->assertContains("users.{$userId}.update", $response['data']['events']);
$this->assertContains("users.{$userId}", $response['data']['events']);
$this->assertContains("users.*.update.email", $response['data']['events']);
$this->assertContains("users.*.update", $response['data']['events']);
$this->assertContains("users.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$this->assertEquals('torsten@appwrite.io', $response['data']['payload']['email']);
/**
@ -347,11 +361,11 @@ class RealtimeCustomClientTest extends Scope
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'cookie' => 'a_session_'.$projectId.'=' . $session,
'cookie' => 'a_session_' . $projectId . '=' . $session,
]), [
'url' => 'http://localhost/verification',
]);
$verificationId = $verification['body']['$id'];
$response = json_decode($client->receive(), true);
$this->assertArrayHasKey('type', $response);
@ -362,7 +376,16 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertContains('account', $response['data']['channels']);
$this->assertContains('account.' . $userId, $response['data']['channels']);
$this->assertEquals("users.{$userId}.verification.{$verification['body']['$id']}.create", $response['data']['event']);
$this->assertContains("users.{$userId}.verification.{$verificationId}.create", $response['data']['events']);
$this->assertContains("users.{$userId}.verification.{$verificationId}", $response['data']['events']);
$this->assertContains("users.{$userId}.verification.*.create", $response['data']['events']);
$this->assertContains("users.{$userId}.verification.*", $response['data']['events']);
$this->assertContains("users.{$userId}", $response['data']['events']);
$this->assertContains("users.*.verification.{$verificationId}.create", $response['data']['events']);
$this->assertContains("users.*.verification.{$verificationId}", $response['data']['events']);
$this->assertContains("users.*.verification.*.create", $response['data']['events']);
$this->assertContains("users.*.verification.*", $response['data']['events']);
$this->assertContains("users.*", $response['data']['events']);
$lastEmail = $this->getLastEmail();
$verification = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256);
@ -374,7 +397,7 @@ class RealtimeCustomClientTest extends Scope
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'cookie' => 'a_session_'.$projectId.'=' . $session,
'cookie' => 'a_session_' . $projectId . '=' . $session,
]), [
'userId' => $userId,
'secret' => $verification,
@ -390,8 +413,16 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertContains('account', $response['data']['channels']);
$this->assertContains('account.' . $userId, $response['data']['channels']);
$this->assertEquals("users.{$userId}.verification.{$verification['body']['$id']}.update", $response['data']['event']);
$this->assertContains("users.{$userId}.verification.{$verificationId}.update", $response['data']['events']);
$this->assertContains("users.{$userId}.verification.{$verificationId}", $response['data']['events']);
$this->assertContains("users.{$userId}.verification.*.update", $response['data']['events']);
$this->assertContains("users.{$userId}.verification.*", $response['data']['events']);
$this->assertContains("users.{$userId}", $response['data']['events']);
$this->assertContains("users.*.verification.{$verificationId}.update", $response['data']['events']);
$this->assertContains("users.*.verification.{$verificationId}", $response['data']['events']);
$this->assertContains("users.*.verification.*.update", $response['data']['events']);
$this->assertContains("users.*.verification.*", $response['data']['events']);
$this->assertContains("users.*", $response['data']['events']);
/**
* Test Acoount Prefs Update
*/
@ -399,7 +430,7 @@ class RealtimeCustomClientTest extends Scope
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'cookie' => 'a_session_'.$projectId.'=' . $session,
'cookie' => 'a_session_' . $projectId . '=' . $session,
]), [
'prefs' => [
'prefKey1' => 'prefValue1',
@ -417,7 +448,12 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertContains('account', $response['data']['channels']);
$this->assertContains('account.' . $userId, $response['data']['channels']);
$this->assertEquals("users.{$userId}.update.prefs", $response['data']['event']);
$this->assertContains("users.{$userId}.update.prefs", $response['data']['events']);
$this->assertContains("users.{$userId}.update", $response['data']['events']);
$this->assertContains("users.{$userId}", $response['data']['events']);
$this->assertContains("users.*.update.prefs", $response['data']['events']);
$this->assertContains("users.*.update", $response['data']['events']);
$this->assertContains("users.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
/**
@ -432,7 +468,7 @@ class RealtimeCustomClientTest extends Scope
'password' => 'new-password',
]);
$sessionNew = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_'.$projectId];
$sessionNew = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $projectId];
$sessionNewId = $response['body']['$id'];
$response = json_decode($client->receive(), true);
@ -445,17 +481,26 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertContains('account', $response['data']['channels']);
$this->assertContains('account.' . $userId, $response['data']['channels']);
$this->assertEquals("users.{$userId}.sessions.{$sessionNewId}.create", $response['data']['event']);
$this->assertContains("users.{$userId}.sessions.{$sessionNewId}.create", $response['data']['events']);
$this->assertContains("users.{$userId}.sessions.{$sessionNewId}", $response['data']['events']);
$this->assertContains("users.{$userId}.sessions.*.create", $response['data']['events']);
$this->assertContains("users.{$userId}.sessions.*", $response['data']['events']);
$this->assertContains("users.{$userId}", $response['data']['events']);
$this->assertContains("users.*.sessions.{$sessionNewId}.create", $response['data']['events']);
$this->assertContains("users.*.sessions.{$sessionNewId}", $response['data']['events']);
$this->assertContains("users.*.sessions.*.create", $response['data']['events']);
$this->assertContains("users.*.sessions.*", $response['data']['events']);
$this->assertContains("users.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
/**
* Test Account Session Delete
*/
$this->client->call(Client::METHOD_DELETE, '/account/sessions/'.$sessionNewId, array_merge([
$this->client->call(Client::METHOD_DELETE, '/account/sessions/' . $sessionNewId, array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'cookie' => 'a_session_'.$projectId.'=' . $sessionNew,
'cookie' => 'a_session_' . $projectId . '=' . $sessionNew,
]));
$response = json_decode($client->receive(), true);
@ -468,7 +513,16 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertContains('account', $response['data']['channels']);
$this->assertContains('account.' . $userId, $response['data']['channels']);
$this->assertEquals("users.{$userId}.sessions.{$sessionNewId}.delete", $response['data']['event']);
$this->assertContains("users.{$userId}.sessions.{$sessionNewId}.delete", $response['data']['events']);
$this->assertContains("users.{$userId}.sessions.{$sessionNewId}", $response['data']['events']);
$this->assertContains("users.{$userId}.sessions.*.delete", $response['data']['events']);
$this->assertContains("users.{$userId}.sessions.*", $response['data']['events']);
$this->assertContains("users.{$userId}", $response['data']['events']);
$this->assertContains("users.*.sessions.{$sessionNewId}.delete", $response['data']['events']);
$this->assertContains("users.*.sessions.{$sessionNewId}", $response['data']['events']);
$this->assertContains("users.*.sessions.*.delete", $response['data']['events']);
$this->assertContains("users.*.sessions.*", $response['data']['events']);
$this->assertContains("users.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
/**
@ -496,7 +550,16 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertContains('account', $response['data']['channels']);
$this->assertContains('account.' . $userId, $response['data']['channels']);
$this->assertEquals("users.{$userId}.recovery.{$recoveryId}.create", $response['data']['event']);
$this->assertContains("users.{$userId}.recovery.{$recoveryId}.create", $response['data']['events']);
$this->assertContains("users.{$userId}.recovery.{$recoveryId}", $response['data']['events']);
$this->assertContains("users.{$userId}.recovery.*.create", $response['data']['events']);
$this->assertContains("users.{$userId}.recovery.*", $response['data']['events']);
$this->assertContains("users.{$userId}", $response['data']['events']);
$this->assertContains("users.*.recovery.{$recoveryId}.create", $response['data']['events']);
$this->assertContains("users.*.recovery.{$recoveryId}", $response['data']['events']);
$this->assertContains("users.*.recovery.*.create", $response['data']['events']);
$this->assertContains("users.*.recovery.*", $response['data']['events']);
$this->assertContains("users.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$response = $this->client->call(Client::METHOD_PUT, '/account/recovery', array_merge([
@ -520,7 +583,16 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertContains('account', $response['data']['channels']);
$this->assertContains('account.' . $userId, $response['data']['channels']);
$this->assertEquals("users.{$userId}.recovery.{$recoveryId}.update", $response['data']['event']);
$this->assertContains("users.{$userId}.recovery.{$recoveryId}.update", $response['data']['events']);
$this->assertContains("users.{$userId}.recovery.{$recoveryId}", $response['data']['events']);
$this->assertContains("users.{$userId}.recovery.*.update", $response['data']['events']);
$this->assertContains("users.{$userId}.recovery.*", $response['data']['events']);
$this->assertContains("users.{$userId}", $response['data']['events']);
$this->assertContains("users.*.recovery.{$recoveryId}.update", $response['data']['events']);
$this->assertContains("users.*.recovery.{$recoveryId}", $response['data']['events']);
$this->assertContains("users.*.recovery.*.update", $response['data']['events']);
$this->assertContains("users.*.recovery.*", $response['data']['events']);
$this->assertContains("users.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$client->close();
@ -534,7 +606,7 @@ class RealtimeCustomClientTest extends Scope
$client = $this->getWebsocket(['documents', 'collections'], [
'origin' => 'http://localhost',
'cookie' => 'a_session_'.$projectId.'=' . $session
'cookie' => 'a_session_' . $projectId . '=' . $session
]);
$response = json_decode($client->receive(), true);
@ -564,9 +636,9 @@ class RealtimeCustomClientTest extends Scope
'permission' => 'document'
]);
$data = ['actorsId' => $actors['body']['$id']];
$actorsId = $actors['body']['$id'];
$name = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['actorsId'] . '/attributes/string', array_merge([
$name = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actorsId . '/attributes/string', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
@ -587,7 +659,7 @@ class RealtimeCustomClientTest extends Scope
/**
* Test Document Create
*/
$document = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['actorsId'] . '/documents', array_merge([
$document = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actorsId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -601,6 +673,8 @@ class RealtimeCustomClientTest extends Scope
$response = json_decode($client->receive(), true);
$documentId = $document['body']['$id'];
$this->assertArrayHasKey('type', $response);
$this->assertArrayHasKey('data', $response);
$this->assertEquals('event', $response['type']);
@ -608,18 +682,25 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(3, $response['data']['channels']);
$this->assertContains('documents', $response['data']['channels']);
$this->assertContains('collections.' . $data['actorsId'] . '.documents.' . $document['body']['$id'], $response['data']['channels']);
$this->assertContains('collections.' . $actors['body']['$id'] . '.documents', $response['data']['channels']);
$this->assertEquals("collections.{$data['actorsId']}.documents.{$document['body']['$id']}.create", $response['data']['event']);
$this->assertContains('collections.' . $actorsId . '.documents.' . $documentId, $response['data']['channels']);
$this->assertContains('collections.' . $actorsId . '.documents', $response['data']['channels']);
$this->assertContains("collections.{$actorsId}.documents.{$documentId}.create", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.documents.{$documentId}", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.documents.*.create", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.documents.*", $response['data']['events']);
$this->assertContains("collections.{$actorsId}", $response['data']['events']);
$this->assertContains("collections.*.documents.{$documentId}.create", $response['data']['events']);
$this->assertContains("collections.*.documents.{$documentId}", $response['data']['events']);
$this->assertContains("collections.*.documents.*.create", $response['data']['events']);
$this->assertContains("collections.*.documents.*", $response['data']['events']);
$this->assertContains("collections.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$this->assertEquals($response['data']['payload']['name'], 'Chris Evans');
$data['documentId'] = $document['body']['$id'];
/**
* Test Document Update
*/
$document = $this->client->call(Client::METHOD_PATCH, '/database/collections/' . $data['actorsId'] . '/documents/' . $data['documentId'], array_merge([
$document = $this->client->call(Client::METHOD_PATCH, '/database/collections/' . $actorsId . '/documents/' . $documentId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -640,9 +721,18 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(3, $response['data']['channels']);
$this->assertContains('documents', $response['data']['channels']);
$this->assertContains('collections.' . $data['actorsId'] . '.documents.' . $data['documentId'], $response['data']['channels']);
$this->assertContains('collections.' . $data['actorsId'] . '.documents', $response['data']['channels']);
$this->assertEquals("collections.{$data['actorsId']}.documents.{$data['documentId']}.update", $response['data']['event']);
$this->assertContains("collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']);
$this->assertContains("collections.{$actorsId}.documents", $response['data']['channels']);
$this->assertContains("collections.{$actorsId}.documents.{$documentId}.update", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.documents.{$documentId}", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.documents.*.update", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.documents.*", $response['data']['events']);
$this->assertContains("collections.{$actorsId}", $response['data']['events']);
$this->assertContains("collections.*.documents.{$documentId}.update", $response['data']['events']);
$this->assertContains("collections.*.documents.{$documentId}", $response['data']['events']);
$this->assertContains("collections.*.documents.*.update", $response['data']['events']);
$this->assertContains("collections.*.documents.*", $response['data']['events']);
$this->assertContains("collections.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$this->assertEquals($response['data']['payload']['name'], 'Chris Evans 2');
@ -650,7 +740,7 @@ class RealtimeCustomClientTest extends Scope
/**
* Test Document Delete
*/
$document = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['actorsId'] . '/documents', array_merge([
$document = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actorsId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -664,7 +754,9 @@ class RealtimeCustomClientTest extends Scope
$client->receive();
$this->client->call(Client::METHOD_DELETE, '/database/collections/' . $data['actorsId'] . '/documents/' . $document['body']['$id'], array_merge([
$documentId = $document['body']['$id'];
$this->client->call(Client::METHOD_DELETE, '/database/collections/' . $actorsId . '/documents/' . $documentId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
@ -678,9 +770,18 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(3, $response['data']['channels']);
$this->assertContains('documents', $response['data']['channels']);
$this->assertContains('collections.' . $data['actorsId'] . '.documents.' . $document['body']['$id'], $response['data']['channels']);
$this->assertContains('collections.' . $data['actorsId'] . '.documents', $response['data']['channels']);
$this->assertEquals("collections.{$data['actorsId']}.documents.{$document['body']['$id']}.delete", $response['data']['event']);
$this->assertContains("collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']);
$this->assertContains("collections.{$actorsId}.documents", $response['data']['channels']);
$this->assertContains("collections.{$actorsId}.documents.{$documentId}.delete", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.documents.{$documentId}", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.documents.*.delete", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.documents.*", $response['data']['events']);
$this->assertContains("collections.{$actorsId}", $response['data']['events']);
$this->assertContains("collections.*.documents.{$documentId}.delete", $response['data']['events']);
$this->assertContains("collections.*.documents.{$documentId}", $response['data']['events']);
$this->assertContains("collections.*.documents.*.delete", $response['data']['events']);
$this->assertContains("collections.*.documents.*", $response['data']['events']);
$this->assertContains("collections.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$this->assertEquals($response['data']['payload']['name'], 'Bradley Cooper');
@ -695,7 +796,7 @@ class RealtimeCustomClientTest extends Scope
$client = $this->getWebsocket(['documents', 'collections'], [
'origin' => 'http://localhost',
'cookie' => 'a_session_'.$projectId.'=' . $session
'cookie' => 'a_session_' . $projectId . '=' . $session
]);
$response = json_decode($client->receive(), true);
@ -725,9 +826,9 @@ class RealtimeCustomClientTest extends Scope
'permission' => 'collection'
]);
$data = ['actorsId' => $actors['body']['$id']];
$actorsId = $actors['body']['$id'];
$name = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['actorsId'] . '/attributes/string', array_merge([
$name = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actorsId . '/attributes/string', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
@ -748,7 +849,7 @@ class RealtimeCustomClientTest extends Scope
/**
* Test Document Create
*/
$document = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['actorsId'] . '/documents', array_merge([
$document = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actorsId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -760,6 +861,8 @@ class RealtimeCustomClientTest extends Scope
'write' => [],
]);
$documentId = $document['body']['$id'];
$response = json_decode($client->receive(), true);
$this->assertArrayHasKey('type', $response);
@ -769,18 +872,25 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(3, $response['data']['channels']);
$this->assertContains('documents', $response['data']['channels']);
$this->assertContains('collections.' . $data['actorsId'] . '.documents.' . $document['body']['$id'], $response['data']['channels']);
$this->assertContains('collections.' . $actors['body']['$id'] . '.documents', $response['data']['channels']);
$this->assertEquals("collections.{$data['actorsId']}.documents.{$document['body']['$id']}.create", $response['data']['event']);
$this->assertContains("collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']);
$this->assertContains("collections.{$actorsId}.documents", $response['data']['channels']);
$this->assertContains("collections.{$actorsId}.documents.{$documentId}.create", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.documents.{$documentId}", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.documents.*.create", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.documents.*", $response['data']['events']);
$this->assertContains("collections.{$actorsId}", $response['data']['events']);
$this->assertContains("collections.*.documents.{$documentId}.create", $response['data']['events']);
$this->assertContains("collections.*.documents.{$documentId}", $response['data']['events']);
$this->assertContains("collections.*.documents.*.create", $response['data']['events']);
$this->assertContains("collections.*.documents.*", $response['data']['events']);
$this->assertContains("collections.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$this->assertEquals($response['data']['payload']['name'], 'Chris Evans');
$data['documentId'] = $document['body']['$id'];
/**
* Test Document Update
*/
$document = $this->client->call(Client::METHOD_PATCH, '/database/collections/' . $data['actorsId'] . '/documents/' . $data['documentId'], array_merge([
$document = $this->client->call(Client::METHOD_PATCH, '/database/collections/' . $actorsId . '/documents/' . $documentId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -800,9 +910,18 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(3, $response['data']['channels']);
$this->assertContains('documents', $response['data']['channels']);
$this->assertContains('collections.' . $data['actorsId'] . '.documents.' . $data['documentId'], $response['data']['channels']);
$this->assertContains('collections.' . $data['actorsId'] . '.documents', $response['data']['channels']);
$this->assertEquals("collections.{$data['actorsId']}.documents.{$document['body']['$id']}.update", $response['data']['event']);
$this->assertContains("collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']);
$this->assertContains("collections.{$actorsId}.documents", $response['data']['channels']);
$this->assertContains("collections.{$actorsId}.documents.{$documentId}.update", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.documents.{$documentId}", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.documents.*.update", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.documents.*", $response['data']['events']);
$this->assertContains("collections.{$actorsId}", $response['data']['events']);
$this->assertContains("collections.*.documents.{$documentId}.update", $response['data']['events']);
$this->assertContains("collections.*.documents.{$documentId}", $response['data']['events']);
$this->assertContains("collections.*.documents.*.update", $response['data']['events']);
$this->assertContains("collections.*.documents.*", $response['data']['events']);
$this->assertContains("collections.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$this->assertEquals($response['data']['payload']['name'], 'Chris Evans 2');
@ -810,7 +929,7 @@ class RealtimeCustomClientTest extends Scope
/**
* Test Document Delete
*/
$document = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['actorsId'] . '/documents', array_merge([
$document = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actorsId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -822,9 +941,11 @@ class RealtimeCustomClientTest extends Scope
'write' => [],
]);
$documentId = $document['body']['$id'];
$client->receive();
$this->client->call(Client::METHOD_DELETE, '/database/collections/' . $data['actorsId'] . '/documents/' . $document['body']['$id'], array_merge([
$this->client->call(Client::METHOD_DELETE, '/database/collections/' . $actorsId . '/documents/' . $documentId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
@ -838,9 +959,18 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(3, $response['data']['channels']);
$this->assertContains('documents', $response['data']['channels']);
$this->assertContains('collections.' . $data['actorsId'] . '.documents.' . $document['body']['$id'], $response['data']['channels']);
$this->assertContains('collections.' . $data['actorsId'] . '.documents', $response['data']['channels']);
$this->assertEquals("collections.{$data['actorsId']}.documents.{$document['body']['$id']}.delete", $response['data']['event']);
$this->assertContains("collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']);
$this->assertContains("collections.{$actorsId}.documents", $response['data']['channels']);
$this->assertContains("collections.{$actorsId}.documents.{$documentId}.delete", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.documents.{$documentId}", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.documents.*.delete", $response['data']['events']);
$this->assertContains("collections.{$actorsId}.documents.*", $response['data']['events']);
$this->assertContains("collections.{$actorsId}", $response['data']['events']);
$this->assertContains("collections.*.documents.{$documentId}.delete", $response['data']['events']);
$this->assertContains("collections.*.documents.{$documentId}", $response['data']['events']);
$this->assertContains("collections.*.documents.*.delete", $response['data']['events']);
$this->assertContains("collections.*.documents.*", $response['data']['events']);
$this->assertContains("collections.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$this->assertEquals($response['data']['payload']['name'], 'Bradley Cooper');
@ -855,7 +985,7 @@ class RealtimeCustomClientTest extends Scope
$client = $this->getWebsocket(['files'], [
'origin' => 'http://localhost',
'cookie' => 'a_session_'.$projectId.'=' . $session
'cookie' => 'a_session_' . $projectId . '=' . $session
]);
$response = json_decode($client->receive(), true);
@ -883,11 +1013,12 @@ class RealtimeCustomClientTest extends Scope
'permission' => 'bucket'
]);
$data = ['bucketId' => $bucket1['body']['$id']];
$bucketId = $bucket1['body']['$id'];
/**
* Test File Create
*/
$file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([
$file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([
'content-type' => 'multipart/form-data',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -897,6 +1028,8 @@ class RealtimeCustomClientTest extends Scope
'write' => ['role:all'],
]);
$fileId = $file['body']['$id'];
$response = json_decode($client->receive(), true);
$this->assertArrayHasKey('type', $response);
@ -906,17 +1039,26 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(3, $response['data']['channels']);
$this->assertContains('files', $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->assertEquals("buckets.{$data['bucketId']}.files.{$file['body']['$id']}.create", $response['data']['event']);
$this->assertContains("buckets.{$bucketId}.files.{$fileId}", $response['data']['channels']);
$this->assertContains("buckets.{$bucketId}.files", $response['data']['channels']);
$this->assertContains("buckets.{$bucketId}.files.{$fileId}.create", $response['data']['events']);
$this->assertContains("buckets.{$bucketId}.files.{$fileId}", $response['data']['events']);
$this->assertContains("buckets.{$bucketId}.files.*.create", $response['data']['events']);
$this->assertContains("buckets.{$bucketId}.files.*", $response['data']['events']);
$this->assertContains("buckets.{$bucketId}", $response['data']['events']);
$this->assertContains("buckets.*.files.{$fileId}.create", $response['data']['events']);
$this->assertContains("buckets.*.files.{$fileId}", $response['data']['events']);
$this->assertContains("buckets.*.files.*.create", $response['data']['events']);
$this->assertContains("buckets.*.files.*", $response['data']['events']);
$this->assertContains("buckets.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$data['fileId'] = $file['body']['$id'];
$fileId = $file['body']['$id'];
/**
* Test File Update
*/
$this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $data['bucketId'] . '/files/' . $data['fileId'], array_merge([
$this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -933,15 +1075,24 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(3, $response['data']['channels']);
$this->assertContains('files', $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->assertEquals("buckets.{$data['bucketId']}.files.{$file['body']['$id']}.update", $response['data']['event']);
$this->assertContains("buckets.{$bucketId}.files.{$fileId}", $response['data']['channels']);
$this->assertContains("buckets.{$bucketId}.files", $response['data']['channels']);
$this->assertContains("buckets.{$bucketId}.files.{$fileId}.update", $response['data']['events']);
$this->assertContains("buckets.{$bucketId}.files.{$fileId}", $response['data']['events']);
$this->assertContains("buckets.{$bucketId}.files.*.update", $response['data']['events']);
$this->assertContains("buckets.{$bucketId}.files.*", $response['data']['events']);
$this->assertContains("buckets.{$bucketId}", $response['data']['events']);
$this->assertContains("buckets.*.files.{$fileId}.update", $response['data']['events']);
$this->assertContains("buckets.*.files.{$fileId}", $response['data']['events']);
$this->assertContains("buckets.*.files.*.update", $response['data']['events']);
$this->assertContains("buckets.*.files.*", $response['data']['events']);
$this->assertContains("buckets.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
/**
* Test File Delete
*/
$this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $data['bucketId'] . '/files/' . $data['fileId'], array_merge([
$this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
@ -955,9 +1106,18 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(3, $response['data']['channels']);
$this->assertContains('files', $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->assertEquals("buckets.{$data['bucketId']}.files.{$file['body']['$id']}.delete", $response['data']['event']);
$this->assertContains("buckets.{$bucketId}.files.{$fileId}", $response['data']['channels']);
$this->assertContains("buckets.{$bucketId}.files", $response['data']['channels']);
$this->assertContains("buckets.{$bucketId}.files.{$fileId}.delete", $response['data']['events']);
$this->assertContains("buckets.{$bucketId}.files.{$fileId}", $response['data']['events']);
$this->assertContains("buckets.{$bucketId}.files.*.delete", $response['data']['events']);
$this->assertContains("buckets.{$bucketId}.files.*", $response['data']['events']);
$this->assertContains("buckets.{$bucketId}", $response['data']['events']);
$this->assertContains("buckets.*.files.{$fileId}.delete", $response['data']['events']);
$this->assertContains("buckets.*.files.{$fileId}", $response['data']['events']);
$this->assertContains("buckets.*.files.*.delete", $response['data']['events']);
$this->assertContains("buckets.*.files.*", $response['data']['events']);
$this->assertContains("buckets.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$client->close();
@ -971,7 +1131,7 @@ class RealtimeCustomClientTest extends Scope
$client = $this->getWebsocket(['executions'], [
'origin' => 'http://localhost',
'cookie' => 'a_session_'.$projectId.'=' . $session
'cookie' => 'a_session_' . $projectId . '=' . $session
]);
$response = json_decode($client->receive(), true);
@ -1007,11 +1167,12 @@ class RealtimeCustomClientTest extends Scope
$folder = 'timeout';
$stderr = '';
$stdout= '';
$code = realpath(__DIR__ . '/../../../resources/functions'). "/$folder/code.tar.gz";
Console::execute('cd '.realpath(__DIR__ . "/../../../resources/functions") . "/$folder && tar --exclude code.tar.gz -czf code.tar.gz .", '', $stdout, $stderr);
$stdout = '';
$code = realpath(__DIR__ . '/../../../resources/functions') . "/{$folder}/code.tar.gz";
$deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([
Console::execute('cd ' . realpath(__DIR__ . "/../../../resources/functions") . "/{$folder} && tar --exclude code.tar.gz -czf code.tar.gz .", '', $stdout, $stderr);
$deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([
'content-type' => 'multipart/form-data',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
@ -1028,7 +1189,7 @@ class RealtimeCustomClientTest extends Scope
// Wait for deployment to be built.
sleep(5);
$response = $this->client->call(Client::METHOD_PATCH, '/functions/'.$functionId.'/deployments/'.$deploymentId, array_merge([
$response = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployments/' . $deploymentId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
@ -1037,7 +1198,7 @@ class RealtimeCustomClientTest extends Scope
$this->assertEquals($response['headers']['status-code'], 200);
$this->assertNotEmpty($response['body']['$id']);
$execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([
$execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id']
], $this->getHeaders()), []);
@ -1048,6 +1209,8 @@ class RealtimeCustomClientTest extends Scope
$response = json_decode($client->receive(), true);
$responseUpdate = json_decode($client->receive(), true);
$executionId = $execution['body']['$id'];
$this->assertArrayHasKey('type', $response);
$this->assertArrayHasKey('data', $response);
$this->assertEquals('event', $response['type']);
@ -1056,9 +1219,18 @@ class RealtimeCustomClientTest extends Scope
$this->assertCount(4, $response['data']['channels']);
$this->assertContains('console', $response['data']['channels']);
$this->assertContains('executions', $response['data']['channels']);
$this->assertContains('executions.' . $execution['body']['$id'], $response['data']['channels']);
$this->assertContains('functions.' . $execution['body']['functionId'], $response['data']['channels']);
$this->assertEquals("functions.{$functionId}.executions.{$execution['body']['$id']}.create", $response['data']['event']);
$this->assertContains("executions.{$executionId}", $response['data']['channels']);
$this->assertContains("functions.{$functionId}", $response['data']['channels']);
$this->assertContains("functions.{$functionId}.executions.{$executionId}.create", $response['data']['events']);
$this->assertContains("functions.{$functionId}.executions.{$executionId}", $response['data']['events']);
$this->assertContains("functions.{$functionId}.executions.*.create", $response['data']['events']);
$this->assertContains("functions.{$functionId}.executions.*", $response['data']['events']);
$this->assertContains("functions.{$functionId}", $response['data']['events']);
$this->assertContains("functions.*.executions.{$executionId}.create", $response['data']['events']);
$this->assertContains("functions.*.executions.{$executionId}", $response['data']['events']);
$this->assertContains("functions.*.executions.*.create", $response['data']['events']);
$this->assertContains("functions.*.executions.*", $response['data']['events']);
$this->assertContains("functions.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$this->assertArrayHasKey('type', $responseUpdate);
@ -1069,15 +1241,24 @@ class RealtimeCustomClientTest extends Scope
$this->assertCount(4, $responseUpdate['data']['channels']);
$this->assertContains('console', $responseUpdate['data']['channels']);
$this->assertContains('executions', $responseUpdate['data']['channels']);
$this->assertContains('executions.' . $execution['body']['$id'], $responseUpdate['data']['channels']);
$this->assertContains('functions.' . $execution['body']['functionId'], $responseUpdate['data']['channels']);
$this->assertEquals("functions.{$functionId}.executions.{$execution['body']['$id']}.update", $responseUpdate['data']['event']);
$this->assertContains("executions.{$executionId}", $responseUpdate['data']['channels']);
$this->assertContains("functions.{$functionId}", $responseUpdate['data']['channels']);
$this->assertContains("functions.{$functionId}.executions.{$executionId}.update", $responseUpdate['data']['events']);
$this->assertContains("functions.{$functionId}.executions.{$executionId}", $responseUpdate['data']['events']);
$this->assertContains("functions.{$functionId}.executions.*.update", $responseUpdate['data']['events']);
$this->assertContains("functions.{$functionId}.executions.*", $responseUpdate['data']['events']);
$this->assertContains("functions.{$functionId}", $responseUpdate['data']['events']);
$this->assertContains("functions.*.executions.{$executionId}.update", $responseUpdate['data']['events']);
$this->assertContains("functions.*.executions.{$executionId}", $responseUpdate['data']['events']);
$this->assertContains("functions.*.executions.*.update", $responseUpdate['data']['events']);
$this->assertContains("functions.*.executions.*", $responseUpdate['data']['events']);
$this->assertContains("functions.*", $responseUpdate['data']['events']);
$this->assertNotEmpty($responseUpdate['data']['payload']);
$client->close();
// Cleanup : Delete function
$response = $this->client->call(Client::METHOD_DELETE, '/functions/'. $functionId, [
$response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
@ -1094,7 +1275,7 @@ class RealtimeCustomClientTest extends Scope
$client = $this->getWebsocket(['teams'], [
'origin' => 'http://localhost',
'cookie' => 'a_session_'.$projectId.'=' . $session
'cookie' => 'a_session_' . $projectId . '=' . $session
]);
$response = json_decode($client->receive(), true);
@ -1133,14 +1314,17 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(2, $response['data']['channels']);
$this->assertContains('teams', $response['data']['channels']);
$this->assertContains('teams.' . $teamId, $response['data']['channels']);
$this->assertEquals("teams.{$teamId}.create", $response['data']['event']);
$this->assertContains("teams.{$teamId}", $response['data']['channels']);
$this->assertContains("teams.{$teamId}.create", $response['data']['events']);
$this->assertContains("teams.{$teamId}", $response['data']['events']);
$this->assertContains("teams.*.create", $response['data']['events']);
$this->assertContains("teams.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
/**
* Test Team Update
*/
$team = $this->client->call(Client::METHOD_PUT, '/teams/'.$teamId, array_merge([
$team = $this->client->call(Client::METHOD_PUT, '/teams/' . $teamId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), [
@ -1159,8 +1343,11 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(2, $response['data']['channels']);
$this->assertContains('teams', $response['data']['channels']);
$this->assertContains('teams.' . $teamId, $response['data']['channels']);
$this->assertEquals("teams.{$teamId}.update", $response['data']['event']);
$this->assertContains("teams.{$teamId}", $response['data']['channels']);
$this->assertContains("teams.{$teamId}.update", $response['data']['events']);
$this->assertContains("teams.{$teamId}", $response['data']['events']);
$this->assertContains("teams.*.update", $response['data']['events']);
$this->assertContains("teams.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$client->close();
@ -1181,7 +1368,7 @@ class RealtimeCustomClientTest extends Scope
$client = $this->getWebsocket(['memberships'], [
'origin' => 'http://localhost',
'cookie' => 'a_session_'.$projectId.'='.$session
'cookie' => 'a_session_' . $projectId . '=' . $session
]);
$response = json_decode($client->receive(), true);
@ -1195,7 +1382,7 @@ class RealtimeCustomClientTest extends Scope
$this->assertNotEmpty($response['data']['user']);
$this->assertEquals($user['$id'], $response['data']['user']['$id']);
$response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamId.'/memberships', array_merge([
$response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamId . '/memberships', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
@ -1206,7 +1393,7 @@ class RealtimeCustomClientTest extends Scope
* Test Update Membership
*/
$roles = ['admin', 'editor', 'uncle'];
$this->client->call(Client::METHOD_PATCH, '/teams/'.$teamId.'/memberships/'.$membershipId, array_merge([
$this->client->call(Client::METHOD_PATCH, '/teams/' . $teamId . '/memberships/' . $membershipId, array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
@ -1223,10 +1410,19 @@ class RealtimeCustomClientTest extends Scope
$this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(2, $response['data']['channels']);
$this->assertContains('memberships', $response['data']['channels']);
$this->assertContains('memberships.' . $membershipId, $response['data']['channels']);
$this->assertEquals("teams.{$teamId}.memberships.{$membershipId}.update", $response['data']['event']);
$this->assertContains("memberships.{$membershipId}", $response['data']['channels']);
$this->assertContains("teams.{$teamId}.memberships.{$membershipId}.update", $response['data']['events']);
$this->assertContains("teams.{$teamId}.memberships.{$membershipId}", $response['data']['events']);
$this->assertContains("teams.{$teamId}.memberships.*.update", $response['data']['events']);
$this->assertContains("teams.{$teamId}.memberships.*", $response['data']['events']);
$this->assertContains("teams.{$teamId}", $response['data']['events']);
$this->assertContains("teams.*.memberships.{$membershipId}.update", $response['data']['events']);
$this->assertContains("teams.*.memberships.{$membershipId}", $response['data']['events']);
$this->assertContains("teams.*.memberships.*.update", $response['data']['events']);
$this->assertContains("teams.*.memberships.*", $response['data']['events']);
$this->assertContains("teams.*", $response['data']['events']);
$this->assertNotEmpty($response['data']['payload']);
$client->close();
}
}
}

View file

@ -24,6 +24,8 @@ trait WebhooksBase
'permission' => 'document',
]);
$actorsId = $actors['body']['$id'];
$this->assertEquals($actors['headers']['status-code'], 201);
$this->assertNotEmpty($actors['body']['$id']);
@ -32,7 +34,10 @@ trait WebhooksBase
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'database.collections.create');
$this->assertStringContainsString('collections.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('collections.*.create', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -44,7 +49,7 @@ trait WebhooksBase
$this->assertCount(1, $webhook['data']['$read']);
$this->assertCount(1, $webhook['data']['$write']);
return array_merge(['actorsId' => $actors['body']['$id']]);
return array_merge(['actorsId' => $actorsId]);
}
/**
@ -52,7 +57,9 @@ trait WebhooksBase
*/
public function testCreateAttributes(array $data): array
{
$firstName = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['actorsId'] . '/attributes/string', array_merge([
$actorsId = $data['actorsId'];
$firstName = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actorsId . '/attributes/string', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
@ -62,7 +69,7 @@ trait WebhooksBase
'required' => true,
]);
$lastName = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['actorsId'] . '/attributes/string', array_merge([
$lastName = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actorsId . '/attributes/string', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
@ -72,7 +79,7 @@ trait WebhooksBase
'required' => true,
]);
$extra = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['actorsId'] . '/attributes/string', array_merge([
$extra = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actorsId . '/attributes/string', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
@ -82,6 +89,8 @@ trait WebhooksBase
'required' => false,
]);
$attributeId = $extra['body']['key'];
$this->assertEquals($firstName['headers']['status-code'], 201);
$this->assertEquals($firstName['body']['key'], 'firstName');
$this->assertEquals($lastName['headers']['status-code'], 201);
@ -97,13 +106,22 @@ trait WebhooksBase
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'database.attributes.create');
$this->assertStringContainsString('collections.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('collections.*.attributes.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('collections.*.attributes.*.create', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.*.attributes.{$actorsId}_{$attributeId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.*.attributes.{$actorsId}_{$attributeId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.attributes.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.attributes.*.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.attributes.{$actorsId}_{$attributeId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.attributes.{$actorsId}_{$attributeId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
$this->assertNotEmpty($webhook['data']['key']);
$this->assertEquals($webhook['data']['key'], 'extra');
$removed = $this->client->call(Client::METHOD_DELETE, '/database/collections/' . $data['actorsId'] . '/attributes/' . $extra['body']['key'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
@ -117,7 +135,16 @@ trait WebhooksBase
// $this->assertEquals($webhook['method'], 'DELETE');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'database.attributes.delete');
$this->assertStringContainsString('collections.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('collections.*.attributes.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('collections.*.attributes.*.delete', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.*.attributes.{$actorsId}_{$attributeId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.*.attributes.{$actorsId}_{$attributeId}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.attributes.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.attributes.*.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.attributes.{$actorsId}_{$attributeId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.attributes.{$actorsId}_{$attributeId}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -132,7 +159,12 @@ trait WebhooksBase
*/
public function testCreateDocument(array $data): array
{
$document = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['actorsId'] . '/documents', array_merge([
$actorsId = $data['actorsId'];
/**
* Test for SUCCESS
*/
$document = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actorsId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -140,12 +172,13 @@ trait WebhooksBase
'data' => [
'firstName' => 'Chris',
'lastName' => 'Evans',
],
'read' => ['role:all'],
'write' => ['role:all'],
]);
$documentId = $document['body']['$id'];
$this->assertEquals($document['headers']['status-code'], 201);
$this->assertNotEmpty($document['body']['$id']);
@ -154,7 +187,16 @@ trait WebhooksBase
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'database.documents.create');
$this->assertStringContainsString('collections.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('collections.*.documents.*.create', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.*.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.*.documents.{$documentId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.documents.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.documents.*.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.documents.{$documentId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -177,7 +219,12 @@ trait WebhooksBase
*/
public function testUpdateDocument(array $data): array
{
$document = $this->client->call(Client::METHOD_PATCH, '/database/collections/' . $data['actorsId'] . '/documents/'.$data['documentId'], array_merge([
$actorsId = $data['actorsId'];
/**
* Test for SUCCESS
*/
$document = $this->client->call(Client::METHOD_PATCH, '/database/collections/' . $actorsId . '/documents/' . $data['documentId'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -189,6 +236,8 @@ trait WebhooksBase
'write' => ['role:all'],
]);
$documentId = $document['body']['$id'];
$this->assertEquals($document['headers']['status-code'], 200);
$this->assertNotEmpty($document['body']['$id']);
@ -197,7 +246,16 @@ trait WebhooksBase
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'database.documents.update');
$this->assertStringContainsString('collections.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('collections.*.documents.*.update', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.*.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.*.documents.{$documentId}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.documents.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.documents.*.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.documents.{$documentId}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -218,7 +276,12 @@ trait WebhooksBase
*/
public function testDeleteDocument(array $data): array
{
$document = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['actorsId'] . '/documents', array_merge([
$actorsId = $data['actorsId'];
/**
* Test for SUCCESS
*/
$document = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actorsId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -226,16 +289,18 @@ trait WebhooksBase
'data' => [
'firstName' => 'Bradly',
'lastName' => 'Cooper',
],
'read' => ['role:all'],
'write' => ['role:all'],
]);
$documentId = $document['body']['$id'];
$this->assertEquals($document['headers']['status-code'], 201);
$this->assertNotEmpty($document['body']['$id']);
$document = $this->client->call(Client::METHOD_DELETE, '/database/collections/' . $data['actorsId'] . '/documents/' . $document['body']['$id'], array_merge([
$document = $this->client->call(Client::METHOD_DELETE, '/database/collections/' . $actorsId . '/documents/' . $document['body']['$id'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
@ -247,7 +312,16 @@ trait WebhooksBase
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'database.documents.delete');
$this->assertStringContainsString('collections.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('collections.*.documents.*.delete', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.*.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.*.documents.{$documentId}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.documents.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.documents.*.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.documents.{$documentId}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -280,7 +354,9 @@ trait WebhooksBase
'read' => ['role:all'],
'write' => ['role:all']
]);
$bucketId = $bucket['body']['$id'];
$this->assertEquals($bucket['headers']['status-code'], 201);
$this->assertNotEmpty($bucket['body']['$id']);
@ -289,7 +365,10 @@ trait WebhooksBase
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'storage.buckets.create');
$this->assertStringContainsString('buckets.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('buckets.*.create', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -299,8 +378,8 @@ trait WebhooksBase
$this->assertEquals(true, $webhook['data']['enabled']);
$this->assertIsArray($webhook['data']['$read']);
$this->assertIsArray($webhook['data']['$write']);
return array_merge(['bucketId' => $bucket['body']['$id']]);
return array_merge(['bucketId' => $bucketId]);
}
/**
@ -308,6 +387,8 @@ trait WebhooksBase
*/
public function testUpdateStorageBucket(array $data): array
{
$bucketId = $data['bucketId'];
/**
* Test for SUCCESS
*/
@ -320,7 +401,7 @@ trait WebhooksBase
'permission' => 'file',
'enabled' => false,
]);
$this->assertEquals($bucket['headers']['status-code'], 200);
$this->assertNotEmpty($bucket['body']['$id']);
@ -329,7 +410,10 @@ trait WebhooksBase
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'storage.buckets.update');
$this->assertStringContainsString('buckets.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('buckets.*.update', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -339,7 +423,7 @@ trait WebhooksBase
$this->assertEquals(false, $webhook['data']['enabled']);
$this->assertIsArray($webhook['data']['$read']);
$this->assertIsArray($webhook['data']['$write']);
return array_merge(['bucketId' => $bucket['body']['$id']]);
}
@ -348,6 +432,8 @@ trait WebhooksBase
*/
public function testCreateBucketFile(array $data): array
{
$bucketId = $data['bucketId'];
//enable bucket
$bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $data['bucketId'], array_merge([
'content-type' => 'application/json',
@ -358,12 +444,12 @@ trait WebhooksBase
'permission' => 'file',
'enabled' => true,
]);
$this->assertEquals($bucket['headers']['status-code'], 200);
/**
* Test for SUCCESS
*/
$file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'. $data['bucketId'] . '/files', array_merge([
$file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([
'content-type' => 'multipart/form-data',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -374,6 +460,8 @@ trait WebhooksBase
'folderId' => 'xyz',
]);
$fileId = $file['body']['$id'];
$this->assertEquals($file['headers']['status-code'], 201);
$this->assertNotEmpty($file['body']['$id']);
@ -382,7 +470,16 @@ trait WebhooksBase
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'storage.files.create');
$this->assertStringContainsString('buckets.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('buckets.*.files.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('buckets.*.files.*.create', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.*.files.{$fileId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.*.files.{$fileId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}.files.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}.files.*.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}.files.{$fileId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}.files.{$fileId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -396,22 +493,23 @@ trait WebhooksBase
$this->assertEquals($webhook['data']['mimeType'], 'image/png');
$this->assertEquals($webhook['data']['sizeOriginal'], 47218);
/**
* Test for FAILURE
*/
$data ['fileId'] = $file['body']['$id'];
$data['fileId'] = $fileId;
return $data;
}
/**
* @depends testCreateBucketFile
*/
public function testUpdateBucketFile(array $data): array
{
$bucketId = $data['bucketId'];
$fileId = $data['fileId'];
/**
* Test for SUCCESS
*/
$file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $data['bucketId'] . '/files/' . $data['fileId'], array_merge([
$file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -427,7 +525,16 @@ trait WebhooksBase
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'storage.files.update');
$this->assertStringContainsString('buckets.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('buckets.*.files.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('buckets.*.files.*.update', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.*.files.{$fileId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.*.files.{$fileId}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}.files.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}.files.*.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}.files.{$fileId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}.files.{$fileId}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -440,15 +547,18 @@ trait WebhooksBase
$this->assertNotEmpty($webhook['data']['signature']);
$this->assertEquals($webhook['data']['mimeType'], 'image/png');
$this->assertEquals($webhook['data']['sizeOriginal'], 47218);
return $data;
}
/**
* @depends testUpdateBucketFile
*/
public function testDeleteBucketFile(array $data): array
{
$bucketId = $data['bucketId'];
$fileId = $data['fileId'];
/**
* Test for SUCCESS
*/
@ -465,7 +575,16 @@ trait WebhooksBase
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'storage.files.delete');
$this->assertStringContainsString('buckets.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('buckets.*.files.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('buckets.*.files.*.delete', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.*.files.{$fileId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.*.files.{$fileId}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}.files.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}.files.*.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}.files.{$fileId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}.files.{$fileId}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -478,24 +597,25 @@ trait WebhooksBase
$this->assertNotEmpty($webhook['data']['signature']);
$this->assertEquals($webhook['data']['mimeType'], 'image/png');
$this->assertEquals($webhook['data']['sizeOriginal'], 47218);
return $data;
}
/**
/**
* @depends testDeleteBucketFile
*/
public function testDeleteStorageBucket(array $data)
{
$bucketId = $data['bucketId'];
/**
* Test for SUCCESS
*/
$bucket = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $data['bucketId'] , array_merge([
$bucket = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]));
$this->assertEquals($bucket['headers']['status-code'], 204);
$this->assertEmpty($bucket['body']);
@ -504,7 +624,10 @@ trait WebhooksBase
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'storage.buckets.delete');
$this->assertStringContainsString('buckets.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('buckets.*.delete', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("buckets.{$bucketId}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -529,6 +652,8 @@ trait WebhooksBase
'name' => 'Arsenal'
]);
$teamId = $team['body']['$id'];
$this->assertEquals(201, $team['headers']['status-code']);
$this->assertNotEmpty($team['body']['$id']);
@ -537,7 +662,10 @@ trait WebhooksBase
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'teams.create');
$this->assertStringContainsString('teams.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('teams.*.create', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -551,7 +679,7 @@ trait WebhooksBase
/**
* Test for FAILURE
*/
return ['teamId' => $team['body']['$id']];
return ['teamId' => $teamId];
}
/**
@ -559,10 +687,11 @@ trait WebhooksBase
*/
public function testUpdateTeam($data): array
{
$teamId = $data['teamId'];
/**
* Test for SUCCESS
*/
$team = $this->client->call(Client::METHOD_PUT, '/teams/'.$data['teamId'], array_merge([
$team = $this->client->call(Client::METHOD_PUT, '/teams/' . $teamId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -577,7 +706,10 @@ trait WebhooksBase
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'teams.update');
$this->assertStringContainsString('teams.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('teams.*.update', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamId}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -607,10 +739,12 @@ trait WebhooksBase
'name' => 'Chelsea'
]);
$teamId = $team['body']['$id'];
$this->assertEquals(201, $team['headers']['status-code']);
$this->assertNotEmpty($team['body']['$id']);
$team = $this->client->call(Client::METHOD_DELETE, '/teams/'.$team['body']['$id'], array_merge([
$team = $this->client->call(Client::METHOD_DELETE, '/teams/' . $team['body']['$id'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
@ -620,7 +754,10 @@ trait WebhooksBase
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'teams.delete');
$this->assertStringContainsString('teams.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('teams.*.delete', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamId}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -642,13 +779,13 @@ trait WebhooksBase
*/
public function testCreateTeamMembership($data): array
{
$teamUid = $data['teamId'] ?? '';
$email = uniqid().'friend@localhost.test';
$teamId = $data['teamId'] ?? '';
$email = uniqid() . 'friend@localhost.test';
/**
* Test for SUCCESS
*/
$team = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([
$team = $this->client->call(Client::METHOD_POST, '/teams/' . $teamId . '/memberships', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -664,15 +801,23 @@ trait WebhooksBase
$lastEmail = $this->getLastEmail();
$secret = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256);
$membershipUid = substr($lastEmail['text'], strpos($lastEmail['text'], '?membershipId=', 0) + 14, 20);
$userUid = substr($lastEmail['text'], strpos($lastEmail['text'], '&userId=', 0) + 8, 20);
$membershipId = $team['body']['$id'];
$webhook = $this->getLastRequest();
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'teams.memberships.create');
$this->assertStringContainsString('teams.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('teams.*.memberships.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('teams.*.memberships.*.create', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.*.memberships.{$membershipId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.*.memberships.{$membershipId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamId}.memberships.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamId}.memberships.*.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamId}.memberships.{$membershipId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamId}.memberships.{$membershipId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -688,25 +833,25 @@ trait WebhooksBase
* Test for FAILURE
*/
return [
'teamId' => $teamUid,
'teamId' => $teamId,
'secret' => $secret,
'membershipId' => $membershipUid,
'membershipId' => $membershipId,
'userId' => $webhook['data']['userId'],
];
}
/**
* @depends testCreateTeam
* @depends testCreateTeamMembership
*/
public function testDeleteTeamMembership($data): array
public function testDeleteTeamMembership($data): void
{
$teamUid = $data['teamId'] ?? '';
$email = uniqid().'friend@localhost.test';
$teamId = $data['teamId'] ?? '';
$email = uniqid() . 'friend@localhost.test';
/**
* Test for SUCCESS
*/
$team = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([
$team = $this->client->call(Client::METHOD_POST, '/teams/' . $teamId . '/memberships', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -716,10 +861,12 @@ trait WebhooksBase
'url' => 'http://localhost:5000/join-us#title'
]);
$membershipId = $team['body']['$id'] ?? '';
$this->assertEquals(201, $team['headers']['status-code']);
$this->assertNotEmpty($team['body']['$id']);
$team = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamUid.'/memberships/'.$team['body']['$id'], array_merge([
$team = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamId . '/memberships/' . $team['body']['$id'], array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
@ -732,7 +879,16 @@ trait WebhooksBase
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'teams.memberships.delete');
$this->assertStringContainsString('teams.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('teams.*.memberships.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('teams.*.memberships.*.delete', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.*.memberships.{$membershipId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.*.memberships.{$membershipId}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamId}.memberships.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamId}.memberships.*.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamId}.memberships.{$membershipId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamId}.memberships.{$membershipId}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -743,10 +899,5 @@ trait WebhooksBase
$this->assertCount(2, $webhook['data']['roles']);
$this->assertIsInt($webhook['data']['joined']);
$this->assertEquals(('server' === $this->getSide()), $webhook['data']['confirm']);
/**
* Test for FAILURE
*/
return [];
}
}
}

View file

@ -13,9 +13,9 @@ class WebhooksCustomClientTest extends Scope
use ProjectCustom;
use SideClient;
public function testCreateAccount():array
public function testCreateAccount(): array
{
$email = uniqid().'user@localhost.test';
$email = uniqid() . 'user@localhost.test';
$password = 'password';
$name = 'User Name';
@ -43,7 +43,10 @@ class WebhooksCustomClientTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'account.create');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.create', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event'],);
$this->assertStringContainsString("users.{$id}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -64,9 +67,9 @@ class WebhooksCustomClientTest extends Scope
];
}
public function testDeleteAccount():array
public function testDeleteAccount(): array
{
$email = uniqid().'user1@localhost.test';
$email = uniqid() . 'user1@localhost.test';
$password = 'password';
$name = 'User Name 1';
@ -95,14 +98,14 @@ class WebhooksCustomClientTest extends Scope
$this->assertEquals($accountSession['headers']['status-code'], 201);
$sessionId = $accountSession['body']['$id'];
$session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']];
$id = $account['body']['$id'];
$session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']];
$account = $this->client->call(Client::METHOD_DELETE, '/account', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session,
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
]));
$this->assertEquals($account['headers']['status-code'], 204);
@ -113,7 +116,10 @@ class WebhooksCustomClientTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'account.delete');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.delete', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -132,8 +138,9 @@ class WebhooksCustomClientTest extends Scope
/**
* @depends testCreateAccount
*/
public function testCreateAccountSession($data):array
public function testCreateAccountSession($data): array
{
$id = $data['id'] ?? '';
$email = $data['email'] ?? '';
$password = $data['password'] ?? '';
@ -152,14 +159,23 @@ class WebhooksCustomClientTest extends Scope
$this->assertEquals($accountSession['headers']['status-code'], 201);
$sessionId = $accountSession['body']['$id'];
$session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']];
$session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']];
$webhook = $this->getLastRequest();
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'account.sessions.create');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.sessions.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.sessions.*.create', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.*.sessions.{$sessionId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.*.sessions.{$sessionId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.sessions.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.sessions.*.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.sessions.{$sessionId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.sessions.{$sessionId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -198,8 +214,9 @@ class WebhooksCustomClientTest extends Scope
/**
* @depends testCreateAccount
*/
public function testDeleteAccountSession($data):array
public function testDeleteAccountSession($data): array
{
$id = $data['id'] ?? '';
$email = $data['email'] ?? '';
$password = $data['password'] ?? '';
@ -216,15 +233,15 @@ class WebhooksCustomClientTest extends Scope
]);
$sessionId = $accountSession['body']['$id'];
$session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']];
$session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']];
$this->assertEquals($accountSession['headers']['status-code'], 201);
$accountSession = $this->client->call(Client::METHOD_DELETE, '/account/sessions/'.$sessionId, array_merge([
$accountSession = $this->client->call(Client::METHOD_DELETE, '/account/sessions/' . $sessionId, array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session,
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
]));
$this->assertEquals($accountSession['headers']['status-code'], 204);
@ -234,7 +251,16 @@ class WebhooksCustomClientTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'account.sessions.delete');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.sessions.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.sessions.*.delete', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.*.sessions.{$sessionId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.*.sessions.{$sessionId}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.sessions.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.sessions.*.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.sessions.{$sessionId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.sessions.{$sessionId}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -270,8 +296,9 @@ class WebhooksCustomClientTest extends Scope
/**
* @depends testCreateAccount
*/
public function testDeleteAccountSessions($data):array
public function testDeleteAccountSessions($data): array
{
$id = $data['id'] ?? '';
$email = $data['email'] ?? '';
$password = $data['password'] ?? '';
@ -287,7 +314,8 @@ class WebhooksCustomClientTest extends Scope
'password' => $password,
]);
$session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']];
$sessionId = $accountSession['body']['$id'];
$session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']];
$this->assertEquals($accountSession['headers']['status-code'], 201);
@ -295,7 +323,7 @@ class WebhooksCustomClientTest extends Scope
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session,
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
]));
$this->assertEquals($accountSession['headers']['status-code'], 204);
@ -305,7 +333,16 @@ class WebhooksCustomClientTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'account.sessions.delete');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.sessions.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.sessions.*.delete', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.*.sessions.{$sessionId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.*.sessions.{$sessionId}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.sessions.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.sessions.*.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.sessions.{$sessionId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.sessions.{$sessionId}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -348,7 +385,7 @@ class WebhooksCustomClientTest extends Scope
$this->assertEquals($accountSession['headers']['status-code'], 201);
$sessionId = $accountSession['body']['$id'];
$session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']];
$session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']];
return array_merge($data, [
'sessionId' => $sessionId,
@ -370,7 +407,7 @@ class WebhooksCustomClientTest extends Scope
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session,
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
]), [
'name' => $newName
]);
@ -383,7 +420,12 @@ class WebhooksCustomClientTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'account.update.name');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.update', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.update.name', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.update.name", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -413,7 +455,7 @@ class WebhooksCustomClientTest extends Scope
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session,
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
]), [
'password' => 'new-password',
'oldPassword' => $password,
@ -427,7 +469,12 @@ class WebhooksCustomClientTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'account.update.password');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.update', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.update.password', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.update.password", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -452,14 +499,14 @@ class WebhooksCustomClientTest extends Scope
{
$id = $data['id'] ?? '';
$email = $data['email'] ?? '';
$newEmail = uniqid().'new@localhost.test';
$newEmail = uniqid() . 'new@localhost.test';
$session = $data['session'] ?? '';
$account = $this->client->call(Client::METHOD_PATCH, '/account/email', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session,
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
]), [
'email' => $newEmail,
'password' => 'new-password',
@ -473,7 +520,12 @@ class WebhooksCustomClientTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'account.update.email');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.update', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.update.email', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.update.email", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -504,7 +556,7 @@ class WebhooksCustomClientTest extends Scope
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session,
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
]), [
'prefs' => [
'prefKey1' => 'prefValue1',
@ -520,7 +572,12 @@ class WebhooksCustomClientTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'account.update.prefs');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.update', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.update.prefs', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.update.prefs", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -546,7 +603,6 @@ class WebhooksCustomClientTest extends Scope
{
$id = $data['id'] ?? '';
$email = $data['email'] ?? '';
$session = $data['session'] ?? '';
$recovery = $this->client->call(Client::METHOD_POST, '/account/recovery', array_merge([
'origin' => 'http://localhost',
@ -557,6 +613,8 @@ class WebhooksCustomClientTest extends Scope
'url' => 'http://localhost/recovery',
]);
$recoveryId = $recovery['body']['$id'];
$this->assertEquals(201, $recovery['headers']['status-code']);
$this->assertIsArray($recovery['body']);
@ -565,18 +623,27 @@ class WebhooksCustomClientTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'account.recovery.create');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.recovery.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.recovery.*.create', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.*.recovery.{$recoveryId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.*.recovery.{$recoveryId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.recovery.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.recovery.*.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.recovery.{$recoveryId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.recovery.{$recoveryId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
$this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id']), true);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-User-Id'], $id);
$this->assertNotEmpty($webhook['data']['$id']);
$this->assertNotEmpty($webhook['data']['userId']);
$this->assertNotEmpty($webhook['data']['secret']);
$this->assertIsNumeric($webhook['data']['expire']);
$data['secret'] = $webhook['data']['secret'];
return $data;
}
@ -602,6 +669,8 @@ class WebhooksCustomClientTest extends Scope
'passwordAgain' => $password,
]);
$recoveryId = $recovery['body']['$id'];
$this->assertEquals(200, $recovery['headers']['status-code']);
$this->assertIsArray($recovery['body']);
@ -610,7 +679,16 @@ class WebhooksCustomClientTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'account.recovery.update');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.recovery.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.recovery.*.update', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.*.recovery.{$recoveryId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.*.recovery.{$recoveryId}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.recovery.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.recovery.*.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.recovery.{$recoveryId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.recovery.{$recoveryId}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -638,11 +716,13 @@ class WebhooksCustomClientTest extends Scope
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session,
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
]), [
'url' => 'http://localhost/verification',
]);
$verificationId = $verification['body']['$id'];
$this->assertEquals(201, $verification['headers']['status-code']);
$this->assertIsArray($verification['body']);
@ -651,7 +731,16 @@ class WebhooksCustomClientTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'account.verification.create');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.verification.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.verification.*.create', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.*.verification.{$verificationId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.*.verification.{$verificationId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.verification.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.verification.*.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.verification.{$verificationId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.verification.{$verificationId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -680,12 +769,14 @@ class WebhooksCustomClientTest extends Scope
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session,
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
]), [
'userId' => $id,
'secret' => $secret,
]);
$verificationId = $verification['body']['$id'];
$this->assertEquals(200, $verification['headers']['status-code']);
$this->assertIsArray($verification['body']);
@ -694,7 +785,16 @@ class WebhooksCustomClientTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'account.verification.update');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.verification.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.verification.*.update', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.*.verification.{$verificationId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.*.verification.{$verificationId}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.verification.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.verification.*.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.verification.{$verificationId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.verification.{$verificationId}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -722,7 +822,7 @@ class WebhooksCustomClientTest extends Scope
/**
* Test for SUCCESS
*/
$team = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([
$team = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
@ -739,7 +839,20 @@ class WebhooksCustomClientTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'teams.memberships.update.status');
$this->assertStringContainsString('teams.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('teams.*.memberships.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('teams.*.memberships.*.update', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('teams.*.memberships.*.update.status', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.*.memberships.{$membershipUid}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.*.memberships.{$membershipUid}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.*.memberships.{$membershipUid}.update.status", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamUid}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamUid}.memberships.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamUid}.memberships.*.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamUid}.memberships.*.update.status", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamUid}.memberships.{$membershipUid}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamUid}.memberships.{$membershipUid}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("teams.{$teamUid}.memberships.{$membershipUid}.update.status", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -756,4 +869,4 @@ class WebhooksCustomClientTest extends Scope
*/
return [];
}
}
}

View file

@ -20,10 +20,12 @@ class WebhooksCustomServerTest extends Scope
*/
public function testUpdateCollection($data): array
{
$id = $data['actorsId'];
/**
* Test for SUCCESS
*/
$actors = $this->client->call(Client::METHOD_PUT, '/database/collections/'.$data['actorsId'], array_merge([
$actors = $this->client->call(Client::METHOD_PUT, '/database/collections/' . $id, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
@ -31,7 +33,7 @@ class WebhooksCustomServerTest extends Scope
'name' => 'Actors1',
'permission' => 'document',
]);
$this->assertEquals($actors['headers']['status-code'], 200);
$this->assertNotEmpty($actors['body']['$id']);
@ -40,7 +42,10 @@ class WebhooksCustomServerTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'database.collections.update');
$this->assertStringContainsString('collections.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('collections.*.update', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -60,6 +65,8 @@ class WebhooksCustomServerTest extends Scope
*/
public function testCreateDeleteIndexes($data): array
{
$actorsId = $data['actorsId'];
$index = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['actorsId'] . '/indexes', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
@ -71,6 +78,7 @@ class WebhooksCustomServerTest extends Scope
'orders' => ['ASC', 'ASC'],
]);
$indexKey = $index['body']['key'];
$this->assertEquals($index['headers']['status-code'], 201);
$this->assertEquals($index['body']['key'], 'fullname');
@ -82,7 +90,16 @@ class WebhooksCustomServerTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'database.indexes.create');
$this->assertStringContainsString('collections.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('collections.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('collections.*.indexes.*.create', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.*.indexes.{$actorsId}_{$indexKey}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.*.indexes.{$actorsId}_{$indexKey}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.indexes.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.indexes.*.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.indexes.{$actorsId}_{$indexKey}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.indexes.{$actorsId}_{$indexKey}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -101,7 +118,16 @@ class WebhooksCustomServerTest extends Scope
// $this->assertEquals($webhook['method'], 'DELETE');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'database.indexes.delete');
$this->assertStringContainsString('collections.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('collections.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('collections.*.indexes.*.delete', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.*.indexes.{$actorsId}_{$indexKey}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.*.indexes.{$actorsId}_{$indexKey}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.indexes.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.indexes.*.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.indexes.{$actorsId}_{$indexKey}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$actorsId}.indexes.{$actorsId}_{$indexKey}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -127,10 +153,12 @@ class WebhooksCustomServerTest extends Scope
'permission' => 'document'
]);
$id = $actors['body']['$id'];
$this->assertEquals($actors['headers']['status-code'], 201);
$this->assertNotEmpty($actors['body']['$id']);
$actors = $this->client->call(Client::METHOD_DELETE, '/database/collections/'.$actors['body']['$id'], array_merge([
$actors = $this->client->call(Client::METHOD_DELETE, '/database/collections/' . $actors['body']['$id'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
@ -143,7 +171,10 @@ class WebhooksCustomServerTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'database.collections.delete');
$this->assertStringContainsString('collections.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('collections.*.delete', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("collections.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event'],);
$this->assertStringContainsString("collections.{$id}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -158,9 +189,9 @@ class WebhooksCustomServerTest extends Scope
return [];
}
public function testCreateUser():array
public function testCreateUser(): array
{
$email = uniqid().'user@localhost.test';
$email = uniqid() . 'user@localhost.test';
$password = 'password';
$name = 'User Name';
@ -187,7 +218,10 @@ class WebhooksCustomServerTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'users.create');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.create', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event'],);
$this->assertStringContainsString("users.{$id}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -206,15 +240,17 @@ class WebhooksCustomServerTest extends Scope
return ['userId' => $user['body']['$id'], 'name' => $user['body']['name'], 'email' => $user['body']['email']];
}
/**
/**
* @depends testCreateUser
*/
public function testUpdateUserPrefs(array $data):array
public function testUpdateUserPrefs(array $data): array
{
$id = $data['userId'];
/**
* Test for SUCCESS
*/
$user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/prefs', array_merge([
$user = $this->client->call(Client::METHOD_PATCH, '/users/' . $id . '/prefs', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -229,7 +265,12 @@ class WebhooksCustomServerTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'users.update.prefs');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.update', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.update.prefs', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.update.prefs", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -242,8 +283,10 @@ class WebhooksCustomServerTest extends Scope
/**
* @depends testUpdateUserPrefs
*/
public function testUpdateUserStatus(array $data):array
public function testUpdateUserStatus(array $data): array
{
$id = $data['userId'];
/**
* Test for SUCCESS
*/
@ -262,7 +305,12 @@ class WebhooksCustomServerTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'users.update.status');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.update', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.update.status', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.update.status", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -277,12 +325,14 @@ class WebhooksCustomServerTest extends Scope
return $data;
}
/**
* @depends testUpdateUserStatus
*/
public function testDeleteUser(array $data):array
public function testDeleteUser(array $data): array
{
$id = $data['userId'];
/**
* Test for SUCCESS
*/
@ -298,7 +348,10 @@ class WebhooksCustomServerTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'users.delete');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('users.*.delete', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("users.{$id}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -314,7 +367,7 @@ class WebhooksCustomServerTest extends Scope
return $data;
}
public function testCreateFunction():array
public function testCreateFunction(): array
{
/**
* Test for SUCCESS
@ -330,7 +383,7 @@ class WebhooksCustomServerTest extends Scope
'timeout' => 10,
]);
$functionId = $function['body']['$id'] ?? '';
$id = $function['body']['$id'] ?? '';
$this->assertEquals($function['headers']['status-code'], 201);
$this->assertNotEmpty($function['body']['$id']);
@ -340,7 +393,10 @@ class WebhooksCustomServerTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'functions.create');
$this->assertStringContainsString('functions.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('functions.*.create', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -350,19 +406,21 @@ class WebhooksCustomServerTest extends Scope
*/
return [
'functionId' => $functionId,
'functionId' => $id,
];
}
/**
* @depends testCreateFunction
*/
public function testUpdateFunction($data):array
public function testUpdateFunction($data): array
{
/**
* Test for SUCCESS
*/
$function = $this->client->call(Client::METHOD_PUT, '/functions/'.$data['functionId'], array_merge([
$id = $data['functionId'];
/**
* Test for SUCCESS
*/
$function = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -383,29 +441,32 @@ class WebhooksCustomServerTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'functions.update');
$this->assertStringContainsString('functions.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('functions.*.update', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
return $data;
}
/**
* @depends testUpdateFunction
*/
public function testCreateDeployment($data):array
public function testCreateDeployment($data): array
{
/**
* Test for SUCCESS
*/
$stderr = '';
$stdout= '';
$stdout = '';
$folder = 'timeout';
$code = realpath(__DIR__ . '/../../../resources/functions'). "/$folder/code.tar.gz";
Console::execute('cd '.realpath(__DIR__ . "/../../../resources/functions") . "/$folder && tar --exclude code.tar.gz -czf code.tar.gz .", '', $stdout, $stderr);
$code = realpath(__DIR__ . '/../../../resources/functions') . "/{$folder}/code.tar.gz";
Console::execute('cd ' . realpath(__DIR__ . "/../../../resources/functions") . "/{$folder} && tar --exclude code.tar.gz -czf code.tar.gz .", '', $stdout, $stderr);
$deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/deployments', array_merge([
$deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/deployments', array_merge([
'content-type' => 'multipart/form-data',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -413,6 +474,7 @@ class WebhooksCustomServerTest extends Scope
'code' => new CURLFile($code, 'application/x-gzip', \basename($code))
]);
$id = $data['functionId'] ?? '';
$deploymentId = $deployment['body']['$id'] ?? '';
$this->assertEquals($deployment['headers']['status-code'], 201);
@ -423,7 +485,12 @@ class WebhooksCustomServerTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'functions.deployments.create');
$this->assertStringContainsString('functions.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('functions.*.deployments.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.*.deployments.{$deploymentId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.deployments.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.deployments.{$deploymentId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -436,12 +503,15 @@ class WebhooksCustomServerTest extends Scope
/**
* @depends testCreateDeployment
*/
public function testUpdateDeployment($data):array
public function testUpdateDeployment($data): array
{
$id = $data['functionId'] ?? '';
$deploymentId = $data['deploymentId'] ?? '';
/**
* Test for SUCCESS
*/
$response = $this->client->call(Client::METHOD_PATCH, '/functions/'.$data['functionId'].'/deployments/'.$data['deploymentId'], array_merge([
$response = $this->client->call(Client::METHOD_PATCH, '/functions/' . $id . '/deployments/' . $deploymentId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
@ -457,7 +527,16 @@ class WebhooksCustomServerTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'functions.deployments.update');
$this->assertStringContainsString('functions.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('functions.*.deployments.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('functions.*.deployments.*.update', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.*.deployments.{$deploymentId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.*.deployments.{$deploymentId}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.deployments.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.deployments.*.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.deployments.{$deploymentId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.deployments.{$deploymentId}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -472,17 +551,20 @@ class WebhooksCustomServerTest extends Scope
/**
* @depends testUpdateDeployment
*/
public function testExecutions($data):array
public function testExecutions($data): array
{
$id = $data['functionId'] ?? '';
/**
* Test for SUCCESS
*/
$execution = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/executions', array_merge([
$execution = $this->client->call(Client::METHOD_POST, '/functions/' . $id . '/executions', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
$executionId = $execution['body']['$id'] ?? '';
$this->assertEquals($execution['headers']['status-code'], 201);
$this->assertNotEmpty($execution['body']['$id']);
@ -491,12 +573,21 @@ class WebhooksCustomServerTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'functions.executions.create');
$this->assertStringContainsString('functions.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('functions.*.executions.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('functions.*.executions.*.create', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.*.executions.{$executionId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.*.executions.{$executionId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.executions.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.executions.*.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.executions.{$executionId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.executions.{$executionId}.create", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
// wait for timeout function to complete (sleep(5);)
// wait for timeout function to complete
sleep(10);
$webhook = $this->getLastRequest();
@ -504,7 +595,16 @@ class WebhooksCustomServerTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'functions.executions.update');
$this->assertStringContainsString('functions.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('functions.*.executions.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('functions.*.executions.*.update', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.*.executions.{$executionId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.*.executions.{$executionId}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.executions.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.executions.*.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.executions.{$executionId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.executions.{$executionId}.update", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -519,12 +619,14 @@ class WebhooksCustomServerTest extends Scope
/**
* @depends testExecutions
*/
public function testDeleteDeployment($data):array
public function testDeleteDeployment($data): array
{
$id = $data['functionId'] ?? '';
$deploymentId = $data['deploymentId'] ?? '';
/**
* Test for SUCCESS
*/
$deployment = $this->client->call(Client::METHOD_DELETE, '/functions/'.$data['functionId'].'/deployments/'.$data['deploymentId'], array_merge([
$deployment = $this->client->call(Client::METHOD_DELETE, '/functions/' . $id . '/deployments/' . $deploymentId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
@ -537,7 +639,16 @@ class WebhooksCustomServerTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'functions.deployments.delete');
$this->assertStringContainsString('functions.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('functions.*.deployments.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('functions.*.deployments.*.delete', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.*.deployments.{$deploymentId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.*.deployments.{$deploymentId}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.deployments.*", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.deployments.*.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.deployments.{$deploymentId}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.deployments.{$deploymentId}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
@ -552,12 +663,14 @@ class WebhooksCustomServerTest extends Scope
/**
* @depends testDeleteDeployment
*/
public function testDeleteFunction($data):array
public function testDeleteFunction($data): array
{
$id = $data['functionId'];
/**
* Test for SUCCESS
*/
$function = $this->client->call(Client::METHOD_DELETE, '/functions/'.$data['functionId'], array_merge([
$function = $this->client->call(Client::METHOD_DELETE, '/functions/' . $id, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
@ -570,7 +683,10 @@ class WebhooksCustomServerTest extends Scope
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'functions.delete');
$this->assertStringContainsString('functions.*', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString('functions.*.delete', $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertStringContainsString("functions.{$id}.delete", $webhook['headers']['X-Appwrite-Webhook-Event']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented');
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);

View file

@ -1,154 +0,0 @@
<?php
namespace Tests\E2E\Services\Workers;
use Tests\E2E\Client;
use Tests\E2E\Scopes\ProjectConsole;
use Tests\E2E\Scopes\ProjectCustom;
use Tests\E2E\Scopes\Scope;
use Tests\E2E\Scopes\SideClient;
use Tests\E2E\Scopes\SideServer;
class WebhooksTest extends Scope
{
use ProjectConsole;
use SideClient;
public function testCreateProject(): array
{
/**
* Test for SUCCESS
*/
$team = $this->client->call(Client::METHOD_POST, '/teams', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'teamId' => 'unique()',
'name' => 'Project Test',
]);
$this->assertEquals(201, $team['headers']['status-code']);
$this->assertEquals('Project Test', $team['body']['name']);
$this->assertNotEmpty($team['body']['$id']);
$response = $this->client->call(Client::METHOD_POST, '/projects', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'projectId' => 'unique()',
'name' => 'Project Test',
'teamId' => $team['body']['$id'],
]);
$this->assertEquals(201, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$this->assertEquals('Project Test', $response['body']['name']);
$this->assertEquals($team['body']['$id'], $response['body']['teamId']);
$this->assertArrayHasKey('platforms', $response['body']);
$this->assertArrayHasKey('webhooks', $response['body']);
$this->assertArrayHasKey('keys', $response['body']);
$projectId = $response['body']['$id'];
/**
* Test for FAILURE
*/
$response = $this->client->call(Client::METHOD_POST, '/projects', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'projectId' => 'unique()',
'name' => '',
'teamId' => $team['body']['$id'],
]);
$this->assertEquals(400, $response['headers']['status-code']);
$response = $this->client->call(Client::METHOD_POST, '/projects', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'name' => 'Project Test',
]);
$this->assertEquals(400, $response['headers']['status-code']);
return ['projectId' => $projectId];
}
/**
* @depends testCreateProject
*/
public function testCreateWebhook($data): array
{
$id = (isset($data['projectId'])) ? $data['projectId'] : '';
$response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/webhooks', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'name' => 'Webhook Worker Test',
'events' => ['account.create', 'account.update.email'],
'url' => 'http://request-catcher:5000/webhook',
'security' => true,
'httpUser' => 'username',
'httpPass' => 'password',
]);
$this->assertEquals(201, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$this->assertContains('account.create', $response['body']['events']);
$this->assertContains('account.update.email', $response['body']['events']);
$this->assertCount(2, $response['body']['events']);
$this->assertEquals('http://request-catcher:5000/webhook', $response['body']['url']);
$this->assertIsBool($response['body']['security']);
$this->assertEquals(true, $response['body']['security']);
$this->assertEquals('username', $response['body']['httpUser']);
$data = array_merge($data, ['webhookId' => $response['body']['$id']]);
/**
* Test for FAILURE
*/
return $data;
}
/**
* @depends testCreateWebhook
*/
public function testCreateAccount($data)
{
$projectId = (isset($data['projectId'])) ? $data['projectId'] : '';
$email = uniqid().'webhook.user@localhost.test';
$password = 'password';
$name = 'User Name';
/**
* Test for SUCCESS
*/
$response = $this->client->call(Client::METHOD_POST, '/account', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
]), [
'userId' => 'unique()',
'email' => $email,
'password' => $password,
'name' => $name,
]);
$this->assertEquals($response['headers']['status-code'], 201);
$webhook = $this->getLastRequest();
$this->assertNotEmpty($webhook['data']);
$this->assertNotEmpty($webhook['data']['$id']);
$this->assertIsBool($webhook['data']['status']);
$this->assertIsNumeric($webhook['data']['registration']);
$this->assertEquals($webhook['data']['email'], $email);
$this->assertEquals($webhook['data']['name'], $name);
$this->assertIsBool($webhook['data']['emailVerification']);
$this->assertIsArray($webhook['data']['prefs']);
}
}

View file

@ -63,8 +63,8 @@ class EventTest extends TestCase
$this->object->trigger();
$this->assertEquals(null, $this->object->getParam('eventKey1'));
$this->assertEquals(null, $this->object->getParam('eventKey2'));
$this->assertEquals('eventValue1', $this->object->getParam('eventKey1'));
$this->assertEquals('eventValue2', $this->object->getParam('eventKey2'));
$this->assertEquals(null, $this->object->getParam('eventKey3'));
$this->assertEquals(\Resque::size($this->queue), 1);
}
@ -111,15 +111,18 @@ class EventTest extends TestCase
'collectionId' => 'chapters',
'documentId' => 'prolog',
]);
$this->assertCount(8, $event);
$this->assertCount(10, $event);
$this->assertContains('collections.chapters.documents.prolog.create', $event);
$this->assertContains('collections.chapters.documents.prolog', $event);
$this->assertContains('collections.chapters.documents.*.create', $event);
$this->assertContains('collections.chapters.documents.*', $event);
$this->assertContains('collections.chapters', $event);
$this->assertContains('collections.*.documents.prolog.create', $event);
$this->assertContains('collections.*.documents.prolog', $event);
$this->assertContains('collections.*.documents.*.create', $event);
$this->assertContains('collections.*.documents.*', $event);
$this->assertContains('collections.*', $event);
try {
$event = Event::generateEvents('collections.[collectionId].documents.[documentId].create', [

View file

@ -202,7 +202,7 @@ class MessagingTest extends TestCase
* Test Collection Level Permissions
*/
$result = Realtime::fromPayload(
event: 'database.documents.create',
event: 'collections.collection_id.documents.document_id.create',
payload: new Document([
'$id' => 'test',
'$collection' => 'collection',
@ -224,7 +224,7 @@ class MessagingTest extends TestCase
* Test Document Level Permissions
*/
$result = Realtime::fromPayload(
event: 'database.documents.create',
event: 'collections.collection_id.documents.document_id.create',
payload: new Document([
'$id' => 'test',
'$collection' => 'collection',
@ -242,4 +242,51 @@ class MessagingTest extends TestCase
$this->assertContains('role:all', $result['roles']);
$this->assertNotContains('role:admin', $result['roles']);
}
public function testFromPayloadBucketLevelPermissions(): void
{
/**
* Test Collection Level Permissions
*/
$result = Realtime::fromPayload(
event: 'buckets.bucket_id.files.file_id.create',
payload: new Document([
'$id' => 'test',
'$collection' => 'bucket',
'$read' => ['role:admin'],
'$write' => ['role:admin']
]),
bucket: new Document([
'$id' => 'bucket',
'$read' => ['role:all'],
'$write' => ['role:all'],
'permission' => 'bucket'
])
);
$this->assertContains('role:all', $result['roles']);
$this->assertNotContains('role:admin', $result['roles']);
/**
* Test Document Level Permissions
*/
$result = Realtime::fromPayload(
event: 'buckets.bucket_id.files.file_id.create',
payload: new Document([
'$id' => 'test',
'$collection' => 'bucket',
'$read' => ['role:all'],
'$write' => ['role:all']
]),
bucket: new Document([
'$id' => 'bucket',
'$read' => ['role:admin'],
'$write' => ['role:admin'],
'permission' => 'file'
])
);
$this->assertContains('role:all', $result['roles']);
$this->assertNotContains('role:admin', $result['roles']);
}
}