1
0
Fork 0
mirror of synced 2024-05-18 19:52:39 +12:00
appwrite/app/controllers/shared/api.php

253 lines
9 KiB
PHP
Raw Normal View History

2019-05-09 18:54:39 +12:00
<?php
2019-10-01 17:57:41 +13:00
2021-01-12 10:52:05 +13:00
use Appwrite\Auth\Auth;
2022-05-26 23:51:08 +12:00
use Appwrite\Event\Audit;
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 22:51:49 +12:00
use Appwrite\Event\Database as EventDatabase;
2022-05-26 23:51:08 +12:00
use Appwrite\Event\Delete;
2022-04-04 18:30:07 +12:00
use Appwrite\Event\Event;
2022-05-26 23:51:08 +12:00
use Appwrite\Event\Mail;
2021-06-30 23:36:58 +12:00
use Appwrite\Messaging\Adapter\Realtime;
2022-05-26 23:51:08 +12:00
use Appwrite\Stats\Stats;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Request;
2020-06-29 05:31:21 +12:00
use Utopia\App;
2022-02-07 01:49:01 +13:00
use Appwrite\Extend\Exception;
2019-11-30 07:23:29 +13:00
use Utopia\Abuse\Abuse;
use Utopia\Abuse\Adapters\TimeLimit;
2022-05-26 23:51:08 +12:00
use Utopia\Database\Database;
2021-10-08 04:35:17 +13:00
use Utopia\Database\Document;
2022-01-19 00:05:04 +13:00
use Utopia\Database\Validator\Authorization;
2022-05-26 23:51:08 +12:00
use Utopia\Registry\Registry;
2019-11-30 07:23:29 +13:00
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 22:51:49 +12:00
App::init(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $events, Audit $audits, Mail $mails, Stats $usage, Delete $deletes, EventDatabase $database, Database $dbForProject, string $mode) {
2021-01-06 01:22:20 +13:00
2019-11-30 07:23:29 +13:00
$route = $utopia->match($request);
2021-06-21 01:59:36 +12:00
if ($project->isEmpty() && $route->getLabel('abuse-limit', 0) > 0) { // Abuse limit requires an active project scope
2022-02-07 01:49:01 +13:00
throw new Exception('Missing or unknown project ID', 400, Exception::PROJECT_UNKNOWN);
}
2021-06-07 17:17:29 +12:00
/*
* Abuse Check
*/
$abuseKeyLabel = $route->getLabel('abuse-key', 'url:{url},ip:{ip}');
$timeLimitArray = [];
2021-06-07 17:17:29 +12:00
2021-11-24 22:57:25 +13:00
$abuseKeyLabel = (!is_array($abuseKeyLabel)) ? [$abuseKeyLabel] : $abuseKeyLabel;
2021-06-07 17:17:29 +12:00
2021-11-10 03:07:10 +13:00
foreach ($abuseKeyLabel as $abuseKey) {
$timeLimit = new TimeLimit($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $dbForProject);
$timeLimit
->setParam('{userId}', $user->getId())
->setParam('{userAgent}', $request->getUserAgent(''))
->setParam('{ip}', $request->getIP())
2022-05-24 02:54:50 +12:00
->setParam('{url}', $request->getHostname() . $route->getPath());
$timeLimitArray[] = $timeLimit;
2021-06-07 17:17:29 +12:00
}
2021-11-10 03:52:32 +13:00
$closestLimit = null;
2021-06-07 17:17:29 +12:00
$roles = Authorization::getRoles();
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
$isAppUser = Auth::isAppUser($roles);
2021-06-07 17:17:29 +12:00
foreach ($timeLimitArray as $timeLimit) {
foreach ($request->getParams() as $key => $value) { // Set request params as potential abuse keys
2022-05-24 02:54:50 +12:00
if (!empty($value)) {
$timeLimit->setParam('{param-' . $key . '}', (\is_array($value)) ? \json_encode($value) : $value);
}
2021-06-24 03:11:23 +12:00
}
2021-06-07 17:17:29 +12:00
$abuse = new Abuse($timeLimit);
2021-06-07 17:17:29 +12:00
2021-11-10 03:56:25 +13:00
if ($timeLimit->limit() && ($timeLimit->remaining() < $closestLimit || is_null($closestLimit))) {
2021-11-10 03:07:10 +13:00
$closestLimit = $timeLimit->remaining();
$response
->addHeader('X-RateLimit-Limit', $timeLimit->limit())
->addHeader('X-RateLimit-Remaining', $timeLimit->remaining())
->addHeader('X-RateLimit-Reset', $timeLimit->time() + $route->getLabel('abuse-time', 3600))
;
}
2021-06-07 17:17:29 +12:00
2022-05-24 02:54:50 +12:00
if (
(App::getEnv('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled' // Route is rate-limited
&& $abuse->check()) // Abuse is not disabled
&& (!$isAppUser && !$isPrivilegedUser)
) { // User is not an admin or API key
throw new Exception('Too many requests', 429, Exception::GENERAL_RATE_LIMIT_EXCEEDED);
}
2021-06-07 17:17:29 +12:00
}
2021-01-06 01:22:20 +13:00
/*
* Background Jobs
*/
2022-04-04 18:30:07 +12:00
$events
->setEvent($route->getLabel('event', ''))
->setProject($project)
->setUser($user)
;
$mails
->setProject($project)
->setUser($user)
2021-01-06 01:22:20 +13:00
;
$audits
->setMode($mode)
->setUserAgent($request->getUserAgent(''))
->setIP($request->getIP())
2022-04-04 18:30:07 +12:00
->setEvent($route->getLabel('event', ''))
->setProject($project)
->setUser($user)
2021-01-06 01:22:20 +13:00
;
$usage
->setParam('projectId', $project->getId())
->setParam('httpRequest', 1)
2022-05-24 02:54:50 +12:00
->setParam('httpUrl', $request->getHostname() . $request->getURI())
2021-01-06 01:22:20 +13:00
->setParam('httpMethod', $request->getMethod())
2021-08-24 21:51:45 +12:00
->setParam('httpPath', $route->getPath())
2021-01-06 01:22:20 +13:00
->setParam('networkRequestSize', 0)
->setParam('networkResponseSize', 0)
->setParam('storage', 0)
;
$deletes->setProject($project);
$database->setProject($project);
}, ['utopia', 'request', 'response', 'project', 'user', 'events', 'audits', 'mails', 'usage', 'deletes', 'database', 'dbForProject', 'mode'], 'api');
2021-01-06 01:22:20 +13:00
2022-05-26 23:51:08 +12:00
App::init(function (App $utopia, Request $request, Document $project) {
2021-03-01 07:36:13 +13:00
$route = $utopia->match($request);
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
$isAppUser = Auth::isAppUser(Authorization::getRoles());
2021-03-01 07:36:13 +13:00
2022-05-24 02:54:50 +12:00
if ($isAppUser || $isPrivilegedUser) { // Skip limits for app and console devs
2021-03-01 07:36:13 +13:00
return;
}
2021-08-06 19:42:31 +12:00
$auths = $project->getAttribute('auths', []);
2021-03-01 07:36:13 +13:00
switch ($route->getLabel('auth.type', '')) {
case 'emailPassword':
2022-05-24 02:54:50 +12:00
if (($auths['emailPassword'] ?? true) === false) {
2022-02-07 01:49:01 +13:00
throw new Exception('Email / Password authentication is disabled for this project', 501, Exception::USER_AUTH_METHOD_UNSUPPORTED);
2021-03-01 07:36:13 +13:00
}
break;
2021-08-31 22:29:54 +12:00
case 'magic-url':
2022-05-24 02:54:50 +12:00
if ($project->getAttribute('usersAuthMagicURL', true) === false) {
2022-02-07 01:49:01 +13:00
throw new Exception('Magic URL authentication is disabled for this project', 501, Exception::USER_AUTH_METHOD_UNSUPPORTED);
2021-08-31 22:29:54 +12:00
}
break;
2021-03-01 07:36:13 +13:00
case 'anonymous':
2022-05-24 02:54:50 +12:00
if (($auths['anonymous'] ?? true) === false) {
2022-02-07 01:49:01 +13:00
throw new Exception('Anonymous authentication is disabled for this project', 501, Exception::USER_AUTH_METHOD_UNSUPPORTED);
2021-03-01 07:36:13 +13:00
}
break;
case 'invites':
2022-05-24 02:54:50 +12:00
if (($auths['invites'] ?? true) === false) {
2022-02-07 01:49:01 +13:00
throw new Exception('Invites authentication is disabled for this project', 501, Exception::USER_AUTH_METHOD_UNSUPPORTED);
2021-03-01 07:36:13 +13:00
}
break;
case 'jwt':
2022-05-24 02:54:50 +12:00
if (($auths['JWT'] ?? true) === false) {
2022-02-07 01:49:01 +13:00
throw new Exception('JWT authentication is disabled for this project', 501, Exception::USER_AUTH_METHOD_UNSUPPORTED);
2021-03-01 07:36:13 +13:00
}
break;
2021-12-07 01:03:12 +13:00
2021-03-01 07:36:13 +13:00
default:
throw new Exception('Unsupported authentication route', 501, Exception::USER_AUTH_METHOD_UNSUPPORTED);
2021-03-01 07:36:13 +13:00
break;
}
2021-08-06 22:48:50 +12:00
}, ['utopia', 'request', 'project'], 'auth');
2021-03-01 07:36:13 +13:00
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 22:51:49 +12:00
App::shutdown(function (App $utopia, Request $request, Response $response, Document $project, Event $events, Audit $audits, Stats $usage, Delete $deletes, EventDatabase $database, string $mode, Database $dbForProject) {
2021-01-06 01:22:20 +13:00
2022-04-04 18:30:07 +12:00
if (!empty($events->getEvent())) {
2022-04-19 04:21:45 +12:00
if (empty($events->getPayload())) {
$events->setPayload($response->getPayload());
}
/**
* Trigger functions.
*/
$events
->setClass(Event::FUNCTIONS_CLASS_NAME)
->setQueue(Event::FUNCTIONS_QUEUE_NAME)
->trigger();
2021-01-06 01:22:20 +13:00
/**
* Trigger webhooks.
*/
$events
->setClass(Event::WEBHOOK_CLASS_NAME)
->setQueue(Event::WEBHOOK_QUEUE_NAME)
2021-01-06 01:22:20 +13:00
->trigger();
2021-03-12 05:28:03 +13:00
/**
* Trigger realtime.
*/
2021-03-12 05:28:03 +13:00
if ($project->getId() !== 'console') {
$allEvents = Event::generateEvents($events->getEvent(), $events->getParams());
2022-04-19 04:21:45 +12:00
$payload = new Document($events->getPayload());
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 22:51:49 +12:00
$db = $events->getContext('database');
$collection = $events->getContext('collection');
$bucket = $events->getContext('bucket');
2021-12-17 07:12:06 +13:00
$target = Realtime::fromPayload(
2022-05-10 00:36:29 +12:00
// Pass first, most verbose event pattern
event: $allEvents[0],
payload: $payload,
project: $project,
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 22:51:49 +12:00
database: $db,
2022-02-16 14:30:27 +13:00
collection: $collection,
bucket: $bucket,
2021-12-17 07:12:06 +13:00
);
2021-06-30 23:36:58 +12:00
Realtime::send(
2022-04-19 04:21:45 +12:00
projectId: $target['projectId'] ?? $project->getId(),
payload: $events->getPayload(),
events: $allEvents,
channels: $target['channels'],
roles: $target['roles'],
options: [
2022-05-24 02:54:50 +12:00
'permissionsChanged' => $target['permissionsChanged'],
2021-06-30 23:36:58 +12:00
'userId' => $events->getParam('userId')
]
);
2021-03-12 05:28:03 +13:00
}
2021-01-06 01:22:20 +13:00
}
2021-10-08 04:35:17 +13:00
if (!empty($audits->getResource())) {
foreach ($events->getParams() as $key => $value) {
$audits->setParam($key, $value);
}
2021-01-06 01:22:20 +13:00
$audits->trigger();
}
2021-10-08 04:35:17 +13:00
2022-04-18 08:34:32 +12:00
if (!empty($deletes->getType())) {
2021-01-06 01:22:20 +13:00
$deletes->trigger();
}
if (!empty($database->getType())) {
$database->trigger();
}
2021-10-08 04:35:17 +13:00
2021-01-06 01:22:20 +13:00
$route = $utopia->match($request);
2022-05-24 02:54:50 +12:00
if (
App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled'
&& $project->getId()
2021-07-28 02:16:12 +12:00
&& $mode !== APP_MODE_ADMIN // TODO: add check to make sure user is admin
2022-05-24 02:54:50 +12:00
&& !empty($route->getLabel('sdk.namespace', null))
) { // Don't calculate console usage on admin mode
2022-04-18 08:34:32 +12:00
$usage
->setParam('networkRequestSize', $request->getSize() + $usage->getParam('storage'))
->setParam('networkResponseSize', $response->getSize())
->submit();
2021-01-06 01:22:20 +13:00
}
2022-05-24 02:54:50 +12:00
}, ['utopia', 'request', 'response', 'project', 'events', 'audits', 'usage', 'deletes', 'database', 'mode', 'dbForProject'], 'api');