Slim app upload stable

parent c498b7e7
This diff is collapsed.
...@@ -37,7 +37,9 @@ $autoloader->addPsr4('Gr\Gov\Minedu\Osteam\Slim\\', __DIR__ . '/../src/osteam'); ...@@ -37,7 +37,9 @@ $autoloader->addPsr4('Gr\Gov\Minedu\Osteam\Slim\\', __DIR__ . '/../src/osteam');
$container['errorHandler'] = function ($c) { $container['errorHandler'] = function ($c) {
return function ($request, $response, $exception) use ($c) { return function ($request, $response, $exception) use ($c) {
return $c['response']->withJson([ return $c['response']->withJson([
'message' => 'Προέκυψε λάθος', 'success' => false,
'timestamp' => date('c'),
'message' => 'An error occured',
'in' => $exception->getMessage() 'in' => $exception->getMessage()
], intval($code = $exception->getCode()) > 0 ? $code : null ], intval($code = $exception->getCode()) > 0 ? $code : null
); );
......
...@@ -8,5 +8,9 @@ $password = isset($settings['app']['secure_endpoint_password']) ? $settings['app ...@@ -8,5 +8,9 @@ $password = isset($settings['app']['secure_endpoint_password']) ? $settings['app
// e.g: $app->add(new \Slim\Csrf\Guard); // e.g: $app->add(new \Slim\Csrf\Guard);
$app->getContainer()->get('router') $app->getContainer()->get('router')
->getNamedRoute('validate') ->getNamedRoute('validate.base64')
->add(new Gr\Gov\Minedu\Osteam\Slim\AuthorizationGuard($username, $password));
$app->getContainer()->get('router')
->getNamedRoute('validate.binary')
->add(new Gr\Gov\Minedu\Osteam\Slim\AuthorizationGuard($username, $password)); ->add(new Gr\Gov\Minedu\Osteam\Slim\AuthorizationGuard($username, $password));
...@@ -7,16 +7,17 @@ use Slim\Http\Body; ...@@ -7,16 +7,17 @@ use Slim\Http\Body;
use Gr\Gov\Minedu\Osteam\Slim\Client; use Gr\Gov\Minedu\Osteam\Slim\Client;
/** /**
* Description of app * Description of app
* *
* @author spapad * @author spapad
*/ */
class App class App
{ {
protected $ci = null; protected $ci = null;
protected $logger = null; protected $logger = null;
protected $savePath; protected $savePath;
protected $saveFileTTL;
public function __construct(ContainerInterface $ci) public function __construct(ContainerInterface $ci)
{ {
...@@ -27,34 +28,88 @@ class App ...@@ -27,34 +28,88 @@ class App
$settings = $this->ci->get('settings'); $settings = $this->ci->get('settings');
if (isset($settings['app'])) { if (isset($settings['app'])) {
$this->savePath = (isset($settings['app']['save_path']) ? $settings['app']['save_path'] : 'tmp'); $this->savePath = (isset($settings['app']['save_path']) ? $settings['app']['save_path'] : 'tmp');
$this->saveFileTTL = (isset($settings['app']['save_file_ttl']) ? $settings['app']['save_file_ttl'] : 0);
} }
} }
/** /**
* Χαιρετισμός - οδηγίες. * Χαιρετισμός - οδηγίες.
* *
* @param Psr\Http\Message\ServerRequestInterface $req * @param Psr\Http\Message\ServerRequestInterface $req
* @param Psr\Http\Message\ResponseInterface $res * @param Psr\Http\Message\ResponseInterface $res
* @param $args * @param $args
* @throws \Exception * @throws \Exception
* @return Response * @return Response
*/ */
public function greet($req, $res, $args) public function greet($req, $res, $args)
{ {
return $res->withJson([ return $res->withJson(array_merge($this->coreResponseData(false), [
'message' => 'Only POST is available' 'message' => 'Only POST is available'
], 401); ]), 405);
} }
/** /**
* Έλεγχος. * Έλεγχος.
* *
* @param Psr\Http\Message\ServerRequestInterface $req * @param Psr\Http\Message\ServerRequestInterface $req
* @param Psr\Http\Message\ResponseInterface $res * @param Psr\Http\Message\ResponseInterface $res
* @throws \Exception * @param array $args
* @return Response * @throws \Exception
*/ * @return Response
public function validate($req, $res, $args) */
public function validateBinary($req, $res, $args)
{
$files = $req->getUploadedFiles();
if (count($files) == 0) {
return $res->withJson(array_merge($this->coreResponseData(false), [
'message' => 'File is mandatory'
]), 400);
}
if (!$this->checkSavePath($this->savePath)) {
return $res->withJson(array_merge($this->coreResponseData(false), [
'message' => 'File location does not exist or is not writeable'
]), 501);
}
foreach ($files as $id => $file) {
if ($file->getError() === UPLOAD_ERR_OK) {
// $contents = base64_encode($file->getStream()->getContents());
$filename = $file->getClientFilename();
$store_filename = $this->savePath . DIRECTORY_SEPARATOR . uniqid() . '_' .
$this->sanitizeFilename($filename);
try {
$file->moveTo($store_filename);
} catch (\Exception $e) {
$this->vaccuumSavePath();
return $res->withJson(array_merge($this->coreResponseData(false), [
'message' => 'Cannot save file for processing'
]), 501);
}
$this->logger->info("validate binary upload::{$store_filename}");
}
}
$this->vaccuumSavePath();
return $res->withJson(array_merge($this->coreResponseData(true), [
'message' => array_reduce($files, function ($c, $v) {
return $c . $v->getClientFilename() . ", ";
}, '') . "processed"
]), 200);
}
/**
* Έλεγχος.
*
* @param Psr\Http\Message\ServerRequestInterface $req
* @param Psr\Http\Message\ResponseInterface $res
* @param array $args
* @throws \Exception
* @return Response
*/
public function validateBase64($req, $res, $args)
{ {
// $body = $req->getBody(); // $body = $req->getBody();
// $contents = $body->getContents(); // $contents = $body->getContents();
...@@ -62,40 +117,94 @@ class App ...@@ -62,40 +117,94 @@ class App
$filename = $req->getParsedBodyParam('filename', null); $filename = $req->getParsedBodyParam('filename', null);
$content = $req->getParsedBodyParam('base64content', null); $content = $req->getParsedBodyParam('base64content', null);
if ($filename === null || $content === null) { if ($filename === null || $content === null) {
return $res->withJson(['message' => 'Filename and file content is mandatory'], 401); return $res->withJson(array_merge($this->coreResponseData(false), [
'message' => 'Filename and file content is mandatory'
]), 400);
} }
if (($filecontent = base64_decode($content)) === false) { if (($filecontent = base64_decode($content)) === false) {
return $res->withJson(['message' => 'File content is not valid base64 encoded'], 401); return $res->withJson(array_merge($this->coreResponseData(false), [
'message' => 'File content is not valid base64 encoded'
]), 400);
} }
if (!is_dir($this->savePath) || !is_writable($this->savePath)) { if (!$this->checkSavePath($this->savePath)) {
return $res->withJson(['message' => 'File location does not exist or is not writeable'], 401); return $res->withJson(array_merge($this->coreResponseData(false), [
'message' => 'File location does not exist or is not writeable'
]), 501);
} }
// TODO check filename // manipulate filename
$store_filename = $this->savePath . DIRECTORY_SEPARATOR . $filename; $store_filename = $this->savePath . DIRECTORY_SEPARATOR . uniqid() . '_' .
$this->sanitizeFilename($filename);
if (($save = file_put_contents($store_filename, $filecontent)) === false) { if (($save = file_put_contents($store_filename, $filecontent)) === false) {
return $res->withJson(['message' => 'Cannot save file for processing'], 401); return $res->withJson(array_merge($this->coreResponseData(false), [
'message' => 'Cannot save file for processing'
]), 501);
} }
$this->logger->info("validate::{$store_filename}"); $this->logger->info("validate base64 upload::{$store_filename}");
// delete any leftover files
// delete file immediately after work; OBSOLETE
// if ($this->saveFileTTL === 0) { @unlink($store_filename); }
$this->vaccuumSavePath();
return $res->withJson([ return $res->withJson(array_merge($this->coreResponseData(true), [
'ok' => 'done', 'message' => "{$filename} processed"// $store_filename,
'file' => $store_filename, ]), 200);
// 'parsedBody' => $parsedBody,
// 'content' => $contents,
], 200);
} }
/**
* Clean save path.
* Delete all files older than saveFileTTL seconds
*/
private function vaccuumSavePath()
{
$files = glob($this->savePath . DIRECTORY_SEPARATOR . '*');
$files = is_array($files) ? $files : [];
$now = time();
$rmv = array_walk($files, function ($v, $k) use ($now) {
if ($now - fileatime($v) > $this->saveFileTTL) {
@unlink($v);
}
});
}
/**
* Check if path exists and is writeable
*/
private function checkSavePath($save_path)
{
return (is_dir($save_path) && is_writable($save_path));
}
/**
* Manipulate the filename provided to strip out unsafe characters
*
* @param string $filename
* @return string
*/
private function sanitizeFilename($filename)
{
return mb_ereg_replace("([^\w\s\d\-_,.])", '_', $filename);
}
public function setDebug($debug = true) public function setDebug($debug = true)
{ {
$this->client->setDebug($debug === true); $this->client->setDebug($debug === true);
return; return;
} }
private function coreResponseData($success)
{
return [
'success' => $success === true,
'timestamp' => date('c')
];
}
/** /**
* Send a JSON formatted string as JSON response to the client. * Send a JSON formatted string as JSON response to the client.
* *
......
...@@ -2,8 +2,10 @@ ...@@ -2,8 +2,10 @@
$app->get('/validate', '\Gr\Gov\Minedu\Osteam\Slim\App:greet'); $app->get('/validate', '\Gr\Gov\Minedu\Osteam\Slim\App:greet');
$app->post('/validate', '\Gr\Gov\Minedu\Osteam\Slim\App:validate') $app->post('/validateBase64', '\Gr\Gov\Minedu\Osteam\Slim\App:validateBase64')
->setName('validate'); ->setName('validate.base64');
$app->post('/validateBinary', '\Gr\Gov\Minedu\Osteam\Slim\App:validateBinary')
->setName('validate.binary');
$app->any('/[{anythingelse}]', function ($request, $response, $args) { $app->any('/[{anythingelse}]', function ($request, $response, $args) {
$this->logger->info("Void response, no action route was enabled"); $this->logger->info("Void response, no action route was enabled");
......
...@@ -17,7 +17,8 @@ return [ ...@@ -17,7 +17,8 @@ return [
// //
// app custom settings // app custom settings
'app' => [ 'app' => [
'save_path' => __DIR__ . '/../logs', 'save_path' => __DIR__ . '/../files', // upload file location
'save_file_ttl' => 0, // if 0 delete file after doing work; if Nr delete some time after Nr seconds
'secure_endpoint_username' => 'username-for-this-wrapper', 'secure_endpoint_username' => 'username-for-this-wrapper',
'secure_endpoint_password' => 'password-for-this-wrapper' 'secure_endpoint_password' => 'password-for-this-wrapper'
] ]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment