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 ;
use Appwrite\Database\Validator\Authorization ;
2020-06-29 05:31:21 +12:00
use Utopia\App ;
2019-11-30 07:23:29 +13:00
use Utopia\Exception ;
use Utopia\Abuse\Abuse ;
use Utopia\Abuse\Adapters\TimeLimit ;
2021-01-22 21:28:33 +13:00
use Utopia\Storage\Device\Local ;
use Utopia\Storage\Storage ;
2019-11-30 07:23:29 +13:00
2021-01-06 01:22:20 +13:00
App :: init ( function ( $utopia , $request , $response , $project , $user , $register , $events , $audits , $usage , $deletes ) {
2020-07-03 05:37:24 +12:00
/** @var Utopia\App $utopia */
2020-10-30 02:07:56 +13:00
/** @var Utopia\Swoole\Request $request */
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2021-05-16 21:18:34 +12:00
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Document $user */
2020-07-03 05:37:24 +12:00
/** @var Utopia\Registry\Registry $register */
2021-01-06 01:22:20 +13:00
/** @var Appwrite\Event\Event $events */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Event\Event $usage */
/** @var Appwrite\Event\Event $deletes */
/** @var Appwrite\Event\Event $functions */
Storage :: setDevice ( 'files' , new Local ( APP_STORAGE_UPLOADS . '/app-' . $project -> getId ()));
Storage :: setDevice ( 'functions' , new Local ( APP_STORAGE_FUNCTIONS . '/app-' . $project -> getId ()));
2020-07-03 05:37:24 +12:00
2019-11-30 07:23:29 +13:00
$route = $utopia -> match ( $request );
2020-06-25 08:59:04 +12:00
if ( empty ( $project -> getId ()) && $route -> getLabel ( 'abuse-limit' , 0 ) > 0 ) { // Abuse limit requires an active project scope
2020-06-18 08:08:55 +12:00
throw new Exception ( 'Missing or unknown project ID' , 400 );
}
2021-05-16 21:18:34 +12:00
// /*
// * Abuse Check
// */
// $timeLimit = new TimeLimit($route->getLabel('abuse-key', 'url:{url},ip:{ip}'), $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), function () use ($register) {
// return $register->get('db');
// });
// $timeLimit->setNamespace('app_'.$project->getId());
// $timeLimit
// ->setParam('{userId}', $user->getId())
// ->setParam('{userAgent}', $request->getUserAgent(''))
// ->setParam('{ip}', $request->getIP())
// ->setParam('{url}', $request->getHostname().$route->getURL())
// ;
2019-11-30 07:23:29 +13:00
2021-05-16 21:18:34 +12:00
// //TODO make sure we get array here
2019-11-30 07:23:29 +13:00
2021-05-16 21:18:34 +12:00
// foreach ($request->getParams() as $key => $value) { // Set request params as potential abuse keys
2021-06-04 08:19:04 +12:00
// if(!empty($value)) {
// $timeLimit->setParam('{param-'.$key.'}', (\is_array($value)) ? \json_encode($value) : $value);
// }
2021-05-16 21:18:34 +12:00
// }
2019-11-30 07:23:29 +13:00
2021-05-16 21:18:34 +12:00
// $abuse = new Abuse($timeLimit);
2019-11-30 07:23:29 +13:00
2021-05-16 21:18:34 +12:00
// if ($timeLimit->limit()) {
// $response
// ->addHeader('X-RateLimit-Limit', $timeLimit->limit())
// ->addHeader('X-RateLimit-Remaining', $timeLimit->remaining())
// ->addHeader('X-RateLimit-Reset', $timeLimit->time() + $route->getLabel('abuse-time', 3600))
// ;
// }
2019-11-30 07:23:29 +13:00
2021-05-16 21:18:34 +12:00
// $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::$roles);
// $isAppUser = Auth::isAppUser(Authorization::$roles);
2021-01-12 10:52:05 +13:00
2021-05-16 21:18:34 +12:00
// if (($abuse->check() // Route is rate-limited
// && App::getEnv('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled') // Abuse is not diabled
// && (!$isAppUser && !$isPrivilegedUser)) // User is not an admin or API key
// {
// throw new Exception('Too many requests', 429);
// }
2021-01-06 01:22:20 +13:00
/*
* Background Jobs
*/
$events
-> setParam ( 'projectId' , $project -> getId ())
2021-05-17 23:32:37 +12:00
-> setParam ( 'webhooks' , $project -> getAttribute ( 'webhooks' , []))
2021-01-06 01:22:20 +13:00
-> setParam ( 'userId' , $user -> getId ())
-> setParam ( 'event' , $route -> getLabel ( 'event' , '' ))
2021-03-30 07:00:10 +13:00
-> setParam ( 'eventData' , [])
2021-01-06 01:22:20 +13:00
-> setParam ( 'functionId' , null )
-> setParam ( 'executionId' , null )
-> setParam ( 'trigger' , 'event' )
;
$audits
-> setParam ( 'projectId' , $project -> getId ())
-> setParam ( 'userId' , $user -> getId ())
-> setParam ( 'event' , '' )
-> setParam ( 'resource' , '' )
-> setParam ( 'userAgent' , $request -> getUserAgent ( '' ))
-> setParam ( 'ip' , $request -> getIP ())
-> setParam ( 'data' , [])
;
$usage
-> setParam ( 'projectId' , $project -> getId ())
-> setParam ( 'httpRequest' , 1 )
-> setParam ( 'httpUrl' , $request -> getHostname () . $request -> getURI ())
-> setParam ( 'httpMethod' , $request -> getMethod ())
-> setParam ( 'networkRequestSize' , 0 )
-> setParam ( 'networkResponseSize' , 0 )
-> setParam ( 'storage' , 0 )
;
$deletes
-> setParam ( 'projectId' , $project -> getId ())
;
}, [ 'utopia' , 'request' , 'response' , 'project' , 'user' , 'register' , 'events' , 'audits' , 'usage' , 'deletes' ], 'api' );
2021-03-01 07:36:13 +13:00
App :: init ( function ( $utopia , $request , $response , $project , $user ) {
/** @var Utopia\App $utopia */
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Appwrite\Database\Document $project */
/** @var Appwrite\Database\Document $user */
/** @var Utopia\Registry\Registry $register */
/** @var Appwrite\Event\Event $events */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Event\Event $usage */
/** @var Appwrite\Event\Event $deletes */
/** @var Appwrite\Event\Event $functions */
$route = $utopia -> match ( $request );
2021-03-02 10:04:53 +13:00
$isPrivilegedUser = Auth :: isPrivilegedUser ( Authorization :: $roles );
2021-03-01 07:36:13 +13:00
$isAppUser = Auth :: isAppUser ( Authorization :: $roles );
2021-03-02 10:04:53 +13:00
if ( $isAppUser || $isPrivilegedUser ) { // Skip limits for app and console devs
2021-03-01 07:36:13 +13:00
return ;
}
switch ( $route -> getLabel ( 'auth.type' , '' )) {
case 'emailPassword' :
2021-03-01 09:46:26 +13:00
if ( $project -> getAttribute ( 'usersAuthEmailPassword' , true ) === false ) {
2021-03-01 07:36:13 +13:00
throw new Exception ( 'Email / Password authentication is disabled for this project' , 501 );
}
break ;
case 'anonymous' :
2021-03-01 09:46:26 +13:00
if ( $project -> getAttribute ( 'usersAuthAnonymous' , true ) === false ) {
2021-03-01 07:36:13 +13:00
throw new Exception ( 'Anonymous authentication is disabled for this project' , 501 );
}
break ;
case 'invites' :
2021-03-01 09:46:26 +13:00
if ( $project -> getAttribute ( 'usersAuthInvites' , true ) === false ) {
2021-03-01 07:36:13 +13:00
throw new Exception ( 'Invites authentication is disabled for this project' , 501 );
}
break ;
case 'jwt' :
2021-03-01 09:46:26 +13:00
if ( $project -> getAttribute ( 'usersAuthJWT' , true ) === false ) {
2021-03-01 07:36:13 +13:00
throw new Exception ( 'JWT authentication is disabled for this project' , 501 );
}
break ;
default :
throw new Exception ( 'Unsupported authentication route' );
break ;
}
}, [ 'utopia' , 'request' , 'response' , 'project' , 'user' ], 'auth' );
2021-01-06 01:22:20 +13:00
App :: shutdown ( function ( $utopia , $request , $response , $project , $events , $audits , $usage , $deletes , $mode ) {
/** @var Utopia\App $utopia */
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Appwrite\Database\Document $project */
/** @var Appwrite\Event\Event $events */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Event\Event $usage */
/** @var Appwrite\Event\Event $deletes */
/** @var Appwrite\Event\Event $functions */
/** @var bool $mode */
if ( ! empty ( $events -> getParam ( 'event' ))) {
2021-03-30 07:00:10 +13:00
if ( empty ( $events -> getParam ( 'eventData' ))) {
$events -> setParam ( 'eventData' , $response -> getPayload ());
2021-01-06 01:22:20 +13:00
}
$webhooks = clone $events ;
$functions = clone $events ;
$webhooks
-> setQueue ( 'v1-webhooks' )
-> setClass ( 'WebhooksV1' )
-> trigger ();
$functions
-> setQueue ( 'v1-functions' )
-> setClass ( 'FunctionsV1' )
-> trigger ();
}
if ( ! empty ( $audits -> getParam ( 'event' ))) {
$audits -> trigger ();
}
if ( ! empty ( $deletes -> getParam ( 'type' )) && ! empty ( $deletes -> getParam ( 'document' ))) {
$deletes -> trigger ();
}
$route = $utopia -> match ( $request );
2021-01-14 19:05:55 +13:00
if ( App :: getEnv ( '_APP_USAGE_STATS' , 'enabled' ) == 'enabled'
&& $project -> getId ()
2021-01-06 01:22:20 +13:00
&& $mode !== APP_MODE_ADMIN //TODO: add check to make sure user is admin
&& ! empty ( $route -> getLabel ( 'sdk.namespace' , null ))) { // Don't calculate console usage on admin mode
$usage
-> setParam ( 'networkRequestSize' , $request -> getSize () + $usage -> getParam ( 'storage' ))
-> setParam ( 'networkResponseSize' , $response -> getSize ())
-> trigger ()
;
}
}, [ 'utopia' , 'request' , 'response' , 'project' , 'events' , 'audits' , 'usage' , 'deletes' , 'mode' ], 'api' );