mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Merge remote-tracking branch 'origin/1.6.x' into feat-development-keys
This commit is contained in:
@@ -212,7 +212,17 @@ jobs:
|
||||
name: benchmark.json
|
||||
path: benchmark.json
|
||||
retention-days: 7
|
||||
- name: Comment on PR
|
||||
uses: thollander/actions-comment-pull-request@v2
|
||||
- name: Find Comment
|
||||
uses: peter-evans/find-comment@v3
|
||||
id: fc
|
||||
with:
|
||||
filePath: benchmark.txt
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: Benchmark results
|
||||
- name: Comment on PR
|
||||
uses: peter-evans/create-or-update-comment@v4
|
||||
with:
|
||||
comment-id: ${{ steps.fc.outputs.comment-id }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
body-path: benchmark.txt
|
||||
edit-mode: replace
|
||||
|
||||
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
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
@@ -711,13 +711,22 @@ return [
|
||||
'variables' => [
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_SIZE_LIMIT',
|
||||
'description' => 'The maximum size deployment in bytes. The default value is 30MB.',
|
||||
'description' => 'The maximum size of a function in bytes. The default value is 30MB.',
|
||||
'introduction' => '0.13.0',
|
||||
'default' => '30000000',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_BUILD_SIZE_LIMIT',
|
||||
'description' => 'The maximum size of a built deployment in bytes. The default value is 2,000,000,000 (2GB), and the maximum value is 4,294,967,295 (4.2GB).',
|
||||
'introduction' => '1.6.0',
|
||||
'default' => '2000000000',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_TIMEOUT',
|
||||
'description' => 'The maximum number of seconds allowed as a timeout value when creating a new function. The default value is 900 seconds. This is the global limit, timeout for individual functions are configured in the function\'s settings or in appwrite.json.',
|
||||
|
||||
@@ -177,6 +177,12 @@ $createSession = function (string $userId, string $secret, Request $request, Res
|
||||
default => throw new Exception(Exception::USER_INVALID_TOKEN)
|
||||
});
|
||||
|
||||
$sendAlert = (match ($verifiedToken->getAttribute('type')) {
|
||||
Auth::TOKEN_TYPE_MAGIC_URL,
|
||||
Auth::TOKEN_TYPE_EMAIL => false,
|
||||
default => true
|
||||
});
|
||||
|
||||
$session = new Document(array_merge(
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
@@ -223,7 +229,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed saving user to DB');
|
||||
}
|
||||
|
||||
if ($project->getAttribute('auths', [])['sessionAlerts'] ?? false) {
|
||||
if (($project->getAttribute('auths', [])['sessionAlerts'] ?? false) && $sendAlert) {
|
||||
if ($dbForProject->count('sessions', [
|
||||
Query::equal('userId', [$user->getId()]),
|
||||
]) !== 1) {
|
||||
|
||||
@@ -848,8 +848,8 @@ App::get('/v1/functions/:functionId/deployments/:deploymentId/download')
|
||||
->label('scope', 'functions.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'functions')
|
||||
->label('sdk.method', 'downloadDeployment')
|
||||
->label('sdk.description', '/docs/references/functions/download-deployment.md')
|
||||
->label('sdk.method', 'getDeploymentDownload')
|
||||
->label('sdk.description', '/docs/references/functions/get-deployment-download.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', '*/*')
|
||||
->label('sdk.methodType', 'location')
|
||||
|
||||
@@ -876,6 +876,14 @@ App::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()) {
|
||||
|
||||
@@ -46,9 +46,9 @@ class MockNumber extends Validator
|
||||
return false;
|
||||
}
|
||||
|
||||
$otp = new Text(6, 6);
|
||||
$otp = new 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -493,6 +493,11 @@ class Builds extends Action
|
||||
$endTime = DateTime::now();
|
||||
$durationEnd = \microtime(true);
|
||||
|
||||
$buildSizeLimit = (int) System::getEnv('_APP_FUNCTIONS_BUILD_SIZE_LIMIT', '2000000000');
|
||||
if ($response['size'] > $buildSizeLimit) {
|
||||
throw new \Exception('Build size should be less than ' . number_format($buildSizeLimit / 1048576, 2) . ' MBs.');
|
||||
}
|
||||
|
||||
/** Update the build document */
|
||||
$build->setAttribute('startTime', DateTime::format((new \DateTime())->setTimestamp(floor($response['startTime']))));
|
||||
$build->setAttribute('endTime', $endTime);
|
||||
|
||||
@@ -111,7 +111,13 @@ class TemplateFunction extends Model
|
||||
'example' => [],
|
||||
'array' => true
|
||||
])
|
||||
;
|
||||
->addRule('scopes', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Function scopes.',
|
||||
'default' => [],
|
||||
'example' => 'users.read',
|
||||
'array' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,8 +33,7 @@ class TemplateRuntime extends Model
|
||||
'description' => 'Path to function in VCS (Version Control System) repository',
|
||||
'default' => '',
|
||||
'example' => 'node/starter',
|
||||
])
|
||||
;
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -620,9 +620,9 @@ class AccountCustomClientTest extends Scope
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
]), [
|
||||
'userId' => ID::unique(),
|
||||
'email' => $data['email'],
|
||||
'password' => $data['password'],
|
||||
'name' => $data['name'],
|
||||
'email' => $data['email'],
|
||||
'password' => $data['password'],
|
||||
'name' => $data['name'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
@@ -1258,6 +1258,56 @@ class AccountCustomClientTest extends Scope
|
||||
$this->assertStringContainsString($response['body']['ip'], $lastEmail['text']); // IP Address
|
||||
$this->assertStringContainsString('Unknown', $lastEmail['text']); // Country
|
||||
$this->assertStringContainsString($response['body']['clientName'], $lastEmail['text']); // Client name
|
||||
|
||||
// Verify no alert sent in OTP login
|
||||
$response = $this->client->call(Client::METHOD_POST, '/account/tokens/email', array_merge([
|
||||
'origin' => 'http://localhost',
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
]), [
|
||||
'userId' => ID::unique(),
|
||||
'email' => 'otpuser2@appwrite.io'
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 201);
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
$this->assertNotEmpty($response['body']['$createdAt']);
|
||||
$this->assertNotEmpty($response['body']['userId']);
|
||||
$this->assertNotEmpty($response['body']['expire']);
|
||||
$this->assertEmpty($response['body']['secret']);
|
||||
$this->assertEmpty($response['body']['phrase']);
|
||||
|
||||
$userId = $response['body']['userId'];
|
||||
|
||||
$lastEmail = $this->getLastEmail();
|
||||
|
||||
$this->assertEquals('otpuser2@appwrite.io', $lastEmail['to'][0]['address']);
|
||||
$this->assertEquals('OTP for ' . $this->getProject()['name'] . ' Login', $lastEmail['subject']);
|
||||
|
||||
// FInd 6 concurrent digits in email text - OTP
|
||||
preg_match_all("/\b\d{6}\b/", $lastEmail['text'], $matches);
|
||||
$code = ($matches[0] ?? [])[0] ?? '';
|
||||
|
||||
$this->assertNotEmpty($code);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/token', array_merge([
|
||||
'origin' => 'http://localhost',
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
]), [
|
||||
'userId' => $userId,
|
||||
'secret' => $code
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertEquals($userId, $response['body']['userId']);
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
$this->assertNotEmpty($response['body']['expire']);
|
||||
$this->assertEmpty($response['body']['secret']);
|
||||
|
||||
$lastEmailId = $lastEmail['id'];
|
||||
$lastEmail = $this->getLastEmail();
|
||||
$this->assertEquals($lastEmailId, $lastEmail['id']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -881,6 +881,9 @@ class FunctionsCustomClientTest extends Scope
|
||||
$this->assertEquals($expectedTemplates[$i]['vcsProvider'], $templates['body']['templates'][$i]['vcsProvider']);
|
||||
$this->assertEquals($expectedTemplates[$i]['runtimes'], $templates['body']['templates'][$i]['runtimes']);
|
||||
$this->assertEquals($expectedTemplates[$i]['variables'], $templates['body']['templates'][$i]['variables']);
|
||||
if (array_key_exists('scopes', $expectedTemplates[$i])) {
|
||||
$this->assertEquals($expectedTemplates[$i]['scopes'], $templates['body']['templates'][$i]['scopes']);
|
||||
}
|
||||
}
|
||||
|
||||
$templates_offset = $this->client->call(Client::METHOD_GET, '/functions/templates', array_merge([
|
||||
|
||||
@@ -1594,7 +1594,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([
|
||||
@@ -1609,7 +1609,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([
|
||||
@@ -1641,6 +1656,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[] = [
|
||||
|
||||
Reference in New Issue
Block a user