1
0
Fork 0
mirror of synced 2024-06-03 03:14:50 +12:00

Removed global vars

This commit is contained in:
Eldad Fux 2020-06-30 00:43:34 +03:00
parent 8596937210
commit 3e808d3bf4
18 changed files with 2444 additions and 2435 deletions

View file

@ -2,7 +2,7 @@
require_once __DIR__.'/init.php';
global $request, $response, $register, $project;
global $register, $project;
use Utopia\App;
use Utopia\Request;
@ -18,146 +18,132 @@ use Appwrite\Database\Document;
use Appwrite\Database\Validator\Authorization;
use Appwrite\Database\Adapter\MySQL as MySQLAdapter;
use Appwrite\Database\Adapter\Redis as RedisAdapter;
use Appwrite\Event\Event;
use Appwrite\Network\Validator\Origin;
$request = new Request();
$response = new Response();
// Config::setParam('domain', $request->getServer('HTTP_HOST', ''));
// Config::setParam('domainVerification', false);
// Config::setParam('version', App::getEnv('_APP_VERSION', 'UNKNOWN'));
// Config::setParam('protocol', $request->getServer('HTTP_X_FORWARDED_PROTO', $request->getServer('REQUEST_SCHEME', 'https')));
// Config::setParam('port', (string) \parse_url(Config::getParam('protocol').'://'.$request->getServer('HTTP_HOST', ''), PHP_URL_PORT));
// Config::setParam('hostname', \parse_url(Config::getParam('protocol').'://'.$request->getServer('HTTP_HOST', null), PHP_URL_HOST));
$locale = $request->getParam('locale', $request->getHeader('X-Appwrite-Locale', ''));
// \define('COOKIE_DOMAIN',
// (
// $request->getServer('HTTP_HOST', null) === 'localhost' ||
// $request->getServer('HTTP_HOST', null) === 'localhost:'.Config::getParam('port') ||
// (\filter_var(Config::getParam('hostname'), FILTER_VALIDATE_IP) !== false)
// )
// ? null
// : '.'.Config::getParam('hostname')
// );
// \define('COOKIE_SAMESITE', Response::COOKIE_SAMESITE_NONE);
if (\in_array($locale, Config::getParam('locales'))) {
Locale::setDefault($locale);
}
// Authorization::disable();
Config::setParam('env', App::getMode());
Config::setParam('domain', $request->getServer('HTTP_HOST', ''));
Config::setParam('domainVerification', false);
Config::setParam('version', App::getEnv('_APP_VERSION', 'UNKNOWN'));
Config::setParam('protocol', $request->getServer('HTTP_X_FORWARDED_PROTO', $request->getServer('REQUEST_SCHEME', 'https')));
Config::setParam('port', (string) \parse_url(Config::getParam('protocol').'://'.$request->getServer('HTTP_HOST', ''), PHP_URL_PORT));
Config::setParam('hostname', \parse_url(Config::getParam('protocol').'://'.$request->getServer('HTTP_HOST', null), PHP_URL_HOST));
// $project = $consoleDB->getDocument($request->getParam('project', $request->getHeader('X-Appwrite-Project', '')));
\define('COOKIE_DOMAIN',
(
$request->getServer('HTTP_HOST', null) === 'localhost' ||
$request->getServer('HTTP_HOST', null) === 'localhost:'.Config::getParam('port') ||
(\filter_var(Config::getParam('hostname'), FILTER_VALIDATE_IP) !== false)
)
? null
: '.'.Config::getParam('hostname')
);
\define('COOKIE_SAMESITE', Response::COOKIE_SAMESITE_NONE);
// Authorization::enable();
Authorization::disable();
// $console = $consoleDB->getDocument('console');
$project = $consoleDB->getDocument($request->getParam('project', $request->getHeader('X-Appwrite-Project', '')));
// $mode = $request->getParam('mode', $request->getHeader('X-Appwrite-Mode', 'default'));
Authorization::enable();
// Auth::setCookieName('a_session_'.$project->getId());
$console = $consoleDB->getDocument('console');
// if (APP_MODE_ADMIN === $mode) {
// Auth::setCookieName('a_session_'.$console->getId());
// }
$mode = $request->getParam('mode', $request->getHeader('X-Appwrite-Mode', 'default'));
// $session = Auth::decodeSession(
// $request->getCookie(Auth::$cookieName, // Get sessions
// $request->getCookie(Auth::$cookieName.'_legacy', // Get fallback session from old clients (no SameSite support)
// $request->getHeader('X-Appwrite-Key', '')))); // Get API Key
Auth::setCookieName('a_session_'.$project->getId());
// // Get fallback session from clients who block 3rd-party cookies
// $response->addHeader('X-Debug-Fallback', 'false');
if (APP_MODE_ADMIN === $mode) {
Auth::setCookieName('a_session_'.$console->getId());
}
// if(empty($session['id']) && empty($session['secret'])) {
// $response->addHeader('X-Debug-Fallback', 'true');
// $fallback = $request->getHeader('X-Fallback-Cookies', '');
// $fallback = \json_decode($fallback, true);
// $session = Auth::decodeSession(((isset($fallback[Auth::$cookieName])) ? $fallback[Auth::$cookieName] : ''));
// }
$session = Auth::decodeSession(
$request->getCookie(Auth::$cookieName, // Get sessions
$request->getCookie(Auth::$cookieName.'_legacy', // Get fallback session from old clients (no SameSite support)
$request->getHeader('X-Appwrite-Key', '')))); // Get API Key
// Auth::$unique = $session['id'];
// Auth::$secret = $session['secret'];
// Get fallback session from clients who block 3rd-party cookies
$response->addHeader('X-Debug-Fallback', 'false');
// $projectDB = new Database();
// $projectDB->setAdapter(new RedisAdapter(new MySQLAdapter($register), $register));
// $projectDB->setNamespace('app_'.$project->getId());
// $projectDB->setMocks(Config::getParam('collections', []));
if(empty($session['id']) && empty($session['secret'])) {
$response->addHeader('X-Debug-Fallback', 'true');
$fallback = $request->getHeader('X-Fallback-Cookies', '');
$fallback = \json_decode($fallback, true);
$session = Auth::decodeSession(((isset($fallback[Auth::$cookieName])) ? $fallback[Auth::$cookieName] : ''));
}
// if (APP_MODE_ADMIN !== $mode) {
// $user = $projectDB->getDocument(Auth::$unique);
// }
// else {
// $user = $consoleDB->getDocument(Auth::$unique);
Auth::$unique = $session['id'];
Auth::$secret = $session['secret'];
// $user
// ->setAttribute('$id', 'admin-'.$user->getAttribute('$id'))
// ;
// }
$projectDB = new Database();
$projectDB->setAdapter(new RedisAdapter(new MySQLAdapter($register), $register));
$projectDB->setNamespace('app_'.$project->getId());
$projectDB->setMocks(Config::getParam('collections', []));
// if (empty($user->getId()) // Check a document has been found in the DB
// || Database::SYSTEM_COLLECTION_USERS !== $user->getCollection() // Validate returned document is really a user document
// || !Auth::tokenVerify($user->getAttribute('tokens', []), Auth::TOKEN_TYPE_LOGIN, Auth::$secret)) { // Validate user has valid login token
// $user = new Document(['$id' => '', '$collection' => Database::SYSTEM_COLLECTION_USERS]);
// }
if (APP_MODE_ADMIN !== $mode) {
$user = $projectDB->getDocument(Auth::$unique);
}
else {
$user = $consoleDB->getDocument(Auth::$unique);
// if (APP_MODE_ADMIN === $mode) {
// if (!empty($user->search('teamId', $project->getAttribute('teamId'), $user->getAttribute('memberships')))) {
// Authorization::disable();
// } else {
// $user = new Document(['$id' => '', '$collection' => Database::SYSTEM_COLLECTION_USERS]);
// }
// }
$user
->setAttribute('$id', 'admin-'.$user->getAttribute('$id'))
;
}
if (empty($user->getId()) // Check a document has been found in the DB
|| Database::SYSTEM_COLLECTION_USERS !== $user->getCollection() // Validate returned document is really a user document
|| !Auth::tokenVerify($user->getAttribute('tokens', []), Auth::TOKEN_TYPE_LOGIN, Auth::$secret)) { // Validate user has valid login token
$user = new Document(['$id' => '', '$collection' => Database::SYSTEM_COLLECTION_USERS]);
}
if (APP_MODE_ADMIN === $mode) {
if (!empty($user->search('teamId', $project->getAttribute('teamId'), $user->getAttribute('memberships')))) {
Authorization::disable();
} else {
$user = new Document(['$id' => '', '$collection' => Database::SYSTEM_COLLECTION_USERS]);
}
}
// Set project mail
$register->get('smtp')
->setFrom(
App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM),
($project->getId() === 'console')
? \urldecode(App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME.' Server'))
: \sprintf(Locale::getText('account.emails.team'), $project->getAttribute('name')
)
);
/*
* Configuration files
*/
$utopia = new App('Asia/Tel_Aviv');
$webhook = new Event('v1-webhooks', 'WebhooksV1');
$audit = new Event('v1-audits', 'AuditsV1');
$usage = new Event('v1-usage', 'UsageV1');
$mail = new Event('v1-mails', 'MailsV1');
$deletes = new Event('v1-deletes', 'DeletesV1');
// // Set project mail
// $register->get('smtp')
// ->setFrom(
// App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM),
// ($project->getId() === 'console')
// ? \urldecode(App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME.' Server'))
// : \sprintf(Locale::getText('account.emails.team'), $project->getAttribute('name')
// )
// );
/**
* Get All verified client URLs for both console and current projects
* + Filter for duplicated entries
*/
$clientsConsole = \array_map(function ($node) {
return $node['hostname'];
}, \array_filter($console->getAttribute('platforms', []), function ($node) {
if (isset($node['type']) && $node['type'] === 'web' && isset($node['hostname']) && !empty($node['hostname'])) {
return true;
}
// $clientsConsole = \array_map(function ($node) {
// return $node['hostname'];
// }, \array_filter($console->getAttribute('platforms', []), function ($node) {
// if (isset($node['type']) && $node['type'] === 'web' && isset($node['hostname']) && !empty($node['hostname'])) {
// return true;
// }
return false;
}));
// return false;
// }));
$clients = \array_unique(\array_merge($clientsConsole, \array_map(function ($node) {
return $node['hostname'];
}, \array_filter($project->getAttribute('platforms', []), function ($node) {
if (isset($node['type']) && $node['type'] === 'web' && isset($node['hostname']) && !empty($node['hostname'])) {
return true;
}
// $clients = \array_unique(\array_merge($clientsConsole, \array_map(function ($node) {
// return $node['hostname'];
// }, \array_filter($project->getAttribute('platforms', []), function ($node) {
// if (isset($node['type']) && $node['type'] === 'web' && isset($node['hostname']) && !empty($node['hostname'])) {
// return true;
// }
return false;
}))));
// return false;
// }))));
App::init(function () use ($utopia, $request, $response, &$user, $project, $console, $webhook, $audit, $usage, $clients) {
App::init(function ($utopia, $request, $response, $user, $project, $console, $webhooks, $audits, $usage, $clients, $locale) {
/** @var $locale Utopia\Locale\Locale */
$localeParam = $request->getParam('locale', $request->getHeader('X-Appwrite-Locale', ''));
if (\in_array($localeParam, Config::getParam('locales'))) {
$locale->setDefault($localeParam);
};
$route = $utopia->match($request);
@ -312,13 +298,13 @@ App::init(function () use ($utopia, $request, $response, &$user, $project, $cons
/*
* Background Jobs
*/
$webhook
$webhooks
->setParam('projectId', $project->getId())
->setParam('event', $route->getLabel('webhook', ''))
->setParam('payload', [])
;
$audit
$audits
->setParam('projectId', $project->getId())
->setParam('userId', $user->getId())
->setParam('event', '')
@ -336,10 +322,9 @@ App::init(function () use ($utopia, $request, $response, &$user, $project, $cons
->setParam('response', 0)
->setParam('storage', 0)
;
});
App::shutdown(function () use ($response, $request, $webhook, $audit, $usage, $deletes, $mode, $project, $utopia) {
}, ['utopia', 'request', 'response', 'user', 'project', 'console', 'webhook', 'audit', 'usage', 'clients', 'locale']);
App::shutdown(function ($utopia, $response, $request, $webhook, $audit, $usage, $deletes, $mode, $project) {
/*
* Trigger events for background workers
*/
@ -366,9 +351,9 @@ App::shutdown(function () use ($response, $request, $webhook, $audit, $usage, $d
->trigger()
;
}
});
}, ['utopia', 'response', 'request', 'webhook', 'audit', 'usage', 'deletes', 'mode', 'project']);
App::options(function () use ($request, $response) {
App::options(function ($request, $response) {
$origin = $request->getServer('HTTP_ORIGIN');
$response
@ -378,9 +363,11 @@ App::options(function () use ($request, $response) {
->addHeader('Access-Control-Allow-Origin', $origin)
->addHeader('Access-Control-Allow-Credentials', 'true')
->send();
});
}, ['request', 'response']);
App::error(function ($error, $utopia, $request, $response, $project) {
/** @var Exception $error */
App::error(function ($error /* @var $error Exception */) use ($request, $response, $utopia, $project) {
$version = Config::getParam('version');
switch ($error->getCode()) {
@ -450,14 +437,15 @@ App::error(function ($error /* @var $error Exception */) use ($request, $respons
$response
->json($output)
;
});
}, ['error', 'utopia', 'request', 'response', 'project']);
App::get('/manifest.json')
->desc('Progressive app manifest file')
->label('scope', 'public')
->label('docs', false)
->action(
function () use ($response) {
->action(function ($response) {
/** @var Utopia\Response $response */
$response->json([
'name' => APP_NAME,
'short_name' => APP_NAME,
@ -475,37 +463,31 @@ App::get('/manifest.json')
],
],
]);
}
);
}, ['response']);
App::get('/robots.txt')
->desc('Robots.txt File')
->label('scope', 'public')
->label('docs', false)
->action(
function () use ($response) {
->action(function ($response) {
$template = new View(__DIR__.'/views/general/robots.phtml');
$response->text($template->render(false));
}
);
}, ['response']);
App::get('/humans.txt')
->desc('Humans.txt File')
->label('scope', 'public')
->label('docs', false)
->action(
function () use ($response) {
->action(function ($response) {
$template = new View(__DIR__.'/views/general/humans.phtml');
$response->text($template->render(false));
}
);
}, ['response']);
App::get('/.well-known/acme-challenge')
->desc('SSL Verification')
->label('scope', 'public')
->label('docs', false)
->action(
function () use ($request, $response) {
->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);
@ -533,8 +515,7 @@ App::get('/.well-known/acme-challenge')
}
$response->text($content);
}
);
}, ['request', 'response']);
include_once __DIR__ . '/controllers/shared/api.php';
include_once __DIR__ . '/controllers/shared/web.php';
@ -543,9 +524,30 @@ foreach(Config::getParam('services', []) as $service) {
include_once $service['controller'];
}
App::setResource('utopia', function() use ($utopia) {return $utopia;});
App::setResource('request', function() use ($request) {return $request;});
App::setResource('response', function() use ($response) {return $response;});
App::setResource('register', function() use ($register) {return $register;});
// Runtime Execution
$utopia->run($request, $response);
App::setResource('register', function() use ($register) { return $register; });
App::setResource('layout', function($locale) {
$layout = new View(__DIR__.'/views/layouts/default.phtml');
$layout->setParam('locale', $locale);
return $layout; }, ['locale']);
App::setResource('locale', function($request) { return new Locale('en'); }, ['request']);
// Queues
App::setResource('webhook', function($register) { return $register->get('queue-webhook'); }, ['register']);
App::setResource('audit', function($register) { return $register->get('queue-audit'); }, ['register']);
App::setResource('usage', function($register) { return $register->get('queue-usage'); }, ['register']);
App::setResource('mail', function($register) { return $register->get('queue-mails'); }, ['register']);
App::setResource('deletes', function($register) { return $register->get('queue-deletes'); }, ['register']);
// Test Mock
App::setResource('clients', function() { return []; });
App::setResource('user', function() { return new Document([]); });
App::setResource('project', function() { return new Document([]); });
App::setResource('console', function() { return new Document([]); });
App::setResource('consoleDB', function() { return new Database(); });
App::setResource('projectDB', function() { return new Database([]); });
App::setResource('mode', function() { return false; });
$app = new App('Asia/Tel_Aviv');
$app->run(new Request(), new Response());

View file

@ -1,8 +1,5 @@
<?php
global $register, $request, $response, $user, $audit,
$webhook, $mail, $project, $projectDB, $clients;
use Utopia\App;
use Utopia\Exception;
use Utopia\Response;
@ -15,7 +12,6 @@ use Utopia\Validator\Host;
use Utopia\Validator\URL;
use Utopia\Audit\Audit;
use Utopia\Audit\Adapters\MySQL as AuditAdapter;
use Utopia\Locale\Locale;
use Appwrite\Auth\Auth;
use Appwrite\Auth\Validator\Password;
use Appwrite\Database\Database;
@ -44,7 +40,7 @@ App::init(function() use (&$oauth2Keys) {
$oauth2Keys[] = 'oauth2'.\ucfirst($key);
$oauth2Keys[] = 'oauth2'.\ucfirst($key).'AccessToken';
}
}, 'account');
}, [], 'account');
App::post('/v1/account')
->desc('Create Account')
@ -59,8 +55,14 @@ App::post('/v1/account')
->param('email', '', function () { return new Email(); }, 'User email.')
->param('password', '', function () { return new Password(); }, 'User password. Must be between 6 to 32 chars.')
->param('name', '', function () { return new Text(100); }, 'User name.', true)
->action(
function ($email, $password, $name) use ($request, $response, $audit, $projectDB, $project, $webhook, $oauth2Keys) {
->action(function ($email, $password, $name, $request, $response, $project, $projectDB, $webhook, $audit) use ($oauth2Keys) {
/** @var Utopia\Request $request */
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $project */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $webhook */
/** @var Appwrite\Event\Event $audit */
if ('console' === $project->getId()) {
$whitlistEmails = $project->getAttribute('authWhitelistEmails');
$whitlistIPs = $project->getAttribute('authWhitelistIPs');
@ -143,8 +145,7 @@ App::post('/v1/account')
],
$oauth2Keys
)), ['roles' => Authorization::getRoles()]));
}
);
}, ['request', 'response', 'project', 'projectDB', 'webhook', 'audit']);
App::post('/v1/account/sessions')
->desc('Create Account Session')
@ -159,8 +160,13 @@ App::post('/v1/account/sessions')
->label('abuse-key', 'url:{url},email:{param-email}')
->param('email', '', function () { return new Email(); }, 'User email.')
->param('password', '', function () { return new Password(); }, 'User password. Must be between 6 to 32 chars.')
->action(
function ($email, $password) use ($response, $request, $projectDB, $audit, $webhook) {
->action(function ($email, $password, $request, $response, $projectDB, $webhook, $audit) {
/** @var Utopia\Request $request */
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $webhook */
/** @var Appwrite\Event\Event $audit */
$protocol = Config::getParam('protocol');
$profile = $projectDB->getCollectionFirst([ // Get user by email address
'limit' => 1,
@ -233,8 +239,7 @@ App::post('/v1/account/sessions')
->setStatusCode(Response::STATUS_CODE_CREATED)
->json($session->getArrayCopy(['$id', 'type', 'expire']))
;
}
);
}, ['request', 'response', 'projectDB', 'webhook', 'audit']);
App::get('/v1/account/sessions/oauth2/:provider')
->desc('Create Account Session with OAuth2')
@ -251,11 +256,14 @@ App::get('/v1/account/sessions/oauth2/:provider')
->label('abuse-limit', 50)
->label('abuse-key', 'ip:{ip}')
->param('provider', '', function () { return new WhiteList(\array_keys(Config::getParam('providers'))); }, 'OAuth2 Provider. Currently, supported providers are: ' . \implode(', ', \array_keys(\array_filter(Config::getParam('providers'), function($node) {return (!$node['mock']);}))).'.')
->param('success', $oauthDefaultSuccess, function () use ($clients) { return new Host($clients); }, 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true)
->param('failure', $oauthDefaultFailure, function () use ($clients) { return new Host($clients); }, 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true)
->param('success', $oauthDefaultSuccess, function ($clients) { return new Host($clients); }, 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients'])
->param('failure', $oauthDefaultFailure, function ($clients) { return new Host($clients); }, 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients'])
->param('scopes', [], function () { return new ArrayList(new Text(128)); }, 'A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes.', true)
->action(
function ($provider, $success, $failure, $scopes) use ($response, $request, $project) {
->action(function ($provider, $success, $failure, $scopes, $request, $response, $project) {
/** @var Utopia\Request $request */
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $project */
$protocol = Config::getParam('protocol');
$callback = $protocol.'://'.$request->getServer('HTTP_HOST').'/v1/account/sessions/oauth2/callback/'.$provider.'/'.$project->getId();
$appId = $project->getAttribute('usersOauth2'.\ucfirst($provider).'Appid', '');
@ -284,8 +292,7 @@ App::get('/v1/account/sessions/oauth2/:provider')
->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
->addHeader('Pragma', 'no-cache')
->redirect($oauth2->getLoginURL());
}
);
}, ['request', 'response', 'project']);
App::get('/v1/account/sessions/oauth2/callback/:provider/:projectId')
->desc('OAuth2 Callback')
@ -297,8 +304,7 @@ App::get('/v1/account/sessions/oauth2/callback/:provider/:projectId')
->param('provider', '', function () { return new WhiteList(\array_keys(Config::getParam('providers'))); }, 'OAuth2 provider.')
->param('code', '', function () { return new Text(1024); }, 'OAuth2 code.')
->param('state', '', function () { return new Text(2048); }, 'Login state params.', true)
->action(
function ($projectId, $provider, $code, $state) use ($response) {
->action(function ($projectId, $provider, $code, $state, $response) {
$domain = Config::getParam('domain');
$protocol = Config::getParam('protocol');
@ -307,8 +313,7 @@ App::get('/v1/account/sessions/oauth2/callback/:provider/:projectId')
->addHeader('Pragma', 'no-cache')
->redirect($protocol.'://'.$domain.'/v1/account/sessions/oauth2/'.$provider.'/redirect?'
.\http_build_query(['project' => $projectId, 'code' => $code, 'state' => $state]));
}
);
}, ['response']);
App::post('/v1/account/sessions/oauth2/callback/:provider/:projectId')
->desc('OAuth2 Callback')
@ -321,8 +326,7 @@ App::post('/v1/account/sessions/oauth2/callback/:provider/:projectId')
->param('provider', '', function () { return new WhiteList(\array_keys(Config::getParam('providers'))); }, 'OAuth2 provider.')
->param('code', '', function () { return new Text(1024); }, 'OAuth2 code.')
->param('state', '', function () { return new Text(2048); }, 'Login state params.', true)
->action(
function ($projectId, $provider, $code, $state) use ($response) {
->action(function ($projectId, $provider, $code, $state, $response) {
$domain = Config::getParam('domain');
$protocol = Config::getParam('protocol');
@ -331,8 +335,7 @@ App::post('/v1/account/sessions/oauth2/callback/:provider/:projectId')
->addHeader('Pragma', 'no-cache')
->redirect($protocol.'://'.$domain.'/v1/account/sessions/oauth2/'.$provider.'/redirect?'
.\http_build_query(['project' => $projectId, 'code' => $code, 'state' => $state]));
}
);
}, ['response']);
App::get('/v1/account/sessions/oauth2/:provider/redirect')
->desc('OAuth2 Redirect')
@ -346,8 +349,14 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
->param('provider', '', function () { return new WhiteList(\array_keys(Config::getParam('providers'))); }, 'OAuth2 provider.')
->param('code', '', function () { return new Text(1024); }, 'OAuth2 code.')
->param('state', '', function () { return new Text(2048); }, 'OAuth2 state params.', true)
->action(
function ($provider, $code, $state) use ($response, $request, $user, $projectDB, $project, $audit, $oauthDefaultSuccess) {
->action(function ($provider, $code, $state, $request, $response, $project, $user, $projectDB, $audit) use ($oauthDefaultSuccess) {
/** @var Utopia\Request $request */
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $project */
/** @var Appwrite\Database\Document $user */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $audit */
$protocol = Config::getParam('protocol');
$callback = $protocol.'://'.$request->getServer('HTTP_HOST').'/v1/account/sessions/oauth2/callback/'.$provider.'/'.$project->getId();
$defaultState = ['success' => $project->getAttribute('url', ''), 'failure' => ''];
@ -525,8 +534,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $secret), $expiry, '/', COOKIE_DOMAIN, ('https' == $protocol), true, COOKIE_SAMESITE)
->redirect($state['success'])
;
}
);
}, ['request', 'response', 'project', 'user', 'projectDB', 'audit']);
App::get('/v1/account')
->desc('Get Account')
@ -537,9 +545,10 @@ App::get('/v1/account')
->label('sdk.method', 'get')
->label('sdk.description', '/docs/references/account/get.md')
->label('sdk.response', ['200' => 'user'])
->inject('response')
->action(
function ($response) use (&$user, $oauth2Keys) {
->action(function ($response, $user) use ($oauth2Keys) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $user */
$response->json(\array_merge($user->getArrayCopy(\array_merge(
[
'$id',
@ -550,8 +559,7 @@ App::get('/v1/account')
],
$oauth2Keys
)), ['roles' => Authorization::getRoles()]));
}
);
}, ['response', ['user']]);
App::get('/v1/account/prefs')
->desc('Get Account Preferences')
@ -561,8 +569,10 @@ App::get('/v1/account/prefs')
->label('sdk.namespace', 'account')
->label('sdk.method', 'getPrefs')
->label('sdk.description', '/docs/references/account/get-prefs.md')
->action(
function () use ($response, $user) {
->action(function ($response, $user) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $user */
$prefs = $user->getAttribute('prefs', '{}');
try {
@ -573,8 +583,7 @@ App::get('/v1/account/prefs')
}
$response->json($prefs);
}
);
}, ['response', 'user']);
App::get('/v1/account/sessions')
->desc('Get Account Sessions')
@ -584,14 +593,17 @@ App::get('/v1/account/sessions')
->label('sdk.namespace', 'account')
->label('sdk.method', 'getSessions')
->label('sdk.description', '/docs/references/account/get-sessions.md')
->action(
function () use ($response, $user) {
->action(function ($response, $user, $locale) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $user */
/** @var Utopia\Locale\Locale $locale */
$tokens = $user->getAttribute('tokens', []);
$reader = new Reader(__DIR__.'/../../db/DBIP/dbip-country-lite-2020-01.mmdb');
$sessions = [];
$current = Auth::tokenVerify($tokens, Auth::TOKEN_TYPE_LOGIN, Auth::$secret);
$index = 0;
$countries = Locale::getText('countries');
$countries = $locale->getText('countries');
foreach ($tokens as $token) { /* @var $token Document */
if (Auth::TOKEN_TYPE_LOGIN != $token->getAttribute('type')) {
@ -622,18 +634,17 @@ App::get('/v1/account/sessions')
try {
$record = $reader->country($token->getAttribute('ip', ''));
$sessions[$index]['geo']['isoCode'] = \strtolower($record->country->isoCode);
$sessions[$index]['geo']['country'] = (isset($countries[$record->country->isoCode])) ? $countries[$record->country->isoCode] : Locale::getText('locale.country.unknown');
$sessions[$index]['geo']['country'] = (isset($countries[$record->country->isoCode])) ? $countries[$record->country->isoCode] : $locale->getText('locale.country.unknown');
} catch (\Exception $e) {
$sessions[$index]['geo']['isoCode'] = '--';
$sessions[$index]['geo']['country'] = Locale::getText('locale.country.unknown');
$sessions[$index]['geo']['country'] = $locale->getText('locale.country.unknown');
}
++$index;
}
$response->json($sessions);
}
);
}, ['response', 'user', 'locale']);
App::get('/v1/account/logs')
->desc('Get Account Logs')
@ -643,13 +654,17 @@ App::get('/v1/account/logs')
->label('sdk.namespace', 'account')
->label('sdk.method', 'getLogs')
->label('sdk.description', '/docs/references/account/get-logs.md')
->action(
function () use ($response, $register, $project, $user) {
->action(function ($response, $register, $project, $user) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $project */
/** @var Appwrite\Database\Document $user */
/** @var Utopia\Locale\Locale $locale */
$adapter = new AuditAdapter($register->get('db'));
$adapter->setNamespace('app_'.$project->getId());
$audit = new Audit($adapter);
$countries = Locale::getText('countries');
$countries = $locale->getText('countries');
$logs = $audit->getLogsByUserAndActions($user->getId(), [
'account.create',
@ -697,16 +712,15 @@ App::get('/v1/account/logs')
$record = $reader->country($log['ip']);
$output[$i]['geo']['isoCode'] = \strtolower($record->country->isoCode);
$output[$i]['geo']['country'] = $record->country->name;
$output[$i]['geo']['country'] = (isset($countries[$record->country->isoCode])) ? $countries[$record->country->isoCode] : Locale::getText('locale.country.unknown');
$output[$i]['geo']['country'] = (isset($countries[$record->country->isoCode])) ? $countries[$record->country->isoCode] : $locale->getText('locale.country.unknown');
} catch (\Exception $e) {
$output[$i]['geo']['isoCode'] = '--';
$output[$i]['geo']['country'] = Locale::getText('locale.country.unknown');
$output[$i]['geo']['country'] = $locale->getText('locale.country.unknown');
}
}
$response->json($output);
}
);
}, ['response', 'register', 'project', 'user']);
App::patch('/v1/account/name')
->desc('Update Account Name')
@ -718,8 +732,12 @@ App::patch('/v1/account/name')
->label('sdk.method', 'updateName')
->label('sdk.description', '/docs/references/account/update-name.md')
->param('name', '', function () { return new Text(100); }, 'User name.')
->action(
function ($name) use ($response, $user, $projectDB, $audit, $oauth2Keys) {
->action(function ($name, $response, $user, $projectDB, $audit) use ($oauth2Keys) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $user */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $audit */
$user = $projectDB->updateDocument(\array_merge($user->getArrayCopy(), [
'name' => $name,
]));
@ -743,8 +761,7 @@ App::patch('/v1/account/name')
],
$oauth2Keys
)), ['roles' => Authorization::getRoles()]));
}
);
}, ['response', 'user', 'projectDB', 'audit']);
App::patch('/v1/account/password')
->desc('Update Account Password')
@ -757,8 +774,12 @@ App::patch('/v1/account/password')
->label('sdk.description', '/docs/references/account/update-password.md')
->param('password', '', function () { return new Password(); }, 'New user password. Must be between 6 to 32 chars.')
->param('oldPassword', '', function () { return new Password(); }, 'Old user password. Must be between 6 to 32 chars.')
->action(
function ($password, $oldPassword) use ($response, $user, $projectDB, $audit, $oauth2Keys) {
->action(function ($password, $oldPassword, $response, $user, $projectDB, $audit) use ($oauth2Keys) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $user */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $audit */
if (!Auth::passwordVerify($oldPassword, $user->getAttribute('password'))) { // Double check user password
throw new Exception('Invalid credentials', 401);
}
@ -786,8 +807,7 @@ App::patch('/v1/account/password')
],
$oauth2Keys
)), ['roles' => Authorization::getRoles()]));
}
);
}, ['response', 'user', 'projectDB', 'audit']);
App::patch('/v1/account/email')
->desc('Update Account Email')
@ -800,8 +820,12 @@ App::patch('/v1/account/email')
->label('sdk.description', '/docs/references/account/update-email.md')
->param('email', '', function () { return new Email(); }, 'User email.')
->param('password', '', function () { return new Password(); }, 'User password. Must be between 6 to 32 chars.')
->action(
function ($email, $password) use ($response, $user, $projectDB, $audit, $oauth2Keys) {
->action(function ($email, $password, $response, $user, $projectDB, $audit) use ($oauth2Keys) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $user */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $audit */
if (!Auth::passwordVerify($password, $user->getAttribute('password'))) { // Double check user password
throw new Exception('Invalid credentials', 401);
}
@ -844,8 +868,7 @@ App::patch('/v1/account/email')
],
$oauth2Keys
)), ['roles' => Authorization::getRoles()]));
}
);
}, ['response', 'user', 'projectDB', 'audit']);
App::patch('/v1/account/prefs')
->desc('Update Account Preferences')
@ -857,8 +880,12 @@ App::patch('/v1/account/prefs')
->label('sdk.method', 'updatePrefs')
->param('prefs', '', function () { return new Assoc();}, 'Prefs key-value JSON object.')
->label('sdk.description', '/docs/references/account/update-prefs.md')
->action(
function ($prefs) use ($response, $user, $projectDB, $audit) {
->action(function ($prefs, $response, $user, $projectDB, $audit) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $user */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $audit */
$old = \json_decode($user->getAttribute('prefs', '{}'), true);
$old = ($old) ? $old : [];
@ -885,8 +912,7 @@ App::patch('/v1/account/prefs')
}
$response->json($prefs);
}
);
}, ['response', 'user', 'projectDB', 'audit']);
App::delete('/v1/account')
->desc('Delete Account')
@ -897,8 +923,13 @@ App::delete('/v1/account')
->label('sdk.namespace', 'account')
->label('sdk.method', 'delete')
->label('sdk.description', '/docs/references/account/delete.md')
->action(
function () use ($response, $user, $projectDB, $audit, $webhook) {
->action(function ($response, $user, $projectDB, $audit, $webhook) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $user */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $audit */
/** @var Appwrite\Event\Event $webhook */
$protocol = Config::getParam('protocol');
$user = $projectDB->updateDocument(\array_merge($user->getArrayCopy(), [
'status' => Auth::USER_STATUS_BLOCKED,
@ -941,8 +972,7 @@ App::delete('/v1/account')
->addCookie(Auth::$cookieName, '', \time() - 3600, '/', COOKIE_DOMAIN, ('https' == $protocol), true, COOKIE_SAMESITE)
->noContent()
;
}
);
}, ['response', 'user', 'projectDB', 'audit', 'webhook']);
App::delete('/v1/account/sessions/:sessionId')
->desc('Delete Account Session')
@ -955,8 +985,13 @@ App::delete('/v1/account/sessions/:sessionId')
->label('sdk.description', '/docs/references/account/delete-session.md')
->label('abuse-limit', 100)
->param('sessionId', null, function () { return new UID(); }, 'Session unique ID. Use the string \'current\' to delete the current device session.')
->action(
function ($sessionId) use ($response, $user, $projectDB, $webhook, $audit) {
->action(function ($sessionId, $response, $user, $projectDB, $audit, $webhook) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $user */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $audit */
/** @var Appwrite\Event\Event $webhook */
$protocol = Config::getParam('protocol');
$sessionId = ($sessionId === 'current')
? Auth::tokenVerify($user->getAttribute('tokens'), Auth::TOKEN_TYPE_LOGIN, Auth::$secret)
@ -1001,8 +1036,7 @@ App::delete('/v1/account/sessions/:sessionId')
}
throw new Exception('Session not found', 404);
}
);
}, ['response', 'user', 'projectDB', 'audit', 'webhook']);
App::delete('/v1/account/sessions')
->desc('Delete All Account Sessions')
@ -1014,8 +1048,13 @@ App::delete('/v1/account/sessions')
->label('sdk.method', 'deleteSessions')
->label('sdk.description', '/docs/references/account/delete-sessions.md')
->label('abuse-limit', 100)
->action(
function () use ($response, $user, $projectDB, $audit, $webhook) {
->action(function ($response, $user, $projectDB, $audit, $webhook) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $user */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $audit */
/** @var Appwrite\Event\Event $webhook */
$protocol = Config::getParam('protocol');
$tokens = $user->getAttribute('tokens', []);
@ -1052,8 +1091,7 @@ App::delete('/v1/account/sessions')
}
$response->noContent();
}
);
}, ['response', 'user', 'projectDB', 'audit', 'webhook']);
App::post('/v1/account/recovery')
->desc('Create Password Recovery')
@ -1066,9 +1104,16 @@ App::post('/v1/account/recovery')
->label('abuse-limit', 10)
->label('abuse-key', 'url:{url},email:{param-email}')
->param('email', '', function () { return new Email(); }, 'User email.')
->param('url', '', function () use ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.')
->action(
function ($email, $url) use ($request, $response, $projectDB, $mail, $audit, $project) {
->param('url', '', function ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients'])
->action(function ($email, $url, $request, $response, $projectDB, $project, $locale, $mail, $audit) {
/** @var Utopia\Request $request */
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Database\Document $project */
/** @var Utopia\Locale\Locale $locale */
/** @var Appwrite\Event\Event $mail */
/** @var Appwrite\Event\Event $audit */
$profile = $projectDB->getCollectionFirst([ // Get user by email address
'limit' => 1,
'filters' => [
@ -1113,14 +1158,14 @@ App::post('/v1/account/recovery')
$url = Template::unParseURL($url);
$body = new Template(__DIR__.'/../../config/locales/templates/_base.tpl');
$content = new Template(__DIR__.'/../../config/locales/templates/'.Locale::getText('account.emails.recovery.body'));
$content = new Template(__DIR__.'/../../config/locales/templates/'.$locale->getText('account.emails.recovery.body'));
$cta = new Template(__DIR__.'/../../config/locales/templates/_cta.tpl');
$body
->setParam('{{content}}', $content->render())
->setParam('{{cta}}', $cta->render())
->setParam('{{title}}', Locale::getText('account.emails.recovery.title'))
->setParam('{{direction}}', Locale::getText('settings.direction'))
->setParam('{{title}}', $locale->getText('account.emails.recovery.title'))
->setParam('{{direction}}', $locale->getText('settings.direction'))
->setParam('{{project}}', $project->getAttribute('name', ['[APP-NAME]']))
->setParam('{{name}}', $profile->getAttribute('name'))
->setParam('{{redirect}}', $url)
@ -1136,7 +1181,7 @@ App::post('/v1/account/recovery')
->setParam('event', 'account.recovery.create')
->setParam('recipient', $profile->getAttribute('email', ''))
->setParam('name', $profile->getAttribute('name', ''))
->setParam('subject', Locale::getText('account.emails.recovery.title'))
->setParam('subject', $locale->getText('account.emails.recovery.title'))
->setParam('body', $body->render())
->trigger();
;
@ -1151,8 +1196,7 @@ App::post('/v1/account/recovery')
->setStatusCode(Response::STATUS_CODE_CREATED)
->json($recovery->getArrayCopy(['$id', 'type', 'expire']))
;
}
);
}, ['request', 'response', 'projectDB', 'project', 'locale', 'mail', 'audit']);
App::put('/v1/account/recovery')
->desc('Complete Password Recovery')
@ -1168,8 +1212,11 @@ App::put('/v1/account/recovery')
->param('secret', '', function () { return new Text(256); }, 'Valid reset token.')
->param('password', '', function () { return new Password(); }, 'New password. Must be between 6 to 32 chars.')
->param('passwordAgain', '', function () {return new Password(); }, 'New password again. Must be between 6 to 32 chars.')
->action(
function ($userId, $secret, $password, $passwordAgain) use ($response, $projectDB, $audit) {
->action(function ($userId, $secret, $password, $passwordAgain, $response, $projectDB, $audit) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $audit */
if ($password !== $passwordAgain) {
throw new Exception('Passwords must match', 400);
}
@ -1221,8 +1268,7 @@ App::put('/v1/account/recovery')
$recovery = $profile->search('$id', $recovery, $profile->getAttribute('tokens', []));
$response->json($recovery->getArrayCopy(['$id', 'type', 'expire']));
}
);
}, ['response', 'projectDB', 'audit']);
App::post('/v1/account/verification')
->desc('Create Email Verification')
@ -1234,9 +1280,17 @@ App::post('/v1/account/verification')
->label('sdk.description', '/docs/references/account/create-verification.md')
->label('abuse-limit', 10)
->label('abuse-key', 'url:{url},email:{param-email}')
->param('url', '', function () use ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.') // TODO add built-in confirm page
->action(
function ($url) use ($request, $response, $mail, $user, $project, $projectDB, $audit) {
->param('url', '', function ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add built-in confirm page
->action(function ($url, $request, $response, $project, $user, $projectDB, $locale, $audit, $mail) {
/** @var Utopia\Request $request */
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $project */
/** @var Appwrite\Database\Document $user */
/** @var Appwrite\Database\Database $projectDB */
/** @var Utopia\Locale\Locale $locale */
/** @var Appwrite\Event\Event $audit */
/** @var Appwrite\Event\Event $mail */
$verificationSecret = Auth::tokenGenerator();
$verification = new Document([
@ -1270,14 +1324,14 @@ App::post('/v1/account/verification')
$url = Template::unParseURL($url);
$body = new Template(__DIR__.'/../../config/locales/templates/_base.tpl');
$content = new Template(__DIR__.'/../../config/locales/templates/'.Locale::getText('account.emails.verification.body'));
$content = new Template(__DIR__.'/../../config/locales/templates/'.$locale->getText('account.emails.verification.body'));
$cta = new Template(__DIR__.'/../../config/locales/templates/_cta.tpl');
$body
->setParam('{{content}}', $content->render())
->setParam('{{cta}}', $cta->render())
->setParam('{{title}}', Locale::getText('account.emails.verification.title'))
->setParam('{{direction}}', Locale::getText('settings.direction'))
->setParam('{{title}}', $locale->getText('account.emails.verification.title'))
->setParam('{{direction}}', $locale->getText('settings.direction'))
->setParam('{{project}}', $project->getAttribute('name', ['[APP-NAME]']))
->setParam('{{name}}', $user->getAttribute('name'))
->setParam('{{redirect}}', $url)
@ -1293,7 +1347,7 @@ App::post('/v1/account/verification')
->setParam('event', 'account.verification.create')
->setParam('recipient', $user->getAttribute('email'))
->setParam('name', $user->getAttribute('name'))
->setParam('subject', Locale::getText('account.emails.verification.title'))
->setParam('subject', $locale->getText('account.emails.verification.title'))
->setParam('body', $body->render())
->trigger()
;
@ -1308,8 +1362,7 @@ App::post('/v1/account/verification')
->setStatusCode(Response::STATUS_CODE_CREATED)
->json($verification->getArrayCopy(['$id', 'type', 'expire']))
;
}
);
}, ['request', 'response', 'project', 'user', 'projectDB', 'locale', 'audit', 'mail']);
App::put('/v1/account/verification')
->desc('Complete Email Verification')
@ -1323,8 +1376,12 @@ App::put('/v1/account/verification')
->label('abuse-key', 'url:{url},userId:{param-userId}')
->param('userId', '', function () { return new UID(); }, 'User unique ID.')
->param('secret', '', function () { return new Text(256); }, 'Valid verification token.')
->action(
function ($userId, $secret) use ($response, $user, $projectDB, $audit) {
->action(function ($userId, $secret, $response, $user, $projectDB, $audit) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $user */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $audit */
$profile = $projectDB->getCollectionFirst([ // Get user by email address
'limit' => 1,
'filters' => [
@ -1370,5 +1427,4 @@ App::put('/v1/account/verification')
$verification = $profile->search('$id', $verification, $profile->getAttribute('tokens', []));
$response->json($verification->getArrayCopy(['$id', 'type', 'expire']));
}
);
}, ['response', 'user', 'projectDB', 'audit']);

View file

@ -1,7 +1,5 @@
<?php
global $response;
use Utopia\App;
use Utopia\Exception;
use Utopia\Validator\Boolean;
@ -20,7 +18,9 @@ use BaconQrCode\Writer;
use Utopia\Config\Config;
use Utopia\Validator\HexColor;
$avatarCallback = function ($type, $code, $width, $height, $quality) use ($response) {
$avatarCallback = function ($type, $code, $width, $height, $quality, $response) {
/** @var Utopia\Response $response */
$code = \strtolower($code);
$type = \strtolower($type);
$set = Config::getParam('avatar-'.$type, []);
@ -86,68 +86,69 @@ $avatarCallback = function ($type, $code, $width, $height, $quality) use ($respo
App::get('/v1/avatars/credit-cards/:code')
->desc('Get Credit Card Icon')
->groups(['api', 'avatars'])
->param('code', '', function () { return new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))); }, 'Credit Card Code. Possible values: '.\implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))).'.')
->param('width', 100, function () { return new Range(0, 2000); }, 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('height', 100, function () { return new Range(0, 2000); }, 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('quality', 100, function () { return new Range(0, 100); }, 'Image quality. Pass an integer between 0 to 100. Defaults to 100.', true)
->label('scope', 'avatars.read')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'avatars')
->label('sdk.method', 'getCreditCard')
->label('sdk.methodType', 'location')
->label('sdk.description', '/docs/references/avatars/get-credit-card.md')
->action(function ($code, $width, $height, $quality) use ($avatarCallback) {
return $avatarCallback('credit-cards', $code, $width, $height, $quality);
});
->param('code', '', function () { return new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))); }, 'Credit Card Code. Possible values: '.\implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))).'.')
->param('width', 100, function () { return new Range(0, 2000); }, 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('height', 100, function () { return new Range(0, 2000); }, 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('quality', 100, function () { return new Range(0, 100); }, 'Image quality. Pass an integer between 0 to 100. Defaults to 100.', true)
->action(function ($code, $width, $height, $quality, $response) use ($avatarCallback) {
return $avatarCallback('credit-cards', $code, $width, $height, $quality, $response);
}, ['response']);
App::get('/v1/avatars/browsers/:code')
->desc('Get Browser Icon')
->groups(['api', 'avatars'])
->param('code', '', function () { return new WhiteList(\array_keys(Config::getParam('avatar-browsers'))); }, 'Browser Code.')
->param('width', 100, function () { return new Range(0, 2000); }, 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('height', 100, function () { return new Range(0, 2000); }, 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('quality', 100, function () { return new Range(0, 100); }, 'Image quality. Pass an integer between 0 to 100. Defaults to 100.', true)
->label('scope', 'avatars.read')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'avatars')
->label('sdk.method', 'getBrowser')
->label('sdk.methodType', 'location')
->label('sdk.description', '/docs/references/avatars/get-browser.md')
->action(function ($code, $width, $height, $quality) use ($avatarCallback) {
return $avatarCallback('browsers', $code, $width, $height, $quality);
});
->param('code', '', function () { return new WhiteList(\array_keys(Config::getParam('avatar-browsers'))); }, 'Browser Code.')
->param('width', 100, function () { return new Range(0, 2000); }, 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('height', 100, function () { return new Range(0, 2000); }, 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('quality', 100, function () { return new Range(0, 100); }, 'Image quality. Pass an integer between 0 to 100. Defaults to 100.', true)
->action(function ($code, $width, $height, $quality, $response) use ($avatarCallback) {
return $avatarCallback('browsers', $code, $width, $height, $quality, $response);
}, ['response']);
App::get('/v1/avatars/flags/:code')
->desc('Get Country Flag')
->groups(['api', 'avatars'])
->param('code', '', function () { return new WhiteList(\array_keys(Config::getParam('avatar-flags'))); }, 'Country Code. ISO Alpha-2 country code format.')
->param('width', 100, function () { return new Range(0, 2000); }, 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('height', 100, function () { return new Range(0, 2000); }, 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('quality', 100, function () { return new Range(0, 100); }, 'Image quality. Pass an integer between 0 to 100. Defaults to 100.', true)
->label('scope', 'avatars.read')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'avatars')
->label('sdk.method', 'getFlag')
->label('sdk.methodType', 'location')
->label('sdk.description', '/docs/references/avatars/get-flag.md')
->action(function ($code, $width, $height, $quality) use ($avatarCallback) {
return $avatarCallback('flags', $code, $width, $height, $quality);
});
->param('code', '', function () { return new WhiteList(\array_keys(Config::getParam('avatar-flags'))); }, 'Country Code. ISO Alpha-2 country code format.')
->param('width', 100, function () { return new Range(0, 2000); }, 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('height', 100, function () { return new Range(0, 2000); }, 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('quality', 100, function () { return new Range(0, 100); }, 'Image quality. Pass an integer between 0 to 100. Defaults to 100.', true)
->action(function ($code, $width, $height, $quality, $response) use ($avatarCallback) {
return $avatarCallback('flags', $code, $width, $height, $quality, $response);
}, ['response']);
App::get('/v1/avatars/image')
->desc('Get Image from URL')
->groups(['api', 'avatars'])
->param('url', '', function () { return new URL(); }, 'Image URL which you want to crop.')
->param('width', 400, function () { return new Range(0, 2000); }, 'Resize preview image width, Pass an integer between 0 to 2000.', true)
->param('height', 400, function () { return new Range(0, 2000); }, 'Resize preview image height, Pass an integer between 0 to 2000.', true)
->label('scope', 'avatars.read')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'avatars')
->label('sdk.method', 'getImage')
->label('sdk.methodType', 'location')
->label('sdk.description', '/docs/references/avatars/get-image.md')
->action(
function ($url, $width, $height) use ($response) {
->param('url', '', function () { return new URL(); }, 'Image URL which you want to crop.')
->param('width', 400, function () { return new Range(0, 2000); }, 'Resize preview image width, Pass an integer between 0 to 2000.', true)
->param('height', 400, function () { return new Range(0, 2000); }, 'Resize preview image height, Pass an integer between 0 to 2000.', true)
->action(function ($url, $width, $height, $response) {
/** @var Utopia\Response $response */
$quality = 80;
$output = 'png';
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT'; // 45 days cache
@ -199,21 +200,21 @@ App::get('/v1/avatars/image')
echo $data;
unset($resize);
}
);
}, ['response']);
App::get('/v1/avatars/favicon')
->desc('Get Favicon')
->groups(['api', 'avatars'])
->param('url', '', function () { return new URL(); }, 'Website URL which you want to fetch the favicon from.')
->label('scope', 'avatars.read')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'avatars')
->label('sdk.method', 'getFavicon')
->label('sdk.methodType', 'location')
->label('sdk.description', '/docs/references/avatars/get-favicon.md')
->action(
function ($url) use ($response) {
->param('url', '', function () { return new URL(); }, 'Website URL which you want to fetch the favicon from.')
->action(function ($url, $response) {
/** @var Utopia\Response $response */
$width = 56;
$height = 56;
$quality = 80;
@ -352,24 +353,24 @@ App::get('/v1/avatars/favicon')
echo $data;
unset($resize);
}
);
}, ['response']);
App::get('/v1/avatars/qr')
->desc('Get QR Code')
->groups(['api', 'avatars'])
->param('text', '', function () { return new Text(512); }, 'Plain text to be converted to QR code image.')
->param('size', 400, function () { return new Range(0, 1000); }, 'QR code size. Pass an integer between 0 to 1000. Defaults to 400.', true)
->param('margin', 1, function () { return new Range(0, 10); }, 'Margin from edge. Pass an integer between 0 to 10. Defaults to 1.', true)
->param('download', false, function () { return new Boolean(true); }, 'Return resulting image with \'Content-Disposition: attachment \' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.', true)
->label('scope', 'avatars.read')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'avatars')
->label('sdk.method', 'getQR')
->label('sdk.methodType', 'location')
->label('sdk.description', '/docs/references/avatars/get-qr.md')
->action(
function ($text, $size, $margin, $download) use ($response) {
->param('text', '', function () { return new Text(512); }, 'Plain text to be converted to QR code image.')
->param('size', 400, function () { return new Range(0, 1000); }, 'QR code size. Pass an integer between 0 to 1000. Defaults to 400.', true)
->param('margin', 1, function () { return new Range(0, 10); }, 'Margin from edge. Pass an integer between 0 to 10. Defaults to 1.', true)
->param('download', false, function () { return new Boolean(true); }, 'Return resulting image with \'Content-Disposition: attachment \' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.', true)
->action(function ($text, $size, $margin, $download, $response) {
/** @var Utopia\Response $response */
$download = ($download === '1' || $download === 'true' || $download === 1 || $download === true);
$renderer = new ImageRenderer(
@ -388,25 +389,26 @@ App::get('/v1/avatars/qr')
->setContentType('image/png')
->send($writer->writeString($text))
;
}
);
}, ['response']);
App::get('/v1/avatars/initials')
->desc('Get User Initials')
->groups(['api', 'avatars'])
->param('name', '', function () { return new Text(512); }, 'Full Name. When empty, current user name or email will be used.', true)
->param('width', 500, function () { return new Range(0, 2000); }, 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('height', 500, function () { return new Range(0, 2000); }, 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('color', '', function () { return new HexColor(); }, 'Changes text color. By default a random color will be picked and stay will persistent to the given name.', true)
->param('background', '', function () { return new HexColor(); }, 'Changes background color. By default a random color will be picked and stay will persistent to the given name.', true)
->label('scope', 'avatars.read')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'avatars')
->label('sdk.method', 'getInitials')
->label('sdk.methodType', 'location')
->label('sdk.description', '/docs/references/avatars/get-initials.md')
->action(
function ($name, $width, $height, $color, $background) use ($response, $user) {
->param('name', '', function () { return new Text(512); }, 'Full Name. When empty, current user name or email will be used.', true)
->param('width', 500, function () { return new Range(0, 2000); }, 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('height', 500, function () { return new Range(0, 2000); }, 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('color', '', function () { return new HexColor(); }, 'Changes text color. By default a random color will be picked and stay will persistent to the given name.', true)
->param('background', '', function () { return new HexColor(); }, 'Changes background color. By default a random color will be picked and stay will persistent to the given name.', true)
->action(function ($name, $width, $height, $color, $background, $response, $user) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $user */
$themes = [
['color' => '#27005e', 'background' => '#e1d2f6'], // VIOLET
['color' => '#5e2700', 'background' => '#f3d9c6'], // ORANGE
@ -465,5 +467,4 @@ App::get('/v1/avatars/initials')
->setContentType('image/png')
->send($image->getImageBlob())
;
}
);
}, ['response', 'user']);

View file

@ -1,7 +1,5 @@
<?php
global $request, $response, $webhook, $audit, $projectDB;
use Utopia\App;
use Utopia\Exception;
use Utopia\Response;
@ -23,9 +21,6 @@ use Appwrite\Database\Validator\Authorization;
use Appwrite\Database\Exception\Authorization as AuthorizationException;
use Appwrite\Database\Exception\Structure as StructureException;
// use DeviceDetector\DeviceDetector;
// use GeoIp2\Database\Reader;
App::post('/v1/database/collections')
->desc('Create Collection')
->groups(['api', 'database'])
@ -38,9 +33,13 @@ App::post('/v1/database/collections')
->param('name', '', function () { return new Text(256); }, 'Collection name.')
->param('read', [], function () { return new ArrayList(new Text(64)); }, 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
->param('write', [], function () { return new ArrayList(new Text(64)); }, 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
->param('rules', [], function () use ($projectDB) { return new ArrayList(new Collection($projectDB, [Database::SYSTEM_COLLECTION_RULES], ['$collection' => Database::SYSTEM_COLLECTION_RULES, '$permissions' => ['read' => [], 'write' => []]])); }, 'Array of [rule objects](/docs/rules). Each rule define a collection field name, data type and validation.')
->action(
function ($name, $read, $write, $rules) use ($response, $projectDB, $webhook, $audit) {
->param('rules', [], function ($projectDB) { return new ArrayList(new Collection($projectDB, [Database::SYSTEM_COLLECTION_RULES], ['$collection' => Database::SYSTEM_COLLECTION_RULES, '$permissions' => ['read' => [], 'write' => []]])); }, 'Array of [rule objects](/docs/rules). Each rule define a collection field name, data type and validation.', false, ['projectDB'])
->action(function ($name, $read, $write, $rules, $response, $projectDB, $webhook, $audit) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $webhook */
/** @var Appwrite\Event\Event $audit */
$parsedRules = [];
foreach ($rules as &$rule) {
@ -97,8 +96,7 @@ App::post('/v1/database/collections')
->setStatusCode(Response::STATUS_CODE_CREATED)
->json($data)
;
}
);
}, ['response', 'projectDB', 'webhook', 'audit']);
App::get('/v1/database/collections')
->desc('List Collections')
@ -112,26 +110,9 @@ App::get('/v1/database/collections')
->param('limit', 25, function () { return new Range(0, 100); }, 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
->param('offset', 0, function () { return new Range(0, 40000); }, 'Results offset. The default value is 0. Use this param to manage pagination.', true)
->param('orderType', 'ASC', function () { return new WhiteList(['ASC', 'DESC']); }, 'Order result by ASC or DESC order.', true)
->action(
function ($search, $limit, $offset, $orderType) use ($response, $projectDB) {
/*$vl = new Structure($projectDB);
var_dump($vl->isValid(new Document([
'$collection' => Database::SYSTEM_COLLECTION_RULES,
'$permissions' => [
'read' => ['*'],
'write' => ['*'],
],
'label' => 'Platforms',
'key' => 'platforms',
'type' => 'document',
'default' => [],
'required' => false,
'array' => true,
'options' => [Database::SYSTEM_COLLECTION_PLATFORMS],
])));
var_dump($vl->getDescription());*/
->action(function ($search, $limit, $offset, $orderType, $response, $projectDB) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Database $projectDB */
$results = $projectDB->getCollection([
'limit' => $limit,
@ -146,8 +127,7 @@ App::get('/v1/database/collections')
]);
$response->json(['sum' => $projectDB->getSum(), 'collections' => $results]);
}
);
}, ['response', 'projectDB']);
App::get('/v1/database/collections/:collectionId')
->desc('Get Collection')
@ -158,8 +138,10 @@ App::get('/v1/database/collections/:collectionId')
->label('sdk.method', 'getCollection')
->label('sdk.description', '/docs/references/database/get-collection.md')
->param('collectionId', '', function () { return new UID(); }, 'Collection unique ID.')
->action(
function ($collectionId) use ($response, $projectDB) {
->action(function ($collectionId, $response, $projectDB) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Database $projectDB */
$collection = $projectDB->getDocument($collectionId, false);
if (empty($collection->getId()) || Database::SYSTEM_COLLECTION_COLLECTIONS != $collection->getCollection()) {
@ -167,8 +149,7 @@ App::get('/v1/database/collections/:collectionId')
}
$response->json($collection->getArrayCopy());
}
);
}, ['response', 'projectDB']);
// App::get('/v1/database/collections/:collectionId/logs')
// ->desc('Get Collection Logs')
@ -249,8 +230,12 @@ App::put('/v1/database/collections/:collectionId')
->param('read', [], function () { return new ArrayList(new Text(64)); }, 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions(/docs/permissions) and get a full list of available permissions.')
->param('write', [], function () { return new ArrayList(new Text(64)); }, 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
->param('rules', [], function () use ($projectDB) { return new ArrayList(new Collection($projectDB, [Database::SYSTEM_COLLECTION_RULES], ['$collection' => Database::SYSTEM_COLLECTION_RULES, '$permissions' => ['read' => [], 'write' => []]])); }, 'Array of [rule objects](/docs/rules). Each rule define a collection field name, data type and validation.', true)
->action(
function ($collectionId, $name, $read, $write, $rules) use ($response, $projectDB, $webhook, $audit) {
->action(function ($collectionId, $name, $read, $write, $rules, $response, $projectDB, $webhook, $audit) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $webhook */
/** @var Appwrite\Event\Event $audit */
$collection = $projectDB->getDocument($collectionId, false);
if (empty($collection->getId()) || Database::SYSTEM_COLLECTION_COLLECTIONS != $collection->getCollection()) {
@ -305,8 +290,7 @@ App::put('/v1/database/collections/:collectionId')
;
$response->json($collection->getArrayCopy());
}
);
}, ['response', 'projectDB', 'webhook', 'audit']);
App::delete('/v1/database/collections/:collectionId')
->desc('Delete Collection')
@ -318,8 +302,12 @@ App::delete('/v1/database/collections/:collectionId')
->label('sdk.method', 'deleteCollection')
->label('sdk.description', '/docs/references/database/delete-collection.md')
->param('collectionId', '', function () { return new UID(); }, 'Collection unique ID.')
->action(
function ($collectionId) use ($response, $projectDB, $webhook, $audit) {
->action(function ($collectionId, $response, $projectDB, $webhook, $audit) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $webhook */
/** @var Appwrite\Event\Event $audit */
$collection = $projectDB->getDocument($collectionId, false);
if (empty($collection->getId()) || Database::SYSTEM_COLLECTION_COLLECTIONS != $collection->getCollection()) {
@ -343,8 +331,7 @@ App::delete('/v1/database/collections/:collectionId')
;
$response->noContent();
}
);
}, ['response', 'projectDB', 'webhook', 'audit']);
App::post('/v1/database/collections/:collectionId/documents')
->desc('Create Document')
@ -362,8 +349,12 @@ App::post('/v1/database/collections/:collectionId/documents')
->param('parentDocument', '', function () { return new UID(); }, 'Parent document unique ID. Use when you want your new document to be a child of a parent document.', true)
->param('parentProperty', '', function () { return new Key(); }, 'Parent document property name. Use when you want your new document to be a child of a parent document.', true)
->param('parentPropertyType', Document::SET_TYPE_ASSIGN, function () { return new WhiteList([Document::SET_TYPE_ASSIGN, Document::SET_TYPE_APPEND, Document::SET_TYPE_PREPEND]); }, 'Parent document property connection type. You can set this value to **assign**, **append** or **prepend**, default value is assign. Use when you want your new document to be a child of a parent document.', true)
->action(
function ($collectionId, $data, $read, $write, $parentDocument, $parentProperty, $parentPropertyType) use ($response, $projectDB, $webhook, $audit) {
->action(function ($collectionId, $data, $read, $write, $parentDocument, $parentProperty, $parentPropertyType, $response, $projectDB, $webhook, $audit) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $webhook */
/** @var Appwrite\Event\Event $audit */
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
if (empty($data)) {
@ -463,8 +454,7 @@ App::post('/v1/database/collections/:collectionId/documents')
->setStatusCode(Response::STATUS_CODE_CREATED)
->json($data)
;
}
);
}, ['response', 'projectDB', 'webhook', 'audit']);
App::get('/v1/database/collections/:collectionId/documents')
->desc('List Documents')
@ -482,8 +472,10 @@ App::get('/v1/database/collections/:collectionId/documents')
->param('orderType', 'ASC', function () { return new WhiteList(array('DESC', 'ASC')); }, 'Order direction. Possible values are DESC for descending order, or ASC for ascending order.', true)
->param('orderCast', 'string', function () { return new WhiteList(array('int', 'string', 'date', 'time', 'datetime')); }, 'Order field type casting. Possible values are int, string, date, time or datetime. The database will attempt to cast the order field to the value you pass here. The default value is a string.', true)
->param('search', '', function () { return new Text(256); }, 'Search query. Enter any free text search. The database will try to find a match against all document attributes and children.', true)
->action(
function ($collectionId, $filters, $offset, $limit, $orderField, $orderType, $orderCast, $search) use ($response, $projectDB) {
->action(function ($collectionId, $filters, $offset, $limit, $orderField, $orderType, $orderCast, $search, $response, $projectDB) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Database $projectDB */
$collection = $projectDB->getDocument($collectionId, false);
if (\is_null($collection->getId()) || Database::SYSTEM_COLLECTION_COLLECTIONS != $collection->getCollection()) {
@ -523,8 +515,7 @@ App::get('/v1/database/collections/:collectionId/documents')
* View
*/
$response->json($collection->getArrayCopy(/*['$id', '$collection', 'name', 'documents']*/[], ['rules']));
}
);
}, ['response', 'projectDB']);
App::get('/v1/database/collections/:collectionId/documents/:documentId')
->desc('Get Document')
@ -536,8 +527,11 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId')
->label('sdk.description', '/docs/references/database/get-document.md')
->param('collectionId', null, function () { return new UID(); }, 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/server/database#createCollection).')
->param('documentId', null, function () { return new UID(); }, 'Document unique ID.')
->action(
function ($collectionId, $documentId) use ($response, $request, $projectDB) {
->action(function ($collectionId, $documentId, $request, $response, $projectDB) {
/** @var Utopia\Request $request */
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Database $projectDB */
$document = $projectDB->getDocument($documentId, false);
$collection = $projectDB->getDocument($collectionId, false);
@ -569,8 +563,7 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId')
* View
*/
$response->json($output);
}
);
}, ['request', 'response', 'projectDB']);
App::patch('/v1/database/collections/:collectionId/documents/:documentId')
->desc('Update Document')
@ -586,8 +579,12 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
->param('data', [], function () { return new JSON(); }, 'Document data as JSON object.')
->param('read', [], function () { return new ArrayList(new Text(64)); }, 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
->param('write', [], function () { return new ArrayList(new Text(64)); }, 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
->action(
function ($collectionId, $documentId, $data, $read, $write) use ($response, $projectDB, $webhook, $audit) {
->action(function ($collectionId, $documentId, $data, $read, $write, $response, $projectDB, $webhook, $audit) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $webhook */
/** @var Appwrite\Event\Event $audit */
$collection = $projectDB->getDocument($collectionId, false);
$document = $projectDB->getDocument($documentId, false);
@ -649,8 +646,7 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
* View
*/
$response->json($data);
}
);
}, ['response', 'projectDB', 'webhook', 'audit']);
App::delete('/v1/database/collections/:collectionId/documents/:documentId')
->desc('Delete Document')
@ -663,8 +659,12 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId')
->label('sdk.description', '/docs/references/database/delete-document.md')
->param('collectionId', null, function () { return new UID(); }, 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/server/database#createCollection).')
->param('documentId', null, function () { return new UID(); }, 'Document unique ID.')
->action(
function ($collectionId, $documentId) use ($response, $projectDB, $audit, $webhook) {
->action(function ($collectionId, $documentId, $response, $projectDB, $webhook, $audit) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $webhook */
/** @var Appwrite\Event\Event $audit */
$collection = $projectDB->getDocument($collectionId, false);
$document = $projectDB->getDocument($documentId, false);
@ -699,5 +699,4 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId')
;
$response->noContent();
}
);
}, ['response', 'projectDB', 'webhook', 'audit']);

View file

@ -1,7 +1,5 @@
<?php
global $request, $response, $register;
use Utopia\App;
use Utopia\Exception;
use Appwrite\Storage\Device\Local;
@ -16,21 +14,21 @@ App::get('/v1/health')
->label('sdk.namespace', 'health')
->label('sdk.method', 'get')
->label('sdk.description', '/docs/references/health/get.md')
->action(
function () use ($response) {
->action(function ($response) {
/** @var Utopia\Response $response */
$response->json(['status' => 'OK']);
}
);
}, ['response']);
App::get('/v1/health/version')
->desc('Get Version')
->groups(['api', 'health'])
->label('scope', 'public')
->action(
function () use ($response) {
->action(function ($response) {
/** @var Utopia\Response $response */
$response->json(['version' => APP_VERSION_STABLE]);
}
);
}, ['response']);
App::get('/v1/health/db')
->desc('Get DB')
@ -40,13 +38,14 @@ App::get('/v1/health/db')
->label('sdk.namespace', 'health')
->label('sdk.method', 'getDB')
->label('sdk.description', '/docs/references/health/get-db.md')
->action(
function () use ($response, $register) {
->action(function ($response, $register) {
/** @var Utopia\Response $response */
/** @var Utopia\Registry\Registry $register */
$register->get('db'); /* @var $db PDO */
$response->json(['status' => 'OK']);
}
);
}, ['response', 'register']);
App::get('/v1/health/cache')
->desc('Get Cache')
@ -56,13 +55,13 @@ App::get('/v1/health/cache')
->label('sdk.namespace', 'health')
->label('sdk.method', 'getCache')
->label('sdk.description', '/docs/references/health/get-cache.md')
->action(
function () use ($response, $register) {
->action(function ($response, $register) {
/** @var Utopia\Response $response */
/** @var Utopia\Registry\Registry $register */
$register->get('cache'); /* @var $cache Predis\Client */
$response->json(['status' => 'OK']);
}
);
}, ['response']);
App::get('/v1/health/time')
->desc('Get Time')
@ -72,8 +71,9 @@ App::get('/v1/health/time')
->label('sdk.namespace', 'health')
->label('sdk.method', 'getTime')
->label('sdk.description', '/docs/references/health/get-time.md')
->action(
function () use ($response) {
->action(function ($response) {
/** @var Utopia\Response $response */
/*
* Code from: @see https://www.beliefmedia.com.au/query-ntp-time-server
*/
@ -109,8 +109,7 @@ App::get('/v1/health/time')
}
$response->json(['remote' => $timestamp, 'local' => \time(), 'diff' => $diff]);
}
);
}, ['response']);
App::get('/v1/health/queue/webhooks')
->desc('Get Webhooks Queue')
@ -120,11 +119,11 @@ App::get('/v1/health/queue/webhooks')
->label('sdk.namespace', 'health')
->label('sdk.method', 'getQueueWebhooks')
->label('sdk.description', '/docs/references/health/get-queue-webhooks.md')
->action(
function () use ($response) {
->action(function ($response) {
/** @var Utopia\Response $response */
$response->json(['size' => Resque::size('v1-webhooks')]);
}
);
}, ['response']);
App::get('/v1/health/queue/tasks')
->desc('Get Tasks Queue')
@ -134,11 +133,11 @@ App::get('/v1/health/queue/tasks')
->label('sdk.namespace', 'health')
->label('sdk.method', 'getQueueTasks')
->label('sdk.description', '/docs/references/health/get-queue-tasks.md')
->action(
function () use ($response) {
->action(function ($response) {
/** @var Utopia\Response $response */
$response->json(['size' => Resque::size('v1-tasks')]);
}
);
}, ['response']);
App::get('/v1/health/queue/logs')
->desc('Get Logs Queue')
@ -148,11 +147,11 @@ App::get('/v1/health/queue/logs')
->label('sdk.namespace', 'health')
->label('sdk.method', 'getQueueLogs')
->label('sdk.description', '/docs/references/health/get-queue-logs.md')
->action(
function () use ($response) {
->action(function ($response) {
/** @var Utopia\Response $response */
$response->json(['size' => Resque::size('v1-audit')]);
}
);
}, ['response']);
App::get('/v1/health/queue/usage')
->desc('Get Usage Queue')
@ -162,11 +161,11 @@ App::get('/v1/health/queue/usage')
->label('sdk.namespace', 'health')
->label('sdk.method', 'getQueueUsage')
->label('sdk.description', '/docs/references/health/get-queue-usage.md')
->action(
function () use ($response) {
->action(function ($response) {
/** @var Utopia\Response $response */
$response->json(['size' => Resque::size('v1-usage')]);
}
);
}, ['response']);
App::get('/v1/health/queue/certificates')
->desc('Get Certificate Queue')
@ -176,11 +175,11 @@ App::get('/v1/health/queue/certificates')
->label('sdk.namespace', 'health')
->label('sdk.method', 'getQueueCertificates')
->label('sdk.description', '/docs/references/health/get-queue-certificates.md')
->action(
function () use ($response) {
->action(function ($response) {
/** @var Utopia\Response $response */
$response->json(['size' => Resque::size('v1-certificates')]);
}
);
}, ['response']);
App::get('/v1/health/queue/functions')
->desc('Get Functions Queue')
@ -190,11 +189,11 @@ App::get('/v1/health/queue/functions')
->label('sdk.namespace', 'health')
->label('sdk.method', 'getQueueFunctions')
->label('sdk.description', '/docs/references/health/get-queue-functions.md')
->action(
function () use ($response) {
->action(function ($response) {
/** @var Utopia\Response $response */
$response->json(['size' => Resque::size('v1-functions')]);
}
);
}, ['response']);
App::get('/v1/health/storage/local')
->desc('Get Local Storage')
@ -204,8 +203,9 @@ App::get('/v1/health/storage/local')
->label('sdk.namespace', 'health')
->label('sdk.method', 'getStorageLocal')
->label('sdk.description', '/docs/references/health/get-storage-local.md')
->action(
function () use ($response) {
->action(function ($response) {
/** @var Utopia\Response $response */
foreach ([
'Uploads' => APP_STORAGE_UPLOADS,
'Cache' => APP_STORAGE_CACHE,
@ -224,8 +224,7 @@ App::get('/v1/health/storage/local')
}
$response->json(['status' => 'OK']);
}
);
}, ['response']);
App::get('/v1/health/anti-virus')
->desc('Get Anti virus')
@ -235,8 +234,9 @@ App::get('/v1/health/anti-virus')
->label('sdk.namespace', 'health')
->label('sdk.method', 'getAntiVirus')
->label('sdk.description', '/docs/references/health/get-storage-anti-virus.md')
->action(
function () use ($response) {
->action(function ($response) {
/** @var Utopia\Response $response */
if (App::getEnv('_APP_STORAGE_ANTIVIRUS') === 'disabled') { // Check if scans are enabled
throw new Exception('Anitvirus is disabled');
}
@ -247,8 +247,7 @@ App::get('/v1/health/anti-virus')
'status' => (@$antiVirus->ping()) ? 'online' : 'offline',
'version' => @$antiVirus->version(),
]);
}
);
}, ['response']);
App::get('/v1/health/stats') // Currently only used internally
->desc('Get System Stats')
@ -258,8 +257,10 @@ App::get('/v1/health/stats') // Currently only used internally
// ->label('sdk.namespace', 'health')
// ->label('sdk.method', 'getStats')
->label('docs', false)
->action(
function () use ($response, $register) {
->action(function ($response, $register) {
/** @var Utopia\Response $response */
/** @var Utopia\Registry\Registry $register */
$device = Storage::getDevice('local');
$cache = $register->get('cache');
@ -287,5 +288,4 @@ App::get('/v1/health/stats') // Currently only used internally
'memory_used_peak_human' => (isset($cacheStats['used_memory_peak_human'])) ? $cacheStats['used_memory_peak_human'] : 0,
],
]);
}
);
}, ['response', 'register']);

View file

@ -1,9 +1,6 @@
<?php
global $request, $response, $user;
use Utopia\App;
use Utopia\Locale\Locale;
use GeoIp2\Database\Reader;
App::get('/v1/locale')
@ -14,16 +11,19 @@ App::get('/v1/locale')
->label('sdk.namespace', 'locale')
->label('sdk.method', 'get')
->label('sdk.description', '/docs/references/locale/get-locale.md')
->action(
function () use ($response, $request) {
->action(function ($request, $response, $locale) {
/** @var Utopia\Request $request */
/** @var Utopia\Response $response */
/** @var Utopia\Locale\Locale $locale */
$eu = include __DIR__.'/../../config/eu.php';
$currencies = include __DIR__.'/../../config/currencies.php';
$reader = new Reader(__DIR__.'/../../db/DBIP/dbip-country-lite-2020-01.mmdb');
$output = [];
$ip = $request->getIP();
$time = (60 * 60 * 24 * 45); // 45 days cache
$countries = Locale::getText('countries');
$continents = Locale::getText('continents');
$countries = $locale->getText('countries');
$continents = $locale->getText('continents');
if (!App::isProduction()) {
$ip = '79.177.241.94';
@ -36,9 +36,9 @@ App::get('/v1/locale')
try {
$record = $reader->country($ip);
$output['countryCode'] = $record->country->isoCode;
$output['country'] = (isset($countries[$record->country->isoCode])) ? $countries[$record->country->isoCode] : Locale::getText('locale.country.unknown');
$output['country'] = (isset($countries[$record->country->isoCode])) ? $countries[$record->country->isoCode] : $locale->getText('locale.country.unknown');
//$output['countryTimeZone'] = DateTimeZone::listIdentifiers(DateTimeZone::PER_COUNTRY, $record->country->isoCode);
$output['continent'] = (isset($continents[$record->continent->code])) ? $continents[$record->continent->code] : Locale::getText('locale.country.unknown');
$output['continent'] = (isset($continents[$record->continent->code])) ? $continents[$record->continent->code] : $locale->getText('locale.country.unknown');
$output['continentCode'] = $record->continent->code;
$output['eu'] = (\in_array($record->country->isoCode, $eu)) ? true : false;
@ -51,8 +51,8 @@ App::get('/v1/locale')
$output['currency'] = $currency;
} catch (\Exception $e) {
$output['countryCode'] = '--';
$output['country'] = Locale::getText('locale.country.unknown');
$output['continent'] = Locale::getText('locale.country.unknown');
$output['country'] = $locale->getText('locale.country.unknown');
$output['continent'] = $locale->getText('locale.country.unknown');
$output['continentCode'] = '--';
$output['eu'] = false;
$output['currency'] = $currency;
@ -62,8 +62,7 @@ App::get('/v1/locale')
->addHeader('Cache-Control', 'public, max-age='.$time)
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time).' GMT') // 45 days cache
->json($output);
}
);
}, ['request', 'response', 'locale']);
App::get('/v1/locale/countries')
->desc('List Countries')
@ -73,15 +72,16 @@ App::get('/v1/locale/countries')
->label('sdk.namespace', 'locale')
->label('sdk.method', 'getCountries')
->label('sdk.description', '/docs/references/locale/get-countries.md')
->action(
function () use ($response) {
$list = Locale::getText('countries'); /* @var $list array */
->action(function ($response, $locale) {
/** @var Utopia\Response $response */
/** @var Utopia\Locale\Locale $locale */
$list = $locale->getText('countries'); /* @var $list array */
\asort($list);
$response->json($list);
}
);
}, ['response', 'locale']);
App::get('/v1/locale/countries/eu')
->desc('List EU Countries')
@ -91,9 +91,11 @@ App::get('/v1/locale/countries/eu')
->label('sdk.namespace', 'locale')
->label('sdk.method', 'getCountriesEU')
->label('sdk.description', '/docs/references/locale/get-countries-eu.md')
->action(
function () use ($response) {
$countries = Locale::getText('countries'); /* @var $countries array */
->action(function ($response, $locale) {
/** @var Utopia\Response $response */
/** @var Utopia\Locale\Locale $locale */
$countries = $locale->getText('countries'); /* @var $countries array */
$eu = include __DIR__.'/../../config/eu.php';
$list = [];
@ -106,8 +108,7 @@ App::get('/v1/locale/countries/eu')
\asort($list);
$response->json($list);
}
);
}, ['response', 'locale']);
App::get('/v1/locale/countries/phones')
->desc('List Countries Phone Codes')
@ -117,11 +118,13 @@ App::get('/v1/locale/countries/phones')
->label('sdk.namespace', 'locale')
->label('sdk.method', 'getCountriesPhones')
->label('sdk.description', '/docs/references/locale/get-countries-phones.md')
->action(
function () use ($response) {
->action(function ($response, $locale) {
/** @var Utopia\Response $response */
/** @var Utopia\Locale\Locale $locale */
$list = include __DIR__.'/../../config/phones.php'; /* @var $list array */
$countries = Locale::getText('countries'); /* @var $countries array */
$countries = $locale->getText('countries'); /* @var $countries array */
foreach ($list as $code => $name) {
if (\array_key_exists($code, $countries)) {
@ -132,8 +135,7 @@ App::get('/v1/locale/countries/phones')
\asort($list);
$response->json($list);
}
);
}, ['response', 'locale']);
App::get('/v1/locale/continents')
->desc('List Continents')
@ -143,15 +145,16 @@ App::get('/v1/locale/continents')
->label('sdk.namespace', 'locale')
->label('sdk.method', 'getContinents')
->label('sdk.description', '/docs/references/locale/get-continents.md')
->action(
function () use ($response) {
$list = Locale::getText('continents'); /* @var $list array */
->action(function ($response, $locale) {
/** @var Utopia\Response $response */
/** @var Utopia\Locale\Locale $locale */
$list = $locale->getText('continents'); /* @var $list array */
\asort($list);
$response->json($list);
}
);
}, ['response', 'locale']);
App::get('/v1/locale/currencies')
@ -162,13 +165,13 @@ App::get('/v1/locale/currencies')
->label('sdk.namespace', 'locale')
->label('sdk.method', 'getCurrencies')
->label('sdk.description', '/docs/references/locale/get-currencies.md')
->action(
function () use ($response) {
->action(function ($response) {
/** @var Utopia\Response $response */
$currencies = include __DIR__.'/../../config/currencies.php';
$response->json($currencies);
}
);
}, ['response']);
App::get('/v1/locale/languages')
@ -179,10 +182,10 @@ App::get('/v1/locale/languages')
->label('sdk.namespace', 'locale')
->label('sdk.method', 'getLanguages')
->label('sdk.description', '/docs/references/locale/get-languages.md')
->action(
function () use ($response) {
->action(function ($response) {
/** @var Utopia\Response $response */
$languages = include __DIR__.'/../../config/languages.php';
$response->json($languages);
}
);
}, ['response']);

View file

@ -1,7 +1,5 @@
<?php
global $response, $register, $user, $consoleDB, $projectDB, $deletes;
use Utopia\App;
use Utopia\Exception;
use Utopia\Response;

View file

@ -1,7 +1,5 @@
<?php
global $request, $response, $user, $audit, $usage, $project, $projectDB;
use Utopia\App;
use Utopia\Exception;
use Utopia\Response;
@ -23,48 +21,7 @@ use Appwrite\Storage\Validator\Upload;
use Appwrite\Storage\Compression\Algorithms\GZIP;
use Appwrite\Resize\Resize;
use Appwrite\OpenSSL\OpenSSL;
$fileLogos = [ // Based on this list @see http://stackoverflow.com/a/4212908/2299554
'default' => __DIR__.'/../../config/files/none.png',
// Video Files
'video/mp4' => __DIR__.'/../../config/files/video.png',
'video/x-flv' => __DIR__.'/../../config/files/video.png',
'application/x-mpegURL' => __DIR__.'/../../config/files/video.png',
'video/MP2T' => __DIR__.'/../../config/files/video.png',
'video/3gpp' => __DIR__.'/../../config/files/video.png',
'video/quicktime' => __DIR__.'/../../config/files/video.png',
'video/x-msvideo' => __DIR__.'/../../config/files/video.png',
'video/x-ms-wmv' => __DIR__.'/../../config/files/video.png',
// // Microsoft Word
'application/msword' => __DIR__.'/../../config/files/word.png',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => __DIR__.'/../../config/files/word.png',
'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => __DIR__.'/../../config/files/word.png',
'application/vnd.ms-word.document.macroEnabled.12' => __DIR__.'/../../config/files/word.png',
// // Microsoft Excel
'application/vnd.ms-excel' => __DIR__.'/../../config/files/excel.png',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => __DIR__.'/../../config/files/excel.png',
'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => __DIR__.'/../../config/files/excel.png',
'application/vnd.ms-excel.sheet.macroEnabled.12' => __DIR__.'/../../config/files/excel.png',
'application/vnd.ms-excel.template.macroEnabled.12' => __DIR__.'/../../config/files/excel.png',
'application/vnd.ms-excel.addin.macroEnabled.12' => __DIR__.'/../../config/files/excel.png',
'application/vnd.ms-excel.sheet.binary.macroEnabled.12' => __DIR__.'/../../config/files/excel.png',
// // Microsoft Power Point
'application/vnd.ms-powerpoint' => __DIR__.'/../../config/files/ppt.png',
'application/vnd.openxmlformats-officedocument.presentationml.presentation' => __DIR__.'/../../config/files/ppt.png',
'application/vnd.openxmlformats-officedocument.presentationml.template' => __DIR__.'/../../config/files/ppt.png',
'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => __DIR__.'/../../config/files/ppt.png',
'application/vnd.ms-powerpoint.addin.macroEnabled.12' => __DIR__.'/../../config/files/ppt.png',
'application/vnd.ms-powerpoint.presentation.macroEnabled.12' => __DIR__.'/../../config/files/ppt.png',
'application/vnd.ms-powerpoint.template.macroEnabled.12' => __DIR__.'/../../config/files/ppt.png',
'application/vnd.ms-powerpoint.slideshow.macroEnabled.12' => __DIR__.'/../../config/files/ppt.png',
// Adobe PDF
'application/pdf' => __DIR__.'/../../config/files/pdf.png',
];
use Utopia\Config\Config;
$inputs = [
'jpg' => 'image/jpeg',
@ -81,58 +38,9 @@ $outputs = [
'webp' => 'image/webp',
];
$mimes = [
'image/jpeg',
'image/jpeg',
'image/gif',
'image/png',
'image/webp',
// Video Files
'video/mp4',
'video/x-flv',
'application/x-mpegURL',
'video/MP2T',
'video/3gpp',
'video/quicktime',
'video/x-msvideo',
'video/x-ms-wmv',
// Microsoft Word
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
'application/vnd.ms-word.document.macroEnabled.12',
// Microsoft Excel
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
'application/vnd.ms-excel.sheet.macroEnabled.12',
'application/vnd.ms-excel.template.macroEnabled.12',
'application/vnd.ms-excel.addin.macroEnabled.12',
'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
// Microsoft Power Point
'application/vnd.ms-powerpoint',
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'application/vnd.openxmlformats-officedocument.presentationml.template',
'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
'application/vnd.ms-powerpoint.addin.macroEnabled.12',
'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
'application/vnd.ms-powerpoint.template.macroEnabled.12',
'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
// Microsoft Access
'application/vnd.ms-access',
// Adobe PDF
'application/pdf',
];
App::init(function () use ($project) {
App::init(function ($project) {
Storage::addDevice('local', new Local(APP_STORAGE_UPLOADS.'/app-'.$project->getId()));
}, 'storage');
}, ['project'], 'storage');
App::post('/v1/storage/files')
->desc('Create File')
@ -148,9 +56,15 @@ App::post('/v1/storage/files')
->param('file', [], function () { return new File(); }, 'Binary File.', false)
->param('read', [], function () { return new ArrayList(new Text(64)); }, 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
->param('write', [], function () { return new ArrayList(new Text(64)); }, 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
// ->param('folderId', '', function () { return new UID(); }, 'Folder to associate files with.', true)
->action(
function ($file, $read, $write, $folderId = '') use ($request, $response, $user, $projectDB, $webhook, $audit, $usage) {
->action(function ($file, $read, $write, $request, $response, $user, $projectDB, $webhook, $audit, $usage) {
/** @var Utopia\Request $request */
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $user */
/** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $webhook */
/** @var Appwrite\Event\Event $audit */
/** @var Appwrite\Event\Event $usage */
$file = $request->getFiles('file');
$read = (empty($read)) ? ['user:'.$user->getId()] : $read;
$write = (empty($write)) ? ['user:'.$user->getId()] : $write;
@ -231,7 +145,7 @@ App::post('/v1/storage/files')
'write' => $write,
],
'dateCreated' => \time(),
'folderId' => $folderId,
'folderId' => '',
'name' => $file['name'],
'path' => $path,
'signature' => $device->getFileHash($path),
@ -268,8 +182,7 @@ App::post('/v1/storage/files')
->setStatusCode(Response::STATUS_CODE_CREATED)
->json($file->getArrayCopy())
;
}
);
}, ['request', 'response', 'user', 'projectDB', 'webhook', 'audit', 'usage']);
App::get('/v1/storage/files')
->desc('List Files')
@ -283,8 +196,10 @@ App::get('/v1/storage/files')
->param('limit', 25, function () { return new Range(0, 100); }, 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
->param('offset', 0, function () { return new Range(0, 2000); }, 'Results offset. The default value is 0. Use this param to manage pagination.', true)
->param('orderType', 'ASC', function () { return new WhiteList(['ASC', 'DESC']); }, 'Order result by ASC or DESC order.', true)
->action(
function ($search, $limit, $offset, $orderType) use ($response, $projectDB) {
->action(function ($search, $limit, $offset, $orderType, $response, $projectDB) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Database $projectDB */
$results = $projectDB->getCollection([
'limit' => $limit,
'offset' => $offset,
@ -302,8 +217,7 @@ App::get('/v1/storage/files')
}, $results);
$response->json(['sum' => $projectDB->getSum(), 'files' => $results]);
}
);
}, ['response', 'projectDB']);
App::get('/v1/storage/files/:fileId')
->desc('Get File')
@ -314,8 +228,10 @@ App::get('/v1/storage/files/:fileId')
->label('sdk.method', 'getFile')
->label('sdk.description', '/docs/references/storage/get-file.md')
->param('fileId', '', function () { return new UID(); }, 'File unique ID.')
->action(
function ($fileId) use ($response, $projectDB) {
->action(function ($fileId, $response, $projectDB) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Database $projectDB */
$file = $projectDB->getDocument($fileId);
if (empty($file->getId()) || Database::SYSTEM_COLLECTION_FILES != $file->getCollection()) {
@ -323,8 +239,7 @@ App::get('/v1/storage/files/:fileId')
}
$response->json($file->getArrayCopy(['$id', '$permissions', 'name', 'dateCreated', 'signature', 'mimeType', 'sizeOriginal']));
}
);
}, ['response', 'projectDB']);
App::get('/v1/storage/files/:fileId/preview')
->desc('Get File Preview')
@ -343,7 +258,7 @@ App::get('/v1/storage/files/:fileId/preview')
->param('background', '', function () { return new HexColor(); }, 'Preview image background color. Only works with transparent images (png). Use a valid HEX color, no # is needed for prefix.', true)
->param('output', null, function () use ($outputs) { return new WhiteList(\array_merge(\array_keys($outputs), [null])); }, 'Output format type (jpeg, jpg, png, gif and webp).', true)
->action(
function ($fileId, $width, $height, $quality, $background, $output) use ($request, $response, $projectDB, $project, $inputs, $outputs, $fileLogos) {
function ($fileId, $width, $height, $quality, $background, $output) use ($request, $response, $projectDB, $project, $inputs, $outputs) {
$storage = 'local';
if (!\extension_loaded('imagick')) {
@ -372,6 +287,7 @@ App::get('/v1/storage/files/:fileId/preview')
$algorithm = $file->getAttribute('algorithm');
$cipher = $file->getAttribute('fileOpenSSLCipher');
$mime = $file->getAttribute('mimeType');
$fileLogos = Config::getParam('storage-logos');
if (!\in_array($mime, $inputs)) {
$path = (\array_key_exists($mime, $fileLogos)) ? $fileLogos[$mime] : $fileLogos['default'];
@ -516,8 +432,9 @@ App::get('/v1/storage/files/:fileId/view')
->param('fileId', '', function () { return new UID(); }, 'File unique ID.')
->param('as', '', function () { return new WhiteList(['pdf', /*'html',*/ 'text']); }, 'Choose a file format to convert your file to. Currently you can only convert word and pdf files to pdf or txt. This option is currently experimental only, use at your own risk.', true)
->action(
function ($fileId, $as) use ($response, $projectDB, $mimes) {
function ($fileId, $as) use ($response, $projectDB) {
$file = $projectDB->getDocument($fileId);
$mimes = Config::getParam('storage-mimes');
if (empty($file->getId()) || Database::SYSTEM_COLLECTION_FILES != $file->getCollection()) {
throw new Exception('File not found', 404);

View file

@ -1,7 +1,5 @@
<?php
global $request, $response, $projectDB, $project, $user, $audit, $mail, $mode, $clients;
use Utopia\App;
use Utopia\Exception;
use Utopia\Response;

View file

@ -1,7 +1,5 @@
<?php
global $response, $projectDB;
use Utopia\App;
use Utopia\Exception;
use Utopia\Response;

View file

@ -10,8 +10,6 @@ use Utopia\Validator\ArrayList;
use Utopia\Validator\Host;
use Appwrite\Storage\Validator\File;
$result = [];
App::get('/v1/mock/tests/foo')
->desc('Mock a get request for SDK tests')
->label('scope', 'public')
@ -335,7 +333,8 @@ App::get('/v1/mock/tests/general/oauth2/failure')
}
);
App::shutdown(function() use ($response, $request, &$result, $utopia) {
App::shutdown(function($response, $request, $utopia) {
$result = [];
$route = $utopia->match($request);
$path = APP_STORAGE_CACHE.'/tests.json';
$tests = (\file_exists($path)) ? \json_decode(\file_get_contents($path), true) : [];
@ -353,4 +352,4 @@ App::shutdown(function() use ($response, $request, &$result, $utopia) {
}
$response->json(['result' => $route->getMethod() . ':' . $route->getURL() . ':passed']);
}, 'mock');
}, ['response', 'request', 'utopia'], 'mock');

View file

@ -7,7 +7,7 @@ use Utopia\Abuse\Adapters\TimeLimit;
global $utopia, $request, $response, $register, $user, $project;
App::init(function () use ($utopia, $request, $response, $register, $user, $project) {
App::init(function ($utopia, $request, $response, $register, $user, $project) {
$route = $utopia->match($request);
if (empty($project->getId()) && $route->getLabel('abuse-limit', 0) > 0) { // Abuse limit requires an active project scope
@ -47,4 +47,4 @@ App::init(function () use ($utopia, $request, $response, $register, $user, $proj
if ($abuse->check() && App::getEnv('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled') {
throw new Exception('Too many requests', 429);
}
}, 'api');
}, ['utopia', 'request', 'response', 'register', 'user', 'project'], 'api');

View file

@ -4,9 +4,7 @@ use Utopia\App;
use Utopia\View;
use Utopia\Config\Config;
$layout = new View(__DIR__.'/../../views/layouts/default.phtml');
App::init(function () use ($utopia, $response, $request, $layout) {
App::init(function ($utopia, $response, $request, $layout) {
/* AJAX check */
if (!empty($request->getQuery('version', ''))) {
@ -29,7 +27,6 @@ App::init(function () use ($utopia, $response, $request, $layout) {
;
$time = (60 * 60 * 24 * 45); // 45 days cache
$isDev = (\Utopia\App::MODE_TYPE_DEVELOPMENT == Config::getParam('env'));
$response
->addHeader('Cache-Control', 'public, max-age='.$time)
@ -40,7 +37,7 @@ App::init(function () use ($utopia, $response, $request, $layout) {
$scope = $route->getLabel('scope', '');
$layout
->setParam('version', Config::getParam('version'))
->setParam('isDev', $isDev)
->setParam('isDev', App::isDevelopment())
->setParam('class', $scope)
;
}, 'web');
}, ['utopia', 'response', 'request', 'layout'], 'web');

View file

@ -11,14 +11,19 @@ use Appwrite\Database\Validator\Authorization;
use Appwrite\Database\Validator\UID;
use Appwrite\Storage\Storage;
App::init(function () use ($layout) {
App::init(function ($layout) {
/** @var Utopia\View $layout */
$layout
->setParam('description', 'Appwrite Console allows you to easily manage, monitor, and control your entire backend API and tools.')
->setParam('analytics', 'UA-26264668-5')
;
}, 'console');
}, ['layout'], 'console');
App::shutdown(function ($response, $layout) {
/** @var Utopia\Response $response */
/** @var Utopia\View $layout */
App::shutdown(function () use ($response, $layout) {
$header = new View(__DIR__.'/../../views/console/comps/header.phtml');
$footer = new View(__DIR__.'/../../views/console/comps/footer.phtml');
@ -33,14 +38,16 @@ App::shutdown(function () use ($response, $layout) {
;
$response->send($layout->render());
}, 'console');
}, ['response', 'layout'], 'console');
App::get('/error/:code')
->groups(['web', 'console'])
->label('permission', 'public')
->label('scope', 'home')
->param('code', null, new \Utopia\Validator\Numeric(), 'Valid status code number', false)
->action(function ($code) use ($layout) {
->action(function ($code, $layout) {
/** @var Utopia\View $layout */
$page = new View(__DIR__.'/../../views/error.phtml');
$page
@ -50,13 +57,15 @@ App::get('/error/:code')
$layout
->setParam('title', APP_NAME.' - Error')
->setParam('body', $page);
});
}, ['layout']);
App::get('/console')
->groups(['web', 'console'])
->label('permission', 'public')
->label('scope', 'console')
->action(function () use ($layout) {
->action(function ($layout) {
/** @var Utopia\View $layout */
$page = new View(__DIR__.'/../../views/console/index.phtml');
$page
@ -66,13 +75,15 @@ App::get('/console')
$layout
->setParam('title', APP_NAME.' - Console')
->setParam('body', $page);
});
}, ['layout']);
App::get('/console/account')
->groups(['web', 'console'])
->label('permission', 'public')
->label('scope', 'console')
->action(function () use ($layout) {
->action(function ($layout) {
/** @var Utopia\View $layout */
$page = new View(__DIR__.'/../../views/console/account/index.phtml');
$cc = new View(__DIR__.'/../../views/console/forms/credit-card.phtml');
@ -84,37 +95,43 @@ App::get('/console/account')
$layout
->setParam('title', 'Account - '.APP_NAME)
->setParam('body', $page);
});
}, ['layout']);
App::get('/console/notifications')
->groups(['web', 'console'])
->label('permission', 'public')
->label('scope', 'console')
->action(function () use ($layout) {
->action(function ($layout) {
/** @var Utopia\View $layout */
$page = new View(__DIR__.'/../../views/v1/console/notifications/index.phtml');
$layout
->setParam('title', APP_NAME.' - Notifications')
->setParam('body', $page);
});
}, ['layout']);
App::get('/console/home')
->groups(['web', 'console'])
->label('permission', 'public')
->label('scope', 'console')
->action(function () use ($layout) {
->action(function ($layout) {
/** @var Utopia\View $layout */
$page = new View(__DIR__.'/../../views/console/home/index.phtml');
$layout
->setParam('title', APP_NAME.' - Console')
->setParam('body', $page);
});
}, ['layout']);
App::get('/console/settings')
->groups(['web', 'console'])
->label('permission', 'public')
->label('scope', 'console')
->action(function () use ($layout) {
->action(function ($layout) {
/** @var Utopia\View $layout */
$target = new Domain(App::getEnv('_APP_DOMAIN_TARGET', ''));
$page = new View(__DIR__.'/../../views/console/settings/index.phtml');
@ -127,13 +144,15 @@ App::get('/console/settings')
$layout
->setParam('title', APP_NAME.' - Settings')
->setParam('body', $page);
});
}, ['layout']);
App::get('/console/webhooks')
->groups(['web', 'console'])
->label('permission', 'public')
->label('scope', 'console')
->action(function () use ($layout) {
->action(function ($layout) {
/** @var Utopia\View $layout */
$page = new View(__DIR__.'/../../views/console/webhooks/index.phtml');
$page
@ -143,13 +162,15 @@ App::get('/console/webhooks')
$layout
->setParam('title', APP_NAME.' - Webhooks')
->setParam('body', $page);
});
}, ['layout']);
App::get('/console/keys')
->groups(['web', 'console'])
->label('permission', 'public')
->label('scope', 'console')
->action(function () use ($layout) {
->action(function ($layout) {
/** @var Utopia\View $layout */
$scopes = include __DIR__.'/../../../app/config/scopes.php';
$page = new View(__DIR__.'/../../views/console/keys/index.phtml');
@ -158,38 +179,46 @@ App::get('/console/keys')
$layout
->setParam('title', APP_NAME.' - API Keys')
->setParam('body', $page);
});
}, ['layout']);
App::get('/console/tasks')
->groups(['web', 'console'])
->label('permission', 'public')
->label('scope', 'console')
->action(function () use ($layout) {
->action(function ($layout) {
/** @var Utopia\View $layout */
$page = new View(__DIR__.'/../../views/console/tasks/index.phtml');
$layout
->setParam('title', APP_NAME.' - Tasks')
->setParam('body', $page);
});
}, ['layout']);
App::get('/console/database')
->groups(['web', 'console'])
->label('permission', 'public')
->label('scope', 'console')
->action(function () use ($layout) {
->action(function ($layout) {
/** @var Utopia\View $layout */
$page = new View(__DIR__.'/../../views/console/database/index.phtml');
$layout
->setParam('title', APP_NAME.' - Database')
->setParam('body', $page);
});
}, ['layout']);
App::get('/console/database/collection')
->groups(['web', 'console'])
->label('permission', 'public')
->label('scope', 'console')
->param('id', '', function () { return new UID(); }, 'Collection unique ID.')
->action(function ($id) use ($response, $layout, $projectDB) {
->action(function ($id, $response, $layout, $projectDB) {
/** @var Utopia\Response $response */
/** @var Utopia\View $layout */
/** @var Appwrite\Database\Database $projectDB */
Authorization::disable();
$collection = $projectDB->getDocument($id, false);
Authorization::reset();
@ -214,14 +243,17 @@ App::get('/console/database/collection')
->addHeader('Expires', 0)
->addHeader('Pragma', 'no-cache')
;
});
}, ['response', 'layout', 'projectDB']);
App::get('/console/database/document')
->groups(['web', 'console'])
->label('permission', 'public')
->label('scope', 'console')
->param('collection', '', function () { return new UID(); }, 'Collection unique ID.')
->action(function ($collection) use ($layout, $projectDB) {
->action(function ($collection, $layout, $projectDB) {
/** @var Utopia\View $layout */
/** @var Appwrite\Database\Database $projectDB */
Authorization::disable();
$collection = $projectDB->getDocument($collection, false);
Authorization::reset();
@ -244,13 +276,14 @@ App::get('/console/database/document')
$layout
->setParam('title', APP_NAME.' - Database Document')
->setParam('body', $page);
});
}, ['layout', 'projectDB']);
App::get('/console/storage')
->groups(['web', 'console'])
->label('permission', 'public')
->label('scope', 'console')
->action(function () use ($request, $layout) {
->action(function ($layout) {
/** @var Utopia\View $layout */
$page = new View(__DIR__.'/../../views/console/storage/index.phtml');
$page
@ -262,13 +295,15 @@ App::get('/console/storage')
$layout
->setParam('title', APP_NAME.' - Storage')
->setParam('body', $page);
});
}, ['layout']);
App::get('/console/users')
->groups(['web', 'console'])
->label('permission', 'public')
->label('scope', 'console')
->action(function () use ($layout) {
->action(function ($layout) {
/** @var Utopia\View $layout */
$page = new View(__DIR__.'/../../views/console/users/index.phtml');
$page->setParam('providers', Config::getParam('providers'));
@ -276,28 +311,32 @@ App::get('/console/users')
$layout
->setParam('title', APP_NAME.' - Users')
->setParam('body', $page);
});
}, ['layout']);
App::get('/console/users/user')
->groups(['web', 'console'])
->label('permission', 'public')
->label('scope', 'console')
->action(function () use ($layout) {
->action(function ($layout) {
/** @var Utopia\View $layout */
$page = new View(__DIR__.'/../../views/console/users/user.phtml');
$layout
->setParam('title', APP_NAME.' - User')
->setParam('body', $page);
});
}, ['layout']);
App::get('/console/users/teams/team')
->groups(['web', 'console'])
->label('permission', 'public')
->label('scope', 'console')
->action(function () use ($layout) {
/** @var Utopia\View $layout */
$page = new View(__DIR__.'/../../views/console/users/team.phtml');
$layout
->setParam('title', APP_NAME.' - Team')
->setParam('body', $page);
});
}, ['layout']);

View file

@ -8,7 +8,7 @@ use Utopia\Config\Config;
use Utopia\Validator\WhiteList;
use Utopia\Validator\Range;
App::init(function () use ($layout) {
App::init(function ($layout) {
$header = new View(__DIR__.'/../../views/home/comps/header.phtml');
$footer = new View(__DIR__.'/../../views/home/comps/footer.phtml');
@ -24,11 +24,11 @@ App::init(function () use ($layout) {
->setParam('header', [$header])
->setParam('footer', [$footer])
;
}, 'home');
}, ['layout'], 'home');
App::shutdown(function () use ($response, $layout) {
App::shutdown(function ($response, $layout) {
$response->send($layout->render());
}, 'home');
}, ['response', 'layout'], 'home');
App::get('/')
->groups(['web', 'home'])

View file

@ -60,6 +60,8 @@ Config::load('services', __DIR__.'/../app/config/services.php'); // List of ser
Config::load('avatar-browsers', __DIR__.'/../app/config/avatars/browsers.php');
Config::load('avatar-credit-cards', __DIR__.'/../app/config/avatars/credit-cards.php');
Config::load('avatar-flags', __DIR__.'/../app/config/avatars/flags.php');
Config::load('storage-logos', __DIR__.'/../app/config/storage/logos.php');
Config::load('storage-mimes', __DIR__.'/../app/config/storage/mimes.php');
Resque::setBackend(App::getEnv('_APP_REDIS_HOST', '')
.':'.App::getEnv('_APP_REDIS_PORT', ''));
@ -141,10 +143,10 @@ $register->set('smtp', function () {
return $mail;
});
$register->set('queue-webhooks', function () {
$register->set('queue-webhook', function () {
return new Event('v1-webhooks', 'WebhooksV1');
});
$register->set('queue-audits', function () {
$register->set('queue-audit', function () {
return new Event('v1-audits', 'AuditsV1');
});
$register->set('queue-usage', function () {
@ -208,8 +210,6 @@ Locale::setLanguage('vi', include __DIR__.'/config/locales/vi.php');
Locale::setLanguage('zh-cn', include __DIR__.'/config/locales/zh-cn.php');
Locale::setLanguage('zh-tw', include __DIR__.'/config/locales/zh-tw.php');
Locale::setDefault('en');
\stream_context_set_default([ // Set global user agent and http settings
'http' => [
'method' => 'GET',

View file

@ -11,6 +11,7 @@ $litespeed = $this->getParam('litespeed', true);
$analytics = $this->getParam('analytics', 'UA-26264668-9');
$env = $this->getParam('env', '');
$canonical = $this->getParam('canonical', '');
$locale = $this->getParam('locale', null);
if(!empty($platforms)) {
$platforms = array_map(function($platform) {
@ -30,14 +31,14 @@ if(!empty($platforms)) {
}
?><!DOCTYPE html><!--
<?php echo Locale::getText('settings.inspire'); ?>
<?php echo $locale->getText('settings.inspire'); ?>
--><html lang="<?php echo Locale::getText('settings.locale'); ?>" class="<?php echo $this->getParam('class', 'none'); ?> <?php echo $env; ?>">
--><html lang="<?php echo $locale->getText('settings.locale'); ?>" class="<?php echo $this->getParam('class', 'none'); ?> <?php echo $env; ?>">
<head>
<link rel="manifest" href="/manifest.json">
<title><?php echo $this->getParam('title', ''); ?></title>
<meta name="description" content="<?php echo $this->getParam('description', ''); ?>" />
<link rel="stylesheet" media="all" type="text/css" href="/dist/styles/default-<?php echo Locale::getText('settings.direction'); ?>.css?v=<?php echo APP_CACHE_BUSTER; ?>.<?php echo $version; ?>" />
<link rel="stylesheet" media="all" type="text/css" href="/dist/styles/default-<?php echo $locale->getText('settings.direction'); ?>.css?v=<?php echo APP_CACHE_BUSTER; ?>.<?php echo $version; ?>" />
<link rel="icon" type="image/png" href="<?php echo $this->escape($this->getParam('icon', '')); ?>?v=<?php echo APP_CACHE_BUSTER; ?>" />
<link rel="apple-touch-icon" href="/images/apple.png">
<!-- <link rel="preconnect" href="" /> -->
@ -76,7 +77,7 @@ if(!empty($platforms)) {
API: '/v1',
PROJECT: 'console',
PLATFORMS: <?php echo json_encode($platforms); ?>,
LOCALE: '<?php echo $this->escape(Locale::getText('settings.locale')); ?>',
LOCALE: '<?php echo $this->escape($locale->getText('settings.locale')); ?>',
PREFIX: '<?php echo $this->escape($this->getParam('prefix')); ?>',
ROLES: <?PHP echo json_encode($this->getParam('roles', [])); ?>,
PAGING_LIMIT: <?PHP echo APP_PAGING_LIMIT; ?>

View file

@ -14,5 +14,6 @@ ini_set('display_errors', 0);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
trigger_error('hide errors in prod', E_USER_NOTICE);
include __DIR__ . '/../app/app.php';