Merge branch '1.1.x' of https://github.com/appwrite/appwrite into feat-console-rewrite
This commit is contained in:
commit
ef1e5a9674
10
CHANGES.md
10
CHANGES.md
|
@ -1,19 +1,15 @@
|
|||
# Version 1.1.0
|
||||
|
||||
## Features
|
||||
- Added new property to projects configuration: `sessionDuration` which allows you to alter the duration of signed in sessions for your project. [#4618](https://github.com/appwrite/appwrite/pull/4618)
|
||||
- Added new property to projects configuration: `authDuration` which allows you to alter the duration of signed in sessions for your project. [#4618](https://github.com/appwrite/appwrite/pull/4618)
|
||||
|
||||
## Bugs
|
||||
- Fix license detection for Flutter and Dart SDKs [#4435](https://github.com/appwrite/appwrite/pull/4435)
|
||||
- Fix missing status, buildStderr and buildStderr from get deployment response [#4611](https://github.com/appwrite/appwrite/pull/4611)
|
||||
- Fix missing `status`, `buildStderr` and `buildStderr` from get deployment response [#4611](https://github.com/appwrite/appwrite/pull/4611)
|
||||
- Fix project pagination in DB usage aggregation [#4517](https://github.com/appwrite/appwrite/pull/4517)
|
||||
|
||||
# Features
|
||||
- Added Auth Duration API to allow users to set the duration of their sessions. [#4618](https://github.com/appwrite/appwrite/pull/4618)
|
||||
|
||||
# Version 1.0.4
|
||||
|
||||
- Fix project pagination in DB usage collector [#4517](https://github.com/appwrite/appwrite/pull/4517)
|
||||
|
||||
# Version 1.0.3
|
||||
## Bugs
|
||||
- Fix document audit deletion [#4429](https://github.com/appwrite/appwrite/pull/4429)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 602943f7a6487789f32ea3643e0c299a5b393d25
|
||||
Subproject commit 0ed6e0c497931f16fcb0750fe351d1d3577a7d97
|
|
@ -81,7 +81,7 @@ App::post('/v1/projects')
|
|||
}
|
||||
|
||||
$auth = Config::getParam('auth', []);
|
||||
$auths = ['limit' => 0];
|
||||
$auths = ['limit' => 0, 'duration' => Auth::TOKEN_EXPIRATION_LOGIN_LONG];
|
||||
foreach ($auth as $index => $method) {
|
||||
$auths[$method['key'] ?? ''] = true;
|
||||
}
|
||||
|
@ -522,7 +522,7 @@ App::patch('/v1/projects/:projectId/auth/duration')
|
|||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_PROJECT)
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('duration', 525600, new Range(0, 525600), 'Project session length in minutes. Max length: 525600 minutes.')
|
||||
->param('duration', 31536000, new Range(0, 31536000), 'Project session length in seconds. Max length: 31536000 seconds.')
|
||||
->inject('response')
|
||||
->inject('dbForConsole')
|
||||
->action(function (string $projectId, int $duration, Response $response, Database $dbForConsole) {
|
||||
|
@ -534,7 +534,7 @@ App::patch('/v1/projects/:projectId/auth/duration')
|
|||
}
|
||||
|
||||
$auths = $project->getAttribute('auths', []);
|
||||
$auths['duration'] = $duration * 60;
|
||||
$auths['duration'] = $duration;
|
||||
|
||||
$dbForConsole->updateDocument('projects', $project->getId(), $project
|
||||
->setAttribute('auths', $auths));
|
||||
|
|
|
@ -306,7 +306,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
|
|||
if ($realtime->hasSubscriber($projectId, 'user:' . $userId)) {
|
||||
$connection = array_key_first(reset($realtime->subscriptions[$projectId]['user:' . $userId]));
|
||||
[$consoleDatabase, $returnConsoleDatabase] = getDatabase($register, '_console');
|
||||
$project = Authorization::skip(fn() => $consoleDatabase->getDocument('projects', $projectId));
|
||||
$project = Authorization::skip(fn () => $consoleDatabase->getDocument('projects', $projectId));
|
||||
[$database, $returnDatabase] = getDatabase($register, "_{$project->getInternalId()}");
|
||||
|
||||
$user = $database->getDocument('users', $userId);
|
||||
|
@ -484,6 +484,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
|||
|
||||
$server->onMessage(function (int $connection, string $message) use ($server, $register, $realtime, $containerId) {
|
||||
try {
|
||||
$app = new App('UTC');
|
||||
$response = new Response(new SwooleResponse());
|
||||
$db = $register->get('dbPool')->get();
|
||||
$redis = $register->get('redisPool')->get();
|
||||
|
@ -493,12 +494,8 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re
|
|||
$database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
|
||||
$database->setNamespace("_console");
|
||||
$projectId = $realtime->connections[$connection]['projectId'];
|
||||
|
||||
if ($projectId !== 'console') {
|
||||
$project = Authorization::skip(fn() => $database->getDocument('projects', $projectId));
|
||||
$database->setNamespace("_{$project->getInternalId()}");
|
||||
}
|
||||
|
||||
$project = $projectId === 'console' ? $app->getResource('console') : Authorization::skip(fn () => $database->getDocument('projects', $projectId));
|
||||
$database->setNamespace("_{$project->getInternalId()}");
|
||||
/*
|
||||
* Abuse Check
|
||||
*
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
<ini name="memory_limit" value="4096M"/>
|
||||
<!-- Exclude SDK's for performance reasons -->
|
||||
<exclude-pattern>./app/sdks</exclude-pattern>
|
||||
<!-- Exclude console -->
|
||||
<exclude-pattern>./app/console</exclude-pattern>
|
||||
<!-- Ignore max line width -->
|
||||
<rule ref="Generic.Files.LineLength">
|
||||
<exclude-pattern>*</exclude-pattern>
|
||||
|
|
|
@ -45,7 +45,7 @@ abstract class Migration
|
|||
'1.0.0' => 'V15',
|
||||
'1.0.1' => 'V15',
|
||||
'1.0.3' => 'V15',
|
||||
'1.1.0' => 'V15',
|
||||
'1.1.0' => 'V16',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
116
src/Appwrite/Migration/Version/V16.php
Normal file
116
src/Appwrite/Migration/Version/V16.php
Normal file
|
@ -0,0 +1,116 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Migration\Version;
|
||||
|
||||
use Appwrite\Auth\Auth;
|
||||
use Appwrite\Migration\Migration;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
|
||||
class V16 extends Migration
|
||||
{
|
||||
public function execute(): void
|
||||
{
|
||||
/**
|
||||
* Disable SubQueries for Performance.
|
||||
*/
|
||||
foreach (['subQueryIndexes', 'subQueryPlatforms', 'subQueryDomains', 'subQueryKeys', 'subQueryWebhooks', 'subQuerySessions', 'subQueryTokens', 'subQueryMemberships', 'subqueryVariables'] as $name) {
|
||||
Database::addFilter(
|
||||
$name,
|
||||
fn () => null,
|
||||
fn () => []
|
||||
);
|
||||
}
|
||||
|
||||
Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')');
|
||||
|
||||
Console::info('Migrating Collections');
|
||||
$this->migrateCollections();
|
||||
|
||||
Console::info('Migrating Documents');
|
||||
$this->forEachDocument([$this, 'fixDocument']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate all Collections.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function migrateCollections(): void
|
||||
{
|
||||
foreach ($this->collections as $collection) {
|
||||
$id = $collection['$id'];
|
||||
|
||||
Console::log("Migrating Collection \"{$id}\"");
|
||||
|
||||
$this->projectDB->setNamespace("_{$this->project->getInternalId()}");
|
||||
|
||||
switch ($id) {
|
||||
case 'sessions':
|
||||
try {
|
||||
/**
|
||||
* Create 'compression' attribute
|
||||
*/
|
||||
$this->projectDB->deleteAttribute($id, 'expire');
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'expire' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'projects':
|
||||
try {
|
||||
/**
|
||||
* Create 'region' attribute
|
||||
*/
|
||||
$this->createAttributeFromCollection($this->projectDB, $id, 'region');
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'region' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
|
||||
try {
|
||||
/**
|
||||
* Create '_key_team' index
|
||||
*/
|
||||
$this->createIndexFromCollection($this->projectDB, $id, '_key_team');
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'_key_team' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
usleep(50000);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix run on each document
|
||||
*
|
||||
* @param \Utopia\Database\Document $document
|
||||
* @return \Utopia\Database\Document
|
||||
*/
|
||||
protected function fixDocument(Document $document)
|
||||
{
|
||||
switch ($document->getCollection()) {
|
||||
case 'projects':
|
||||
/**
|
||||
* Bump version number.
|
||||
*/
|
||||
$document->setAttribute('version', '1.1.0');
|
||||
|
||||
/**
|
||||
* Set default authDuration
|
||||
*/
|
||||
$document->setAttribute('auths', array_merge($document->getAttribute('auths', []), [
|
||||
'duration' => Auth::TOKEN_EXPIRATION_LOGIN_LONG
|
||||
]));
|
||||
break;
|
||||
}
|
||||
|
||||
return $document;
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Appwrite\Utopia\Response\Model;
|
||||
|
||||
use Appwrite\Auth\Auth;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Appwrite\Utopia\Response\Model;
|
||||
use Utopia\Config\Config;
|
||||
|
@ -102,10 +103,10 @@ class Project extends Model
|
|||
'example' => '131102020',
|
||||
])
|
||||
->addRule('authDuration', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Session duration in seconds.',
|
||||
'default' => '',
|
||||
'example' => '30',
|
||||
'default' => Auth::TOKEN_EXPIRATION_LOGIN_LONG,
|
||||
'example' => 60,
|
||||
])
|
||||
->addRule('authLimit', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
|
@ -231,7 +232,7 @@ class Project extends Model
|
|||
$auth = Config::getParam('auth', []);
|
||||
|
||||
$document->setAttribute('authLimit', $authValues['limit'] ?? 0);
|
||||
$document->setAttribute('authDuration', $authValues['duration'] ?? 0);
|
||||
$document->setAttribute('authDuration', $authValues['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG);
|
||||
|
||||
foreach ($auth as $index => $method) {
|
||||
$key = $method['key'];
|
||||
|
|
|
@ -85,7 +85,7 @@ class UsageTest extends Scope
|
|||
#[Retry(count: 1)]
|
||||
public function testUsersStats(array $data): array
|
||||
{
|
||||
sleep(10);
|
||||
sleep(20);
|
||||
|
||||
$projectId = $data['projectId'];
|
||||
$headers = $data['headers'];
|
||||
|
@ -256,7 +256,7 @@ class UsageTest extends Scope
|
|||
$filesCreate = $data['filesCreate'];
|
||||
$filesDelete = $data['filesDelete'];
|
||||
|
||||
sleep(10);
|
||||
sleep(20);
|
||||
|
||||
// console request
|
||||
$headers = [
|
||||
|
@ -414,7 +414,7 @@ class UsageTest extends Scope
|
|||
$this->assertEquals('name', $res['body']['key']);
|
||||
$collectionsUpdate++;
|
||||
$requestsCount++;
|
||||
sleep(10);
|
||||
sleep(20);
|
||||
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
$name = uniqid() . ' collection';
|
||||
|
@ -496,7 +496,7 @@ class UsageTest extends Scope
|
|||
$documentsRead = $data['documentsRead'];
|
||||
$documentsDelete = $data['documentsDelete'];
|
||||
|
||||
sleep(10);
|
||||
sleep(20);
|
||||
|
||||
// check datbase stats
|
||||
$headers = [
|
||||
|
@ -704,7 +704,7 @@ class UsageTest extends Scope
|
|||
$executions = $data['executions'];
|
||||
$failures = $data['failures'];
|
||||
|
||||
sleep(10);
|
||||
sleep(20);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/usage', $headers, [
|
||||
'range' => '30d'
|
||||
|
|
|
@ -417,6 +417,15 @@ class ProjectsConsoleClientTest extends Scope
|
|||
{
|
||||
$id = $data['projectId'];
|
||||
|
||||
// Check defaults
|
||||
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => 'console',
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(Auth::TOKEN_EXPIRATION_LOGIN_LONG, $response['body']['authDuration']); // 1 Year
|
||||
|
||||
/**
|
||||
* Test for SUCCESS
|
||||
*/
|
||||
|
@ -425,7 +434,7 @@ class ProjectsConsoleClientTest extends Scope
|
|||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'duration' => '1', // Set session duration to 2 minutes
|
||||
'duration' => 60, // Set session duration to 2 minutes
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
@ -475,8 +484,21 @@ class ProjectsConsoleClientTest extends Scope
|
|||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
||||
// Check session doesn't expire too soon.
|
||||
|
||||
sleep(30);
|
||||
|
||||
// Get User
|
||||
$response = $this->client->call(Client::METHOD_GET, '/account', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $projectId,
|
||||
'Cookie' => $sessionCookie,
|
||||
]));
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
||||
// Wait just over a minute
|
||||
sleep(65);
|
||||
sleep(35);
|
||||
|
||||
// Get User
|
||||
$response = $this->client->call(Client::METHOD_GET, '/account', array_merge([
|
||||
|
@ -492,7 +514,7 @@ class ProjectsConsoleClientTest extends Scope
|
|||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'duration' => 525600,
|
||||
'duration' => Auth::TOKEN_EXPIRATION_LOGIN_LONG,
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
@ -505,7 +527,7 @@ class ProjectsConsoleClientTest extends Scope
|
|||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(31536000, $response['body']['authDuration']); // 1 Year
|
||||
$this->assertEquals(Auth::TOKEN_EXPIRATION_LOGIN_LONG, $response['body']['authDuration']); // 1 Year
|
||||
|
||||
return ['projectId' => $projectId];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue