1
0
Fork 0
mirror of synced 2024-07-04 06:00:53 +12:00

Merge branch '1.3.x' of https://github.com/appwrite/appwrite into feat-team-prefs

This commit is contained in:
Torsten Dittmann 2023-03-23 13:03:50 +01:00
commit 10cd97e978
55 changed files with 2998 additions and 320 deletions

View file

@ -436,6 +436,14 @@ composer lint
composer lint <your file path>
```
## Clearing the Cache
If you need to clear the cache, you can do so by running the following command:
```bash
docker compose exec redis redis-cli FLUSHALL
```
## Tutorials
From time to time, our team will add tutorials that will help contributors find their way in the Appwrite source code. Below is a list of currently available tutorials:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -62,7 +62,7 @@ App::post('/v1/account')
->label('sdk.description', '/docs/references/account/create.md')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ACCOUNT)
->label('sdk.response.model', Response::MODEL_USER)
->label('abuse-limit', 10)
->param('userId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('email', '', new Email(), 'User email.')
@ -1328,7 +1328,7 @@ App::get('/v1/account')
->label('sdk.description', '/docs/references/account/get.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ACCOUNT)
->label('sdk.response.model', Response::MODEL_USER)
->label('sdk.offline.model', '/account')
->label('sdk.offline.key', 'current')
->inject('response')
@ -1520,7 +1520,7 @@ App::patch('/v1/account/name')
->label('sdk.description', '/docs/references/account/update-name.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ACCOUNT)
->label('sdk.response.model', Response::MODEL_USER)
->label('sdk.offline.model', '/account')
->label('sdk.offline.key', 'current')
->param('name', '', new Text(128), 'User name. Max length: 128 chars.')
@ -1558,9 +1558,9 @@ App::patch('/v1/account/password')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ACCOUNT)
->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, $project->getAttribute('auths', [])['passwordDictionary'] ?? false), 'New user password. Must be at least 8 chars.', false, ['project', 'passwordsDictionary'])
->label('sdk.offline.model', '/account')
->label('sdk.offline.key', 'current')
->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, $project->getAttribute('auths', [])['passwordDictionary'] ?? false), 'New user password. Must be at least 8 chars.', false, ['project', 'passwordsDictionary'])
->param('oldPassword', '', new Password(), 'Current user password. Must be at least 8 chars.', true)
->inject('requestTimestamp')
->inject('response')
@ -1618,7 +1618,7 @@ App::patch('/v1/account/email')
->label('sdk.description', '/docs/references/account/update-email.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ACCOUNT)
->label('sdk.response.model', Response::MODEL_USER)
->label('sdk.offline.model', '/account')
->label('sdk.offline.key', 'current')
->param('email', '', new Email(), 'User email.')
@ -1674,7 +1674,7 @@ App::patch('/v1/account/phone')
->label('sdk.description', '/docs/references/account/update-phone.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ACCOUNT)
->label('sdk.response.model', Response::MODEL_USER)
->label('sdk.offline.model', '/account')
->label('sdk.offline.key', 'current')
->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.')
@ -1726,7 +1726,7 @@ App::patch('/v1/account/prefs')
->label('sdk.description', '/docs/references/account/update-prefs.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ACCOUNT)
->label('sdk.response.model', Response::MODEL_USER)
->label('sdk.offline.model', '/account/prefs')
->label('sdk.offline.key', 'current')
->param('prefs', [], new Assoc(), 'Prefs key-value JSON object.')

View file

@ -6,7 +6,7 @@ use Appwrite\Extend\Exception;
use Utopia\Audit\Audit;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Validator\DatetimeValidator;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
use Utopia\Database\Helpers\ID;
use Utopia\Validator\Boolean;
use Utopia\Validator\FloatValidator;
@ -48,6 +48,7 @@ use Appwrite\Utopia\Database\Validator\Queries\Databases;
use Appwrite\Utopia\Database\Validator\Queries\Documents;
use Utopia\Config\Config;
use MaxMind\Db\Reader;
use Utopia\Validator\Nullable;
/**
* Create attribute of varying type
@ -147,6 +148,143 @@ function createAttribute(string $databaseId, string $collectionId, Document $att
return $attribute;
}
function updateAttribute(
string $databaseId,
string $collectionId,
string $key,
Database $dbForProject,
Event $events,
string $type,
string $filter = null,
string|bool|int|float $default = null,
bool $required = null,
int|float $min = null,
int|float $max = null,
array $elements = null
): Document {
$db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
if ($db->isEmpty()) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
}
$collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId);
if ($collection->isEmpty()) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
}
$attribute = $dbForProject->getDocument('attributes', ID::custom($db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key));
if ($attribute->isEmpty()) {
throw new Exception(Exception::ATTRIBUTE_NOT_FOUND);
}
if ($attribute->getAttribute('status') !== 'available') {
throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE);
}
if ($attribute->getAttribute(('type') !== $type)) {
throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID);
}
if ($attribute->getAttribute('type') === Database::VAR_STRING && $attribute->getAttribute(('filter') !== $filter)) {
throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID);
}
if ($required && isset($default)) {
throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for required attribute');
}
if ($attribute->getAttribute('array', false) && isset($default)) {
throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for array attributes');
}
$collectionId = 'database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId();
$attribute
->setAttribute('default', $default)
->setAttribute('required', $required);
$formatOptions = $attribute->getAttribute('formatOptions');
switch ($attribute->getAttribute('format')) {
case APP_DATABASE_ATTRIBUTE_INT_RANGE:
case APP_DATABASE_ATTRIBUTE_FLOAT_RANGE:
if ($min === $formatOptions['min'] && $max === $formatOptions['max']) {
break;
}
if ($min > $max) {
throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value');
}
if ($attribute->getAttribute('format') === APP_DATABASE_ATTRIBUTE_INT_RANGE) {
$validator = new Range($min, $max, Database::VAR_INTEGER);
} else {
$validator = new Range($min, $max, Database::VAR_FLOAT);
if (!is_null($default)) {
$default = \floatval($default);
}
}
if (!is_null($default) && !$validator->isValid($default)) {
throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription());
}
$options = [
'min' => $min,
'max' => $max
];
$attribute->setAttribute('formatOptions', $options);
break;
case APP_DATABASE_ATTRIBUTE_ENUM:
if (empty($elements)) {
throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Enum elements must not be empty');
}
foreach ($elements as $element) {
if (\strlen($element) === 0) {
throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Each enum element must not be empty');
}
}
if (!is_null($default) && !in_array($default, $elements)) {
throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Default value not found in elements');
}
$options = [
'elements' => $elements
];
$attribute->setAttribute('formatOptions', $options);
break;
}
$dbForProject->updateAttribute(
collection: $collectionId,
id: $key,
required: $required,
default: $default,
formatOptions: $options ?? null
);
$dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key, $attribute);
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId);
$events
->setContext('collection', $collection)
->setContext('database', $db)
->setParam('databaseId', $databaseId)
->setParam('collectionId', $collection->getId())
->setParam('attributeId', $attribute->getId());
return $attribute;
}
App::post('/v1/databases')
->desc('Create Database')
->groups(['api', 'database'])
@ -964,7 +1102,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum')
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('elements', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' elements are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.')
->param('elements', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE, min: 0), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' elements are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Text(0), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true)
->param('array', false, new Boolean(), 'Is attribute an array?', true)
@ -1392,7 +1530,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key')
Response::MODEL_ATTRIBUTE_URL,
Response::MODEL_ATTRIBUTE_IP,
Response::MODEL_ATTRIBUTE_DATETIME,
Response::MODEL_ATTRIBUTE_STRING])// needs to be last, since its condition would dominate any other string attribute
Response::MODEL_ATTRIBUTE_STRING // needs to be last, since its condition would dominate any other string attribute
])
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', '', new Key(), 'Attribute Key.')
@ -1440,6 +1579,394 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key')
$response->dynamic($attribute, $model);
});
App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/string/:key')
->desc('Update String Attribute')
->groups(['api', 'database', 'schema'])
->label('scope', 'collections.write')
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update')
->label('audits.event', 'attribute.update')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('usage.metric', 'collections.{scope}.requests.update')
->label('usage.params', ['databaseId:{request.databaseId}'])
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'updateStringAttribute')
->label('sdk.description', '/docs/references/databases/update-string-attribute.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_STRING)
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Text(0)), 'Default value for attribute when not provided. Cannot be set when attribute is required.')
->inject('response')
->inject('dbForProject')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $events) {
$attribute = updateAttribute(
databaseId: $databaseId,
collectionId: $collectionId,
key: $key,
dbForProject: $dbForProject,
events: $events,
type: Database::VAR_STRING,
default: $default,
required: $required
);
$response
->setStatusCode(Response::STATUS_CODE_OK)
->dynamic($attribute, Response::MODEL_ATTRIBUTE_STRING);
});
App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/email/:key')
->desc('Update Email Attribute')
->groups(['api', 'database', 'schema'])
->label('scope', 'collections.write')
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update')
->label('audits.event', 'attribute.update')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('usage.metric', 'collections.{scope}.requests.update')
->label('usage.params', ['databaseId:{request.databaseId}'])
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'updateEmailAttribute')
->label('sdk.description', '/docs/references/databases/update-email-attribute.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_EMAIL)
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Email()), 'Default value for attribute when not provided. Cannot be set when attribute is required.')
->inject('response')
->inject('dbForProject')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $events) {
$attribute = updateAttribute(
databaseId: $databaseId,
collectionId: $collectionId,
key: $key,
dbForProject: $dbForProject,
events: $events,
type: Database::VAR_STRING,
filter: APP_DATABASE_ATTRIBUTE_EMAIL,
default: $default,
required: $required
);
$response
->setStatusCode(Response::STATUS_CODE_OK)
->dynamic($attribute, Response::MODEL_ATTRIBUTE_EMAIL);
});
App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/enum/:key')
->desc('Update Enum Attribute')
->groups(['api', 'database', 'schema'])
->label('scope', 'collections.write')
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update')
->label('audits.event', 'attribute.update')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('usage.metric', 'collections.{scope}.requests.update')
->label('usage.params', ['databaseId:{request.databaseId}'])
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'updateEnumAttribute')
->label('sdk.description', '/docs/references/databases/update-enum-attribute.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_ENUM)
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('elements', null, new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' elements are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Text(0)), 'Default value for attribute when not provided. Cannot be set when attribute is required.')
->inject('response')
->inject('dbForProject')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $key, ?array $elements, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $events) {
$attribute = updateAttribute(
databaseId: $databaseId,
collectionId: $collectionId,
key: $key,
dbForProject: $dbForProject,
events: $events,
type: Database::VAR_STRING,
filter: APP_DATABASE_ATTRIBUTE_ENUM,
default: $default,
required: $required,
elements: $elements
);
$response
->setStatusCode(Response::STATUS_CODE_OK)
->dynamic($attribute, Response::MODEL_ATTRIBUTE_ENUM);
});
App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/ip/:key')
->desc('Update IP Address Attribute')
->groups(['api', 'database', 'schema'])
->label('scope', 'collections.write')
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update')
->label('audits.event', 'attribute.update')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('usage.metric', 'collections.{scope}.requests.update')
->label('usage.params', ['databaseId:{request.databaseId}'])
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'updateIpAttribute')
->label('sdk.description', '/docs/references/databases/update-ip-attribute.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_IP)
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new IP()), 'Default value for attribute when not provided. Cannot be set when attribute is required.')
->inject('response')
->inject('dbForProject')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $events) {
$attribute = updateAttribute(
databaseId: $databaseId,
collectionId: $collectionId,
key: $key,
dbForProject: $dbForProject,
events: $events,
type: Database::VAR_STRING,
filter: APP_DATABASE_ATTRIBUTE_IP,
default: $default,
required: $required
);
$response
->setStatusCode(Response::STATUS_CODE_OK)
->dynamic($attribute, Response::MODEL_ATTRIBUTE_IP);
});
App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/url/:key')
->desc('Update URL Attribute')
->groups(['api', 'database', 'schema'])
->label('scope', 'collections.write')
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update')
->label('audits.event', 'attribute.update')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('usage.metric', 'collections.{scope}.requests.update')
->label('usage.params', ['databaseId:{request.databaseId}'])
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'updateUrlAttribute')
->label('sdk.description', '/docs/references/databases/update-url-attribute.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_URL)
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new URL()), 'Default value for attribute when not provided. Cannot be set when attribute is required.')
->inject('response')
->inject('dbForProject')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $events) {
$attribute = updateAttribute(
databaseId: $databaseId,
collectionId: $collectionId,
key: $key,
dbForProject: $dbForProject,
events: $events,
type: Database::VAR_STRING,
filter: APP_DATABASE_ATTRIBUTE_URL,
default: $default,
required: $required
);
$response
->setStatusCode(Response::STATUS_CODE_OK)
->dynamic($attribute, Response::MODEL_ATTRIBUTE_URL);
});
App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/integer/:key')
->desc('Update Integer Attribute')
->groups(['api', 'database', 'schema'])
->label('scope', 'collections.write')
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update')
->label('audits.event', 'attribute.update')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('usage.metric', 'collections.{scope}.requests.update')
->label('usage.params', ['databaseId:{request.databaseId}'])
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'updateIntegerAttribute')
->label('sdk.description', '/docs/references/databases/update-integer-attribute.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_INTEGER)
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('min', null, new Integer(), 'Minimum value to enforce on new documents')
->param('max', null, new Integer(), 'Maximum value to enforce on new documents')
->param('default', null, new Nullable(new Integer()), 'Default value for attribute when not provided. Cannot be set when attribute is required.')
->inject('response')
->inject('dbForProject')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, Response $response, Database $dbForProject, Event $events) {
$attribute = updateAttribute(
databaseId: $databaseId,
collectionId: $collectionId,
key: $key,
dbForProject: $dbForProject,
events: $events,
type: Database::VAR_INTEGER,
default: $default,
required: $required,
min: $min,
max: $max
);
$formatOptions = $attribute->getAttribute('formatOptions', []);
if (!empty($formatOptions)) {
$attribute->setAttribute('min', \intval($formatOptions['min']));
$attribute->setAttribute('max', \intval($formatOptions['max']));
}
$response
->setStatusCode(Response::STATUS_CODE_OK)
->dynamic($attribute, Response::MODEL_ATTRIBUTE_INTEGER);
});
App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/float/:key')
->desc('Update Float Attribute')
->groups(['api', 'database', 'schema'])
->label('scope', 'collections.write')
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update')
->label('audits.event', 'attribute.update')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('usage.metric', 'collections.{scope}.requests.update')
->label('usage.params', ['databaseId:{request.databaseId}'])
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'updateFloatAttribute')
->label('sdk.description', '/docs/references/databases/update-float-attribute.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_FLOAT)
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('min', null, new FloatValidator(), 'Minimum value to enforce on new documents')
->param('max', null, new FloatValidator(), 'Maximum value to enforce on new documents')
->param('default', null, new Nullable(new FloatValidator()), 'Default value for attribute when not provided. Cannot be set when attribute is required.')
->inject('response')
->inject('dbForProject')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, Response $response, Database $dbForProject, Event $events) {
$attribute = updateAttribute(
databaseId: $databaseId,
collectionId: $collectionId,
key: $key,
dbForProject: $dbForProject,
events: $events,
type: Database::VAR_FLOAT,
default: $default,
required: $required,
min: $min,
max: $max
);
$formatOptions = $attribute->getAttribute('formatOptions', []);
if (!empty($formatOptions)) {
$attribute->setAttribute('min', \floatval($formatOptions['min']));
$attribute->setAttribute('max', \floatval($formatOptions['max']));
}
$response
->setStatusCode(Response::STATUS_CODE_OK)
->dynamic($attribute, Response::MODEL_ATTRIBUTE_FLOAT);
});
App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/boolean/:key')
->desc('Update Boolean Attribute')
->groups(['api', 'database', 'schema'])
->label('scope', 'collections.write')
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update')
->label('audits.event', 'attribute.update')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('usage.metric', 'collections.{scope}.requests.update')
->label('usage.params', ['databaseId:{request.databaseId}'])
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'updateBooleanAttribute')
->label('sdk.description', '/docs/references/databases/update-boolean-attribute.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_BOOLEAN)
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Boolean()), 'Default value for attribute when not provided. Cannot be set when attribute is required.')
->inject('response')
->inject('dbForProject')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, Response $response, Database $dbForProject, Event $events) {
$attribute = updateAttribute(
databaseId: $databaseId,
collectionId: $collectionId,
key: $key,
dbForProject: $dbForProject,
events: $events,
type: Database::VAR_BOOLEAN,
default: $default,
required: $required
);
$response
->setStatusCode(Response::STATUS_CODE_OK)
->dynamic($attribute, Response::MODEL_ATTRIBUTE_BOOLEAN);
});
App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/datetime/:key')
->desc('Update DateTime Attribute')
->groups(['api', 'database', 'schema'])
->label('scope', 'collections.write')
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update')
->label('audits.event', 'attribute.update')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('usage.metric', 'collections.{scope}.requests.update')
->label('usage.params', ['databaseId:{request.databaseId}'])
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'updateDatetimeAttribute')
->label('sdk.description', '/docs/references/databases/update-datetime-attribute.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_DATETIME)
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new DatetimeValidator()), 'Default value for attribute when not provided. Cannot be set when attribute is required.')
->inject('response')
->inject('dbForProject')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $events) {
$attribute = updateAttribute(
databaseId: $databaseId,
collectionId: $collectionId,
key: $key,
dbForProject: $dbForProject,
events: $events,
type: Database::VAR_DATETIME,
default: $default,
required: $required
);
$response
->setStatusCode(Response::STATUS_CODE_OK)
->dynamic($attribute, Response::MODEL_ATTRIBUTE_DATETIME);
});
App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key')
->alias('/v1/database/collections/:collectionId/attributes/:key', ['databaseId' => 'default'])
->desc('Delete Attribute')
@ -1483,7 +2010,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key
}
// Only update status if removing available attribute
if ($attribute->getAttribute('status' === 'available')) {
if ($attribute->getAttribute('status') === 'available') {
$attribute = $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'deleting'));
}

View file

@ -25,7 +25,6 @@ use Appwrite\Task\Validator\Cron;
use Appwrite\Utopia\Database\Validator\Queries\Deployments;
use Appwrite\Utopia\Database\Validator\Queries\Executions;
use Appwrite\Utopia\Database\Validator\Queries\Functions;
use Appwrite\Utopia\Database\Validator\Queries\Variables;
use Utopia\App;
use Utopia\Database\Database;
use Utopia\Database\Document;
@ -33,7 +32,6 @@ use Utopia\Database\DateTime;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Validator\ArrayList;
use Utopia\Validator\Assoc;
use Utopia\Validator\Text;
use Utopia\Validator\Range;
use Utopia\Validator\WhiteList;
@ -63,7 +61,7 @@ App::post('/v1/functions')
->label('sdk.response.model', Response::MODEL_FUNCTION)
->param('functionId', '', new CustomId(), 'Function ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('name', '', new Text(128), 'Function name. Max length: 128 chars.')
->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution roles. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.')
->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution roles. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true)
->param('runtime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Execution runtime.')
->param('events', [], new ArrayList(new ValidatorEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.', true)
->param('schedule', '', new Cron(), 'Schedule CRON syntax.', true)
@ -440,7 +438,7 @@ App::put('/v1/functions/:functionId')
->label('sdk.response.model', Response::MODEL_FUNCTION)
->param('functionId', '', new UID(), 'Function ID.')
->param('name', '', new Text(128), 'Function name. Max length: 128 chars.')
->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution roles. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.')
->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution roles. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true)
->param('events', [], new ArrayList(new ValidatorEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.', true)
->param('schedule', '', new Cron(), 'Schedule CRON syntax.', true)
->param('timeout', 15, new Range(1, (int) App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)), 'Maximum execution time in seconds.', true)
@ -601,8 +599,8 @@ App::post('/v1/functions/:functionId/deployments')
->label('sdk.response.model', Response::MODEL_DEPLOYMENT)
->param('functionId', '', new UID(), 'Function ID.')
->param('entrypoint', '', new Text('1028'), 'Entrypoint File.')
->param('code', [], new File(), 'Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.', false)
->param('activate', false, new Boolean(true), 'Automatically activate the deployment when it is finished building.', false)
->param('code', [], new File(), 'Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.', skipValidation: true)
->param('activate', false, new Boolean(true), 'Automatically activate the deployment when it is finished building.')
->inject('request')
->inject('response')
->inject('dbForProject')
@ -1348,7 +1346,7 @@ App::post('/v1/functions/:functionId/variables')
->label('sdk.response.model', Response::MODEL_VARIABLE)
->param('functionId', '', new UID(), 'Function unique ID.', false)
->param('key', null, new Text(Database::LENGTH_KEY), 'Variable key. Max length: ' . Database::LENGTH_KEY . ' chars.', false)
->param('value', null, new Text(8192), 'Variable value. Max length: 8192 chars.', false)
->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', false)
->inject('response')
->inject('dbForProject')
->action(function (string $functionId, string $key, string $value, Response $response, Database $dbForProject) {
@ -1464,7 +1462,7 @@ App::put('/v1/functions/:functionId/variables/:variableId')
->param('functionId', '', new UID(), 'Function unique ID.', false)
->param('variableId', '', new UID(), 'Variable unique ID.', false)
->param('key', null, new Text(255), 'Variable key. Max length: 255 chars.', false)
->param('value', null, new Text(8192), 'Variable value. Max length: 8192 chars.', true)
->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', true)
->inject('response')
->inject('dbForProject')
->action(function (string $functionId, string $variableId, string $key, ?string $value, Response $response, Database $dbForProject) {

View file

@ -30,7 +30,7 @@ App::get('/v1/graphql')
->label('sdk.response.model', Response::MODEL_ANY)
->label('abuse-limit', 60)
->label('abuse-time', 60)
->param('query', '', new Text(0), 'The query to execute.')
->param('query', '', new Text(0, 0), 'The query to execute.')
->param('operationName', '', new Text(256), 'The name of the operation to execute.', true)
->param('variables', '', new Text(0), 'The JSON encoded variables to use in the query.', true)
->inject('request')

View file

@ -23,7 +23,7 @@ use Utopia\Database\Helpers\Permission;
use Utopia\Database\Query;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\DatetimeValidator;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
use Utopia\Database\Validator\UID;
use Utopia\Domains\Domain;
use Utopia\Registry\Registry;

View file

@ -348,7 +348,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
->label('sdk.response.model', Response::MODEL_FILE)
->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](/docs/server/storage#createBucket).')
->param('fileId', '', new CustomId(), 'File ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('file', [], new File(), 'Binary file.', false)
->param('file', [], new File(), 'Binary file.', skipValidation: true)
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permission strings. By default, only the current user is granted all permissions. [Learn more about permissions](/docs/permissions).', true)
->inject('request')
->inject('response')

View file

@ -594,7 +594,7 @@ App::get('/.well-known/acme-challenge')
$uriChunks = \explode('/', $request->getURI());
$token = $uriChunks[\count($uriChunks) - 1];
$validator = new Text(100, [
$validator = new Text(100, allowList: [
...Text::NUMBERS,
...Text::ALPHABET_LOWER,
...Text::ALPHABET_UPPER,

View file

@ -15,6 +15,7 @@ use Utopia\Validator\Text;
use Utopia\Storage\Validator\File;
use Utopia\Validator\WhiteList;
use Utopia\Database\Helpers\ID;
use Utopia\Validator\Nullable;
App::get('/v1/mock/tests/foo')
->desc('Get Foo')
@ -428,6 +429,21 @@ App::get('/v1/mock/tests/general/empty')
$response->noContent();
});
App::post('/v1/mock/tests/general/nullable')
->desc('Nullable Test')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'general')
->label('sdk.method', 'nullable')
->label('sdk.description', 'Mock a nullable parameter.')
->label('sdk.mock', true)
->param('required', '', new Text(100), 'Sample string param')
->param('nullable', '', new Nullable(new Text(100)), 'Sample string param')
->param('optional', '', new Text(100), 'Sample string param', true)
->action(function (string $required, string $nullable, ?string $optional) {
});
/** Endpoint to test if required headers are sent from the SDK */
App::get('/v1/mock/tests/general/headers')
->desc('Get headers')

View file

@ -165,14 +165,14 @@ App::post('/v1/runtimes')
->desc("Create a new runtime server")
->param('runtimeId', '', new Text(64), 'Unique runtime ID.')
->param('source', '', new Text(0), 'Path to source files.')
->param('destination', '', new Text(0), 'Destination folder to store build files into.', true)
->param('destination', '', new Text(0, 0), 'Destination folder to store build files into.', true)
->param('vars', [], new Assoc(), 'Environment Variables required for the build.')
->param('commands', [], new ArrayList(new Text(1024), 100), 'Commands required to build the container. Maximum of 100 commands are allowed, each 1024 characters long.')
->param('runtime', '', new Text(128), 'Runtime for the cloud function.')
->param('baseImage', '', new Text(128), 'Base image name of the runtime.')
->param('entrypoint', '', new Text(256), 'Entrypoint of the code file.', true)
->param('remove', false, new Boolean(), 'Remove a runtime after execution.')
->param('workdir', '', new Text(256), 'Working directory.', true)
->param('workdir', '', new Text(256, 0), 'Working directory.', true)
->inject('orchestrationPool')
->inject('activeRuntimes')
->inject('response')
@ -459,7 +459,7 @@ App::post('/v1/execution')
->desc('Create an execution')
->param('runtimeId', '', new Text(64), 'The runtimeID to execute.')
->param('vars', [], new Assoc(), 'Environment variables required for the build.')
->param('data', '', new Text(8192), 'Data to be forwarded to the function, this is user specified.', true)
->param('data', '', new Text(8192, 0), 'Data to be forwarded to the function, this is user specified.', true)
->param('timeout', 15, new Range(1, (int) App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)), 'Function maximum execution time in seconds.')
->inject('activeRuntimes')
->inject('response')

View file

@ -92,7 +92,6 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) {
$collections = Config::getParam('collections', []);
try {
$redis->flushAll();
Console::success('[Setup] - Creating database: appwrite...');
$dbForConsole->create();
} catch (\Exception $e) {

View file

@ -53,7 +53,7 @@ use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\DatetimeValidator;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
use Utopia\Database\Validator\Structure;
use Utopia\Locale\Locale;
use Utopia\Messaging\Adapters\SMS\Mock;

View file

@ -43,16 +43,16 @@
"ext-sockets": "*",
"appwrite/php-clamav": "1.1.*",
"appwrite/php-runtimes": "0.11.*",
"utopia-php/abuse": "0.19.*",
"utopia-php/abuse": "0.21.*",
"utopia-php/analytics": "0.2.*",
"utopia-php/audit": "0.21.*",
"utopia-php/audit": "0.23.*",
"utopia-php/cache": "0.8.*",
"utopia-php/cli": "0.13.*",
"utopia-php/config": "0.2.*",
"utopia-php/database": "0.31.*",
"utopia-php/database": "0.33.*",
"utopia-php/preloader": "0.2.*",
"utopia-php/domains": "1.1.*",
"utopia-php/framework": "0.26.*",
"utopia-php/framework": "0.28.*",
"utopia-php/image": "0.5.*",
"utopia-php/locale": "0.4.*",
"utopia-php/logger": "0.3.*",

71
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "3e00aa37bea907b7dcca7f912402a392",
"content-hash": "db9e7adb4caf775eaa200d3888b65579",
"packages": [
{
"name": "adhocore/jwt",
@ -1808,23 +1808,23 @@
},
{
"name": "utopia-php/abuse",
"version": "0.19.0",
"version": "0.21.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/abuse.git",
"reference": "419b6e2e0a5dec35ea83a25758df9cd129b6c412"
"reference": "7483068b192b27d698da9534c80091f69666d5eb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/419b6e2e0a5dec35ea83a25758df9cd129b6c412",
"reference": "419b6e2e0a5dec35ea83a25758df9cd129b6c412",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/7483068b192b27d698da9534c80091f69666d5eb",
"reference": "7483068b192b27d698da9534c80091f69666d5eb",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-pdo": "*",
"php": ">=8.0",
"utopia-php/database": "0.31.*"
"utopia-php/database": "0.33.*"
},
"require-dev": {
"laravel/pint": "1.2.*",
@ -1851,9 +1851,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/abuse/issues",
"source": "https://github.com/utopia-php/abuse/tree/0.19.0"
"source": "https://github.com/utopia-php/abuse/tree/0.21.0"
},
"time": "2023-02-26T03:28:48+00:00"
"time": "2023-03-10T08:49:10+00:00"
},
{
"name": "utopia-php/analytics",
@ -1912,28 +1912,27 @@
},
{
"name": "utopia-php/audit",
"version": "0.21.0",
"version": "0.23.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/audit.git",
"reference": "7f9783a14718c82570c6effb35a3cb42c30b13a2"
"reference": "f16e893a22b93560d2af02afcb4761b3a940148a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/7f9783a14718c82570c6effb35a3cb42c30b13a2",
"reference": "7f9783a14718c82570c6effb35a3cb42c30b13a2",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/f16e893a22b93560d2af02afcb4761b3a940148a",
"reference": "f16e893a22b93560d2af02afcb4761b3a940148a",
"shasum": ""
},
"require": {
"ext-pdo": "*",
"php": ">=8.0",
"utopia-php/database": "0.31.*"
"utopia-php/database": "0.33.*"
},
"require-dev": {
"laravel/pint": "1.2.*",
"phpstan/phpstan": "^1.8",
"phpunit/phpunit": "^9.3",
"vimeo/psalm": "4.0.1"
"phpunit/phpunit": "^9.3"
},
"type": "library",
"autoload": {
@ -1955,9 +1954,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/audit/issues",
"source": "https://github.com/utopia-php/audit/tree/0.21.0"
"source": "https://github.com/utopia-php/audit/tree/0.23.0"
},
"time": "2023-02-26T03:28:30+00:00"
"time": "2023-03-10T08:51:26+00:00"
},
{
"name": "utopia-php/cache",
@ -2114,23 +2113,23 @@
},
{
"name": "utopia-php/database",
"version": "0.31.0",
"version": "0.33.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
"reference": "61f9f4743a317f1d78558a5f981adf74e7fdc931"
"reference": "7453256728053cddfb0c872ac8ca60157c4d8a11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/61f9f4743a317f1d78558a5f981adf74e7fdc931",
"reference": "61f9f4743a317f1d78558a5f981adf74e7fdc931",
"url": "https://api.github.com/repos/utopia-php/database/zipball/7453256728053cddfb0c872ac8ca60157c4d8a11",
"reference": "7453256728053cddfb0c872ac8ca60157c4d8a11",
"shasum": ""
},
"require": {
"php": ">=8.0",
"utopia-php/cache": "0.8.*",
"utopia-php/framework": "0.*.*",
"utopia-php/mongo": "0.0.2"
"utopia-php/mongo": "0.1.*"
},
"require-dev": {
"ext-mongodb": "*",
@ -2162,9 +2161,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/0.31.0"
"source": "https://github.com/utopia-php/database/tree/0.33.0"
},
"time": "2023-02-23T09:49:44+00:00"
"time": "2023-03-08T08:46:35+00:00"
},
{
"name": "utopia-php/domains",
@ -2222,16 +2221,16 @@
},
{
"name": "utopia-php/framework",
"version": "0.26.0",
"version": "0.28.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/framework.git",
"reference": "e8da5576370366d3bf9c574ec855f8c96fe4f34e"
"reference": "7f22c556fc5991e54e5811a68fb39809b21bda55"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/framework/zipball/e8da5576370366d3bf9c574ec855f8c96fe4f34e",
"reference": "e8da5576370366d3bf9c574ec855f8c96fe4f34e",
"url": "https://api.github.com/repos/utopia-php/framework/zipball/7f22c556fc5991e54e5811a68fb39809b21bda55",
"reference": "7f22c556fc5991e54e5811a68fb39809b21bda55",
"shasum": ""
},
"require": {
@ -2260,9 +2259,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/framework/issues",
"source": "https://github.com/utopia-php/framework/tree/0.26.0"
"source": "https://github.com/utopia-php/framework/tree/0.28.1"
},
"time": "2023-01-13T08:14:43+00:00"
"time": "2023-03-02T08:16:01+00:00"
},
{
"name": "utopia-php/image",
@ -2470,16 +2469,16 @@
},
{
"name": "utopia-php/mongo",
"version": "0.0.2",
"version": "0.1.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/mongo.git",
"reference": "62f9a9c0201af91b6d0dd4f0aa8a335ec9b56a1e"
"reference": "f4b6ec74c5323ca16c500dd19109518d2eeb1f8f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/mongo/zipball/62f9a9c0201af91b6d0dd4f0aa8a335ec9b56a1e",
"reference": "62f9a9c0201af91b6d0dd4f0aa8a335ec9b56a1e",
"url": "https://api.github.com/repos/utopia-php/mongo/zipball/f4b6ec74c5323ca16c500dd19109518d2eeb1f8f",
"reference": "f4b6ec74c5323ca16c500dd19109518d2eeb1f8f",
"shasum": ""
},
"require": {
@ -2524,9 +2523,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/mongo/issues",
"source": "https://github.com/utopia-php/mongo/tree/0.0.2"
"source": "https://github.com/utopia-php/mongo/tree/0.1.0"
},
"time": "2022-11-08T11:58:46+00:00"
"time": "2023-01-12T14:02:08+00:00"
},
{
"name": "utopia-php/orchestration",

View file

@ -0,0 +1 @@
Update an email attribute. Changing the `default` value will not update already existing documents.

View file

@ -0,0 +1 @@
Update an enum attribute. Changing the `default` value will not update already existing documents.

View file

@ -0,0 +1 @@
Update a float attribute. Changing the `default` value will not update already existing documents.

View file

@ -0,0 +1 @@
Update an integer attribute. Changing the `default` value will not update already existing documents.

View file

@ -0,0 +1 @@
Update an ip attribute. Changing the `default` value will not update already existing documents.

View file

@ -0,0 +1 @@
Update a string attribute. Changing the `default` value will not update already existing documents.

View file

@ -0,0 +1 @@
Update an url attribute. Changing the `default` value will not update already existing documents.

View file

@ -146,6 +146,7 @@ class Exception extends \Exception
public const ATTRIBUTE_ALREADY_EXISTS = 'attribute_already_exists';
public const ATTRIBUTE_LIMIT_EXCEEDED = 'attribute_limit_exceeded';
public const ATTRIBUTE_VALUE_INVALID = 'attribute_value_invalid';
public const ATTRIBUTE_TYPE_INVALID = 'attribute_type_invalid';
/** Indexes */
public const INDEX_NOT_FOUND = 'index_not_found';

View file

@ -11,6 +11,7 @@ use GraphQL\Type\Definition\UnionType;
use Utopia\App;
use Utopia\Route;
use Utopia\Validator;
use Utopia\Validator\Nullable;
class Mapper
{
@ -109,9 +110,6 @@ class Mapper
'type' => $parameterType,
'description' => $parameter['description'],
];
if ($parameter['optional']) {
$params[$name]['defaultValue'] = $parameter['default'];
}
}
$field = [
@ -224,6 +222,12 @@ class Mapper
? \call_user_func_array($validator, $utopia->getResources($injections))
: $validator;
$isNullable = $validator instanceof Nullable;
if ($isNullable) {
$validator = $validator->getValidator();
}
switch ((!empty($validator)) ? $validator::class : '') {
case 'Appwrite\Network\Validator\CNAME':
case 'Appwrite\Task\Validator\Cron':
@ -294,7 +298,7 @@ class Mapper
break;
}
if ($required) {
if ($required && !$isNullable) {
$type = Type::nonNull($type);
}

View file

@ -50,6 +50,7 @@ abstract class Migration
'1.1.2' => 'V16',
'1.2.0' => 'V17',
'1.2.1' => 'V17',
'1.3.0' => 'V18',
];
/**

View file

@ -80,13 +80,7 @@ class V18 extends Migration
/**
* Bump version number.
*/
$document->setAttribute('version', '1.2.0');
break;
case 'projects':
/**
* Bump version number.
*/
$document->setAttribute('passwordHistory', []);
$document->setAttribute('version', '1.3.0');
/**
* Set default passwordHistory
@ -95,7 +89,12 @@ class V18 extends Migration
'passwordHistory' => 0,
'passwordDictionary' => false,
]));
break;
case 'users':
/**
* Default Password history
*/
$document->setAttribute('passwordHistory', []);
break;
}

View file

@ -8,6 +8,7 @@ use Appwrite\Utopia\Response\Model;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Validator;
use Utopia\Validator\Nullable;
class OpenAPI3 extends Format
{
@ -284,6 +285,13 @@ class OpenAPI3 extends Format
}
}
$isNullable = $validator instanceof Nullable;
if ($isNullable) {
/** @var Nullable $validator */
$validator = $validator->getValidator();
}
switch ((!empty($validator)) ? \get_class($validator) : '') {
case 'Utopia\Validator\Text':
$node['schema']['type'] = $validator->getType();
@ -449,6 +457,10 @@ class OpenAPI3 extends Format
if ($node['x-global'] ?? false) {
$body['content'][$consumes[0]]['schema']['properties'][$name]['x-global'] = true;
}
if ($isNullable) {
$body['content'][$consumes[0]]['schema']['properties'][$name]['x-nullable'] = true;
}
}
$url = \str_replace(':' . $name, '{' . $name . '}', $url);

View file

@ -8,6 +8,7 @@ use Appwrite\Utopia\Response\Model;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Validator;
use Utopia\Validator\Nullable;
class Swagger2 extends Format
{
@ -285,6 +286,13 @@ class Swagger2 extends Format
}
}
$isNullable = $validator instanceof Nullable;
if ($isNullable) {
/** @var Nullable $validator */
$validator = $validator->getValidator();
}
switch ((!empty($validator)) ? \get_class($validator) : '') {
case 'Utopia\Validator\Text':
$node['type'] = $validator->getType();
@ -448,6 +456,10 @@ class Swagger2 extends Format
$body['schema']['properties'][$name]['x-global'] = true;
}
if ($isNullable) {
$body['schema']['properties'][$name]['x-nullable'] = true;
}
if (\array_key_exists('items', $node)) {
$body['schema']['properties'][$name]['items'] = $node['items'];
}

View file

@ -11,7 +11,7 @@ use CURLFile;
use Tests\E2E\Services\Functions\FunctionsBase;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Validator\DatetimeValidator;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
class UsageTest extends Scope
{

View file

@ -46,14 +46,7 @@ trait ProjectCustom
'name' => 'Demo Project',
'teamId' => $team['body']['$id'],
'description' => 'Demo Project Description',
'logo' => '',
'url' => 'https://appwrite.io',
'legalName' => '',
'legalCountry' => '',
'legalState' => '',
'legalCity' => '',
'legalAddress' => '',
'legalTaxId' => '',
]);
$this->assertEquals(201, $project['headers']['status-code']);
@ -111,8 +104,6 @@ trait ProjectCustom
],
'url' => 'http://request-catcher:5000/webhook',
'security' => false,
'httpUser' => '',
'httpPass' => '',
]);
$this->assertEquals(201, $webhook['headers']['status-code']);

View file

@ -6,7 +6,7 @@ use Appwrite\Tests\Retry;
use Tests\E2E\Client;
use Utopia\Database\Helpers\ID;
use Utopia\Database\DateTime;
use Utopia\Database\Validator\DatetimeValidator;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
trait AccountBase
{

View file

@ -10,7 +10,7 @@ use Tests\E2E\Scopes\ProjectCustom;
use Tests\E2E\Scopes\SideClient;
use Utopia\Database\DateTime;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Validator\DatetimeValidator;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
use function sleep;

View file

@ -8,7 +8,7 @@ use Utopia\Database\DateTime;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Validator\DatetimeValidator;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
trait DatabasesBase
{

File diff suppressed because it is too large Load diff

View file

@ -109,6 +109,7 @@ class FunctionsCustomClientTest extends Scope
], [
'entrypoint' => 'index.php',
'code' => new CURLFile($code, 'application/x-gzip', \basename($code)),
'activate' => true
]);
$deploymentId = $deployment['body']['$id'] ?? '';
@ -223,6 +224,7 @@ class FunctionsCustomClientTest extends Scope
], [
'entrypoint' => 'index.php',
'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), //different tarball names intentional
'activate' => true
]);
$deploymentId = $deployment['body']['$id'] ?? '';
@ -321,6 +323,7 @@ class FunctionsCustomClientTest extends Scope
], [
'entrypoint' => 'index.php',
'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), //different tarball names intentional
'activate' => true
]);
$deploymentId = $deployment['body']['$id'] ?? '';
@ -549,6 +552,7 @@ class FunctionsCustomClientTest extends Scope
], [
'entrypoint' => 'index.php',
'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), //different tarball names intentional
'activate' => true
]);
$deploymentId = $deployment['body']['$id'] ?? '';

View file

@ -9,7 +9,7 @@ use Tests\E2E\Scopes\ProjectCustom;
use Tests\E2E\Scopes\Scope;
use Tests\E2E\Scopes\SideServer;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Validator\DatetimeValidator;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
class FunctionsCustomServerTest extends Scope
{
@ -363,6 +363,7 @@ class FunctionsCustomServerTest extends Scope
], $this->getHeaders()), [
'entrypoint' => 'index.php',
'code' => new CURLFile($code, 'application/x-gzip', \basename($code)),
'activate' => true
]);
$deploymentId = $deployment['body']['$id'] ?? '';
@ -411,6 +412,7 @@ class FunctionsCustomServerTest extends Scope
$largeTag = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/deployments', array_merge($headers, $this->getHeaders()), [
'entrypoint' => 'index.php',
'code' => $curlFile,
'activate' => true
]);
$counter++;
$id = $largeTag['body']['$id'];
@ -741,7 +743,6 @@ class FunctionsCustomServerTest extends Scope
/**
* Test for SUCCESS
*/
$execution = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/executions', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
@ -752,7 +753,6 @@ class FunctionsCustomServerTest extends Scope
$this->assertEquals(201, $execution['headers']['status-code']);
$this->assertEquals('completed', $execution['body']['status']);
$this->assertStringContainsString($data['deploymentId'], $execution['body']['response']);
$this->assertStringContainsString('Test1', $execution['body']['response']);
$this->assertStringContainsString('http', $execution['body']['response']);
$this->assertStringContainsString('PHP', $execution['body']['response']);
@ -869,7 +869,6 @@ class FunctionsCustomServerTest extends Scope
'name' => 'Test ' . $name,
'runtime' => $name,
'events' => [],
'schedule' => '',
'timeout' => $timeout,
]);
@ -953,7 +952,6 @@ class FunctionsCustomServerTest extends Scope
'name' => 'Test ' . $name,
'runtime' => $name,
'events' => [],
'schedule' => '',
'timeout' => $timeout,
]);
@ -967,6 +965,7 @@ class FunctionsCustomServerTest extends Scope
], $this->getHeaders()), [
'entrypoint' => $entrypoint,
'code' => new CURLFile($code, 'application/x-gzip', basename($code)),
'activate' => true
]);
$deploymentId = $deployment['body']['$id'] ?? '';
@ -1063,7 +1062,6 @@ class FunctionsCustomServerTest extends Scope
'name' => 'Test ' . $name,
'runtime' => $name,
'events' => [],
'schedule' => '',
'timeout' => $timeout,
]);
@ -1176,7 +1174,6 @@ class FunctionsCustomServerTest extends Scope
'name' => 'Test ' . $name,
'runtime' => $name,
'events' => [],
'schedule' => '',
'timeout' => $timeout,
]);
@ -1290,7 +1287,6 @@ class FunctionsCustomServerTest extends Scope
'name' => 'Test ' . $name,
'runtime' => $name,
'events' => [],
'schedule' => '',
'timeout' => $timeout,
]);
@ -1404,7 +1400,6 @@ class FunctionsCustomServerTest extends Scope
'name' => 'Test ' . $name,
'runtime' => $name,
'events' => [],
'schedule' => '',
'timeout' => $timeout,
]);

View file

@ -26,6 +26,15 @@ trait Base
public static string $CREATE_IP_ATTRIBUTE = 'create_ip_attribute';
public static string $CREATE_ENUM_ATTRIBUTE = 'create_enum_attribute';
public static string $CREATE_DATETIME_ATTRIBUTE = 'create_datetime_attribute';
public static string $UPDATE_STRING_ATTRIBUTE = 'update_string_attribute';
public static string $UPDATE_INTEGER_ATTRIBUTE = 'update_integer_attribute';
public static string $UPDATE_FLOAT_ATTRIBUTE = 'update_float_attribute';
public static string $UPDATE_BOOLEAN_ATTRIBUTE = 'update_boolean_attribute';
public static string $UPDATE_URL_ATTRIBUTE = 'update_url_attribute';
public static string $UPDATE_EMAIL_ATTRIBUTE = 'update_email_attribute';
public static string $UPDATE_IP_ATTRIBUTE = 'update_ip_attribute';
public static string $UPDATE_ENUM_ATTRIBUTE = 'update_enum_attribute';
public static string $UPDATE_DATETIME_ATTRIBUTE = 'update_datetime_attribute';
public static string $GET_ATTRIBUTES = 'get_attributes';
public static string $GET_ATTRIBUTE = 'get_attribute';
public static string $DELETE_ATTRIBUTE = 'delete_attribute';
@ -451,6 +460,74 @@ trait Base
array
}
}';
case self::$UPDATE_STRING_ATTRIBUTE:
return 'mutation updateStringAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){
databasesUpdateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) {
required
default
}
}';
case self::$UPDATE_INTEGER_ATTRIBUTE:
return 'mutation updateIntegerAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $min: Int!, $max: Int!, $default: Int){
databasesUpdateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, min: $min, max: $max, default: $default) {
required
min
max
default
}
}';
case self::$UPDATE_FLOAT_ATTRIBUTE:
return 'mutation updateFloatAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $min: Float!, $max: Float!, $default: Float){
databasesUpdateFloatAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default) {
required
min
max
default
}
}';
case self::$UPDATE_BOOLEAN_ATTRIBUTE:
return 'mutation updateBooleanAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: Boolean){
databasesUpdateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) {
required
default
}
}';
case self::$UPDATE_URL_ATTRIBUTE:
return 'mutation updateUrlAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){
databasesUpdateUrlAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) {
required
default
}
}';
case self::$UPDATE_EMAIL_ATTRIBUTE:
return 'mutation updateEmailAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){
databasesUpdateEmailAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) {
required
default
}
}';
case self::$UPDATE_IP_ATTRIBUTE:
return 'mutation updateIpAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){
databasesUpdateIpAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) {
required
default
}
}';
case self::$UPDATE_ENUM_ATTRIBUTE:
return 'mutation updateEnumAttribute($databaseId: String!, $collectionId: String!, $key: String!, $elements: [String!]!, $required: Boolean!, $default: String){
databasesUpdateEnumAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, elements: $elements, required: $required, default: $default) {
elements
required
default
}
}';
case self::$UPDATE_DATETIME_ATTRIBUTE:
return 'mutation updateDatetimeAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){
databasesUpdateDatetimeAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) {
required
default
}
}';
case self::$CREATE_INDEX:
return 'mutation createIndex($databaseId: String!, $collectionId: String!, $key: String!, $type: String!, $attributes: [String!]!, $orders: [String!]){
databasesCreateIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key, type: $type, attributes: $attributes, orders: $orders) {

View file

@ -112,6 +112,42 @@ class DatabaseServerTest extends Scope
return $data;
}
/**
* @depends testCreateStringAttribute
* @throws Exception
*/
public function testUpdateStringAttribute($data): array
{
// Wait for attributes to be available
sleep(3);
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::$UPDATE_STRING_ATTRIBUTE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'collectionId' => $data['collection']['_id'],
'key' => 'name',
'required' => false,
'default' => 'Default Value',
]
];
$attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($attribute['body']['data']);
$this->assertIsArray($attribute['body']['data']['databasesUpdateStringAttribute']);
$this->assertFalse($attribute['body']['data']['databasesUpdateStringAttribute']['required']);
$this->assertEquals('Default Value', $attribute['body']['data']['databasesUpdateStringAttribute']['default']);
$this->assertEquals(200, $attribute['headers']['status-code']);
return $data;
}
/**
* @depends testCreateCollection
* @throws Exception
@ -144,6 +180,46 @@ class DatabaseServerTest extends Scope
return $data;
}
/**
* @depends testCreateIntegerAttribute
* @throws Exception
*/
public function testUpdateIntegerAttribute($data): array
{
// Wait for attributes to be available
sleep(3);
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::$UPDATE_INTEGER_ATTRIBUTE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'collectionId' => $data['collection']['_id'],
'key' => 'age',
'required' => false,
'min' => 12,
'max' => 160,
'default' => 50
]
];
$attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($attribute['body']['data']);
$this->assertIsArray($attribute['body']['data']['databasesUpdateIntegerAttribute']);
$this->assertFalse($attribute['body']['data']['databasesUpdateIntegerAttribute']['required']);
$this->assertEquals(12, $attribute['body']['data']['databasesUpdateIntegerAttribute']['min']);
$this->assertEquals(160, $attribute['body']['data']['databasesUpdateIntegerAttribute']['max']);
$this->assertEquals(50, $attribute['body']['data']['databasesUpdateIntegerAttribute']['default']);
$this->assertEquals(200, $attribute['headers']['status-code']);
return $data;
}
/**
* @depends testCreateCollection
* @throws Exception
@ -174,6 +250,42 @@ class DatabaseServerTest extends Scope
return $data;
}
/**
* @depends testCreateBooleanAttribute
* @throws Exception
*/
public function testUpdateBooleanAttribute($data): array
{
// Wait for attributes to be available
sleep(3);
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::$UPDATE_BOOLEAN_ATTRIBUTE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'collectionId' => $data['collection']['_id'],
'key' => 'alive',
'required' => false,
'default' => true
]
];
$attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($attribute['body']['data']);
$this->assertIsArray($attribute['body']['data']['databasesUpdateBooleanAttribute']);
$this->assertFalse($attribute['body']['data']['databasesUpdateBooleanAttribute']['required']);
$this->assertTrue($attribute['body']['data']['databasesUpdateBooleanAttribute']['default']);
$this->assertEquals(200, $attribute['headers']['status-code']);
return $data;
}
/**
* @depends testCreateCollection
* @throws Exception
@ -207,6 +319,46 @@ class DatabaseServerTest extends Scope
return $data;
}
/**
* @depends testCreateFloatAttribute
* @throws Exception
*/
public function testUpdateFloatAttribute($data): array
{
// Wait for attributes to be available
sleep(3);
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::$UPDATE_FLOAT_ATTRIBUTE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'collectionId' => $data['collection']['_id'],
'key' => 'salary',
'required' => false,
'min' => 100.0,
'max' => 1000000.0,
'default' => 2500.0
]
];
$attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($attribute['body']['data']);
$this->assertIsArray($attribute['body']['data']['databasesUpdateFloatAttribute']);
$this->assertFalse($attribute['body']['data']['databasesUpdateFloatAttribute']['required']);
$this->assertEquals(100.0, $attribute['body']['data']['databasesUpdateFloatAttribute']['min']);
$this->assertEquals(1000000.0, $attribute['body']['data']['databasesUpdateFloatAttribute']['max']);
$this->assertEquals(2500.0, $attribute['body']['data']['databasesUpdateFloatAttribute']['default']);
$this->assertEquals(200, $attribute['headers']['status-code']);
return $data;
}
/**
* @depends testCreateCollection
* @throws Exception
@ -237,6 +389,42 @@ class DatabaseServerTest extends Scope
return $data;
}
/**
* @depends testCreateEmailAttribute
* @throws Exception
*/
public function testUpdateEmailAttribute($data): array
{
// Wait for attributes to be available
sleep(3);
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::$UPDATE_EMAIL_ATTRIBUTE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'collectionId' => $data['collection']['_id'],
'key' => 'email',
'required' => false,
'default' => 'torsten@appwrite.io',
]
];
$attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($attribute['body']['data']);
$this->assertIsArray($attribute['body']['data']['databasesUpdateEmailAttribute']);
$this->assertFalse($attribute['body']['data']['databasesUpdateEmailAttribute']['required']);
$this->assertEquals('torsten@appwrite.io', $attribute['body']['data']['databasesUpdateEmailAttribute']['default']);
$this->assertEquals(200, $attribute['headers']['status-code']);
return $data;
}
/**
* @depends testCreateCollection
* @throws Exception
@ -272,6 +460,50 @@ class DatabaseServerTest extends Scope
return $data;
}
/**
* @depends testCreateEnumAttribute
* @throws Exception
*/
public function testUpdateEnumAttribute($data): array
{
// Wait for attributes to be available
sleep(3);
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::$UPDATE_ENUM_ATTRIBUTE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'collectionId' => $data['collection']['_id'],
'key' => 'role',
'required' => false,
'elements' => [
'crew',
'tech',
'actor'
],
'default' => 'tech'
]
];
$attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($attribute['body']['data']);
$this->assertIsArray($attribute['body']['data']['databasesUpdateEnumAttribute']);
$this->assertFalse($attribute['body']['data']['databasesUpdateEnumAttribute']['required']);
$this->assertEquals('tech', $attribute['body']['data']['databasesUpdateEnumAttribute']['default']);
$this->assertContains('tech', $attribute['body']['data']['databasesUpdateEnumAttribute']['elements']);
$this->assertNotContains('guest', $attribute['body']['data']['databasesUpdateEnumAttribute']['elements']);
$this->assertEquals(200, $attribute['headers']['status-code']);
return $data;
}
/**
* @depends testCreateCollection
* @throws Exception
@ -302,6 +534,42 @@ class DatabaseServerTest extends Scope
return $data;
}
/**
* @depends testCreateDatetimeAttribute
* @throws Exception
*/
public function testUpdateDatetimeAttribute($data): array
{
// Wait for attributes to be available
sleep(3);
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::$UPDATE_DATETIME_ATTRIBUTE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'collectionId' => $data['collection']['_id'],
'key' => 'dob',
'required' => false,
'default' => '2000-01-01T00:00:00Z'
]
];
$attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($attribute['body']['data']);
$this->assertIsArray($attribute['body']['data']['databasesUpdateDatetimeAttribute']);
$this->assertFalse($attribute['body']['data']['databasesUpdateDatetimeAttribute']['required']);
$this->assertEquals('2000-01-01T00:00:00Z', $attribute['body']['data']['databasesUpdateDatetimeAttribute']['default']);
$this->assertEquals(200, $attribute['headers']['status-code']);
return $data;
}
/**
* @depends testCreateCollection
* @throws Exception
@ -333,6 +601,42 @@ class DatabaseServerTest extends Scope
return $data;
}
/**
* @depends testCreateIPAttribute
* @throws Exception
*/
public function testUpdateIPAttribute($data): array
{
// Wait for attributes to be available
sleep(3);
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::$UPDATE_IP_ATTRIBUTE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'collectionId' => $data['collection']['_id'],
'key' => 'ip',
'required' => false,
'default' => '127.0.0.1'
]
];
$attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($attribute['body']['data']);
$this->assertIsArray($attribute['body']['data']['databasesUpdateIpAttribute']);
$this->assertFalse($attribute['body']['data']['databasesUpdateIpAttribute']['required']);
$this->assertEquals('127.0.0.1', $attribute['body']['data']['databasesUpdateIpAttribute']['default']);
$this->assertEquals(200, $attribute['headers']['status-code']);
return $data;
}
/**
* @depends testCreateCollection
* @throws Exception
@ -365,15 +669,46 @@ class DatabaseServerTest extends Scope
}
/**
* @depends testCreateStringAttribute
* @depends testCreateIntegerAttribute
* @depends testCreateURLAttribute
* @throws Exception
*/
public function testCreateIndex($data): array
public function testUpdateURLAttribute($data): void
{
// Wait for attributes to be available
sleep(3);
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::$UPDATE_URL_ATTRIBUTE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'collectionId' => $data['collection']['_id'],
'key' => 'url',
'required' => false,
'default' => 'https://cloud.appwrite.io'
]
];
$attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($attribute['body']['data']);
$this->assertIsArray($attribute['body']['data']['databasesUpdateUrlAttribute']);
$this->assertFalse($attribute['body']['data']['databasesUpdateUrlAttribute']['required']);
$this->assertEquals('https://cloud.appwrite.io', $attribute['body']['data']['databasesUpdateUrlAttribute']['default']);
$this->assertEquals(200, $attribute['headers']['status-code']);
}
/**
* @depends testUpdateStringAttribute
* @depends testUpdateIntegerAttribute
* @throws Exception
*/
public function testCreateIndex($data): array
{
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::$CREATE_INDEX);
$gqlPayload = [
@ -407,10 +742,10 @@ class DatabaseServerTest extends Scope
}
/**
* @depends testCreateStringAttribute
* @depends testCreateIntegerAttribute
* @depends testCreateBooleanAttribute
* @depends testCreateEnumAttribute
* @depends testUpdateStringAttribute
* @depends testUpdateIntegerAttribute
* @depends testUpdateBooleanAttribute
* @depends testUpdateEnumAttribute
* @throws Exception
*/
public function testCreateDocument($data): array
@ -458,45 +793,45 @@ class DatabaseServerTest extends Scope
];
}
// /**
// * @depends testCreateStringAttribute
// * @depends testCreateIntegerAttribute
// * @depends testCreateBooleanAttribute
// * @depends testCreateFloatAttribute
// * @depends testCreateEmailAttribute
// * @depends testCreateEnumAttribute
// * @depends testCreateDatetimeAttribute
// * @throws Exception
// */
// public function testCreateCustomEntity(): array
// {
// $projectId = $this->getProject()['$id'];
// $query = $this->getQuery(self::$CREATE_CUSTOM_ENTITY);
// $gqlPayload = [
// 'query' => $query,
// 'variables' => [
// 'name' => 'John Doe',
// 'age' => 35,
// 'alive' => true,
// 'salary' => 9999.9,
// 'email' => 'johndoe@appwrite.io',
// 'role' => 'crew',
// 'dob' => '2000-01-01T00:00:00Z',
// ]
// ];
//
// $actor = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
// 'content-type' => 'application/json',
// 'x-appwrite-project' => $projectId,
// ], $this->getHeaders()), $gqlPayload);
//
// $this->assertArrayNotHasKey('errors', $actor['body']);
// $this->assertIsArray($actor['body']['data']);
// $actor = $actor['body']['data']['actorsCreate'];
// $this->assertIsArray($actor);
//
// return $actor;
// }
// /**
// * @depends testCreateStringAttribute
// * @depends testCreateIntegerAttribute
// * @depends testCreateBooleanAttribute
// * @depends testCreateFloatAttribute
// * @depends testCreateEmailAttribute
// * @depends testCreateEnumAttribute
// * @depends testCreateDatetimeAttribute
// * @throws Exception
// */
// public function testCreateCustomEntity(): array
// {
// $projectId = $this->getProject()['$id'];
// $query = $this->getQuery(self::$CREATE_CUSTOM_ENTITY);
// $gqlPayload = [
// 'query' => $query,
// 'variables' => [
// 'name' => 'John Doe',
// 'age' => 35,
// 'alive' => true,
// 'salary' => 9999.9,
// 'email' => 'johndoe@appwrite.io',
// 'role' => 'crew',
// 'dob' => '2000-01-01T00:00:00Z',
// ]
// ];
//
// $actor = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
// 'content-type' => 'application/json',
// 'x-appwrite-project' => $projectId,
// ], $this->getHeaders()), $gqlPayload);
//
// $this->assertArrayNotHasKey('errors', $actor['body']);
// $this->assertIsArray($actor['body']['data']);
// $actor = $actor['body']['data']['actorsCreate'];
// $this->assertIsArray($actor);
//
// return $actor;
// }
public function testGetDatabases(): void
{
@ -593,8 +928,8 @@ class DatabaseServerTest extends Scope
}
/**
* @depends testCreateStringAttribute
* @depends testCreateIntegerAttribute
* @depends testUpdateStringAttribute
* @depends testUpdateIntegerAttribute
* @throws Exception
*/
public function testGetAttributes($data): void
@ -752,52 +1087,52 @@ class DatabaseServerTest extends Scope
$this->assertIsArray($document['body']['data']['databasesGetDocument']);
}
// /**
// * @depends testCreateCustomEntity
// * @throws Exception
// */
// public function testGetCustomEntities($data)
// {
// $projectId = $this->getProject()['$id'];
// $query = $this->getQuery(self::$GET_CUSTOM_ENTITIES);
// $gqlPayload = [
// 'query' => $query,
// ];
//
// $customEntities = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
// 'content-type' => 'application/json',
// 'x-appwrite-project' => $projectId,
// ], $this->getHeaders()), $gqlPayload);
//
// $this->assertArrayNotHasKey('errors', $customEntities['body']);
// $this->assertIsArray($customEntities['body']['data']);
// $this->assertIsArray($customEntities['body']['data']['actorsList']);
// }
//
// /**
// * @depends testCreateCustomEntity
// * @throws Exception
// */
// public function testGetCustomEntity($data)
// {
// $projectId = $this->getProject()['$id'];
// $query = $this->getQuery(self::$GET_CUSTOM_ENTITY);
// $gqlPayload = [
// 'query' => $query,
// 'variables' => [
// 'id' => $data['id'],
// ]
// ];
//
// $entity = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
// 'content-type' => 'application/json',
// 'x-appwrite-project' => $projectId,
// ], $this->getHeaders()), $gqlPayload);
//
// $this->assertArrayNotHasKey('errors', $entity['body']);
// $this->assertIsArray($entity['body']['data']);
// $this->assertIsArray($entity['body']['data']['actorsGet']);
// }
// /**
// * @depends testCreateCustomEntity
// * @throws Exception
// */
// public function testGetCustomEntities($data)
// {
// $projectId = $this->getProject()['$id'];
// $query = $this->getQuery(self::$GET_CUSTOM_ENTITIES);
// $gqlPayload = [
// 'query' => $query,
// ];
//
// $customEntities = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
// 'content-type' => 'application/json',
// 'x-appwrite-project' => $projectId,
// ], $this->getHeaders()), $gqlPayload);
//
// $this->assertArrayNotHasKey('errors', $customEntities['body']);
// $this->assertIsArray($customEntities['body']['data']);
// $this->assertIsArray($customEntities['body']['data']['actorsList']);
// }
//
// /**
// * @depends testCreateCustomEntity
// * @throws Exception
// */
// public function testGetCustomEntity($data)
// {
// $projectId = $this->getProject()['$id'];
// $query = $this->getQuery(self::$GET_CUSTOM_ENTITY);
// $gqlPayload = [
// 'query' => $query,
// 'variables' => [
// 'id' => $data['id'],
// ]
// ];
//
// $entity = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
// 'content-type' => 'application/json',
// 'x-appwrite-project' => $projectId,
// ], $this->getHeaders()), $gqlPayload);
//
// $this->assertArrayNotHasKey('errors', $entity['body']);
// $this->assertIsArray($entity['body']['data']);
// $this->assertIsArray($entity['body']['data']['actorsGet']);
// }
/**
* @depends testCreateDatabase
@ -885,33 +1220,33 @@ class DatabaseServerTest extends Scope
$this->assertStringContainsString('New Document Name', $document['data']);
}
// /**
// * @depends testCreateCustomEntity
// * @throws Exception
// */
// public function testUpdateCustomEntity(array $data)
// {
// $projectId = $this->getProject()['$id'];
// $query = $this->getQuery(self::$UPDATE_CUSTOM_ENTITY);
// $gqlPayload = [
// 'query' => $query,
// 'variables' => [
// 'id' => $data['id'],
// 'name' => 'New Custom Entity Name',
// ]
// ];
//
// $entity = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
// 'content-type' => 'application/json',
// 'x-appwrite-project' => $projectId,
// ], $this->getHeaders()), $gqlPayload);
//
// $this->assertArrayNotHasKey('errors', $entity['body']);
// $this->assertIsArray($entity['body']['data']);
// $entity = $entity['body']['data']['actorsUpdate'];
// $this->assertIsArray($entity);
// $this->assertStringContainsString('New Custom Entity Name', $entity['name']);
// }
// /**
// * @depends testCreateCustomEntity
// * @throws Exception
// */
// public function testUpdateCustomEntity(array $data)
// {
// $projectId = $this->getProject()['$id'];
// $query = $this->getQuery(self::$UPDATE_CUSTOM_ENTITY);
// $gqlPayload = [
// 'query' => $query,
// 'variables' => [
// 'id' => $data['id'],
// 'name' => 'New Custom Entity Name',
// ]
// ];
//
// $entity = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
// 'content-type' => 'application/json',
// 'x-appwrite-project' => $projectId,
// ], $this->getHeaders()), $gqlPayload);
//
// $this->assertArrayNotHasKey('errors', $entity['body']);
// $this->assertIsArray($entity['body']['data']);
// $entity = $entity['body']['data']['actorsUpdate'];
// $this->assertIsArray($entity);
// $this->assertStringContainsString('New Custom Entity Name', $entity['name']);
// }
/**
* @depends testCreateDocument
@ -939,32 +1274,32 @@ class DatabaseServerTest extends Scope
$this->assertEquals(204, $document['headers']['status-code']);
}
// /**
// * @depends testCreateCustomEntity
// * @throws Exception
// */
// public function testDeleteCustomEntity(array $data)
// {
// $projectId = $this->getProject()['$id'];
// $query = $this->getQuery(self::$DELETE_CUSTOM_ENTITY);
// $gqlPayload = [
// 'query' => $query,
// 'variables' => [
// 'id' => $data['id'],
// ]
// ];
//
// $entity = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
// 'content-type' => 'application/json',
// 'x-appwrite-project' => $projectId,
// ], $this->getHeaders()), $gqlPayload);
//
// $this->assertIsNotArray($entity['body']);
// $this->assertEquals(204, $entity['headers']['status-code']);
// }
// /**
// * @depends testCreateCustomEntity
// * @throws Exception
// */
// public function testDeleteCustomEntity(array $data)
// {
// $projectId = $this->getProject()['$id'];
// $query = $this->getQuery(self::$DELETE_CUSTOM_ENTITY);
// $gqlPayload = [
// 'query' => $query,
// 'variables' => [
// 'id' => $data['id'],
// ]
// ];
//
// $entity = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
// 'content-type' => 'application/json',
// 'x-appwrite-project' => $projectId,
// ], $this->getHeaders()), $gqlPayload);
//
// $this->assertIsNotArray($entity['body']);
// $this->assertEquals(204, $entity['headers']['status-code']);
// }
/**
* @depends testCreateStringAttribute
* @depends testUpdateStringAttribute
* @throws Exception
*/
public function testDeleteAttribute($data): void

View file

@ -1655,8 +1655,6 @@ class ProjectsConsoleClientTest extends Scope
'events' => ['users.*.delete', 'users.*.sessions.*.delete', 'buckets.*.files.*.create'],
'url' => 'https://appwrite.io/new',
'security' => false,
'httpUser' => '',
'httpPass' => ''
]);
$this->assertEquals(200, $response['headers']['status-code']);
@ -1703,8 +1701,6 @@ class ProjectsConsoleClientTest extends Scope
'events' => ['users.*.delete', 'users.*.sessions.*.delete', 'buckets.*.files.*.unknown'],
'url' => 'https://appwrite.io/new',
'security' => false,
'httpUser' => '',
'httpPass' => '',
]);
$this->assertEquals(400, $response['headers']['status-code']);
@ -1717,8 +1713,6 @@ class ProjectsConsoleClientTest extends Scope
'events' => ['users.*.delete', 'users.*.sessions.*.delete', 'buckets.*.files.*.create'],
'url' => 'appwrite.io/new',
'security' => false,
'httpUser' => '',
'httpPass' => '',
]);
$this->assertEquals(400, $response['headers']['status-code']);
@ -2090,8 +2084,6 @@ class ProjectsConsoleClientTest extends Scope
], $this->getHeaders()), [
'type' => 'web',
'name' => 'Web App',
'key' => '',
'store' => '',
'hostname' => 'localhost',
]);
@ -2112,8 +2104,6 @@ class ProjectsConsoleClientTest extends Scope
'type' => 'flutter-ios',
'name' => 'Flutter App (iOS)',
'key' => 'com.example.ios',
'store' => '',
'hostname' => '',
]);
$this->assertEquals(201, $response['headers']['status-code']);
@ -2133,8 +2123,6 @@ class ProjectsConsoleClientTest extends Scope
'type' => 'flutter-android',
'name' => 'Flutter App (Android)',
'key' => 'com.example.android',
'store' => '',
'hostname' => '',
]);
$this->assertEquals(201, $response['headers']['status-code']);
@ -2153,8 +2141,6 @@ class ProjectsConsoleClientTest extends Scope
], $this->getHeaders()), [
'type' => 'flutter-web',
'name' => 'Flutter App (Web)',
'key' => '',
'store' => '',
'hostname' => 'flutter.appwrite.io',
]);
@ -2175,8 +2161,6 @@ class ProjectsConsoleClientTest extends Scope
'type' => 'apple-ios',
'name' => 'iOS App',
'key' => 'com.example.ios',
'store' => '',
'hostname' => '',
]);
$this->assertEquals(201, $response['headers']['status-code']);
@ -2196,8 +2180,6 @@ class ProjectsConsoleClientTest extends Scope
'type' => 'apple-macos',
'name' => 'macOS App',
'key' => 'com.example.macos',
'store' => '',
'hostname' => '',
]);
$this->assertEquals(201, $response['headers']['status-code']);
@ -2217,8 +2199,6 @@ class ProjectsConsoleClientTest extends Scope
'type' => 'apple-watchos',
'name' => 'watchOS App',
'key' => 'com.example.watchos',
'store' => '',
'hostname' => '',
]);
$this->assertEquals(201, $response['headers']['status-code']);
@ -2238,8 +2218,6 @@ class ProjectsConsoleClientTest extends Scope
'type' => 'apple-tvos',
'name' => 'tvOS App',
'key' => 'com.example.tvos',
'store' => '',
'hostname' => '',
]);
$this->assertEquals(201, $response['headers']['status-code']);
@ -2261,8 +2239,6 @@ class ProjectsConsoleClientTest extends Scope
], $this->getHeaders()), [
'type' => 'unknown',
'name' => 'Web App',
'key' => '',
'store' => '',
'hostname' => 'localhost',
]);
@ -2457,8 +2433,6 @@ class ProjectsConsoleClientTest extends Scope
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'name' => 'Web App 2',
'key' => '',
'store' => '',
'hostname' => 'localhost-new',
]);
@ -2479,8 +2453,6 @@ class ProjectsConsoleClientTest extends Scope
], $this->getHeaders()), [
'name' => 'Flutter App (iOS) 2',
'key' => 'com.example.ios2',
'store' => '',
'hostname' => '',
]);
$this->assertEquals(200, $response['headers']['status-code']);
@ -2500,8 +2472,6 @@ class ProjectsConsoleClientTest extends Scope
], $this->getHeaders()), [
'name' => 'Flutter App (Android) 2',
'key' => 'com.example.android2',
'store' => '',
'hostname' => '',
]);
$this->assertEquals(200, $response['headers']['status-code']);
@ -2520,8 +2490,6 @@ class ProjectsConsoleClientTest extends Scope
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'name' => 'Flutter App (Web) 2',
'key' => '',
'store' => '',
'hostname' => 'flutter2.appwrite.io',
]);
@ -2542,8 +2510,6 @@ class ProjectsConsoleClientTest extends Scope
], $this->getHeaders()), [
'name' => 'iOS App 2',
'key' => 'com.example.ios2',
'store' => '',
'hostname' => '',
]);
$this->assertEquals(200, $response['headers']['status-code']);
@ -2563,8 +2529,6 @@ class ProjectsConsoleClientTest extends Scope
], $this->getHeaders()), [
'name' => 'macOS App 2',
'key' => 'com.example.macos2',
'store' => '',
'hostname' => '',
]);
$this->assertEquals(200, $response['headers']['status-code']);
@ -2584,8 +2548,6 @@ class ProjectsConsoleClientTest extends Scope
], $this->getHeaders()), [
'name' => 'watchOS App 2',
'key' => 'com.example.watchos2',
'store' => '',
'hostname' => '',
]);
$this->assertEquals(200, $response['headers']['status-code']);
@ -2605,8 +2567,6 @@ class ProjectsConsoleClientTest extends Scope
], $this->getHeaders()), [
'name' => 'tvOS App 2',
'key' => 'com.example.tvos2',
'store' => '',
'hostname' => '',
]);
$this->assertEquals(200, $response['headers']['status-code']);
@ -2627,8 +2587,6 @@ class ProjectsConsoleClientTest extends Scope
], $this->getHeaders()), [
'name' => 'Flutter App (Android) 2',
'key' => 'com.example.android2',
'store' => '',
'hostname' => '',
]);
$this->assertEquals(404, $response['headers']['status-code']);
@ -2836,8 +2794,6 @@ class ProjectsConsoleClientTest extends Scope
], $this->getHeaders()), [
'type' => 'web',
'name' => 'Too Long Hostname',
'key' => '',
'store' => '',
'hostname' => \str_repeat("bestdomain", 25) . '.com' // 250 + 4 chars total (exactly above limit)
]);

View file

@ -443,7 +443,7 @@ class RealtimeConsoleClientTest extends Scope
'users.*.delete',
],
'schedule' => '0 0 1 1 *',
'timeout' => 10,
'timeout' => 10
]);
$functionId = $response1['body']['$id'] ?? '';
@ -482,6 +482,7 @@ class RealtimeConsoleClientTest extends Scope
], $this->getHeaders()), [
'entrypoint' => 'index.php',
'code' => new CURLFile($code, 'application/x-gzip', \basename($code)),
'activate' => true
]);
$deploymentId = $deployment['body']['$id'] ?? '';

View file

@ -1284,7 +1284,8 @@ class RealtimeCustomClientTest extends Scope
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'entrypoint' => 'index.php',
'code' => new CURLFile($code, 'application/x-gzip', basename($code))
'code' => new CURLFile($code, 'application/x-gzip', basename($code)),
'activate' => true
]);
$deploymentId = $deployment['body']['$id'] ?? '';

View file

@ -7,7 +7,7 @@ use Tests\E2E\Client;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Validator\DatetimeValidator;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
trait StorageBase
{

View file

@ -10,7 +10,7 @@ use Tests\E2E\Scopes\SideClient;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Validator\DatetimeValidator;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
class StorageCustomClientTest extends Scope
{

View file

@ -7,7 +7,7 @@ use Tests\E2E\Scopes\ProjectCustom;
use Tests\E2E\Scopes\Scope;
use Tests\E2E\Scopes\SideServer;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Validator\DatetimeValidator;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
class StorageCustomServerTest extends Scope
{

View file

@ -4,7 +4,7 @@ namespace Tests\E2E\Services\Teams;
use Tests\E2E\Client;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Validator\DatetimeValidator;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
trait TeamsBase
{

View file

@ -4,7 +4,7 @@ namespace Tests\E2E\Services\Teams;
use Tests\E2E\Client;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Validator\DatetimeValidator;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
trait TeamsBaseClient
{
@ -517,11 +517,22 @@ trait TeamsBaseClient
'x-appwrite-project' => $this->getProject()['$id'],
]), [
'secret' => $secret,
'userId' => ID::custom(''),
'userId' => ID::custom('$notallowed'),
]);
$this->assertEquals(400, $response['headers']['status-code']);
$response = $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'],
]), [
'secret' => $secret,
'userId' => ID::custom(''),
]);
$this->assertEquals(401, $response['headers']['status-code']);
$response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',

View file

@ -3,7 +3,7 @@
namespace Tests\E2E\Services\Teams;
use Tests\E2E\Client;
use Utopia\Database\Validator\DatetimeValidator;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
trait TeamsBaseServer
{

View file

@ -8,7 +8,7 @@ use Tests\E2E\Client;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Validator\DatetimeValidator;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
trait WebhooksBase
{

View file

@ -8,7 +8,7 @@ use Tests\E2E\Scopes\Scope;
use Tests\E2E\Scopes\ProjectCustom;
use Tests\E2E\Scopes\SideClient;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Validator\DatetimeValidator;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
class WebhooksCustomClientTest extends Scope
{

View file

@ -11,7 +11,7 @@ use Utopia\CLI\Console;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Validator\DatetimeValidator;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
class WebhooksCustomServerTest extends Scope
{
@ -484,16 +484,6 @@ class WebhooksCustomServerTest extends Scope
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
$function = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'name' => 'Test Failure',
'execute' => [ 'not-valid-permission' ]
]);
$this->assertEquals($function['headers']['status-code'], 400);
return $data;
}
@ -516,7 +506,8 @@ class WebhooksCustomServerTest extends Scope
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'entrypoint' => 'index.php',
'code' => new CURLFile($code, 'application/x-gzip', \basename($code))
'code' => new CURLFile($code, 'application/x-gzip', \basename($code)),
'activate' => true
]);
$id = $data['functionId'] ?? '';