Start adding support to use AWS S3, Google Cloud Storage, Dropbox and FTP(s) accounts as storage location

This commit is contained in:
Sergio Brighenti 2019-05-19 15:39:42 +02:00
parent 635cffeb20
commit f6a6be7312
11 changed files with 953 additions and 55 deletions

View file

@ -1,3 +1,7 @@
## v2.6
+ Added support to use AWS S3, Google Cloud Storage, Dropbox and FTP(s) accounts as storage location.
+ Fixed missing icon.
## v2.5.3
+ Fixed bad css loading on Firefox (#35).
+ Fixed wrong style for publish/unpublish button.

View file

@ -26,7 +26,7 @@ class AdminController extends Controller
$totalSize = 0;
$filesystem = storage();
$filesystem = $this->storage;
foreach ($medias as $media) {
$totalSize += $filesystem->getSize($media->storage_path);
}
@ -50,7 +50,7 @@ class AdminController extends Controller
{
$orphans = $this->database->query('SELECT * FROM `uploads` WHERE `user_id` IS NULL')->fetchAll();
$filesystem = storage();
$filesystem = $this->storage;
$deleted = 0;
foreach ($orphans as $orphan) {

View file

@ -5,6 +5,7 @@ namespace App\Controllers;
use App\Database\DB;
use App\Web\Session;
use League\Flysystem\FileNotFoundException;
use League\Flysystem\Filesystem;
use Monolog\Logger;
use Slim\Container;
@ -13,6 +14,7 @@ use Slim\Container;
* @property mixed|null view
* @property DB|null database
* @property Logger|null logger
* @property Filesystem|null storage
*/
abstract class Controller
{
@ -48,7 +50,7 @@ abstract class Controller
$totalSize = 0;
$filesystem = storage();
$filesystem = $this->storage;
foreach ($medias as $media) {
try {
$totalSize += $filesystem->getSize($media->storage_path);

View file

@ -34,7 +34,7 @@ class DashboardController extends Controller
$page = isset($args['page']) ? (int)$args['page'] : 0;
$page = max(0, --$page);
$query = new MediaQuery($this->database, $this->session->get('admin', false));
$query = new MediaQuery($this->database, $this->session->get('admin', false), $this->storage);
switch ($request->getParam('sort', 'time')) {
case 'size':

View file

@ -71,7 +71,7 @@ class UploadController extends Controller
$fileInfo = pathinfo($file->getClientFilename());
$storagePath = "$user->user_code/$code.$fileInfo[extension]";
storage()->writeStream($storagePath, $file->getStream()->detach());
$this->storage->writeStream($storagePath, $file->getStream()->detach());
$this->database->query('INSERT INTO `uploads`(`user_id`, `code`, `filename`, `storage_path`) VALUES (?, ?, ?, ?)', [
$user->id,
@ -104,7 +104,7 @@ class UploadController extends Controller
throw new NotFoundException($request, $response);
}
$filesystem = storage();
$filesystem = $this->storage;
if (isBot($request->getHeaderLine('User-Agent'))) {
return $this->streamMedia($request, $response, $filesystem, $media);
@ -168,7 +168,7 @@ class UploadController extends Controller
if ($this->session->get('admin', false) || $user->id === $media->user_id) {
try {
storage()->delete($media->storage_path);
$this->storage->delete($media->storage_path);
} catch (FileNotFoundException $e) {
throw new NotFoundException($request, $response);
} finally {
@ -199,7 +199,7 @@ class UploadController extends Controller
throw new NotFoundException($request, $response);
}
return $this->streamMedia($request, $response, storage(), $media);
return $this->streamMedia($request, $response, $this->storage, $media);
}
/**
@ -217,7 +217,7 @@ class UploadController extends Controller
if (!$media || !$media->published && $this->session->get('user_id') !== $media->user_id && !$this->session->get('admin', false)) {
throw new NotFoundException($request, $response);
}
return $this->streamMedia($request, $response, storage(), $media);
return $this->streamMedia($request, $response, $this->storage, $media);
}
@ -236,7 +236,7 @@ class UploadController extends Controller
if (!$media || !$media->published && $this->session->get('user_id') !== $media->user_id && !$this->session->get('admin', false)) {
throw new NotFoundException($request, $response);
}
return $this->streamMedia($request, $response, storage(), $media, 'attachment');
return $this->streamMedia($request, $response, $this->storage, $media, 'attachment');
}
/**
@ -282,7 +282,7 @@ class UploadController extends Controller
if ($this->session->get('admin', false) || $media->user_id === $this->session->get('user_id')) {
try {
storage()->delete($media->storage_path);
$this->storage->delete($media->storage_path);
} catch (FileNotFoundException $e) {
throw new NotFoundException($request, $response);
} finally {

View file

@ -5,6 +5,7 @@ namespace App\Database\Queries;
use App\Database\DB;
use League\Flysystem\FileNotFoundException;
use League\Flysystem\Filesystem;
use League\Flysystem\Plugin\ListFiles;
class MediaQuery
@ -34,6 +35,9 @@ class MediaQuery
/** @var string */
protected $text;
/** @var Filesystem */
protected $storage;
private $pages;
private $media;
@ -41,11 +45,13 @@ class MediaQuery
* MediaQuery constructor.
* @param DB $db
* @param bool $isAdmin
* @param Filesystem $storage
*/
public function __construct(DB $db, bool $isAdmin)
public function __construct(DB $db, bool $isAdmin, Filesystem $storage)
{
$this->db = $db;
$this->isAdmin = $isAdmin;
$this->storage = $storage;
}
/**
@ -128,12 +134,10 @@ class MediaQuery
$this->pages = $this->db->query($queryPages, array_merge([$this->userId], $params))->fetch()->count / self::PER_PAGE;
}
$filesystem = storage();
foreach ($this->media as $media) {
try {
$media->size = humanFileSize($filesystem->getSize($media->storage_path));
$media->mimetype = $filesystem->getMimetype($media->storage_path);
$media->size = humanFileSize($this->storage->getSize($media->storage_path));
$media->mimetype = $this->storage->getMimetype($media->storage_path);
} catch (FileNotFoundException $e) {
$media->size = null;
$media->mimetype = null;
@ -148,17 +152,17 @@ class MediaQuery
*/
private function runWithOrderBySize(int $page)
{
$filesystem = storage()->addPlugin(new ListFiles());
$this->storage->addPlugin(new ListFiles());
if ($this->isAdmin) {
$files = $filesystem->listFiles('/', true);
$files = $this->storage->listFiles('/', true);
$this->pages = count($files) / self::PER_PAGE_ADMIN;
$offset = $page * self::PER_PAGE_ADMIN;
$limit = self::PER_PAGE_ADMIN;
} else {
$userCode = $this->db->query('SELECT `user_code` FROM `users` WHERE `id` = ?', [$this->userId])->fetch()->user_code;
$files = $filesystem->listFiles($userCode);
$files = $this->storage->listFiles($userCode);
$this->pages = count($files) / self::PER_PAGE;
$offset = $page * self::PER_PAGE;
@ -195,7 +199,7 @@ class MediaQuery
}
$media->size = humanFileSize($file['size']);
try {
$media->mimetype = $filesystem->getMimetype($file['path']);
$media->mimetype = $this->storage->getMimetype($file['path']);
} catch (FileNotFoundException $e) {
$media->mimetype = null;
}

View file

@ -5,20 +5,6 @@ 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
@ -224,13 +210,13 @@ if (!function_exists('mime2font')) {
return $class;
}
}
return 'fa-file-download';
return 'fa-file';
}
}
if (!function_exists('dd')) {
/**
* Dumps all the giver vars and halt the execution.
* Dumps all the given vars and halt the execution.
*/
function dd()
{

View file

@ -5,6 +5,12 @@ use App\Exceptions\MaintenanceException;
use App\Exceptions\UnauthorizedException;
use App\Web\Lang;
use App\Web\Session;
use Aws\S3\S3Client;
use Google\Cloud\Storage\StorageClient;
use League\Flysystem\Adapter\Ftp as FtpAdapter;
use League\Flysystem\Adapter\Local;
use League\Flysystem\AwsS3v3\AwsS3Adapter;
use League\Flysystem\Filesystem;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Logger;
@ -15,6 +21,9 @@ use Slim\Http\Request;
use Slim\Http\Response;
use Slim\Http\Uri;
use Slim\Views\Twig;
use Spatie\Dropbox\Client as DropboxClient;
use Spatie\FlysystemDropbox\DropboxAdapter;
use Superbalist\Flysystem\GoogleStorage\GoogleStorageAdapter;
use Twig\TwigFunction;
if (!file_exists('config.php') && is_dir('install/')) {
@ -28,7 +37,6 @@ if (!file_exists('config.php') && is_dir('install/')) {
$config = array_replace_recursive([
'app_name' => 'XBackBone',
'base_url' => isset($_SERVER['HTTPS']) ? 'https://' . $_SERVER['HTTP_HOST'] : 'http://' . $_SERVER['HTTP_HOST'],
'storage_dir' => 'storage',
'displayErrorDetails' => false,
'maintenance' => false,
'db' => [
@ -37,6 +45,9 @@ $config = array_replace_recursive([
'username' => null,
'password' => null,
],
'storage' => [
'driver' => 'local',
],
], require BASE_DIR . 'config.php');
if (!$config['displayErrorDetails']) {
@ -73,6 +84,47 @@ $container['database'] = function ($container) use (&$config) {
return new DB($config['db']['connection'] . ':' . $dsn, $config['db']['username'], $config['db']['password']);
};
$container['storage'] = function ($container) use (&$config) {
switch ($config['storage']['driver']) {
case 'local':
return new Filesystem(new Local($config['storage']['path']));
case 's3':
$client = new S3Client([
'credentials' => [
'key' => $config['storage']['key'],
'secret' => $config['storage']['secret'],
],
'region' => $config['storage']['region'],
'version' => 'latest',
]);
return new Filesystem(new AwsS3Adapter($client, $config['storage']['bucket'], $config['storage']['path']));
case 'dropbox':
$client = new DropboxClient($config['storage']['token']);
return new Filesystem(new DropboxAdapter($client), ['case_sensitive' => false]);
case 'ftp':
return new Filesystem(new FtpAdapter([
'host' => $config['storage']['host'],
'username' => $config['storage']['username'],
'password' => $config['storage']['password'],
'port' => $config['storage']['port'],
'root' => $config['storage']['path'],
'passive' => $config['storage']['passive'],
'ssl' => $config['storage']['ssl'],
'timeout' => 30,
]));
case 'google-cloud':
$client = new StorageClient([
'projectId' => $config['storage']['project_id'],
'keyFilePath' => $config['storage']['key_path'],
]);
return new Filesystem(new GoogleStorageAdapter($client, $client->bucket($config['storage']['bucket'])));
default:
throw new InvalidArgumentException('The driver specified is not supported.');
}
};
$container['lang'] = function ($container) {
return Lang::build(Lang::recognize(), BASE_DIR . 'resources/lang/');
};

View file

@ -1,6 +1,6 @@
{
"name": "sergix44/xbackbone",
"version": "2.5.3",
"version": "2.6",
"description": "A lightweight ShareX PHP backend",
"type": "project",
"require": {
@ -13,7 +13,10 @@
"ext-json": "*",
"ext-gd": "*",
"ext-pdo": "*",
"ext-zip": "*"
"ext-zip": "*",
"league/flysystem-aws-s3-v3": "^1.0",
"spatie/flysystem-dropbox": "^1.0",
"superbalist/flysystem-google-storage": "^7.2"
},
"autoload": {
"files": [

757
composer.lock generated
View file

@ -1,11 +1,94 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"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": "120224d788960ba61ae3d0e49e173ad3",
"content-hash": "d2c8e7bde7729d78cef484491535c639",
"packages": [
{
"name": "aws/aws-sdk-php",
"version": "3.93.12",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
"reference": "60f5c4bd261e19844d4263c3a8f370e88e038282"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/60f5c4bd261e19844d4263c3a8f370e88e038282",
"reference": "60f5c4bd261e19844d4263c3a8f370e88e038282",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-pcre": "*",
"ext-simplexml": "*",
"guzzlehttp/guzzle": "^5.3.3|^6.2.1",
"guzzlehttp/promises": "~1.0",
"guzzlehttp/psr7": "^1.4.1",
"mtdowling/jmespath.php": "~2.2",
"php": ">=5.5"
},
"require-dev": {
"andrewsville/php-token-reflection": "^1.4",
"aws/aws-php-sns-message-validator": "~1.0",
"behat/behat": "~3.0",
"doctrine/cache": "~1.4",
"ext-dom": "*",
"ext-openssl": "*",
"ext-pcntl": "*",
"ext-sockets": "*",
"nette/neon": "^2.3",
"phpunit/phpunit": "^4.8.35|^5.4.3",
"psr/cache": "^1.0",
"psr/simple-cache": "^1.0"
},
"suggest": {
"aws/aws-php-sns-message-validator": "To validate incoming SNS notifications",
"doctrine/cache": "To use the DoctrineCacheAdapter",
"ext-curl": "To send requests using cURL",
"ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages",
"ext-sockets": "To use client-side monitoring"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"psr-4": {
"Aws\\": "src/"
},
"files": [
"src/functions.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Amazon Web Services",
"homepage": "http://aws.amazon.com"
}
],
"description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project",
"homepage": "http://aws.amazon.com/sdkforphp",
"keywords": [
"amazon",
"aws",
"cloud",
"dynamodb",
"ec2",
"glacier",
"s3",
"sdk"
],
"time": "2019-05-17T18:26:46+00:00"
},
{
"name": "container-interop/container-interop",
"version": "1.2.0",
@ -37,6 +120,329 @@
"homepage": "https://github.com/container-interop/container-interop",
"time": "2017-02-14T19:40:03+00:00"
},
{
"name": "firebase/php-jwt",
"version": "v5.0.0",
"source": {
"type": "git",
"url": "https://github.com/firebase/php-jwt.git",
"reference": "9984a4d3a32ae7673d6971ea00bae9d0a1abba0e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/9984a4d3a32ae7673d6971ea00bae9d0a1abba0e",
"reference": "9984a4d3a32ae7673d6971ea00bae9d0a1abba0e",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": " 4.8.35"
},
"type": "library",
"autoload": {
"psr-4": {
"Firebase\\JWT\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Neuman Vong",
"email": "neuman+pear@twilio.com",
"role": "Developer"
},
{
"name": "Anant Narayanan",
"email": "anant@php.net",
"role": "Developer"
}
],
"description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
"homepage": "https://github.com/firebase/php-jwt",
"time": "2017-06-27T22:17:23+00:00"
},
{
"name": "google/auth",
"version": "v1.5.1",
"source": {
"type": "git",
"url": "https://github.com/googleapis/google-auth-library-php.git",
"reference": "0f75e20e7392e863f5550ed2c2d3d50af21710fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/0f75e20e7392e863f5550ed2c2d3d50af21710fb",
"reference": "0f75e20e7392e863f5550ed2c2d3d50af21710fb",
"shasum": ""
},
"require": {
"firebase/php-jwt": "~2.0|~3.0|~4.0|~5.0",
"guzzlehttp/guzzle": "~5.3.1|~6.0",
"guzzlehttp/psr7": "^1.2",
"php": ">=5.4",
"psr/cache": "^1.0",
"psr/http-message": "^1.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^1.11",
"guzzlehttp/promises": "0.1.1|^1.3",
"phpseclib/phpseclib": "^2",
"phpunit/phpunit": "^4.8.36|^5.7",
"sebastian/comparator": ">=1.2.3"
},
"suggest": {
"phpseclib/phpseclib": "May be used in place of OpenSSL for signing strings. Please require version ^2."
},
"type": "library",
"autoload": {
"psr-4": {
"Google\\Auth\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"description": "Google Auth Library for PHP",
"homepage": "http://github.com/google/google-auth-library-php",
"keywords": [
"Authentication",
"google",
"oauth2"
],
"time": "2019-04-16T18:48:28+00:00"
},
{
"name": "google/cloud-core",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/googleapis/google-cloud-php-core.git",
"reference": "d32db261499d28268f9ed97834e7aca829df5b53"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/googleapis/google-cloud-php-core/zipball/d32db261499d28268f9ed97834e7aca829df5b53",
"reference": "d32db261499d28268f9ed97834e7aca829df5b53",
"shasum": ""
},
"require": {
"google/auth": "^1.5.1",
"guzzlehttp/guzzle": "^5.3|^6.0",
"guzzlehttp/promises": "^1.3",
"guzzlehttp/psr7": "^1.2",
"monolog/monolog": "~1",
"php": ">=5.5",
"psr/http-message": "1.0.*",
"rize/uri-template": "~0.3"
},
"require-dev": {
"erusev/parsedown": "^1.6",
"google/gax": "^1.0",
"opis/closure": "^3",
"phpdocumentor/reflection": "^3.0",
"phpunit/phpunit": "^4.8|^5.0",
"squizlabs/php_codesniffer": "2.*"
},
"suggest": {
"opis/closure": "May be used to serialize closures to process jobs in the batch daemon. Please require version ^3.",
"symfony/lock": "Required for the Spanner cached based session pool. Please require the following commit: 3.3.x-dev#1ba6ac9"
},
"bin": [
"bin/google-cloud-batch"
],
"type": "library",
"extra": {
"component": {
"id": "cloud-core",
"target": "googleapis/google-cloud-php-core.git",
"path": "Core",
"entry": "src/ServiceBuilder.php"
}
},
"autoload": {
"psr-4": {
"Google\\Cloud\\Core\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"description": "Google Cloud PHP shared dependency, providing functionality useful to all components.",
"time": "2019-04-16T20:44:33+00:00"
},
{
"name": "google/cloud-storage",
"version": "v1.12.1",
"source": {
"type": "git",
"url": "https://github.com/googleapis/google-cloud-php-storage.git",
"reference": "a252e2012ea875e873b6d146159e54edb8fa4544"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/googleapis/google-cloud-php-storage/zipball/a252e2012ea875e873b6d146159e54edb8fa4544",
"reference": "a252e2012ea875e873b6d146159e54edb8fa4544",
"shasum": ""
},
"require": {
"google/cloud-core": "^1.28"
},
"require-dev": {
"erusev/parsedown": "^1.6",
"google/cloud-pubsub": "^1.0",
"phpdocumentor/reflection": "^3.0",
"phpseclib/phpseclib": "^2",
"phpunit/phpunit": "^4.8|^5.0",
"squizlabs/php_codesniffer": "2.*"
},
"suggest": {
"google/cloud-pubsub": "May be used to register a topic to receive bucket notifications.",
"phpseclib/phpseclib": "May be used in place of OpenSSL for creating signed Cloud Storage URLs. Please require version ^2."
},
"type": "library",
"extra": {
"component": {
"id": "cloud-storage",
"target": "googleapis/google-cloud-php-storage.git",
"path": "Storage",
"entry": "src/StorageClient.php"
}
},
"autoload": {
"psr-4": {
"Google\\Cloud\\Storage\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"description": "Cloud Storage Client for PHP",
"time": "2019-05-02T16:40:15+00:00"
},
{
"name": "guzzlehttp/guzzle",
"version": "6.3.3",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba",
"reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba",
"shasum": ""
},
"require": {
"guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.4",
"php": ">=5.5"
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
"psr/log": "^1.0"
},
"suggest": {
"psr/log": "Required for using the Log middleware"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.3-dev"
}
},
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle is a PHP HTTP client library",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"rest",
"web service"
],
"time": "2018-04-22T15:46:56+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "v1.3.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"shasum": ""
},
"require": {
"php": ">=5.5.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle promises library",
"keywords": [
"promise"
],
"time": "2016-12-20T10:07:11+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "1.5.2",
@ -258,6 +664,53 @@
],
"time": "2019-03-30T13:22:34+00:00"
},
{
"name": "league/flysystem-aws-s3-v3",
"version": "1.0.22",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git",
"reference": "883b02c80ca9cd68cf58a9b4b2185beef24b836b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/883b02c80ca9cd68cf58a9b4b2185beef24b836b",
"reference": "883b02c80ca9cd68cf58a9b4b2185beef24b836b",
"shasum": ""
},
"require": {
"aws/aws-sdk-php": "^3.0.0",
"league/flysystem": "^1.0.40",
"php": ">=5.5.0"
},
"require-dev": {
"henrikbjorn/phpspec-code-coverage": "~1.0.1",
"phpspec/phpspec": "^2.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"League\\Flysystem\\AwsS3v3\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Frank de Jonge",
"email": "info@frenky.net"
}
],
"description": "Flysystem adapter for the AWS S3 SDK v3.x",
"time": "2019-01-31T15:07:25+00:00"
},
{
"name": "monolog/monolog",
"version": "1.24.0",
@ -336,6 +789,61 @@
],
"time": "2018-11-05T09:00:11+00:00"
},
{
"name": "mtdowling/jmespath.php",
"version": "2.4.0",
"source": {
"type": "git",
"url": "https://github.com/jmespath/jmespath.php.git",
"reference": "adcc9531682cf87dfda21e1fd5d0e7a41d292fac"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/adcc9531682cf87dfda21e1fd5d0e7a41d292fac",
"reference": "adcc9531682cf87dfda21e1fd5d0e7a41d292fac",
"shasum": ""
},
"require": {
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"bin": [
"bin/jp.php"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"psr-4": {
"JmesPath\\": "src/"
},
"files": [
"src/JmesPath.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Declaratively specify how to extract elements from a JSON document",
"keywords": [
"json",
"jsonpath"
],
"time": "2016-12-03T22:08:25+00:00"
},
{
"name": "nikic/fast-route",
"version": "v1.3.0",
@ -432,6 +940,52 @@
],
"time": "2018-01-21T07:42:36+00:00"
},
{
"name": "psr/cache",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/cache.git",
"reference": "d11b50ad223250cf17b86e38383413f5a6764bf8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8",
"reference": "d11b50ad223250cf17b86e38383413f5a6764bf8",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Cache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for caching libraries",
"keywords": [
"cache",
"psr",
"psr-6"
],
"time": "2016-08-06T20:24:11+00:00"
},
{
"name": "psr/container",
"version": "1.0.0",
@ -618,6 +1172,50 @@
"description": "A polyfill for getallheaders.",
"time": "2016-02-11T07:05:27+00:00"
},
{
"name": "rize/uri-template",
"version": "0.3.2",
"source": {
"type": "git",
"url": "https://github.com/rize/UriTemplate.git",
"reference": "9e5fdd5c47147aa5adf7f760002ee591ed37b9ca"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rize/UriTemplate/zipball/9e5fdd5c47147aa5adf7f760002ee591ed37b9ca",
"reference": "9e5fdd5c47147aa5adf7f760002ee591ed37b9ca",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0.0"
},
"type": "library",
"autoload": {
"psr-0": {
"Rize\\UriTemplate": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marut K",
"homepage": "http://twitter.com/rezigned"
}
],
"description": "PHP URI Template (RFC 6570) supports both expansion & extraction",
"keywords": [
"RFC 6570",
"template",
"uri"
],
"time": "2017-06-14T03:57:53+00:00"
},
{
"name": "slim/slim",
"version": "3.12.1",
@ -740,6 +1338,161 @@
],
"time": "2019-04-06T16:34:38+00:00"
},
{
"name": "spatie/dropbox-api",
"version": "1.8.0",
"source": {
"type": "git",
"url": "https://github.com/spatie/dropbox-api.git",
"reference": "dc930cde4fdb802d20d0aeef5a98c3805fdcf9c2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/dropbox-api/zipball/dc930cde4fdb802d20d0aeef5a98c3805fdcf9c2",
"reference": "dc930cde4fdb802d20d0aeef5a98c3805fdcf9c2",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": "^6.2",
"php": "^7.1"
},
"require-dev": {
"phpunit/phpunit": "^6.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Spatie\\Dropbox\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Freek Van der Herten",
"email": "freek@spatie.be",
"homepage": "https://spatie.be",
"role": "Developer"
},
{
"name": "Alex Vanderbist",
"email": "alex.vanderbist@gmail.com",
"homepage": "https://spatie.be",
"role": "Developer"
}
],
"description": "A minimal implementation of Dropbox API v2",
"homepage": "https://github.com/spatie/dropbox-api",
"keywords": [
"Dropbox-API",
"api",
"dropbox",
"spatie",
"v2"
],
"time": "2019-04-13T10:52:11+00:00"
},
{
"name": "spatie/flysystem-dropbox",
"version": "1.0.6",
"source": {
"type": "git",
"url": "https://github.com/spatie/flysystem-dropbox.git",
"reference": "cff7dba925282736fff271fc41781a76fbe40799"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/flysystem-dropbox/zipball/cff7dba925282736fff271fc41781a76fbe40799",
"reference": "cff7dba925282736fff271fc41781a76fbe40799",
"shasum": ""
},
"require": {
"league/flysystem": "^1.0",
"php": "^7.0",
"spatie/dropbox-api": "^1.1.0"
},
"require-dev": {
"phpunit/phpunit": "^6.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Spatie\\FlysystemDropbox\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Alex Vanderbist",
"email": "alex.vanderbist@gmail.com",
"homepage": "https://spatie.be",
"role": "Developer"
}
],
"description": "Flysystem Adapter for the Dropbox v2 API",
"homepage": "https://github.com/spatie/flysystem-dropbox",
"keywords": [
"Flysystem",
"api",
"dropbox",
"flysystem-dropbox",
"spatie",
"v2"
],
"time": "2017-11-18T21:56:03+00:00"
},
{
"name": "superbalist/flysystem-google-storage",
"version": "7.2.1",
"source": {
"type": "git",
"url": "https://github.com/Superbalist/flysystem-google-cloud-storage.git",
"reference": "97cf8a5c9a9d368260b2791ec130690a1bec0cbd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Superbalist/flysystem-google-cloud-storage/zipball/97cf8a5c9a9d368260b2791ec130690a1bec0cbd",
"reference": "97cf8a5c9a9d368260b2791ec130690a1bec0cbd",
"shasum": ""
},
"require": {
"google/cloud-storage": "~1.0",
"league/flysystem": "~1.0",
"php": ">=5.5.0"
},
"require-dev": {
"mockery/mockery": "0.9.*",
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"Superbalist\\Flysystem\\GoogleStorage\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Superbalist.com a division of Takealot Online (Pty) Ltd",
"email": "info@superbalist.com"
}
],
"description": "Flysystem adapter for Google Cloud Storage",
"time": "2019-02-21T08:07:24+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.11.0",

View file

@ -4,6 +4,13 @@ require __DIR__ . '/../vendor/autoload.php';
use App\Database\DB;
use App\Web\Session;
use Aws\S3\S3Client;
use Google\Cloud\Storage\StorageClient;
use League\Flysystem\Adapter\Local;
use League\Flysystem\AwsS3v3\AwsS3Adapter;
use League\Flysystem\Adapter\Ftp as FtpAdapter;
use Spatie\Dropbox\Client as DropboxClient;
use League\Flysystem\Filesystem;
use Slim\App;
use Slim\Container;
use Slim\Http\Environment;
@ -11,21 +18,28 @@ use Slim\Http\Request;
use Slim\Http\Response;
use Slim\Http\Uri;
use Slim\Views\Twig;
use Spatie\FlysystemDropbox\DropboxAdapter;
use Superbalist\Flysystem\GoogleStorage\GoogleStorageAdapter;
define('PLATFORM_VERSION', json_decode(file_get_contents(__DIR__ . '/../composer.json'))->version);
$config = [
'base_url' => isset($_SERVER['HTTPS']) ? 'https://' . $_SERVER['HTTP_HOST'] : 'http://' . $_SERVER['HTTP_HOST'],
'storage_dir' => 'storage',
'displayErrorDetails' => true,
'db' => [
'connection' => 'sqlite',
'dsn' => 'resources/database/xbackbone.db',
'username' => null,
'password' => null,
],
'storage' => [
'driver' => 'local',
],
];
if (file_exists(__DIR__ . '/../config.php')) {
$config = array_replace_recursive($config, require __DIR__ . '/../config.php');
}
$container = new Container(['settings' => $config]);
$container['session'] = function ($container) {
@ -53,6 +67,47 @@ $container['view'] = function ($container) use (&$config) {
return $view;
};
$container['storage'] = function ($container) use (&$config) {
switch ($config['storage']['driver']) {
case 'local':
return new Filesystem(new Local($config['storage']['path']));
case 's3':
$client = new S3Client([
'credentials' => [
'key' => $config['storage']['key'],
'secret' => $config['storage']['secret'],
],
'region' => $config['storage']['region'],
'version' => 'latest',
]);
return new Filesystem(new AwsS3Adapter($client, $config['storage']['bucket'], $config['storage']['path']));
case 'dropbox':
$client = new DropboxClient($config['storage']['token']);
return new Filesystem(new DropboxAdapter($client), ['case_sensitive' => false]);
case 'ftp':
return new Filesystem(new FtpAdapter([
'host' => $config['storage']['host'],
'username' => $config['storage']['username'],
'password' => $config['storage']['password'],
'port' => $config['storage']['port'],
'root' => $config['storage']['path'],
'passive' => $config['storage']['passive'],
'ssl' => $config['storage']['ssl'],
'timeout' => 30,
]));
case 'google-cloud':
$client = new StorageClient([
'projectId' => $config['storage']['project_id'],
'keyFilePath' => $config['storage']['key_path'],
]);
return new Filesystem(new GoogleStorageAdapter($client, $client->bucket($config['storage']['bucket'])));
default:
throw new InvalidArgumentException('The driver specified is not supported.');
}
};
function migrate($config)
{
$firstMigrate = false;
@ -137,28 +192,64 @@ $app->get('/', function (Request $request, Response $response) {
});
$app->post('/', function (Request $request, Response $response) use (&$config) {
// Check if there is a previous installation, if not, setup the config file
$installed = true;
if (!file_exists(__DIR__ . '/../config.php')) {
$installed = false;
// config file setup
$config['base_url'] = $request->getParam('base_url');
$config['storage_dir'] = $request->getParam('storage_dir');
$config['storage']['driver'] = $request->getParam('storage_driver');
unset($config['displayErrorDetails']);
$config['db']['connection'] = $request->getParam('connection');
$config['db']['dsn'] = $request->getParam('dsn');
$config['db']['username'] = $request->getParam('db_user');
$config['db']['password'] = $request->getParam('db_password');
// setup storage configuration
switch ($config['storage']['driver']) {
case 's3':
$config['storage']['key'] = $request->getParam('storage_key');
$config['storage']['secret'] = $request->getParam('storage_secret');
$config['storage']['region'] = $request->getParam('storage_region');
$config['storage']['bucket'] = $request->getParam('storage_bucket');
$config['storage']['path'] = $request->getParam('storage_path');
break;
case 'dropbox':
$config['storage']['token'] = $request->getParam('storage_token');
break;
case 'ftp':
$config['storage']['host'] = $request->getParam('storage_host');
$config['storage']['username'] = $request->getParam('storage_username');
$config['storage']['password'] = $request->getParam('storage_password');
$config['storage']['port'] = $request->getParam('storage_port');
$config['storage']['path'] = $request->getParam('storage_path');
$config['storage']['passive'] = $request->getParam('storage_passive');
$config['storage']['ssl'] = $request->getParam('storage_ssl');
break;
case 'google-cloud':
$config['storage']['project_id'] = $request->getParam('storage_project_id');
$config['storage']['key_path'] = $request->getParam('storage_key_path');
$config['storage']['bucket'] = $request->getParam('storage_bucket');
break;
case 'local':
default:
$config['storage']['path'] = $request->getParam('storage_path');
break;
}
// check if the storage is valid
try {
storage($config['storage_dir']);
} catch (LogicException $exception) {
$this->session->alert('The storage folder is not readable (' . $config['storage_dir'] . ')', 'danger');
return redirect($response, './');
} finally {
if (!is_writable($config['storage_dir'])) {
$this->session->alert('The storage folder is not writable (' . $config['storage_dir'] . ')', 'danger');
return redirect($response, './');
$success = $this->storage->write('test.install.txt', '');
$this->storage->readAndDelete('test.install.txt');
if (!$success) {
throw new Exception('The storage is not writable.');
}
} catch (Exception $e) {
$this->session->alert("Storage setup error: {$e->getMessage()} [{$e->getTraceAsString()}]", 'danger');
return redirect($response, './');
}
$ret = file_put_contents(__DIR__ . '/../config.php', '<?php' . PHP_EOL . 'return ' . var_export($config, true) . ';');
@ -166,13 +257,13 @@ $app->post('/', function (Request $request, Response $response) use (&$config) {
$this->session->alert('The config folder is not writable (' . __DIR__ . '/../config.php' . ')', 'danger');
return redirect($response, './');
}
} else {
$config = require __DIR__ . '/../config.php';
}
$dsn = $config['db']['connection'] === 'sqlite' ? __DIR__ . '/../' . $config['db']['dsn'] : $config['db']['dsn'];
// Build the dns string and run the migrations
try {
$dsn = $config['db']['connection'] === 'sqlite' ? __DIR__ . '/../' . $config['db']['dsn'] : $config['db']['dsn'];
DB::setDsn($config['db']['connection'] . ':' . $dsn, $config['db']['username'], $config['db']['password']);
migrate($config);
@ -181,15 +272,18 @@ $app->post('/', function (Request $request, Response $response) use (&$config) {
return redirect($response, './');
}
// if not installed, create the default admin account
if (!$installed) {
DB::doQuery("INSERT INTO `users` (`email`, `username`, `password`, `is_admin`, `user_code`) VALUES (?, 'admin', ?, 1, ?)", [$request->getParam('email'), password_hash($request->getParam('password'), PASSWORD_DEFAULT), substr(md5(microtime()), rand(0, 26), 5)]);
}
// post install cleanup
cleanDirectory(__DIR__ . '/../resources/cache');
cleanDirectory(__DIR__ . '/../resources/sessions');
removeDirectory(__DIR__ . '/../install');
// if is upgrading and existing installation, put it out maintenance
if ($installed) {
unset($config['maintenance']);