2019-05-09 18:54:39 +12:00
< ? php
// Init
require_once __DIR__ . '/init.php' ;
global $env , $request , $response , $register , $consoleDB , $project , $domain , $sentry , $version , $service ;
use Utopia\App ;
use Utopia\Request ;
use Utopia\Response ;
use Utopia\Validator\Host ;
use Utopia\Validator\Range ;
use Utopia\View ;
use Utopia\Exception ;
use Utopia\Abuse\Abuse ;
use Utopia\Abuse\Adapters\TimeLimit ;
use Auth\Auth ;
use Database\Document ;
use Database\Validator\Authorization ;
use Event\Event ;
/**
* Configuration files
*/
$roles = include __DIR__ . '/config/roles.php' ; // User roles and scopes
$providers = include __DIR__ . '/config/providers.php' ; // OAuth providers list
$sdks = include __DIR__ . '/config/sdks.php' ; // List of SDK clients
2019-08-03 17:58:44 +12:00
$services = include __DIR__ . '/config/services.php' ; // List of SDK clients
2019-05-09 18:54:39 +12:00
$utopia = new App ( 'Asia/Tel_Aviv' , $env );
$webhook = new Event ( 'v1-webhooks' , 'WebhooksV1' );
$audit = new Event ( 'v1-audits' , 'AuditsV1' );
$usage = new Event ( 'v1-usage' , 'UsageV1' );
2019-08-11 03:24:47 +12:00
$clients = 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' ])) {
return true ;
}
return false ;
}));
$utopia -> init ( function () use ( $utopia , $request , $response , $register , & $user , $project , $roles , $webhook , $audit , $usage , $domain , $clients ) {
2019-05-09 18:54:39 +12:00
$route = $utopia -> match ( $request );
/**
* Validate SSL Connection
*/
$https = $request -> getServer ( 'HTTP_X_FORWARDED_PROTO' , $request -> getServer ( 'HTTPS' , '' ));
if ( empty ( $https ) || 'off' == $https ) {
$response -> redirect ( 'https://' . $request -> getServer ( 'HTTP_HOST' , '' ) . $request -> getServer ( 'REQUEST_URI' ));
exit ( 0 );
}
$referrer = $request -> getServer ( 'HTTP_REFERER' , '' );
$origin = $request -> getServer ( 'HTTP_ORIGIN' , parse_url ( $referrer , PHP_URL_SCHEME ) . '://' . parse_url ( $referrer , PHP_URL_HOST ));
2019-08-11 03:24:47 +12:00
$refDomain = ( in_array ( $origin , $clients ))
2019-05-09 18:54:39 +12:00
? $origin : 'http://localhost' ;
/**
* Security Headers
*
* As recommended at :
* @ see https :// www . owasp . org / index . php / List_of_useful_HTTP_headers
*/
$response
-> addHeader ( 'Server' , 'Appwrite' )
-> addHeader ( 'X-XSS-Protection' , '1; mode=block; report=/v1/xss?url=' . urlencode ( $request -> getServer ( 'REQUEST_URI' )))
-> addHeader ( 'Strict-Transport-Security' , 'max-age=16070400' )
//->addHeader('X-Frame-Options', ($refDomain == 'http://localhost') ? 'SAMEORIGIN' : 'ALLOW-FROM ' . $refDomain)
-> addHeader ( 'X-Content-Type-Options' , 'nosniff' )
-> addHeader ( 'Access-Control-Allow-Methods' , 'GET, POST, PUT, PATCH, DELETE' )
-> addHeader ( 'Access-Control-Allow-Headers' , 'Origin, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Ajax, Origin, Content-Type, Accept, X-Appwrite-Project, X-Appwrite-Key, X-SDK-Version' )
-> addHeader ( 'Access-Control-Allow-Origin' , $refDomain )
-> addHeader ( 'Access-Control-Allow-Credentials' , 'true' )
;
/**
* Validate Client Domain - Check to avoid CSRF attack
* Adding appwrite api domains to allow XDOMAIN communication
*/
2019-08-11 03:24:47 +12:00
$hostValidator = new Host ( array_merge ( $clients , [ 'http://localhost' , 'https://localhost' , 'https://appwrite.test' , 'https://appwrite.io' ]));
2019-05-09 18:54:39 +12:00
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 );
}
/**
* ACL Check
*/
$role = ( $user -> isEmpty ()) ? Auth :: USER_ROLE_GUEST : Auth :: USER_ROLE_MEMBER ;
// Add user roles
$membership = $user -> search ( 'teamId' , $project -> getAttribute ( 'teamId' , null ), $user -> getAttribute ( 'memberships' , []));
if ( $membership ) {
foreach ( $membership -> getAttribute ( 'roles' , []) as $memberRole ) {
switch ( $memberRole ) {
case 'owner' :
$role = Auth :: USER_ROLE_OWNER ;
break ;
case 'admin' :
$role = Auth :: USER_ROLE_ADMIN ;
break ;
case 'developer' :
$role = Auth :: USER_ROLE_DEVELOPER ;
break ;
}
}
}
$scope = $route -> getLabel ( 'scope' , 'none' ); // Allowed scope for chosen route
$scopes = $roles [ $role ][ 'scopes' ]; // Allowed scopes for user role
// Check if given key match project API keys
$key = $project -> search ( 'secret' , $request -> getHeader ( 'X-Appwrite-Key' , '' ), $project -> getAttribute ( 'keys' , []));
/**
* Try app auth when we have project key and no user
* Mock user to app and grant API key scopes in addition to default app scopes
*/
if ( null !== $key && $user -> isEmpty ()) {
$user = new Document ([
'$uid' => 0 ,
'status' => Auth :: USER_STATUS_ACTIVATED ,
'email' => 'app.' . $project -> getUid () . '@service.' . $domain ,
'password' => '' ,
'name' => $project -> getAttribute ( 'name' , 'Untitled' ),
]);
$role = Auth :: USER_ROLE_APP ;
$scopes = array_merge ( $roles [ $role ][ 'scopes' ], $key -> getAttribute ( 'scopes' , []));
Authorization :: disable (); // Cancel security segmentation for API keys.
}
Authorization :: setRole ( 'user:' . $user -> getUid ());
Authorization :: setRole ( 'role:' . $role );
array_map ( function ( $node ) {
if ( isset ( $node [ 'teamId' ]) && isset ( $node [ 'roles' ])) {
Authorization :: setRole ( 'team:' . $node [ 'teamId' ]);
foreach ( $node [ 'roles' ] as $nodeRole ) { // Set all team roles
Authorization :: setRole ( 'team:' . $node [ 'teamId' ] . '/' . $nodeRole );
}
}
}, $user -> getAttribute ( 'memberships' , []));
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
throw new Exception ( 'Invalid credentials. User is blocked' , 401 ); // User is in status blocked
}
if ( $user -> getAttribute ( 'reset' )) {
throw new Exception ( 'Password reset is required' , 412 );
}
/**
* Background Jobs
*/
$webhook
-> setParam ( 'projectId' , $project -> getUid ())
-> setParam ( 'event' , $route -> getLabel ( 'webhook' , '' ))
-> setParam ( 'payload' , [])
;
$audit
-> setParam ( 'projectId' , $project -> getUid ())
-> setParam ( 'userId' , $user -> getUid ())
-> setParam ( 'event' , '' )
-> setParam ( 'resource' , '' )
-> setParam ( 'userAgent' , $request -> getServer ( 'HTTP_USER_AGENT' , '' ))
-> setParam ( 'ip' , $request -> getIP ())
-> setParam ( 'data' , [])
;
$usage
-> setParam ( 'projectId' , $project -> getUid ())
-> setParam ( 'url' , $request -> getServer ( 'HTTP_HOST' , '' ) . $request -> getServer ( 'REQUEST_URI' , '' ))
-> setParam ( 'method' , $request -> getServer ( 'REQUEST_METHOD' , 'UNKNOWN' ))
-> setParam ( 'request' , 0 )
-> setParam ( 'response' , 0 )
-> setParam ( 'storage' , 0 )
;
/**
* 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 -> setNamespace ( 'app_' . $project -> getUid ());
$timeLimit
-> setParam ( '{userId}' , $user -> getUid ())
-> setParam ( '{userAgent}' , $request -> getServer ( 'HTTP_USER_AGENT' , '' ))
-> setParam ( '{ip}' , $request -> getIP ())
-> setParam ( '{url}' , $request -> getServer ( 'HTTP_HOST' , '' ) . $route -> getURL ())
;
2019-06-09 01:13:19 +12:00
//TODO make sure we get array here
2019-05-09 18:54:39 +12:00
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 );
$response
-> addHeader ( 'X-RateLimit-Limit' , $timeLimit -> limit ())
-> addHeader ( 'X-RateLimit-Remaining' , $timeLimit -> remaining ())
-> addHeader ( 'X-RateLimit-Reset' , $timeLimit -> time () + $route -> getLabel ( 'abuse-time' , 3600 ))
;
if ( $abuse -> check ()) {
throw new Exception ( 'Too many requests' , 429 );
}
});
$utopia -> shutdown ( function () use ( $response , $request , $webhook , $audit , $usage ) {
/**
* Trigger Events for background jobs
*/
if ( ! empty ( $webhook -> getParam ( 'event' ))) {
$webhook -> trigger ();
}
if ( ! empty ( $audit -> getParam ( 'event' ))) {
$audit -> trigger ();
}
$usage
-> setParam ( 'request' , $request -> getSize ())
-> setParam ( 'response' , $response -> getSize ())
-> trigger ()
;
});
$utopia -> options ( function () use ( $request , $response , $domain , $project ) {
2019-07-06 21:48:57 +12:00
$origin = $request -> getServer ( 'HTTP_ORIGIN' );
2019-05-09 18:54:39 +12:00
$response
-> addHeader ( 'Access-Control-Allow-Methods' , 'GET, POST, PUT, PATCH, DELETE' )
-> addHeader ( 'Access-Control-Allow-Headers' , 'Origin, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Ajax, Origin, Content-Type, Accept, X-Appwrite-Project, X-Appwrite-Key, X-SDK-Version' )
-> addHeader ( 'Access-Control-Allow-Origin' , $origin )
-> addHeader ( 'Access-Control-Allow-Credentials' , 'true' )
-> send ();
;
});
$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
case 403 : // Error allowed publicly
case 404 : // Error allowed publicly
case 412 : // Error allowed publicly
case 429 : // Error allowed publicly
$code = $error -> getCode ();
$message = $error -> getMessage ();
break ;
default :
$code = 500 ; // All other errors get the generic 500 server error status code
$message = 'Server Error' ;
}
$_SERVER = []; // Reset before reporting to error log to avoid keys being compromised
2019-08-11 18:15:23 +12:00
$output = (( App :: ENV_TYPE_DEVELOPMENT == $env )) ? [
2019-05-09 18:54:39 +12:00
'message' => $error -> getMessage (),
'code' => $error -> getCode (),
'file' => $error -> getFile (),
'line' => $error -> getLine (),
'trace' => $error -> getTrace (),
'version' => $version ,
] : [
'message' => $message ,
'code' => $code ,
'version' => $version ,
];
$response
-> addHeader ( 'Cache-Control' , 'no-cache, no-store, must-revalidate' )
-> addHeader ( 'Expires' , '0' )
-> addHeader ( 'Pragma' , 'no-cache' )
-> setStatusCode ( $code )
;
$route = $utopia -> match ( $request );
$template = ( $route ) ? $route -> getLabel ( 'error' , null ) : null ;
if ( $template ) {
$layout = new View ( __DIR__ . '/views/layouts/default.phtml' );
$comp = new View ( $template );
$comp
-> setParam ( 'projectName' , $project -> getAttribute ( 'name' ))
-> setParam ( 'projectURL' , $project -> getAttribute ( 'url' ))
-> setParam ( 'message' , $error -> getMessage ())
-> setParam ( 'code' , $code )
;
$layout
-> setParam ( 'title' , $project -> getAttribute ( 'name' ) . ' - Error' )
-> setParam ( 'description' , 'No Description' )
-> setParam ( 'body' , $comp )
-> setParam ( 'version' , $version )
-> setParam ( 'litespeed' , false )
;
$response -> send ( $layout -> render ());
}
$response
-> json ( $output )
;
});
2019-07-30 19:54:12 +12:00
$utopia -> get ( '/manifest.json' )
-> desc ( 'Progressive app manifest file' )
-> label ( 'scope' , 'public' )
-> label ( 'docs' , false )
-> action (
function () use ( $response , $project ) {
$response -> json ([
2019-08-03 17:58:44 +12:00
'name' => APP_NAME ,
'short_name' => APP_NAME ,
'start_url' => '.' ,
'url' => 'https://appwrite.io/' ,
'display' => 'standalone' ,
'background_color' => '#fff' ,
'theme_color' => '#f02e65' ,
'description' => 'End to end backend server for frontend and mobile apps. 👩💻👨💻' ,
'icons' => [
2019-07-30 19:54:12 +12:00
[
'src' => 'images/favicon.png' ,
'sizes' => '256x256' ,
'type' => 'image/png'
]
]
]);
}
);
$utopia -> get ( '/robots.txt' )
-> desc ( 'Robots.txt File' )
-> label ( 'scope' , 'public' )
-> label ( 'docs' , false )
-> action (
function () use ( $response , $project ) {
$response -> text ( " # robotstxt.org/
User - agent : *
" );
}
);
$utopia -> get ( '/humans.txt' )
-> desc ( 'Humans.txt File' )
-> label ( 'scope' , 'public' )
-> label ( 'docs' , false )
-> action (
function () use ( $response , $project ) {
$response -> text ( " # humanstxt.org/
# The humans responsible & technology colophon
# TEAM
< name > -- < role > -- < twitter >
# THANKS
< name > " );
}
);
2019-05-09 18:54:39 +12:00
$utopia -> get ( '/v1/info' ) // This is only visible to gods
2019-08-03 17:58:44 +12:00
-> label ( 'scope' , 'god' )
2019-05-09 18:54:39 +12:00
-> label ( 'docs' , false )
-> action (
function () use ( $request , $response , $user , $project , $version , $env ) { //TODO CONSIDER BLOCKING THIS ACTION TO ROLE GOD
$response -> json ([
'name' => 'API' ,
'version' => $version ,
'environment' => $env ,
'time' => date ( 'Y-m-d H:i:s' , time ()),
'user' => [
'id' => $user -> getUid (),
'name' => $user -> getAttribute ( 'name' , '' ),
],
'project' => [
'id' => $project -> getUid (),
'name' => $project -> getAttribute ( 'name' , '' ),
],
]);
}
);
$utopia -> get ( '/v1/xss' )
-> desc ( 'Log XSS errors reported by browsers using X-XSS-Protection header' )
-> label ( 'scope' , 'public' )
-> label ( 'docs' , false )
-> action (
2019-08-11 03:24:47 +12:00
function () {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'XSS detected and reported by a browser client' , 500 );
}
);
$utopia -> get ( '/v1/proxy' )
-> label ( 'scope' , 'public' )
-> label ( 'docs' , false )
-> action (
2019-08-11 03:24:47 +12:00
function () use ( $response , $console , $clients ) {
2019-05-09 18:54:39 +12:00
$view = new View ( __DIR__ . '/views/proxy.phtml' );
$view
-> setParam ( 'routes' , '' )
2019-08-11 03:24:47 +12:00
-> setParam ( 'clients' , array_merge ( $clients , $console -> getAttribute ( 'clients' , [])))
2019-05-09 18:54:39 +12:00
;
$response
-> setContentType ( Response :: CONTENT_TYPE_HTML )
-> removeHeader ( 'X-Frame-Options' )
-> send ( $view -> render ());
}
);
$utopia -> get ( '/v1/docs' )
-> label ( 'scope' , 'public' )
-> label ( 'docs' , false )
-> action (
function () use ( $response , $utopia ) {
$view = new View ( __DIR__ . '/views/docs.phtml' );
$view
-> setParam ( 'routes' , $utopia -> getRoutes ())
;
$response -> send ( $view -> render ());
}
);
$utopia -> get ( '/v1/server' ) // This is only visible to gods
2019-08-03 17:58:44 +12:00
-> label ( 'scope' , 'god' )
2019-05-09 18:54:39 +12:00
-> label ( 'docs' , false )
-> action (
function () use ( $response ) {
$response -> json ( $_SERVER );
}
);
$utopia -> get ( '/v1/open-api-2.json' )
-> label ( 'scope' , 'public' )
-> label ( 'docs' , false )
2019-07-06 21:48:57 +12:00
-> param ( 'extensions' , 0 , function () { return new Range ( 0 , 1 );}, 'Show extra data.' , true )
2019-05-09 18:54:39 +12:00
-> action (
2019-08-03 17:58:44 +12:00
function ( $extensions ) use ( $response , $utopia , $domain , $version , $services , $consoleDB ) {
2019-05-09 18:54:39 +12:00
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 ) {
$match = $match == strtoupper ( $match ) ? strtolower ( $match ) : lcfirst ( $match );
}
return implode ( '_' , $ret );
}
function fromCamelCaseToDash ( $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 ) {
$match = $match == strtoupper ( $match ) ? strtolower ( $match ) : lcfirst ( $match );
}
return implode ( '-' , $ret );
}
/* $scopes = [
'client' => [
'name' => 'Client' ,
'auth' => [],
'services' => [],
],
'server' => [
'name' => 'Server' ,
'auth' => [],
'services' => [],
],
'admin' => [
'name' => 'Admin' ,
'auth' => [],
'services' => [],
],
]; */
2019-08-03 17:58:44 +12:00
foreach ( $services as $service ) { /** @noinspection PhpIncludeInspection */
2019-05-09 18:54:39 +12:00
if ( ! $service [ 'sdk' ]) {
continue ;
}
/** @noinspection PhpIncludeInspection */
include_once $service [ 'controller' ];
}
/**
* Specifications ( v3 . 0.0 ) :
* https :// github . com / OAI / OpenAPI - Specification / blob / master / versions / 3.0 . 0. md
*/
$output = [
'swagger' => '2.0' ,
'info' => [
'version' => $version ,
'title' => APP_NAME ,
'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)' ,
'termsOfService' => 'https://appwrite.io/policy/terms' ,
'contact' => [
'name' => 'Appwrite Team' ,
'url' => 'https://appwrite.io/support' ,
'email' => APP_EMAIL_TEAM ,
],
'license' => [
2019-06-10 17:44:55 +12:00
'name' => 'BSD-3-Clause' ,
2019-06-09 20:51:10 +12:00
'url' => 'https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE' ,
2019-05-09 18:54:39 +12:00
],
],
'host' => $domain ,
'basePath' => '/v1' ,
'schemes' => [ 'https' ],
'consumes' => [ 'application/json' , 'application/x-www-form-urlencoded' ],
'produces' => [ 'application/json' ],
'securityDefinitions' => [
'Project' => [
'type' => 'apiKey' ,
'name' => 'X-Appwrite-Project' ,
2019-06-09 20:51:10 +12:00
'description' => 'Your Appwrite project ID. You can find your project ID in your Appwrite console project settings.' ,
2019-05-09 18:54:39 +12:00
'in' => 'header' ,
],
'Key' => [
'type' => 'apiKey' ,
'name' => 'X-Appwrite-Key' ,
2019-06-09 20:51:10 +12:00
'description' => 'Your Appwrite project secret key. You can can create a new API key from your Appwrite console API keys dashboard.' ,
2019-05-09 18:54:39 +12:00
'in' => 'header' ,
],
'Locale' => [
'type' => 'apiKey' ,
'name' => 'X-Appwrite-Locale' ,
'description' => '' ,
'in' => 'header' ,
],
'Mode' => [
'type' => 'apiKey' ,
'name' => 'X-Appwrite-Mode' ,
'description' => '' ,
'in' => 'header' ,
],
],
'paths' => [],
'definitions' => array (
2019-08-03 17:58:44 +12:00
'Pet' =>
array (
'required' =>
array (
0 => 'id' ,
1 => 'name' ,
),
'properties' =>
array (
'id' =>
array (
'type' => 'integer' ,
'format' => 'int64' ,
),
'name' =>
array (
'type' => 'string' ,
),
'tag' =>
array (
'type' => 'string' ,
),
),
),
'Pets' =>
array (
'type' => 'array' ,
'items' =>
array (
'$ref' => '#/definitions/Pet' ,
),
),
'Error' =>
array (
'required' =>
array (
0 => 'code' ,
1 => 'message' ,
),
'properties' =>
array (
'code' =>
array (
'type' => 'integer' ,
'format' => 'int32' ,
),
'message' =>
array (
'type' => 'string' ,
),
),
),
),
2019-06-09 20:51:10 +12:00
'externalDocs' => [
'description' => 'Full API docs, specs and tutorials' ,
'url' => APP_PROTOCOL . '://' . $domain . '/docs'
]
2019-05-09 18:54:39 +12:00
];
foreach ( $utopia -> getRoutes () as $key => $method ) {
foreach ( $method as $route ) { /* @var $route \Utopia\Route */
if ( ! $route -> getLabel ( 'docs' , true )) {
continue ;
}
if ( empty ( $route -> getLabel ( 'sdk.namespace' , null ))) {
continue ;
}
$url = str_replace ( '/v1' , '' , $route -> getURL ());
$scope = $route -> getLabel ( 'scope' , '' );
$hide = $route -> getLabel ( 'sdk.hide' , false );
if ( $hide ) {
continue ;
}
$temp = [
'summary' => $route -> getDesc (),
'operationId' => $route -> getLabel ( 'sdk.method' , uniqid ()),
'tags' => [ $route -> getLabel ( 'sdk.namespace' , 'default' )],
'description' => $route -> getLabel ( 'sdk.description' , '' ),
'responses' => [
200 => [
'description' => 'An paged array of pets' ,
'schema' => [
'$ref' => '#/definitions/Pet'
],
],
],
];
2019-07-06 21:48:57 +12:00
if ( $extensions ) {
2019-05-09 18:54:39 +12:00
$temp [ 'extensions' ] = [
'weight' => $route -> getOrder (),
'cookies' => $route -> getLabel ( 'sdk.cookies' , false ),
'demo' => 'docs/examples/' . fromCamelCaseToDash ( $route -> getLabel ( 'sdk.namespace' , 'default' )) . '/' . fromCamelCaseToDash ( $temp [ 'operationId' ]) . '.md' ,
];
}
if (( ! empty ( $scope ) && 'public' != $scope )) {
$temp [ 'security' ][] = [ 'Project' => [], 'Key' => []];
}
$requestBody = [
'content' => [
'application/x-www-form-urlencoded' => [
'schema' => [
'type' => 'object' ,
'properties' => [],
],
'required' => [],
]
]
];
foreach ( $route -> getParams () as $name => $param ) {
$validator = ( is_callable ( $param [ 'validator' ])) ? $param [ 'validator' ]() : $param [ 'validator' ]; /* @var $validator \Utopia\Validator */
$node = [
'name' => $name ,
'description' => $param [ 'description' ],
'required' => ! $param [ 'optional' ],
];
switch (( ! empty ( $validator )) ? get_class ( $validator ) : '' ) {
case 'Utopia\Validator\Text' :
$node [ 'type' ] = 'string' ;
$node [ 'x-example' ] = '[' . strtoupper ( fromCamelCase ( $node [ 'name' ])) . ']' ;
break ;
case 'Database\Validator\UID' :
$node [ 'type' ] = 'string' ;
$node [ 'x-example' ] = '[' . strtoupper ( fromCamelCase ( $node [ 'name' ])) . ']' ;
break ;
case 'Utopia\Validator\Email' :
$node [ 'type' ] = 'string' ;
$node [ 'format' ] = 'email' ;
$node [ 'x-example' ] = 'email@example.com' ;
break ;
case 'Utopia\Validator\URL' :
$node [ 'type' ] = 'string' ;
$node [ 'format' ] = 'url' ;
$node [ 'x-example' ] = 'https://example.com' ;
break ;
case 'Utopia\Validator\JSON' :
case 'Utopia\Validator\Mock' :
$node [ 'type' ] = 'object' ;
$node [ 'type' ] = 'string' ;
$node [ 'x-example' ] = '{}' ;
//$node['format'] = 'json';
break ;
case 'Storage\Validators\File' :
$node [ 'type' ] = 'file' ;
$temp [ 'consumes' ] = [ 'multipart/form-data' ];
break ;
case 'Utopia\Validator\ArrayList' :
$node [ 'type' ] = 'array' ;
$node [ 'collectionFormat' ] = 'multi' ;
$node [ 'items' ] = [
'type' => 'string'
];
break ;
case 'Auth\Validator\Password' :
$node [ 'type' ] = 'string' ;
$node [ 'format' ] = 'format' ;
$node [ 'x-example' ] = 'password' ;
break ;
case 'Utopia\Validator\Range' : /* @var $validator \Utopia\Validator\Range */
$node [ 'type' ] = 'integer' ;
$node [ 'format' ] = 'int32' ;
$node [ 'x-example' ] = rand ( $validator -> getMin (), $validator -> getMax ());
break ;
case 'Utopia\Validator\Numeric' :
$node [ 'type' ] = 'integer' ;
$node [ 'format' ] = 'int32' ;
break ;
case 'Utopia\Validator\Length' :
$node [ 'type' ] = 'string' ;
break ;
case 'Utopia\Validator\Host' :
$node [ 'type' ] = 'string' ;
$node [ 'format' ] = 'url' ;
$node [ 'x-example' ] = 'https://example.com' ;
break ;
case 'Utopia\Validator\WhiteList' : /* @var $validator \Utopia\Validator\WhiteList */
$node [ 'type' ] = 'string' ;
$node [ 'x-example' ] = $validator -> getList ()[ 0 ];
break ;
default :
$node [ 'type' ] = 'string' ;
break ;
}
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
$node [ 'in' ] = 'query' ;
$temp [ 'parameters' ][] = $node ;
}
else { // Param is in payload
$node [ 'in' ] = 'formData' ;
$temp [ 'parameters' ][] = $node ;
$requestBody [ 'content' ][ 'application/x-www-form-urlencoded' ][ 'schema' ][ 'properties' ][] = $node ;
if ( ! $param [ 'optional' ]) {
$requestBody [ 'content' ][ 'application/x-www-form-urlencoded' ][ 'required' ][] = $name ;
}
}
$url = str_replace ( ':' . $name , '{' . $name . '}' , $url );
}
$output [ 'paths' ][ $url ][ strtolower ( $route -> getMethod ())] = $temp ;
}
}
/* foreach ( $consoleDB -> getMocks () as $mock ) {
var_dump ( $mock [ 'name' ]);
} */
ksort ( $output [ 'paths' ]);
$response -> json ( $output );
}
);
$name = APP_NAME ;
2019-08-03 17:58:44 +12:00
if ( array_key_exists ( $service , $services )) { /** @noinspection PhpIncludeInspection */
include_once $services [ $service ][ 'controller' ];
$name = APP_NAME . ' ' . ucfirst ( $services [ $service ][ 'name' ]);
2019-05-09 18:54:39 +12:00
}
else {
/** @noinspection PhpIncludeInspection */
2019-08-03 17:58:44 +12:00
include_once $services [ '/' ][ 'controller' ];
2019-05-09 18:54:39 +12:00
}
if ( extension_loaded ( 'newrelic' )) {
$route = $utopia -> match ( $request );
$url = ( ! empty ( $route )) ? $route -> getURL () : '/error' ;
newrelic_set_appname ( $name );
newrelic_name_transaction ( $request -> getServer ( 'REQUEST_METHOD' , 'UNKNOWN' ) . ': ' . $url );
}
$utopia -> run ( $request , $response );