mirror of
https://github.com/appwrite/appwrite
synced 2026-05-23 17:08:45 +00:00
Merge branch '1.5.x' of github.com:appwrite/appwrite into migration-clean-cache
This commit is contained in:
commit
29e169fe95
19 changed files with 252 additions and 39 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1672,10 +1672,10 @@ App::post('/v1/account/tokens/magic-url')
|
|||
->inject('queueForEvents')
|
||||
->inject('queueForMails')
|
||||
->action(function (string $userId, string $email, string $url, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails) {
|
||||
|
||||
if (empty(System::getEnv('_APP_SMTP_HOST'))) {
|
||||
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled');
|
||||
}
|
||||
$url = htmlentities($url);
|
||||
|
||||
if ($phrase === true) {
|
||||
$phrase = Phrase::generate();
|
||||
|
|
@ -2860,6 +2860,7 @@ App::post('/v1/account/recovery')
|
|||
if (empty(System::getEnv('_APP_SMTP_HOST'))) {
|
||||
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled');
|
||||
}
|
||||
$url = htmlentities($url);
|
||||
|
||||
$roles = Authorization::getRoles();
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
|
||||
|
|
@ -3123,6 +3124,7 @@ App::post('/v1/account/verification')
|
|||
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled');
|
||||
}
|
||||
|
||||
$url = htmlentities($url);
|
||||
if ($user->getAttribute('emailVerification')) {
|
||||
throw new Exception(Exception::USER_EMAIL_ALREADY_VERIFIED);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -499,6 +499,8 @@ App::get('/v1/functions/:functionId/usage')
|
|||
str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE),
|
||||
str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS),
|
||||
str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE),
|
||||
str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS),
|
||||
str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS)
|
||||
];
|
||||
|
||||
Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) {
|
||||
|
|
@ -561,6 +563,10 @@ App::get('/v1/functions/:functionId/usage')
|
|||
'buildsTime' => $usage[$metrics[4]]['data'],
|
||||
'executions' => $usage[$metrics[5]]['data'],
|
||||
'executionsTime' => $usage[$metrics[6]]['data'],
|
||||
'buildsMbSecondsTotal' => $usage[$metrics[7]]['total'],
|
||||
'buildsMbSeconds' => $usage[$metrics[7]]['data'],
|
||||
'executionsMbSeconds' => $usage[$metrics[8]]['data'],
|
||||
'executionsMbSecondsTotal' => $usage[$metrics[8]]['total']
|
||||
]), Response::MODEL_USAGE_FUNCTION);
|
||||
});
|
||||
|
||||
|
|
@ -591,6 +597,8 @@ App::get('/v1/functions/usage')
|
|||
METRIC_BUILDS_COMPUTE,
|
||||
METRIC_EXECUTIONS,
|
||||
METRIC_EXECUTIONS_COMPUTE,
|
||||
METRIC_BUILDS_MB_SECONDS,
|
||||
METRIC_EXECUTIONS_MB_SECONDS,
|
||||
];
|
||||
|
||||
Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) {
|
||||
|
|
@ -654,6 +662,10 @@ App::get('/v1/functions/usage')
|
|||
'buildsTime' => $usage[$metrics[5]]['data'],
|
||||
'executions' => $usage[$metrics[6]]['data'],
|
||||
'executionsTime' => $usage[$metrics[7]]['data'],
|
||||
'buildsMbSecondsTotal' => $usage[$metrics[8]]['total'],
|
||||
'buildsMbSeconds' => $usage[$metrics[8]]['data'],
|
||||
'executionsMbSeconds' => $usage[$metrics[9]]['data'],
|
||||
'executionsMbSecondsTotal' => $usage[$metrics[9]]['total'],
|
||||
]), Response::MODEL_USAGE_FUNCTIONS);
|
||||
});
|
||||
|
||||
|
|
@ -1761,6 +1773,8 @@ App::post('/v1/functions/:functionId/executions')
|
|||
->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1)
|
||||
->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000)) // per project
|
||||
->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function
|
||||
->addMetric(METRIC_EXECUTIONS_MB_SECONDS, (int)(512 * $execution->getAttribute('duration', 0)))
|
||||
->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS), (int)(512 * $execution->getAttribute('duration', 0)))
|
||||
;
|
||||
|
||||
if ($function->getAttribute('logging')) {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ App::get('/v1/project/usage')
|
|||
$metrics = [
|
||||
'total' => [
|
||||
METRIC_EXECUTIONS,
|
||||
METRIC_EXECUTIONS_MB_SECONDS,
|
||||
METRIC_BUILDS_MB_SECONDS,
|
||||
METRIC_DOCUMENTS,
|
||||
METRIC_DATABASES,
|
||||
METRIC_USERS,
|
||||
|
|
@ -52,7 +54,9 @@ App::get('/v1/project/usage')
|
|||
METRIC_NETWORK_INBOUND,
|
||||
METRIC_NETWORK_OUTBOUND,
|
||||
METRIC_USERS,
|
||||
METRIC_EXECUTIONS
|
||||
METRIC_EXECUTIONS,
|
||||
METRIC_EXECUTIONS_MB_SECONDS,
|
||||
METRIC_BUILDS_MB_SECONDS
|
||||
]
|
||||
];
|
||||
|
||||
|
|
@ -161,6 +165,38 @@ App::get('/v1/project/usage')
|
|||
];
|
||||
}, $dbForProject->find('functions'));
|
||||
|
||||
$executionsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) {
|
||||
$id = $function->getId();
|
||||
$name = $function->getAttribute('name');
|
||||
$metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS);
|
||||
$value = $dbForProject->findOne('stats', [
|
||||
Query::equal('metric', [$metric]),
|
||||
Query::equal('period', ['inf'])
|
||||
]);
|
||||
|
||||
return [
|
||||
'resourceId' => $id,
|
||||
'name' => $name,
|
||||
'value' => $value['value'] ?? 0,
|
||||
];
|
||||
}, $dbForProject->find('functions'));
|
||||
|
||||
$buildsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) {
|
||||
$id = $function->getId();
|
||||
$name = $function->getAttribute('name');
|
||||
$metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS);
|
||||
$value = $dbForProject->findOne('stats', [
|
||||
Query::equal('metric', [$metric]),
|
||||
Query::equal('period', ['inf'])
|
||||
]);
|
||||
|
||||
return [
|
||||
'resourceId' => $id,
|
||||
'name' => $name,
|
||||
'value' => $value['value'] ?? 0,
|
||||
];
|
||||
}, $dbForProject->find('functions'));
|
||||
|
||||
// merge network inbound + outbound
|
||||
$projectBandwidth = [];
|
||||
foreach ($usage[METRIC_NETWORK_INBOUND] as $item) {
|
||||
|
|
@ -188,6 +224,8 @@ App::get('/v1/project/usage')
|
|||
'users' => ($usage[METRIC_USERS]),
|
||||
'executions' => ($usage[METRIC_EXECUTIONS]),
|
||||
'executionsTotal' => $total[METRIC_EXECUTIONS],
|
||||
'executionsMbSecondsTotal' => $total[METRIC_EXECUTIONS_MB_SECONDS],
|
||||
'buildsMbSecondsTotal' => $total[METRIC_BUILDS_MB_SECONDS],
|
||||
'documentsTotal' => $total[METRIC_DOCUMENTS],
|
||||
'databasesTotal' => $total[METRIC_DATABASES],
|
||||
'usersTotal' => $total[METRIC_USERS],
|
||||
|
|
@ -195,6 +233,8 @@ App::get('/v1/project/usage')
|
|||
'filesStorageTotal' => $total[METRIC_FILES_STORAGE],
|
||||
'deploymentsStorageTotal' => $total[METRIC_DEPLOYMENTS_STORAGE],
|
||||
'executionsBreakdown' => $executionsBreakdown,
|
||||
'executionsMbSecondsBreakdown' => $executionsMbSecondsBreakdown,
|
||||
'buildsMbSecondsBreakdown' => $buildsMbSecondsBreakdown,
|
||||
'bucketsBreakdown' => $bucketsBreakdown,
|
||||
'deploymentsStorageBreakdown' => $deploymentsStorageBreakdown,
|
||||
]), Response::MODEL_USAGE_PROJECT);
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ App::init()
|
|||
App::post('/v1/projects')
|
||||
->desc('Create project')
|
||||
->groups(['api', 'projects'])
|
||||
->label('audits.event', 'projects.create')
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
|
|
@ -825,6 +826,7 @@ App::patch('/v1/projects/:projectId/auth/max-sessions')
|
|||
App::delete('/v1/projects/:projectId')
|
||||
->desc('Delete project')
|
||||
->groups(['api', 'projects'])
|
||||
->label('audits.event', 'projects.delete')
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
|
|
@ -1321,6 +1323,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId')
|
|||
App::post('/v1/projects/:projectId/platforms')
|
||||
->desc('Create platform')
|
||||
->groups(['api', 'projects'])
|
||||
->label('audits.event', 'platforms.create')
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
|
|
@ -1484,6 +1487,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId')
|
|||
App::delete('/v1/projects/:projectId/platforms/:platformId')
|
||||
->desc('Delete platform')
|
||||
->groups(['api', 'projects'])
|
||||
->label('audits.event', 'platforms.delete')
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ App::post('/v1/storage/buckets')
|
|||
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, no user is granted with any permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
|
||||
->param('fileSecurity', false, new Boolean(true), 'Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
|
||||
->param('enabled', true, new Boolean(true), 'Is bucket enabled? When set to \'disabled\', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.', true)
|
||||
->param('maximumFileSize', fn (array $plan) => empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1024 * 1024, fn (array $plan) => new Range(1, empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1024 * 1024), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(System::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true, ['plan'])
|
||||
->param('maximumFileSize', fn (array $plan) => empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000, fn (array $plan) => new Range(1, empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(System::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true, ['plan'])
|
||||
->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true)
|
||||
->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true)
|
||||
->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true)
|
||||
|
|
@ -240,7 +240,7 @@ App::put('/v1/storage/buckets/:bucketId')
|
|||
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
|
||||
->param('fileSecurity', false, new Boolean(true), 'Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
|
||||
->param('enabled', true, new Boolean(true), 'Is bucket enabled? When set to \'disabled\', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.', true)
|
||||
->param('maximumFileSize', fn (array $plan) => empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1024 * 1024, fn (array $plan) => new Range(1, empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1024 * 1024), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(System::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true, ['plan'])
|
||||
->param('maximumFileSize', fn (array $plan) => empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000, fn (array $plan) => new Range(1, empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(System::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true, ['plan'])
|
||||
->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true)
|
||||
->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true)
|
||||
->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true)
|
||||
|
|
|
|||
|
|
@ -401,6 +401,7 @@ App::post('/v1/teams/:teamId/memberships')
|
|||
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
|
||||
|
||||
$url = htmlentities($url);
|
||||
if (empty($url)) {
|
||||
if (!$isAPIKey && !$isPrivilegedUser) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'URL is required');
|
||||
|
|
|
|||
|
|
@ -310,6 +310,8 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo
|
|||
->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1)
|
||||
->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000)) // per project
|
||||
->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function
|
||||
->addMetric(METRIC_EXECUTIONS_MB_SECONDS, (int)(512 * $execution->getAttribute('duration', 0)))
|
||||
->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS), (int)(512 * $execution->getAttribute('duration', 0)))
|
||||
;
|
||||
|
||||
if ($function->getAttribute('logging')) {
|
||||
|
|
|
|||
|
|
@ -231,15 +231,19 @@ const METRIC_DEPLOYMENTS_STORAGE = 'deployments.storage';
|
|||
const METRIC_BUILDS = 'builds';
|
||||
const METRIC_BUILDS_STORAGE = 'builds.storage';
|
||||
const METRIC_BUILDS_COMPUTE = 'builds.compute';
|
||||
const METRIC_BUILDS_MB_SECONDS = 'builds.mbSeconds';
|
||||
const METRIC_FUNCTION_ID_BUILDS = '{functionInternalId}.builds';
|
||||
const METRIC_FUNCTION_ID_BUILDS_STORAGE = '{functionInternalId}.builds.storage';
|
||||
const METRIC_FUNCTION_ID_BUILDS_COMPUTE = '{functionInternalId}.builds.compute';
|
||||
const METRIC_FUNCTION_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments';
|
||||
const METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage';
|
||||
const METRIC_FUNCTION_ID_BUILDS_MB_SECONDS = '{functionInternalId}.builds.mbSeconds';
|
||||
const METRIC_EXECUTIONS = 'executions';
|
||||
const METRIC_EXECUTIONS_COMPUTE = 'executions.compute';
|
||||
const METRIC_EXECUTIONS_MB_SECONDS = 'executions.mbSeconds';
|
||||
const METRIC_FUNCTION_ID_EXECUTIONS = '{functionInternalId}.executions';
|
||||
const METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE = '{functionInternalId}.executions.compute';
|
||||
const METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS = '{functionInternalId}.executions.mbSeconds';
|
||||
const METRIC_NETWORK_REQUESTS = 'network.requests';
|
||||
const METRIC_NETWORK_INBOUND = 'network.inbound';
|
||||
const METRIC_NETWORK_OUTBOUND = 'network.outbound';
|
||||
|
|
|
|||
56
composer.lock
generated
56
composer.lock
generated
|
|
@ -355,16 +355,16 @@
|
|||
},
|
||||
{
|
||||
"name": "chillerlan/php-settings-container",
|
||||
"version": "2.1.5",
|
||||
"version": "2.1.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/chillerlan/php-settings-container.git",
|
||||
"reference": "f705310389264c3578fdd9ffb15aa2cd6d91772e"
|
||||
"reference": "5553558bd381fce5108c6d0343c12e488cfec6bb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/f705310389264c3578fdd9ffb15aa2cd6d91772e",
|
||||
"reference": "f705310389264c3578fdd9ffb15aa2cd6d91772e",
|
||||
"url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/5553558bd381fce5108c6d0343c12e488cfec6bb",
|
||||
"reference": "5553558bd381fce5108c6d0343c12e488cfec6bb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -372,15 +372,16 @@
|
|||
"php": "^7.4 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phan/phan": "^5.4",
|
||||
"phpcsstandards/php_codesniffer": "^3.8",
|
||||
"phpmd/phpmd": "^2.13",
|
||||
"phpunit/phpunit": "^9.6"
|
||||
"phpmd/phpmd": "^2.15",
|
||||
"phpstan/phpstan": "^1.11",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.2",
|
||||
"phpunit/phpunit": "^9.6",
|
||||
"squizlabs/php_codesniffer": "^3.10"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"chillerlan\\Settings\\": "src/"
|
||||
"chillerlan\\Settings\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
|
|
@ -417,7 +418,7 @@
|
|||
"type": "ko_fi"
|
||||
}
|
||||
],
|
||||
"time": "2024-01-05T23:20:55+00:00"
|
||||
"time": "2024-07-17T01:04:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dragonmantank/cron-expression",
|
||||
|
|
@ -1719,16 +1720,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/database",
|
||||
"version": "0.50.0",
|
||||
"version": "0.50.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/database.git",
|
||||
"reference": "ce3eaccb2f3bbd34b2b97419836fec633b26b8f7"
|
||||
"reference": "1745147bef29a9bddf5dd03fd9174ec29e2c26f0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/ce3eaccb2f3bbd34b2b97419836fec633b26b8f7",
|
||||
"reference": "ce3eaccb2f3bbd34b2b97419836fec633b26b8f7",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/1745147bef29a9bddf5dd03fd9174ec29e2c26f0",
|
||||
"reference": "1745147bef29a9bddf5dd03fd9174ec29e2c26f0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -1769,9 +1770,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/database/issues",
|
||||
"source": "https://github.com/utopia-php/database/tree/0.50.0"
|
||||
"source": "https://github.com/utopia-php/database/tree/0.50.1"
|
||||
},
|
||||
"time": "2024-06-21T03:21:42+00:00"
|
||||
"time": "2024-07-26T11:56:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/domains",
|
||||
|
|
@ -2170,16 +2171,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/migration",
|
||||
"version": "0.5.1",
|
||||
"version": "0.5.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/migration.git",
|
||||
"reference": "f0e7ff0a76546de353d1ea1f49605b958d407ed2"
|
||||
"reference": "f18d44d4459f78c292dac9edde856fd156fe497a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/migration/zipball/f0e7ff0a76546de353d1ea1f49605b958d407ed2",
|
||||
"reference": "f0e7ff0a76546de353d1ea1f49605b958d407ed2",
|
||||
"url": "https://api.github.com/repos/utopia-php/migration/zipball/f18d44d4459f78c292dac9edde856fd156fe497a",
|
||||
"reference": "f18d44d4459f78c292dac9edde856fd156fe497a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -2189,6 +2190,7 @@
|
|||
"require-dev": {
|
||||
"laravel/pint": "1.*",
|
||||
"phpunit/phpunit": "9.*",
|
||||
"utopia-php/cli": "^0.18.0",
|
||||
"vlucas/phpdotenv": "5.*"
|
||||
},
|
||||
"type": "library",
|
||||
|
|
@ -2211,9 +2213,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/migration/issues",
|
||||
"source": "https://github.com/utopia-php/migration/tree/0.5.1"
|
||||
"source": "https://github.com/utopia-php/migration/tree/0.5.2"
|
||||
},
|
||||
"time": "2024-07-10T05:48:42+00:00"
|
||||
"time": "2024-07-22T09:27:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/mongo",
|
||||
|
|
@ -3156,16 +3158,16 @@
|
|||
},
|
||||
{
|
||||
"name": "laravel/pint",
|
||||
"version": "v1.16.2",
|
||||
"version": "v1.17.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/pint.git",
|
||||
"reference": "51f1ba679a6afe0315621ad143d788bd7ded0eca"
|
||||
"reference": "4dba80c1de4b81dc4c4fb10ea6f4781495eb29f5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/pint/zipball/51f1ba679a6afe0315621ad143d788bd7ded0eca",
|
||||
"reference": "51f1ba679a6afe0315621ad143d788bd7ded0eca",
|
||||
"url": "https://api.github.com/repos/laravel/pint/zipball/4dba80c1de4b81dc4c4fb10ea6f4781495eb29f5",
|
||||
"reference": "4dba80c1de4b81dc4c4fb10ea6f4781495eb29f5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -3218,7 +3220,7 @@
|
|||
"issues": "https://github.com/laravel/pint/issues",
|
||||
"source": "https://github.com/laravel/pint"
|
||||
},
|
||||
"time": "2024-07-09T15:58:08+00:00"
|
||||
"time": "2024-07-23T16:40:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "matthiasmullie/minify",
|
||||
|
|
|
|||
|
|
@ -543,9 +543,11 @@ class Builds extends Action
|
|||
->addMetric(METRIC_BUILDS, 1) // per project
|
||||
->addMetric(METRIC_BUILDS_STORAGE, $build->getAttribute('size', 0))
|
||||
->addMetric(METRIC_BUILDS_COMPUTE, (int)$build->getAttribute('duration', 0) * 1000)
|
||||
->addMetric(METRIC_BUILDS_MB_SECONDS, (int)(512 * $build->getAttribute('duration', 0)))
|
||||
->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS), 1) // per function
|
||||
->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE), $build->getAttribute('size', 0))
|
||||
->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int)$build->getAttribute('duration', 0) * 1000)
|
||||
->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS), (int)(512 * $build->getAttribute('duration', 0)))
|
||||
->setProject($project)
|
||||
->trigger();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -507,6 +507,8 @@ class Functions extends Action
|
|||
->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1)
|
||||
->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000))// per project
|
||||
->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000))
|
||||
->addMetric(METRIC_EXECUTIONS_MB_SECONDS, (int)(512 * $execution->getAttribute('duration', 0)))
|
||||
->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS), (int)(512 * $execution->getAttribute('duration', 0)))
|
||||
->trigger()
|
||||
;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,12 @@ class UsageFunction extends Model
|
|||
'default' => 0,
|
||||
'example' => 0,
|
||||
])
|
||||
->addRule('buildsMbSecondsTotal', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Total aggregated sum of function builds mbSeconds.',
|
||||
'default' => 0,
|
||||
'example' => 0,
|
||||
])
|
||||
->addRule('executionsTotal', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Total aggregated number of function executions.',
|
||||
|
|
@ -58,6 +64,12 @@ class UsageFunction extends Model
|
|||
'default' => 0,
|
||||
'example' => 0,
|
||||
])
|
||||
->addRule('executionsMbSecondsTotal', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Total aggregated sum of function executions mbSeconds.',
|
||||
'default' => 0,
|
||||
'example' => 0,
|
||||
])
|
||||
->addRule('deployments', [
|
||||
'type' => Response::MODEL_METRIC,
|
||||
'description' => 'Aggregated number of function deployments per period.',
|
||||
|
|
@ -93,6 +105,13 @@ class UsageFunction extends Model
|
|||
'example' => [],
|
||||
'array' => true
|
||||
])
|
||||
->addRule('buildsMbSeconds', [
|
||||
'type' => Response::MODEL_METRIC,
|
||||
'description' => 'Aggregated number of function builds mbSeconds per period.',
|
||||
'default' => [],
|
||||
'example' => [],
|
||||
'array' => true
|
||||
])
|
||||
->addRule('executions', [
|
||||
'type' => Response::MODEL_METRIC,
|
||||
'description' => 'Aggregated number of function executions per period.',
|
||||
|
|
@ -108,6 +127,13 @@ class UsageFunction extends Model
|
|||
'example' => [],
|
||||
'array' => true
|
||||
])
|
||||
->addRule('executionsMbSeconds', [
|
||||
'type' => Response::MODEL_METRIC,
|
||||
'description' => 'Aggregated number of function mbSeconds per period.',
|
||||
'default' => [],
|
||||
'example' => [],
|
||||
'array' => true
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,12 @@ class UsageFunctions extends Model
|
|||
'default' => 0,
|
||||
'example' => 0,
|
||||
])
|
||||
->addRule('buildsMbSecondsTotal', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Total aggregated sum of functions build mbSeconds.',
|
||||
'default' => 0,
|
||||
'example' => 0,
|
||||
])
|
||||
->addRule('executionsTotal', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Total aggregated number of functions execution.',
|
||||
|
|
@ -64,6 +70,12 @@ class UsageFunctions extends Model
|
|||
'default' => 0,
|
||||
'example' => 0,
|
||||
])
|
||||
->addRule('executionsMbSecondsTotal', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Total aggregated sum of functions execution mbSeconds.',
|
||||
'default' => 0,
|
||||
'example' => 0,
|
||||
])
|
||||
->addRule('functions', [
|
||||
'type' => Response::MODEL_METRIC,
|
||||
'description' => 'Aggregated number of functions per period.',
|
||||
|
|
@ -106,6 +118,13 @@ class UsageFunctions extends Model
|
|||
'example' => [],
|
||||
'array' => true
|
||||
])
|
||||
->addRule('buildsMbSeconds', [
|
||||
'type' => Response::MODEL_METRIC,
|
||||
'description' => 'Aggregated sum of functions build mbSeconds per period.',
|
||||
'default' => [],
|
||||
'example' => [],
|
||||
'array' => true
|
||||
])
|
||||
->addRule('executions', [
|
||||
'type' => Response::MODEL_METRIC,
|
||||
'description' => 'Aggregated number of functions execution per period.',
|
||||
|
|
@ -121,6 +140,13 @@ class UsageFunctions extends Model
|
|||
'example' => [],
|
||||
'array' => true
|
||||
])
|
||||
->addRule('executionsMbSeconds', [
|
||||
'type' => Response::MODEL_METRIC,
|
||||
'description' => 'Aggregated number of functions mbSeconds per period.',
|
||||
'default' => [],
|
||||
'example' => [],
|
||||
'array' => true
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,18 @@ class UsageProject extends Model
|
|||
'default' => 0,
|
||||
'example' => 0,
|
||||
])
|
||||
->addRule('executionsMbSecondsTotal', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Total aggregated number of function executions mbSeconds.',
|
||||
'default' => 0,
|
||||
'example' => 0,
|
||||
])
|
||||
->addRule('buildsMbSecondsTotal', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Total aggregated number of function builds mbSeconds.',
|
||||
'default' => 0,
|
||||
'example' => 0,
|
||||
])
|
||||
->addRule('requests', [
|
||||
'type' => Response::MODEL_METRIC,
|
||||
'description' => 'Aggregated number of requests per period.',
|
||||
|
|
@ -94,6 +106,20 @@ class UsageProject extends Model
|
|||
'example' => [],
|
||||
'array' => true
|
||||
])
|
||||
->addRule('executionsMbSecondsBreakdown', [
|
||||
'type' => Response::MODEL_METRIC_BREAKDOWN,
|
||||
'description' => 'Aggregated breakdown in totals of execution mbSeconds by functions.',
|
||||
'default' => [],
|
||||
'example' => [],
|
||||
'array' => true
|
||||
])
|
||||
->addRule('buildsMbSecondsBreakdown', [
|
||||
'type' => Response::MODEL_METRIC_BREAKDOWN,
|
||||
'description' => 'Aggregated breakdown in totals of build mbSeconds by functions.',
|
||||
'default' => [],
|
||||
'example' => [],
|
||||
'array' => true
|
||||
])
|
||||
->addRule('deploymentsStorageBreakdown', [
|
||||
'type' => Response::MODEL_METRIC_BREAKDOWN,
|
||||
'description' => 'Aggregated breakdown in totals of deployments storage size (in bytes).',
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ class UsageTest extends Scope
|
|||
);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(14, count($response['body']));
|
||||
$this->assertEquals(18, count($response['body']));
|
||||
$this->validateDates($response['body']['network']);
|
||||
$this->validateDates($response['body']['requests']);
|
||||
$this->validateDates($response['body']['users']);
|
||||
|
|
@ -321,7 +321,7 @@ class UsageTest extends Scope
|
|||
]
|
||||
);
|
||||
|
||||
$this->assertEquals(14, count($response['body']));
|
||||
$this->assertEquals(18, count($response['body']));
|
||||
$this->assertEquals(1, count($response['body']['requests']));
|
||||
$this->assertEquals($requestsTotal, $response['body']['requests'][array_key_last($response['body']['requests'])]['value']);
|
||||
$this->validateDates($response['body']['requests']);
|
||||
|
|
@ -542,7 +542,7 @@ class UsageTest extends Scope
|
|||
]
|
||||
);
|
||||
|
||||
$this->assertEquals(14, count($response['body']));
|
||||
$this->assertEquals(18, count($response['body']));
|
||||
$this->assertEquals(1, count($response['body']['requests']));
|
||||
$this->assertEquals(1, count($response['body']['network']));
|
||||
$this->assertEquals($requestsTotal, $response['body']['requests'][array_key_last($response['body']['requests'])]['value']);
|
||||
|
|
@ -774,15 +774,19 @@ class UsageTest extends Scope
|
|||
);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(15, count($response['body']));
|
||||
$this->assertEquals(19, count($response['body']));
|
||||
$this->assertEquals('30d', $response['body']['range']);
|
||||
$this->assertIsArray($response['body']['deployments']);
|
||||
$this->assertIsArray($response['body']['deploymentsStorage']);
|
||||
$this->assertIsNumeric($response['body']['deploymentsStorageTotal']);
|
||||
$this->assertIsNumeric($response['body']['buildsMbSecondsTotal']);
|
||||
$this->assertIsNumeric($response['body']['executionsMbSecondsTotal']);
|
||||
$this->assertIsArray($response['body']['builds']);
|
||||
$this->assertIsArray($response['body']['buildsTime']);
|
||||
$this->assertIsArray($response['body']['buildsMbSeconds']);
|
||||
$this->assertIsArray($response['body']['executions']);
|
||||
$this->assertIsArray($response['body']['executionsTime']);
|
||||
$this->assertIsArray($response['body']['executionsMbSeconds']);
|
||||
$this->assertEquals($executions, $response['body']['executions'][array_key_last($response['body']['executions'])]['value']);
|
||||
$this->validateDates($response['body']['executions']);
|
||||
$this->assertEquals($executionTime, $response['body']['executionsTime'][array_key_last($response['body']['executionsTime'])]['value']);
|
||||
|
|
@ -795,15 +799,17 @@ class UsageTest extends Scope
|
|||
);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(17, count($response['body']));
|
||||
$this->assertEquals(21, count($response['body']));
|
||||
$this->assertEquals($response['body']['range'], '30d');
|
||||
$this->assertIsArray($response['body']['functions']);
|
||||
$this->assertIsArray($response['body']['deployments']);
|
||||
$this->assertIsArray($response['body']['deploymentsStorage']);
|
||||
$this->assertIsArray($response['body']['builds']);
|
||||
$this->assertIsArray($response['body']['buildsTime']);
|
||||
$this->assertIsArray($response['body']['buildsMbSeconds']);
|
||||
$this->assertIsArray($response['body']['executions']);
|
||||
$this->assertIsArray($response['body']['executionsTime']);
|
||||
$this->assertIsArray($response['body']['executionsMbSeconds']);
|
||||
$this->assertEquals($executions, $response['body']['executions'][array_key_last($response['body']['executions'])]['value']);
|
||||
$this->validateDates($response['body']['executions']);
|
||||
$this->assertEquals($executionTime, $response['body']['executionsTime'][array_key_last($response['body']['executionsTime'])]['value']);
|
||||
|
|
|
|||
|
|
@ -92,23 +92,27 @@ class FunctionsConsoleClientTest extends Scope
|
|||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(15, count($response['body']));
|
||||
$this->assertEquals(19, count($response['body']));
|
||||
$this->assertEquals('24h', $response['body']['range']);
|
||||
$this->assertIsNumeric($response['body']['deploymentsTotal']);
|
||||
$this->assertIsNumeric($response['body']['deploymentsStorageTotal']);
|
||||
$this->assertIsNumeric($response['body']['buildsTotal']);
|
||||
$this->assertIsNumeric($response['body']['buildsStorageTotal']);
|
||||
$this->assertIsNumeric($response['body']['buildsTimeTotal']);
|
||||
$this->assertIsNumeric($response['body']['buildsMbSecondsTotal']);
|
||||
$this->assertIsNumeric($response['body']['executionsTotal']);
|
||||
$this->assertIsNumeric($response['body']['executionsTimeTotal']);
|
||||
$this->assertIsNumeric($response['body']['executionsMbSecondsTotal']);
|
||||
$this->assertIsArray($response['body']['deployments']);
|
||||
$this->assertIsArray($response['body']['deploymentsStorage']);
|
||||
$this->assertIsArray($response['body']['builds']);
|
||||
$this->assertIsArray($response['body']['buildsTime']);
|
||||
$this->assertIsArray($response['body']['buildsStorage']);
|
||||
$this->assertIsArray($response['body']['buildsTime']);
|
||||
$this->assertIsArray($response['body']['buildsMbSeconds']);
|
||||
$this->assertIsArray($response['body']['executions']);
|
||||
$this->assertIsArray($response['body']['executionsTime']);
|
||||
$this->assertIsArray($response['body']['executionsMbSeconds']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Tests\E2E\Services\Teams;
|
||||
|
||||
use Tests\E2E\Client;
|
||||
use Tests\E2E\Scopes\ProjectCustom;
|
||||
use Tests\E2E\Scopes\Scope;
|
||||
use Tests\E2E\Scopes\SideClient;
|
||||
|
|
@ -12,4 +13,55 @@ class TeamsCustomClientTest extends Scope
|
|||
use TeamsBaseClient;
|
||||
use ProjectCustom;
|
||||
use SideClient;
|
||||
|
||||
/**
|
||||
* @depends testUpdateTeamMembership
|
||||
*/
|
||||
public function testTeamsInviteHTMLInjection($data): array
|
||||
{
|
||||
$teamUid = $data['teamUid'] ?? '';
|
||||
$email = uniqid() . 'friend@localhost.test';
|
||||
$name = 'Friend User';
|
||||
$password = 'password';
|
||||
|
||||
// Create a user account before we create a invite so we can check if the user has permissions when it shouldn't
|
||||
$user = $this->client->call(Client::METHOD_POST, '/account', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => 'console'], [
|
||||
'userId' => 'unique()',
|
||||
'email' => $email,
|
||||
'password' => $password,
|
||||
'name' => $name,
|
||||
], false);
|
||||
|
||||
$this->assertEquals(201, $user['headers']['status-code']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'email' => $email,
|
||||
'name' => $name,
|
||||
'roles' => ['admin', 'editor'],
|
||||
'url' => 'http://localhost:5000/join-us\"></a><h1>INJECTED</h1>'
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
|
||||
$email = $this->getLastEmail();
|
||||
$encoded = 'http://localhost:5000/join-us\"></a><h1>INJECTED</h1>?';
|
||||
|
||||
$this->assertStringNotContainsString('<h1>INJECTED</h1>', $email['html']);
|
||||
$this->assertStringContainsString($encoded, $email['html']);
|
||||
$this->assertStringContainsString($encoded, $email['text']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/'.$response['body']['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue