Refactoring storage access

Added checks during installation phase
This commit is contained in:
Sergio Brighenti 2018-12-09 14:42:50 +01:00
parent 535fce4f8f
commit da437a203b
11 changed files with 75 additions and 57 deletions

View file

@ -32,15 +32,6 @@ abstract class Controller
return null;
}
/**
* Get a filesystem instance
* @return Filesystem
*/
protected function getStorage(): Filesystem
{
return new Filesystem(new Local($this->settings['storage_dir']));
}
/**
* @param $id
* @return int
@ -51,7 +42,7 @@ abstract class Controller
$totalSize = 0;
$filesystem = $this->getStorage();
$filesystem = storage();
foreach ($medias as $media) {
try {
$totalSize += $filesystem->getSize($media->storage_path);

View file

@ -49,7 +49,7 @@ class DashboardController extends Controller
$pages = $this->database->query('SELECT COUNT(*) AS `count` FROM `uploads` WHERE `user_id` = ?', Session::get('user_id'))->fetch()->count / self::PER_PAGE;
}
$filesystem = $this->getStorage();
$filesystem = storage();
foreach ($medias as $media) {
$extension = pathinfo($media->filename, PATHINFO_EXTENSION);
@ -91,7 +91,7 @@ class DashboardController extends Controller
$totalSize = 0;
$filesystem = $this->getStorage();
$filesystem = storage();
foreach ($medias as $media) {
$totalSize += $filesystem->getSize($media->storage_path);
}

View file

@ -55,7 +55,7 @@ class UploadController extends Controller
$fileInfo = pathinfo($file->getClientFilename());
$storagePath = "$user->user_code/$code.$fileInfo[extension]";
$this->getStorage()->writeStream($storagePath, $file->getStream()->detach());
storage()->writeStream($storagePath, $file->getStream()->detach());
$this->database->query('INSERT INTO `uploads`(`user_id`, `code`, `filename`, `storage_path`) VALUES (?, ?, ?, ?)', [
$user->id,
@ -88,12 +88,10 @@ class UploadController extends Controller
throw new NotFoundException($request, $response);
}
$filesystem = $this->getStorage();
if (isBot($request->getHeaderLine('User-Agent'))) {
return $this->streamMedia($request, $response, $filesystem, $media);
return $this->streamMedia($request, $response, storage(), $media);
} else {
$filesystem = storage();
try {
$media->mimetype = $filesystem->getMimetype($media->storage_path);
$media->size = humanFileSize($filesystem->getSize($media->storage_path));
@ -152,9 +150,8 @@ class UploadController extends Controller
if (Session::get('admin', false) || $user->id === $media->user_id) {
$filesystem = $this->getStorage();
try {
$filesystem->delete($media->storage_path);
storage()->delete($media->storage_path);
} catch (FileNotFoundException $e) {
throw new NotFoundException($request, $response);
} finally {
@ -185,7 +182,7 @@ class UploadController extends Controller
throw new NotFoundException($request, $response);
}
return $this->streamMedia($request, $response, $this->getStorage(), $media);
return $this->streamMedia($request, $response, storage(), $media);
}
/**
@ -203,7 +200,7 @@ class UploadController extends Controller
if (!$media || !$media->published && Session::get('user_id') !== $media->user_id && !Session::get('admin', false)) {
throw new NotFoundException($request, $response);
}
return $this->streamMedia($request, $response, $this->getStorage(), $media);
return $this->streamMedia($request, $response, storage(), $media);
}
@ -222,7 +219,7 @@ class UploadController extends Controller
if (!$media || !$media->published && Session::get('user_id') !== $media->user_id && !Session::get('admin', false)) {
throw new NotFoundException($request, $response);
}
return $this->streamMedia($request, $response, $this->getStorage(), $media, 'attachment');
return $this->streamMedia($request, $response, storage(), $media, 'attachment');
}
/**
@ -267,9 +264,8 @@ class UploadController extends Controller
if (Session::get('admin', false) || $media->user_id === Session::get('user_id')) {
$filesystem = $this->getStorage();
try {
$filesystem->delete($media->storage_path);
storage()->delete($media->storage_path);
} catch (FileNotFoundException $e) {
throw new NotFoundException($request, $response);
} finally {

View file

@ -90,7 +90,7 @@ class Session
*/
public static function alert($message, string $type = 'info'): void
{
$_SESSION['_flash'] = [$type => $message];
$_SESSION['_flash'][] = [$type => $message];
}

View file

