2020-05-05 02:35:01 +12:00
< ? php
use Appwrite\Database\Database ;
2020-05-06 05:30:12 +12:00
use Appwrite\Database\Validator\UID ;
2020-07-15 08:33:52 +12:00
use Appwrite\Storage\Storage ;
use Appwrite\Storage\Validator\File ;
use Appwrite\Storage\Validator\FileSize ;
use Appwrite\Storage\Validator\FileType ;
use Appwrite\Storage\Validator\Upload ;
2020-05-06 05:30:12 +12:00
use Appwrite\Task\Validator\Cron ;
2020-07-13 09:18:52 +12:00
use Utopia\App ;
2020-05-06 05:30:12 +12:00
use Utopia\Response ;
use Utopia\Validator\ArrayList ;
use Utopia\Validator\Assoc ;
2020-05-05 02:35:01 +12:00
use Utopia\Validator\Text ;
use Utopia\Validator\Range ;
2020-05-06 05:30:12 +12:00
use Utopia\Validator\WhiteList ;
2020-07-15 04:13:18 +12:00
use Utopia\Config\Config ;
2020-05-13 10:00:48 +12:00
use Cron\CronExpression ;
2020-05-05 02:35:01 +12:00
include_once __DIR__ . '/../shared/api.php' ;
2020-07-13 09:18:52 +12:00
App :: post ( '/v1/functions' )
-> groups ([ 'api' , 'functions' ])
2020-05-05 02:35:01 +12:00
-> desc ( 'Create Function' )
-> label ( 'scope' , 'functions.write' )
-> label ( 'sdk.platform' , [ APP_PLATFORM_SERVER ])
-> label ( 'sdk.namespace' , 'functions' )
-> label ( 'sdk.method' , 'create' )
2020-05-06 05:30:12 +12:00
-> label ( 'sdk.description' , '/docs/references/functions/create-function.md' )
2020-05-05 02:35:01 +12:00
-> param ( 'name' , '' , function () { return new Text ( 128 ); }, 'Function name.' )
2020-07-15 04:13:18 +12:00
-> param ( 'env' , '' , function () { return new WhiteList ( array_keys ( Config :: getParam ( 'environments' ))); }, 'Execution enviornment.' )
2020-05-11 08:44:28 +12:00
-> param ( 'vars' , [], function () { return new Assoc ();}, 'Key-value JSON object.' , true )
2020-07-15 04:43:34 +12:00
-> param ( 'events' , [], function () { return new ArrayList ( new WhiteList ( array_keys ( Config :: getParam ( 'events' )), true )); }, 'Events list.' , true )
2020-05-11 08:44:28 +12:00
-> param ( 'schedule' , '' , function () { return new Cron (); }, 'Schedule CRON syntax.' , true )
2020-05-14 08:59:02 +12:00
-> param ( 'timeout' , 15 , function () { return new Range ( 1 , 900 ); }, 'Function maximum execution time in seconds.' , true )
2020-07-15 04:13:18 +12:00
-> action ( function ( $name , $env , $vars , $events , $schedule , $timeout , $response , $projectDB ) {
2020-07-13 09:18:52 +12:00
$function = $projectDB -> createDocument ([
'$collection' => Database :: SYSTEM_COLLECTION_FUNCTIONS ,
'$permissions' => [
'read' => [],
'write' => [],
],
'dateCreated' => time (),
'dateUpdated' => time (),
'status' => 'paused' ,
'name' => $name ,
2020-07-15 04:13:18 +12:00
'env' => $env ,
2020-07-13 09:18:52 +12:00
'tag' => '' ,
'vars' => $vars ,
'events' => $events ,
'schedule' => $schedule ,
'previous' => null ,
'next' => null ,
'timeout' => $timeout ,
]);
if ( false === $function ) {
throw new Exception ( 'Failed saving function to DB' , 500 );
2020-05-06 05:30:12 +12:00
}
2020-07-13 09:18:52 +12:00
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> json ( $function -> getArrayCopy ())
;
}, [ 'response' , 'projectDB' ]);
App :: get ( '/v1/functions' )
-> groups ([ 'api' , 'functions' ])
2020-05-06 05:30:12 +12:00
-> desc ( 'List Functions' )
-> label ( 'scope' , 'functions.read' )
-> label ( 'sdk.platform' , [ APP_PLATFORM_SERVER ])
-> label ( 'sdk.namespace' , 'functions' )
-> label ( 'sdk.method' , 'list' )
-> label ( 'sdk.description' , '/docs/references/functions/list-functions.md' )
-> 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 )
2020-07-13 09:18:52 +12:00
-> action ( function ( $search , $limit , $offset , $orderType , $response , $projectDB ) {
$results = $projectDB -> getCollection ([
'limit' => $limit ,
'offset' => $offset ,
'orderField' => 'dateCreated' ,
'orderType' => $orderType ,
'orderCast' => 'int' ,
'search' => $search ,
'filters' => [
'$collection=' . Database :: SYSTEM_COLLECTION_FUNCTIONS ,
],
]);
$response -> json ([ 'sum' => $projectDB -> getSum (), 'functions' => $results ]);
}, [ 'response' , 'projectDB' ]);
App :: get ( '/v1/functions/:functionId' )
-> groups ([ 'api' , 'functions' ])
2020-05-06 05:30:12 +12:00
-> desc ( 'Get Function' )
-> label ( 'scope' , 'functions.read' )
-> label ( 'sdk.platform' , [ APP_PLATFORM_SERVER ])
-> label ( 'sdk.namespace' , 'functions' )
-> label ( 'sdk.method' , 'get' )
-> label ( 'sdk.description' , '/docs/references/functions/get-function.md' )
-> param ( 'functionId' , '' , function () { return new UID (); }, 'Function unique ID.' )
2020-07-13 09:18:52 +12:00
-> action ( function ( $functionId , $response , $projectDB ) {
$function = $projectDB -> getDocument ( $functionId );
2020-05-06 05:30:12 +12:00
2020-07-13 09:18:52 +12:00
if ( empty ( $function -> getId ()) || Database :: SYSTEM_COLLECTION_FUNCTIONS != $function -> getCollection ()) {
2020-07-21 23:53:48 +12:00
throw new Exception ( 'Function not found' , 404 );
2020-05-06 05:30:12 +12:00
}
2020-07-13 09:18:52 +12:00
$response -> json ( $function -> getArrayCopy ());
}, [ 'response' , 'projectDB' ]);
2020-07-21 22:33:23 +12:00
App :: get ( '/v1/functions/:functionId/usage' )
-> desc ( 'Get Function Usage' )
-> groups ([ 'api' , 'functions' ])
-> label ( 'scope' , 'functions.read' )
2020-07-21 23:53:48 +12:00
-> label ( 'sdk.platform' , [ APP_PLATFORM_CONSOLE ])
2020-07-21 22:33:23 +12:00
-> label ( 'sdk.namespace' , 'functions' )
-> label ( 'sdk.method' , 'getUsage' )
-> param ( 'functionId' , '' , function () { return new UID (); }, 'Function unique ID.' )
-> param ( 'range' , 'last30' , function () { return new WhiteList ([ 'daily' , 'monthly' , 'last30' , 'last90' ]); }, 'Date range.' , true )
-> action ( function ( $functionId , $range , $response , $project , $projectDB , $register ) {
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $project */
/** @var Appwrite\Database\Database $consoleDB */
/** @var Appwrite\Database\Database $projectDB */
/** @var Utopia\Registry\Registry $register */
$function = $projectDB -> getDocument ( $functionId );
if ( empty ( $function -> getId ()) || Database :: SYSTEM_COLLECTION_FUNCTIONS != $function -> getCollection ()) {
2020-07-21 23:53:48 +12:00
throw new Exception ( 'Function not found' , 404 );
2020-07-21 22:33:23 +12:00
}
$period = [
'daily' => [
'start' => DateTime :: createFromFormat ( 'U' , \strtotime ( 'today' )),
'end' => DateTime :: createFromFormat ( 'U' , \strtotime ( 'tomorrow' )),
'group' => '1m' ,
],
'monthly' => [
'start' => DateTime :: createFromFormat ( 'U' , \strtotime ( 'midnight first day of this month' )),
'end' => DateTime :: createFromFormat ( 'U' , \strtotime ( 'midnight last day of this month' )),
'group' => '1d' ,
],
'last30' => [
'start' => DateTime :: createFromFormat ( 'U' , \strtotime ( '-30 days' )),
'end' => DateTime :: createFromFormat ( 'U' , \strtotime ( 'tomorrow' )),
'group' => '1d' ,
],
'last90' => [
'start' => DateTime :: createFromFormat ( 'U' , \strtotime ( '-90 days' )),
'end' => DateTime :: createFromFormat ( 'U' , \strtotime ( 'today' )),
'group' => '1d' ,
],
// 'yearly' => [
// 'start' => DateTime::createFromFormat('U', strtotime('midnight first day of january')),
// 'end' => DateTime::createFromFormat('U', strtotime('midnight last day of december')),
// 'group' => '4w',
// ],
];
$client = $register -> get ( 'influxdb' );
$executions = [];
$compute = [];
if ( $client ) {
$start = $period [ $range ][ 'start' ] -> format ( DateTime :: RFC3339 );
$end = $period [ $range ][ 'end' ] -> format ( DateTime :: RFC3339 );
$database = $client -> selectDB ( 'telegraf' );
// Executions
$result = $database -> query ( 'SELECT sum(value) AS "value" FROM "appwrite_usage_executions_all" WHERE time > \'' . $start . '\' AND time < \'' . $end . '\' AND "metric_type"=\'counter\' AND "project"=\'' . $project -> getId () . '\' AND "functionId"=\'' . $function -> getId () . '\' GROUP BY time(' . $period [ $range ][ 'group' ] . ') FILL(null)' );
$points = $result -> getPoints ();
foreach ( $points as $point ) {
$executions [] = [
'value' => ( ! empty ( $point [ 'value' ])) ? $point [ 'value' ] : 0 ,
'date' => \strtotime ( $point [ 'time' ]),
];
}
// Compute
$result = $database -> query ( 'SELECT sum(value) AS "value" FROM "appwrite_usage_executions_time" WHERE time > \'' . $start . '\' AND time < \'' . $end . '\' AND "metric_type"=\'counter\' AND "project"=\'' . $project -> getId () . '\' AND "functionId"=\'' . $function -> getId () . '\' GROUP BY time(' . $period [ $range ][ 'group' ] . ') FILL(null)' );
$points = $result -> getPoints ();
foreach ( $points as $point ) {
$compute [] = [
2020-07-21 23:53:48 +12:00
'value' => ( ! empty ( $point [ 'value' ])) ? $point [ 'value' ] / 60000 : 0 , // minutes
2020-07-21 22:33:23 +12:00
'date' => \strtotime ( $point [ 'time' ]),
];
}
}
$response -> json ([
'executions' => [
'data' => $executions ,
'total' => \array_sum ( \array_map ( function ( $item ) {
return $item [ 'value' ];
}, $executions )),
],
'compute' => [
'data' => $compute ,
'total' => \array_sum ( \array_map ( function ( $item ) {
return $item [ 'value' ];
}, $compute )),
],
]);
2020-07-21 23:53:48 +12:00
}, [ 'response' , 'project' , 'projectDB' , 'register' ]);
2020-07-21 22:33:23 +12:00
2020-07-13 09:18:52 +12:00
App :: put ( '/v1/functions/:functionId' )
-> groups ([ 'api' , 'functions' ])
2020-05-06 05:30:12 +12:00
-> desc ( 'Update Function' )
-> label ( 'scope' , 'functions.write' )
-> label ( 'sdk.platform' , [ APP_PLATFORM_SERVER ])
-> label ( 'sdk.namespace' , 'functions' )
-> label ( 'sdk.method' , 'update' )
-> label ( 'sdk.description' , '/docs/references/functions/update-function.md' )
-> param ( 'functionId' , '' , function () { return new UID (); }, 'Function unique ID.' )
-> param ( 'name' , '' , function () { return new Text ( 128 ); }, 'Function name.' )
2020-05-11 08:44:28 +12:00
-> param ( 'vars' , [], function () { return new Assoc ();}, 'Key-value JSON object.' , true )
2020-07-15 04:43:34 +12:00
-> param ( 'events' , [], function () { return new ArrayList ( new WhiteList ( array_keys ( Config :: getParam ( 'events' )), true )); }, 'Events list.' , true )
2020-05-11 08:44:28 +12:00
-> param ( 'schedule' , '' , function () { return new Cron (); }, 'Schedule CRON syntax.' , true )
2020-05-14 08:59:02 +12:00
-> param ( 'timeout' , 15 , function () { return new Range ( 1 , 900 ); }, 'Function maximum execution time in seconds.' , true )
2020-07-13 09:18:52 +12:00
-> action ( function ( $functionId , $name , $vars , $events , $schedule , $timeout , $response , $projectDB ) {
$function = $projectDB -> getDocument ( $functionId );
if ( empty ( $function -> getId ()) || Database :: SYSTEM_COLLECTION_FUNCTIONS != $function -> getCollection ()) {
throw new Exception ( 'Function not found' , 404 );
}
$cron = ( ! empty ( $function -> getAttribute ( 'tag' , null )) && ! empty ( $schedule )) ? CronExpression :: factory ( $schedule ) : null ;
$next = ( ! empty ( $function -> getAttribute ( 'tag' , null )) && ! empty ( $schedule )) ? $cron -> getNextRunDate () -> format ( 'U' ) : null ;
$function = $projectDB -> updateDocument ( array_merge ( $function -> getArrayCopy (), [
'dateUpdated' => time (),
'name' => $name ,
'vars' => $vars ,
'events' => $events ,
'schedule' => $schedule ,
'previous' => null ,
'next' => $next ,
'timeout' => $timeout ,
]));
if ( false === $function ) {
throw new Exception ( 'Failed saving function to DB' , 500 );
2020-05-06 05:30:12 +12:00
}
2020-07-13 09:18:52 +12:00
$response -> json ( $function -> getArrayCopy ());
}, [ 'response' , 'projectDB' ]);
App :: patch ( '/v1/functions/:functionId/tag' )
-> groups ([ 'api' , 'functions' ])
2020-05-11 16:39:00 +12:00
-> desc ( 'Update Function Tag' )
2020-05-07 05:35:56 +12:00
-> label ( 'scope' , 'functions.write' )
-> label ( 'sdk.platform' , [ APP_PLATFORM_SERVER ])
-> label ( 'sdk.namespace' , 'functions' )
2020-05-11 08:44:28 +12:00
-> label ( 'sdk.method' , 'updateTag' )
2020-05-07 05:35:56 +12:00
-> label ( 'sdk.description' , '/docs/references/functions/update-tag.md' )
-> param ( 'functionId' , '' , function () { return new UID (); }, 'Function unique ID.' )
2020-05-11 16:39:00 +12:00
-> param ( 'tag' , '' , function () { return new UID (); }, 'Tag unique ID.' )
2020-07-13 09:18:52 +12:00
-> action ( function ( $functionId , $tag , $response , $projectDB ) {
$function = $projectDB -> getDocument ( $functionId );
2020-07-16 07:09:33 +12:00
$tag = $projectDB -> getDocument ( $tag );
2020-05-07 05:35:56 +12:00
2020-07-13 09:18:52 +12:00
if ( empty ( $function -> getId ()) || Database :: SYSTEM_COLLECTION_FUNCTIONS != $function -> getCollection ()) {
throw new Exception ( 'Function not found' , 404 );
}
2020-05-13 10:00:48 +12:00
2020-07-16 07:09:33 +12:00
if ( empty ( $tag -> getId ()) || Database :: SYSTEM_COLLECTION_TAGS != $tag -> getCollection ()) {
throw new Exception ( 'Tag not found' , 404 );
}
2020-07-13 09:18:52 +12:00
$schedule = $function -> getAttribute ( 'schedule' , '' );
$cron = ( ! empty ( $function -> getAttribute ( 'tag' ) && ! empty ( $schedule ))) ? CronExpression :: factory ( $schedule ) : null ;
$next = ( ! empty ( $function -> getAttribute ( 'tag' ) && ! empty ( $schedule ))) ? $cron -> getNextRunDate () -> format ( 'U' ) : null ;
2020-05-07 05:35:56 +12:00
2020-07-13 09:18:52 +12:00
$function = $projectDB -> updateDocument ( array_merge ( $function -> getArrayCopy (), [
2020-07-16 07:09:33 +12:00
'tag' => $tag -> getId (),
2020-07-13 09:18:52 +12:00
'next' => $next ,
]));
2020-05-07 05:35:56 +12:00
2020-07-13 09:18:52 +12:00
if ( false === $function ) {
throw new Exception ( 'Failed saving function to DB' , 500 );
2020-05-07 05:35:56 +12:00
}
2020-07-13 09:18:52 +12:00
$response -> json ( $function -> getArrayCopy ());
}, [ 'response' , 'projectDB' ]);
App :: delete ( '/v1/functions/:functionId' )
-> groups ([ 'api' , 'functions' ])
2020-05-06 05:30:12 +12:00
-> desc ( 'Delete Function' )
-> label ( 'scope' , 'functions.write' )
-> label ( 'sdk.platform' , [ APP_PLATFORM_SERVER ])
-> label ( 'sdk.namespace' , 'functions' )
-> label ( 'sdk.method' , 'delete' )
-> label ( 'sdk.description' , '/docs/references/functions/delete-function.md' )
-> param ( 'functionId' , '' , function () { return new UID (); }, 'Function unique ID.' )
2020-07-13 09:18:52 +12:00
-> action ( function ( $functionId , $response , $projectDB ) {
$function = $projectDB -> getDocument ( $functionId );
2020-05-06 05:30:12 +12:00
2020-07-13 09:18:52 +12:00
if ( empty ( $function -> getId ()) || Database :: SYSTEM_COLLECTION_FUNCTIONS != $function -> getCollection ()) {
throw new Exception ( 'Function not found' , 404 );
}
2020-05-07 00:12:52 +12:00
2020-07-13 09:18:52 +12:00
if ( ! $projectDB -> deleteDocument ( $function -> getId ())) {
throw new Exception ( 'Failed to remove function from DB' , 500 );
2020-05-05 02:35:01 +12:00
}
2020-05-06 05:30:12 +12:00
2020-07-13 09:18:52 +12:00
$response -> noContent ();
}, [ 'response' , 'projectDB' ]);
App :: post ( '/v1/functions/:functionId/tags' )
-> groups ([ 'api' , 'functions' ])
2020-05-06 05:30:12 +12:00
-> desc ( 'Create Tag' )
-> label ( 'scope' , 'functions.write' )
-> label ( 'sdk.platform' , [ APP_PLATFORM_SERVER ])
-> label ( 'sdk.namespace' , 'functions' )
-> label ( 'sdk.method' , 'createTag' )
-> label ( 'sdk.description' , '/docs/references/functions/create-tag.md' )
-> param ( 'functionId' , '' , function () { return new UID (); }, 'Function unique ID.' )
2020-05-06 07:42:35 +12:00
-> param ( 'command' , '' , function () { return new Text ( '1028' ); }, 'Code execution command.' )
2020-07-15 08:33:52 +12:00
-> param ( 'code' , [], function () { return new File (); }, 'Gzip file containing your code.' , false )
2020-07-15 15:38:57 +12:00
// ->param('code', '', function () { return new Text(128); }, 'Code package. Use the '.APP_NAME.' code packager to create a deployable package file.')
2020-07-19 09:48:28 +12:00
-> action ( function ( $functionId , $command , $code , $request , $response , $projectDB , $usage ) {
2020-07-13 09:18:52 +12:00
$function = $projectDB -> getDocument ( $functionId );
if ( empty ( $function -> getId ()) || Database :: SYSTEM_COLLECTION_FUNCTIONS != $function -> getCollection ()) {
throw new Exception ( 'Function not found' , 404 );
}
2020-07-15 08:33:52 +12:00
$file = $request -> getFiles ( 'code' );
2020-07-15 09:20:46 +12:00
$device = Storage :: getDevice ( 'functions' );
2020-07-15 08:33:52 +12:00
$fileType = new FileType ([ FileType :: FILE_TYPE_GZIP ]);
$fileSize = new FileSize ( App :: getEnv ( '_APP_STORAGE_LIMIT' , 0 ));
$upload = new Upload ();
if ( empty ( $file )) {
throw new Exception ( 'No file sent' , 400 );
}
// Make sure we handle a single file and multiple files the same way
$file [ 'name' ] = ( \is_array ( $file [ 'name' ]) && isset ( $file [ 'name' ][ 0 ])) ? $file [ 'name' ][ 0 ] : $file [ 'name' ];
$file [ 'tmp_name' ] = ( \is_array ( $file [ 'tmp_name' ]) && isset ( $file [ 'tmp_name' ][ 0 ])) ? $file [ 'tmp_name' ][ 0 ] : $file [ 'tmp_name' ];
$file [ 'size' ] = ( \is_array ( $file [ 'size' ]) && isset ( $file [ 'size' ][ 0 ])) ? $file [ 'size' ][ 0 ] : $file [ 'size' ];
// Check if file type is allowed (feature for project settings?)
2020-07-15 15:38:57 +12:00
// if (!$fileType->isValid($file['tmp_name'])) {
// throw new Exception('File type not allowed', 400);
// }
2020-07-15 08:33:52 +12:00
if ( ! $fileSize -> isValid ( $file [ 'size' ])) { // Check if file size is exceeding allowed limit
throw new Exception ( 'File size not allowed' , 400 );
}
if ( ! $upload -> isValid ( $file [ 'tmp_name' ])) {
throw new Exception ( 'Invalid file' , 403 );
}
// Save to storage
$size = $device -> getFileSize ( $file [ 'tmp_name' ]);
$path = $device -> getPath ( \uniqid () . '.' . \pathinfo ( $file [ 'name' ], PATHINFO_EXTENSION ));
if ( ! $device -> upload ( $file [ 'tmp_name' ], $path )) { // TODO deprecate 'upload' and replace with 'move'
throw new Exception ( 'Failed moving file' , 500 );
}
2020-07-13 09:18:52 +12:00
$tag = $projectDB -> createDocument ([
'$collection' => Database :: SYSTEM_COLLECTION_TAGS ,
'$permissions' => [
'read' => [],
'write' => [],
],
'dateCreated' => time (),
'functionId' => $function -> getId (),
'command' => $command ,
2020-07-15 08:33:52 +12:00
'codePath' => $path ,
'codeSize' => $size ,
2020-07-13 09:18:52 +12:00
]);
if ( false === $tag ) {
throw new Exception ( 'Failed saving tag to DB' , 500 );
2020-05-06 05:30:12 +12:00
}
2020-07-19 09:48:28 +12:00
$usage
-> setParam ( 'storage' , $tag -> getAttribute ( 'codeSize' , 0 ))
;
2020-07-13 09:18:52 +12:00
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> json ( $tag -> getArrayCopy ())
;
2020-07-19 09:48:28 +12:00
}, [ 'request' , 'response' , 'projectDB' , 'usage' ]);
2020-07-13 09:18:52 +12:00
App :: get ( '/v1/functions/:functionId/tags' )
-> groups ([ 'api' , 'functions' ])
2020-05-06 05:30:12 +12:00
-> desc ( 'List Tags' )
-> label ( 'scope' , 'functions.read' )
-> label ( 'sdk.platform' , [ APP_PLATFORM_SERVER ])
-> label ( 'sdk.namespace' , 'functions' )
-> label ( 'sdk.method' , 'listTags' )
-> label ( 'sdk.description' , '/docs/references/functions/list-tags.md' )
2020-05-06 07:42:35 +12:00
-> param ( 'functionId' , '' , function () { return new UID (); }, 'Function unique ID.' )
2020-05-06 05:30:12 +12:00
-> 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 )
2020-07-13 09:18:52 +12:00
-> action ( function ( $functionId , $search , $limit , $offset , $orderType , $response , $projectDB ) {
$function = $projectDB -> getDocument ( $functionId );
2020-05-06 05:30:12 +12:00
2020-07-13 09:18:52 +12:00
if ( empty ( $function -> getId ()) || Database :: SYSTEM_COLLECTION_FUNCTIONS != $function -> getCollection ()) {
throw new Exception ( 'Function not found' , 404 );
}
$results = $projectDB -> getCollection ([
'limit' => $limit ,
'offset' => $offset ,
'orderField' => 'dateCreated' ,
'orderType' => $orderType ,
'orderCast' => 'int' ,
'search' => $search ,
'filters' => [
'$collection=' . Database :: SYSTEM_COLLECTION_TAGS ,
'functionId=' . $function -> getId (),
],
]);
$response -> json ([ 'sum' => $projectDB -> getSum (), 'tags' => $results ]);
}, [ 'response' , 'projectDB' ]);
App :: get ( '/v1/functions/:functionId/tags/:tagId' )
-> groups ([ 'api' , 'functions' ])
2020-05-06 05:30:12 +12:00
-> desc ( 'Get Tag' )
-> label ( 'scope' , 'functions.read' )
-> label ( 'sdk.platform' , [ APP_PLATFORM_SERVER ])
-> label ( 'sdk.namespace' , 'functions' )
-> label ( 'sdk.method' , 'getTag' )
-> label ( 'sdk.description' , '/docs/references/functions/get-tag.md' )
-> param ( 'functionId' , '' , function () { return new UID (); }, 'Function unique ID.' )
-> param ( 'tagId' , '' , function () { return new UID (); }, 'Tag unique ID.' )
2020-07-13 09:18:52 +12:00
-> action ( function ( $functionId , $tagId , $response , $projectDB ) {
$function = $projectDB -> getDocument ( $functionId );
2020-05-06 05:30:12 +12:00
2020-07-13 09:18:52 +12:00
if ( empty ( $function -> getId ()) || Database :: SYSTEM_COLLECTION_FUNCTIONS != $function -> getCollection ()) {
throw new Exception ( 'Function not found' , 404 );
}
2020-05-06 05:30:12 +12:00
2020-07-13 09:18:52 +12:00
$tag = $projectDB -> getDocument ( $tagId );
2020-05-06 05:30:12 +12:00
2020-07-13 09:18:52 +12:00
if ( $tag -> getAttribute ( 'functionId' ) !== $function -> getId ()) {
throw new Exception ( 'Tag not found' , 404 );
}
2020-05-06 05:30:12 +12:00
2020-07-13 09:18:52 +12:00
if ( empty ( $tag -> getId ()) || Database :: SYSTEM_COLLECTION_TAGS != $tag -> getCollection ()) {
throw new Exception ( 'Tag not found' , 404 );
2020-05-06 05:30:12 +12:00
}
2020-07-13 09:18:52 +12:00
$response -> json ( $tag -> getArrayCopy ());
}, [ 'response' , 'projectDB' ]);
App :: delete ( '/v1/functions/:functionId/tags/:tagId' )
-> groups ([ 'api' , 'functions' ])
2020-05-06 05:30:12 +12:00
-> desc ( 'Delete Tag' )
-> label ( 'scope' , 'functions.write' )
-> label ( 'sdk.platform' , [ APP_PLATFORM_SERVER ])
-> label ( 'sdk.namespace' , 'functions' )
-> label ( 'sdk.method' , 'deleteTag' )
-> label ( 'sdk.description' , '/docs/references/functions/delete-tag.md' )
-> param ( 'functionId' , '' , function () { return new UID (); }, 'Function unique ID.' )
-> param ( 'tagId' , '' , function () { return new UID (); }, 'Tag unique ID.' )
2020-07-19 09:48:28 +12:00
-> action ( function ( $functionId , $tagId , $response , $projectDB , $usage ) {
2020-07-13 09:18:52 +12:00
$function = $projectDB -> getDocument ( $functionId );
2020-05-06 05:30:12 +12:00
2020-07-13 09:18:52 +12:00
if ( empty ( $function -> getId ()) || Database :: SYSTEM_COLLECTION_FUNCTIONS != $function -> getCollection ()) {
throw new Exception ( 'Function not found' , 404 );
}
$tag = $projectDB -> getDocument ( $tagId );
2020-05-06 05:30:12 +12:00
2020-07-13 09:18:52 +12:00
if ( $tag -> getAttribute ( 'functionId' ) !== $function -> getId ()) {
throw new Exception ( 'Tag not found' , 404 );
}
2020-05-06 05:30:12 +12:00
2020-07-13 09:18:52 +12:00
if ( empty ( $tag -> getId ()) || Database :: SYSTEM_COLLECTION_TAGS != $tag -> getCollection ()) {
throw new Exception ( 'Tag not found' , 404 );
}
2020-05-07 00:12:52 +12:00
2020-07-19 09:48:28 +12:00
$device = Storage :: getDevice ( 'functions' );
if ( $device -> delete ( $tag -> getAttribute ( 'codePath' , '' ))) {
if ( ! $projectDB -> deleteDocument ( $tag -> getId ())) {
throw new Exception ( 'Failed to remove tag from DB' , 500 );
}
2020-05-06 05:30:12 +12:00
}
2020-07-19 09:48:28 +12:00
$usage
-> setParam ( 'storage' , $tag -> getAttribute ( 'codeSize' , 0 ) * - 1 )
;
2020-07-13 09:18:52 +12:00
$response -> noContent ();
2020-07-19 09:48:28 +12:00
}, [ 'response' , 'projectDB' , 'usage' ]);
2020-07-13 09:18:52 +12:00
App :: post ( '/v1/functions/:functionId/executions' )
-> groups ([ 'api' , 'functions' ])
2020-05-06 05:30:12 +12:00
-> desc ( 'Create Execution' )
-> label ( 'scope' , 'functions.write' )
-> label ( 'sdk.platform' , [ APP_PLATFORM_SERVER ])
-> label ( 'sdk.namespace' , 'functions' )
-> label ( 'sdk.method' , 'createExecution' )
-> label ( 'sdk.description' , '/docs/references/functions/create-execution.md' )
-> param ( 'functionId' , '' , function () { return new UID (); }, 'Function unique ID.' )
2020-05-06 07:42:35 +12:00
-> param ( 'async' , 1 , function () { return new Range ( 0 , 1 ); }, 'Execute code asynchronously. Pass 1 for true, 0 for false. Default value is 1.' , true )
2020-07-17 00:04:06 +12:00
-> action ( function ( $functionId , $async , $response , $project , $projectDB ) {
2020-07-17 09:50:37 +12:00
/** @var Utopia\Response $response */
/** @var Appwrite\Database\Document $project */
/** @var Appwrite\Database\Database $projectDB */
2020-07-13 09:18:52 +12:00
$function = $projectDB -> getDocument ( $functionId );
if ( empty ( $function -> getId ()) || Database :: SYSTEM_COLLECTION_FUNCTIONS != $function -> getCollection ()) {
throw new Exception ( 'Function not found' , 404 );
}
2020-07-17 09:50:37 +12:00
$tag = $projectDB -> getDocument ( $function -> getAttribute ( 'tag' ));
if ( $tag -> getAttribute ( 'functionId' ) !== $function -> getId ()) {
throw new Exception ( 'Tag not found. Deploy tag before trying to execute a function' , 404 );
}
if ( empty ( $tag -> getId ()) || Database :: SYSTEM_COLLECTION_TAGS != $tag -> getCollection ()) {
throw new Exception ( 'Tag not found. Deploy tag before trying to execute a function' , 404 );
}
2020-07-13 09:18:52 +12:00
$execution = $projectDB -> createDocument ([
'$collection' => Database :: SYSTEM_COLLECTION_EXECUTIONS ,
'$permissions' => [
'read' => [],
'write' => [],
],
'dateCreated' => time (),
'functionId' => $function -> getId (),
2020-07-17 20:14:16 +12:00
'status' => 'waiting' , // waiting / processing / completed / failed
2020-07-13 09:18:52 +12:00
'exitCode' => 0 ,
'stdout' => '' ,
'stderr' => '' ,
'time' => 0 ,
]);
if ( false === $execution ) {
throw new Exception ( 'Failed saving execution to DB' , 500 );
2020-05-06 05:30:12 +12:00
}
2020-07-13 09:18:52 +12:00
if (( bool ) $async ) {
2020-07-16 00:49:10 +12:00
// Issue a TLS certificate when domain is verified
Resque :: enqueue ( 'v1-functions' , 'FunctionsV1' , [
2020-07-17 00:04:06 +12:00
'projectId' => $project -> getId (),
2020-07-16 08:29:55 +12:00
'functionId' => $function -> getId (),
2020-07-17 09:50:37 +12:00
'executionId' => $execution -> getId (),
2020-07-16 08:29:55 +12:00
'functionTag' => $tag -> getId (),
2020-07-17 09:50:37 +12:00
'functionTrigger' => 'API' ,
2020-07-16 00:49:10 +12:00
]);
2020-07-13 09:18:52 +12:00
}
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> json ( $execution -> getArrayCopy ())
;
2020-07-17 00:04:06 +12:00
}, [ 'response' , 'project' , 'projectDB' ]);
2020-07-13 09:18:52 +12:00
App :: get ( '/v1/functions/:functionId/executions' )
-> groups ([ 'api' , 'functions' ])
2020-05-06 05:30:12 +12:00
-> desc ( 'List Executions' )
-> label ( 'scope' , 'functions.read' )
-> label ( 'sdk.platform' , [ APP_PLATFORM_SERVER ])
-> label ( 'sdk.namespace' , 'functions' )
-> label ( 'sdk.method' , 'listExecutions' )
-> label ( 'sdk.description' , '/docs/references/functions/list-executions.md' )
2020-05-06 07:42:35 +12:00
-> param ( 'functionId' , '' , function () { return new UID (); }, 'Function unique ID.' )
2020-05-06 05:30:12 +12:00
-> 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 )
2020-07-13 09:18:52 +12:00
-> action ( function ( $functionId , $search , $limit , $offset , $orderType , $response , $projectDB ) {
$function = $projectDB -> getDocument ( $functionId );
2020-05-06 05:30:12 +12:00
2020-07-13 09:18:52 +12:00
if ( empty ( $function -> getId ()) || Database :: SYSTEM_COLLECTION_FUNCTIONS != $function -> getCollection ()) {
throw new Exception ( 'Function not found' , 404 );
}
$results = $projectDB -> getCollection ([
'limit' => $limit ,
'offset' => $offset ,
'orderField' => 'dateCreated' ,
'orderType' => $orderType ,
'orderCast' => 'int' ,
'search' => $search ,
'filters' => [
'$collection=' . Database :: SYSTEM_COLLECTION_EXECUTIONS ,
'functionId=' . $function -> getId (),
],
]);
$response -> json ([ 'sum' => $projectDB -> getSum (), 'executions' => $results ]);
}, [ 'response' , 'projectDB' ]);
App :: get ( '/v1/functions/:functionId/executions/:executionId' )
-> groups ([ 'api' , 'functions' ])
2020-05-06 05:30:12 +12:00
-> desc ( 'Get Execution' )
-> label ( 'scope' , 'functions.read' )
-> label ( 'sdk.platform' , [ APP_PLATFORM_SERVER ])
-> label ( 'sdk.namespace' , 'functions' )
-> label ( 'sdk.method' , 'getExecution' )
-> label ( 'sdk.description' , '/docs/references/functions/get-execution.md' )
-> param ( 'functionId' , '' , function () { return new UID (); }, 'Function unique ID.' )
-> param ( 'executionId' , '' , function () { return new UID (); }, 'Execution unique ID.' )
2020-07-13 09:18:52 +12:00
-> action ( function ( $functionId , $executionId , $response , $projectDB ) {
$function = $projectDB -> getDocument ( $functionId );
2020-05-06 05:30:12 +12:00
2020-07-13 09:18:52 +12:00
if ( empty ( $function -> getId ()) || Database :: SYSTEM_COLLECTION_FUNCTIONS != $function -> getCollection ()) {
throw new Exception ( 'Function not found' , 404 );
}
2020-05-06 05:30:12 +12:00
2020-07-13 09:18:52 +12:00
$execution = $projectDB -> getDocument ( $executionId );
2020-05-06 05:30:12 +12:00
2020-07-13 09:18:52 +12:00
if ( $execution -> getAttribute ( 'functionId' ) !== $function -> getId ()) {
throw new Exception ( 'Execution not found' , 404 );
}
2020-05-06 05:30:12 +12:00
2020-07-13 09:18:52 +12:00
if ( empty ( $execution -> getId ()) || Database :: SYSTEM_COLLECTION_EXECUTIONS != $execution -> getCollection ()) {
throw new Exception ( 'Execution not found' , 404 );
2020-05-06 05:30:12 +12:00
}
2020-07-13 09:18:52 +12:00
$response -> json ( $execution -> getArrayCopy ());
}, [ 'response' , 'projectDB' ]);