diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 5278abae3e..19264454e0 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1574,7 +1574,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') Query::equal('databaseInternalId', [$db->getInternalId()]) ], 61); - $limit = 64 - MariaDB::getNumberOfDefaultIndexes(); + $limit = 64 - MariaDB::getCountOfDefaultIndexes(); if ($count >= $limit) { throw new Exception(Exception::INDEX_LIMIT_EXCEEDED, 'Index limit exceeded'); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 407bc1eaab..c95105b775 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -888,7 +888,7 @@ App::patch('/v1/users/:userId/phone') try { $user = $dbForProject->updateDocument('users', $user->getId(), $user); } catch (Duplicate $th) { - throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); + throw new Exception(Exception::USER_PHONE_ALREADY_EXISTS); } $events->setParam('userId', $user->getId()); diff --git a/app/http.php b/app/http.php index afda7053b4..fe0778bb15 100644 --- a/app/http.php +++ b/app/http.php @@ -91,18 +91,11 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { /** @var array $collections */ $collections = Config::getParam('collections', []); - if (!$dbForConsole->exists(App::getEnv('_APP_DB_SCHEMA', 'appwrite'))) { - $redis->flushAll(); - - Console::success('[Setup] - Creating database: appwrite...'); - - $dbForConsole->create(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); - } - try { - Console::success('[Setup] - Creating metadata table: appwrite...'); - $dbForConsole->createMetadata(); - } catch (\Throwable $th) { + $redis->flushAll(); + Console::success('[Setup] - Creating database: appwrite...'); + $dbForConsole->create(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); + } catch (\Exception $e) { Console::success('[Setup] - Skip: metadata table already exists'); } diff --git a/app/init.php b/app/init.php index a19492394b..054721d439 100644 --- a/app/init.php +++ b/app/init.php @@ -282,7 +282,7 @@ Database::addFilter( ->find('attributes', [ Query::equal('collectionInternalId', [$document->getInternalId()]), Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), - Query::limit($database->getAttributeLimit()), + Query::limit($database->getLimitForAttributes()), ]); } ); diff --git a/composer.json b/composer.json index f8eee2eca2..f52586277a 100644 --- a/composer.json +++ b/composer.json @@ -45,14 +45,14 @@ "appwrite/php-runtimes": "0.11.*", "utopia-php/framework": "0.22.*", "utopia-php/logger": "0.3.*", - "utopia-php/abuse": "0.13.*", + "utopia-php/abuse": "0.14.*", "utopia-php/analytics": "0.2.*", - "utopia-php/audit": "0.14.*", + "utopia-php/audit": "0.15.*", "utopia-php/cache": "0.6.*", "utopia-php/platform": "0.2.*", "utopia-php/cli": "0.13.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.25.*", + "utopia-php/database": "0.26.*", "utopia-php/locale": "0.4.*", "utopia-php/registry": "0.5.*", "utopia-php/preloader": "0.2.*", diff --git a/composer.lock b/composer.lock index f845b953ac..1f69ffffca 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "c2fa5b94159eb9fc1e0d414ae507ba9e", + "content-hash": "3bcc6cfb6966fef9fdba36dd31f07b5b", "packages": [ { "name": "adhocore/jwt", @@ -1741,23 +1741,23 @@ }, { "name": "utopia-php/abuse", - "version": "0.13.1", + "version": "0.14.0", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "4c1b8fe742f17158c59550cdfd9074a94bf474ac" + "reference": "1a5da248e74c1bfc39bc440fa949de6935acceeb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/4c1b8fe742f17158c59550cdfd9074a94bf474ac", - "reference": "4c1b8fe742f17158c59550cdfd9074a94bf474ac", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/1a5da248e74c1bfc39bc440fa949de6935acceeb", + "reference": "1a5da248e74c1bfc39bc440fa949de6935acceeb", "shasum": "" }, "require": { "ext-curl": "*", "ext-pdo": "*", "php": ">=8.0", - "utopia-php/database": "0.25.*" + "utopia-php/database": "0.26.*" }, "require-dev": { "phpunit/phpunit": "^9.4", @@ -1789,9 +1789,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.13.1" + "source": "https://github.com/utopia-php/abuse/tree/0.14.0" }, - "time": "2022-09-07T16:02:58+00:00" + "time": "2022-10-14T11:26:39+00:00" }, { "name": "utopia-php/analytics", @@ -1850,22 +1850,22 @@ }, { "name": "utopia-php/audit", - "version": "0.14.1", + "version": "0.15.0", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "b011224ed9bfef7e5c849938e65619af28f7cf41" + "reference": "937ffd13e7a5ac9ad220b329247569ef2a4881d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/b011224ed9bfef7e5c849938e65619af28f7cf41", - "reference": "b011224ed9bfef7e5c849938e65619af28f7cf41", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/937ffd13e7a5ac9ad220b329247569ef2a4881d9", + "reference": "937ffd13e7a5ac9ad220b329247569ef2a4881d9", "shasum": "" }, "require": { "ext-pdo": "*", "php": ">=8.0", - "utopia-php/database": "0.25.*" + "utopia-php/database": "0.26.*" }, "require-dev": { "phpunit/phpunit": "^9.3", @@ -1881,12 +1881,6 @@ "license": [ "MIT" ], - "authors": [ - { - "name": "Eldad Fux", - "email": "eldad@appwrite.io" - } - ], "description": "A simple audit library to manage application users logs", "keywords": [ "Audit", @@ -1897,9 +1891,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/0.14.1" + "source": "https://github.com/utopia-php/audit/tree/0.15.0" }, - "time": "2022-09-07T16:03:16+00:00" + "time": "2022-10-14T11:39:18+00:00" }, { "name": "utopia-php/cache", @@ -2060,16 +2054,16 @@ }, { "name": "utopia-php/database", - "version": "0.25.5", + "version": "0.26.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "6d1c1d46d66553154975a3e8e72d30b5bd2413d9" + "reference": "d172af2541137c83a86d066f82f48914b5a3a610" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/6d1c1d46d66553154975a3e8e72d30b5bd2413d9", - "reference": "6d1c1d46d66553154975a3e8e72d30b5bd2413d9", + "url": "https://api.github.com/repos/utopia-php/database/zipball/d172af2541137c83a86d066f82f48914b5a3a610", + "reference": "d172af2541137c83a86d066f82f48914b5a3a610", "shasum": "" }, "require": { @@ -2118,9 +2112,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.25.5" + "source": "https://github.com/utopia-php/database/tree/0.26.0" }, - "time": "2022-09-30T15:01:32+00:00" + "time": "2022-10-03T17:12:01+00:00" }, { "name": "utopia-php/domains", diff --git a/docs/tutorials/add-environment-variable.md b/docs/tutorials/add-environment-variable.md index e056d338d1..61dc040c28 100644 --- a/docs/tutorials/add-environment-variable.md +++ b/docs/tutorials/add-environment-variable.md @@ -5,12 +5,12 @@ This document is part of the Appwrite contributors' guide. Before you continue r ## Getting Started ### Agenda -Adding new features may require various configurations options to be set by the users. And for such options, we use environment variables in Appwrite. +Adding new features may require various configuration options to be set by the users. And for such options, we use environment variables in Appwrite. This tutorial will cover how to properly add a new environment variable in Appwrite. ### Naming environment variable -The environment variables in Appwrite are prefixed with `_APP_`. If it belongs to a specific category, the category name is appended as `_APP_REDIS` for the Redis category. The available categories are General, Redis, MariaDB, InfluxDB, StatsD, SMTP, Storage and Functions. Finally, a properly describing name is given to the variable. For example, `_APP_REDIS_HOST` is an environment variable for Redis connection host. You can find more information on available categories and existing environment variables in the [environment variables doc](https://appwrite.io/docs/environment-variables). +The environment variables in Appwrite are prefixed with `_APP_`. If it belongs to a specific category, the category name is appended as `_APP_REDIS` for the Redis category. The available categories are General, Redis, MariaDB, InfluxDB, StatsD, SMTP, Storage and Functions. Finally, a properly describing name is given to the variable. For example, `_APP_REDIS_HOST` is an environment variable for the Redis connection host. You can find more information on available categories and existing environment variables in the [environment variables doc](https://appwrite.io/docs/environment-variables). ### Describe new environment variable First of all, we add the new environment variable to `app/config/variables.php` in the designated category. If none of the categories fit, add it to the General category. Copy the existing variable description to create a new one so that you will not miss any required fields. diff --git a/src/Appwrite/Auth/Auth.php b/src/Appwrite/Auth/Auth.php index dbe74af0d2..adde25a7a3 100644 --- a/src/Appwrite/Auth/Auth.php +++ b/src/Appwrite/Auth/Auth.php @@ -14,6 +14,7 @@ use Utopia\Database\Document; use Utopia\Database\DateTime; use Utopia\Database\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Roles; class Auth { @@ -427,11 +428,11 @@ class Auth $phoneVerified = $user->getAttribute('phoneVerification', false); if ($emailVerified || $phoneVerified) { - $roles[] = Role::user($user->getId(), Database::DIMENSION_VERIFIED)->toString(); - $roles[] = Role::users(Database::DIMENSION_VERIFIED)->toString(); + $roles[] = Role::user($user->getId(), Roles::DIMENSION_VERIFIED)->toString(); + $roles[] = Role::users(Roles::DIMENSION_VERIFIED)->toString(); } else { - $roles[] = Role::user($user->getId(), Database::DIMENSION_UNVERIFIED)->toString(); - $roles[] = Role::users(Database::DIMENSION_UNVERIFIED)->toString(); + $roles[] = Role::user($user->getId(), Roles::DIMENSION_UNVERIFIED)->toString(); + $roles[] = Role::users(Roles::DIMENSION_UNVERIFIED)->toString(); } } else { return [Role::guests()->toString()]; diff --git a/src/Appwrite/Resque/Worker.php b/src/Appwrite/Resque/Worker.php index 40adc3e52e..dd7cebd084 100644 --- a/src/Appwrite/Resque/Worker.php +++ b/src/Appwrite/Resque/Worker.php @@ -229,7 +229,7 @@ abstract class Worker throw new \Exception("Project does not exist: {$projectId}"); } - if ($type === self::DATABASE_CONSOLE && !$database->exists($database->getDefaultDatabase(), '_metadata')) { + if ($type === self::DATABASE_CONSOLE && !$database->exists($database->getDefaultDatabase(), Database::METADATA)) { throw new \Exception('Console project not ready'); } diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index 627f12d3d1..ac3b116b32 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -926,6 +926,81 @@ trait UsersBase return $data; } + /** + * @depends testGetUser + */ + public function testUpdateUserNumber(array $data): array + { + /** + * Test for SUCCESS + */ + $updatedNumber = "+910000000000"; //dummy number + $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/phone', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'number' => $updatedNumber, + ]); + + $this->assertEquals($user['headers']['status-code'], 200); + $this->assertEquals($user['body']['phone'], $updatedNumber); + + $user = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals($user['headers']['status-code'], 200); + $this->assertEquals($user['body']['phone'], $updatedNumber); + + /** + * Test for FAILURE + */ + + $errorType = "user_phone_already_exists"; + $user1Id = "user1"; + $statusCodeForUserPhoneAlredyExists = 409; + + // adding same number ($updatedNumber) to different user i.e user1 + $response = $this->client->call(Client::METHOD_PATCH, '/users/' . $user1Id . '/phone', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'number' => $updatedNumber, + ]); + $this->assertEquals($response['headers']['status-code'], $statusCodeForUserPhoneAlredyExists); + $this->assertNotEmpty($response['body']); + $this->assertEquals($response['body']['type'], $errorType); + + return $data; + } + + /** + * @depends testUpdateUserNumber + */ + public function testUpdateUserNumberSearch($data): void + { + $id = $data['userId'] ?? ''; + $newNumber = "+910000000000"; //dummy number + + /** + * Test for SUCCESS + */ + $response = $this->client->call(Client::METHOD_GET, '/users', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => $newNumber, + ]); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertNotEmpty($response['body']); + $this->assertNotEmpty($response['body']['users']); + $this->assertCount(1, $response['body']['users']); + $this->assertEquals($response['body']['users'][0]['$id'], $id); + $this->assertEquals($response['body']['users'][0]['phone'], $newNumber); + } + /** * @depends testGetUser diff --git a/tests/unit/Auth/AuthTest.php b/tests/unit/Auth/AuthTest.php index 43a2bef8ed..822b612db8 100644 --- a/tests/unit/Auth/AuthTest.php +++ b/tests/unit/Auth/AuthTest.php @@ -10,6 +10,7 @@ use Utopia\Database\Role; use Utopia\Database\Validator\Authorization; use PHPUnit\Framework\TestCase; use Utopia\Database\Database; +use Utopia\Database\Validator\Roles; class AuthTest extends TestCase { @@ -379,8 +380,8 @@ class AuthTest extends TestCase $this->assertCount(11, $roles); $this->assertContains(Role::users()->toString(), $roles); $this->assertContains(Role::user(ID::custom('123'))->toString(), $roles); - $this->assertContains(Role::users(Database::DIMENSION_VERIFIED)->toString(), $roles); - $this->assertContains(Role::user(ID::custom('123'), Database::DIMENSION_VERIFIED)->toString(), $roles); + $this->assertContains(Role::users(Roles::DIMENSION_VERIFIED)->toString(), $roles); + $this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_VERIFIED)->toString(), $roles); $this->assertContains(Role::team(ID::custom('abc'))->toString(), $roles); $this->assertContains(Role::team(ID::custom('abc'), 'administrator')->toString(), $roles); $this->assertContains(Role::team(ID::custom('abc'), 'moderator')->toString(), $roles); @@ -394,15 +395,15 @@ class AuthTest extends TestCase $user['phoneVerification'] = false; $roles = Auth::getRoles($user); - $this->assertContains(Role::users(Database::DIMENSION_UNVERIFIED)->toString(), $roles); - $this->assertContains(Role::user(ID::custom('123'), Database::DIMENSION_UNVERIFIED)->toString(), $roles); + $this->assertContains(Role::users(Roles::DIMENSION_UNVERIFIED)->toString(), $roles); + $this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_UNVERIFIED)->toString(), $roles); // Enable single verification type $user['emailVerification'] = true; $roles = Auth::getRoles($user); - $this->assertContains(Role::users(Database::DIMENSION_VERIFIED)->toString(), $roles); - $this->assertContains(Role::user(ID::custom('123'), Database::DIMENSION_VERIFIED)->toString(), $roles); + $this->assertContains(Role::users(Roles::DIMENSION_VERIFIED)->toString(), $roles); + $this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_VERIFIED)->toString(), $roles); } public function testPrivilegedUserRoles(): void @@ -438,8 +439,8 @@ class AuthTest extends TestCase $this->assertCount(7, $roles); $this->assertNotContains(Role::users()->toString(), $roles); $this->assertNotContains(Role::user(ID::custom('123'))->toString(), $roles); - $this->assertNotContains(Role::users(Database::DIMENSION_VERIFIED)->toString(), $roles); - $this->assertNotContains(Role::user(ID::custom('123'), Database::DIMENSION_VERIFIED)->toString(), $roles); + $this->assertNotContains(Role::users(Roles::DIMENSION_VERIFIED)->toString(), $roles); + $this->assertNotContains(Role::user(ID::custom('123'), Roles::DIMENSION_VERIFIED)->toString(), $roles); $this->assertContains(Role::team(ID::custom('abc'))->toString(), $roles); $this->assertContains(Role::team(ID::custom('abc'), 'administrator')->toString(), $roles); $this->assertContains(Role::team(ID::custom('abc'), 'moderator')->toString(), $roles);