@ -1,7 +1,24 @@
<?php
use League\Flysystem\Adapter\Local;
use League\Flysystem\Filesystem;
require __DIR__ . '/../vendor/autoload.php';
if (!function_exists('storage')) {
/**
* Get a filesystem instance given a path
* @param string $root
* @return Filesystem
*/
function storage($root = null): Filesystem
{
global $app;
$storagePath = $app->getContainer()->get('settings')['storage_dir'];
return new Filesystem(new Local($root !== null ? $root : $storagePath));
}
}
if (!function_exists('humanFileSize')) {
/**
* Generate a human readable file size
@ -61,7 +78,7 @@ if (!function_exists('redirect')) {
*/
function redirect(\Slim\Http\Response $response, string $path, $args = [], $status = null)
{
if ($path === '/' || substr($path, 0, 1) === '/') {
if ($path === '/' || $path === './' || substr($path, 0, 1) === '/') {
$url = urlFor($path);
} else {
$url = route($path, $args);

View file

@ -1,6 +1,6 @@
{
"name": "sergix44/xbackbone",
"version": "2.3",
"version": "2.3.1",
"description": "A lightweight ShareX PHP backend",
"type": "project",
"require": {

12
composer.lock generated
View file

@ -4,7 +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"
],
"content-hash": "b7bca0067b8963611274642752122ecb",
"content-hash": "265c1ca72d526b36b50fcec633b5807f",
"packages": [
{
"name": "container-interop/container-interop",
@ -39,16 +39,16 @@
},
{
"name": "guzzlehttp/psr7",
"version": "1.5.0",
"version": "1.5.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "53662d6688033a5eccde987bdd5a4a98ebe2d952"
"reference": "9f83dded91781a01c63574e387eaa769be769115"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/53662d6688033a5eccde987bdd5a4a98ebe2d952",
"reference": "53662d6688033a5eccde987bdd5a4a98ebe2d952",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115",
"reference": "9f83dded91781a01c63574e387eaa769be769115",
"shasum": ""
},
"require": {
@ -102,7 +102,7 @@
"uri",
"url"
],
"time": "2018-12-03T05:07:51+00:00"
"time": "2018-12-04T20:46:45+00:00"
},
{
"name": "intervention/image",

View file

@ -113,6 +113,18 @@ $app = new App($container);
$app->get('/', function (Request $request, Response $response) {
if (!is_writable(__DIR__ . '/../resources/cache')) {
Session::alert('The cache folder is not writable (' . __DIR__ . '/../resources/cache' . ')', 'danger');
}
if (!is_writable(__DIR__ . '/../resources/database')) {
Session::alert('The database folder is not writable (' . __DIR__ . '/../resources/database' . ')', 'danger');
}
if (!is_writable(__DIR__ . '/../resources/sessions')) {
Session::alert('The sessions folder is not writable (' . __DIR__ . '/../resources/sessions' . ')', 'danger');
}
$installed = file_exists(__DIR__ . '/../config.php');
return $this->view->render($response, 'install.twig', ['installed' => $installed]);
@ -131,15 +143,22 @@ $app->post('/', function (Request $request, Response $response) use (&$config) {
$config['db']['username'] = $request->getParam('db_user');
$config['db']['password'] = $request->getParam('db_password');
if (!is_writable($config['storage_dir'])) {
Session::alert('The storage folder is not writable (' . $config['storage_dir'] . ')', 'danger');
return redirect($response, '.');
try {
storage($config['storage_dir']);
} catch (LogicException $exception) {
Session::alert('The storage folder is not readable (' . $config['storage_dir'] . ')', 'danger');
return redirect($response, './');
} finally {
if (!is_writable($config['storage_dir'])) {
Session::alert('The storage folder is not writable (' . $config['storage_dir'] . ')', 'danger');
return redirect($response, './');
}
}
$ret = file_put_contents(__DIR__ . '/../config.php', '<?php' . PHP_EOL . 'return ' . var_export($config, true) . ';');
if ($ret === false) {
Session::alert('The config folder is not writable (' . __DIR__ . '/../config.php' . ')', 'danger');
return redirect($response, '.');
return redirect($response, './');
}
}
@ -151,7 +170,7 @@ $app->post('/', function (Request $request, Response $response) use (&$config) {
migrate($config);
} catch (PDOException $exception) {
Session::alert("Cannot connect to the database: {$exception->getMessage()} [{$exception->getCode()}]", 'danger');
return redirect($response, '.');
return redirect($response, './');
}
if (!$installed) {

View file

@ -19,14 +19,7 @@
</head>
<body>
<div class="container">
{% for type, message in alerts %}
<div class="alert alert-{{ type }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endfor %}
{% include 'comp/alert.twig' %}
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card mt-3">

View file

@ -12,11 +12,11 @@
"devDependencies": {
"grunt": "^1.0",
"grunt-contrib-copy": "^1.0.0",
"grunt-contrib-cssmin": "^2.2.1",
"grunt-contrib-jshint": "^1.1.0",
"grunt-contrib-uglify": "^3.3.0",
"grunt-contrib-cssmin": "^3.0.0",
"grunt-contrib-jshint": "^2.0.0",
"grunt-contrib-uglify": "^4.0.0",
"grunt-contrib-watch": "^1.1.0",
"grunt-zip": "^0.17.1",
"grunt-zip": "^0.18.1",
"load-grunt-tasks": "^4.0.0"
}
}

View file

@ -1,8 +1,10 @@
{% for type, message in alerts %}
<div class="alert alert-{{ type }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% for alert in alerts %}
{% for type, message in alert %}
<div class="alert alert-{{ type }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endfor %}
{% endfor %}