diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index da02fb4514..d07c8f061e 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -903,6 +903,14 @@ Http::patch('/v1/projects/:projectId/auth/mock-numbers') ->inject('dbForConsole') ->action(function (string $projectId, array $numbers, Response $response, Database $dbForConsole) { + $uniqueNumbers = []; + foreach ($numbers as $number) { + if (isset($uniqueNumbers[$number['phone']])) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Duplicate phone numbers are not allowed.'); + } + $uniqueNumbers[$number['phone']] = $number['otp']; + } + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { diff --git a/src/Appwrite/Auth/Validator/MockNumber.php b/src/Appwrite/Auth/Validator/MockNumber.php index 0a8db26ab2..900f1ba215 100644 --- a/src/Appwrite/Auth/Validator/MockNumber.php +++ b/src/Appwrite/Auth/Validator/MockNumber.php @@ -45,9 +45,9 @@ class MockNumber extends Validator return false; } - $otp = new Validator\Text(6, 6); + $otp = new Validator\Text(6, 6, Text::NUMBERS); if (!$otp->isValid($value['otp'])) { - $this->message = 'OTP must be a valid string and exactly 6 characters.'; + $this->message = 'Invalid OTP. Please make sure the OTP is a 6 digit number'; return false; } diff --git a/src/Appwrite/Utopia/Response/Model/TemplateFunction.php b/src/Appwrite/Utopia/Response/Model/TemplateFunction.php index 7a3a4cfbd5..f5df10986f 100644 --- a/src/Appwrite/Utopia/Response/Model/TemplateFunction.php +++ b/src/Appwrite/Utopia/Response/Model/TemplateFunction.php @@ -110,8 +110,7 @@ class TemplateFunction extends Model 'default' => [], 'example' => [], 'array' => true - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/TemplateRuntime.php b/src/Appwrite/Utopia/Response/Model/TemplateRuntime.php index c08ea9b32a..c98a59789d 100644 --- a/src/Appwrite/Utopia/Response/Model/TemplateRuntime.php +++ b/src/Appwrite/Utopia/Response/Model/TemplateRuntime.php @@ -33,8 +33,7 @@ class TemplateRuntime extends Model 'description' => 'Path to function in VCS (Version Control System) repository', 'default' => '', 'example' => 'node/starter', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/TemplateVariable.php b/src/Appwrite/Utopia/Response/Model/TemplateVariable.php index b0fd919dbf..c992083a87 100644 --- a/src/Appwrite/Utopia/Response/Model/TemplateVariable.php +++ b/src/Appwrite/Utopia/Response/Model/TemplateVariable.php @@ -10,37 +10,42 @@ class TemplateVariable extends Model public function __construct() { $this - ->addRule('name', [ - 'type' => self::TYPE_STRING, - 'description' => 'Variable Name.', - 'default' => '', - 'example' => 'APPWRITE_DATABASE_ID', - ]) - ->addRule('description', [ - 'type' => self::TYPE_STRING, - 'description' => 'Variable Description.', - 'default' => '', - 'example' => 'The ID of the Appwrite database that contains the collection to sync.', - ]) - ->addRule('placeholder', [ - 'type' => self::TYPE_STRING, - 'description' => 'Variable Placeholder.', - 'default' => '', - 'example' => '64a55...7b912', - ]) - ->addRule('required', [ - 'type' => self::TYPE_BOOLEAN, - 'description' => 'Is the variable required?', - 'default' => false, - 'example' => false, - ]) - ->addRule('type', [ - 'type' => self::TYPE_STRING, - 'description' => 'Variable Type.', - 'default' => '', - 'example' => 'password', - ]) - ; + ->addRule('name', [ + 'type' => self::TYPE_STRING, + 'description' => 'Variable Name.', + 'default' => '', + 'example' => 'APPWRITE_DATABASE_ID', + ]) + ->addRule('description', [ + 'type' => self::TYPE_STRING, + 'description' => 'Variable Description.', + 'default' => '', + 'example' => 'The ID of the Appwrite database that contains the collection to sync.', + ]) + ->addRule('value', [ + 'type' => self::TYPE_STRING, + 'description' => 'Variable Value.', + 'default' => '', + 'example' => '512', + ]) + ->addRule('placeholder', [ + 'type' => self::TYPE_STRING, + 'description' => 'Variable Placeholder.', + 'default' => '', + 'example' => '64a55...7b912', + ]) + ->addRule('required', [ + 'type' => self::TYPE_BOOLEAN, + 'description' => 'Is the variable required?', + 'default' => false, + 'example' => false, + ]) + ->addRule('type', [ + 'type' => self::TYPE_STRING, + 'description' => 'Variable Type.', + 'default' => '', + 'example' => 'password', + ]); } /** diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 753322f168..dd0c8420d5 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -1592,7 +1592,7 @@ class ProjectsConsoleClientTest extends Scope ] ]); $this->assertEquals(400, $response['headers']['status-code']); - $this->assertEquals('Invalid `numbers` param: Value must a valid array no longer than 10 items and OTP must be a valid string and exactly 6 characters.', $response['body']['message']); + $this->assertEquals('Invalid `numbers` param: Value must a valid array no longer than 10 items and Invalid OTP. Please make sure the OTP is a 6 digit number', $response['body']['message']); /** Trying to pass an OTP shorter than 6 characters*/ $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/mock-numbers', array_merge([ @@ -1607,7 +1607,22 @@ class ProjectsConsoleClientTest extends Scope ] ]); $this->assertEquals(400, $response['headers']['status-code']); - $this->assertEquals('Invalid `numbers` param: Value must a valid array no longer than 10 items and OTP must be a valid string and exactly 6 characters.', $response['body']['message']); + $this->assertEquals('Invalid `numbers` param: Value must a valid array no longer than 10 items and Invalid OTP. Please make sure the OTP is a 6 digit number', $response['body']['message']); + + /** Trying to pass an OTP with non numeric characters */ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/mock-numbers', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'numbers' => [ + [ + 'phone' => '+1655513432', + 'otp' => '123re2' + ] + ] + ]); + $this->assertEquals(400, $response['headers']['status-code']); + $this->assertEquals('Invalid `numbers` param: Value must a valid array no longer than 10 items and Invalid OTP. Please make sure the OTP is a 6 digit number', $response['body']['message']); /** Trying to pass an invalid phone number */ $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/mock-numbers', array_merge([ @@ -1639,6 +1654,25 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); $this->assertEquals('Invalid `numbers` param: Value must a valid array no longer than 10 items and Phone number must start with a \'+\' can have a maximum of fifteen digits.', $response['body']['message']); + /** Trying to pass duplicate numbers */ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/mock-numbers', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'numbers' => [ + [ + 'phone' => '+1655513432', + 'otp' => '123456' + ], + [ + 'phone' => '+1655513432', + 'otp' => '123456' + ] + ] + ]); + $this->assertEquals(400, $response['headers']['status-code']); + $this->assertEquals('Duplicate phone numbers are not allowed.', $response['body']['message']); + $numbers = []; for ($i = 0; $i < 11; $i++) { $numbers[] = [