Last active
April 13, 2021 23:45
-
-
Save summersab/363c753c4936f0bc563ea88a85de6241 to your computer and use it in GitHub Desktop.
Add app and category whitelisting and blacklisting to Nextcloud
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @copyright Copyright (c) 2021, Platypus Innovations LLC | |
* | |
* @author Andrew Summers | |
* | |
* This snippet provides a way to implement app and category whitelists/ | |
* blacklists on Nextcloud. This is accomplished by creating a dummy | |
* "appstore" on the local system: | |
* - Download the official listings from the Nextcloud servers | |
* - Filter out the apps/categories based on the provided configuration | |
* - Save the app/category files to the webroot | |
* - Modify `config.php` to point `appstoreurl` to localhost | |
* | |
* To use this script: | |
* 1. Save the file to the Nextcloud webroot | |
* 2. Make sure to set the proper permissions and ownership (usually by | |
* running `chown www-data:www-data appstore.php`) | |
* 3. From your browser, go to: | |
* https://your-Nextcloud-url.com/appstore.php?clearappcache | |
* This will automatically set up values in your `config.php` | |
* 4. Open up `config.php` and edit the whitelist/blacklist values as | |
* you see fit | |
* 5. Reload the page from step 3 | |
* | |
* You will need to set up a cron job or other scheduled tast to call | |
* the script on a regular basis in order to refresh the listings on | |
* your server. Also, Nextcloud caches the app and category listings, | |
* so if you want to force your system to refresh the files, make sure | |
* to append the `?clearappcache` URL parameter. | |
* | |
* In addition to a whitelist/blacklist, this script provides a few | |
* other features: | |
* - If you need to get a list of all available apps and categories, | |
* include the URL parameter `applist` or `categorylist`, respectively | |
* - Add an "All Apps" category to the app manager page. | |
* - Hide untested apps. This checks `version` value in `config.php` to | |
* determine if apps are compatible or not. Note that it only checks | |
* the maximum version value of an app, not the minimum. Also, it | |
* only checks whole-number values, not dot-revisions (i.e. 20.0.6 or | |
* 15.3.8) | |
*/ | |
<?php | |
<?php | |
require './lib/private/Config.php'; | |
$config = new \OC\Config('./config/'); | |
$config_keys = $config->getKeys(); | |
if (isset($_GET['clearappcache'])) { | |
unlink($config->getValue('datadirectory') . '/appdata_' . $config->getValue('instanceid') . '/appstore/apps.json'); | |
unlink($config->getValue('datadirectory') . '/appdata_' . $config->getValue('instanceid') . '/appstore/categories.json'); | |
} | |
$app_whitelist = array(); | |
$app_blacklist = array(); | |
$category_whitelist = array(); | |
$category_blacklist = array(); | |
$hide_untested_apps = false; | |
$hide_invalid_urls = false; | |
$add_all_apps_category = false; | |
if (in_array('appwhitelist', $config_keys)) { | |
$app_whitelist = $config->getValue('appwhitelist'); | |
} | |
if (in_array('appblacklist', $config_keys)) { | |
$app_blacklist = $config->getValue('appblacklist'); | |
} | |
if (in_array('categorywhitelist', $config_keys)) { | |
$category_whitelist = $config->getValue('categorywhitelist'); | |
} | |
if (in_array('categoryblacklist', $config_keys)) { | |
$category_blacklist = $config->getValue('categoryblacklist'); | |
} | |
if (in_array('hideuntestedapps', $config_keys)) { | |
$hide_untested_apps = $config->getValue('hideuntestedapps'); | |
} | |
if (in_array('hideinvalidurls', $config_keys)) { | |
$hide_invalid_urls = $config->getValue('hideinvalidurls'); | |
} | |
if (in_array('addallappscategory', $config_keys)) { | |
$add_all_apps_category = $config->getValue('addallappscategory'); | |
} | |
if (! in_array('appstoreenabled', $config_keys)) { | |
$config->setValue('appstoreenabled', true); | |
} | |
if (! in_array('appstoreurl', $config_keys)) { | |
$config->setValue('appstoreurl', $config->getValue('overwrite.cli.url')); | |
} | |
$apps = json_decode(file_get_contents('https://apps.nextcloud.com/api/v1/apps.json'),1); | |
$categories = json_decode(file_get_contents('https://apps.nextcloud.com/api/v1/categories.json'),1); | |
if (isset($_GET['applist']) && $_GET['applist'] != 'filtered') { | |
printAppList($apps); | |
} | |
if (isset($_GET['categorylist'])) { | |
printCategoryList($categories); | |
} | |
if (sizeof($app_whitelist) > 0) { | |
$apps = array_filter($apps, function($var) use ($app_whitelist) { | |
return in_array($var['id'], $app_whitelist); | |
}); | |
} | |
if (sizeof($app_blacklist) > 0) { | |
$apps = array_filter($apps, function($var) use ($app_blacklist) { | |
return ! in_array($var['id'], $app_blacklist); | |
}); | |
} | |
if (sizeof($category_whitelist) > 0) { | |
$categories = array_filter($categories, function($var) use ($category_whitelist) { | |
return in_array($var['id'], $category_whitelist); | |
}); | |
} | |
if (sizeof($category_blacklist) > 0) { | |
$categories = array_filter($categories, function($var) use ($category_blacklist) { | |
return ! in_array($var['id'], $category_blacklist); | |
}); | |
} | |
if ($add_all_apps_category) { | |
$all_apps_array = [ | |
'id' => 'all', | |
'translations' => [ | |
'en' => [ | |
'description' => 'All available Nextcloud apps', | |
'name' => 'All Apps', | |
], | |
], | |
]; | |
array_push($categories, $all_apps_array); | |
foreach ($apps as $key=>$app) { | |
array_push($apps[$key]['categories'], 'all'); | |
} | |
} | |
if ($hide_untested_apps) { | |
foreach ($apps as $app_key=>$app) { | |
if (isset($app['releases']) || array_key_exists('releases', $app)) { | |
foreach ($app['releases'] as $release_key=>$release) { | |
$versions = explode(' ', $release['platformVersionSpec']); | |
if (sizeof($versions) != 2) { | |
$version_max = PHP_INT_MAX; | |
$versions[1] = '<' . PHP_INT_MAX; | |
} | |
$version_min = ltrim($versions[0], '=><'); | |
$version_max = ltrim($versions[1], '=><'); | |
$version_min_comp = explode($version_min, $versions[0])[0]; | |
$version_max_comp = explode($version_max, $versions[1])[0]; | |
if ( | |
! version_compare($config->getValue('version'), $version_min, $version_min_comp) || | |
! version_compare($config->getValue('version'), $version_max, $version_max_comp) | |
) { | |
unset($apps[$app_key]['releases'][$release_key]); | |
} | |
else { | |
$head = @get_headers($release['download']); | |
if ($head && is_array($head) && sizeof($head) > 0) { | |
$response_code = explode(' ', $head[0])[1]; | |
if ($response_code > 399) { | |
unset($apps[$app_key]['releases'][$release_key]); | |
} | |
} | |
else { | |
unset($apps[$app_key]['releases'][$release_key]); | |
} | |
} | |
} | |
if (sizeof($apps[$app_key]['releases']) == 0) { | |
unset($apps[$app_key]); | |
} | |
else { | |
$apps[$app_key]['releases'] = array_values($apps[$app_key]['releases']); | |
} | |
} | |
} | |
$apps = array_values($apps); | |
} | |
if ($hide_invalid_urls) { | |
foreach ($apps as $app_key=>$app) { | |
if (isset($app['releases']) || array_key_exists('releases', $app)) { | |
foreach ($app['releases'] as $release_key=>$release) { | |
$head = @get_headers($release['download']); | |
if ($head && is_array($head) && sizeof($head) > 0) { | |
$response_code = explode(' ', $head[0])[1]; | |
if ($response_code > 399) { | |
unset($apps[$app_key]['releases'][$release_key]); | |
} | |
} | |
else { | |
unset($apps[$app_key]['releases'][$release_key]); | |
} | |
} | |
if (sizeof($apps[$app_key]['releases']) == 0) { | |
unset($apps[$app_key]); | |
} | |
else { | |
$apps[$app_key]['releases'] = array_values($apps[$app_key]['releases']); | |
} | |
} | |
} | |
$apps = array_values($apps); | |
} | |
if (isset($_GET['applist']) && $_GET['applist'] == 'filtered') { | |
printAppList($apps); | |
} | |
file_put_contents('apps.json', json_encode($apps)); | |
file_put_contents('categories.json', json_encode($categories)); | |
function printAppList($apps) { | |
echo '<style>table,th,td{border:1px solid black; border-collapse:collapse;}</style>'; | |
echo '<table>'; | |
foreach ($apps as $app) { | |
if (sizeof($app['releases']) > 0) { | |
echo '<tr>'; | |
echo '<td>' . $app['id'] . '</td>'; | |
echo '<td>' . $app['translations']['en']['name'] . '</td>'; | |
echo '</tr>'; | |
} | |
} | |
echo '</table>'; | |
} | |
function printCategoryList($categories) { | |
echo '<style>table,th,td{border:1px solid black; border-collapse:collapse;}</style>'; | |
echo '<table>'; | |
foreach ($categories as $category) { | |
echo '<tr>'; | |
echo '<td>' . $category['id'] . '</td>'; | |
echo '<td>' . $category['translations']['en']['name'] . '</td>'; | |
echo '</tr>'; | |
} | |
echo '</table>'; | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment