Merge branch '1.5.x' into feat-oauth-token-endpoint

This commit is contained in:
Luke B. Silver
2024-02-05 09:34:45 +00:00
committed by GitHub
19 changed files with 253 additions and 46 deletions
+1
View File
@@ -4,6 +4,7 @@ _APP_WORKER_PER_CORE=6
_APP_CONSOLE_WHITELIST_ROOT=disabled
_APP_CONSOLE_WHITELIST_EMAILS=
_APP_CONSOLE_WHITELIST_IPS=
_APP_CONSOLE_COUNTRIES_DENYLIST=AQ
_APP_CONSOLE_HOSTNAMES=localhost,appwrite.io,*.appwrite.io
_APP_SYSTEM_EMAIL_NAME=Appwrite
_APP_SYSTEM_EMAIL_ADDRESS=team@appwrite.io
+5
View File
@@ -114,6 +114,11 @@ return [
'description' => 'Value must be a valid phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.',
'code' => 400,
],
Exception::GENERAL_REGION_ACCESS_DENIED => [
'name' => Exception::GENERAL_REGION_ACCESS_DENIED,
'description' => 'Your location is not supported due to legal requirements.',
'code' => 451,
],
/** User Errors */
Exception::USER_COUNT_EXCEEDED => [
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
+2 -3
View File
@@ -1286,9 +1286,9 @@ App::post('/v1/account/tokens/magic-url')
App::post('/v1/account/tokens/email')
->desc('Create email token (OTP)')
->groups(['api', 'account'])
->groups(['api', 'account', 'auth'])
->label('scope', 'sessions.write')
->label('auth.type', 'email')
->label('auth.type', 'email-otp')
->label('audits.event', 'session.create')
->label('audits.resource', 'user/{response.userId}')
->label('audits.userId', '{response.userId}')
@@ -3876,7 +3876,6 @@ App::post('/v1/account/targets/push')
->param('providerId', '', new UID(), 'Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.', true)
->inject('queueForEvents')
->inject('user')
->inject('session')
->inject('request')
->inject('response')
->inject('dbForProject')
+1 -1
View File
@@ -3296,7 +3296,7 @@ App::patch('/v1/messaging/messages/push/:messageId')
->label('scope', 'messages.write')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'messaging')
->label('sdk.method', 'updatePushNotification')
->label('sdk.method', 'updatePush')
->label('sdk.description', '/docs/references/messaging/update-push-notification.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
+1
View File
@@ -736,6 +736,7 @@ App::error()
case 412: // Error allowed publicly
case 416: // Error allowed publicly
case 429: // Error allowed publicly
case 451: // Error allowed publicly
case 501: // Error allowed publicly
case 503: // Error allowed publicly
break;
+18 -1
View File
@@ -22,6 +22,7 @@ use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Validator\Authorization;
use MaxMind\Db\Reader;
$parseLabel = function (string $label, array $responsePayload, array $requestParams, Document $user) {
preg_match_all('/{(.*?)}/', $label, $matches);
@@ -319,7 +320,17 @@ App::init()
->inject('utopia')
->inject('request')
->inject('project')
->action(function (App $utopia, Request $request, Document $project) {
->inject('geodb')
->action(function (App $utopia, Request $request, Document $project, Reader $geodb) {
$denylist = App::getEnv('_APP_CONSOLE_COUNTRIES_DENYLIST', '');
if (!empty($denylist) && $project->getId() === 'console') {
$countries = explode(',', $denylist);
$record = $geodb->get($request->getIP()) ?? [];
$country = $record['country']['iso_code'] ?? '';
if (in_array($country, $countries)) {
throw new Exception(Exception::GENERAL_REGION_ACCESS_DENIED);
}
}
$route = $utopia->getRoute();
@@ -368,6 +379,12 @@ App::init()
}
break;
case 'email-otp':
if (($auths['emailOTP'] ?? true) === false) {
throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Email OTP authentication is disabled for this project');
}
break;
default:
throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Unsupported authentication route');
break;
+18 -1
View File
@@ -6,13 +6,24 @@ use Utopia\App;
use Appwrite\Extend\Exception;
use Utopia\Database\Document;
use Utopia\Database\Validator\Authorization;
use MaxMind\Db\Reader;
App::init()
->groups(['auth'])
->inject('utopia')
->inject('request')
->inject('project')
->action(function (App $utopia, Request $request, Document $project) {
->inject('geodb')
->action(function (App $utopia, Request $request, Document $project, Reader $geodb) {
$denylist = App::getEnv('_APP_CONSOLE_COUNTRIES_DENYLIST', '');
if (!empty($denylist && $project->getId() === 'console')) {
$countries = explode(',', $denylist);
$record = $geodb->get($request->getIP()) ?? [];
$country = $record['country']['iso_code'] ?? '';
if (in_array($country, $countries)) {
throw new Exception(Exception::GENERAL_REGION_ACCESS_DENIED);
}
}
$route = $utopia->match($request);
@@ -61,6 +72,12 @@ App::init()
}
break;
case 'email-otp':
if (($auths['emailOTP'] ?? true) === false) {
throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Email OTP authentication is disabled for this project');
}
break;
default:
throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Unsupported authentication route');
break;
+1 -1
View File
@@ -65,7 +65,7 @@
"utopia-php/queue": "0.6.*",
"utopia-php/registry": "0.5.*",
"utopia-php/storage": "0.18.*",
"utopia-php/swoole": "0.5.*",
"utopia-php/swoole": "0.8.*",
"utopia-php/vcs": "0.6.*",
"utopia-php/websocket": "0.1.*",
"matomo/device-detector": "6.1.*",
Generated
+10 -10
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": "3b43bf6f0fca50a3a2834e1bbaa90d63",
"content-hash": "e6e0d6874f4d718d96396d71a66864da",
"packages": [
{
"name": "adhocore/jwt",
@@ -2432,28 +2432,28 @@
},
{
"name": "utopia-php/swoole",
"version": "0.5.0",
"version": "0.8.2",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/swoole.git",
"reference": "c2a3a4f944a2f22945af3cbcb95b13f0769628b1"
"reference": "5fa9d42c608ad46a4ce42a6d2b2eae00592fccd4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/swoole/zipball/c2a3a4f944a2f22945af3cbcb95b13f0769628b1",
"reference": "c2a3a4f944a2f22945af3cbcb95b13f0769628b1",
"url": "https://api.github.com/repos/utopia-php/swoole/zipball/5fa9d42c608ad46a4ce42a6d2b2eae00592fccd4",
"reference": "5fa9d42c608ad46a4ce42a6d2b2eae00592fccd4",
"shasum": ""
},
"require": {
"ext-swoole": "*",
"php": ">=8.0",
"utopia-php/framework": "0.*.*"
"utopia-php/framework": "0.33.*"
},
"require-dev": {
"laravel/pint": "1.2.*",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^9.3",
"swoole/ide-helper": "4.8.3",
"vimeo/psalm": "4.15.0"
"swoole/ide-helper": "5.0.2"
},
"type": "library",
"autoload": {
@@ -2477,9 +2477,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/swoole/issues",
"source": "https://github.com/utopia-php/swoole/tree/0.5.0"
"source": "https://github.com/utopia-php/swoole/tree/0.8.2"
},
"time": "2022-10-19T22:19:07+00:00"
"time": "2024-02-01T14:54:12+00:00"
},
{
"name": "utopia-php/system",
+1
View File
@@ -188,6 +188,7 @@ services:
- _APP_MESSAGE_SMS_TEST_DSN
- _APP_MESSAGE_EMAIL_TEST_DSN
- _APP_MESSAGE_PUSH_TEST_DSN
- _APP_CONSOLE_COUNTRIES_DENYLIST
appwrite-realtime:
entrypoint: realtime
+1
View File
@@ -57,6 +57,7 @@ class Exception extends \Exception
public const GENERAL_NOT_IMPLEMENTED = 'general_not_implemented';
public const GENERAL_INVALID_EMAIL = 'general_invalid_email';
public const GENERAL_INVALID_PHONE = 'general_invalid_phone';
public const GENERAL_REGION_ACCESS_DENIED = 'general_region_access_denied';
/** Users */
public const USER_COUNT_EXCEEDED = 'user_count_exceeded';
+173 -23
View File
@@ -116,7 +116,28 @@ abstract class Format
case 'account':
switch ($method) {
case 'createOAuth2Session':
return 'Provider';
switch ($param) {
case 'provider':
return 'OAuthProvider';
}
break;
case 'addAuthenticator':
case 'verifyAuthenticator':
case 'deleteAuthenticator':
switch ($param) {
case 'factor':
return 'AuthenticatorFactor';
case 'provider':
return 'AuthenticatorProvider';
}
break;
case 'createChallenge':
case 'verifyChallenge':
switch ($param) {
case 'provider':
return 'AuthenticatorProvider';
}
break;
}
break;
case 'avatars':
@@ -129,20 +150,16 @@ abstract class Format
return 'Flag';
}
break;
case 'storage':
switch ($method) {
case 'getFilePreview':
switch ($param) {
case 'gravity':
return 'ImageGravity';
case 'output':
return 'ImageFormat';
}
break;
}
break;
case 'databases':
switch ($method) {
case 'getUsage':
case 'getCollectionUsage':
case 'getDatabaseUsage':
switch ($param) {
case 'range':
return 'DatabaseUsageRange';
}
break;
case 'createRelationshipAttribute':
switch ($param) {
case 'type':
@@ -166,14 +183,144 @@ abstract class Format
}
}
break;
case 'functions':
switch ($method) {
case 'getUsage':
case 'getFunctionUsage':
switch ($param) {
case 'range':
return 'FunctionUsageRange';
}
break;
case 'createExecution':
switch ($param) {
case 'method':
return 'ExecutionMethod';
}
break;
}
break;
case 'messaging':
switch ($method) {
case 'getUsage':
switch ($param) {
case 'period':
return 'MessagingUsageRange';
}
break;
case 'createSMS':
case 'createPush':
case 'createEmail':
case 'updateSMS':
case 'updatePush':
case 'updateEmail':
switch ($param) {
case 'status':
return 'MessageType';
}
break;
case 'createSMTPProvider':
case 'updateSMTPProvider':
switch ($param) {
case 'encryption':
return 'SMTPEncryption';
}
break;
}
break;
case 'project':
switch ($method) {
case 'getUsage':
switch ($param) {
case 'period':
return 'ProjectUsageRange';
}
break;
}
break;
case 'projects':
switch ($method) {
case 'getSmsTemplate':
case 'getEmailTemplate':
case 'updateSmsTemplate':
case 'updateEmailTemplate':
case 'deleteSmsTemplate':
case 'deleteEmailTemplate':
switch ($param) {
case 'type':
return 'TemplateType';
case 'locale':
return 'TemplateLocale';
}
break;
case 'createPlatform':
switch ($param) {
case 'type':
return 'PlatformType';
}
break;
case 'createSmtpTest':
case 'updateSmtp':
switch ($param) {
case 'secure':
return 'SMTPSecure';
}
break;
case 'updateOAuth2':
switch ($param) {
case 'provider':
return 'OAuthProvider';
}
break;
case 'updateAuthStatus':
switch ($param) {
case 'method':
return 'AuthMethod';
}
break;
}
break;
case 'storage':
switch ($method) {
case 'getUsage':
case 'getBucketUsage':
switch ($param) {
case 'range':
return 'StorageUsageRange';
}
break;
case 'getFilePreview':
switch ($param) {
case 'gravity':
return 'ImageGravity';
case 'output':
return 'ImageFormat';
}
break;
}
break;
case 'users':
switch ($method) {
case 'getUsage':
switch ($param) {
case 'range':
return 'UserUsageRange';
}
break;
case 'deleteAuthenticator':
switch ($param) {
case 'factor':
return 'AuthenticatorFactor';
case 'provider':
return 'AuthenticatorProvider';
}
break;
case 'createTarget':
switch ($param) {
case 'providerType':
return 'MessagingProviderType';
}
break;
}
break;
}
@@ -211,27 +358,23 @@ abstract class Format
case 'getCollectionUsage':
case 'getDatabaseUsage':
// Range Enum Keys
$values = ['Twenty Four Hours', 'Seven Days', 'Thirty Days', 'Ninety Days'];
return $values;
return ['Twenty Four Hours', 'Thirty Days', 'Ninety Days'];
}
break;
case 'function':
case 'functions':
switch ($method) {
case 'getUsage':
case 'getFunctionUsage':
// Range Enum Keys
$values = ['Twenty Four Hours', 'Seven Days', 'Thirty Days', 'Ninety Days'];
return $values;
return ['Twenty Four Hours', 'Thirty Days', 'Ninety Days'];
}
break;
case 'users':
switch ($method) {
case 'getUsage':
case 'getUserUsage':
// Range Enum Keys
if ($param == 'range') {
$values = ['Twenty Four Hours', 'Seven Days', 'Thirty Days', 'Ninety Days'];
return $values;
return ['Twenty Four Hours', 'Thirty Days', 'Ninety Days'];
}
}
break;
@@ -240,9 +383,16 @@ abstract class Format
case 'getUsage':
case 'getBucketUsage':
// Range Enum Keys
$values = ['Twenty Four Hours', 'Seven Days', 'Thirty Days', 'Ninety Days'];
return $values;
return ['Twenty Four Hours', 'Thirty Days', 'Ninety Days'];
}
break;
case 'project':
switch ($method) {
case 'getUsage':
// Range Enum Keys
return ['One Hour', 'One Day'];
}
break;
}
return $values;
}
@@ -44,6 +44,21 @@ trait AccountBase
/**
* Test for FAILURE
*/
// Deny request from blocked IP
$response = $this->client->call(Client::METHOD_POST, '/account', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => 'console',
'x-forwarded-for' => '103.152.127.250' // Test IP for denied access region
]), [
'userId' => ID::unique(),
'email' => $email,
'password' => $password,
'name' => $name,
]);
$this->assertEquals(451, $response['headers']['status-code']);
$response = $this->client->call(Client::METHOD_POST, '/account', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',