2019-05-09 18:54:39 +12:00
< ? php
2020-07-29 19:29:34 +12:00
require_once __DIR__ . '/../init.php' ;
2019-10-25 06:53:37 +13:00
2019-05-09 18:54:39 +12:00
use Utopia\App ;
2020-07-08 08:40:08 +12:00
use Appwrite\Swoole\Request ;
2020-06-29 19:22:53 +12:00
use Appwrite\Utopia\Response ;
2019-10-25 06:53:37 +13:00
use Utopia\View ;
use Utopia\Exception ;
2020-03-29 01:42:16 +13:00
use Utopia\Config\Config ;
2020-03-18 00:36:13 +13:00
use Utopia\Domains\Domain ;
2020-03-25 06:56:32 +13:00
use Appwrite\Auth\Auth ;
use Appwrite\Database\Database ;
use Appwrite\Database\Document ;
use Appwrite\Database\Validator\Authorization ;
2020-06-12 07:36:10 +12:00
use Appwrite\Network\Validator\Origin ;
2020-07-15 08:33:52 +12:00
use Appwrite\Storage\Device\Local ;
use Appwrite\Storage\Storage ;
2019-05-09 18:54:39 +12:00
2020-06-29 08:45:36 +12:00
Config :: setParam ( 'domainVerification' , false );
2020-07-01 18:35:57 +12:00
Config :: setParam ( 'cookieDomain' , 'localhost' );
Config :: setParam ( 'cookieSamesite' , Response :: COOKIE_SAMESITE_NONE );
2020-06-30 09:43:34 +12:00
2020-08-03 23:47:32 +12:00
App :: init ( function ( $utopia , $request , $response , $console , $project , $user , $locale , $webhooks , $audits , $usage , $functions , $clients ) {
2020-07-08 08:40:08 +12:00
/** @var Appwrite\Swoole\Request $request */
2020-08-06 18:55:17 +12:00
/** @var Appwrite\Swoole\Response $response */
2020-06-30 23:09:28 +12:00
/** @var Appwrite\Database\Document $console */
/** @var Appwrite\Database\Document $project */
/** @var Appwrite\Database\Document $user */
/** @var Utopia\Locale\Locale $locale */
2020-07-06 02:19:59 +12:00
/** @var Appwrite\Event\Event $webhooks */
/** @var Appwrite\Event\Event $audits */
2020-06-30 23:09:28 +12:00
/** @var Appwrite\Event\Event $usage */
2020-08-03 23:47:32 +12:00
/** @var Appwrite\Event\Event $functions */
2020-06-30 23:09:28 +12:00
/** @var bool $mode */
/** @var array $clients */
2020-07-05 00:31:26 +12:00
Authorization :: $roles = [ '*' ];
2020-06-30 23:09:28 +12:00
2020-07-05 10:22:22 +12:00
$localeParam = ( string ) $request -> getParam ( 'locale' , $request -> getHeader ( 'x-appwrite-locale' , '' ));
2020-06-30 17:27:52 +12:00
if ( \in_array ( $localeParam , Config :: getParam ( 'locale-codes' ))) {
2020-06-30 09:43:34 +12:00
$locale -> setDefault ( $localeParam );
};
2019-10-25 06:53:37 +13:00
$route = $utopia -> match ( $request );
2020-05-01 22:07:53 +12:00
if ( ! empty ( $route -> getLabel ( 'sdk.platform' , [])) && empty ( $project -> getId ()) && ( $route -> getLabel ( 'scope' , '' ) !== 'public' )) {
2020-04-08 23:21:41 +12:00
throw new Exception ( 'Missing or unknown project ID' , 400 );
2020-04-07 18:10:58 +12:00
}
2020-06-29 08:45:36 +12:00
$console -> setAttribute ( 'platforms' , [ // Allways allow current host
'$collection' => Database :: SYSTEM_COLLECTION_PLATFORMS ,
'name' => 'Current Host' ,
'type' => 'web' ,
2020-07-03 05:37:24 +12:00
'hostname' => $request -> getHostname (),
2020-06-29 09:06:29 +12:00
], Document :: SET_TYPE_APPEND );
2020-06-29 08:45:36 +12:00
2020-07-03 09:48:02 +12:00
$referrer = $request -> getReferer ();
$origin = \parse_url ( $request -> getOrigin ( $referrer ), PHP_URL_HOST );
$protocol = \parse_url ( $request -> getOrigin ( $referrer ), PHP_URL_SCHEME );
$port = \parse_url ( $request -> getOrigin ( $referrer ), PHP_URL_PORT );
2019-10-25 06:53:37 +13:00
2020-07-21 17:48:31 +12:00
$refDomain = ( ! empty ( $protocol ) ? $protocol : $request -> getProtocol ()) . '://' . (( \in_array ( $origin , $clients ))
2020-03-17 08:07:43 +13:00
? $origin : 'localhost' ) . ( ! empty ( $port ) ? ':' . $port : '' );
2019-10-25 06:53:37 +13:00
2020-07-03 09:48:02 +12:00
$selfDomain = new Domain ( $request -> getHostname ());
2020-03-18 00:36:13 +13:00
$endDomain = new Domain ( $origin );
2020-07-03 09:48:02 +12:00
// var_dump('referer', $referrer);
// var_dump('origin', $origin);
2020-07-03 05:37:24 +12:00
// var_dump('port', $request->getPort());
// var_dump('hostname', $request->getHostname());
// var_dump('protocol', $request->getProtocol());
// var_dump('method', $request->getMethod());
// var_dump('ip', $request->getIP());
// var_dump('-----------------');
// var_dump($request->debug());
2020-04-07 18:10:58 +12:00
Config :: setParam ( 'domainVerification' ,
2020-05-28 22:10:38 +12:00
( $selfDomain -> getRegisterable () === $endDomain -> getRegisterable ()) &&
$endDomain -> getRegisterable () !== '' );
2020-04-07 18:10:58 +12:00
2020-07-01 18:35:57 +12:00
Config :: setParam ( 'cookieDomain' , (
2020-07-03 09:48:02 +12:00
$request -> getHostname () === 'localhost' ||
$request -> getHostname () === 'localhost:' . $request -> getPort () ||
2020-07-01 18:35:57 +12:00
( \filter_var ( $request -> getHostname (), FILTER_VALIDATE_IP ) !== false )
)
? null
: '.' . $request -> getHostname ()
);
2020-07-03 09:48:02 +12:00
2020-07-15 09:20:46 +12:00
Storage :: setDevice ( 'files' , new Local ( APP_STORAGE_UPLOADS . '/app-' . $project -> getId ()));
Storage :: setDevice ( 'functions' , new Local ( APP_STORAGE_FUNCTIONS . '/app-' . $project -> getId ()));
2020-07-15 08:33:52 +12:00
2019-10-25 06:53:37 +13:00
/*
* Security Headers
*
* As recommended at :
* @ see https :// www . owasp . org / index . php / List_of_useful_HTTP_headers
*/
2020-06-29 05:31:21 +12:00
if ( App :: getEnv ( '_APP_OPTIONS_FORCE_HTTPS' , 'disabled' ) === 'enabled' ) { // Force HTTPS
2020-06-30 23:09:28 +12:00
if ( $request -> getProtocol () !== 'https' ) {
2020-07-05 09:50:55 +12:00
return $response -> redirect ( 'https://' . $request -> getHostname () . $request -> getURI ());
2020-06-02 07:58:58 +12:00
}
$response -> addHeader ( 'Strict-Transport-Security' , 'max-age=' . ( 60 * 60 * 24 * 126 )); // 126 days
}
2019-10-25 06:53:37 +13:00
$response
-> addHeader ( 'Server' , 'Appwrite' )
2020-07-05 09:50:55 +12:00
-> addHeader ( 'X-XSS-Protection' , '1; mode=block; report=/v1/xss?url=' . \urlencode ( $request -> getURI ()))
2019-10-25 06:53:37 +13:00
//->addHeader('X-Frame-Options', ($refDomain == 'http://localhost') ? 'SAMEORIGIN' : 'ALLOW-FROM ' . $refDomain)
-> addHeader ( 'X-Content-Type-Options' , 'nosniff' )
-> addHeader ( 'Access-Control-Allow-Methods' , 'GET, POST, PUT, PATCH, DELETE' )
2020-05-26 06:11:22 +12:00
-> addHeader ( 'Access-Control-Allow-Headers' , 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-SDK-Version, Cache-Control, Expires, Pragma' )
2020-02-27 22:17:09 +13:00
-> addHeader ( 'Access-Control-Expose-Headers' , 'X-Fallback-Cookies' )
2019-10-25 06:53:37 +13:00
-> addHeader ( 'Access-Control-Allow-Origin' , $refDomain )
-> addHeader ( 'Access-Control-Allow-Credentials' , 'true' )
;
2019-05-09 18:54:39 +12:00
2019-10-25 06:53:37 +13:00
/*
* Validate Client Domain - Check to avoid CSRF attack
* Adding Appwrite API domains to allow XDOMAIN communication
2020-01-29 23:49:18 +13:00
* Skip this check for non - web platforms which are not requiredto send an origin header
2019-10-25 06:53:37 +13:00
*/
2020-07-04 03:14:51 +12:00
$origin = $request -> getOrigin ( $request -> getReferer ( '' ));
2020-06-20 23:20:49 +12:00
$originValidator = new Origin ( \array_merge ( $project -> getAttribute ( 'platforms' , []), $console -> getAttribute ( 'platforms' , [])));
2020-04-14 17:44:15 +12:00
if ( ! $originValidator -> isValid ( $origin )
2020-06-20 23:20:49 +12:00
&& \in_array ( $request -> getMethod (), [ Request :: METHOD_POST , Request :: METHOD_PUT , Request :: METHOD_PATCH , Request :: METHOD_DELETE ])
2020-05-30 00:02:53 +12:00
&& $route -> getLabel ( 'origin' , false ) !== '*'
2020-07-05 10:22:22 +12:00
&& empty ( $request -> getHeader ( 'x-appwrite-key' , '' ))) {
2020-04-14 17:44:15 +12:00
throw new Exception ( $originValidator -> getDescription (), 403 );
2019-10-25 06:53:37 +13:00
}
2020-04-14 17:44:15 +12:00
2019-10-25 06:53:37 +13:00
/*
* ACL Check
*/
$role = ( $user -> isEmpty ()) ? Auth :: USER_ROLE_GUEST : Auth :: USER_ROLE_MEMBER ;
// Add user roles
$membership = $user -> search ( 'teamId' , $project -> getAttribute ( 'teamId' , null ), $user -> getAttribute ( 'memberships' , []));
if ( $membership ) {
foreach ( $membership -> getAttribute ( 'roles' , []) as $memberRole ) {
switch ( $memberRole ) {
case 'owner' :
$role = Auth :: USER_ROLE_OWNER ;
break ;
case 'admin' :
$role = Auth :: USER_ROLE_ADMIN ;
break ;
case 'developer' :
$role = Auth :: USER_ROLE_DEVELOPER ;
break ;
}
}
}
2019-05-09 18:54:39 +12:00
2020-06-26 18:14:54 +12:00
$roles = Config :: getParam ( 'roles' , []);
2019-10-25 06:53:37 +13:00
$scope = $route -> getLabel ( 'scope' , 'none' ); // Allowed scope for chosen route
$scopes = $roles [ $role ][ 'scopes' ]; // Allowed scopes for user role
2020-01-12 10:53:57 +13:00
2019-10-25 06:53:37 +13:00
// Check if given key match project API keys
2020-07-05 10:22:22 +12:00
$key = $project -> search ( 'secret' , $request -> getHeader ( 'x-appwrite-key' , '' ), $project -> getAttribute ( 'keys' , []));
2020-01-12 10:53:57 +13:00
2019-10-25 06:53:37 +13:00
/*
* Try app auth when we have project key and no user
* Mock user to app and grant API key scopes in addition to default app scopes
*/
if ( null !== $key && $user -> isEmpty ()) {
$user = new Document ([
2020-02-17 20:16:11 +13:00
'$id' => 0 ,
2019-10-25 06:53:37 +13:00
'status' => Auth :: USER_STATUS_ACTIVATED ,
2020-07-03 09:48:02 +12:00
'email' => 'app.' . $project -> getId () . '@service.' . $request -> getHostname (),
2019-10-25 06:53:37 +13:00
'password' => '' ,
'name' => $project -> getAttribute ( 'name' , 'Untitled' ),
]);
$role = Auth :: USER_ROLE_APP ;
2020-06-20 23:20:49 +12:00
$scopes = \array_merge ( $roles [ $role ][ 'scopes' ], $key -> getAttribute ( 'scopes' , []));
2019-10-25 06:53:37 +13:00
2020-02-11 19:17:40 +13:00
Authorization :: setDefaultStatus ( false ); // Cancel security segmentation for API keys.
2019-10-25 06:53:37 +13:00
}
2019-05-09 18:54:39 +12:00
2020-02-17 20:16:11 +13:00
Authorization :: setRole ( 'user:' . $user -> getId ());
2019-10-25 06:53:37 +13:00
Authorization :: setRole ( 'role:' . $role );
2019-05-09 18:54:39 +12:00
2020-06-20 23:20:49 +12:00
\array_map ( function ( $node ) {
2019-10-25 06:53:37 +13:00
if ( isset ( $node [ 'teamId' ]) && isset ( $node [ 'roles' ])) {
Authorization :: setRole ( 'team:' . $node [ 'teamId' ]);
2019-05-09 18:54:39 +12:00
2019-10-25 06:53:37 +13:00
foreach ( $node [ 'roles' ] as $nodeRole ) { // Set all team roles
Authorization :: setRole ( 'team:' . $node [ 'teamId' ] . '/' . $nodeRole );
}
}
}, $user -> getAttribute ( 'memberships' , []));
2019-05-09 18:54:39 +12:00
2019-10-25 06:53:37 +13:00
// TDOO Check if user is god
2019-05-09 18:54:39 +12:00
2020-06-20 23:20:49 +12:00
if ( ! \in_array ( $scope , $scopes )) {
2020-02-17 20:16:11 +13:00
if ( empty ( $project -> getId ()) || Database :: SYSTEM_COLLECTION_PROJECTS !== $project -> getCollection ()) { // Check if permission is denied because project is missing
2019-12-17 17:16:50 +13:00
throw new Exception ( 'Project not found' , 404 );
}
2020-06-20 23:20:49 +12:00
throw new Exception ( $user -> getAttribute ( 'email' , 'User' ) . ' (role: ' . \strtolower ( $roles [ $role ][ 'label' ]) . ') missing scope (' . $scope . ')' , 401 );
2019-10-25 06:53:37 +13:00
}
2019-05-09 18:54:39 +12:00
2019-10-25 06:53:37 +13:00
if ( Auth :: USER_STATUS_BLOCKED == $user -> getAttribute ( 'status' )) { // Account has not been activated
throw new Exception ( 'Invalid credentials. User is blocked' , 401 ); // User is in status blocked
}
2019-05-09 18:54:39 +12:00
2019-10-25 06:53:37 +13:00
if ( $user -> getAttribute ( 'reset' )) {
throw new Exception ( 'Password reset is required' , 412 );
}
2019-05-09 18:54:39 +12:00
2019-10-25 06:53:37 +13:00
/*
* Background Jobs
*/
2020-08-03 23:47:32 +12:00
$functions
-> setParam ( 'projectId' , $project -> getId ())
2020-08-05 17:18:45 +12:00
-> setParam ( 'event' , $route -> getLabel ( 'event' , '' ))
2020-08-03 23:47:32 +12:00
-> setParam ( 'payload' , [])
-> setParam ( 'functionId' , null )
-> setParam ( 'executionId' , null )
2020-08-04 17:23:38 +12:00
-> setParam ( 'trigger' , 'event' )
2020-08-03 23:47:32 +12:00
;
2020-06-30 09:43:34 +12:00
$webhooks
2020-02-17 20:16:11 +13:00
-> setParam ( 'projectId' , $project -> getId ())
2020-08-05 17:18:45 +12:00
-> setParam ( 'event' , $route -> getLabel ( 'event' , '' ))
2019-10-25 06:53:37 +13:00
-> setParam ( 'payload' , [])
;
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
$audits
2020-02-17 20:16:11 +13:00
-> setParam ( 'projectId' , $project -> getId ())
-> setParam ( 'userId' , $user -> getId ())
2019-10-25 06:53:37 +13:00
-> setParam ( 'event' , '' )
-> setParam ( 'resource' , '' )
2020-07-04 03:14:51 +12:00
-> setParam ( 'userAgent' , $request -> getUserAgent ( '' ))
2019-10-25 06:53:37 +13:00
-> setParam ( 'ip' , $request -> getIP ())
-> setParam ( 'data' , [])
;
2019-06-09 01:13:19 +12:00
2019-10-25 06:53:37 +13:00
$usage
2020-02-17 20:16:11 +13:00
-> setParam ( 'projectId' , $project -> getId ())
2020-07-20 18:43:25 +12:00
-> setParam ( 'httpRequest' , 1 )
-> setParam ( 'httpUrl' , $request -> getHostname () . $request -> getURI ())
-> setParam ( 'httpMethod' , $request -> getMethod ())
-> setParam ( 'networkRequestSize' , 0 )
-> setParam ( 'networkResponseSize' , 0 )
2019-10-25 06:53:37 +13:00
-> setParam ( 'storage' , 0 )
;
2020-08-03 23:47:32 +12:00
}, [ 'utopia' , 'request' , 'response' , 'console' , 'project' , 'user' , 'locale' , 'webhooks' , 'audits' , 'usage' , 'functions' , 'clients' ]);
2019-05-09 18:54:39 +12:00
2020-08-03 23:47:32 +12:00
App :: shutdown ( function ( $utopia , $request , $response , $project , $webhooks , $audits , $usage , $deletes , $functions , $mode ) {
2020-07-05 06:21:16 +12:00
/** @var Utopia\App $utopia */
2020-08-06 18:55:17 +12:00
/** @var Appwrite\Swoole\Request $request */
/** @var Appwrite\Swoole\Response $response */
2020-07-05 06:21:16 +12:00
/** @var Appwrite\Database\Document $project */
2020-07-06 02:19:59 +12:00
/** @var Appwrite\Event\Event $webhooks */
/** @var Appwrite\Event\Event $audits */
2020-07-05 06:21:16 +12:00
/** @var Appwrite\Event\Event $usage */
/** @var Appwrite\Event\Event $deletes */
2020-08-03 23:47:32 +12:00
/** @var Appwrite\Event\Event $functions */
2020-07-05 06:21:16 +12:00
/** @var bool $mode */
2020-08-03 23:47:32 +12:00
if ( ! empty ( $functions -> getParam ( 'event' ))) {
2020-08-06 01:12:23 +12:00
$functions -> setParam ( 'payload' , $webhooks -> getParam ( 'payload' ));
2020-08-03 23:47:32 +12:00
$functions -> trigger ();
}
2020-07-06 02:19:59 +12:00
if ( ! empty ( $webhooks -> getParam ( 'event' ))) {
$webhooks -> trigger ();
2019-10-25 06:53:37 +13:00
}
2020-01-12 02:58:02 +13:00
2020-07-06 02:19:59 +12:00
if ( ! empty ( $audits -> getParam ( 'event' ))) {
$audits -> trigger ();
2019-10-25 06:53:37 +13:00
}
2020-02-13 21:04:52 +13:00
2020-05-27 05:11:20 +12:00
if ( ! empty ( $deletes -> getParam ( 'document' ))) {
$deletes -> trigger ();
}
2020-02-13 21:04:52 +13:00
$route = $utopia -> match ( $request );
2020-06-08 04:33:51 +12:00
2020-02-17 20:16:11 +13:00
if ( $project -> getId ()
2020-02-13 21:04:52 +13:00
&& $mode !== APP_MODE_ADMIN
&& ! empty ( $route -> getLabel ( 'sdk.namespace' , null ))) { // Don't calculate console usage and admin mode
2020-05-16 05:58:56 +12:00
2020-02-13 21:04:52 +13:00
$usage
2020-07-20 18:43:25 +12:00
-> setParam ( 'networkRequestSize' , $request -> getSize () + $usage -> getParam ( 'storage' ))
-> setParam ( 'networkResponseSize' , $response -> getSize ())
2020-02-13 21:04:52 +13:00
-> trigger ()
;
}
2020-08-03 23:47:32 +12:00
}, [ 'utopia' , 'request' , 'response' , 'project' , 'webhooks' , 'audits' , 'usage' , 'deletes' , 'functions' , 'mode' ]);
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
App :: options ( function ( $request , $response ) {
2020-07-08 08:40:08 +12:00
/** @var Appwrite\Swoole\Request $request */
2020-08-06 18:55:17 +12:00
/** @var Appwrite\Swoole\Response $response */
2020-07-04 03:14:51 +12:00
2020-07-08 08:40:08 +12:00
$origin = $request -> getOrigin ();
2019-05-09 18:54:39 +12:00
2019-10-25 06:53:37 +13:00
$response
2020-07-08 08:40:08 +12:00
-> addHeader ( 'Server' , 'Appwrite' )
2019-10-25 06:53:37 +13:00
-> addHeader ( 'Access-Control-Allow-Methods' , 'GET, POST, PUT, PATCH, DELETE' )
2020-05-26 06:11:22 +12:00
-> addHeader ( 'Access-Control-Allow-Headers' , 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-SDK-Version, Cache-Control, Expires, Pragma, X-Fallback-Cookies' )
2020-02-27 22:17:09 +13:00
-> addHeader ( 'Access-Control-Expose-Headers' , 'X-Fallback-Cookies' )
2019-10-25 06:53:37 +13:00
-> addHeader ( 'Access-Control-Allow-Origin' , $origin )
-> addHeader ( 'Access-Control-Allow-Credentials' , 'true' )
-> send ();
2020-06-30 09:43:34 +12:00
}, [ 'request' , 'response' ]);
2020-07-03 17:55:08 +12:00
App :: error ( function ( $error , $utopia , $request , $response , $layout , $project ) {
2020-06-30 09:43:34 +12:00
/** @var Exception $error */
2020-07-03 17:55:08 +12:00
/** @var Utopia\App $utopia */
2020-08-06 18:55:17 +12:00
/** @var Appwrite\Swoole\Request $request */
/** @var Appwrite\Swoole\Response $response */
2020-07-03 17:55:08 +12:00
/** @var Utopia\View $layout */
/** @var Appwrite\Database\Document $project */
2019-05-09 18:54:39 +12:00
2020-07-07 16:40:18 +12:00
if ( php_sapi_name () === 'cli' ) {
var_dump ( get_class ( $error ));
var_dump ( $error -> getMessage ());
var_dump ( $error -> getFile ());
var_dump ( $error -> getLine ());
}
2020-07-05 00:31:26 +12:00
2020-06-30 23:09:28 +12:00
$version = App :: getEnv ( '_APP_VERSION' , 'UNKNOWN' );
2020-03-29 01:42:16 +13:00
2019-10-25 06:53:37 +13:00
switch ( $error -> getCode ()) {
case 400 : // Error allowed publicly
case 401 : // Error allowed publicly
case 402 : // Error allowed publicly
case 403 : // Error allowed publicly
case 404 : // Error allowed publicly
2020-01-04 10:01:09 +13:00
case 409 : // Error allowed publicly
2019-10-25 06:53:37 +13:00
case 412 : // Error allowed publicly
case 429 : // Error allowed publicly
$code = $error -> getCode ();
$message = $error -> getMessage ();
break ;
default :
$code = 500 ; // All other errors get the generic 500 server error status code
$message = 'Server Error' ;
}
2019-05-09 18:54:39 +12:00
2020-07-02 21:02:43 +12:00
//$_SERVER = []; // Reset before reporting to error log to avoid keys being compromised
2019-10-25 06:53:37 +13:00
2020-06-29 20:32:46 +12:00
$output = (( App :: isDevelopment ())) ? [
2019-10-25 06:53:37 +13:00
'message' => $error -> getMessage (),
'code' => $error -> getCode (),
'file' => $error -> getFile (),
'line' => $error -> getLine (),
'trace' => $error -> getTrace (),
'version' => $version ,
] : [
'message' => $message ,
'code' => $code ,
'version' => $version ,
];
$response
-> addHeader ( 'Cache-Control' , 'no-cache, no-store, must-revalidate' )
-> addHeader ( 'Expires' , '0' )
-> addHeader ( 'Pragma' , 'no-cache' )
-> setStatusCode ( $code )
2019-10-25 06:53:11 +13:00
;
2019-05-09 18:54:39 +12:00
2019-10-25 06:53:37 +13:00
$route = $utopia -> match ( $request );
$template = ( $route ) ? $route -> getLabel ( 'error' , null ) : null ;
if ( $template ) {
$comp = new View ( $template );
$comp
-> setParam ( 'projectName' , $project -> getAttribute ( 'name' ))
-> setParam ( 'projectURL' , $project -> getAttribute ( 'url' ))
-> setParam ( 'message' , $error -> getMessage ())
-> setParam ( 'code' , $code )
;
$layout
-> setParam ( 'title' , $project -> getAttribute ( 'name' ) . ' - Error' )
-> setParam ( 'description' , 'No Description' )
-> setParam ( 'body' , $comp )
-> setParam ( 'version' , $version )
-> setParam ( 'litespeed' , false )
;
2020-07-09 21:11:10 +12:00
$response -> html ( $layout -> render ());
2019-10-25 06:53:11 +13:00
}
2019-10-25 06:53:37 +13:00
2020-06-24 03:01:20 +12:00
$response -> dynamic ( new Document ( $output ),
$utopia -> isDevelopment () ? Response :: MODEL_ERROR_DEV : Response :: MODEL_LOCALE );
2020-07-03 17:55:08 +12:00
}, [ 'error' , 'utopia' , 'request' , 'response' , 'layout' , 'project' ]);
2019-10-25 06:53:37 +13:00
2020-06-29 05:31:21 +12:00
App :: get ( '/manifest.json' )
2019-10-25 06:53:37 +13:00
-> desc ( 'Progressive app manifest file' )
-> label ( 'scope' , 'public' )
-> label ( 'docs' , false )
2020-06-30 09:43:34 +12:00
-> action ( function ( $response ) {
2020-08-06 18:55:17 +12:00
/** @var Appwrite\Swoole\Response $response */
2020-06-30 09:43:34 +12:00
$response -> json ([
'name' => APP_NAME ,
'short_name' => APP_NAME ,
'start_url' => '.' ,
'url' => 'https://appwrite.io/' ,
'display' => 'standalone' ,
'background_color' => '#fff' ,
'theme_color' => '#f02e65' ,
'description' => 'End to end backend server for frontend and mobile apps. 👩💻👨💻' ,
'icons' => [
[
'src' => 'images/favicon.png' ,
'sizes' => '256x256' ,
'type' => 'image/png' ,
2019-10-25 06:53:37 +13:00
],
2020-06-30 09:43:34 +12:00
],
]);
}, [ 'response' ]);
2019-10-25 06:53:37 +13:00
2020-06-29 05:31:21 +12:00
App :: get ( '/robots.txt' )
2019-10-25 06:53:37 +13:00
-> desc ( 'Robots.txt File' )
-> label ( 'scope' , 'public' )
-> label ( 'docs' , false )
2020-06-30 09:43:34 +12:00
-> action ( function ( $response ) {
$template = new View ( __DIR__ . '/views/general/robots.phtml' );
$response -> text ( $template -> render ( false ));
}, [ 'response' ]);
2019-10-25 06:53:37 +13:00
2020-06-29 05:31:21 +12:00
App :: get ( '/humans.txt' )
2019-10-25 06:53:37 +13:00
-> desc ( 'Humans.txt File' )
-> label ( 'scope' , 'public' )
-> label ( 'docs' , false )
2020-06-30 09:43:34 +12:00
-> action ( function ( $response ) {
$template = new View ( __DIR__ . '/views/general/humans.phtml' );
$response -> text ( $template -> render ( false ));
}, [ 'response' ]);
2019-10-25 06:53:37 +13:00
2020-06-29 05:31:21 +12:00
App :: get ( '/.well-known/acme-challenge' )
2020-02-19 11:13:18 +13:00
-> desc ( 'SSL Verification' )
-> label ( 'scope' , 'public' )
-> label ( 'docs' , false )
2020-06-30 09:43:34 +12:00
-> action ( function ( $request , $response ) {
$base = \realpath ( APP_STORAGE_CERTIFICATES );
$path = \str_replace ( '/.well-known/acme-challenge/' , '' , $request -> getParam ( 'q' ));
$absolute = \realpath ( $base . '/.well-known/acme-challenge/' . $path );
2020-02-23 21:55:57 +13:00
2020-06-30 09:43:34 +12:00
if ( ! $base ) {
throw new Exception ( 'Storage error' , 500 );
}
2020-02-19 11:13:18 +13:00
2020-06-30 09:43:34 +12:00
if ( ! $absolute ) {
throw new Exception ( 'Unknown path' , 404 );
}
2020-02-23 21:55:57 +13:00
2020-06-30 09:43:34 +12:00
if ( ! \substr ( $absolute , 0 , \strlen ( $base )) === $base ) {
throw new Exception ( 'Invalid path' , 401 );
}
2020-02-24 06:45:51 +13:00
2020-06-30 09:43:34 +12:00
if ( ! \file_exists ( $absolute )) {
throw new Exception ( 'Unknown path' , 404 );
}
2020-02-23 21:55:57 +13:00
2020-06-30 09:43:34 +12:00
$content = @ \file_get_contents ( $absolute );
2020-02-19 11:13:18 +13:00
2020-06-30 09:43:34 +12:00
if ( ! $content ) {
throw new Exception ( 'Failed to get contents' , 500 );
2020-02-19 11:13:18 +13:00
}
2020-06-30 09:43:34 +12:00
$response -> text ( $content );
}, [ 'request' , 'response' ]);
2020-02-19 11:13:18 +13:00
2020-07-29 19:29:34 +12:00
include_once __DIR__ . '/shared/api.php' ;
include_once __DIR__ . '/shared/web.php' ;
2020-06-26 07:53:36 +12:00
2020-06-26 18:14:54 +12:00
foreach ( Config :: getParam ( 'services' , []) as $service ) {
include_once $service [ 'controller' ];
2020-07-01 17:45:47 +12:00
}