New core-extensions to allow Docker volumes for third-party extensions (#2837)

* New core-extensions to allow Docker volumes for third-party extensions

#Fix https://github.com/FreshRSS/FreshRSS/issues/2650
Split our extensions directory into two:
1) Core extensions shipped with FreshRSS in ./lib/core-extensions/
2) Third-party extensions modified by end-users in ./extensions/ which
can easily be mounted as a Docker volume

* Example of Docker Compose with extensions

* Back-compatibility + fix array merge bug
This commit is contained in:
Alexandre Alapetite 2020-03-22 16:31:20 +01:00 committed by GitHub
parent c03e097dae
commit cd49e9819b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 43 additions and 22 deletions

View File

@ -56,10 +56,12 @@ You must first chose a domain (DNS) or sub-domain, e.g. `freshrss.example.net`.
```sh
docker volume create freshrss-data
docker volume create freshrss-extensions
# Remember to replace freshrss.example.net by your server address in the command below:
docker run -d --restart unless-stopped --log-opt max-size=10m \
-v freshrss-data:/var/www/FreshRSS/data \
-v freshrss-extensions:/var/www/FreshRSS/extensions \
-e 'CRON_MIN=4,34' \
-e TZ=Europe/Paris \
--net freshrss-network \
@ -223,6 +225,7 @@ See cron option 1 for customising the cron schedule.
```sh
docker run -d --restart unless-stopped --log-opt max-size=10m \
-v freshrss-data:/var/www/FreshRSS/data \
-v freshrss-extensions:/var/www/FreshRSS/extensions \
-e 'CRON_MIN=17,47' \
--net freshrss-network \
--name freshrss_cron freshrss/freshrss \
@ -233,6 +236,7 @@ docker run -d --restart unless-stopped --log-opt max-size=10m \
```sh
docker run -d --restart unless-stopped --log-opt max-size=10m \
-v freshrss-data:/var/www/FreshRSS/data \
-v freshrss-extensions:/var/www/FreshRSS/extensions \
-e 'CRON_MIN=27,57' \
--net freshrss-network \
--name freshrss_cron freshrss/freshrss:alpine \

View File

@ -20,6 +20,7 @@ services:
- freshrss_postgresql
volumes:
- freshrss_data:/var/www/FreshRSS/data
- freshrss_extensions:/var/www/FreshRSS/extensions
environment:
- CRON_MIN=*/20
- TZ=Europe/Copenhagen
@ -29,3 +30,4 @@ services:
volumes:
pgsql_data:
freshrss_data:
freshrss_extensions:

View File

@ -13,7 +13,7 @@ define('INDEX_PATH', PUBLIC_PATH . PUBLIC_TO_INDEX_PATH);
define('PUBLIC_RELATIVE', '..');
define('LIB_PATH', FRESHRSS_PATH . '/lib');
define('APP_PATH', FRESHRSS_PATH . '/app');
define('EXTENSIONS_PATH', FRESHRSS_PATH . '/extensions');
define('CORE_EXTENSIONS_PATH', LIB_PATH . '/core-extensions');
//</Not customisable>
function safe_define($name, $value) {
@ -49,6 +49,11 @@ safe_define('API_LOG', USERS_PATH . '/_/log_api.txt');
safe_define('CACHE_PATH', DATA_PATH . '/cache');
safe_define('PSHB_LOG', USERS_PATH . '/_/log_pshb.txt');
safe_define('PSHB_PATH', DATA_PATH . '/PubSubHubbub');
safe_define('EXTENSIONS_DATA', DATA_PATH . '/extensions-data');
safe_define('THIRDPARTY_EXTENSIONS_PATH', FRESHRSS_PATH . '/extensions');
//Deprecated constants
safe_define('EXTENSIONS_PATH', FRESHRSS_PATH . '/extensions');
//Directory used for feed mutex with *.freshrss.lock files. Must be writable.
safe_define('TMP_PATH', sys_get_temp_dir());

View File

@ -1,4 +1,4 @@
# FreshRSS extensions
# FreshRSS third-party extensions
You may place custom extensions for FreshRSS in this directory.

View File

@ -1,7 +1,7 @@
<?php
/**
* An extension manager to load extensions present in EXTENSIONS_PATH.
* An extension manager to load extensions present in CORE_EXTENSIONS_PATH and THIRDPARTY_EXTENSIONS_PATH.
*
* @todo see coding style for methods!!
*/
@ -78,16 +78,17 @@ class Minz_ExtensionManager {
* inherit from Minz_Extension class.
*/
public static function init() {
$list_potential_extensions = array_values(array_diff(
scandir(EXTENSIONS_PATH),
array('..', '.')
));
$list_core_extensions = array_diff(scandir(CORE_EXTENSIONS_PATH), [ '..', '.' ]);
$list_thirdparty_extensions = array_diff(scandir(THIRDPARTY_EXTENSIONS_PATH), [ '..', '.' ], $list_core_extensions);
array_walk($list_core_extensions, function (&$s) { $s = CORE_EXTENSIONS_PATH . '/' . $s; });
array_walk($list_thirdparty_extensions, function (&$s) { $s = THIRDPARTY_EXTENSIONS_PATH . '/' . $s; });
$list_potential_extensions = array_merge($list_core_extensions, $list_thirdparty_extensions);
$system_conf = Minz_Configuration::get('system');
self::$ext_auto_enabled = $system_conf->extensions_enabled;
foreach ($list_potential_extensions as $ext_dir) {
$ext_pathname = EXTENSIONS_PATH . '/' . $ext_dir;
foreach ($list_potential_extensions as $ext_pathname) {
if (!is_dir($ext_pathname)) {
continue;
}
@ -111,7 +112,7 @@ class Minz_ExtensionManager {
// Try to load extension itself
$extension = self::load($meta_json);
if (!is_null($extension)) {
if ($extension != null) {
self::register($extension);
}
}

View File

@ -0,0 +1,5 @@
# FreshRSS core extensions
This directory contains some core extensions shipped with FreshRSS.
For custom third-party extensions, use the `./FreshRSS/extensions/` directory instead.

View File

@ -7,19 +7,9 @@ if (!isset($_GET['f']) ||
require(__DIR__ . '/../constants.php');
/**
* Check if a file can be served by ext.php. A valid file is under a
* EXTENSIONS_PATH/extension_name/static/ directory.
*
* You should sanitize path by using the realpath() function.
*
* @param $path the path to the file we want to serve.
* @return true if it can be served, false else.
*
*/
function is_valid_path($path) {
function is_valid_path_extension($path, $extensionPath) {
// It must be under the extension path.
$real_ext_path = realpath(EXTENSIONS_PATH);
$real_ext_path = realpath($extensionPath);
//Windows compatibility
$real_ext_path = str_replace('\\', '/', $real_ext_path);
@ -40,6 +30,20 @@ function is_valid_path($path) {
return true;
}
/**
* Check if a file can be served by ext.php. A valid file is under a
* CORE_EXTENSIONS_PATH/extension_name/static/ or THIRDPARTY_EXTENSIONS_PATH/extension_name/static/ directory.
*
* You should sanitize path by using the realpath() function.
*
* @param $path the path to the file we want to serve.
* @return true if it can be served, false otherwise.
*
*/
function is_valid_path($path) {
return is_valid_path_extension($path, CORE_EXTENSIONS_PATH) || is_valid_path_extension($path, THIRDPARTY_EXTENSIONS_PATH);
}
$file_name = urldecode($_GET['f']);
$file_type = $_GET['t'];