1
0
Fork 0
mirror of synced 2024-06-02 10:54:44 +12:00
appwrite/app/controllers/general.php

529 lines
19 KiB
PHP
Raw Normal View History

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;
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;
use Utopia\Domains\Domain;
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;
use Appwrite\Utopia\Response\Filter;
use Appwrite\Utopia\Response\Filter\V06;
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
function mapResponseFormatToClass(string $responseFormat): Filter {
switch($responseFormat) {
2020-12-30 08:08:48 +13:00
case preg_match($responseFormat, "/0\.[0-6]\.\d?/"):
return new V06();
default:
return null;
}
}
2020-12-07 11:14:57 +13:00
App::init(function ($utopia, $request, $response, $console, $project, $user, $locale, $events, $audits, $usage, $deletes, $clients) {
/** @var Utopia\Swoole\Request $request */
2020-07-03 09:48:02 +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 */
/** @var Appwrite\Database\Document $user */
/** @var Utopia\Locale\Locale $locale */
2020-12-07 11:14:57 +13:00
/** @var Appwrite\Event\Event $events */
2020-07-06 02:19:59 +12:00
/** @var Appwrite\Event\Event $audits */
2020-06-30 23:09:28 +12:00
/** @var Appwrite\Event\Event $usage */
2020-10-31 08:53:27 +13:00
/** @var Appwrite\Event\Event $deletes */
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 10:22:22 +12:00
$localeParam = (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', ''));
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-10-28 08:46:15 +13: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());
$endDomain = new Domain((string)$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',
($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
/*
* Response format
*/
$responseFormatEnvVar = App::getEnv('_APP_SYSTEM_RESPONSE_FORMAT', '');
$responseFormatHeader = $request->getHeader('x-appwrite-response-format', '');
$responseFormat = empty($responseFormatHeader) ? $responseFormatEnvVar : $responseFormatHeader;
if (empty($responseFormat) || ($filter = mapResponseFormatToClass($responseFormat)) == null) {
throw new Exception('No filter available for response format : '.$responseFormat, 404);
} else {
Response::setFilter($filter);
}
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
}
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')
->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
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])
&& $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
}
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([
'$id' => '',
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-10-30 11:44:01 +13:00
if ($user->getId()) {
Authorization::setRole('user:'.$user->getId());
}
2020-10-31 08:53:27 +13:00
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
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
2020-12-07 11:14:57 +13:00
$events
2020-02-17 20:16:11 +13:00
->setParam('projectId', $project->getId())
2020-11-19 11:08:01 +13:00
->setParam('userId', $user->getId())
2020-10-31 08:53:27 +13:00
->setParam('event', $route->getLabel('event', ''))
2019-10-25 06:53:37 +13:00
->setParam('payload', [])
2020-12-08 07:33:22 +13:00
->setParam('functionId', null)
->setParam('executionId', null)
->setParam('trigger', 'event')
2019-10-25 06:53:37 +13:00
;
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-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-10-31 08:53:27 +13:00
$deletes
->setParam('projectId', $project->getId())
;
2019-05-09 18:54:39 +12:00
2020-12-07 11:14:57 +13:00
}, ['utopia', 'request', 'response', 'console', 'project', 'user', 'locale', 'events', 'audits', 'usage', 'deletes', 'clients']);
2019-05-09 18:54:39 +12:00
2020-12-07 11:14:57 +13:00
App::shutdown(function ($utopia, $request, $response, $project, $events, $audits, $usage, $deletes, $mode) {
2020-07-05 06:21:16 +12:00
/** @var Utopia\App $utopia */
/** @var Utopia\Swoole\Request $request */
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2020-07-05 06:21:16 +12:00
/** @var Appwrite\Database\Document $project */
2020-12-07 11:14:57 +13:00
/** @var Appwrite\Event\Event $events */
2020-07-06 02:19:59 +12:00
/** @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-12-07 11:14:57 +13:00
if (!empty($events->getParam('event'))) {
if(empty($events->getParam('payload'))) {
$events->setParam('payload', $response->getPayload());
2020-10-31 08:53:27 +13:00
}
2020-12-08 07:16:23 +13:00
$webhooks = clone $events;
$functions = clone $events;
$webhooks
->setQueue('v1-webhooks')
->setClass('WebhooksV1')
->trigger();
2020-12-08 07:16:23 +13:00
$functions
->setQueue('v1-functions')
->setClass('FunctionsV1')
->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
}
if (!empty($deletes->getParam('type')) && !empty($deletes->getParam('document'))) {
$deletes->trigger();
}
$route = $utopia->match($request);
2020-06-08 04:33:51 +12:00
2020-10-28 08:46:15 +13:00
if ($project->getId()
2020-11-19 11:08:01 +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
2020-05-16 05:58:56 +12:00
$usage
2020-07-20 18:43:25 +12:00
->setParam('networkRequestSize', $request->getSize() + $usage->getParam('storage'))
->setParam('networkResponseSize', $response->getSize())
->trigger()
;
}
2020-12-07 11:14:57 +13:00
}, ['utopia', 'request', 'response', 'project', 'events', 'audits', 'usage', 'deletes', 'mode']);
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
App::options(function ($request, $response) {
/** @var Utopia\Swoole\Request $request */
2020-07-04 03:14:51 +12:00
/** @var Appwrite\Utopia\Response $response */
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')
->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 */
/** @var Utopia\Swoole\Request $request */
2020-09-11 02:40:14 +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
2020-10-30 11:04:53 +13:00
$route = $utopia->match($request);
$template = ($route) ? $route->getLabel('error', null) : null;
2020-10-28 08:46:15 +13:00
if (php_sapi_name() === 'cli') {
2020-10-30 11:04:53 +13:00
Console::error('[Error] Method: '.$route->getMethod());
Console::error('[Error] URL: '.$route->getURL());
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
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
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-10-30 02:50:49 +13: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-10-30 10:08:20 +13: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-10-30 10:08:20 +13: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);
$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-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'];
2020-07-01 17:45:47 +12:00
}