1
0
Fork 0
mirror of synced 2024-06-28 11:10:46 +12:00

Merge branch 'master' into ro-locale

This commit is contained in:
Bogdan Covrig 2019-10-01 06:00:35 +02:00 committed by GitHub
commit 1c322a413c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
94 changed files with 2730 additions and 624 deletions

3
.gitignore vendored
View file

@ -3,4 +3,5 @@
/storage/uploads/
/tests/resources/storage/
/.idea/
.DS_Store
.DS_Store
.php_cs.cache

View file

@ -1,5 +0,0 @@
Version 1.0.0 (NOT-RELEASED)
-------------
Version 0.1.0 (PRE-RELEASE)
-------------

23
CHANGES.md Normal file
View file

@ -0,0 +1,23 @@
# Version 0.2.0 (PRE-RELEASE)
## Features
* Added option to limit access to the Appwrite console
* Added option to disable abuse check and rate limits
* Added input field with the server API endpoint for easy access
* Added new OAuth providers for Google and Gitlab
* Added 8 new locales for locale service and email templates (no, pt-br, es, ua, ru, id, fi, cat)
* Improved test coverage for the project and synced DEV & CI environments settings
## Bug Fixes
* Fixed bug not allowing to update OAuth providers settings
* Fixed some broken API examples in docs
* Fixed bug that caused the Appwrite container to change DB directory file permissions.
## Breaking Changes
* Changed auth service 'redirect' param to 'confirm' for better clarity
* Updated all SDKs to sync with API changes
# Version 0.1.15 (NOT-RELEASED)

View file

@ -36,7 +36,7 @@ Appwrite uses PHPs Composer for managing dependencies on the server-side and JS
Appwrite is following the PHP-FIG standards. Currently, we are using both PSR-0 and PSR-4 for coding standards and autoloading standards. Soon we will also review the project for support with PSR-12 (Extended Coding Style).
We use prettier for our JS coding standards and for auto-formmating our code.
We use prettier for our JS coding standards and for auto-formatting our code.
## Scalability, Speed and Performance
@ -83,9 +83,9 @@ Adding a new dependency should have vital value on the product with minimum poss
## Introducing New Features
We whould 💖 you to contribute to Appwrite, but we whould also like to make sure Appwrite is as great as possible and loyal to its vision and mission statement 🙏.
We would 💖 you to contribute to Appwrite, but we would also like to make sure Appwrite is as great as possible and loyal to its vision and mission statement 🙏.
For us to find the right balance, please open an issue explaining your ideas before intoducing a new pull requests.
For us to find the right balance, please open an issue explaining your ideas before introducing a new pull requests.
This will allow the Appwrite community to have sufficient discussion about the new feature value and how it fits in the product roadmap and vision.
@ -121,6 +121,6 @@ Before running the command make sure you have proper write permissions to Appwri
## Tutorials
From time to time our team will add tutorials that will help contributers find there way in the Appwrite source code. Below is a list of currently available tutorials:
From time to time our team will add tutorials that will help contributors find there way in the Appwrite source code. Below is a list of currently available tutorials:
* [Adding Support for a New OAuth Provider](./docs/AddOAuthProvider.md)

View file

