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-08-15 23:39:44 +12:00
use Utopia\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 ;
2021-01-10 11:29:49 +13:00
use Appwrite\Utopia\Response\Filters\V06 ;
2021-05-15 03:15:29 +12:00
use Appwrite\Utopia\Response\Filters\V07 ;
2021-07-02 01:35:36 +12:00
use Appwrite\Utopia\Response\Filters\V08 ;
2020-10-30 11:04:53 +13:00
use Utopia\CLI\Console ;
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
2021-05-11 22:47:02 +12:00
App :: init ( function ( $utopia , $request , $response , $console , $project , $consoleDB , $user , $locale , $clients ) {
2021-09-07 00:06:33 +12:00
/** @var Utopia\App $utopia */
2020-08-15 23:39:44 +12:00
/** @var Utopia\Swoole\Request $request */
2020-08-15 09:56:33 +12:00
/** @var Appwrite\Utopia\Response $response */
2020-06-30 23:09:28 +12:00
/** @var Appwrite\Database\Document $console */
/** @var Appwrite\Database\Document $project */
2021-09-07 00:06:33 +12:00
/** @var Appwrite\Database\Database $consoleDB */
2020-06-30 23:09:28 +12:00
/** @var Appwrite\Database\Document $user */
/** @var Utopia\Locale\Locale $locale */
/** @var array $clients */
2021-08-18 22:20:49 +12:00
2021-05-11 22:47:02 +12:00
$domain = $request -> getHostname ();
2021-05-12 17:19:48 +12:00
$domains = Config :: getParam ( 'domains' , []);
if ( ! array_key_exists ( $domain , $domains )) {
2021-05-11 22:47:02 +12:00
$domain = new Domain ( ! empty ( $domain ) ? $domain : '' );
2021-05-11 23:15:26 +12:00
if ( empty ( $domain -> get ()) || ! $domain -> isKnown () || $domain -> isTest ()) {
2021-05-12 17:19:48 +12:00
$domains [ $domain -> get ()] = false ;
2021-05-12 17:17:34 +12:00
Console :: warning ( $domain -> get () . ' is not a publicly accessible domain. Skipping SSL certificate generation.' );
2021-09-07 03:26:30 +12:00
} elseif ( str_starts_with ( $request -> getURI (), '/.well-known/acme-challenge' )) {
2021-09-07 00:06:33 +12:00
Console :: warning ( 'Skipping SSL certificates generation on ACME challenge.' );
2021-05-11 22:47:02 +12:00
} else {
2021-05-11 23:36:27 +12:00
Authorization :: disable ();
2021-05-11 22:47:02 +12:00
$dbDomain = $consoleDB -> getCollectionFirst ([
'limit' => 1 ,
'offset' => 0 ,
'filters' => [
'$collection=' . Database :: SYSTEM_COLLECTION_CERTIFICATES ,
'domain=' . $domain -> get (),
],
]);
if ( empty ( $dbDomain )) {
$dbDomain = [
'$collection' => Database :: SYSTEM_COLLECTION_CERTIFICATES ,
'$permissions' => [
'read' => [],
'write' => [],
],
'domain' => $domain -> get (),
];
$dbDomain = $consoleDB -> createDocument ( $dbDomain );
2021-05-11 23:21:55 +12:00
Authorization :: enable ();
2021-05-11 22:47:02 +12:00
2021-05-19 04:24:00 +12:00
Console :: info ( 'Issuing a TLS certificate for the master domain (' . $domain -> get () . ') in a few seconds...' ); // TODO move this to installation script
2021-05-11 22:47:02 +12:00
2021-05-19 01:10:09 +12:00
Resque :: enqueue ( 'v1-certificates' , 'CertificatesV1' , [
2021-05-12 17:19:48 +12:00
'document' => $dbDomain ,
2021-05-11 22:47:02 +12:00
'domain' => $domain -> get (),
'validateTarget' => false ,
'validateCNAME' => false ,
]);
}
2021-05-12 17:19:48 +12:00
$domains [ $domain -> get ()] = true ;
2021-05-11 22:47:02 +12:00
}
2021-05-12 17:19:48 +12:00
Config :: setParam ( 'domains' , $domains );
2021-05-11 22:47:02 +12:00
}
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 );
2021-04-16 19:22:17 +12:00
if ( ! empty ( $route -> getLabel ( 'sdk.auth' , [])) && 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-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 ))
2021-01-18 19:58:48 +13:00
? $origin : 'localhost' ) . ( ! empty ( $port ) ? ':' . $port : '' );
2021-08-18 22:20:49 +12:00
2021-01-18 19:58:48 +13:00
$refDomain = ( ! $route -> getLabel ( 'origin' , false )) // This route is publicly accessible
? $refDomain
: ( ! empty ( $protocol ) ? $protocol : $request -> getProtocol ()) . '://' . $origin . ( ! 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-10-27 13:08:29 +13:00
$endDomain = new Domain (( string ) $origin );
2020-03-18 00:36:13 +13:00
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 () !== '' );
2021-08-18 22:20:49 +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-12-30 08:07:33 +13:00
/*
* Response format
*/
2021-01-01 08:56:39 +13:00
$responseFormat = $request -> getHeader ( 'x-appwrite-response-format' , App :: getEnv ( '_APP_SYSTEM_RESPONSE_FORMAT' , '' ));
2021-01-06 02:46:06 +13:00
if ( $responseFormat ) {
2021-01-03 04:35:21 +13:00
switch ( $responseFormat ) {
2021-01-03 05:53:31 +13:00
case version_compare ( $responseFormat , '0.6.2' , '<=' ) :
2021-01-03 04:35:21 +13:00
Response :: setFilter ( new V06 ());
break ;
2021-05-15 03:15:29 +12:00
case version_compare ( $responseFormat , '0.7.2' , '<=' ) :
Response :: setFilter ( new V07 ());
break ;
2021-07-02 01:35:36 +12:00
case version_compare ( $responseFormat , '0.8.0' , '<=' ) :
Response :: setFilter ( new V08 ());
break ;
2021-01-03 04:35:21 +13:00
default :
2021-02-10 19:07:49 +13:00
Response :: setFilter ( null );
2021-01-03 04:35:21 +13:00
}
2021-01-04 07:07:19 +13:00
} else {
Response :: setFilter ( null );
2020-12-30 08:07:33 +13: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-10-28 08:46:15 +13:00
if ( $request -> getProtocol () !== 'https' ) {
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
2021-01-18 19:49:24 +13:00
}
2020-06-02 07:58:58 +12:00
2019-10-25 06:53:37 +13:00
$response
-> addHeader ( 'Server' , 'Appwrite' )
-> addHeader ( 'X-Content-Type-Options' , 'nosniff' )
-> addHeader ( 'Access-Control-Allow-Methods' , 'GET, POST, PUT, PATCH, DELETE' )
2021-03-05 19:36:41 +13: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-Appwrite-JWT, X-Appwrite-Response-Format, 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
2021-01-06 01:22:20 +13:00
* Skip this check for non - web platforms which are not required to 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
2020-10-28 08:46:15 +13: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-10-28 08:46:15 +13:00
throw new Exception ( $originValidator -> getDescription (), 403 );
2019-10-25 06:53:37 +13:00
}
2021-08-18 22:20:49 +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-12-29 09:31:42 +13:00
2020-12-29 06:03:47 +13:00
$authKey = $request -> getHeader ( 'x-appwrite-key' , '' );
2020-12-29 09:31:42 +13:00
2020-12-29 06:03:47 +13:00
if ( ! empty ( $authKey )) { // API Key authentication
// Check if given key match project API keys
$key = $project -> search ( 'secret' , $authKey , $project -> getAttribute ( 'keys' , []));
2021-08-18 22:20:49 +12:00
2020-12-29 06:03:47 +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
*/
2020-12-29 23:45:44 +13:00
if ( $key && $user -> isEmpty ()) {
2020-12-29 06:03:47 +13:00
$user = new Document ([
'$id' => '' ,
'status' => Auth :: USER_STATUS_ACTIVATED ,
'email' => 'app.' . $project -> getId () . '@service.' . $request -> getHostname (),
'password' => '' ,
'name' => $project -> getAttribute ( 'name' , 'Untitled' ),
]);
$role = Auth :: USER_ROLE_APP ;
2021-07-01 02:47:55 +12:00
$scopes = \array_merge ( $roles [ $role ][ 'scopes' ], $key -> getAttribute ( 'scopes' , []));
2020-12-29 06:03:47 +13:00
2021-07-01 02:04:32 +12:00
Authorization :: setRole ( 'role:' . Auth :: USER_ROLE_APP );
2020-12-29 06:03:47 +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
2021-09-04 02:42:31 +12:00
Authorization :: setRole ( 'role:' . $role );
2021-09-04 02:30:16 +12:00
2021-08-18 22:20:49 +12:00
foreach ( Auth :: getRoles ( $user ) as $authRole ) {
Authorization :: setRole ( $authRole );
2021-06-28 22:18:00 +12:00
}
2019-05-09 18:54:39 +12:00
2021-05-13 02:53:25 +12:00
// TDOO Check if user is root
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 );
}
2021-08-18 22:20:49 +12:00
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
2021-05-11 22:47:02 +12:00
}, [ 'utopia' , 'request' , 'response' , 'console' , 'project' , 'consoleDB' , 'user' , 'locale' , 'clients' ]);
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
App :: options ( function ( $request , $response ) {
2020-08-15 23:39:44 +12:00
/** @var Utopia\Swoole\Request $request */
2020-08-15 09:56:33 +12:00
/** @var Appwrite\Utopia\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' )
2021-03-05 19:36:41 +13: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-Appwrite-JWT, X-Appwrite-Response-Format, 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' )
2021-02-02 19:03:28 +13:00
-> noContent ();
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-15 23:39:44 +12:00
/** @var Utopia\Swoole\Request $request */
2020-08-15 09:56:33 +12:00
/** @var Appwrite\Utopia\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
2021-07-13 04:15:21 +12:00
if ( $error instanceof PDOException ) {
2021-07-13 03:27:26 +12:00
throw $error ;
}
2020-08-10 09:19:30 +12:00
$route = $utopia -> match ( $request );
$template = ( $route ) ? $route -> getLabel ( 'error' , null ) : null ;
2021-01-18 02:50:01 +13:00
if ( php_sapi_name () === 'cli' ) {
2021-03-19 11:08:19 +13:00
Console :: error ( '[Error] Timestamp: ' . date ( 'c' , time ()));
2021-08-18 22:20:49 +12:00
2021-01-18 02:50:01 +13:00
if ( $route ) {
Console :: error ( '[Error] Method: ' . $route -> getMethod ());
2021-08-19 17:05:21 +12:00
Console :: error ( '[Error] URL: ' . $route -> getPath ());
2021-01-18 02:50:01 +13:00
}
2021-08-18 22:20:49 +12:00
2020-10-30 11:04:53 +13:00
Console :: error ( '[Error] Type: ' . get_class ( $error ));
Console :: error ( '[Error] Message: ' . $error -> getMessage ());
Console :: error ( '[Error] File: ' . $error -> getFile ());
Console :: error ( '[Error] Line: ' . $error -> getLine ());
2020-07-07 16:40:18 +12:00
}
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
2021-03-01 10:22:03 +13:00
switch ( $error -> getCode ()) { // Don't show 500 errors!
2019-10-25 06:53:37 +13:00
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
2021-03-01 10:22:03 +13:00
case 501 : // Error allowed publicly
2021-08-31 19:35:51 +12:00
case 503 : // Error allowed publicly
2019-10-25 06:53:37 +13:00
$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
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 ),
2020-12-23 09:33:20 +13:00
$utopia -> isDevelopment () ? Response :: MODEL_ERROR_DEV : Response :: MODEL_ERROR );
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-12-27 01:19:46 +13:00
-> inject ( 'response' )
2020-06-30 09:43:34 +12:00
-> action ( function ( $response ) {
2020-08-15 09:56:33 +12:00
/** @var Appwrite\Utopia\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
],
]);
2020-12-27 01:19:46 +13:00
});
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-12-27 01:19:46 +13:00
-> inject ( 'response' )
2020-06-30 09:43:34 +12:00
-> action ( function ( $response ) {
2020-08-12 02:28:24 +12:00
$template = new View ( __DIR__ . '/../views/general/robots.phtml' );
2020-06-30 09:43:34 +12:00
$response -> text ( $template -> render ( false ));
2020-12-27 01:19:46 +13:00
});
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-12-27 01:19:46 +13:00
-> inject ( 'response' )
2020-06-30 09:43:34 +12:00
-> action ( function ( $response ) {
2020-08-12 02:28:24 +12:00
$template = new View ( __DIR__ . '/../views/general/humans.phtml' );
2020-06-30 09:43:34 +12:00
$response -> text ( $template -> render ( false ));
2020-12-27 01:19:46 +13:00
});
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-12-27 01:19:46 +13:00
-> inject ( 'request' )
-> inject ( 'response' )
2020-06-30 09:43:34 +12:00
-> action ( function ( $request , $response ) {
$base = \realpath ( APP_STORAGE_CERTIFICATES );
2021-02-03 03:48:07 +13:00
$path = \str_replace ( '/.well-known/acme-challenge/' , '' , $request -> getURI ());
2020-06-30 09:43:34 +12:00
$absolute = \realpath ( $base . '/.well-known/acme-challenge/' . $path );
2020-02-23 21:55:57 +13:00
2020-10-28 08:46:15 +13:00
if ( ! $base ) {
2020-06-30 09:43:34 +12:00
throw new Exception ( 'Storage error' , 500 );
}
2020-02-19 11:13:18 +13:00
2020-10-28 08:46:15 +13:00
if ( ! $absolute ) {
2020-06-30 09:43:34 +12:00
throw new Exception ( 'Unknown path' , 404 );
}
2020-02-23 21:55:57 +13:00
2020-10-28 08:46:15 +13:00
if ( ! \substr ( $absolute , 0 , \strlen ( $base )) === $base ) {
2020-06-30 09:43:34 +12:00
throw new Exception ( 'Invalid path' , 401 );
}
2020-02-24 06:45:51 +13:00
2020-10-28 08:46:15 +13:00
if ( ! \file_exists ( $absolute )) {
2020-06-30 09:43:34 +12:00
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-10-28 08:46:15 +13:00
if ( ! $content ) {
2020-06-30 09:43:34 +12:00
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 );
2020-12-27 01:19:46 +13:00
});
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-10-28 08:46:15 +13:00
foreach ( Config :: getParam ( 'services' , []) as $service ) {
2020-06-26 18:14:54 +12:00
include_once $service [ 'controller' ];
2021-05-12 17:17:34 +12:00
}