Enabled code upload
This commit is contained in:
parent
d5b33e229e
commit
436300439d
|
@ -14,6 +14,8 @@ use Appwrite\Database\Database;
|
|||
use Appwrite\Database\Document;
|
||||
use Appwrite\Database\Validator\Authorization;
|
||||
use Appwrite\Network\Validator\Origin;
|
||||
use Appwrite\Storage\Device\Local;
|
||||
use Appwrite\Storage\Storage;
|
||||
|
||||
Config::setParam('domainVerification', false);
|
||||
Config::setParam('cookieDomain', 'localhost');
|
||||
|
@ -87,6 +89,8 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
|
|||
: '.'.$request->getHostname()
|
||||
);
|
||||
|
||||
Storage::setDevice('local', new Local(APP_STORAGE_UPLOADS.'/app-'.$project->getId()));
|
||||
|
||||
/*
|
||||
* Security Headers
|
||||
*
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
use Appwrite\Database\Database;
|
||||
use Appwrite\Database\Validator\UID;
|
||||
use Appwrite\Storage\Storage;
|
||||
use Appwrite\Storage\Validator\File;
|
||||
use Appwrite\Storage\Validator\FileSize;
|
||||
use Appwrite\Storage\Validator\FileType;
|
||||
use Appwrite\Storage\Validator\Upload;
|
||||
use Appwrite\Task\Validator\Cron;
|
||||
use Utopia\App;
|
||||
use Utopia\Response;
|
||||
|
@ -215,13 +220,50 @@ App::post('/v1/functions/:functionId/tags')
|
|||
->label('sdk.description', '/docs/references/functions/create-tag.md')
|
||||
->param('functionId', '', function () { return new UID(); }, 'Function unique ID.')
|
||||
->param('command', '', function () { return new Text('1028'); }, 'Code execution command.')
|
||||
->param('code', '', function () { return new Text(128); }, 'Code package. Use the '.APP_NAME.' code packager to create a deployable package file.')
|
||||
->action(function ($functionId, $command, $code, $response, $projectDB) {
|
||||
// ->param('code', '', function () { return new Text(128); }, 'Code package. Use the '.APP_NAME.' code packager to create a deployable package file.')
|
||||
->param('code', [], function () { return new File(); }, 'Gzip file containing your code.', false)
|
||||
->action(function ($functionId, $command, $code, $request, $response, $projectDB) {
|
||||
$function = $projectDB->getDocument($functionId);
|
||||
|
||||
if (empty($function->getId()) || Database::SYSTEM_COLLECTION_FUNCTIONS != $function->getCollection()) {
|
||||
throw new Exception('Function not found', 404);
|
||||
}
|
||||
|
||||
$file = $request->getFiles('code');
|
||||
$device = Storage::getDevice('local');
|
||||
$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?)
|
||||
if (!$fileType->isValid($file['tmp_name'])) {
|
||||
throw new Exception('File type not allowed', 400);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
$tag = $projectDB->createDocument([
|
||||
'$collection' => Database::SYSTEM_COLLECTION_TAGS,
|
||||
|
@ -232,7 +274,8 @@ App::post('/v1/functions/:functionId/tags')
|
|||
'dateCreated' => time(),
|
||||
'functionId' => $function->getId(),
|
||||
'command' => $command,
|
||||
'code' => $code,
|
||||
'codePath' => $path,
|
||||
'codeSize' => $size,
|
||||
]);
|
||||
|
||||
if (false === $tag) {
|
||||
|
@ -243,7 +286,7 @@ App::post('/v1/functions/:functionId/tags')
|
|||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->json($tag->getArrayCopy())
|
||||
;
|
||||
}, ['response', 'projectDB']);
|
||||
}, ['request', 'response', 'projectDB']);
|
||||
|
||||
App::get('/v1/functions/:functionId/tags')
|
||||
->groups(['api', 'functions'])
|
||||
|
|
|
@ -23,10 +23,6 @@ use Appwrite\Resize\Resize;
|
|||
use Appwrite\OpenSSL\OpenSSL;
|
||||
use Utopia\Config\Config;
|
||||
|
||||
App::init(function ($project) {
|
||||
Storage::setDevice('local', new Local(APP_STORAGE_UPLOADS.'/app-'.$project->getId()));
|
||||
}, ['project'], 'storage');
|
||||
|
||||
App::post('/v1/storage/files')
|
||||
->desc('Create File')
|
||||
->groups(['api', 'storage'])
|
||||
|
@ -38,7 +34,7 @@ App::post('/v1/storage/files')
|
|||
->label('sdk.description', '/docs/references/storage/create-file.md')
|
||||
->label('sdk.consumes', 'multipart/form-data')
|
||||
->label('sdk.methodType', 'upload')
|
||||
->param('file', [], function () { return new File(); }, 'Binary File.', false)
|
||||
->param('file', [], function () { return new File(); }, 'Binary file.', false)
|
||||
->param('read', [], function () { return new ArrayList(new Text(64)); }, 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||
->param('write', [], function () { return new ArrayList(new Text(64)); }, 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||
->action(function ($file, $read, $write, $request, $response, $user, $projectDB, $webhooks, $audits, $usage) {
|
||||
|
|
|
@ -6,7 +6,7 @@ sdk
|
|||
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
|
||||
;
|
||||
|
||||
let promise = sdk.functions.createTag('[FUNCTION_ID]', '[COMMAND]', '[CODE]');
|
||||
let promise = sdk.functions.createTag('[FUNCTION_ID]', '[COMMAND]', document.getElementById('uploader').files[0]);
|
||||
|
||||
promise.then(function (response) {
|
||||
console.log(response); // Success
|
||||
|
|
|
@ -2149,7 +2149,7 @@
|
|||
*
|
||||
* @param {string} functionId
|
||||
* @param {string} command
|
||||
* @param {string} code
|
||||
* @param {File} code
|
||||
* @throws {Error}
|
||||
* @return {Promise}
|
||||
*/
|
||||
|
@ -2180,7 +2180,7 @@
|
|||
|
||||
return http
|
||||
.post(path, {
|
||||
'content-type': 'application/json',
|
||||
'content-type': 'multipart/form-data',
|
||||
}, payload);
|
||||
},
|
||||
|
||||
|
|
2
app/sdks/console-web/src/sdk.min.js
vendored
2
app/sdks/console-web/src/sdk.min.js
vendored
|
@ -187,7 +187,7 @@ if(command===undefined){throw new Error('Missing required parameter: "command"')
|
|||
if(code===undefined){throw new Error('Missing required parameter: "code"')}
|
||||
let path='/functions/{functionId}/tags'.replace(new RegExp('{functionId}','g'),functionId);let payload={};if(command){payload.command=command}
|
||||
if(code){payload.code=code}
|
||||
return http.post(path,{'content-type':'application/json',},payload)},getTag:function(functionId,tagId){if(functionId===undefined){throw new Error('Missing required parameter: "functionId"')}
|
||||
return http.post(path,{'content-type':'multipart/form-data',},payload)},getTag:function(functionId,tagId){if(functionId===undefined){throw new Error('Missing required parameter: "functionId"')}
|
||||
if(tagId===undefined){throw new Error('Missing required parameter: "tagId"')}
|
||||
let path='/functions/{functionId}/tags/{tagId}'.replace(new RegExp('{functionId}','g'),functionId).replace(new RegExp('{tagId}','g'),tagId);let payload={};return http.get(path,{'content-type':'application/json',},payload)},deleteTag:function(functionId,tagId){if(functionId===undefined){throw new Error('Missing required parameter: "functionId"')}
|
||||
if(tagId===undefined){throw new Error('Missing required parameter: "tagId"')}
|
||||
|
|
4
app/sdks/console-web/types/index.d.ts
vendored
4
app/sdks/console-web/types/index.d.ts
vendored
|
@ -739,11 +739,11 @@ declare namespace Appwrite {
|
|||
*
|
||||
* @param {string} functionId
|
||||
* @param {string} command
|
||||
* @param {string} code
|
||||
* @param {File} code
|
||||
* @throws {Error}
|
||||
* @return {Promise}
|
||||
*/
|
||||
createTag(functionId: string, command: string, code: string): Promise<object>;
|
||||
createTag(functionId: string, command: string, code: File): Promise<object>;
|
||||
|
||||
/**
|
||||
* Get Tag
|
||||
|
|
|
@ -90,9 +90,32 @@ $events = array_keys($this->getParam('events', []));
|
|||
|
||||
<h1>Deploy a New Tag</h1>
|
||||
|
||||
<footer>
|
||||
<button type="submit">Create</button> <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
|
||||
</footer>
|
||||
<form
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Function Tag"
|
||||
data-service="functions.createTag"
|
||||
data-scope="sdk"
|
||||
data-event="submit"
|
||||
data-success="alert,trigger,reset"
|
||||
data-success-param-alert-text="Created function tag successfully"
|
||||
data-success-param-trigger-events="functions.createTag"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to create function tag"
|
||||
data-failure-param-alert-classname="error">
|
||||
|
||||
<input type="hidden" name="functionId" data-ls-bind="{{router.params.id}}" />
|
||||
|
||||
<label for="tag-command">Command</label>
|
||||
<input type="text" id="tag-command" name="command" required autocomplete="off" class="margin-bottom" placeholder="node main.js" />
|
||||
|
||||
<label for="tag-code">Gzipped Code</label>
|
||||
<input type="file" name="code" id="tag-code" size="1" required class="margin-bottom-xl">
|
||||
|
||||
<footer>
|
||||
<button type="submit">Create</button> <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
|
||||
</footer>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
2
public/dist/scripts/app-all.js
vendored
2
public/dist/scripts/app-all.js
vendored
|
@ -201,7 +201,7 @@ if(command===undefined){throw new Error('Missing required parameter: "command"')
|
|||
if(code===undefined){throw new Error('Missing required parameter: "code"');}
|
||||
let path='/functions/{functionId}/tags'.replace(new RegExp('{functionId}','g'),functionId);let payload={};if(command){payload['command']=command;}
|
||||
if(code){payload['code']=code;}
|
||||
return http.post(path,{'content-type':'application/json',},payload);},getTag:function(functionId,tagId){if(functionId===undefined){throw new Error('Missing required parameter: "functionId"');}
|
||||
return http.post(path,{'content-type':'multipart/form-data',},payload);},getTag:function(functionId,tagId){if(functionId===undefined){throw new Error('Missing required parameter: "functionId"');}
|
||||
if(tagId===undefined){throw new Error('Missing required parameter: "tagId"');}
|
||||
let path='/functions/{functionId}/tags/{tagId}'.replace(new RegExp('{functionId}','g'),functionId).replace(new RegExp('{tagId}','g'),tagId);let payload={};return http.get(path,{'content-type':'application/json',},payload);},deleteTag:function(functionId,tagId){if(functionId===undefined){throw new Error('Missing required parameter: "functionId"');}
|
||||
if(tagId===undefined){throw new Error('Missing required parameter: "tagId"');}
|
||||
|
|
2
public/dist/scripts/app-dep.js
vendored
2
public/dist/scripts/app-dep.js
vendored
|
@ -201,7 +201,7 @@ if(command===undefined){throw new Error('Missing required parameter: "command"')
|
|||
if(code===undefined){throw new Error('Missing required parameter: "code"');}
|
||||
let path='/functions/{functionId}/tags'.replace(new RegExp('{functionId}','g'),functionId);let payload={};if(command){payload['command']=command;}
|
||||
if(code){payload['code']=code;}
|
||||
return http.post(path,{'content-type':'application/json',},payload);},getTag:function(functionId,tagId){if(functionId===undefined){throw new Error('Missing required parameter: "functionId"');}
|
||||
return http.post(path,{'content-type':'multipart/form-data',},payload);},getTag:function(functionId,tagId){if(functionId===undefined){throw new Error('Missing required parameter: "functionId"');}
|
||||
if(tagId===undefined){throw new Error('Missing required parameter: "tagId"');}
|
||||
let path='/functions/{functionId}/tags/{tagId}'.replace(new RegExp('{functionId}','g'),functionId).replace(new RegExp('{tagId}','g'),tagId);let payload={};return http.get(path,{'content-type':'application/json',},payload);},deleteTag:function(functionId,tagId){if(functionId===undefined){throw new Error('Missing required parameter: "functionId"');}
|
||||
if(tagId===undefined){throw new Error('Missing required parameter: "tagId"');}
|
||||
|
|
|
@ -2149,7 +2149,7 @@
|
|||
*
|
||||
* @param {string} functionId
|
||||
* @param {string} command
|
||||
* @param {string} code
|
||||
* @param {File} code
|
||||
* @throws {Error}
|
||||
* @return {Promise}
|
||||
*/
|
||||
|
@ -2180,7 +2180,7 @@
|
|||
|
||||
return http
|
||||
.post(path, {
|
||||
'content-type': 'application/json',
|
||||
'content-type': 'multipart/form-data',
|
||||
}, payload);
|
||||
},
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ class FileType extends Validator
|
|||
const FILE_TYPE_JPEG = 'jpeg';
|
||||
const FILE_TYPE_GIF = 'gif';
|
||||
const FILE_TYPE_PNG = 'png';
|
||||
const FILE_TYPE_GZIP = 'gz';
|
||||
|
||||
/**
|
||||
* File Type Binaries.
|
||||
|
@ -23,6 +24,7 @@ class FileType extends Validator
|
|||
self::FILE_TYPE_JPEG => "\xFF\xD8\xFF",
|
||||
self::FILE_TYPE_GIF => 'GIF',
|
||||
self::FILE_TYPE_PNG => "\x89\x50\x4e\x47\x0d\x0a",
|
||||
self::FILE_TYPE_GZIP => "application/x-gzip",
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -76,6 +78,8 @@ class FileType extends Validator
|
|||
|
||||
$bytes = \fgets($handle, 8);
|
||||
|
||||
var_dump($bytes);
|
||||
|
||||
foreach ($this->whiteList as $key) {
|
||||
if (\strpos($bytes, $this->types[$key]) === 0) {
|
||||
\fclose($handle);
|
||||
|
|
Loading…
Reference in a new issue