@ -16,7 +16,7 @@
Appwrite is a simple self-hosted backend server for web and mobile developers with a shiny dashboard and a very easy to use REST API.
Appwrite API services aims to make developers life a lot easier by hiding the complexity of common and repetitve software development tasks.
Appwrite API services aims to make developers life a lot easier by hiding the complexity of common and repetitive software development tasks.
Using Appwrite you can easily manage user authentication with multiple sign-in methods, database for storing and querying user and teams data, storage and file management, image manipulation and cropping, scheduled cron tasks and many other features to help you get more results in faster times and with a lot less code.
@ -39,7 +39,7 @@ docker-compose up -d --remove-orphans
Once the Docker installation completes, go to http://localhost to access the Appwrite console from your browser. Please notice that on non-linux native hosts the server might take a few minutes to start after installation completes.
For advanced, production and custon installation check out our Docker [enviornemnt variables](/docs/EnviornementVariables.md) docs.
For advanced, production and custom installation check out our Docker [environment variables](/docs/EnviornementVariables.md) docs.
### Changing Port Number
@ -98,6 +98,15 @@ We really ❤️ pull requests! If you wish to help, you can learn more about ho
Created by [Eldad Fux](https://twitter.com/eldadfux) with the amazing help of our **amazing contributors:**
* 🇺🇸Justin Dorfman ([Github](https://github.com/@jdorfman), [Twitter](https://twitter.com/jdorfman))
* 🇺🇳0xflotus ([Github](https://github.com/0xflotus))
* 🇳🇴Chaaarles ([Github](https://github.com/Chaaarles))
* 🇺🇸 Justin Dorfman ([Github](https://github.com/jdorfman), [Twitter](https://twitter.com/jdorfman))
* 🇺🇳 0xflotus ([Github](https://github.com/0xflotus))
* 🇳🇴 Petter Charles Redfern ([Github](https://github.com/Chaaarles))
* 🇧🇷 Jessé Souza ([Github](https://github.com/jessescn))
* 🇪🇸 Esther Álvarez Feijoo ([Github](https://github.com/EstherAF))
* 🇮🇳 Christy Jacob ([Github](https://github.com/christyjacob4), [Linkedin](https://www.linkedin.com/in/christyjacob4/))
* 🇺🇦 Dmitriy Danilov ([Github](https://github.com/daniloff200), [Twitter](https://twitter.com/daniloff200))
* 🇮🇩 Zeet ([Github](https://github.com/Kiy4h))
* 🇫🇮 Pessi Päivärinne ([Github](https://github.com/pessip))
* 🇺🇳 Sergi Vos ([Github](https://github.com/sergivb01), [Twitter](https://twitter.com/sergivb01), [Linkedin](https://www.linkedin.com/in/sergivb01/))
* 🇮🇱 Tomer Cohen ([Github](https://github.com/tomer), [Twitter](https://twitter.com/tomer))
* 🇬🇷 Panagiotis Skarlas ([Github](https://github.com/1qk1), [Twitter](https://twitter.com/qktweets))

View file

@ -31,26 +31,25 @@ $webhook = new Event('v1-webhooks', 'WebhooksV1');
$audit = new Event('v1-audits', 'AuditsV1');
$usage = new Event('v1-usage', 'UsageV1');
$clientsConsole = array_map(function($node) {
$clientsConsole = array_map(function ($node) {
return $node['url'];
}, array_filter($console->getAttribute('platforms', []), function($node) {
if(isset($node['type']) && $node['type'] === 'web' && isset($node['url']) && !empty($node['url'])) {
}, array_filter($console->getAttribute('platforms', []), function ($node) {
if (isset($node['type']) && $node['type'] === 'web' && isset($node['url']) && !empty($node['url'])) {
return true;
}
return false;
}));
$clients = array_merge($clientsConsole, array_map(function($node) {
$clients = array_merge($clientsConsole, array_map(function ($node) {
return $node['url'];
}, array_filter($project->getAttribute('platforms', []), function($node) {
if(isset($node['type']) && $node['type'] === 'web' && isset($node['url']) && !empty($node['url'])) {
}, array_filter($project->getAttribute('platforms', []), function ($node) {
if (isset($node['type']) && $node['type'] === 'web' && isset($node['url']) && !empty($node['url'])) {
return true;
}
return false;
})));
$utopia->init(function() use ($utopia, $request, $response, $register, &$user, $project, $roles, $webhook, $audit, $usage, $domain, $clients) {
$utopia->init(function () use ($utopia, $request, $response, $register, &$user, $project, $roles, $webhook, $audit, $usage, $domain, $clients) {
$route = $utopia->match($request);
$referrer = $request->getServer('HTTP_REFERER', '');
@ -82,7 +81,7 @@ $utopia->init(function() use ($utopia, $request, $response, $register, &$user, $
*/
$hostValidator = new Host($clients);
if(!$hostValidator->isValid($request->getServer('HTTP_ORIGIN', $request->getServer('HTTP_REFERER', '')))
if (!$hostValidator->isValid($request->getServer('HTTP_ORIGIN', $request->getServer('HTTP_REFERER', '')))
&& in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH, Request::METHOD_DELETE])
&& empty($request->getHeader('X-Appwrite-Key', ''))) {
throw new Exception('Access from this client host is forbidden. ' . $hostValidator->getDescription(), 403);
@ -96,7 +95,7 @@ $utopia->init(function() use ($utopia, $request, $response, $register, &$user, $
// Add user roles
$membership = $user->search('teamId', $project->getAttribute('teamId', null), $user->getAttribute('memberships', []));
if($membership) {
if ($membership) {
foreach ($membership->getAttribute('roles', []) as $memberRole) {
switch ($memberRole) {
case 'owner':
@ -122,7 +121,7 @@ $utopia->init(function() use ($utopia, $request, $response, $register, &$user, $
* Try app auth when we have project key and no user
* Mock user to app and grant API key scopes in addition to default app scopes
*/
if(null !== $key && $user->isEmpty()) {
if (null !== $key && $user->isEmpty()) {
$user = new Document([
'$uid' => 0,
'status' => Auth::USER_STATUS_ACTIVATED,
@ -141,7 +140,7 @@ $utopia->init(function() use ($utopia, $request, $response, $register, &$user, $
Authorization::setRole('role:' . $role);
array_map(function ($node) {
if(isset($node['teamId']) && isset($node['roles'])) {
if (isset($node['teamId']) && isset($node['roles'])) {
Authorization::setRole('team:' . $node['teamId']);
foreach ($node['roles'] as $nodeRole) { // Set all team roles
@ -150,15 +149,15 @@ $utopia->init(function() use ($utopia, $request, $response, $register, &$user, $
}
}, $user->getAttribute('memberships', []));
if(!in_array($scope, $scopes)) {
if (!in_array($scope, $scopes)) {
throw new Exception($user->getAttribute('email', 'Guest') . ' (role: ' . strtolower($roles[$role]['label']) . ') missing scope (' . $scope . ')', 401);
}
if(Auth::USER_STATUS_BLOCKED == $user->getAttribute('status')) { // Account has not been activated
if (Auth::USER_STATUS_BLOCKED == $user->getAttribute('status')) { // Account has not been activated
throw new Exception('Invalid credentials. User is blocked', 401); // User is in status blocked
}
if($user->getAttribute('reset')) {
if ($user->getAttribute('reset')) {
throw new Exception('Password reset is required', 412);
}
@ -193,7 +192,9 @@ $utopia->init(function() use ($utopia, $request, $response, $register, &$user, $
/**
* Abuse Check
*/
$timeLimit = new TimeLimit($route->getLabel('abuse-key', 'url:{url},ip:{ip}'), $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), function () use ($register) {return $register->get('db');});
$timeLimit = new TimeLimit($route->getLabel('abuse-key', 'url:{url},ip:{ip}'), $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), function () use ($register) {
return $register->get('db');
});
$timeLimit->setNamespace('app_' . $project->getUid());
$timeLimit
->setParam('{userId}', $user->getUid())
@ -204,13 +205,13 @@ $utopia->init(function() use ($utopia, $request, $response, $register, &$user, $
//TODO make sure we get array here
foreach($request->getParams() as $key => $value) { // Set request params as potential abuse keys
foreach ($request->getParams() as $key => $value) { // Set request params as potential abuse keys
$timeLimit->setParam('{param-' . $key . '}', (is_array($value)) ? json_encode($value) : $value);
}
$abuse = new Abuse($timeLimit);
if($timeLimit->limit()) {
if ($timeLimit->limit()) {
$response
->addHeader('X-RateLimit-Limit', $timeLimit->limit())
->addHeader('X-RateLimit-Remaining', $timeLimit->remaining())
@ -218,7 +219,7 @@ $utopia->init(function() use ($utopia, $request, $response, $register, &$user, $
;
}
if($abuse->check() && $request->getServer('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled') {
if ($abuse->check() && $request->getServer('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled') {
throw new Exception('Too many requests', 429);
}
});
@ -228,11 +229,11 @@ $utopia->shutdown(function () use ($response, $request, $webhook, $audit, $usage
/**
* Trigger Events for background jobs
*/
if(!empty($webhook->getParam('event'))) {
if (!empty($webhook->getParam('event'))) {
$webhook->trigger();
}
if(!empty($audit->getParam('event'))) {
if (!empty($audit->getParam('event'))) {
$audit->trigger();
}
@ -243,7 +244,7 @@ $utopia->shutdown(function () use ($response, $request, $webhook, $audit, $usage
;
});
$utopia->options(function() use ($request, $response, $domain, $project) {
$utopia->options(function () use ($request, $response, $domain, $project) {
$origin = $request->getServer('HTTP_ORIGIN');
$response
@ -255,8 +256,8 @@ $utopia->options(function() use ($request, $response, $domain, $project) {
;
});
$utopia->error(function($error /* @var $error Exception */) use ($request, $response, $utopia, $project, $env, $version, $sentry, $user) {
switch($error->getCode()) {
$utopia->error(function ($error /* @var $error Exception */) use ($request, $response, $utopia, $project, $env, $version, $sentry, $user) {
switch ($error->getCode()) {
case 400: // Error allowed publicly
case 401: // Error allowed publicly
case 402: // Error allowed publicly
@ -297,7 +298,7 @@ $utopia->error(function($error /* @var $error Exception */) use ($request, $resp
$route = $utopia->match($request);
$template = ($route) ? $route->getLabel('error', null): null;
if($template) {
if ($template) {
$layout = new View(__DIR__ . '/views/layouts/default.phtml');
$comp = new View($template);
@ -329,8 +330,7 @@ $utopia->get('/manifest.json')
->label('scope', 'public')
->label('docs', false)
->action(
function() use ($response) {
function () use ($response) {
$response->json([
'name' => APP_NAME,
'short_name' => APP_NAME,
@ -356,8 +356,7 @@ $utopia->get('/robots.txt')
->label('scope', 'public')
->label('docs', false)
->action(
function() use ($response) {
function () use ($response) {
$response->text("# robotstxt.org/
User-agent: *
@ -370,8 +369,7 @@ $utopia->get('/humans.txt')
->label('scope', 'public')
->label('docs', false)
->action(
function() use ($response) {
function () use ($response) {
$response->text("# humanstxt.org/
# The humans responsible & technology colophon
@ -387,7 +385,7 @@ $utopia->get('/v1/info') // This is only visible to gods
->label('scope', 'god')
->label('docs', false)
->action(
function() use ($response, $user, $project, $version, $env) { //TODO CONSIDER BLOCKING THIS ACTION TO ROLE GOD
function () use ($response, $user, $project, $version, $env) { //TODO CONSIDER BLOCKING THIS ACTION TO ROLE GOD
$response->json([
'name' => 'API',
'version' => $version,
@ -410,7 +408,7 @@ $utopia->get('/v1/xss')
->label('scope', 'public')
->label('docs', false)
->action(
function() {
function () {
throw new Exception('XSS detected and reported by a browser client', 500);
}
);
@ -419,7 +417,7 @@ $utopia->get('/v1/proxy')
->label('scope', 'public')
->label('docs', false)
->action(
function() use ($response, $console, $clients) {
function () use ($response, $console, $clients) {
$view = new View(__DIR__ . '/views/proxy.phtml');
$view
->setParam('routes', '')
@ -436,12 +434,16 @@ $utopia->get('/v1/proxy')
$utopia->get('/v1/open-api-2.json')
->label('scope', 'public')
->label('docs', false)
->param('platform', 'client' , function () {return new WhiteList(['client', 'server']);}, 'Choose target platform.', true)
->param('extensions', 0 , function () {return new Range(0, 1);}, 'Show extra data.', true)
->param('platform', 'client', function () {
return new WhiteList(['client', 'server']);
}, 'Choose target platform.', true)
->param('extensions', 0, function () {
return new Range(0, 1);
}, 'Show extra data.', true)
->action(
function($platform, $extensions) use ($response, $request, $utopia, $domain, $version, $services) {
function fromCamelCase($input) {
function ($platform, $extensions) use ($response, $request, $utopia, $domain, $version, $services) {
function fromCamelCase($input)
{
preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
$ret = $matches[0];
foreach ($ret as &$match) {
@ -450,12 +452,13 @@ $utopia->get('/v1/open-api-2.json')
return implode('_', $ret);
}
function fromCamelCaseToDash($input) {
function fromCamelCaseToDash($input)
{
return str_replace([' ', '_'], '-', strtolower(preg_replace('/([a-zA-Z])(?=[A-Z])/', '$1-', $input)));
}
foreach ($services as $service) { /** @noinspection PhpIncludeInspection */
if(!$service['sdk']) {
if (!$service['sdk']) {
continue;
}
@ -538,29 +541,29 @@ $utopia->get('/v1/open-api-2.json')
],
],
'Pets' =>
array (
array(
'type' => 'array',
'items' =>
array (
array(
'$ref' => '#/definitions/Pet',
),
),
'Error' =>
array (
array(
'required' =>
array (
array(
0 => 'code',
1 => 'message',
),
'properties' =>
array (
array(
'code' =>
array (
array(
'type' => 'integer',
'format' => 'int32',
),
'message' =>
array (
array(
'type' => 'string',
),
),
@ -574,11 +577,11 @@ $utopia->get('/v1/open-api-2.json')
foreach ($utopia->getRoutes() as $key => $method) {
foreach ($method as $route) { /* @var $route \Utopia\Route */
if(!$route->getLabel('docs', true)) {
if (!$route->getLabel('docs', true)) {
continue;
}
if(empty($route->getLabel('sdk.namespace', null))) {
if (empty($route->getLabel('sdk.namespace', null))) {
continue;
}
@ -587,7 +590,7 @@ $utopia->get('/v1/open-api-2.json')
$hide = $route->getLabel('sdk.hide', false);
$consumes = [];
if($hide) {
if ($hide) {
continue;
}
@ -607,15 +610,16 @@ $utopia->get('/v1/open-api-2.json')
],
];
if($extensions) {
if ($extensions) {
$temp['extensions'] = [
'weight' => $route->getOrder(),
'cookies' => $route->getLabel('sdk.cookies', false),
'location' => $route->getLabel('sdk.location', false),
'demo' => 'docs/examples/' . fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')) . '/' . fromCamelCaseToDash($temp['operationId']) . '.md',
];
}
if((!empty($scope) && 'public' != $scope)) {
if ((!empty($scope) && 'public' != $scope)) {
$temp['security'][] = $route->getLabel('sdk.security', $security[$platform]);
}
@ -708,24 +712,22 @@ $utopia->get('/v1/open-api-2.json')
break;
}
if($param['optional'] && !is_null($param['default'])) { // Param has default value
if ($param['optional'] && !is_null($param['default'])) { // Param has default value
$node['default'] = $param['default'];
}
if (false !== strpos($url, ':' . $name)) { // Param is in URL path
$node['in'] = 'path';
$temp['parameters'][] = $node;
}
elseif ($key == 'GET') { // Param is in query
} elseif ($key == 'GET') { // Param is in query
$node['in'] = 'query';
$temp['parameters'][] = $node;
}
else { // Param is in payload
} else { // Param is in payload
$node['in'] = 'formData';
$temp['parameters'][] = $node;
$requestBody['content']['application/x-www-form-urlencoded']['schema']['properties'][] = $node;
if(!$param['optional']) {
if (!$param['optional']) {
$requestBody['content']['application/x-www-form-urlencoded']['required'][] = $name;
}
}
@ -751,11 +753,10 @@ $utopia->get('/v1/open-api-2.json')
$name = APP_NAME;
if(array_key_exists($service, $services)) { /** @noinspection PhpIncludeInspection */
if (array_key_exists($service, $services)) { /** @noinspection PhpIncludeInspection */
include_once $services[$service]['controller'];
$name = APP_NAME . ' ' . ucfirst($services[$service]['name']);
}
else {
} else {
/** @noinspection PhpIncludeInspection */
include_once $services['/']['controller'];
}
@ -768,4 +769,4 @@ if (extension_loaded('newrelic')) {
newrelic_name_transaction($request->getServer('REQUEST_METHOD', 'UNKNOWN') . ': ' . $url);
}
$utopia->run($request, $response);
$utopia->run($request, $response);

View file

@ -1076,7 +1076,7 @@ foreach ($providers as $key => $provider) {
$collections[Database::SYSTEM_COLLECTION_PROJECTS]['rules'][] = [
'$collection' => Database::SYSTEM_COLLECTION_RULES,
'label' => 'OAuth '.ucfirst($key).' ID',
'key' => 'oauth'.ucfirst($key),
'key' => 'usersOauth'.ucfirst($key) . 'Appid',
'type' => 'text',
'default' => '',
'required' => false,
@ -1085,8 +1085,8 @@ foreach ($providers as $key => $provider) {
$collections[Database::SYSTEM_COLLECTION_PROJECTS]['rules'][] = [
'$collection' => Database::SYSTEM_COLLECTION_RULES,
'label' => 'OAuth '.ucfirst($key).' Access Token',
'key' => 'oauth'.ucfirst($key).'AccessToken',
'label' => 'OAuth '.ucfirst($key).' Secret',
'key' => 'usersOauth'.ucfirst($key).'Secret',
'type' => 'text',
'default' => '',
'required' => false,

View file

@ -0,0 +1,11 @@
<?php
return [
'AF' => 'África',
'AN' => 'Antártica',
'AS' => 'Asia',
'EU' => 'Europa',
'NA' => 'América del Norte',
'OC' => 'Oceanía',
'SA' => 'América del Sur',
];

View file

@ -0,0 +1,197 @@
<?php
return [
'AF' => 'Afganistán',
'AO' => 'Angola',
'AL' => 'Albania',
'AD' => 'Andorra',
'AE' => 'Emiratos Árabes Unidos',
'AR' => 'Argentina',
'AM' => 'Armenia',
'AG' => 'Antigua y Barbuda',
'AU' => 'Australia',
'AT' => 'Austria',
'AZ' => 'Azerbaiyán',
'BI' => 'Burundi',
'BE' => 'Bélgica',
'BJ' => 'Benin',
'BF' => 'Burkina Faso',
'BD' => 'Bangladesh',
'BG' => 'Bulgaria',
'BH' => 'Bahrein',
'BS' => 'Bahamas',
'BA' => 'Bosnia y Herzegovina',
'BY' => 'Bielorrusia',
'BZ' => 'Belice',
'BO' => 'Bolivia',
'BR' => 'Brasil',
'BB' => 'Barbados',
'BN' => 'Brunei',
'BT' => 'Bután',
'BW' => 'Botsuana',
'CF' => 'República Centroafricana',
'CA' => 'Canadá',
'CH' => 'Suiza',
'CL' => 'Chile',
'CN' => 'China',
'CI' => 'Costa de Marfil',
'CM' => 'Camerún',
'CD' => 'República Democrática del Congo',
'CG' => 'República del congo',
'CO' => 'Colombia',
'KM' => 'Comoras',
'CV' => 'Cabo Verde',
'CR' => 'Costa Rica',
'CU' => 'Cuba',
'CY' => 'Chipre',
'CZ' => 'Chequia',
'DE' => 'Alemania',
'DJ' => 'Yibuti',
'DM' => 'Dominica',
'DK' => 'Dinamarca',
'DO' => 'República Dominicana',
'DZ' => 'Argelia',
'EC' => 'Ecuador',
'EG' => 'Egipto',
'ER' => 'Eritrea',
'ES' => 'España',
'EE' => 'Estonia',
'ET' => 'Etiopía',
'FI' => 'Finlandia',
'FJ' => 'Fiyi',
'FR' => 'Francia',
'FM' => 'Micronesia',
'GA' => 'Gabón',
'GB' => 'Reino Unido',
'GE' => 'Georgia',
'GH' => 'Ghana',
'GN' => 'Guinea',
'GM' => 'Gambia',
'GW' => 'Guinea-Bissau',
'GQ' => 'Guinea Ecuatorial',
'GR' => 'Grecia',
'GD' => 'Granada',
'GT' => 'Guatemala',
'GY' => 'Guayana',
'HN' => 'Honduras',
'HR' => 'Croacia',
'HT' => 'Haití',
'HU' => 'Hungría',
'ID' => 'Indonesia',
'IN' => 'India',
'IE' => 'Irlanda',
'IR' => 'Iran',
'IQ' => 'Irak',
'IS' => 'Islandia',
'IL' => 'Israel',
'IT' => 'Italia',
'JM' => 'Jamaica',
'JO' => 'Jordán',
'JP' => 'Japón',
'KZ' => 'Kazajstán',
'KE' => 'Kenia',
'KG' => 'Kirguistán',
'KH' => 'Camboya',
'KI' => 'Kiribati',
'KN' => 'San Cristóbal y Nieves',
'KR' => 'Corea del Sur',
'KW' => 'Kuwait',
'LA' => 'Laos',
'LB' => 'Líbano',
'LR' => 'Liberia',
'LY' => 'Libia',
'LC' => 'Santa Lucía',
'LI' => 'Liechtenstein',
'LK' => 'Sri Lanka',
'LS' => 'Lesoto',
'LT' => 'Lituania',
'LU' => 'Luxemburgo',
'LV' => 'Letonia',
'MA' => 'Marruecos',
'MC' => 'Mónaco',
'MD' => 'Moldavia',
'MG' => 'Madagascar',
'MV' => 'Maldivas',
'MX' => 'Mexico',
'MH' => 'Islas Marshall',
'MK' => 'Macedonia',
'ML' => 'Mali',
'MT' => 'Malta',
'MM' => 'Myanmar',
'ME' => 'Montenegro',
'MN' => 'Mongolia',
'MZ' => 'Mozambique',
'MR' => 'Mauritania',
'MU' => 'Mauricio',
'MW' => 'Malawi',
'MY' => 'Malasia',
'NA' => 'Namibia',
'NE' => 'Níger',
'NG' => 'Nigeria',
'NI' => 'Nicaragua',
'NL' => 'Países Bajos',
'NO' => 'Noruega',
'NP' => 'Nepal',
'NR' => 'Nauru',
'NZ' => 'Nueva Zelanda',
'OM' => 'Omán',
'PK' => 'Pakistán',
'PA' => 'Panamá',
'PE' => 'Perú',
'PH' => 'Filipinas',
'PW' => 'Palaos',
'PG' => 'Papúa Nueva Guinea',
'PL' => 'Polonia',
'KP' => 'Corea del Norte',
'PT' => 'Portugal',
'PY' => 'Paraguay',
'QA' => 'Katar',
'RO' => 'Rumania',
'RU' => 'Rusia',
'RW' => 'Ruanda',
'SA' => 'Arabia Saudita',
'SD' => 'Sudán',
'SN' => 'Senegal',
'SG' => 'Singapur',
'SB' => 'Islas Salomón',
'SL' => 'Sierra Leona',
'SV' => 'El Salvador',
'SM' => 'San Marino',
'SO' => 'Somalia',
'RS' => 'Serbia',
'SS' => 'Sudán del Sur',
'ST' => 'Santo Tomé y Príncipe',
'SR' => 'Surinam',
'SK' => 'Eslovaquia',
'SI' => 'Eslovenia',
'SE' => 'Suecia',
'SZ' => 'Suazilandia',
'SC' => 'Seychelles',
'SY' => 'Siria',
'TD' => 'Chad',
'TG' => 'Togo',
'TH' => 'Tailandia',
'TJ' => 'Tayikistán',
'TM' => 'Turkmenistán',
'TL' => 'Timor Oriental',
'TO' => 'Tonga',
'TT' => 'Trinidad y Tobago',
'TN' => 'Túnez',
'TR' => 'Turquía',
'TV' => 'Tuvalu',
'TZ' => 'Tanzania',
'UG' => 'Uganda',
'UA' => 'Ucrania',
'UY' => 'Uruguay',
'US' => 'Estados Unidos',
'UZ' => 'Uzbekistán',
'VA' => 'Ciudad del Vaticano',
'VC' => 'San Vicente y las Granadinas',
'VE' => 'Venezuela',
'VN' => 'Vietnam',
'VU' => 'Vanuatu',
'WS' => 'Samoa',
'YE' => 'Yemen',
'ZA' => 'Sudáfrica',
'ZM' => 'Zambia',
'ZW' => 'Zimbabue',
];

21
app/config/locale/es.php Normal file
View file

@ -0,0 +1,21 @@
<?php
return [
'settings.inspire' => '"El arte de ser sabio es el arte de saber qué pasar por alto"', // This is the line printed in the homepage and console 'view-source'
'settings.locale' => 'es',
'settings.direction' => 'ltr',
// Service - Users
'auth.emails.team' => '%s Equipo',
'auth.emails.confirm.title' => 'Confirmación de la cuenta',
'auth.emails.confirm.body' => 'es.email.auth.confirm.tpl',
'auth.emails.recovery.title' => 'Reestablecer contraseña',
'auth.emails.recovery.body' => 'es.email.auth.recovery.tpl',
'auth.emails.invitation.title' => 'Invitación al Equipo %s en %s',
'auth.emails.invitation.body' => 'es.email.auth.invitation.tpl',
'locale.country.unknown' => 'Desconocido',
'countries' => include 'es.countries.php',
'continents' => include 'es.continents.php',
];

View file

@ -0,0 +1,11 @@
<?php
return [
'AF' => 'Αφρική',
'AN' => 'Ανταρκτική',
'AS' => 'Ασία',
'EU' => 'Ευρώπη',
'NA' => 'Βόρεια Αμερική',
'OC' => 'Ωκεανία',
'SA' => 'Νότια Αμερική',
];

View file

@ -0,0 +1,198 @@
<?php
return [
'AF' => 'Αφγανιστάν',
'AO' => 'Ανγκόλα',
'AL' => 'Αλβανία',
'AD' => 'Ανδόρα',
'AE' => 'Ηνωμένα Αραβικά Εμιράτα',
'AR' => 'Αργεντινή',
'AM' => 'Αρμενία',
'AG' => 'Αντίγκουα και Μπαρμπούντα',
'AU' => 'Αυστραλία',
'AT' => 'Αυστρία',
'AZ' => 'Αζερμπαϊτζάν',
'BI' => 'Μπουρούντι',
'BE' => 'Βέλγιο',
'BJ' => 'Μπενίν',
'BF' => 'Μπουρκίνα Φάσο',
'BD' => 'Μπανγκλαντές',
'BG' => 'Βουλγαρία',
'BH' => 'Μπαχρέιν',
'BS' => 'Μπαχάμες',
'BA' => 'Βοσνία και Ερζεγοβίνη',
'BY' => 'Λευκορωσία',
'BZ' => 'Μπελίζε',
'BO' => 'Βολιβία',
'BR' => 'Βραζιλία',
'BB' => 'Μπαρμπάντος',
'BN' => 'Μπρουνέι',
'BT' => 'Μπουτάν',
'BW' => 'Μποτσουάνα',
'CF' => 'Κεντροαφρικανική Δημοκρατία',
'CA' => 'Καναδάς',
'CH' => 'Ελβετία',
'CL' => 'Χιλή',
'CN' => 'Κίνα',
'CI' => 'Ακτή Ελεφαντοστού',
'CM' => 'Καμερούν',
'CD' => 'Λαϊκή Δημοκρατία του Κονγκό',
'CG' => 'Δημοκρατία του Κονγκό',
'CO' => 'Κολομβία',
'KM' => 'Κομόρες',
'CV' => 'Πράσινο Ακρωτήρι',
'CR' => 'Κόστα Ρίκα',
'CU' => 'Κούβα',
'CY' => 'Κύπρος',
'CZ' => 'Τσεχία',
'DE' => 'Γερμανία',
'DJ' => 'Τζιμπουτί',
'DM' => 'Ντομίνικα',
'DK' => 'Δανία',
'DO' => 'Δομινικανή Δημοκρατία',
'DZ' => 'Αλγερία',
'EC' => 'Εκουαδόρ',
'EG' => 'Αίγυπτος',
'ER' => 'Ερυθραία',
'ES' => 'Ισπανία',
'EE' => 'Εσθονία',
'ET' => 'Αιθιοπία',
'FI' => 'Φινλανδία',
'FJ' => 'Φίτζι',
'FR' => 'Γαλλία',
'FM' => 'Μικρονησία',
'GA' => 'Γκαμπόν',
'GB' => 'Ηνωμένο Βασίλειο',
'GE' => 'Γεωργία',
'GH' => 'Γκάνα',
'GN' => 'Γουινέα',
'GM' => 'Γκάμπια',
'GW' => 'Γουινέα-Μπισσάου',
'GQ' => 'Ισημερινή Γουινέα',
'GR' => 'Ελλάδα',
'GD' => 'Γρενάδα',
'GT' => 'Γουατεμάλα',
'GY' => 'Γουιάνα',
'HN' => 'Ονδούρα',
'HR' => 'Κροατία',
'HT' => 'Αϊτή',
'HU' => 'Ουγγαρία',
'ID' => 'Ινδονησία',
'IN' => 'Ινδία',
'IE' => 'Ιρλανδία',
'IR' => 'Ιράν',
'IQ' => 'Ιράκ',
'IS' => 'Ισλανδία',
'IL' => 'Ισραήλ',
'IT' => 'Ιταλία',
'JM' => 'Τζαμάικα',
'JO' => 'Ιορδανία',
'JP' => 'Ιαπωνία',
'KZ' => 'Καζακστάν',
'KE' => 'Κένυα',
'KG' => 'Κιργιζιστάν',
'KH' => 'Καμπότζη',
'KI' => 'Κιριμπάτι',
'KN' => 'Άγιος Χριστόφορος και Νέβις',
'KR' => 'Νότια Κορέα',
'KW' => 'Κουβέιτ',
'LA' => 'Λάος',
'LB' => 'Λίβανος',
'LR' => 'Λιβερία',
'LY' => 'Λιβύη',
'LC' => 'Αγία Λουδία',
'LI' => 'Λιχτενστάιν',
'LK' => 'Σρι Λάνκα',
'LS' => 'Λεσότο',
'LT' => 'Λιθουανία',
'LU' => 'Λουξεμβούργο',
'LV' => 'Λετονία',
'MA' => 'Μαρόκο',
'MC' => 'Μονακό',
'MD' => 'Μολδαβία',
'MG' => 'Μαδαγασκάρη',
'MV' => 'Μαλδίβες',
'MX' => 'Μεξικό',
'MH' => 'Νήσοι Μάρσαλ',
'MK' => 'Μακεδονία',
'ML' => 'Μάλι',
'MT' => 'Μάλτα',
'MM' => 'Μυανμάρ',
'ME' => 'Μαυροβούνιο',
'MN' => 'Μογγολία',
'MZ' => 'Μοζαμβίκη',
'MR' => 'Μαυριτανία',
'MU' => 'Μαυρίκιος',
'MW' => 'Μαλάουι',
'MY' => 'Μαλαισία',
'NA' => 'Ναμίμπια',
'NE' => 'Νίγηρα',
'NG' => 'Νιγηρία',
'NI' => 'Νικαράγουα',
'NL' => 'Ολλανδία',
'NO' => 'Νορβηγία',
'NP' => 'Νεπάλ',
'NR' => 'Ναουρού',
'NZ' => 'Νέα Ζηλανδία',
'OM' => 'Ομάν',
'PK' => 'Πακιστάν',
'PA' => 'Παναμάς',
'PE' => 'Περού',
'PH' => 'Φιλιππίνες',
'PW' => 'Palau',
'PG' => 'Παπούα Νέα Γουινέα',
'PL' => 'Πολωνία',
'KP' => 'Βόρεια Κορέα',
'PT' => 'Πορτογαλία',
'PY' => 'Παραγουάη',
'QA' => 'Κατάρ',
'RO' => 'Ρουμανία',
'RU' => 'Ρωσία',
'RW' => 'Ρουάντα',
'SA' => 'Σαουδική Αραβία',
'SD' => 'Σουδάν',
'SN' => 'Σενεγάλη',
'SG' => 'Σιγκαπούρη',
'SB' => 'Νησιά Σολομώντα',
'SL' => 'Σιέρα Λεόνε',
'SV' => 'Ελ Σαλβαδόρ',
'SM' => 'Σαν Μαρίνο',
'SO' => 'Σομαλία',
'RS' => 'Σερβία',
'SS' => 'Νότια Σουδάν',
'ST' => 'Σάο Τομέ και Πρινσίπε',
'SR' => 'Σουρινάμ',
'SK' => 'Σλοβακία',
'SI' => 'Σλοβενία',
'SE' => 'Σουηδία',
'SZ' => 'Σουαζιλάνδη',
'SC' => 'Σεϋχέλλες',
'SY' => 'Συρία',
'TD' => 'Τσαντ',
'TG' => 'Τόγκο',
'TH' => 'Ταϊλάνδη',
'TJ' => 'Τατζικιστάν',
'TM' => 'Τουρκμενιστάν',
'TL' => 'Ανατολικό Τιμόρ',
'TO' => 'Τόνγκα',
'TT' => 'Τρινιντάντ και Τομπάγκο',
'TN' => 'Τυνησία',
'TR' => 'Τουρκία',
'TV' => 'Τουβαλού',
'TZ' => 'Τανζανία',
'UG' => 'Ουγκάντα',
'UA' => 'Ουκρανία',
'UY' => 'Ουρουγουάη',
'US' => 'Ηνωμένες Πολιτείες',
'UZ' => 'Ουζμπεκιστάν',
'VA' => 'Βατικανό',
'VC' => 'Άγιος Βικέντιος και Γρεναδίνες',
'VE' => 'Βενεζουέλα',
'VN' => 'Βιετνάμ',
'VU' => 'Βανουάτου',
'WS' => 'Σαμόα',
'YE' => 'Υεμένη',
'ZA' => 'Νότια Αφρική',
'ZM' => 'Ζάμπια',
'ZW' => 'Ζιμπάμπουε',
];

21
app/config/locale/gr.php Normal file
View file

@ -0,0 +1,21 @@
<?php
return [
'settings.inspire' => '"The art of being wise is the art of knowing what to overlook."', // This is the line printed in the homepage and console 'view-source'
'settings.locale' => 'gr',
'settings.direction' => 'ltr',
// Service - Users
'auth.emails.team' => 'Ομάδα %s',
'auth.emails.confirm.title' => 'Επιβεβαίωση Λογαριασμού',
'auth.emails.confirm.body' => 'gr.email.auth.confirm.tpl',
'auth.emails.recovery.title' => 'Επαναφορά Κωδικού Πρόσβασης',
'auth.emails.recovery.body' => 'gr.email.auth.recovery.tpl',
'auth.emails.invitation.title' => 'Πρόσκληση στην ομάδα %s στο %s',
'auth.emails.invitation.body' => 'gr.email.auth.invitation.tpl',
'locale.country.unknown' => 'Άγνωστο',
'countries' => include 'gr.countries.php',
'continents' => include 'gr.continents.php',
];

View file

@ -7,7 +7,7 @@ return [
'AU' => 'אוסטרליה',
'UA' => 'אוקראינה',
'UY' => 'אורוגוואי',
'AZ' => 'אזרבייג\'ן',
'AZ' => 'אזרבייג׳ן',
'AE' => 'איחוד האמירויות הערביות',
'IT' => 'איטליה',
'BS' => 'איי בהאמה',

View file

@ -11,7 +11,7 @@ return [
'auth.emails.confirm.body' => 'he.email.auth.confirm.tpl',
'auth.emails.recovery.title' => 'איפוס סיסמא',
'auth.emails.recovery.body' => 'he.email.auth.recovery.tpl',
'auth.emails.invitation.title' => 'הזמנה לצוות של %s ב-%s',
'auth.emails.invitation.title' => 'הזמנה לצוות של %s ב־%s',
'auth.emails.invitation.body' => 'he.email.auth.invitation.tpl',
'locale.country.unknown' => 'לא ידוע',

View file

@ -0,0 +1,10 @@
<?php
return [
'AF' => 'Africa',
'AN' => 'Antartide',
'AS' => 'Asia',
'EU' => 'Europa',
'NA' => 'Nord America',
'OC' => 'Oceania',
'SA' => 'Sud America',
];

View file

@ -0,0 +1,198 @@
<?php
return [
'AF' => 'Afghanistan',
'AO' => 'Angola',
'AL' => 'Albania',
'AD' => 'Andorra',
'AE' => 'Emirati Arabi Uniti',
'AR' => 'Argentina',
'AM' => 'Armenia',
'AG' => 'Antigua e Barbuda',
'AU' => 'Australia',
'AT' => 'Austria',
'AZ' => 'Azerbaigian',
'BI' => 'Burundi',
'BE' => 'Belgio',
'BJ' => 'Benin',
'BF' => 'Burkina Faso',
'BD' => 'Bangladesh',
'BG' => 'Bulgaria',
'BH' => 'Bahrein',
'BS' => 'Bahamas',
"BA" => "Bosnia ed Erzegovina",
'BY' => 'Bielorussia',
'BZ' => 'Belize',
'BO' => 'Bolivia',
'BR' => 'Brasile',
'BB' => 'Barbados',
'BN' => 'Brunei',
'BT' => 'Bhutan',
'BW' => 'Botswana',
"CF" => "Repubblica centrafricana",
'CA' => 'Canada',
'CH' => 'Svizzera',
'CL' => 'Cile',
'CN' => 'Cina',
'CI' => 'Costa d\'Avorio',
'CM' => 'Camerun',
'CD' => 'DR Congo',
'CG' => 'Repubblica del Congo',
'CO' => 'Colombia',
'KM' => 'Comore',
'CV' => 'Capo Verde',
'CR' => 'Costa Rica',
'CU' => 'Cuba',
'CY' => 'Cipro',
'CZ' => 'Czechia',
'DE' => 'Germania',
'DJ' => 'Gibuti',
'DM' => 'Dominica',
'DK' => 'Danimarca',
'DO' => 'Repubblica Dominicana',
'DZ' => 'Algeria',
'EC' => 'Ecuador',
'EG' => 'Egitto',
'ER' => 'Eritrea',
'ES' => 'Spagna',
'EE' => 'Estonia',
'ET' => 'Etiopia',
'FI' => 'Finlandia',
'FJ' => 'Figi',
'FR' => 'France',
'FM' => 'Micronesia',
'GA' => 'Gabon',
'GB' => 'Regno Unito',
'GE' => 'Georgia',
'GH' => 'Ghana',
'GN' => 'Guinea',
'GM' => 'Gambia',
'GW' => 'Guinea-Bissau',
'GQ' => 'Guinea equatoriale',
'GR' => 'Grecia',
'GD' => 'Grenada',
'GT' => 'Guatemala',
'GY' => 'Guyana',
'HN' => 'Honduras',
'HR' => 'Croazia',
'HT' => 'Haiti',
'HU' => 'Ungheria',
'ID' => 'Indonesia',
'IN' => 'India',
'IE' => 'Irlanda',
'IR' => 'Iran',
'IQ' => 'Iraq',
'IS' => 'Islanda',
'IL' => 'Israele',
'IT' => 'Italia',
'JM' => 'Giamaica',
'JO' => 'Jordan',
'JP' => 'Giappone',
'KZ' => 'Kazakistan',
'KE' => 'Kenya',
'KG' => 'Kirghizistan',
'KH' => 'Cambogia',
'KI' => 'Kiribati',
'KN' => 'Saint Kitts e Nevis',
"KR" => "Corea del Sud",
'KW' => 'Kuwait',
'LA' => 'Laos',
'LB' => 'Libano',
'LR' => 'Liberia',
'LY' => 'Libia',
'LC' => 'Santa Lucia',
'LI' => 'Liechtenstein',
'LK' => 'Sri Lanka',
'LS' => 'Lesotho',
'LT' => 'Lituania',
'LU' => 'Lussemburgo',
'LV' => 'Lettonia',
'MA' => 'Marocco',
'MC' => 'Monaco',
'MD' => 'Moldavia',
'MG' => 'Madagascar',
'MV' => 'Maldive',
'MX' => 'Messico',
'MH' => 'Isole Marshall',
'MK' => 'Macedonia',
'ML' => 'Mali',
'MT' => 'Malta',
'MM' => 'Myanmar',
'ME' => 'Montenegro',
'MN' => 'Mongolia',
'MZ' => 'Mozambico',
'MR' => 'Mauritania',
'MU' => 'Mauritius',
'MW' => 'Malawi',
'MY' => 'Malaysia',
'NA' => 'Namibia',
'NE' => 'Niger',
'NG' => 'Nigeria',
'NI' => 'Nicaragua',
'NL' => 'Paesi Bassi',
'NO' => 'Norvegia',
'NP' => 'Nepal',
'NR' => 'Nauru',
'NZ' => 'Nuova Zelanda',
'OM' => 'Oman',
'PK' => 'Pakistan',
'PA' => 'Panama',
'PE' => 'Perù',
'PH' => 'Filippine',
'PW' => 'Palau',
'PG' => 'Papua New Guinea',
'PL' => 'Polonia',
'KP' => 'Corea del Nord',
'PT' => 'Portogallo',
'PY' => 'Paraguay',
'QA' => 'Qatar',
'RO' => 'Romania',
'RU' => 'Russia',
'RW' => 'Ruanda',
'SA' => 'Arabia Saudita',
'SD' => 'Sudan',
'SN' => 'Senegal',
'SG' => 'Singapore',
'SB' => 'Isole Salomone',
'SL' => 'Sierra Leone',
'SV' => 'El Salvador',
'SM' => 'San Marino',
'SO' => 'Somalia',
'RS' => 'Serbia',
'SS' => 'Sudan del Sud',
'ST' => 'São Tomé and Príncipe',
'SR' => 'Suriname',
'SK' => 'Slovacchia',
'SI' => 'Slovenia',
'SE' => 'Svezia',
'SZ' => 'Swaziland',
'SC' => 'Seychelles',
'SY' => 'Siria',
'TD' => 'Chad',
'TG' => 'Togo',
'TH' => 'Thailand',
'TJ' => 'Tagikistan',
'TM' => 'Turkmenistan',
'TL' => 'Timor Est',
'TO' => 'Tonga',
'TT' => 'Trinidad e Tobago',
'TN' => 'Tunisia',
'TR' => 'Turchia',
'TV' => 'Tuvalu',
'TZ' => 'Tanzania',
'UG' => 'Uganda',
'UA' => 'Ucraina',
'UY' => 'Uruguay',
'US' => 'Stati Uniti',
'UZ' => 'Uzbekistan',
'VA' => 'Città del Vaticano',
'VC' => 'Saint Vincent e Grenadine',
'VE' => 'Venezuela',
'VN' => 'Vietnam',
'VU' => 'Vanuatu',
'WS' => 'Samoa',
'YE' => 'Yemen',
'ZA' => 'Sudafrica',
'ZM' => 'Zambia',
'ZW' => 'Zimbabwe',
];

18
app/config/locale/it.php Normal file
View file

@ -0,0 +1,18 @@
<?php
return [
'settings.inspire' => '"L\'arte di essere saggi è l\'arte di sapere cosa trascurare."', // Questa è la riga stampata nella homepage e nella console 'view-source'
'settings.locale' => 'it',
'settings.direction' => 'ltr',
// Servizio - Utenti
'auth.emails.team' => '%s Squadra',
'auth.emails.confirm.title' => 'Conferma dell\'account',
'auth.emails.confirm.body' => 'en.email.auth.confirm.tpl',
'auth.emails.recovery.title' => 'Reimpostazione della password',
'auth.emails.recovery.body' => 'en.email.auth.recovery.tpl',
'auth.emails.invitation.title' => 'Invito a %s squadra %s',
'auth.emails.invitation.body' => 'en.email.auth.invitation.tpl',
'locale.country.unknown' => 'Sconosciuto',
'countries' => include 'it.countries.php',
'continents' => include 'it.continents.php',
];

View file

@ -0,0 +1,11 @@
<?php
return [
'AF' => 'África',
'AN' => 'Antártica',
'AS' => 'Ásia',
'EU' => 'Europa',
'NA' => 'América do Norte',
'OC' => 'Oceania',
'SA' => 'América do Sul',
];

View file

@ -0,0 +1,198 @@
<?php
return [
'AF' => 'Afeganistão',
'AO' => 'Angola',
'AL' => 'Albânia',
'AD' => 'Andorra',
'AE' => 'Emirados Árabes Unidos',
'AR' => 'Argentina',
'AM' => 'Armênia',
'AG' => 'Antígua e Barbuda',
'AU' => 'Austrália',
'AT' => 'Áustria',
'AZ' => 'Azerbaijão',
'BI' => 'Burúndi',
'BE' => 'Bélgica',
'BJ' => 'Benim',
'BF' => 'Burkina Faso',
'BD' => 'Bangladesh',
'BG' => 'Bulgária',
'BH' => 'Bahrein',
'BS' => 'Bahamas',
'BA' => 'Bósnia and Herzegovina',
'BY' => 'Bielorússia',
'BZ' => 'Belize',
'BO' => 'Bolívia',
'BR' => 'Brasil',
'BB' => 'Barbados',
'BN' => 'Brunei',
'BT' => 'Butão',
'BW' => 'Botsuana',
'CF' => 'República Centro-Africana',
'CA' => 'Canadá',
'CH' => 'Suíça',
'CL' => 'Chile',
'CN' => 'China',
'CI' => 'Costa do Marfim',
'CM' => 'Camarões',
'CD' => 'República Democrática do Congo',
'CG' => 'República do Congo',
'CO' => 'Colombia',
'KM' => 'Comores',
'CV' => 'Cabo Verde',
'CR' => 'Costa Rica',
'CU' => 'Cuba',
'CY' => 'Chipre',
'CZ' => 'Tchéquia',
'DE' => 'Alemanha',
'DJ' => 'Djibouti',
'DM' => 'Dominica',
'DK' => 'Dinamarca',
'DO' => 'República Dominicana',
'DZ' => 'Argélia',
'EC' => 'Equador',
'EG' => 'Egito',
'ER' => 'Eritrea',
'ES' => 'Espanha',
'EE' => 'Estônia',
'ET' => 'Etiópia',
'FI' => 'Finlândia',
'FJ' => 'Fiji',
'FR' => 'França',
'FM' => 'Micronésia',
'GA' => 'Gabão',
'GB' => 'Reino Unido',
'GE' => 'Geórgia',
'GH' => 'Gana',
'GN' => 'Guiné',
'GM' => 'Gâmbia',
'GW' => 'Guiné-Bissau',
'GQ' => 'Guiné Equatorial',
'GR' => 'Grécia',
'GD' => 'Granada',
'GT' => 'Guatemala',
'GY' => 'Guiana',
'HN' => 'Honduras',
'HR' => 'Croácia',
'HT' => 'Haiti',
'HU' => 'Hungria',
'ID' => 'Indonésia',
'IN' => 'Índia',
'IE' => 'Irlanda',
'IR' => 'Irã',
'IQ' => 'Iraque',
'IS' => 'Islândia',
'IL' => 'Israel',
'IT' => 'Itália',
'JM' => 'Jamaica',
'JO' => 'Jordânia',
'JP' => 'Japão',
'KZ' => 'Cazaquistão',
'KE' => 'Quênia',
'KG' => 'Quirguistão',
'KH' => 'Camboja',
'KI' => 'Quiribati',
'KN' => 'São Cristóvão e Névis',
'KR' => 'Coreia do Sul',
'KW' => 'Kuwait',
'LA' => 'Laos',
'LB' => 'Líbano',
'LR' => 'Libéria',
'LY' => 'Líbia',
'LC' => 'Santa Lúcia',
'LI' => 'Liechtenstein',
'LK' => 'Sri Lanka',
'LS' => 'Lesoto',
'LT' => 'Lituânia',
'LU' => 'Luxemburgo',
'LV' => 'Letônia',
'MA' => 'Marrocos',
'MC' => 'Mônaco',
'MD' => 'Moldávia',
'MG' => 'Madagascar',
'MV' => 'Maldivas',
'MX' => 'México',
'MH' => 'Ilhas Marshall',
'MK' => 'Macedônia',
'ML' => 'Mali',
'MT' => 'Malta',
'MM' => 'Myanmar',
'ME' => 'Montenegro',
'MN' => 'Mongólia',
'MZ' => 'Moçambique',
'MR' => 'Mauritânia',
'MU' => 'Ilhas Maurício',
'MW' => 'Malawi',
'MY' => 'Malásia',
'NA' => 'Namíbia',
'NE' => 'Níger',
'NG' => 'Nigéria',
'NI' => 'Nicarágua',
'NL' => 'Países Baixos',
'NO' => 'Noruega',
'NP' => 'Nepal',
'NR' => 'Nauru',
'NZ' => 'Nova Zelândia',
'OM' => 'Omã',
'PK' => 'Paquistão',
'PA' => 'Panamá',
'PE' => 'Peru',
'PH' => 'Filipinas',
'PW' => 'Palau',
'PG' => 'Papua-Nova Guiné',
'PL' => 'Polônia',
'KP' => 'Coreia do Norte',
'PT' => 'Portugal',
'PY' => 'Paraguai',
'QA' => 'Catar',
'RO' => 'Romênia',
'RU' => 'Rússia',
'RW' => 'Ruanda',
'SA' => 'Arábia Saudita',
'SD' => 'Sudão',
'SN' => 'Senegal',
'SG' => 'Singapura',
'SB' => 'Ilhas Salomão',
'SL' => 'Serra Leoa',
'SV' => 'El Salvador',
'SM' => 'San Marino',
'SO' => 'Somália',
'RS' => 'Sérvia',
'SS' => 'Sudão do Sul',
'ST' => 'São Tomé e Príncipe',
'SR' => 'Suriname',
'SK' => 'Eslováquia',
'SI' => 'Eslovênia',
'SE' => 'Suécia',
'SZ' => 'Suazilândia',
'SC' => 'Seicheles',
'SY' => 'Síria',
'TD' => 'Chade',
'TG' => 'Togo',
'TH' => 'Tailândia',
'TJ' => 'Tajisquistão',
'TM' => 'Turcomenistão',
'TL' => 'Timor-Leste',
'TO' => 'Tonga',
'TT' => 'Trindade e Tobago',
'TN' => 'Tunísia',
'TR' => 'Turquia',
'TV' => 'Tuvalu',
'TZ' => 'Tanzânia',
'UG' => 'Uganda',
'UA' => 'Ucrânia',
'UY' => 'Uruguai',
'US' => 'Estados Unidos',
'UZ' => 'Uzbequistão',
'VA' => 'Cidade do Vaticano',
'VC' => 'São Vincente e Granadinas',
'VE' => 'Venezuela',
'VN' => 'Vietnã',
'VU' => 'Vanuatu',
'WS' => 'Samoa',
'YE' => 'Iêmen',
'ZA' => 'África do Sul',
'ZM' => 'Zâmbia',
'ZW' => 'Zimbábue',
];

View file

@ -0,0 +1,21 @@
<?php
return [
'settings.inspire' => '"The art of being wise is the art of knowing what to overlook."', // This is the line printed in the homepage and console 'view-source'
'settings.locale' => 'pt-br',
'settings.direction' => 'ltr',
// Service - Users
'auth.emails.team' => 'Time %s',
'auth.emails.confirm.title' => 'Confirmação de Conta',
'auth.emails.confirm.body' => 'pt-br.email.auth.confirm.tpl',
'auth.emails.recovery.title' => 'Redefinição de Senha',
'auth.emails.recovery.body' => 'pt-br.email.auth.recovery.tpl',
'auth.emails.invitation.title' => 'Convite para a Equipe %s em %s',
'auth.emails.invitation.body' => 'pt-br.email.auth.invitation.tpl',
'locale.country.unknown' => 'Desconhecido',
'countries' => include 'pt-br.countries.php',
'continents' => include 'pt-br.continents.php',
];

View file

@ -10,7 +10,7 @@
Hello,
<br />
<br />
This mail was sent to you because <b>{{owner}}</b> wanted to invite to become a team member at the <b>{{team}}</b> team over at {{project}}.
This mail was sent to you because <b>{{owner}}</b> wanted to invite you to become a team member at the <b>{{team}}</b> team over at {{project}}.
<br />
<br />
Follow this link to join the <b>{{team}}</b> team:

View file

@ -0,0 +1,24 @@
<style>
* {
font-family: sans-serif,Arial;
-webkit-font-smoothing: antialiased;
font-weight: lighter;
}
</style>
<div style="direction: {{direction}}">
Hola {{name}},
<br />
<br />
Sigue este enlace para verificar tu dirección de correo:
<br />
<a href="{{redirect}}">{{redirect}}</a>
<br />
<br />
Si no has solicitado verificar esta dirección, puedes ignorar este mensaje.
<br />
<br />
Gracias,
<br />
Equipo {{project}}
</div>

View file

@ -0,0 +1,27 @@
<style>
* {
font-family: sans-serif,Arial;
-webkit-font-smoothing: antialiased;
font-weight: lighter;
}
</style>
<div style="direction: {{direction}}">
Hola,
<br />
<br />
Te hemos enviamos este correo porque <b>{{owner}}</b> quiere invitarte a formar parte del equipo <b>{{team}}</b> en {{project}}.
<br />
<br />
Sigue este enlace para unirte al equipo <b>{{team}}</b>:
<br />
<a href="{{redirect}}">{{redirect}}</a>
<br />
<br />
Si no estás interesado, puedes ignorar este mensaje.
<br />
<br />
Gracias,
<br />
Equipo {{project}}
</div>

View file

@ -0,0 +1,24 @@
<style>
* {
font-family: sans-serif,Arial;
-webkit-font-smoothing: antialiased;
font-weight: lighter;
}
</style>
<div style="direction: {{direction}}">
Hola {{name}},
<br />
<br />
Sigue este enlace para reestablecer tu contraseña de {{project}}.
<br />
<a href="{{redirect}}">{{redirect}}</a>
<br />
<br />
Si no has pedido reestablecer tu contraseña, puedes ignorar este mensaje.
<br />
<br />
Gracias,
<br />
Equipo {{project}}
</div>

View file

@ -0,0 +1,24 @@
<style>
* {
font-family: sans-serif,Arial;
-webkit-font-smoothing: antialiased;
font-weight: lighter;
}
</style>
<div style="direction: {{direction}}">
Γεια σου {{name}},
<br />
<br />
Ακολούθησε αυτό τον σύνδεσμο για να επιβεβαιώσεις τη διεύθυνση email σου.
<br />
<a href="{{redirect}}">{{redirect}}</a>
<br />
<br />
Αν δεν ζήτησες να επιβεβαιώσεις αυτή τη διεύθυνση, μπορείς να αγνοήσεις αυτό το μήνυμα.
<br />
<br />
Ευχαριστούμε,
<br />
Η ομάδα του {{project}}
</div>

View file

@ -0,0 +1,27 @@
<style>
* {
font-family: sans-serif,Arial;
-webkit-font-smoothing: antialiased;
font-weight: lighter;
}
</style>
<div style="direction: {{direction}}">
Γεια,
<br />
<br />
Έλαβες αυτό το email επειδή ο <b>{{owner}}</b> σε προσκάλεσε να γίνεις μέλος της ομάδας <b>{{team}}</b> στο {{project}}.
<br />
<br />
Ακολούθησε αυτό τον σύνδεσμο για να γίνεις μέλος της ομάδας <b>{{team}}</b>:
<br />
<a href="{{redirect}}">{{redirect}}</a>
<br />
<br />
Άν δεν ενδιαφέρεσαι, μπορείς να αγνοήσεις αυτό το μήνυμα.
<br />
<br />
Ευχαριστούμε,
<br />
Η ομάδα του {{project}}
</div>

View file

@ -0,0 +1,24 @@
<style>
* {
font-family: sans-serif,Arial;
-webkit-font-smoothing: antialiased;
font-weight: lighter;
}
</style>
<div style="direction: {{direction}}">
Γεια σου {{name}},
<br />
<br />
Ακολούθησε αυτό τον σύνδεσμο για να επαναφέρεις τον κωδικό πρόσβασής σου για το {{project}}.
<br />
<a href="{{redirect}}">{{redirect}}</a>
<br />
<br />
Άν δεν ζήτησες αλλαγή κωδικού πρόσβασης, μπορείς να αγνοήσεις αυτο το μήνυμα.
<br />
<br />
Ευχαριστούμε,
<br />
Η ομάδα του {{project}}
</div>

View file

@ -10,15 +10,15 @@
שלום {{name}},
<br />
<br />
לחץ\י על הלינק הבא על מנת לאמת את החשבון שלך.
נא ללחוץ על הקישור שלהלן כדי לאמת את החשבון שלך.
<br />
<a href="{{redirect}}">{{redirect}}</a>
<br />
<br />
במידה ולא ביקשת לאמת את כתובת המייל הזאת, את\ה יכול\ה להתעלם ממייל זה.
אם לא ביקשת לאמת את כתובת הדוא״ל, ניתן להתעלם מההודעה זו.
<br />
<br />
תודה,
בברכה,
<br />
צוות {{project}}
</div>

View file

@ -10,18 +10,18 @@
שלום,
<br />
<br />
מייל זה נשלח אליך בגלל ש-<b>{{owner}}</b> רוצה להזמין אותך להפוך לחבר\ת צוות בצוות <b>{{team}}</b> ב-{{project}}.
הודעת דוא״ל זו נשלחה אליך כי <b>{{owner}}</b> ביקש להזמינך להצטרף לצוות <b>{{team}}</b> ב־{{project}}.
<br />
<br />
בכדי להצטרף לצוות <b>{{team}}</b>, לחץ על הלינק:
כדי להצטרף לצוות <b>{{team}}</b>, נא ללחוץ על הקישור:
<br />
<a href="{{redirect}}">{{redirect}}</a>
<br />
<br />
במידה ואינך מעוניין\ת, אנא התעלם\י ממייל זה.
אם איך לך עניין להצטרף לצוות, ניתן להתעלם מהודעת דוא״ל זו.
<br />
<br />
תודה,
בברכה,
<br />
צוות {{project}}
</div>

View file

@ -10,15 +10,15 @@
שלום {{name}},
<br />
<br />
לחץ\י על הלינק בכדי לאפס את הסיסמא שלך ב-{{project}}.
נא ללחוץ על הקישור שלהלן כדי לאפס את הסיסמה שלך ב־{{project}}.
<br />
<a href="{{redirect}}">{{redirect}}</a>
<br />
<br />
במידה ולא ביקשת לאפס את סיסמתך, את\ה יכול\ה להתעלם ממייל זה.
אם לא ביקשת לאפס את סיסמתך, ניתן להתעלם מהודעת דוא״ל זו.
<br />
<br />
תודה,
בברכה,
<br />
צוות {{project}}
</div>

View file

@ -0,0 +1,25 @@
<style>
* {
font-family: sans-serif,Arial;
-webkit-font-smoothing: antialiased;
font-weight: lighter;
}
</style>
<div style="direction: {{direction}}">
Ciao {{name}},
<br />
<br />
Segui questo link per verificare il tuo indirizzo email.
<br />
<a href="{{redirect}}">{{redirect}}</a>
<br />
<br />
Se non hai chiesto di verificare questo indirizzo, puoi ignorare questo messaggio.
<br />
<br />
Grazie,
<br />
{{project}} squadra
</div>

View file

@ -0,0 +1,28 @@
<style>
* {
font-family: sans-serif,Arial;
-webkit-font-smoothing: antialiased;
font-weight: lighter;
}
</style>
<div style="direction: {{direction}}">
Ciao,
<br />
<br />
Questa mail ti è stata inviata perché <b>{{owner}}</b> volevo invitarti a diventare un membro del team al <b>{{team}}</b> squadra a {{project}}.
<br />
<br />
Segui questo link per unirti a <b>{{team}}</b> squadra:
<br />
<a href="{{redirect}}">{{redirect}}</a>
<br />
<br />
Se non sei interessato, puoi ignorare questo messaggio.
<br />
<br />
Grazie,
<br />
{{project}} squadra
</div>

View file

@ -0,0 +1,24 @@
<style>
* {
font-family: sans-serif,Arial;
-webkit-font-smoothing: antialiased;
font-weight: lighter;
}
</style>
<div style="direction: {{direction}}">
Ciao {{name}},
<br />
<br />
Segui questo link per reimpostare la tua {{project}} password.
<br />
<a href="{{redirect}}">{{redirect}}</a>
<br />
<br />
Se non hai chiesto di reimpostare la password, puoi ignorare questo messaggio.
<br />
<br />
Grazie,
<br />
{{project}} squadra
</div>

View file

@ -0,0 +1,24 @@
<style>
* {
font-family: sans-serif,Arial;
-webkit-font-smoothing: antialiased;
font-weight: lighter;
}
</style>
<div style="direction: {{direction}}">
Olá {{name}},
<br />
<br />
Por favor, confirme o seu email acessando este link abaixo.
<br />
<a href="{{redirect}}">{{redirect}}</a>
<br />
<br />
Se a confirmação de email não foi solicitada por você, ignore esta mensagem.
<br />
<br />
Atenciosamente,
<br />
Equipe {{project}}
</div>

View file

@ -0,0 +1,27 @@
<style>
* {
font-family: sans-serif,Arial;
-webkit-font-smoothing: antialiased;
font-weight: lighter;
}
</style>
<div style="direction: {{direction}}">
Olá,
<br />
<br />
Este email foi enviado a você porque <br>{{owner}} deseja lhe convidar a se tornar membro da equipe <b>{{team}}<b> no {{project}}.
<br />
<br />
Siga este link para se juntar a equipe <b>{{team}}<b>:
<br />
<a href="{{redirect}}">{{redirect}}</a>
<br />
<br />
Se não estiver interessado, por favor ignore esta mensagem.
<br />
<br />
Atenciosamente,
<br />
Equipe {{project}}
</div>

View file

@ -0,0 +1,24 @@
<style>
* {
font-family: sans-serif,Arial;
-webkit-font-smoothing: antialiased;
font-weight: lighter;
}
</style>
<div style="direction: {{direction}}">
Olá {{name}},
<br />
<br />
Acesse este link para redefinir sua senha do {{project}}.
<br />
<a href="{{redirect}}">{{redirect}}</a>
<br />
<br />
Se você não solicitou a redefinição de senha, por favor ignore esta mensagem.
<br />
<br />
Atenciosamente,
<br />
Equipe {{project}}
</div>

View file

@ -19,12 +19,12 @@ return [
'gitlab' => [
'developers' => 'https://docs.gitlab.com/ee/api/',
'icon' => 'icon-gitlab',
'enabled' => false,
'enabled' => true,
],
'google' => [
'developers' => 'https://developers.google.com/',
'icon' => 'icon-google',
'enabled' => false,
'enabled' => true,
],
'instagram' => [
'developers' => 'https://www.instagram.com/developer/',

View file

@ -60,7 +60,7 @@ return [
'tag' => 'Soon',
],
[
'label' => '.NET',
'label' => 'C#',
'versions' => [],
'logo' => 'dotnet.svg',
'link' => 'https://...',

View file

@ -39,7 +39,8 @@ $utopia->get('/v1/account')
'registration',
'confirm',
'name',
], $oauthKeys
],
$oauthKeys
)), ['roles' => Authorization::getRoles()]));
}
);
@ -133,7 +134,6 @@ $utopia->get('/v1/account/security')
->label('sdk.description', 'Get currently logged in user list of latest security activity logs. Each log returns user IP address, location and date and time of log.')
->action(
function () use ($response, $register, $project, $user) {
$ad = new \Audit\Adapter\MySQL($register->get('db'));
$ad->setNamespace('app_'.$project->getUid());
$au = new \Audit\Audit($ad, $user->getUid(), $user->getAttribute('type'), '', '', '');
@ -202,7 +202,9 @@ $utopia->patch('/v1/account/name')
->label('sdk.namespace', 'account')
->label('sdk.method', 'updateName')
->label('sdk.description', 'Update currently logged in user account name.')
->param('name', '', function () {return new Text(100);}, 'User name')
->param('name', '', function () {
return new Text(100);
}, 'User name')
->action(
function ($name) use ($response, $user, $projectDB, $audit) {
$user = $projectDB->updateDocument(array_merge($user->getArrayCopy(), [
@ -226,8 +228,12 @@ $utopia->patch('/v1/account/password')
->label('sdk.namespace', 'account')
->label('sdk.method', 'updatePassword')
->label('sdk.description', 'Update currently logged in user password. For validation, user is required to pass the password twice.')
->param('password', '', function () {return new Password();}, 'New password')
->param('old-password', '', function () {return new Password();}, 'Old password')
->param('password', '', function () {
return new Password();
}, 'New password')
->param('old-password', '', function () {
return new Password();
}, 'Old password')
->action(
function ($password, $oldPassword) use ($response, $user, $projectDB, $audit) {
if (!Auth::passwordVerify($oldPassword, $user->getAttribute('password'))) { // Double check user password
@ -255,8 +261,12 @@ $utopia->patch('/v1/account/email')
->label('sdk.namespace', 'account')
->label('sdk.method', 'updateEmail')
->label('sdk.description', 'Update currently logged in user account email address. After changing user address, user confirmation status is being reset and a new confirmation mail is sent. For security measures, user password is required to complete this request.')
->param('email', '', function () {return new Email();}, 'Email Address')
->param('password', '', function () {return new Password();}, 'User Password')
->param('email', '', function () {
return new Email();
}, 'Email Address')
->param('password', '', function () {
return new Password();
}, 'User Password')
->action(
function ($email, $password) use ($response, $user, $projectDB, $audit) {
if (!Auth::passwordVerify($password, $user->getAttribute('password'))) { // Double check user password
@ -298,7 +308,9 @@ $utopia->patch('/v1/account/prefs')
->label('scope', 'account')
->label('sdk.namespace', 'account')
->label('sdk.method', 'updatePrefs')
->param('prefs', '', function () {return new \Utopia\Validator\Mock();}, 'Prefs key-value JSON object string.')
->param('prefs', '', function () {
return new \Utopia\Validator\Mock();
}, 'Prefs key-value JSON object string.')
->label('sdk.description', 'Update currently logged in user account preferences. You can pass only the specific settings you wish to update.')
->action(
function ($prefs) use ($response, $user, $projectDB, $audit) {

View file

@ -28,28 +28,40 @@ $utopia->post('/v1/auth/register')
->label('sdk.description', "Use this endpoint to allow a new user to register an account in your project. Use the success and failure URL's to redirect users back to your application after signup completes.\n\nIf registration completes successfully user will be sent with a confirmation email in order to confirm he is the owner of the account email address. Use the confirmation parameter to redirect the user from the confirmation email back to your app. When the user is redirected, use the /auth/confirm endpoint to complete the account confirmation.\n\nPlease notice that in order to avoid a [Redirect Attacks](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) the only valid redirect URL's are the once from domains you have set when added your platforms in the console interface.\n\nWhen accessing this route using Javascript from the browser, success and failure parameter URLs are required. Appwrite server will respond with a 301 redirect status code and will set the user session cookie. This behavior is enforced because modern browsers are limiting 3rd party cookies in XHR of fetch requests to protect user privacy.")
->label('sdk.cookies', true)
->label('abuse-limit', 10)
->param('email', '', function () {return new Email();}, 'Account email')
->param('password', '', function () {return new Password();}, 'User password')
->param('confirmation', '', function () use ($clients) {return new Host($clients);}, 'Confirmation URL to redirect user after confirm token has been sent to user email') // TODO add our own built-in confirm page
->param('success', null, function () use ($clients) {return new Host($clients);}, 'Redirect when registration succeed', true)
->param('failure', null, function () use ($clients) {return new Host($clients);}, 'Redirect when registration failed', true)
->param('name', '', function () {return new Text(100);}, 'User name', true)
->param('email', '', function () {
return new Email();
}, 'Account email')
->param('password', '', function () {
return new Password();
}, 'User password')
->param('confirm', '', function () use ($clients) {
return new Host($clients);
}, 'Confirmation URL to redirect user after confirm token has been sent to user email') // TODO add our own built-in confirm page
->param('success', null, function () use ($clients) {
return new Host($clients);
}, 'Redirect when registration succeed', true)
->param('failure', null, function () use ($clients) {
return new Host($clients);
}, 'Redirect when registration failed', true)
->param('name', '', function () {
return new Text(100);
}, 'User name', true)
->action(
function ($email, $password, $confirmation, $success, $failure, $name) use ($request, $response, $register, $audit, $projectDB, $project, $webhook) {
if('console' === $project->getUid()) {
function ($email, $password, $confirm, $success, $failure, $name) use ($request, $response, $register, $audit, $projectDB, $project, $webhook) {
if ('console' === $project->getUid()) {
$whitlistEmails = $project->getAttribute('authWhitelistEmails');
$whitlistIPs = $project->getAttribute('authWhitelistIPs');
$whitlistDomains = $project->getAttribute('authWhitelistDomains');
if(!empty($whitlistEmails) && !in_array($email, $whitlistEmails)) {
if (!empty($whitlistEmails) && !in_array($email, $whitlistEmails)) {
throw new Exception('Console registration is restricted to specific emails. Contact your administrator for more information.', 401);
}
if(!empty($whitlistIPs) && !in_array($request->getIP(), $whitlistIPs)) {
if (!empty($whitlistIPs) && !in_array($request->getIP(), $whitlistIPs)) {
throw new Exception('Console registration is restricted to specific IPs. Contact your administrator for more information.', 401);
}
if(!empty($whitlistDomains) && !in_array(substr(strrchr($email, "@"), 1), $whitlistDomains)) {
if (!empty($whitlistDomains) && !in_array(substr(strrchr($email, "@"), 1), $whitlistDomains)) {
throw new Exception('Console registration is restricted to specific domains. Contact your administrator for more information.', 401);
}
}
@ -132,16 +144,16 @@ $utopia->post('/v1/auth/register')
// Send email address confirmation email
$confirmation = Template::parseURL($confirmation);
$confirmation['query'] = Template::mergeQuery(((isset($confirmation['query'])) ? $confirmation['query'] : ''), ['userId' => $user->getUid(), 'token' => $confirmSecret]);
$confirmation = Template::unParseURL($confirmation);
$confirm = Template::parseURL($confirm);
$confirm['query'] = Template::mergeQuery(((isset($confirm['query'])) ? $confirm['query'] : ''), ['userId' => $user->getUid(), 'token' => $confirmSecret]);
$confirm = Template::unParseURL($confirm);
$body = new Template(__DIR__.'/../config/locale/templates/'.Locale::getText('auth.emails.confirm.body'));
$body
->setParam('{{direction}}', Locale::getText('settings.direction'))
->setParam('{{project}}', $project->getAttribute('name', ['[APP-NAME]']))
->setParam('{{name}}', $name)
->setParam('{{redirect}}', $confirmation)
->setParam('{{redirect}}', $confirm)
;
$mail = $register->get('smtp'); /* @var $mail \PHPMailer\PHPMailer\PHPMailer */
@ -194,8 +206,12 @@ $utopia->post('/v1/auth/register/confirm')
->label('sdk.description', 'Use this endpoint to complete the confirmation of the user account email address. Both the **userId** and **token** arguments will be passed as query parameters to the redirect URL you have provided when sending your request to the /auth/register endpoint.')
->label('abuse-limit', 10)
->label('abuse-key', 'url:{url},userId:{param-userId}')
->param('userId', '', function () {return new UID();}, 'User unique ID')
->param('token', '', function () {return new Text(256);}, 'Confirmation secret token')
->param('userId', '', function () {
return new UID();
}, 'User unique ID')
->param('token', '', function () {
return new Text(256);
}, 'Confirmation secret token')
->action(
function ($userId, $token) use ($response, $request, $projectDB, $audit) {
$profile = $projectDB->getCollection([ // Get user by email address
@ -244,9 +260,11 @@ $utopia->post('/v1/auth/register/confirm/resend')
->label('sdk.description', "This endpoint allows the user to request your app to resend him his email confirmation message. The redirect arguments acts the same way as in /auth/register endpoint.\n\nPlease notice that in order to avoid a [Redirect Attacks](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) the only valid redirect URL's are the once from domains you have set when added your platforms in the console interface.")
->label('abuse-limit', 10)
->label('abuse-key', 'url:{url},userId:{param-userId}')
->param('confirmation', '', function () use ($clients) {return new Host($clients);}, 'Confirmation URL to redirect user to your app after confirm token has been sent to user email.')
->param('confirm', '', function () use ($clients) {
return new Host($clients);
}, 'Confirmation URL to redirect user to your app after confirm token has been sent to user email.')
->action(
function ($confirmation) use ($response, $request, $projectDB, $user, $register, $project) {
function ($confirm) use ($response, $request, $projectDB, $user, $register, $project) {
if ($user->getAttribute('confirm', false)) {
throw new Exception('Email address is already confirmed', 400);
}
@ -269,16 +287,16 @@ $utopia->post('/v1/auth/register/confirm/resend')
throw new Exception('Failed saving user to DB', 500);
}
$confirmation = Template::parseURL($confirmation);
$confirmation['query'] = Template::mergeQuery(((isset($confirmation['query'])) ? $confirmation['query'] : ''), ['userId' => $user->getUid(), 'token' => $secret]);
$confirmation = Template::unParseURL($confirmation);
$confirm = Template::parseURL($confirm);
$confirm['query'] = Template::mergeQuery(((isset($confirm['query'])) ? $confirm['query'] : ''), ['userId' => $user->getUid(), 'token' => $secret]);
$confirm = Template::unParseURL($confirm);
$body = new Template(__DIR__.'/../config/locale/templates/'.Locale::getText('auth.emails.confirm.body'));
$body
->setParam('{{direction}}', Locale::getText('settings.direction'))
->setParam('{{project}}', $project->getAttribute('name', ['[APP-NAME]']))
->setParam('{{name}}', $user->getAttribute('name'))
->setParam('{{redirect}}', $confirmation)
->setParam('{{redirect}}', $confirm)
;
$mail = $register->get('smtp'); /* @var $mail \PHPMailer\PHPMailer\PHPMailer */
@ -309,10 +327,18 @@ $utopia->post('/v1/auth/login')
->label('sdk.cookies', true)
->label('abuse-limit', 10)
->label('abuse-key', 'url:{url},email:{param-email}')
->param('email', '', function () {return new Email();}, 'User account email address')
->param('password', '', function () {return new Password();}, 'User account password')
->param('success', null, function () use ($clients) {return new Host($clients);}, 'URL to redirect back to your app after a successful login attempt.')
->param('failure', null, function () use ($clients) {return new Host($clients);}, 'URL to redirect back to your app after a failed login attempt.')
->param('email', '', function () {
return new Email();
}, 'User account email address')
->param('password', '', function () {
return new Password();
}, 'User account password')
->param('success', null, function () use ($clients) {
return new Host($clients);
}, 'URL to redirect back to your app after a successful login attempt.')
->param('failure', null, function () use ($clients) {
return new Host($clients);
}, 'URL to redirect back to your app after a failed login attempt.')
->action(
function ($email, $password, $success, $failure) use ($response, $request, $projectDB, $audit, $webhook) {
$profile = $projectDB->getCollection([ // Get user by email address
@ -423,7 +449,9 @@ $utopia->delete('/v1/auth/logout/:id')
->label('sdk.method', 'logoutBySession')
->label('sdk.description', 'Use this endpoint to log out the currently logged in user from all his account sessions across all his different devices. When using the option id argument, only the session unique ID provider will be deleted.')
->label('abuse-limit', 100)
->param('id', null, function () {return new UID();}, 'User specific session unique ID number. if 0 delete all sessions.')
->param('id', null, function () {
return new UID();
}, 'User specific session unique ID number. if 0 delete all sessions.')
->action(
function ($id) use ($response, $request, $user, $projectDB, $audit) {
$tokens = $user->getAttribute('tokens', []);
@ -457,8 +485,12 @@ $utopia->post('/v1/auth/recovery')
->label('sdk.description', 'Sends the user an email with a temporary secret token for password reset. When the user clicks the confirmation link he is redirected back to your app password reset redirect URL with a secret token and email address values attached to the URL query string. Use the query string params to submit a request to the /auth/password/reset endpoint to complete the process.')
->label('abuse-limit', 10)
->label('abuse-key', 'url:{url},email:{param-email}')
->param('email', '', function () {return new Email();}, 'User account email address.')
->param('reset', '', function () use ($clients) {return new Host($clients);}, 'Reset URL in your app to redirect the user after the reset token has been sent to the user email.')
->param('email', '', function () {
return new Email();
}, 'User account email address.')
->param('reset', '', function () use ($clients) {
return new Host($clients);
}, 'Reset URL in your app to redirect the user after the reset token has been sent to the user email.')
->action(
function ($email, $reset) use ($request, $response, $projectDB, $register, $audit, $project) {
$profile = $projectDB->getCollection([ // Get user by email address
@ -537,10 +569,18 @@ $utopia->put('/v1/auth/recovery/reset')
->label('sdk.description', "Use this endpoint to complete the user account password reset. Both the **userId** and **token** arguments will be passed as query parameters to the redirect URL you have provided when sending your request to the /auth/recovery endpoint.\n\nPlease notice that in order to avoid a [Redirect Attacks](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) the only valid redirect URL's are the once from domains you have set when added your platforms in the console interface.")
->label('abuse-limit', 10)
->label('abuse-key', 'url:{url},userId:{param-userId}')
->param('userId', '', function () {return new UID();}, 'User account email address.')
->param('token', '', function () {return new Text(256);}, 'Valid reset token.')
->param('password-a', '', function () {return new Password();}, 'New password.')
->param('password-b', '', function () {return new Password();}, 'New password again.')
->param('userId', '', function () {
return new UID();
}, 'User account email address.')
->param('token', '', function () {
return new Text(256);
}, 'Valid reset token.')
->param('password-a', '', function () {
return new Password();
}, 'New password.')
->param('password-b', '', function () {
return new Password();
}, 'New password again.')
->action(
function ($userId, $token, $passwordA, $passwordB) use ($response, $projectDB, $audit) {
if ($passwordA !== $passwordB) {
@ -597,11 +637,18 @@ $utopia->get('/v1/auth/oauth/:provider')
->label('scope', 'auth')
->label('sdk.namespace', 'auth')
->label('sdk.method', 'oauth')
->label('sdk.location', true)
->label('abuse-limit', 50)
->label('abuse-key', 'ip:{ip}')
->param('provider', '', function () use ($providers) {return new WhiteList(array_keys($providers));}, 'OAuth Provider')
->param('success', '', function () use ($clients) {return new Host($clients);}, 'URL to redirect back to your app after a successful login attempt.', true)
->param('failure', '', function () use ($clients) {return new Host($clients);}, 'URL to redirect back to your app after a failed login attempt.', true)
->param('provider', '', function () use ($providers) {
return new WhiteList(array_keys($providers));
}, 'OAuth Provider')
->param('success', '', function () use ($clients) {
return new Host($clients);
}, 'URL to redirect back to your app after a successful login attempt.', true)
->param('failure', '', function () use ($clients) {
return new Host($clients);
}, 'URL to redirect back to your app after a failed login attempt.', true)
->action(
function ($provider, $success, $failure) use ($response, $request, $project) {
$callback = $request->getServer('REQUEST_SCHEME', 'https').'://'.$request->getServer('HTTP_HOST').'/v1/auth/oauth/callback/'.$provider.'/'.$project->getUid();
@ -635,14 +682,23 @@ $utopia->get('/v1/auth/oauth/callback/:provider/:projectId')
->desc('OAuth Callback')
->label('error', __DIR__.'/../views/general/error.phtml')
->label('scope', 'auth')
->label('sdk.namespace', 'auth')
->label('sdk.method', 'oauthCallback')
//->label('sdk.namespace', 'auth')
//->label('sdk.method', 'oauthCallback')
->label('abuse-limit', 50)
->label('abuse-key', 'ip:{ip}')
->param('projectId', '', function () {return new Text(1024);}, 'Project unique ID')
->param('provider', '', function () use ($providers) {return new WhiteList(array_keys($providers));}, 'OAuth provider')
->param('code', '', function () {return new Text(1024);}, 'OAuth code')
->param('state', '', function () {return new Text(2048);}, 'Login state params', true)
->label('docs', false)
->param('projectId', '', function () {
return new Text(1024);
}, 'Project unique ID')
->param('provider', '', function () use ($providers) {
return new WhiteList(array_keys($providers));
}, 'OAuth provider')
->param('code', '', function () {
return new Text(1024);
}, 'OAuth code')
->param('state', '', function () {
return new Text(2048);
}, 'Login state params', true)
->action(
function ($projectId, $provider, $code, $state) use ($response, $request, $domain) {
$response->redirect($request->getServer('REQUEST_SCHEME', 'https').'://'.$domain.'/v1/auth/oauth/'.$provider.'/redirect?'
@ -655,14 +711,20 @@ $utopia->get('/v1/auth/oauth/:provider/redirect')
->label('error', __DIR__.'/../views/general/error.phtml')
->label('webhook', 'auth.oauth')
->label('scope', 'auth')
->label('sdk.namespace', 'auth')
->label('sdk.method', 'oauthRedirect')
//->label('sdk.namespace', 'auth')
//->label('sdk.method', 'oauthRedirect')
->label('abuse-limit', 50)
->label('abuse-key', 'ip:{ip}')
->label('docs', false)
->param('provider', '', function () use ($providers) {return new WhiteList(array_keys($providers));}, 'OAuth provider')
->param('code', '', function () {return new Text(1024);}, 'OAuth code')
->param('state', '', function () {return new Text(2048);}, 'OAuth state params', true)
->param('provider', '', function () use ($providers) {
return new WhiteList(array_keys($providers));
}, 'OAuth provider')
->param('code', '', function () {
return new Text(1024);
}, 'OAuth code')
->param('state', '', function () {
return new Text(2048);
}, 'OAuth state params', true)
->action(
function ($provider, $code, $state) use ($response, $request, $user, $projectDB, $project, $audit) {
$callback = $request->getServer('REQUEST_SCHEME', 'https').'://'.$request->getServer('HTTP_HOST').'/v1/auth/oauth/callback/'.$provider.'/'.$project->getUid();
@ -716,7 +778,7 @@ $utopia->get('/v1/auth/oauth/:provider/redirect')
}
$oauthID = $oauth->getUserID($accessToken);
if (empty($oauthID)) {
if (!empty($state['failure'])) {
$response->redirect($state['failure'], 301, 0);
@ -726,7 +788,7 @@ $utopia->get('/v1/auth/oauth/:provider/redirect')
}
$current = Auth::tokenVerify($user->getAttribute('tokens', []), Auth::TOKEN_TYPE_LOGIN, Auth::$secret);
if ($current) {
$projectDB->deleteDocument($current); //throw new Exception('User already logged in', 401);
}
@ -740,6 +802,7 @@ $utopia->get('/v1/auth/oauth/:provider/redirect')
],
]) : $user;
if (empty($user)) { // No user logged in or with oauth provider ID, create new one or connect with account with same email
$name = $oauth->getUserName($accessToken);
$email = $oauth->getUserEmail($accessToken);
@ -753,7 +816,7 @@ $utopia->get('/v1/auth/oauth/:provider/redirect')
],
]);
if (empty($user->getUid())) { // Last option -> create user alone, generate random password
if (!$user || empty($user->getUid())) { // Last option -> create user alone, generate random password
Authorization::disable();
$user = $projectDB->createDocument([

View file

@ -87,45 +87,81 @@ $avatarCallback = function ($type, $code, $width, $height, $quality) use ($types
$utopia->get('/v1/avatars/credit-cards/:code')
->desc('Get Credit Card Icon')
->param('code', '', function () use ($types) {return new WhiteList(array_keys($types['credit-cards'])); }, 'Credit Card Code. Possible values: '.implode(', ', array_keys($types['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)
->param('code', '', function () use ($types) {
return new WhiteList(array_keys($types['credit-cards']));
}, 'Credit Card Code. Possible values: '.implode(', ', array_keys($types['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.namespace', 'avatars')
->label('sdk.method', 'getCreditCard')
->label('sdk.description', 'Need to display your users with your billing method or there payment methods? The credit card endpoint will return you the icon of the credit card provider you need. Use width, height and quality arguments to change the output settings.')
->action(function ($code, $width, $height, $quality) use ($avatarCallback) {return $avatarCallback('credit-cards', $code, $width, $height, $quality);});
->action(function ($code, $width, $height, $quality) use ($avatarCallback) {
return $avatarCallback('credit-cards', $code, $width, $height, $quality);
});
$utopia->get('/v1/avatars/browsers/:code')
->desc('Get Browser Icon')
->param('code', '', function () use ($types) {return new WhiteList(array_keys($types['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)
->param('code', '', function () use ($types) {
return new WhiteList(array_keys($types['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.namespace', 'avatars')
->label('sdk.method', 'getBrowser')
->label('sdk.description', 'You can use this endpoint to show different browser icons to your users, The code argument receives the browser code as appear in your user /account/sessions endpoint. Use width, height and quality arguments to change the output settings.')
->action(function ($code, $width, $height, $quality) use ($avatarCallback) {return $avatarCallback('browsers', $code, $width, $height, $quality);});
->action(function ($code, $width, $height, $quality) use ($avatarCallback) {
return $avatarCallback('browsers', $code, $width, $height, $quality);
});
$utopia->get('/v1/avatars/flags/:code')
->desc('Get Country Flag')
->param('code', '', function () use ($types) {return new WhiteList(array_keys($types['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)
->param('code', '', function () use ($types) {
return new WhiteList(array_keys($types['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.namespace', 'avatars')
->label('sdk.method', 'getFlag')
->label('sdk.description', 'You can use this endpoint to show different country flags icons to your users, The code argument receives the a 2 letter country code. Use width, height and quality arguments to change the output settings.')
->action(function ($code, $width, $height, $quality) use ($avatarCallback) {return $avatarCallback('flags', $code, $width, $height, $quality);});
->action(function ($code, $width, $height, $quality) use ($avatarCallback) {
return $avatarCallback('flags', $code, $width, $height, $quality);
});
$utopia->get('/v1/avatars/image')
->desc('Get Image from URL')
->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 4000', true)
->param('height', 400, function () {return new Range(0, 2000);}, 'Resize preview image height, Pass an integer between 0 to 4000', true)
->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 4000', true)
->param('height', 400, function () {
return new Range(0, 2000);
}, 'Resize preview image height, Pass an integer between 0 to 4000', true)
->label('scope', 'avatars.read')
->label('sdk.namespace', 'avatars')
->label('sdk.method', 'getImage')
@ -190,7 +226,9 @@ $utopia->get('/v1/avatars/image')
$utopia->get('/v1/avatars/favicon')
->desc('Get Favicon')
->param('url', '', function () {return new URL();}, 'Website URL which you want to fetch the favicon from.')
->param('url', '', function () {
return new URL();
}, 'Website URL which you want to fetch the favicon from.')
->label('scope', 'avatars.read')
->label('sdk.namespace', 'avatars')
->label('sdk.method', 'getFavicon')
@ -339,10 +377,18 @@ $utopia->get('/v1/avatars/favicon')
$utopia->get('/v1/avatars/qr')
->desc('Text to QR Generator')
->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', 0, function () {return new Range(0, 1);}, '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)
->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', 0, function () {
return new Range(0, 1);
}, '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.namespace', 'avatars')
->label('sdk.method', 'getQR')
@ -365,7 +411,6 @@ $utopia->get('/v1/avatars/qr')
->setContentType('image/png')
->send('', $writer->writeString($text))
;
}
);

View file

@ -175,7 +175,9 @@ $utopia->get('/console/database/collection')
->desc('Platform console project settings')
->label('permission', 'public')
->label('scope', 'console')
->param('id', '', function () {return new UID();}, 'Collection unique ID.')
->param('id', '', function () {
return new UID();
}, 'Collection unique ID.')
->action(function ($id) use ($layout, $projectDB) {
$collection = $projectDB->getDocument($id, false);
@ -216,7 +218,7 @@ $utopia->get('/console/users')
$page->setParam('providers', $providers);
$layout
->setParam('title', APP_NAME.' - '.Locale::getText('console.users.title'))
->setParam('title', APP_NAME.' - Users')
->setParam('body', $page);
});
@ -228,6 +230,6 @@ $utopia->get('/console/users/view')
$page = new View(__DIR__.'/../views/console/users/view.phtml');
$layout
->setParam('title', APP_NAME.' - '.Locale::getText('console.users.title'))
->setParam('title', APP_NAME.' - View User')
->setParam('body', $page);
});

View file

@ -27,10 +27,18 @@ $utopia->get('/v1/database')
->label('sdk.namespace', 'database')
->label('sdk.method', 'listCollections')
->label('sdk.description', 'Get a list of all the user collections. You can use the query params to filter your results. On admin mode, this endpoint will return a list of all of the project collections. [Learn more about different API modes](/docs/modes).')
->param('search', '', function () {return new Text(256);}, 'Search term to filter your list results.', true)
->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)
->param('search', '', function () {
return new Text(256);
}, 'Search term to filter your list results.', true)
->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);
@ -74,7 +82,9 @@ $utopia->get('/v1/database/:collectionId')
->label('sdk.namespace', 'database')
->label('sdk.method', 'getCollection')
->label('sdk.description', 'Get collection by its unique ID. This endpoint response returns a JSON object with the collection metadata.')
->param('collectionId', '', function () {return new UID();}, 'Collection unique ID.')
->param('collectionId', '', function () {
return new UID();
}, 'Collection unique ID.')
->action(
function ($collectionId) use ($response, $projectDB) {
$collection = $projectDB->getDocument($collectionId, false);
@ -94,15 +104,23 @@ $utopia->post('/v1/database')
->label('sdk.namespace', 'database')
->label('sdk.method', 'createCollection')
->label('sdk.description', 'Create a new Collection.')
->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. [Learn more about permissions and roles](/docs/permissions).', true)
->param('write', [], function () {return new ArrayList(new Text(64));}, 'An array of strings with write permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->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)
->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. [Learn more about permissions and roles](/docs/permissions).', true)
->param('write', [], function () {
return new ArrayList(new Text(64));
}, 'An array of strings with write permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->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 ($name, $read, $write, $rules) use ($response, $projectDB, $webhook, $audit) {
$parsedRules = [];
foreach($rules as &$rule) {
foreach ($rules as &$rule) {
$parsedRules[] = array_merge([
'$collection' => Database::SYSTEM_COLLECTION_RULES,
'$permissions' => [
@ -161,11 +179,21 @@ $utopia->put('/v1/database/:collectionId')
->label('sdk.namespace', 'database')
->label('sdk.method', 'updateCollection')
->label('sdk.description', 'Update collection by its unique ID.')
->param('collectionId', '', function () {return new UID();}, 'Collection unique ID.')
->param('name', null, function () {return new Text(256);}, 'Collection name.')
->param('read', [], function () {return new ArrayList(new Text(64));}, 'An array of strings with read permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->param('write', [], function () {return new ArrayList(new Text(64));}, 'An array of strings with write permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->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)
->param('collectionId', '', function () {
return new UID();
}, 'Collection unique ID.')
->param('name', null, function () {
return new Text(256);
}, 'Collection name.')
->param('read', [], function () {
return new ArrayList(new Text(64));
}, 'An array of strings with read permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->param('write', [], function () {
return new ArrayList(new Text(64));
}, 'An array of strings with write permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->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) {
$collection = $projectDB->getDocument($collectionId, false);
@ -176,7 +204,7 @@ $utopia->put('/v1/database/:collectionId')
$parsedRules = [];
foreach($rules as &$rule) {
foreach ($rules as &$rule) {
$parsedRules[] = array_merge([
'$collection' => Database::SYSTEM_COLLECTION_RULES,
'$permissions' => [
@ -211,7 +239,9 @@ $utopia->delete('/v1/database/:collectionId')
->label('sdk.namespace', 'database')
->label('sdk.method', 'deleteCollection')
->label('sdk.description', 'Delete a collection by its unique ID. Only users with write permissions have access to delete this resource.')
->param('collectionId', '', function () {return new UID();}, 'Collection unique ID.')
->param('collectionId', '', function () {
return new UID();
}, 'Collection unique ID.')
->action(
function ($collectionId) use ($response, $projectDB, $audit) {
$collection = $projectDB->getDocument($collectionId, false);
@ -240,16 +270,36 @@ $utopia->get('/v1/database/:collectionId/documents')
->label('sdk.namespace', 'database')
->label('sdk.method', 'listDocuments')
->label('sdk.description', 'Get a list of all the user documents. You can use the query params to filter your results. On admin mode, this endpoint will return a list of all of the project documents. [Learn more about different API modes](/docs/modes).')
->param('collectionId', null, function () {return new UID();}, 'Collection unique ID.')
->param('filters', [], function () {return new ArrayList(new Text(128));}, 'Array of filter strings. Each filter is constructed from a key name, comparison operator (=, !=, >, <, <=, >=) and a value. You can also use a dot (.) separator in attribute names to filter by child document attributes. Examples: \'name=John Doe\' or \'category.$uid>=5bed2d152c362\'', true)
->param('offset', 0, function () {return new Range(0, 900000000);}, 'Offset value. Use this value to manage pagination.', true)
->param('limit', 50, function () {return new Range(0, 1000);}, 'Maximum number of documents to return in response. Use this value to manage pagination.', true)
->param('order-field', '$uid', function () {return new Text(128);}, 'Document field that results will be sorted by.', true)
->param('order-type', 'ASC', function () {return new WhiteList(array('DESC', 'ASC'));}, 'Order direction. Possible values are DESC for descending order, or ASC for ascending order.', true)
->param('order-cast', '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)
->param('first', 0, function () {return new Range(0, 1);}, 'Return only first document. Pass 1 for true or 0 for false. The default value is 0.', true)
->param('last', 0, function () {return new Range(0, 1);}, 'Return only last document. Pass 1 for true or 0 for false. The default value is 0.', true)
->param('collectionId', null, function () {
return new UID();
}, 'Collection unique ID.')
->param('filters', [], function () {
return new ArrayList(new Text(128));
}, 'Array of filter strings. Each filter is constructed from a key name, comparison operator (=, !=, >, <, <=, >=) and a value. You can also use a dot (.) separator in attribute names to filter by child document attributes. Examples: \'name=John Doe\' or \'category.$uid>=5bed2d152c362\'', true)
->param('offset', 0, function () {
return new Range(0, 900000000);
}, 'Offset value. Use this value to manage pagination.', true)
->param('limit', 50, function () {
return new Range(0, 1000);
}, 'Maximum number of documents to return in response. Use this value to manage pagination.', true)
->param('order-field', '$uid', function () {
return new Text(128);
}, 'Document field that results will be sorted by.', true)
->param('order-type', 'ASC', function () {
return new WhiteList(array('DESC', 'ASC'));
}, 'Order direction. Possible values are DESC for descending order, or ASC for ascending order.', true)
->param('order-cast', '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)
->param('first', 0, function () {
return new Range(0, 1);
}, 'Return only first document. Pass 1 for true or 0 for false. The default value is 0.', true)
->param('last', 0, function () {
return new Range(0, 1);
}, 'Return only last document. Pass 1 for true or 0 for false. The default value is 0.', true)
->action(
function ($collectionId, $filters, $offset, $limit, $orderField, $orderType, $orderCast, $search, $first, $last) use ($response, $projectDB, $isDev) {
$collection = $projectDB->getDocument($collectionId, $isDev);
@ -306,8 +356,12 @@ $utopia->get('/v1/database/:collectionId/documents/:documentId')
->label('sdk.namespace', 'database')
->label('sdk.method', 'getDocument')
->label('sdk.description', 'Get document by its unique ID. This endpoint response returns a JSON object with the document data.')
->param('collectionId', null, function () {return new UID();}, 'Collection unique ID')
->param('documentId', null, function () {return new UID();}, 'Document unique ID')
->param('collectionId', null, function () {
return new UID();
}, 'Collection unique ID')
->param('documentId', null, function () {
return new UID();
}, 'Document unique ID')
->action(
function ($collectionId, $documentId) use ($response, $request, $projectDB, $isDev) {
$document = $projectDB->getDocument($documentId, $isDev);
@ -351,13 +405,27 @@ $utopia->post('/v1/database/:collectionId/documents')
->label('sdk.namespace', 'database')
->label('sdk.method', 'createDocument')
->label('sdk.description', 'Create a new Document.')
->param('collectionId', null, function () {return new UID();}, 'Collection unique ID.')
->param('data', [], function () {return new \Utopia\Validator\Mock();}, 'Document data as JSON string.')
->param('read', [], function () {return new ArrayList(new Text(64));}, 'An array of strings with read permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->param('write', [], function () {return new ArrayList(new Text(64));}, 'An array of strings with write permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->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)
->param('collectionId', null, function () {
return new UID();
}, 'Collection unique ID.')
->param('data', [], function () {
return new \Utopia\Validator\Mock();
}, 'Document data as JSON string.')
->param('read', [], function () {
return new ArrayList(new Text(64));
}, 'An array of strings with read permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->param('write', [], function () {
return new ArrayList(new Text(64));
}, 'An array of strings with write permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->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) {
if (empty($data)) {
@ -454,11 +522,21 @@ $utopia->patch('/v1/database/:collectionId/documents/:documentId')
->label('scope', 'documents.write')
->label('sdk.namespace', 'database')
->label('sdk.method', 'updateDocument')
->param('collectionId', null, function () {return new UID();}, 'Collection unique ID')
->param('documentId', null, function () {return new UID();}, 'Document unique ID')
->param('data', [], function () {return new \Utopia\Validator\Mock();}, 'Document data as JSON string')
->param('read', [], function () {return new ArrayList(new Text(64));}, 'An array of strings with read permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->param('write', [], function () {return new ArrayList(new Text(64));}, 'An array of strings with write permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->param('collectionId', null, function () {
return new UID();
}, 'Collection unique ID')
->param('documentId', null, function () {
return new UID();
}, 'Document unique ID')
->param('data', [], function () {
return new \Utopia\Validator\Mock();
}, 'Document data as JSON string')
->param('read', [], function () {
return new ArrayList(new Text(64));
}, 'An array of strings with read permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->param('write', [], function () {
return new ArrayList(new Text(64));
}, 'An array of strings with write permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->action(
function ($collectionId, $documentId, $data, $read, $write) use ($response, $projectDB, &$output, $webhook, $audit, $isDev) {
$collection = $projectDB->getDocument($collectionId/*, $isDev*/);
@ -531,11 +609,14 @@ $utopia->delete('/v1/database/:collectionId/documents/:documentId')
->label('sdk.namespace', 'database')
->label('sdk.method', 'deleteDocument')
->label('sdk.description', 'Delete document by its unique ID. This endpoint deletes only the parent documents, his attributes and relations to other documents. Child documents **will not** be deleted.')
->param('collectionId', null, function () {return new UID();}, 'Collection unique ID')
->param('documentId', null, function () {return new UID();}, 'Document unique ID')
->param('collectionId', null, function () {
return new UID();
}, 'Collection unique ID')
->param('documentId', null, function () {
return new UID();
}, 'Document unique ID')
->action(
function ($collectionId, $documentId) use ($response, $projectDB, $audit, $isDev) {
$collection = $projectDB->getDocument($collectionId, $isDev);
$document = $projectDB->getDocument($documentId, $isDev);

View file

@ -67,7 +67,9 @@ $utopia->get('/v1/projects/:projectId')
->label('scope', 'projects.read')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'getProject')
->param('projectId', '', function () {return new UID();}, 'Project unique ID.')
->param('projectId', '', function () {
return new UID();
}, 'Project unique ID.')
->action(
function ($projectId) use ($request, $response, $providers, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -94,7 +96,9 @@ $utopia->get('/v1/projects/:projectId/usage')
->label('scope', 'projects.read')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'getProjectUsage')
->param('projectId', '', function () {return new UID();}, 'Project unique ID.')
->param('projectId', '', function () {
return new UID();
}, 'Project unique ID.')
->action(
function ($projectId) use ($response, $consoleDB, $projectDB, $register) {
$project = $consoleDB->getDocument($projectId);
@ -182,11 +186,15 @@ $utopia->get('/v1/projects/:projectId/usage')
$response->json([
'requests' => [
'data' => $requests,
'total' => array_sum(array_map(function ($item) {return $item['value'];}, $requests)),
'total' => array_sum(array_map(function ($item) {
return $item['value'];
}, $requests)),
],
'network' => [
'data' => $network,
'total' => array_sum(array_map(function ($item) {return $item['value'];}, $network)),
'total' => array_sum(array_map(function ($item) {
return $item['value'];
}, $network)),
],
'collections' => [
'data' => $collections,
@ -194,7 +202,9 @@ $utopia->get('/v1/projects/:projectId/usage')
],
'documents' => [
'data' => $documents,
'total' => array_sum(array_map(function ($item) {return $item['total'];}, $documents)),
'total' => array_sum(array_map(function ($item) {
return $item['total'];
}, $documents)),
],
'users' => [
'data' => [],
@ -205,7 +215,8 @@ $utopia->get('/v1/projects/:projectId/usage')
'total' => $tasksTotal,
],
'storage' => [
'total' => $projectDB->getCount([
'total' => $projectDB->getCount(
[
'filters' => [
'$collection='.Database::SYSTEM_COLLECTION_FILES,
],
@ -221,17 +232,39 @@ $utopia->post('/v1/projects')
->label('scope', 'projects.write')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'createProject')
->param('name', null, function () {return new Text(100);}, 'Project name')
->param('teamId', '', function () {return new UID();}, 'Team unique ID.')
->param('description', '', function () {return new Text(255);}, 'Project description', true)
->param('logo', '', function () {return new Text(1024);}, 'Project logo', true)
->param('url', '', function () {return new URL();}, 'Project URL', true)
->param('legalName', '', function () {return new Text(256);}, 'Project Legal Name', true)
->param('legalCountry', '', function () {return new Text(256);}, 'Project Legal Country', true)
->param('legalState', '', function () {return new Text(256);}, 'Project Legal State', true)
->param('legalCity', '', function () {return new Text(256);}, 'Project Legal City', true)
->param('legalAddress', '', function () {return new Text(256);}, 'Project Legal Address', true)
->param('legalTaxId', '', function () {return new Text(256);}, 'Project Legal Tax ID', true)
->param('name', null, function () {
return new Text(100);
}, 'Project name')
->param('teamId', '', function () {
return new UID();
}, 'Team unique ID.')
->param('description', '', function () {
return new Text(255);
}, 'Project description', true)
->param('logo', '', function () {
return new Text(1024);
}, 'Project logo', true)
->param('url', '', function () {
return new URL();
}, 'Project URL', true)
->param('legalName', '', function () {
return new Text(256);
}, 'Project Legal Name', true)
->param('legalCountry', '', function () {
return new Text(256);
}, 'Project Legal Country', true)
->param('legalState', '', function () {
return new Text(256);
}, 'Project Legal State', true)
->param('legalCity', '', function () {
return new Text(256);
}, 'Project Legal City', true)
->param('legalAddress', '', function () {
return new Text(256);
}, 'Project Legal Address', true)
->param('legalTaxId', '', function () {
return new Text(256);
}, 'Project Legal Tax ID', true)
->action(
function ($name, $teamId, $description, $logo, $url, $legalName, $legalCountry, $legalState, $legalCity, $legalAddress, $legalTaxId) use ($response, $user, $consoleDB, $projectDB) {
$team = $projectDB->getDocument($teamId);
@ -260,7 +293,8 @@ $utopia->post('/v1/projects')
'teamId' => $team->getUid(),
'webhooks' => [],
'keys' => [],
]);
]
);
if (false === $project) {
throw new Exception('Failed saving project to DB', 500);
@ -280,17 +314,39 @@ $utopia->patch('/v1/projects/:projectId')
->label('scope', 'projects.write')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'updateProject')
->param('projectId', '', function () {return new UID();}, 'Project unique ID.')
->param('name', null, function () {return new Text(100);}, 'Project name')
->param('description', '', function () {return new Text(255);}, 'Project description', true)
->param('logo', '', function () {return new Text(1024);}, 'Project logo', true)
->param('url', '', function () {return new URL();}, 'Project URL', true)
->param('legalName', '', function () {return new Text(256);}, 'Project Legal Name', true)
->param('legalCountry', '', function () {return new Text(256);}, 'Project Legal Country', true)
->param('legalState', '', function () {return new Text(256);}, 'Project Legal State', true)
->param('legalCity', '', function () {return new Text(256);}, 'Project Legal City', true)
->param('legalAddress', '', function () {return new Text(256);}, 'Project Legal Address', true)
->param('legalTaxId', '', function () {return new Text(256);}, 'Project Legal Tax ID', true)
->param('projectId', '', function () {
return new UID();
}, 'Project unique ID.')
->param('name', null, function () {
return new Text(100);
}, 'Project name')
->param('description', '', function () {
return new Text(255);
}, 'Project description', true)
->param('logo', '', function () {
return new Text(1024);
}, 'Project logo', true)
->param('url', '', function () {
return new URL();
}, 'Project URL', true)
->param('legalName', '', function () {
return new Text(256);
}, 'Project Legal Name', true)
->param('legalCountry', '', function () {
return new Text(256);
}, 'Project Legal Country', true)
->param('legalState', '', function () {
return new Text(256);
}, 'Project Legal State', true)
->param('legalCity', '', function () {
return new Text(256);
}, 'Project Legal City', true)
->param('legalAddress', '', function () {
return new Text(256);
}, 'Project Legal Address', true)
->param('legalTaxId', '', function () {
return new Text(256);
}, 'Project Legal Tax ID', true)
->action(
function ($projectId, $name, $description, $logo, $url, $legalName, $legalCountry, $legalState, $legalCity, $legalAddress, $legalTaxId) use ($response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -325,10 +381,18 @@ $utopia->patch('/v1/projects/:projectId/oauth')
->label('scope', 'projects.write')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'updateProjectOAuth')
->param('projectId', '', function () {return new UID();}, 'Project unique ID.')
->param('provider', '', function () use ($providers) {return new WhiteList(array_keys($providers));}, 'Provider Name', false)
->param('appId', '', function () {return new Text(256);}, 'Provider App ID', true)
->param('secret', '', function () {return new text(256);}, 'Provider Secret Key', true)
->param('projectId', '', function () {
return new UID();
}, 'Project unique ID.')
->param('provider', '', function () use ($providers) {
return new WhiteList(array_keys($providers));
}, 'Provider Name', false)
->param('appId', '', function () {
return new Text(256);
}, 'Provider App ID', true)
->param('secret', '', function () {
return new text(256);
}, 'Provider Secret Key', true)
->action(
function ($projectId, $provider, $appId, $secret) use ($request, $response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -366,7 +430,9 @@ $utopia->delete('/v1/projects/:projectId')
->label('scope', 'projects.write')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'deleteProject')
->param('projectId', '', function () {return new UID();}, 'Project unique ID.')
->param('projectId', '', function () {
return new UID();
}, 'Project unique ID.')
->action(
function ($projectId) use ($response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -400,7 +466,9 @@ $utopia->get('/v1/projects/:projectId/webhooks')
->label('scope', 'projects.read')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'listWebhooks')
->param('projectId', '', function () {return new UID();}, 'Project unique ID.')
->param('projectId', '', function () {
return new UID();
}, 'Project unique ID.')
->action(
function ($projectId) use ($request, $response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -432,8 +500,12 @@ $utopia->get('/v1/projects/:projectId/webhooks/:webhookId')
->label('scope', 'projects.read')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'getWebhook')
->param('projectId', null, function () {return new UID();}, 'Project unique ID.')
->param('webhookId', null, function () {return new UID();}, 'Webhook unique ID.')
->param('projectId', null, function () {
return new UID();
}, 'Project unique ID.')
->param('webhookId', null, function () {
return new UID();
}, 'Webhook unique ID.')
->action(
function ($projectId, $webhookId) use ($request, $response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -464,13 +536,27 @@ $utopia->post('/v1/projects/:projectId/webhooks')
->label('scope', 'projects.write')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'createWebhook')
->param('projectId', null, function () {return new UID();}, 'Project unique ID.')
->param('name', null, function () {return new Text(256);}, 'Webhook name')
->param('events', null, function () {return new ArrayList(new Text(256));}, 'Webhook events list')
->param('url', null, function () {return new Text(2000);}, 'Webhook URL')
->param('security', null, function () {return new Range(0, 1);}, 'Certificate verification, 0 for disabled or 1 for enabled')
->param('httpUser', '', function () {return new Text(256);}, 'Webhook HTTP user', true)
->param('httpPass', '', function () {return new Text(256);}, 'Webhook HTTP password', true)
->param('projectId', null, function () {
return new UID();
}, 'Project unique ID.')
->param('name', null, function () {
return new Text(256);
}, 'Webhook name')
->param('events', null, function () {
return new ArrayList(new Text(256));
}, 'Webhook events list')
->param('url', null, function () {
return new Text(2000);
}, 'Webhook URL')
->param('security', null, function () {
return new Range(0, 1);
}, 'Certificate verification, 0 for disabled or 1 for enabled')
->param('httpUser', '', function () {
return new Text(256);
}, 'Webhook HTTP user', true)
->param('httpPass', '', function () {
return new Text(256);
}, 'Webhook HTTP password', true)
->action(
function ($projectId, $name, $events, $url, $security, $httpUser, $httpPass) use ($request, $response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -528,14 +614,30 @@ $utopia->put('/v1/projects/:projectId/webhooks/:webhookId')
->label('scope', 'projects.write')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'updateWebhook')
->param('projectId', null, function () {return new UID();}, 'Project unique ID.')
->param('webhookId', null, function () {return new UID();}, 'Webhook unique ID.')
->param('name', null, function () {return new Text(256);}, 'Webhook name')
->param('events', null, function () {return new ArrayList(new Text(256));}, 'Webhook events list')
->param('url', null, function () {return new Text(2000);}, 'Webhook URL')
->param('security', null, function () {return new Range(0, 1);}, 'Certificate verification, 0 for disabled or 1 for enabled')
->param('httpUser', '', function () {return new Text(256);}, 'Webhook HTTP user', true)
->param('httpPass', '', function () {return new Text(256);}, 'Webhook HTTP password', true)
->param('projectId', null, function () {
return new UID();
}, 'Project unique ID.')
->param('webhookId', null, function () {
return new UID();
}, 'Webhook unique ID.')
->param('name', null, function () {
return new Text(256);
}, 'Webhook name')
->param('events', null, function () {
return new ArrayList(new Text(256));
}, 'Webhook events list')
->param('url', null, function () {
return new Text(2000);
}, 'Webhook URL')
->param('security', null, function () {
return new Range(0, 1);
}, 'Certificate verification, 0 for disabled or 1 for enabled')
->param('httpUser', '', function () {
return new Text(256);
}, 'Webhook HTTP user', true)
->param('httpPass', '', function () {
return new Text(256);
}, 'Webhook HTTP password', true)
->action(
function ($projectId, $webhookId, $name, $events, $url, $security, $httpUser, $httpPass) use ($request, $response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -583,8 +685,12 @@ $utopia->delete('/v1/projects/:projectId/webhooks/:webhookId')
->label('scope', 'projects.write')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'deleteWebhook')
->param('projectId', null, function () {return new UID();}, 'Project unique ID.')
->param('webhookId', null, function () {return new UID();}, 'Webhook unique ID.')
->param('projectId', null, function () {
return new UID();
}, 'Project unique ID.')
->param('webhookId', null, function () {
return new UID();
}, 'Webhook unique ID.')
->action(
function ($projectId, $webhookId) use ($response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -614,7 +720,9 @@ $utopia->get('/v1/projects/:projectId/keys')
->label('scope', 'projects.read')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'listKeys')
->param('projectId', null, function () {return new UID();}, 'Project unique ID.')
->param('projectId', null, function () {
return new UID();
}, 'Project unique ID.')
->action(
function ($projectId) use ($response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -632,8 +740,12 @@ $utopia->get('/v1/projects/:projectId/keys/:keyId')
->label('scope', 'projects.read')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'getKey')
->param('projectId', null, function () {return new UID();}, 'Project unique ID.')
->param('keyId', null, function () {return new UID();}, 'Key unique ID.')
->param('projectId', null, function () {
return new UID();
}, 'Project unique ID.')
->param('keyId', null, function () {
return new UID();
}, 'Key unique ID.')
->action(
function ($projectId, $keyId) use ($response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -657,9 +769,15 @@ $utopia->post('/v1/projects/:projectId/keys')
->label('scope', 'projects.write')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'createKey')
->param('projectId', null, function () {return new UID();}, 'Project unique ID.')
->param('name', null, function () {return new Text(256);}, 'Key name')
->param('scopes', null, function () use ($scopes) {return new ArrayList(new WhiteList($scopes));}, 'Key scopes list')
->param('projectId', null, function () {
return new UID();
}, 'Project unique ID.')
->param('name', null, function () {
return new Text(256);
}, 'Key name')
->param('scopes', null, function () use ($scopes) {
return new ArrayList(new WhiteList($scopes));
}, 'Key scopes list')
->action(
function ($projectId, $name, $scopes) use ($response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -703,10 +821,18 @@ $utopia->put('/v1/projects/:projectId/keys/:keyId')
->label('scope', 'projects.write')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'updateKey')
->param('projectId', null, function () {return new UID();}, 'Project unique ID.')
->param('keyId', null, function () {return new UID();}, 'Key unique ID.')
->param('name', null, function () {return new Text(256);}, 'Key name')
->param('scopes', null, function () use ($scopes) {return new ArrayList(new WhiteList($scopes));}, 'Key scopes list')
->param('projectId', null, function () {
return new UID();
}, 'Project unique ID.')
->param('keyId', null, function () {
return new UID();
}, 'Key unique ID.')
->param('name', null, function () {
return new Text(256);
}, 'Key name')
->param('scopes', null, function () use ($scopes) {
return new ArrayList(new WhiteList($scopes));
}, 'Key scopes list')
->action(
function ($projectId, $keyId, $name, $scopes) use ($response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -739,8 +865,12 @@ $utopia->delete('/v1/projects/:projectId/keys/:keyId')
->label('scope', 'projects.write')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'deleteKey')
->param('projectId', null, function () {return new UID();}, 'Project unique ID.')
->param('keyId', null, function () {return new UID();}, 'Key unique ID.')
->param('projectId', null, function () {
return new UID();
}, 'Project unique ID.')
->param('keyId', null, function () {
return new UID();
}, 'Key unique ID.')
->action(
function ($projectId, $keyId) use ($response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -770,7 +900,9 @@ $utopia->get('/v1/projects/:projectId/tasks')
->label('scope', 'projects.read')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'listTasks')
->param('projectId', '', function () {return new UID();}, 'Project unique ID.')
->param('projectId', '', function () {
return new UID();
}, 'Project unique ID.')
->action(
function ($projectId) use ($request, $response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -802,8 +934,12 @@ $utopia->get('/v1/projects/:projectId/tasks/:taskId')
->label('scope', 'projects.read')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'getTask')
->param('projectId', null, function () {return new UID();}, 'Project unique ID.')
->param('taskId', null, function () {return new UID();}, 'Task unique ID.')
->param('projectId', null, function () {
return new UID();
}, 'Project unique ID.')
->param('taskId', null, function () {
return new UID();
}, 'Task unique ID.')
->action(
function ($projectId, $taskId) use ($request, $response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -834,16 +970,36 @@ $utopia->post('/v1/projects/:projectId/tasks')
->label('scope', 'projects.write')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'createTask')
->param('projectId', null, function () {return new UID();}, 'Project unique ID.')
->param('name', null, function () {return new Text(256);}, 'Task name')
->param('status', null, function () {return new WhiteList(['play', 'pause']);}, 'Task status')
->param('schedule', null, function () {return new Cron();}, 'Task schedule syntax')
->param('security', null, function () {return new Range(0, 1);}, 'Certificate verification, 0 for disabled or 1 for enabled')
->param('httpMethod', '', function () {return new WhiteList(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT']);}, 'Task HTTP method')
->param('httpUrl', '', function () {return new URL();}, 'Task HTTP URL')
->param('httpHeaders', null, function () {return new ArrayList(new Text(256));}, 'Task HTTP headers list', true)
->param('httpUser', '', function () {return new Text(256);}, 'Task HTTP user', true)
->param('httpPass', '', function () {return new Text(256);}, 'Task HTTP password', true)
->param('projectId', null, function () {
return new UID();
}, 'Project unique ID.')
->param('name', null, function () {
return new Text(256);
}, 'Task name')
->param('status', null, function () {
return new WhiteList(['play', 'pause']);
}, 'Task status')
->param('schedule', null, function () {
return new Cron();
}, 'Task schedule syntax')
->param('security', null, function () {
return new Range(0, 1);
}, 'Certificate verification, 0 for disabled or 1 for enabled')
->param('httpMethod', '', function () {
return new WhiteList(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT']);
}, 'Task HTTP method')
->param('httpUrl', '', function () {
return new URL();
}, 'Task HTTP URL')
->param('httpHeaders', null, function () {
return new ArrayList(new Text(256));
}, 'Task HTTP headers list', true)
->param('httpUser', '', function () {
return new Text(256);
}, 'Task HTTP user', true)
->param('httpPass', '', function () {
return new Text(256);
}, 'Task HTTP password', true)
->action(
function ($projectId, $name, $status, $schedule, $security, $httpMethod, $httpUrl, $httpHeaders, $httpUser, $httpPass) use ($request, $response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -916,17 +1072,39 @@ $utopia->put('/v1/projects/:projectId/tasks/:taskId')
->label('scope', 'projects.write')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'updateTask')
->param('projectId', null, function () {return new UID();}, 'Project unique ID.')
->param('taskId', null, function () {return new UID();}, 'Task unique ID.')
->param('name', null, function () {return new Text(256);}, 'Task name')
->param('status', null, function () {return new WhiteList(['play', 'pause']);}, 'Task status')
->param('schedule', null, function () {return new Cron();}, 'Task schedule syntax')
->param('security', null, function () {return new Range(0, 1);}, 'Certificate verification, 0 for disabled or 1 for enabled')
->param('httpMethod', '', function () {return new WhiteList(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT']);}, 'Task HTTP method')
->param('httpUrl', '', function () {return new URL();}, 'Task HTTP URL')
->param('httpHeaders', null, function () {return new ArrayList(new Text(256));}, 'Task HTTP headers list', true)
->param('httpUser', '', function () {return new Text(256);}, 'Task HTTP user', true)
->param('httpPass', '', function () {return new Text(256);}, 'Task HTTP password', true)
->param('projectId', null, function () {
return new UID();
}, 'Project unique ID.')
->param('taskId', null, function () {
return new UID();
}, 'Task unique ID.')
->param('name', null, function () {
return new Text(256);
}, 'Task name')
->param('status', null, function () {
return new WhiteList(['play', 'pause']);
}, 'Task status')
->param('schedule', null, function () {
return new Cron();
}, 'Task schedule syntax')
->param('security', null, function () {
return new Range(0, 1);
}, 'Certificate verification, 0 for disabled or 1 for enabled')
->param('httpMethod', '', function () {
return new WhiteList(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT']);
}, 'Task HTTP method')
->param('httpUrl', '', function () {
return new URL();
}, 'Task HTTP URL')
->param('httpHeaders', null, function () {
return new ArrayList(new Text(256));
}, 'Task HTTP headers list', true)
->param('httpUser', '', function () {
return new Text(256);
}, 'Task HTTP user', true)
->param('httpPass', '', function () {
return new Text(256);
}, 'Task HTTP password', true)
->action(
function ($projectId, $taskId, $name, $status, $schedule, $security, $httpMethod, $httpUrl, $httpHeaders, $httpUser, $httpPass) use ($request, $response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -986,8 +1164,12 @@ $utopia->delete('/v1/projects/:projectId/tasks/:taskId')
->label('scope', 'projects.write')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'deleteTask')
->param('projectId', null, function () {return new UID();}, 'Project unique ID.')
->param('taskId', null, function () {return new UID();}, 'Task unique ID.')
->param('projectId', null, function () {
return new UID();
}, 'Project unique ID.')
->param('taskId', null, function () {
return new UID();
}, 'Task unique ID.')
->action(
function ($projectId, $taskId) use ($response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -1017,7 +1199,9 @@ $utopia->get('/v1/projects/:projectId/platforms')
->label('scope', 'projects.read')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'listPlatforms')
->param('projectId', '', function () {return new UID();}, 'Project unique ID.')
->param('projectId', '', function () {
return new UID();
}, 'Project unique ID.')
->action(
function ($projectId) use ($request, $response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -1037,8 +1221,12 @@ $utopia->get('/v1/projects/:projectId/platforms/:platformId')
->label('scope', 'projects.read')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'getPlatform')
->param('projectId', null, function () {return new UID();}, 'Project unique ID.')
->param('platformId', null, function () {return new UID();}, 'Platform unique ID.')
->param('projectId', null, function () {
return new UID();
}, 'Project unique ID.')
->param('platformId', null, function () {
return new UID();
}, 'Platform unique ID.')
->action(
function ($projectId, $platformId) use ($request, $response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -1062,12 +1250,24 @@ $utopia->post('/v1/projects/:projectId/platforms')
->label('scope', 'projects.write')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'createPlatform')
->param('projectId', null, function () {return new UID();}, 'Project unique ID.')
->param('type', null, function () {return new WhiteList(['web', 'ios', 'android', 'unity']);}, 'Platform name')
->param('name', null, function () {return new Text(256);}, 'Platform name')
->param('key', '', function () {return new Text(256);}, 'Package name for android or bundle ID for iOS', true)
->param('store', '', function () {return new Text(256);}, 'App store or Google Play store ID', true)
->param('url', '', function () {return new URL();}, 'Platform client URL', true)
->param('projectId', null, function () {
return new UID();
}, 'Project unique ID.')
->param('type', null, function () {
return new WhiteList(['web', 'ios', 'android', 'unity']);
}, 'Platform name')
->param('name', null, function () {
return new Text(256);
}, 'Platform name')
->param('key', '', function () {
return new Text(256);
}, 'Package name for android or bundle ID for iOS', true)
->param('store', '', function () {
return new Text(256);
}, 'App store or Google Play store ID', true)
->param('url', '', function () {
return new URL();
}, 'Platform client URL', true)
->action(
function ($projectId, $type, $name, $key, $store, $url) use ($response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -1115,12 +1315,24 @@ $utopia->put('/v1/projects/:projectId/platforms/:platformId')
->label('scope', 'projects.write')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'updatePlatform')
->param('projectId', null, function () {return new UID();}, 'Project unique ID.')
->param('platformId', null, function () {return new UID();}, 'Platform unique ID.')
->param('name', null, function () {return new Text(256);}, 'Platform name')
->param('key', '', function () {return new Text(256);}, 'Package name for android or bundle ID for iOS', true)
->param('store', '', function () {return new Text(256);}, 'App store or Google Play store ID', true)
->param('url', '', function () {return new URL();}, 'Platform client URL', true)
->param('projectId', null, function () {
return new UID();
}, 'Project unique ID.')
->param('platformId', null, function () {
return new UID();
}, 'Platform unique ID.')
->param('name', null, function () {
return new Text(256);
}, 'Platform name')
->param('key', '', function () {
return new Text(256);
}, 'Package name for android or bundle ID for iOS', true)
->param('store', '', function () {
return new Text(256);
}, 'App store or Google Play store ID', true)
->param('url', '', function () {
return new URL();
}, 'Platform client URL', true)
->action(
function ($projectId, $platformId, $name, $key, $store, $url) use ($response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@ -1156,8 +1368,12 @@ $utopia->delete('/v1/projects/:projectId/platforms/:platformId')
->label('scope', 'projects.write')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'deletePlatform')
->param('projectId', null, function () {return new UID();}, 'Project unique ID.')
->param('platformId', null, function () {return new UID();}, 'Platform unique ID.')
->param('projectId', null, function () {
return new UID();
}, 'Project unique ID.')
->param('platformId', null, function () {
return new UID();
}, 'Platform unique ID.')
->action(
function ($projectId, $platformId) use ($response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);

View file

@ -119,10 +119,18 @@ $utopia->get('/v1/storage/files')
->label('sdk.namespace', 'storage')
->label('sdk.method', 'listFiles')
->label('sdk.description', 'Get a list of all the user files. You can use the query params to filter your results. On admin mode, this endpoint will return a list of all of the project files. [Learn more about different API modes](/docs/modes).')
->param('search', '', function () {return new Text(256);}, 'Search term to filter your list results.', true)
->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)
->param('search', '', function () {
return new Text(256);
}, 'Search term to filter your list results.', true)
->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) {
$results = $projectDB->getCollection([
@ -151,7 +159,9 @@ $utopia->get('/v1/storage/files/:fileId')
->label('sdk.namespace', 'storage')
->label('sdk.method', 'getFile')
->label('sdk.description', 'Get file by its unique ID. This endpoint response returns a JSON object with the file metadata.')
->param('fileId', '', function () {return new UID();}, 'File unique ID.')
->param('fileId', '', function () {
return new UID();
}, 'File unique ID.')
->action(
function ($fileId) use ($response, $projectDB) {
$file = $projectDB->getDocument($fileId);
@ -170,12 +180,24 @@ $utopia->get('/v1/storage/files/:fileId/preview')
->label('sdk.namespace', 'storage')
->label('sdk.method', 'getFilePreview')
->label('sdk.description', 'Get file preview image. Currently, this method supports preview for image files (jpg, png, and gif), other supported formats, like pdf, docs, slides, and spreadsheets will return file icon image. You can also pass query string arguments for cutting and resizing your preview image.')
->param('fileId', '', function () {return new UID();}, 'File unique ID')
->param('width', 0, function () {return new Range(0, 4000);}, 'Resize preview image width, Pass an integer between 0 to 4000', true)
->param('height', 0, function () {return new Range(0, 4000);}, 'Resize preview image height, Pass an integer between 0 to 4000', true)
->param('quality', 100, function () {return new Range(0, 100);}, 'Preview image quality. Pass an integer between 0 to 100. Defaults to 100', true)
->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)
->param('fileId', '', function () {
return new UID();
}, 'File unique ID')
->param('width', 0, function () {
return new Range(0, 4000);
}, 'Resize preview image width, Pass an integer between 0 to 4000', true)
->param('height', 0, function () {
return new Range(0, 4000);
}, 'Resize preview image height, Pass an integer between 0 to 4000', true)
->param('quality', 100, function () {
return new Range(0, 100);
}, 'Preview image quality. Pass an integer between 0 to 100. Defaults to 100', true)
->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)
//->param('storage', 'local', function () {return new WhiteList(array('local'));}, 'Selected storage device. defaults to local')
//->param('token', '', function () {return new Text(128);}, 'Preview token', true)
->action(
@ -282,7 +304,9 @@ $utopia->get('/v1/storage/files/:fileId/download')
->label('sdk.namespace', 'storage')
->label('sdk.method', 'getFileDownload')
->label('sdk.description', 'Get file content by its unique ID. The endpoint response return with a \'Content-Disposition: attachment\' header that tells the browser to start downloading the file to user downloads directory.')
->param('fileId', '', function () {return new UID();}, 'File unique ID.')
->param('fileId', '', function () {
return new UID();
}, 'File unique ID.')
->action(
function ($fileId) use ($response, $request, $projectDB) {
$file = $projectDB->getDocument($fileId);
@ -332,8 +356,12 @@ $utopia->get('/v1/storage/files/:fileId/view')
->label('sdk.namespace', 'storage')
->label('sdk.method', 'getFileView')
->label('sdk.description', 'Get file content by its unique ID. This endpoint is similar to the download method but returns with no \'Content-Disposition: attachment\' header.')
->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)
->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, $request, $projectDB, $mimes) {
$file = $projectDB->getDocument($fileId);
@ -400,10 +428,18 @@ $utopia->post('/v1/storage/files')
->label('sdk.method', 'createFile')
->label('sdk.description', 'Create a new file. The user who creates the file will automatically be assigned to read and write access unless he has passed custom values for read and write arguments.')
->label('sdk.consumes', 'multipart/form-data')
->param('files', [], function () {return new File();}, 'Binary Files.', false)
->param('read', [], function () {return new ArrayList(new Text(64));}, 'An array of strings with read permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->param('write', [], function () {return new ArrayList(new Text(64));}, 'An array of strings with write permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->param('folderId', '', function () {return new UID();}, 'Folder to associate files with.', true)
->param('files', [], function () {
return new File();
}, 'Binary Files.', false)
->param('read', [], function () {
return new ArrayList(new Text(64));
}, 'An array of strings with read permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->param('write', [], function () {
return new ArrayList(new Text(64));
}, 'An array of strings with write permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->param('folderId', '', function () {
return new UID();
}, 'Folder to associate files with.', true)
->action(
function ($files, $read, $write, $folderId) use ($request, $response, $user, $projectDB, $audit, $usage) {
$files = $request->getFiles('files');
@ -522,10 +558,18 @@ $utopia->put('/v1/storage/files/:fileId')
->label('sdk.namespace', 'storage')
->label('sdk.method', 'updateFile')
->label('sdk.description', 'Update file by its unique ID. Only users with write permissions have access to update this resource.')
->param('fileId', '', function () {return new UID();}, 'File unique ID.')
->param('read', [], function () {return new ArrayList(new Text(64));}, 'An array of strings with read permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->param('write', [], function () {return new ArrayList(new Text(64));}, 'An array of strings with write permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->param('folderId', '', function () {return new UID();}, 'Folder to associate files with.', true)
->param('fileId', '', function () {
return new UID();
}, 'File unique ID.')
->param('read', [], function () {
return new ArrayList(new Text(64));
}, 'An array of strings with read permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->param('write', [], function () {
return new ArrayList(new Text(64));
}, 'An array of strings with write permissions. [Learn more about permissions and roles](/docs/permissions).', true)
->param('folderId', '', function () {
return new UID();
}, 'Folder to associate files with.', true)
->action(
function ($fileId, $read, $write, $folderId) use ($response, $projectDB) {
$file = $projectDB->getDocument($fileId);
@ -556,7 +600,9 @@ $utopia->delete('/v1/storage/files/:fileId')
->label('sdk.namespace', 'storage')
->label('sdk.method', 'deleteFile')
->label('sdk.description', 'Delete a file by its unique ID. Only users with write permissions have access to delete this resource.')
->param('fileId', '', function () {return new UID();}, 'File unique ID.')
->param('fileId', '', function () {
return new UID();
}, 'File unique ID.')
->action(
function ($fileId) use ($response, $projectDB, $audit, $usage) {
$file = $projectDB->getDocument($fileId);
@ -592,8 +638,12 @@ $utopia->get('/v1/storage/files/:fileId/scan')
->label('sdk.namespace', 'storage')
->label('sdk.method', 'getFileScan')
->label('sdk.hide', true)
->param('fileId', '', function () {return new UID();}, 'File unique ID.')
->param('storage', 'local', function () {return new WhiteList(['local']);})
->param('fileId', '', function () {
return new UID();
}, 'File unique ID.')
->param('storage', 'local', function () {
return new WhiteList(['local']);
})
->action(
function ($fileId, $storage) use ($response, $request, $projectDB) {
$file = $projectDB->getDocument($fileId);

View file

@ -24,10 +24,18 @@ $utopia->get('/v1/teams')
->label('sdk.namespace', 'teams')
->label('sdk.method', 'listTeams')
->label('sdk.description', 'Get a list of all the current user teams. You can use the query params to filter your results. On admin mode, this endpoint will return a list of all of the project teams. [Learn more about different API modes](/docs/modes).')
->param('search', '', function () {return new Text(256);}, 'Search term to filter your list results.', true)
->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)
->param('search', '', function () {
return new Text(256);
}, 'Search term to filter your list results.', true)
->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) {
$results = $projectDB->getCollection([
@ -52,7 +60,9 @@ $utopia->get('/v1/teams/:teamId')
->label('sdk.namespace', 'teams')
->label('sdk.method', 'getTeam')
->label('sdk.description', 'Get team by its unique ID. All team members have read access for this resource.')
->param('teamId', '', function () {return new UID();}, 'Team unique ID.')
->param('teamId', '', function () {
return new UID();
}, 'Team unique ID.')
->action(
function ($teamId) use ($response, $projectDB) {
$team = $projectDB->getDocument($teamId);
@ -71,7 +81,9 @@ $utopia->get('/v1/teams/:teamId/members')
->label('sdk.namespace', 'teams')
->label('sdk.method', 'getTeamMembers')
->label('sdk.description', 'Get team members by the team unique ID. All team members have read access for this list of resources.')
->param('teamId', '', function () {return new UID();}, 'Team unique ID.')
->param('teamId', '', function () {
return new UID();
}, 'Team unique ID.')
->action(
function ($teamId) use ($response, $projectDB) {
$team = $projectDB->getDocument($teamId);
@ -123,8 +135,12 @@ $utopia->post('/v1/teams')
->label('sdk.namespace', 'teams')
->label('sdk.method', 'createTeam')
->label('sdk.description', 'Create a new team. The user who creates the team will automatically be assigned as the owner of the team. The team owner can invite new members, who will be able add new owners and update or delete the team from your project.')
->param('name', null, function () {return new Text(100);}, 'Team name.')
->param('roles', ['owner'], function () {return new ArrayList(new Text(128));}, 'User roles array. Use this param to set the roles in the team for the user who created the team. The default role is **owner**, a role can be any string.', true)
->param('name', null, function () {
return new Text(100);
}, 'Team name.')
->param('roles', ['owner'], function () {
return new ArrayList(new Text(128));
}, 'User roles array. Use this param to set the roles in the team for the user who created the team. The default role is **owner**, a role can be any string.', true)
->action(
function ($name, $roles) use ($response, $projectDB, $user, $mode) {
Authorization::disable();
@ -185,8 +201,12 @@ $utopia->put('/v1/teams/:teamId')
->label('sdk.namespace', 'teams')
->label('sdk.method', 'updateTeam')
->label('sdk.description', 'Update team by its unique ID. Only team owners have write access for this resource.')
->param('teamId', '', function () {return new UID();}, 'Team unique ID.')
->param('name', null, function () {return new Text(100);}, 'Team name.')
->param('teamId', '', function () {
return new UID();
}, 'Team unique ID.')
->param('name', null, function () {
return new Text(100);
}, 'Team name.')
->action(
function ($teamId, $name) use ($response, $projectDB) {
$team = $projectDB->getDocument($teamId);
@ -213,7 +233,9 @@ $utopia->delete('/v1/teams/:teamId')
->label('sdk.namespace', 'teams')
->label('sdk.method', 'deleteTeam')
->label('sdk.description', 'Delete team by its unique ID. Only team owners have write access for this resource.')
->param('teamId', '', function () {return new UID();}, 'Team unique ID.')
->param('teamId', '', function () {
return new UID();
}, 'Team unique ID.')
->action(
function ($teamId) use ($response, $projectDB) {
$team = $projectDB->getDocument($teamId);
@ -253,11 +275,21 @@ $utopia->post('/v1/teams/:teamId/memberships')
->label('sdk.namespace', 'teams')
->label('sdk.method', 'createTeamMembership')
->label('sdk.description', "Use this endpoint to invite a new member to your team. An email with a link to join the team will be sent to the new member email address. If member doesn't exists in the project it will be automatically created.\n\nUse the redirect parameter to redirect the user from the invitation email back to your app. When the user is redirected, use the /teams/{teamId}/memberships/{inviteId}/status endpoint to finally join the user to the team.\n\nPlease notice that in order to avoid a [Redirect Attacks](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) the only valid redirect URL's are the once from domains you have set when added your platforms in the console interface.")
->param('teamId', '', function () {return new UID();}, 'Team unique ID.')
->param('email', '', function () {return new Email();}, 'New team member email address.')
->param('name', '', function () {return new Text(100);}, 'New team member name.', true)
->param('roles', [], function () {return new ArrayList(new Text(128));}, 'Invite roles array. Learn more about [roles and permissions](/docs/permissions).')
->param('redirect', '', function () use ($clients) {return new Host($clients);}, 'Reset page to redirect user back to your app from the invitation email.')
->param('teamId', '', function () {
return new UID();
}, 'Team unique ID.')
->param('email', '', function () {
return new Email();
}, 'New team member email address.')
->param('name', '', function () {
return new Text(100);
}, 'New team member name.', true)
->param('roles', [], function () {
return new ArrayList(new Text(128));
}, 'Invite roles array. Learn more about [roles and permissions](/docs/permissions).')
->param('redirect', '', function () use ($clients) {
return new Host($clients);
}, 'Reset page to redirect user back to your app from the invitation email.')
->action(
function ($teamId, $email, $name, $roles, $redirect) use ($request, $response, $register, $project, $user, $audit, $projectDB) {
$name = (empty($name)) ? $email : $name;
@ -396,9 +428,15 @@ $utopia->post('/v1/teams/:teamId/memberships/:inviteId/resend')
->label('sdk.namespace', 'teams')
->label('sdk.method', 'createTeamMembershipResend')
->label('sdk.description', 'Use this endpoint to resend your invitation email for a user to join a team.')
->param('teamId', '', function () {return new UID();}, 'Team unique ID.')
->param('inviteId', '', function () {return new UID();}, 'Invite unique ID.')
->param('redirect', '', function () use ($clients) {return new Host($clients);}, 'Reset page to redirect user back to your app from the invitation email.')
->param('teamId', '', function () {
return new UID();
}, 'Team unique ID.')
->param('inviteId', '', function () {
return new UID();
}, 'Invite unique ID.')
->param('redirect', '', function () use ($clients) {
return new Host($clients);
}, 'Reset page to redirect user back to your app from the invitation email.')
->action(
function ($teamId, $inviteId, $redirect) use ($response, $register, $project, $user, $audit, $projectDB) {
$membership = $projectDB->getDocument($inviteId);
@ -477,12 +515,24 @@ $utopia->patch('/v1/teams/:teamId/memberships/:inviteId/status')
->label('sdk.method', 'updateTeamMembershipStatus')
->label('sdk.description', "Use this endpoint to let user accept an invitation to join a team after he is being redirect back to your app from the invitation email. Use the success and failure URL's to redirect users back to your application after the request completes.\n\nPlease notice that in order to avoid a [Redirect Attacks](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) the only valid redirect URL's are the once from domains you have set when added your platforms in the console interface.\n\nWhen not using the success or failure redirect arguments this endpoint will result with a 200 status code on success and with 401 status error on failure. This behavior was applied to help the web clients deal with browsers who don't allow to set 3rd party HTTP cookies needed for saving the account session token.")
->label('sdk.cookies', true)
->param('teamId', '', function () {return new UID();}, 'Team unique ID.')
->param('inviteId', '', function () {return new UID();}, 'Invite unique ID')
->param('userId', '', function () {return new UID();}, 'User unique ID')
->param('secret', '', function () {return new Text(256);}, 'Secret Key')
->param('success', null, function () use ($clients) {return new Host($clients);}, 'Redirect when registration succeed', true)
->param('failure', null, function () use ($clients) {return new Host($clients);}, 'Redirect when registration failed', true)
->param('teamId', '', function () {
return new UID();
}, 'Team unique ID.')
->param('inviteId', '', function () {
return new UID();
}, 'Invite unique ID')
->param('userId', '', function () {
return new UID();
}, 'User unique ID')
->param('secret', '', function () {
return new Text(256);
}, 'Secret Key')
->param('success', null, function () use ($clients) {
return new Host($clients);
}, 'Redirect when registration succeed', true)
->param('failure', null, function () use ($clients) {
return new Host($clients);
}, 'Redirect when registration failed', true)
->action(
function ($teamId, $inviteId, $userId, $secret, $success, $failure) use ($response, $request, $user, $audit, $projectDB) {
$invite = $projectDB->getDocument($inviteId);
@ -608,8 +658,12 @@ $utopia->delete('/v1/teams/:teamId/memberships/:inviteId')
->label('sdk.namespace', 'teams')
->label('sdk.method', 'deleteTeamMembership')
->label('sdk.description', 'This endpoint allows a user to leave a team or for a team owner to delete the membership of any other team member.')
->param('teamId', '', function () {return new UID();}, 'Team unique ID.')
->param('inviteId', '', function () {return new UID();}, 'Invite unique ID')
->param('teamId', '', function () {
return new UID();
}, 'Team unique ID.')
->param('inviteId', '', function () {
return new UID();
}, 'Invite unique ID')
->action(
function ($teamId, $inviteId) use ($response, $projectDB, $audit) {
$invite = $projectDB->getDocument($inviteId);

View file

@ -23,10 +23,18 @@ $utopia->get('/v1/users')
->label('sdk.namespace', 'users')
->label('sdk.method', 'listUsers')
->label('sdk.description', 'Get a list of all the project users. You can use the query params to filter your results.')
->param('search', '', function () {return new Text(256);}, 'Search term to filter your list results.', true)
->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)
->param('search', '', function () {
return new Text(256);
}, 'Search term to filter your list results.', true)
->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, $providers) {
$results = $projectDB->getCollection([
@ -60,7 +68,8 @@ $utopia->get('/v1/users')
'registration',
'confirm',
'name',
], $oauthKeys
],
$oauthKeys
));
}, $results);
@ -74,7 +83,9 @@ $utopia->get('/v1/users/:userId')
->label('sdk.namespace', 'users')
->label('sdk.method', 'getUser')
->label('sdk.description', 'Get user by its unique ID.')
->param('userId', '', function () {return new UID();}, 'User unique ID.')
->param('userId', '', function () {
return new UID();
}, 'User unique ID.')
->action(
function ($userId) use ($response, $projectDB, $providers) {
$user = $projectDB->getDocument($userId);
@ -101,7 +112,8 @@ $utopia->get('/v1/users/:userId')
'registration',
'confirm',
'name',
], $oauthKeys
],
$oauthKeys
)), ['roles' => Authorization::getRoles()]));
}
);
@ -112,7 +124,9 @@ $utopia->get('/v1/users/:userId/prefs')
->label('sdk.namespace', 'users')
->label('sdk.method', 'getUserPrefs')
->label('sdk.description', 'Get user preferences by its unique ID.')
->param('userId', '', function () {return new UID();}, 'User unique ID.')
->param('userId', '', function () {
return new UID();
}, 'User unique ID.')
->action(
function ($userId) use ($response, $projectDB) {
$user = $projectDB->getDocument($userId);
@ -143,7 +157,9 @@ $utopia->get('/v1/users/:userId/sessions')
->label('sdk.namespace', 'users')
->label('sdk.method', 'getUserSessions')
->label('sdk.description', 'Get user sessions list by its unique ID.')
->param('userId', '', function () {return new UID();}, 'User unique ID.')
->param('userId', '', function () {
return new UID();
}, 'User unique ID.')
->action(
function ($userId) use ($response, $projectDB) {
$user = $projectDB->getDocument($userId);
@ -205,7 +221,9 @@ $utopia->get('/v1/users/:userId/logs')
->label('sdk.namespace', 'users')
->label('sdk.method', 'getUserLogs')
->label('sdk.description', 'Get user activity logs list by its unique ID.')
->param('userId', '', function () {return new UID();}, 'User unique ID.')
->param('userId', '', function () {
return new UID();
}, 'User unique ID.')
->action(
function ($userId) use ($response, $register, $projectDB, $project) {
$user = $projectDB->getDocument($userId);
@ -266,9 +284,15 @@ $utopia->post('/v1/users')
->label('sdk.namespace', 'users')
->label('sdk.method', 'createUser')
->label('sdk.description', 'Create a new user.')
->param('email', '', function () {return new Email();}, 'User account email.')
->param('password', '', function () {return new Password();}, 'User account password.')
->param('name', '', function () {return new Text(100);}, 'User account name.', true)
->param('email', '', function () {
return new Email();
}, 'User account email.')
->param('password', '', function () {
return new Password();
}, 'User account password.')
->param('name', '', function () {
return new Text(100);
}, 'User account name.', true)
->action(
function ($email, $password, $name) use ($response, $register, $projectDB, $providers) {
$profile = $projectDB->getCollection([ // Get user by email address
@ -330,8 +354,12 @@ $utopia->patch('/v1/users/:userId/status')
->label('sdk.namespace', 'users')
->label('sdk.method', 'updateUserStatus')
->label('sdk.description', 'Update user status by its unique ID.')
->param('userId', '', function () {return new UID();}, 'User unique ID.')
->param('status', '', function () {return new WhiteList([Auth::USER_STATUS_ACTIVATED, Auth::USER_STATUS_BLOCKED, Auth::USER_STATUS_UNACTIVATED]);}, 'User Status code. To activate the user pass '.Auth::USER_STATUS_ACTIVATED.', to blocking the user pass '.Auth::USER_STATUS_BLOCKED.' and for disabling the user pass '.Auth::USER_STATUS_UNACTIVATED)
->param('userId', '', function () {
return new UID();
}, 'User unique ID.')
->param('status', '', function () {
return new WhiteList([Auth::USER_STATUS_ACTIVATED, Auth::USER_STATUS_BLOCKED, Auth::USER_STATUS_UNACTIVATED]);
}, 'User Status code. To activate the user pass '.Auth::USER_STATUS_ACTIVATED.', to blocking the user pass '.Auth::USER_STATUS_BLOCKED.' and for disabling the user pass '.Auth::USER_STATUS_UNACTIVATED)
->action(
function ($userId, $status) use ($response, $projectDB) {
$user = $projectDB->getDocument($userId);
@ -360,8 +388,12 @@ $utopia->delete('/v1/users/:userId/sessions/:session')
->label('sdk.method', 'deleteUsersSession')
->label('sdk.description', 'Delete user sessions by its unique ID.')
->label('abuse-limit', 100)
->param('userId', '', function () {return new UID();}, 'User unique ID.')
->param('sessionId', null, function () {return new UID();}, 'User unique session ID.')
->param('userId', '', function () {
return new UID();
}, 'User unique ID.')
->param('sessionId', null, function () {
return new UID();
}, 'User unique session ID.')
->action(
function ($userId, $sessionId) use ($response, $request, $projectDB) {
$user = $projectDB->getDocument($userId);
@ -391,7 +423,9 @@ $utopia->delete('/v1/users/:userId/sessions')
->label('sdk.method', 'deleteUserSessions')
->label('sdk.description', 'Delete all user sessions by its unique ID.')
->label('abuse-limit', 100)
->param('userId', '', function () {return new UID();}, 'User unique ID.')
->param('userId', '', function () {
return new UID();
}, 'User unique ID.')
->action(
function ($userId) use ($response, $request, $projectDB) {
$user = $projectDB->getDocument($userId);

View file

@ -1,7 +1,7 @@
<?php
// Init
if(file_exists(__DIR__ . '/../vendor/autoload.php')) {
if (file_exists(__DIR__ . '/../vendor/autoload.php')) {
require_once __DIR__ . '/../vendor/autoload.php';
}
@ -24,7 +24,7 @@ const APP_EMAIL_TEAM = 'team@' . APP_DOMAIN;
const APP_EMAIL_SECURITY = 'security@' . APP_DOMAIN;
const APP_USERAGENT = APP_NAME . '-Server/%s Please report abuse at ' . APP_EMAIL_SECURITY;
const APP_MODE_ADMIN = 'admin';
const APP_LOCALES = ['en', 'he', 'ro'];
const APP_LOCALES = ['en', 'he', 'pt-br', 'es', 'ro'];
const APP_PAGING_LIMIT = 15;
$register = new Registry();
@ -51,7 +51,7 @@ define('COOKIE_DOMAIN', ($request->getServer('HTTP_HOST', null) === 'localhost'
/**
* Registry
*/
$register->set('db', function() use ($request) { // Register DB connection
$register->set('db', function () use ($request) { // Register DB connection
$dbHost = $request->getServer('_APP_DB_HOST', '');
$dbUser = $request->getServer('_APP_DB_USER', '');
$dbPass = $request->getServer('_APP_DB_PASS', '');
@ -68,11 +68,11 @@ $register->set('db', function() use ($request) { // Register DB connection
return $pdo;
});
$register->set('influxdb', function() use ($request) { // Register DB connection
$register->set('influxdb', function () use ($request) { // Register DB connection
$host = $request->getServer('_APP_INFLUXDB_HOST', '');
$port = $request->getServer('_APP_INFLUXDB_PORT', '');
if(empty($host) || empty($port)) {
if (empty($host) || empty($port)) {
return null;
}
@ -80,7 +80,7 @@ $register->set('influxdb', function() use ($request) { // Register DB connection
return $client;
});
$register->set('statsd', function() use ($request) { // Register DB connection
$register->set('statsd', function () use ($request) { // Register DB connection
$host = $request->getServer('_APP_STATSD_HOST', 'telegraf');
$port = $request->getServer('_APP_STATSD_PORT', 8125);
@ -89,13 +89,13 @@ $register->set('statsd', function() use ($request) { // Register DB connection
return $statsd;
});
$register->set('cache', function() use ($redisHost, $redisPort) { // Register cache connection
$register->set('cache', function () use ($redisHost, $redisPort) { // Register cache connection
$redis = new Redis();
$redis->connect($redisHost, $redisPort);
return $redis;
});
$register->set('smtp', function() use ($request) {
$register->set('smtp', function () use ($request) {
$mail = new PHPMailer(true);
$mail->isSMTP();
@ -128,10 +128,11 @@ Locale::$exceptions = false;
Locale::setLanguage('en', include __DIR__ . '/config/locale/en.php');
Locale::setLanguage('he', include __DIR__ . '/config/locale/he.php');
Locale::setLanguage('pt-br', include __DIR__ . '/config/locale/pt-br.php');
Locale::setLanguage('es', include __DIR__ . '/config/locale/es.php');
Locale::setLanguage('ro', include __DIR__ . '/config/locale/ro.php');
if(in_array($locale, APP_LOCALES)) {
if (in_array($locale, APP_LOCALES)) {
Locale::setDefault($locale);
}
@ -159,7 +160,7 @@ Authorization::enable();
$console = $consoleDB->getDocument('console');
if(is_null($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS !== $project->getCollection()) {
if (is_null($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS !== $project->getCollection()) {
$project = $console;
}
@ -167,7 +168,7 @@ $mode = $request->getParam('mode', $request->getHeader('X-Appwrite-Mode', 'defau
Auth::setCookieName('a-session-' . $project->getUid());
if(APP_MODE_ADMIN === $mode) {
if (APP_MODE_ADMIN === $mode) {
Auth::setCookieName('a-session-' . $console->getUid());
}
@ -182,7 +183,7 @@ $projectDB->setMocks($collections);
$user = $projectDB->getDocument(Auth::$unique);
if(APP_MODE_ADMIN === $mode) {
if (APP_MODE_ADMIN === $mode) {
$user = $consoleDB->getDocument(Auth::$unique);
$user
@ -190,17 +191,16 @@ if(APP_MODE_ADMIN === $mode) {
;
}
if(empty($user->getUid()) // Check a document has been found in the DB
if (empty($user->getUid()) // 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(['$uid' => '', '$collection' => Database::SYSTEM_COLLECTION_USERS]);
}
if(APP_MODE_ADMIN === $mode) {
if(!empty($user->search('teamId', $project->getAttribute('teamId'), $user->getAttribute('memberships')))) {
if (APP_MODE_ADMIN === $mode) {
if (!empty($user->search('teamId', $project->getAttribute('teamId'), $user->getAttribute('memberships')))) {
Authorization::disable();
}
else {
} else {
$user = new Document(['$uid' => '', '$collection' => Database::SYSTEM_COLLECTION_USERS]);
}
}

View file

@ -38,5 +38,5 @@ GET https://appwrite.test/v1/locale/countries/phones
GET https://appwrite.test/v1/locale/currencies
```
** List of all currencies, including currency symol, name, plural, and decimal digits for all major and minor currencies. You can use the locale header to get the data in supported language. **
** List of all currencies, including currency symbol, name, plural, and decimal digits for all major and minor currencies. You can use the locale header to get the data in supported language. **

View file

@ -185,7 +185,7 @@ class Client
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, php_uname('s') . '-' . php_uname('r') . ':php-' . phpversion());
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($curl, $header) use (&$responseHeaders) {
curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($curl, $header) use (&$responseHeaders) {
$len = strlen($header);
$header = explode(':', strtolower($header), 2);
@ -198,12 +198,12 @@ class Client
return $len;
});
if($method != self::METHOD_GET) {
if ($method != self::METHOD_GET) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
}
// Allow self signed certificates
if($this->selfSigned) {
if ($this->selfSigned) {
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
}
@ -212,7 +212,7 @@ class Client
$responseType = (isset($responseHeaders['content-type'])) ? $responseHeaders['content-type'] : '';
$responseStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
switch(substr($responseType, 0, strpos($responseType, ';'))) {
switch (substr($responseType, 0, strpos($responseType, ';'))) {
case 'application/json':
$responseBody = json_decode($responseBody, true);
break;
@ -234,16 +234,16 @@ class Client
* @param string $prefix
* @return array
*/
protected function flatten(array $data, $prefix = '') {
protected function flatten(array $data, $prefix = '')
{
$output = [];
foreach($data as $key => $value) {
foreach ($data as $key => $value) {
$finalKey = $prefix ? "{$prefix}[{$key}]" : $key;
if (is_array($value)) {
$output += $this->flatten($value, $finalKey); // @todo: handle name collision here if needed
}
else {
} else {
$output[$finalKey] = $value;
}
}

View file

@ -16,4 +16,4 @@ abstract class Service
{
$this->client = $client;
}
}
}

View file

@ -188,5 +188,4 @@ class Account extends Service
return $this->client->call(Client::METHOD_GET, $path, [
], $params);
}
}
}

View file

@ -13,13 +13,13 @@ class Auth extends Service
*
* Allow the user to login into his account by providing a valid email and
* password combination. Use the success and failure arguments to provide a
* redirect URL\'s back to your app when login is completed.
*
* redirect URL\'s back to your app when login is completed.
*
* Please notice that in order to avoid a [Redirect
* Attacks](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md)
* the only valid redirect URL's are the once from domains you have set when
* added your platforms in the console interface.
*
*
* When not using the success or failure redirect arguments this endpoint will
* result with a 200 status code and the user account object on success and
* with 401 status error on failure. This behavior was applied to help the web
@ -165,7 +165,7 @@ class Auth extends Service
* **userId** and **token** arguments will be passed as query parameters to
* the redirect URL you have provided when sending your request to the
* /auth/recovery endpoint.
*
*
* Please notice that in order to avoid a [Redirect
* Attacks](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md)
* the only valid redirect URL's are the once from domains you have set when
@ -198,18 +198,18 @@ class Auth extends Service
* Use this endpoint to allow a new user to register an account in your
* project. Use the success and failure URL's to redirect users back to your
* application after signup completes.
*
*
* If registration completes successfully user will be sent with a
* confirmation email in order to confirm he is the owner of the account email
* address. Use the redirect parameter to redirect the user from the
* confirmation email back to your app. When the user is redirected, use the
* /auth/confirm endpoint to complete the account confirmation.
*
*
* Please notice that in order to avoid a [Redirect
* Attacks](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md)
* the only valid redirect URL's are the once from domains you have set when
* added your platforms in the console interface.
*
*
* When not using the success or failure redirect arguments this endpoint will
* result with a 200 status code and the user account object on success and
* with 401 status error on failure. This behavior was applied to help the web
@ -272,7 +272,7 @@ class Auth extends Service
* This endpoint allows the user to request your app to resend him his email
* confirmation message. The redirect arguments acts the same way as in
* /auth/register endpoint.
*
*
* Please notice that in order to avoid a [Redirect
* Attacks](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md)
* the only valid redirect URL's are the once from domains you have set when
@ -292,5 +292,4 @@ class Auth extends Service
return $this->client->call(Client::METHOD_POST, $path, [
], $params);
}
}
}

View file

@ -165,5 +165,4 @@ class Avatars extends Service
return $this->client->call(Client::METHOD_GET, $path, [
], $params);
}
}
}

View file

@ -267,5 +267,4 @@ class Database extends Service
return $this->client->call(Client::METHOD_DELETE, $path, [
], $params);
}
}
}

View file

@ -106,5 +106,4 @@ class Locale extends Service
return $this->client->call(Client::METHOD_GET, $path, [
], $params);
}
}
}

View file

@ -610,5 +610,4 @@ class Projects extends Service
return $this->client->call(Client::METHOD_DELETE, $path, [
], $params);
}
}
}

View file

@ -205,5 +205,4 @@ class Storage extends Service
return $this->client->call(Client::METHOD_GET, $path, [
], $params);
}
}
}

View file

@ -149,12 +149,12 @@ class Teams extends Service
* Use this endpoint to invite a new member to your team. An email with a link
* to join the team will be sent to the new member email address. If member
* doesn't exists in the project it will be automatically created.
*
*
* Use the redirect parameter to redirect the user from the invitation email
* back to your app. When the user is redirected, use the
* /teams/{teamId}/memberships/{inviteId}/status endpoint to finally join the
* user to the team.
*
*
* Please notice that in order to avoid a [Redirect
* Attacks](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md)
* the only valid redirect URL's are the once from domains you have set when
@ -233,12 +233,12 @@ class Teams extends Service
* is being redirect back to your app from the invitation email. Use the
* success and failure URL's to redirect users back to your application after
* the request completes.
*
*
* Please notice that in order to avoid a [Redirect
* Attacks](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md)
* the only valid redirect URL's are the once from domains you have set when
* added your platforms in the console interface.
*
*
* When not using the success or failure redirect arguments this endpoint will
* result with a 200 status code on success and with 401 status error on
* failure. This behavior was applied to help the web clients deal with
@ -267,5 +267,4 @@ class Teams extends Service
return $this->client->call(Client::METHOD_PATCH, $path, [
], $params);
}
}
}

View file

@ -195,5 +195,4 @@ class Users extends Service
return $this->client->call(Client::METHOD_PATCH, $path, [
], $params);
}
}
}

View file

@ -19,7 +19,6 @@ $cli = new CLI();
$cli
->task('generate')
->action(function () {
function getSSLPage($url)
{
$ch = curl_init();
@ -211,4 +210,4 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
}
});
$cli->run();
$cli->run();

View file

@ -307,8 +307,13 @@ $providers = $this->getParam('providers', []);
<li data-state="/console/users/providers?project={{router.params.project}}">
<h2>Providers</h2>
<div class="box margin-bottom margin-top-large">
<div class="box margin-bottom margin-top-large"
data-service="projects.getProject"
data-event="load,platform-create,platform-update,platform-delete"
data-name="console-project"
data-param-project-id="{{router.params.project}}"
data-scope="console">
<ul class="list">
<?php foreach ($providers as $provider => $data): if(isset($data['enabled']) && !$data['enabled']) { continue; } ?>
<li class="clear <?php echo (isset($data['enabled']) && !$data['enabled']) ? 'dev-feature' : ''; ?>">
@ -357,7 +362,9 @@ $providers = $this->getParam('providers', []);
<span>
<?php echo ucfirst($provider); ?>
<span data-ls-if="{{console-project.usersOauth<?php echo ucfirst($provider); ?>Appid}} === '' || {{console-project.usersOauth<?php echo ucfirst($provider); ?>Secret}} == '' || {{console-project.usersOauth<?php echo ucfirst($provider); ?>Appid}} === undefined || {{console-project.usersOauth<?php echo ucfirst($provider); ?>Secret}} === undefined">
<span data-ls-if="
!{{console-project.usersOauth<?php echo ucfirst($provider); ?>Appid}} ||
!{{console-project.usersOauth<?php echo ucfirst($provider); ?>Secret}}" data-debug="1">
&nbsp;<span class="tag red">Disabled</span>
</span>
</span>

View file

@ -18,7 +18,7 @@
<label>Email</label>
<input name="email" type="email" class="full-width" autocomplete="email" placeholder="me@example.com" required>
<input name="confirmation" type="hidden" data-ls-bind="{{env.PROTOCOL}}://{{env.DOMAIN}}/auth/recovery/reset" />
<input name="confirm" type="hidden" data-ls-bind="{{env.PROTOCOL}}://{{env.DOMAIN}}/auth/recovery/reset" />
<button type="submit" class="btn btn-primary"><i class="fa fa-sign-in"></i> Recover</button>
</form>

View file

@ -18,7 +18,7 @@
data-failure-param-alert-text="Registration Failed. Please try again later"
data-failure-param-alert-classname="error">
<input name="confirmation" type="hidden" data-ls-bind="{{env.PROTOCOL}}://{{env.DOMAIN}}/console">
<input name="confirm" type="hidden" data-ls-bind="{{env.PROTOCOL}}://{{env.DOMAIN}}/console">
<input name="success" type="hidden" data-ls-bind="{{env.PROTOCOL}}://{{env.DOMAIN}}/console">
<input name="failure" type="hidden" data-ls-bind="{{env.PROTOCOL}}://{{env.DOMAIN}}/auth/signup?failure=1">

View file

@ -91,7 +91,10 @@ class TasksV1
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, sprintf(APP_USERAGENT, $version));
curl_setopt($ch, CURLOPT_HTTPHEADER, array_merge($headers, [
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
array_merge($headers, [
'X-'.APP_NAME.'-Task-UID: '.$task->getAttribute('$uid', ''),
'X-'.APP_NAME.'-Task-Name: '.$task->getAttribute('name', ''),
])

View file

@ -59,7 +59,10 @@ class WebhooksV1
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, sprintf(APP_USERAGENT, $version));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
[
'Content-Type: application/json',
'Content-Length: '.strlen($payload),
'X-'.APP_NAME.'-Event: '.$event,

121
composer.lock generated
View file

@ -4,6 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "cf3e9453a93f3ee5cfec76f6cd6bc139",
"content-hash": "470f543ebf989400a43a6269f0b4d60a",
"packages": [
{
@ -12,12 +13,12 @@
"source": {
"type": "git",
"url": "https://github.com/appwrite/sdk-for-php.git",
"reference": "6d920c6f7aa7c36a06915bbe4b91ab5a9cf7ebb6"
"reference": "457a20948a7f1e9b8e4cea09205b6fd42f8ca811"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/appwrite/sdk-for-php/zipball/6d920c6f7aa7c36a06915bbe4b91ab5a9cf7ebb6",
"reference": "6d920c6f7aa7c36a06915bbe4b91ab5a9cf7ebb6",
"url": "https://api.github.com/repos/appwrite/sdk-for-php/zipball/457a20948a7f1e9b8e4cea09205b6fd42f8ca811",
"reference": "457a20948a7f1e9b8e4cea09205b6fd42f8ca811",
"shasum": ""
},
"require": {
@ -39,7 +40,7 @@
"BSD-3-Clause"
],
"description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)",
"time": "2019-09-20T06:34:28+00:00"
"time": "2019-09-21T12:46:08+00:00"
},
{
"name": "appwrite/php-clamav",
@ -84,7 +85,7 @@
"clamav",
"php"
],
"time": "2019-09-08 17:36:32"
"time": "2019-09-08T17:36:32+00:00"
},
{
"name": "appwrite/sdk-generator",
@ -92,7 +93,15 @@
"source": {
"type": "git",
"url": "https://github.com/appwrite/sdk-generator",
"reference": "e456fafb3d32a83c104a47ad064b2295281e58c0"
<<<<<<< HEAD
<<<<<<< HEAD
"reference": "2cdf218f735e5c52a47f1d8977f460261fd9017f"
=======
"reference": "22cd594e2406fbcfc64262fdcdfa78069bf29aa0"
>>>>>>> upstream/master
=======
"reference": "22cd594e2406fbcfc64262fdcdfa78069bf29aa0"
>>>>>>> upstream/master
},
"require": {
"ext-curl": "*",
@ -122,7 +131,15 @@
}
],
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
"time": "2019-09-20 06:30:54"
<<<<<<< HEAD
<<<<<<< HEAD
"time": "2019-09-22 12:47:11"
=======
"time": "2019-09-28 23:31:14"
>>>>>>> upstream/master
=======
"time": "2019-09-28 23:31:14"
>>>>>>> upstream/master
},
{
"name": "bacon/bacon-qr-code",
@ -171,7 +188,7 @@
],
"description": "BaconQrCode is a QR code generator for PHP.",
"homepage": "https://github.com/Bacon/BaconQrCode",
"time": "2018-04-25T17:53:56+00:00"
"time": "2018-04-25 17:53:56"
},
{
"name": "chrisboulton/php-resque",
@ -228,7 +245,7 @@
"resque"
],
"abandoned": "resque/php-resque",
"time": "2017-04-12 21:58:19"
"time": "2017-04-12T21:58:19+00:00"
},
{
"name": "chrisboulton/php-resque-scheduler",
@ -264,7 +281,7 @@
}
],
"description": "php-resque-scheduler is a PHP port of resque-scheduler, which adds support for scheduling items in the future to Resque.",
"time": "2016-11-28 22:38:06"
"time": "2016-11-28T22:38:06+00:00"
},
{
"name": "colinmollenhour/credis",
@ -304,7 +321,7 @@
],
"description": "Credis is a lightweight interface to the Redis key-value store which wraps the phpredis library when available for better performance.",
"homepage": "https://github.com/colinmollenhour/credis",
"time": "2019-03-05T16:29:14+00:00"
"time": "2019-03-05 16:29:14"
},
{
"name": "composer/ca-bundle",
@ -360,7 +377,7 @@
"ssl",
"tls"
],
"time": "2019-08-30 08:44:50"
"time": "2019-08-30T08:44:50+00:00"
},
{
"name": "dasprid/enum",
@ -402,7 +419,7 @@
"enum",
"map"
],
"time": "2017-10-25T22:45:27+00:00"
"time": "2017-10-25 22:45:27"
},
{
"name": "domnikl/statsd",
@ -449,7 +466,7 @@
"statsd",
"udp"
],
"time": "2014-12-09T09:37:49+00:00"
"time": "2014-12-09 09:37:49"
},
{
"name": "dragonmantank/cron-expression",
@ -498,7 +515,7 @@
"cron",
"schedule"
],
"time": "2018-06-06T03:12:17+00:00"
"time": "2018-06-06 03:12:17"
},
{
"name": "geoip2/geoip2",
@ -550,7 +567,7 @@
"geolocation",
"maxmind"
],
"time": "2018-04-10T15:32:59+00:00"
"time": "2018-04-10 15:32:59"
},
{
"name": "guzzlehttp/guzzle",
@ -616,7 +633,7 @@
"rest",
"web service"
],
"time": "2019-08-23 22:16:30"
"time": "2019-08-23T22:16:30+00:00"
},
{
"name": "guzzlehttp/promises",
@ -667,7 +684,7 @@
"keywords": [
"promise"
],
"time": "2019-07-02 14:54:06"
"time": "2019-07-02T14:54:06+00:00"
},
{
"name": "guzzlehttp/psr7",
@ -738,7 +755,7 @@
"uri",
"url"
],
"time": "2019-08-13 16:05:52"
"time": "2019-08-13T16:05:52+00:00"
},
{
"name": "influxdb/influxdb-php",
@ -799,7 +816,7 @@
"influxdb library",
"time series"
],
"time": "2019-05-30T00:15:14+00:00"
"time": "2019-05-30 00:15:14"
},
{
"name": "matthiasmullie/minify",
@ -859,7 +876,7 @@
"minifier",
"minify"
],
"time": "2018-11-26T23:10:39+00:00"
"time": "2018-11-26 23:10:39"
},
{
"name": "matthiasmullie/path-converter",
@ -908,7 +925,7 @@
"paths",
"relative"
],
"time": "2018-10-25T15:19:41+00:00"
"time": "2018-10-25 15:19:41"
},
{
"name": "maxmind-db/reader",
@ -964,7 +981,7 @@
"geolocation",
"maxmind"
],
"time": "2019-01-04T19:55:56+00:00"
"time": "2019-01-04 19:55:56"
},
{
"name": "maxmind/web-service-common",
@ -1010,20 +1027,20 @@
],
"description": "Internal MaxMind Web Service API",
"homepage": "https://github.com/maxmind/web-service-common-php",
"time": "2018-02-12T22:31:54+00:00"
"time": "2018-02-12 22:31:54"
},
{
"name": "mustangostang/spyc",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/mustangostang/spyc.git",
"reference": "576c42ecbc9630b52a95da3279f07278572c6b15"
"url": "git@github.com:mustangostang/spyc.git",
"reference": "4627c838b16550b666d15aeae1e5289dd5b77da0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mustangostang/spyc/zipball/576c42ecbc9630b52a95da3279f07278572c6b15",
"reference": "576c42ecbc9630b52a95da3279f07278572c6b15",
"url": "https://api.github.com/repos/mustangostang/spyc/zipball/4627c838b16550b666d15aeae1e5289dd5b77da0",
"reference": "4627c838b16550b666d15aeae1e5289dd5b77da0",
"shasum": ""
},
"require": {
@ -1060,7 +1077,7 @@
"yaml",
"yml"
],
"time": "2017-07-23 16:38:44"
"time": "2019-09-10T13:16:29+00:00"
},
{
"name": "phpmailer/phpmailer",
@ -1126,7 +1143,7 @@
}
],
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"time": "2019-02-01T15:04:28+00:00"
"time": "2019-02-01 15:04:28"
},
{
"name": "piwik/device-detector",
@ -1177,7 +1194,7 @@
"parser",
"useragent"
],
"time": "2016-01-21T22:26:37+00:00"
"time": "2016-01-21 22:26:37"
},
{
"name": "psr/http-message",
@ -1227,7 +1244,7 @@
"request",
"response"
],
"time": "2019-08-29 13:16:46"
"time": "2019-08-29T13:16:46+00:00"
},
{
"name": "psr/log",
@ -1274,7 +1291,7 @@
"psr",
"psr-3"
],
"time": "2018-11-21 13:42:00"
"time": "2018-11-21T13:42:00+00:00"
},
{
"name": "ralouphie/getallheaders",
@ -1314,7 +1331,7 @@
}
],
"description": "A polyfill for getallheaders.",
"time": "2019-03-08T08:55:37+00:00"
"time": "2019-03-08 08:55:37"
},
{
"name": "symfony/polyfill-ctype",
@ -1372,7 +1389,7 @@
"polyfill",
"portable"
],
"time": "2019-08-06 08:03:45"
"time": "2019-08-06T08:03:45+00:00"
},
{
"name": "symfony/polyfill-mbstring",
@ -1431,7 +1448,7 @@
"portable",
"shim"
],
"time": "2019-09-17 10:46:08"
"time": "2019-09-17T10:46:08+00:00"
},
{
"name": "twig/twig",
@ -1439,12 +1456,12 @@
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "d83802c011b99b5326ccd13e7fc87bacebd4c724"
"reference": "c2fd9990fcab344b67a12ead04890a88141d5897"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/d83802c011b99b5326ccd13e7fc87bacebd4c724",
"reference": "d83802c011b99b5326ccd13e7fc87bacebd4c724",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/c2fd9990fcab344b67a12ead04890a88141d5897",
"reference": "c2fd9990fcab344b67a12ead04890a88141d5897",
"shasum": ""
},
"require": {
@ -1498,7 +1515,15 @@
"keywords": [
"templating"
],
"time": "2019-09-17 06:08:14"
<<<<<<< HEAD
<<<<<<< HEAD
"time": "2019-09-20 12:53:54"
=======
"time": "2019-09-20T12:53:54+00:00"
>>>>>>> upstream/master
=======
"time": "2019-09-20T12:53:54+00:00"
>>>>>>> upstream/master
},
{
"name": "utopia-php/abuse",
@ -1545,7 +1570,7 @@
"upf",
"utopia"
],
"time": "2019-05-08 20:26:59"
"time": "2019-05-08T20:26:59+00:00"
},
{
"name": "utopia-php/cache",
@ -1592,7 +1617,7 @@
"upf",
"utopia"
],
"time": "2019-05-08 20:28:54"
"time": "2019-05-08T20:28:54+00:00"
},
{
"name": "utopia-php/cli",
@ -1640,7 +1665,7 @@
"upf",
"utopia"
],
"time": "2019-05-08 20:27:54"
"time": "2019-05-08T20:27:54+00:00"
},
{
"name": "utopia-php/framework",
@ -1684,7 +1709,7 @@
"php",
"upf"
],
"time": "2019-08-15 06:36:30"
"time": "2019-08-15T06:36:30+00:00"
},
{
"name": "utopia-php/locale",
@ -1730,7 +1755,7 @@
"upf",
"utopia"
],
"time": "2019-08-17 08:18:24"
"time": "2019-08-17T08:18:24+00:00"
},
{
"name": "utopia-php/registry",
@ -1777,7 +1802,9 @@
"upf",
"utopia"
],
"time": "2019-05-08 20:25:57"
"time": "2019-05-08T20:25:57+00:00"
<<<<<<< HEAD
=======
}
],
"packages-dev": [
@ -3195,8 +3222,10 @@
"validate"
],
"time": "2019-08-24T08:43:50+00:00"
>>>>>>> upstream/master
}
],
"packages-dev": null,
"aliases": [],
"minimum-stability": "dev",
"stability-flags": [],

View file

@ -16,12 +16,12 @@ services:
- "80:80"
- "443:443"
depends_on:
- mariadb
- redis
- smtp
- clamav
- influxdb
- telegraf
- mariadb
- redis
- smtp
- clamav
- influxdb
- telegraf
environment:
- _APP_ENV=development
- _APP_OPENSSL_KEY_V1=your-secret-key

View file

@ -18,11 +18,11 @@ The first step in adding a new OAuth provider is to list it in providers config
./app/config/providers.php
```
Make sure to fill all data needed and that your provider array key name is in camelcase format and has no spaces or special characters.
Make sure to fill all data needed and that your provider array key name is in camelCase format and has no spaces or special characters.
### Add Provider Logo
Add a logo image to your new provider in this path: ./public/images/oauth. Your logo should be a png 100X100px file with the name ofyour provider (all lowercase). Please make sure to leave about 20px padding around the logo to be consistent with other logos.
Add a logo image to your new provider in this path: ./public/images/oauth. Your logo should be a png 100×100px file with the name of your provider (all lowercase). Please make sure to leave about 20px padding around the logo to be consistent with other logos.
### Add Provider Class
@ -30,8 +30,8 @@ Once finished setting all the metadata for the new provider you need to start co
Create a new class that extends the basic OAuth provider abstract class in this location:
```
\Auth\OAuth\ProviderName
```bash
src/Auth/OAuth/ProviderName
```
Note that the class name should start with a capital letter as PHP FIG standards suggest.

13
package-lock.json generated
View file

@ -2517,8 +2517,7 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"aproba": {
"version": "1.2.0",
@ -2933,8 +2932,7 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"safer-buffer": {
"version": "2.1.2",
@ -2990,7 +2988,6 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@ -3034,14 +3031,12 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
"dev": true,
"optional": true
"dev": true
}
}
},

View file

@ -38,15 +38,15 @@ let path='/auth/recovery';return http.post(path,{'content-type':'application/jso
if(token===undefined){throw new Error('Missing required parameter: "token"');}
if(passwordA===undefined){throw new Error('Missing required parameter: "passwordA"');}
if(passwordB===undefined){throw new Error('Missing required parameter: "passwordB"');}
let path='/auth/recovery/reset';return http.put(path,{'content-type':'application/json'},{'userId':userId,'token':token,'password-a':passwordA,'password-b':passwordB});},register:function(email,password,confirmation,success,failure,name=''){if(email===undefined){throw new Error('Missing required parameter: "email"');}
let path='/auth/recovery/reset';return http.put(path,{'content-type':'application/json'},{'userId':userId,'token':token,'password-a':passwordA,'password-b':passwordB});},register:function(email,password,confirm,success,failure,name=''){if(email===undefined){throw new Error('Missing required parameter: "email"');}
if(password===undefined){throw new Error('Missing required parameter: "password"');}
if(confirmation===undefined){throw new Error('Missing required parameter: "confirmation"');}
if(confirm===undefined){throw new Error('Missing required parameter: "confirm"');}
if(success===undefined){throw new Error('Missing required parameter: "success"');}
if(failure===undefined){throw new Error('Missing required parameter: "failure"');}
let path='/auth/register';return iframe('post',path,{project:config.project,'email':email,'password':password,'confirmation':confirmation,'success':success,'failure':failure,'name':name});},confirm:function(userId,token){if(userId===undefined){throw new Error('Missing required parameter: "userId"');}
let path='/auth/register';return iframe('post',path,{project:config.project,'email':email,'password':password,'confirm':confirm,'success':success,'failure':failure,'name':name});},confirm:function(userId,token){if(userId===undefined){throw new Error('Missing required parameter: "userId"');}
if(token===undefined){throw new Error('Missing required parameter: "token"');}
let path='/auth/register/confirm';return http.post(path,{'content-type':'application/json'},{'userId':userId,'token':token});},confirmResend:function(redirect){if(redirect===undefined){throw new Error('Missing required parameter: "redirect"');}
let path='/auth/register/confirm/resend';return http.post(path,{'content-type':'application/json'},{'redirect':redirect});}};let avatars={getBrowser:function(code,width=100,height=100,quality=100){if(code===undefined){throw new Error('Missing required parameter: "code"');}
let path='/auth/register/confirm';return http.post(path,{'content-type':'application/json'},{'userId':userId,'token':token});},confirmResend:function(confirm){if(confirm===undefined){throw new Error('Missing required parameter: "confirm"');}
let path='/auth/register/confirm/resend';return http.post(path,{'content-type':'application/json'},{'confirm':confirm});}};let avatars={getBrowser:function(code,width=100,height=100,quality=100){if(code===undefined){throw new Error('Missing required parameter: "code"');}
let path='/avatars/browsers/{code}'.replace(new RegExp('{code}','g'),code);return http.get(path,{'content-type':'application/json'},{'width':width,'height':height,'quality':quality});},getCreditCard:function(code,width=100,height=100,quality=100){if(code===undefined){throw new Error('Missing required parameter: "code"');}
let path='/avatars/credit-cards/{code}'.replace(new RegExp('{code}','g'),code);return http.get(path,{'content-type':'application/json'},{'width':width,'height':height,'quality':quality});},getFavicon:function(url){if(url===undefined){throw new Error('Missing required parameter: "url"');}
let path='/avatars/favicon';return http.get(path,{'content-type':'application/json'},{'url':url});},getFlag:function(code,width=100,height=100,quality=100){if(code===undefined){throw new Error('Missing required parameter: "code"');}

View file

@ -38,15 +38,15 @@ let path='/auth/recovery';return http.post(path,{'content-type':'application/jso
if(token===undefined){throw new Error('Missing required parameter: "token"');}
if(passwordA===undefined){throw new Error('Missing required parameter: "passwordA"');}
if(passwordB===undefined){throw new Error('Missing required parameter: "passwordB"');}
let path='/auth/recovery/reset';return http.put(path,{'content-type':'application/json'},{'userId':userId,'token':token,'password-a':passwordA,'password-b':passwordB});},register:function(email,password,confirmation,success,failure,name=''){if(email===undefined){throw new Error('Missing required parameter: "email"');}
let path='/auth/recovery/reset';return http.put(path,{'content-type':'application/json'},{'userId':userId,'token':token,'password-a':passwordA,'password-b':passwordB});},register:function(email,password,confirm,success,failure,name=''){if(email===undefined){throw new Error('Missing required parameter: "email"');}
if(password===undefined){throw new Error('Missing required parameter: "password"');}
if(confirmation===undefined){throw new Error('Missing required parameter: "confirmation"');}
if(confirm===undefined){throw new Error('Missing required parameter: "confirm"');}
if(success===undefined){throw new Error('Missing required parameter: "success"');}
if(failure===undefined){throw new Error('Missing required parameter: "failure"');}
let path='/auth/register';return iframe('post',path,{project:config.project,'email':email,'password':password,'confirmation':confirmation,'success':success,'failure':failure,'name':name});},confirm:function(userId,token){if(userId===undefined){throw new Error('Missing required parameter: "userId"');}
let path='/auth/register';return iframe('post',path,{project:config.project,'email':email,'password':password,'confirm':confirm,'success':success,'failure':failure,'name':name});},confirm:function(userId,token){if(userId===undefined){throw new Error('Missing required parameter: "userId"');}
if(token===undefined){throw new Error('Missing required parameter: "token"');}
let path='/auth/register/confirm';return http.post(path,{'content-type':'application/json'},{'userId':userId,'token':token});},confirmResend:function(redirect){if(redirect===undefined){throw new Error('Missing required parameter: "redirect"');}
let path='/auth/register/confirm/resend';return http.post(path,{'content-type':'application/json'},{'redirect':redirect});}};let avatars={getBrowser:function(code,width=100,height=100,quality=100){if(code===undefined){throw new Error('Missing required parameter: "code"');}
let path='/auth/register/confirm';return http.post(path,{'content-type':'application/json'},{'userId':userId,'token':token});},confirmResend:function(confirm){if(confirm===undefined){throw new Error('Missing required parameter: "confirm"');}
let path='/auth/register/confirm/resend';return http.post(path,{'content-type':'application/json'},{'confirm':confirm});}};let avatars={getBrowser:function(code,width=100,height=100,quality=100){if(code===undefined){throw new Error('Missing required parameter: "code"');}
let path='/avatars/browsers/{code}'.replace(new RegExp('{code}','g'),code);return http.get(path,{'content-type':'application/json'},{'width':width,'height':height,'quality':quality});},getCreditCard:function(code,width=100,height=100,quality=100){if(code===undefined){throw new Error('Missing required parameter: "code"');}
let path='/avatars/credit-cards/{code}'.replace(new RegExp('{code}','g'),code);return http.get(path,{'content-type':'application/json'},{'width':width,'height':height,'quality':quality});},getFavicon:function(url){if(url===undefined){throw new Error('Missing required parameter: "url"');}
let path='/avatars/favicon';return http.get(path,{'content-type':'application/json'},{'url':url});},getFlag:function(code,width=100,height=100,quality=100){if(code===undefined){throw new Error('Missing required parameter: "code"');}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 KiB

View file

@ -31,4 +31,4 @@ switch ($version) { // Switch between API version
$service = $version . '/';
include __DIR__ . '/../app/app.php';
break;
}
}

View file

@ -46,14 +46,14 @@ class MySQL extends Adapter
$data = mb_strcut(json_encode($data), 0, 64000, 'UTF-8'); // Limit data to MySQL 64kb limit
$st->bindValue(':userId', $userId, PDO::PARAM_STR);
$st->bindValue(':userType', $userType, PDO::PARAM_INT);
$st->bindValue(':event', $event, PDO::PARAM_STR);
$st->bindValue(':resource', $resource, PDO::PARAM_STR);
$st->bindValue(':userAgent', $userAgent, PDO::PARAM_STR);
$st->bindValue(':ip', $ip, PDO::PARAM_STR);
$st->bindValue(':location', $location, PDO::PARAM_STR);
$st->bindValue(':data', $data, PDO::PARAM_STR);
$st->bindValue(':userId', $userId, PDO::PARAM_STR);
$st->bindValue(':userType', $userType, PDO::PARAM_INT);
$st->bindValue(':event', $event, PDO::PARAM_STR);
$st->bindValue(':resource', $resource, PDO::PARAM_STR);
$st->bindValue(':userAgent', $userAgent, PDO::PARAM_STR);
$st->bindValue(':ip', $ip, PDO::PARAM_STR);
$st->bindValue(':location', $location, PDO::PARAM_STR);
$st->bindValue(':data', $data, PDO::PARAM_STR);
$st->execute();
@ -69,8 +69,8 @@ class MySQL extends Adapter
ORDER BY `time` DESC LIMIT 10
');
$st->bindValue(':userId', $userId, PDO::PARAM_STR);
$st->bindValue(':userType', $userType, PDO::PARAM_INT);
$st->bindValue(':userId', $userId, PDO::PARAM_STR);
$st->bindValue(':userType', $userType, PDO::PARAM_INT);
$st->execute();
@ -95,8 +95,8 @@ class MySQL extends Adapter
ORDER BY `time` DESC LIMIT 10
');
$st->bindValue(':userId', $userId, PDO::PARAM_STR);
$st->bindValue(':userType', $userType, PDO::PARAM_INT);
$st->bindValue(':userId', $userId, PDO::PARAM_STR);
$st->bindValue(':userType', $userType, PDO::PARAM_INT);
foreach ($actions as $k => $id) {
$st->bindValue(':action_'.$k, $id);

View file

@ -94,13 +94,15 @@ abstract class OAuth
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, 'Console_OAuth_Agent');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
if (!empty($payload)) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
}
// Send the request & save response to $resp
$headers[] = "Content-length: ".strlen($payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Send the request & save response to $response
$response = curl_exec($ch);
curl_close($ch);

View file

@ -39,7 +39,9 @@ class Facebook extends OAuth
*/
public function getAccessToken(string $code):string
{
$accessToken = $this->request('GET', 'https://graph.facebook.com/'.$this->version.'/oauth/access_token?'.
$accessToken = $this->request(
'GET',
'https://graph.facebook.com/'.$this->version.'/oauth/access_token?'.
'client_id='.urlencode($this->appID).
'&redirect_uri='.urlencode($this->callback).
'&client_secret='.urlencode($this->appSecret).

View file

@ -34,7 +34,10 @@ class Github extends OAuth
*/
public function getAccessToken(string $code):string
{
$accessToken = $this->request('POST', 'https://github.com/login/oauth/access_token', [],
$accessToken = $this->request(
'POST',
'https://github.com/login/oauth/access_token',
[],
'client_id='.urlencode($this->appID).
'&redirect_uri='.urlencode($this->callback).
'&client_secret='.urlencode($this->appSecret).

123
src/Auth/OAuth/Gitlab.php Normal file
View file

@ -0,0 +1,123 @@
<?php
namespace Auth\OAuth;
use Auth\OAuth;
class Gitlab extends OAuth
{
/**
* @var array
*/
protected $user = [];
/**
* @return string
*/
public function getName(): string
{
return 'gitlab';
}
/**
* @return string
*/
public function getLoginURL(): string
{
return 'https://gitlab.com/oauth/authorize?' .
'client_id=' . urlencode($this->appID) .
'&redirect_uri=' . urlencode($this->callback) .
'&scope=read_user' .
'&state=' . urlencode(json_encode($this->state)) .
'&response_type=code';
}
/**
* @param string $code
*
* @return string
*/
public function getAccessToken(string $code): string
{
$accessToken = $this->request(
'POST',
'https://gitlab.com/oauth/token?'.
'code=' . urlencode($code) .
'&client_id=' . urlencode($this->appID) .
'&client_secret=' . urlencode($this->appSecret) .
'&redirect_uri=' . urlencode($this->callback) .
'&grant_type=authorization_code'
);
$accessToken = json_decode($accessToken, true);
if (isset($accessToken['access_token'])) {
return $accessToken['access_token'];
}
return '';
}
/**
* @param string $accessToken
*
* @return string
*/
public function getUserID(string $accessToken): string
{
$user = $this->getUser($accessToken);
if (isset($user['id'])) {
return $user['id'];
}
return '';
}
/**
* @param string $accessToken
*
* @return string
*/
public function getUserEmail(string $accessToken): string
{
$user = $this->getUser($accessToken);
if (isset($user['email'])) {
return $user['email'];
}
return '';
}
/**
* @param string $accessToken
*
* @return string
*/
public function getUserName(string $accessToken): string
{
$user = $this->getUser($accessToken);
if (isset($user['name'])) {
return $user['name'];
}
return '';
}
/**
* @param string $accessToken
*
* @return array
*/
protected function getUser(string $accessToken): array
{
if (empty($this->user)) {
$user = $this->request('GET', 'https://gitlab.com/api/v4/user?access_token=' . urlencode($accessToken));
$this->user = json_decode($user, true);
}
return $this->user;
}
}

127
src/Auth/OAuth/Google.php Normal file
View file

@ -0,0 +1,127 @@
<?php
namespace Auth\OAuth;
use Auth\OAuth;
class Google extends OAuth
{
/**
* @var string
*/
protected $version = 'v4';
/**
* @var array
*/
protected $user = [];
/**
* @return string
*/
public function getName(): string
{
return 'google';
}
/**
* @return string
*/
public function getLoginURL(): string
{
return 'https://accounts.google.com/o/oauth2/v2/auth?' .
'client_id=' . urlencode($this->appID) .
'&redirect_uri=' . urlencode($this->callback) .
'&scope=https://www.googleapis.com/auth/userinfo.email+https://www.googleapis.com/auth/userinfo.profile' .
'&state=' . urlencode(json_encode($this->state)) .
'&response_type=code';
}
/**
* @param string $code
*
* @return string
*/
public function getAccessToken(string $code): string
{
$accessToken = $this->request(
'POST',
'https://www.googleapis.com/oauth2/' . $this->version . '/token?' .
'code=' . urlencode($code) .
'&client_id=' . urlencode($this->appID) .
'&client_secret=' . urlencode($this->appSecret) .
'&redirect_uri=' . urlencode($this->callback) .
'&scope=' .
'&grant_type=authorization_code'
);
$accessToken = json_decode($accessToken, true);
if (isset($accessToken['access_token'])) {
return $accessToken['access_token'];
}
return '';
}
/**
* @param string $accessToken
*
* @return string
*/
public function getUserID(string $accessToken): string
{
$user = $this->getUser($accessToken);
if (isset($user['id'])) {
return $user['id'];
}
return '';
}
/**
* @param string $accessToken
*
* @return string
*/
public function getUserEmail(string $accessToken): string
{
$user = $this->getUser($accessToken);
if (isset($user['email'])) {
return $user['email'];
}
return '';
}
/**
* @param string $accessToken
*
* @return string
*/
public function getUserName(string $accessToken): string
{
$user = $this->getUser($accessToken);
if (isset($user['name'])) {
return $user['name'];
}
return '';
}
/**
* @param string $accessToken
*
* @return array
*/
protected function getUser(string $accessToken): array
{
if (empty($this->user)) {
$user = $this->request('GET', 'https://www.googleapis.com/oauth2/v2/userinfo?access_token=' . urlencode($accessToken));
$this->user = json_decode($user, true);
}
return $this->user;
}
}

View file

@ -61,7 +61,10 @@ class LinkedIn extends OAuth
*/
public function getAccessToken(string $code):string
{
$accessToken = $this->request('POST', 'https://www.linkedin.com/oauth/v2/accessToken', ['Content-Type: application/x-www-form-urlencoded'],
$accessToken = $this->request(
'POST',
'https://www.linkedin.com/oauth/v2/accessToken',
['Content-Type: application/x-www-form-urlencoded'],
http_build_query([
'grant_type' => 'authorization_code',
'code' => $code,

View file

@ -189,11 +189,11 @@ class MySQL extends Adapter
$data['$uid'] = $this->getUid();
}
$st1->bindValue(':uid', $data['$uid'], PDO::PARAM_STR);
$st1->bindValue(':revision', $revision, PDO::PARAM_STR);
$st1->bindValue(':signature', $signature, PDO::PARAM_STR);
$st1->bindValue(':createdAt', date('Y-m-d H:i:s', time()), PDO::PARAM_STR);
$st1->bindValue(':updatedAt', date('Y-m-d H:i:s', time()), PDO::PARAM_STR);
$st1->bindValue(':uid', $data['$uid'], PDO::PARAM_STR);
$st1->bindValue(':revision', $revision, PDO::PARAM_STR);
$st1->bindValue(':signature', $signature, PDO::PARAM_STR);
$st1->bindValue(':createdAt', date('Y-m-d H:i:s', time()), PDO::PARAM_STR);
$st1->bindValue(':updatedAt', date('Y-m-d H:i:s', time()), PDO::PARAM_STR);
$st1->bindValue(':permissions', json_encode($data['$permissions']), PDO::PARAM_STR);
$st1->execute();
@ -274,14 +274,14 @@ class MySQL extends Adapter
if (is_array($prop['value'])) {
throw new Exception('Value can\'t be an array: '.json_encode($prop['value']));
}
$st2->bindValue(':documentUid', $data['$uid'], PDO::PARAM_STR);
$st2->bindValue(':documentRevision', $revision, PDO::PARAM_STR);
$st2->bindValue(':documentUid', $data['$uid'], PDO::PARAM_STR);
$st2->bindValue(':documentRevision', $revision, PDO::PARAM_STR);
$st2->bindValue(':key', $prop['key'], PDO::PARAM_STR);
$st2->bindValue(':value', $prop['value'], PDO::PARAM_STR);
$st2->bindValue(':primitive', $prop['type'], PDO::PARAM_STR);
$st2->bindValue(':array', $prop['array'], PDO::PARAM_BOOL);
$st2->bindValue(':order', $prop['order'], PDO::PARAM_STR);
$st2->bindValue(':key', $prop['key'], PDO::PARAM_STR);
$st2->bindValue(':value', $prop['value'], PDO::PARAM_STR);
$st2->bindValue(':primitive', $prop['type'], PDO::PARAM_STR);
$st2->bindValue(':array', $prop['array'], PDO::PARAM_BOOL);
$st2->bindValue(':order', $prop['order'], PDO::PARAM_STR);
$st2->execute();
}
@ -367,12 +367,12 @@ class MySQL extends Adapter
(`revision`, `start`, `end`, `key`, `array`, `order`)
VALUES (:revision, :start, :end, :key, :array, :order)');
$st2->bindValue(':revision', $revision, PDO::PARAM_STR);
$st2->bindValue(':start', $start, PDO::PARAM_STR);
$st2->bindValue(':end', $end, PDO::PARAM_STR);
$st2->bindValue(':key', $key, PDO::PARAM_STR);
$st2->bindValue(':array', $isArray, PDO::PARAM_INT);
$st2->bindValue(':order', $order, PDO::PARAM_INT);
$st2->bindValue(':revision', $revision, PDO::PARAM_STR);
$st2->bindValue(':start', $start, PDO::PARAM_STR);
$st2->bindValue(':end', $end, PDO::PARAM_STR);
$st2->bindValue(':key', $key, PDO::PARAM_STR);
$st2->bindValue(':array', $isArray, PDO::PARAM_INT);
$st2->bindValue(':order', $order, PDO::PARAM_INT);
$st2->execute();

View file

@ -38,7 +38,8 @@ class Collection extends Structure
public function isValid($document)
{
$document = new Document(
array_merge($this->merge, ($document instanceof Document) ? $document->getArrayCopy() : $document));
array_merge($this->merge, ($document instanceof Document) ? $document->getArrayCopy() : $document)
);
if (is_null($document->getCollection())) {
$this->message = 'Missing collection attribute $collection';

View file

@ -187,8 +187,12 @@ class Structure extends Validator
if (empty($validator)) { // Error creating validator for property
$this->message = 'Unknown rule type "' . $ruleType . '" for property "' . htmlspecialchars($key, ENT_QUOTES, 'UTF-8') . '"';
// $this->message = 'Unknown property "'.$key.'" type'.
// '. Make sure to follow '.strtolower($collection->getAttribute('name', 'unknown')).' collection structure';
if (empty($ruleType)) {
$this->message = 'Unknown property "'.$key.'" type'.
'. Make sure to follow '.strtolower($collection->getAttribute('name', 'unknown')).' collection structure';
}
return false;
}

View file

@ -34,9 +34,9 @@ class OpenSSL
*
* @return string
*/
public static function decrypt($data, $method, $password, $options = 1, $iv = '', $tag = '', $aad = '')
public static function decrypt($data, $method, $password, $options = 1, $iv = '', $tag = '', $aad = '')
{
return openssl_decrypt($data, $method, $password, $options, $iv, $tag, $aad);
return openssl_decrypt($data, $method, $password, $options, $iv, $tag, $aad);
}
/**

View file

@ -23,8 +23,8 @@ class BaseConsole extends TestCase
->setEndpoint($this->endpoint)
;
$this->demoEmail = 'user.' . rand(0,1000000) . '@appwrite.io';
$this->demoPassword = 'password.' . rand(0,1000000);
$this->demoEmail = 'user.' . rand(0, 1000000) . '@appwrite.io';
$this->demoPassword = 'password.' . rand(0, 1000000);
}
public function tearDown()
@ -32,14 +32,15 @@ class BaseConsole extends TestCase
$this->client = null;
}
public function register() {
public function register()
{
$response = $this->client->call(Client::METHOD_POST, '/auth/register', [
'origin' => 'http://localhost',
'content-type' => 'application/json',
], [
'email' => $this->demoEmail,
'password' => $this->demoPassword,
'confirmation' => 'http://localhost/confirm',
'confirm' => 'http://localhost/confirm',
'success' => 'http://localhost/success',
'failure' => 'http://localhost/failure',
'name' => 'Demo User',
@ -47,4 +48,4 @@ class BaseConsole extends TestCase
return $response;
}
}
}

View file

@ -16,8 +16,8 @@ class BaseProjects extends BaseConsole
{
parent::setUp();
$this->projectsDemoEmail = 'user.' . rand(0,1000000) . '@appwrite.io';
$this->projectsDemoPassword = 'password.' . rand(0,1000000);
$this->projectsDemoEmail = 'user.' . rand(0, 1000000) . '@appwrite.io';
$this->projectsDemoPassword = 'password.' . rand(0, 1000000);
}
public function tearDown()
@ -36,7 +36,7 @@ class BaseProjects extends BaseConsole
], [
'email' => $this->projectsDemoEmail,
'password' => $this->projectsDemoPassword,
'confirmation' => 'http://localhost/confirm',
'confirm' => 'http://localhost/confirm',
'success' => 'http://localhost/success',
'failure' => 'http://localhost/failure',
'name' => 'Porject Demo User',
@ -44,4 +44,4 @@ class BaseProjects extends BaseConsole
return $response;
}
}
}

View file

@ -185,7 +185,7 @@ class Client
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, php_uname('s') . '-' . php_uname('r') . ':php-' . phpversion());
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($curl, $header) use (&$responseHeaders) {
curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($curl, $header) use (&$responseHeaders) {
$len = strlen($header);
$header = explode(':', $header, 2);
@ -198,12 +198,12 @@ class Client
return $len;
});
if($method != self::METHOD_GET) {
if ($method != self::METHOD_GET) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
}
// Allow self signed certificates
if($this->selfSigned) {
if ($this->selfSigned) {
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
}
@ -212,7 +212,7 @@ class Client
$responseType = (isset($responseHeaders['content-type'])) ? $responseHeaders['content-type'] : '';
$responseStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
switch(substr($responseType, 0, strpos($responseType, ';'))) {
switch (substr($responseType, 0, strpos($responseType, ';'))) {
case 'application/json':
$responseBody = json_decode($responseBody, true);
break;
@ -254,16 +254,16 @@ class Client
* @param string $prefix
* @return array
*/
protected function flatten(array $data, $prefix = '') {
protected function flatten(array $data, $prefix = '')
{
$output = [];
foreach($data as $key => $value) {
foreach ($data as $key => $value) {
$finalKey = $prefix ? "{$prefix}[{$key}]" : $key;
if (is_array($value)) {
$output += $this->flatten($value, $finalKey); // @todo: handle name collision here if needed
}
else {
} else {
$output[$finalKey] = $value;
}
}

View file

@ -5,7 +5,7 @@ namespace Tests\E2E;
use Tests\E2E\Client;
class ConsoleHealthTest extends BaseConsole
{
{
public function testHTTPSuccess()
{
$response = $this->client->call(Client::METHOD_GET, '/health', [
@ -88,4 +88,4 @@ class ConsoleHealthTest extends BaseConsole
$this->assertEquals('online', $response['body']['status']);
$this->assertStringStartsWith('ClamAV ', $response['body']['version']);
}
}
}

View file

@ -5,7 +5,7 @@ namespace Tests\E2E;
use Tests\E2E\Client;
class ConsoleProjectsTest extends BaseConsole
{
{
public function testRegisterSuccess()
{
$response = $this->register();
@ -25,7 +25,8 @@ class ConsoleProjectsTest extends BaseConsole
/**
* @depends testRegisterSuccess
*/
public function testProjectsList($data) {
public function testProjectsList($data)
{
$response = $this->client->call(Client::METHOD_GET, '/projects', [
'origin' => 'http://localhost',
'content-type' => 'application/json',
@ -39,7 +40,8 @@ class ConsoleProjectsTest extends BaseConsole
/**
* @depends testRegisterSuccess
*/
public function testProjectsCreateSuccess($data) {
public function testProjectsCreateSuccess($data)
{
$team = $this->client->call(Client::METHOD_POST, '/teams', [
'origin' => 'http://localhost',
'content-type' => 'application/json',
@ -81,8 +83,8 @@ class ConsoleProjectsTest extends BaseConsole
/**
* @depends testProjectsCreateSuccess
*/
public function testProjectsUpdateSuccess($data) {
public function testProjectsUpdateSuccess($data)
{
$response = $this->client->call(Client::METHOD_POST, '/projects', [
'origin' => 'http://localhost',
'content-type' => 'application/json',
@ -100,4 +102,4 @@ class ConsoleProjectsTest extends BaseConsole
$this->assertEquals('New Demo Project Description', $response['body']['description']);
$this->assertEquals('https://appwrite.io/new', $response['body']['url']);
}
}
}

View file

@ -10,6 +10,8 @@ class ConsoleTest extends BaseConsole
{
$response = $this->register();
var_dump($_SERVER);
$this->assertEquals('http://localhost/success', $response['headers']['location']);
$this->assertEquals("\n", $response['body']);
@ -93,4 +95,4 @@ class ConsoleTest extends BaseConsole
$this->assertEquals('401', $response['body']['code']);
}
}
}

View file

@ -79,8 +79,8 @@ class ProjectDatabaseTest extends BaseProjects
/**
* @depends testRegisterSuccess
*/
public function testCollectionCreateSuccess($data) {
public function testCollectionCreateSuccess($data)
{
$actors = $this->client->call(Client::METHOD_POST, '/database', [
'content-type' => 'application/json',
'x-appwrite-project' => $data['projectUid'],
@ -170,7 +170,8 @@ class ProjectDatabaseTest extends BaseProjects
/**
* @depends testCollectionCreateSuccess
*/
public function testDocumentCreateSuccess($data) {
public function testDocumentCreateSuccess($data)
{
$document1 = $this->client->call(Client::METHOD_POST, '/database/' . $data['moviesId'] . '/documents', [
'content-type' => 'application/json',
'x-appwrite-project' => $data['projectUid'],
@ -313,7 +314,8 @@ class ProjectDatabaseTest extends BaseProjects
/**
* @depends testDocumentCreateSuccess
*/
public function testDocumentsListSuccessOrderAndCasting($data) {
public function testDocumentsListSuccessOrderAndCasting($data)
{
$documents = $this->client->call(Client::METHOD_GET, '/database/' . $data['moviesId'] . '/documents', [
'content-type' => 'application/json',
'x-appwrite-project' => $data['projectUid'],
@ -348,7 +350,8 @@ class ProjectDatabaseTest extends BaseProjects
/**
* @depends testDocumentCreateSuccess
*/
public function testDocumentsListSuccessLimitAndOffset($data) {
public function testDocumentsListSuccessLimitAndOffset($data)
{
$documents = $this->client->call(Client::METHOD_GET, '/database/' . $data['moviesId'] . '/documents', [
'content-type' => 'application/json',
'x-appwrite-project' => $data['projectUid'],
@ -383,7 +386,8 @@ class ProjectDatabaseTest extends BaseProjects
/**
* @depends testDocumentCreateSuccess
*/
public function testDocumentsListSuccessFirstAndLast($data) {
public function testDocumentsListSuccessFirstAndLast($data)
{
$documents = $this->client->call(Client::METHOD_GET, '/database/' . $data['moviesId'] . '/documents', [
'content-type' => 'application/json',
'x-appwrite-project' => $data['projectUid'],
@ -417,7 +421,8 @@ class ProjectDatabaseTest extends BaseProjects
/**
* @depends testDocumentCreateSuccess
*/
public function testDocumentsListSuccessSerach($data) {
public function testDocumentsListSuccessSerach($data)
{
$documents = $this->client->call(Client::METHOD_GET, '/database/' . $data['moviesId'] . '/documents', [
'content-type' => 'application/json',
'x-appwrite-project' => $data['projectUid'],
@ -456,7 +461,8 @@ class ProjectDatabaseTest extends BaseProjects
/**
* @depends testDocumentCreateSuccess
*/
public function testDocumentsListSuccessFilters($data) {
public function testDocumentsListSuccessFilters($data)
{
$documents = $this->client->call(Client::METHOD_GET, '/database/' . $data['moviesId'] . '/documents', [
'content-type' => 'application/json',
'x-appwrite-project' => $data['projectUid'],
@ -498,4 +504,4 @@ class ProjectDatabaseTest extends BaseProjects
$this->assertEquals('Spider-Man: Far From Home', $documents['body']['documents'][0]['name']);
$this->assertEquals('Spider-Man: Homecoming', $documents['body']['documents'][1]['name']);
}
}
}