Add experimental applications switch
Allows administrators to disable or enabled experimental applications as well as show the trust level.
This commit is contained in:
parent
a2087f30d1
commit
0816cf9142
|
@ -576,6 +576,15 @@ $CONFIG = array(
|
|||
*/
|
||||
'appstoreurl' => 'https://api.owncloud.com/v1',
|
||||
|
||||
/**
|
||||
* Whether to experimental apps in the appstore interface
|
||||
*
|
||||
* Experimental apps are not checked for security issues and are new or known
|
||||
* to be unstable and under heavy development. Installing these can cause data
|
||||
* loss or security breaches.
|
||||
*/
|
||||
'appstore.experimental.enabled' => false,
|
||||
|
||||
/**
|
||||
* Use the ``apps_paths`` parameter to set the location of the Apps directory,
|
||||
* which should be scanned for available apps, and where user-specific apps
|
||||
|
|
|
@ -123,7 +123,7 @@
|
|||
if(OC_User::isAdminUser(OC_User::getUser())):
|
||||
?>
|
||||
<li id="apps-management">
|
||||
<a href="<?php print_unescaped(OC_Helper::linkToRoute('settings_apps')); ?>" tabindex="4"
|
||||
<a href="<?php print_unescaped(\OC::$server->getURLGenerator()->linkToRoute('settings.AppSettings.viewApps')); ?>" tabindex="4"
|
||||
<?php if( $_['appsmanagement_active'] ): ?> class="active"<?php endif; ?>>
|
||||
<img class="app-icon svg" alt="" src="<?php print_unescaped(OC_Helper::imagePath('settings', 'apps.svg')); ?>">
|
||||
<div class="icon-loading-dark" style="display:none;"></div>
|
||||
|
|
|
@ -61,6 +61,7 @@ class OC_App {
|
|||
static private $loadedApps = array();
|
||||
static private $altLogin = array();
|
||||
private static $shippedApps = null;
|
||||
const officialApp = 200;
|
||||
|
||||
/**
|
||||
* clean the appId
|
||||
|
@ -306,8 +307,13 @@ class OC_App {
|
|||
* @return int
|
||||
*/
|
||||
public static function downloadApp($app) {
|
||||
$appData= OCSClient::getApplication($app);
|
||||
$download= OCSClient::getApplicationDownload($app, 1);
|
||||
$ocsClient = new OCSClient(
|
||||
\OC::$server->getHTTPClientService(),
|
||||
\OC::$server->getConfig(),
|
||||
\OC::$server->getLogger()
|
||||
);
|
||||
$appData = $ocsClient->getApplication($app);
|
||||
$download= $ocsClient->getApplicationDownload($app);
|
||||
if(isset($download['downloadlink']) and $download['downloadlink']!='') {
|
||||
// Replace spaces in download link without encoding entire URL
|
||||
$download['downloadlink'] = str_replace(' ', '%20', $download['downloadlink']);
|
||||
|
@ -780,8 +786,9 @@ class OC_App {
|
|||
}
|
||||
|
||||
/**
|
||||
* Lists all apps, this is used in apps.php
|
||||
* List all apps, this is used in apps.php
|
||||
*
|
||||
* @param bool $onlyLocal
|
||||
* @return array
|
||||
*/
|
||||
public static function listAllApps($onlyLocal = false) {
|
||||
|
@ -819,8 +826,7 @@ class OC_App {
|
|||
|
||||
if (isset($info['shipped']) and ($info['shipped'] == 'true')) {
|
||||
$info['internal'] = true;
|
||||
$info['internallabel'] = (string)$l->t('Recommended');
|
||||
$info['internalclass'] = 'recommendedapp';
|
||||
$info['level'] = self::officialApp;
|
||||
$info['removable'] = false;
|
||||
} else {
|
||||
$info['internal'] = false;
|
||||
|
@ -845,7 +851,7 @@ class OC_App {
|
|||
}
|
||||
}
|
||||
if ($onlyLocal) {
|
||||
$remoteApps = array();
|
||||
$remoteApps = [];
|
||||
} else {
|
||||
$remoteApps = OC_App::getAppstoreApps();
|
||||
}
|
||||
|
@ -865,34 +871,6 @@ class OC_App {
|
|||
} else {
|
||||
$combinedApps = $appList;
|
||||
}
|
||||
// bring the apps into the right order with a custom sort function
|
||||
usort($combinedApps, function ($a, $b) {
|
||||
|
||||
// priority 1: active
|
||||
if ($a['active'] != $b['active']) {
|
||||
return $b['active'] - $a['active'];
|
||||
}
|
||||
|
||||
// priority 2: shipped
|
||||
$aShipped = (array_key_exists('shipped', $a) && $a['shipped'] === 'true') ? 1 : 0;
|
||||
$bShipped = (array_key_exists('shipped', $b) && $b['shipped'] === 'true') ? 1 : 0;
|
||||
if ($aShipped !== $bShipped) {
|
||||
return ($bShipped - $aShipped);
|
||||
}
|
||||
|
||||
// priority 3: recommended
|
||||
$internalClassA = isset($a['internalclass']) ? $a['internalclass'] : '';
|
||||
$internalClassB = isset($b['internalclass']) ? $b['internalclass'] : '';
|
||||
if ($internalClassA != $internalClassB) {
|
||||
$aTemp = ($internalClassA == 'recommendedapp' ? 1 : 0);
|
||||
$bTemp = ($internalClassB == 'recommendedapp' ? 1 : 0);
|
||||
return ($bTemp - $aTemp);
|
||||
}
|
||||
|
||||
// priority 4: alphabetical
|
||||
return strcasecmp($a['name'], $b['name']);
|
||||
|
||||
});
|
||||
|
||||
return $combinedApps;
|
||||
}
|
||||
|
@ -913,15 +891,24 @@ class OC_App {
|
|||
}
|
||||
|
||||
/**
|
||||
* get a list of all apps on apps.owncloud.com
|
||||
*
|
||||
* @return array|false multi-dimensional array of apps.
|
||||
* Get a list of all apps on the appstore
|
||||
* @param string $filter
|
||||
* @param string $category
|
||||
* @return array|bool multi-dimensional array of apps.
|
||||
* Keys: id, name, type, typename, personid, license, detailpage, preview, changed, description
|
||||
*/
|
||||
public static function getAppstoreApps($filter = 'approved', $category = null) {
|
||||
$categories = array($category);
|
||||
$categories = [$category];
|
||||
|
||||
$ocsClient = new OCSClient(
|
||||
\OC::$server->getHTTPClientService(),
|
||||
\OC::$server->getConfig(),
|
||||
\OC::$server->getLogger()
|
||||
);
|
||||
|
||||
|
||||
if (is_null($category)) {
|
||||
$categoryNames = OCSClient::getCategories();
|
||||
$categoryNames = $ocsClient->getCategories();
|
||||
if (is_array($categoryNames)) {
|
||||
// Check that categories of apps were retrieved correctly
|
||||
if (!$categories = array_keys($categoryNames)) {
|
||||
|
@ -933,34 +920,36 @@ class OC_App {
|
|||
}
|
||||
|
||||
$page = 0;
|
||||
$remoteApps = OCSClient::getApplications($categories, $page, $filter);
|
||||
$app1 = array();
|
||||
$remoteApps = $ocsClient->getApplications($categories, $page, $filter);
|
||||
$apps = [];
|
||||
$i = 0;
|
||||
$l = \OC::$server->getL10N('core');
|
||||
foreach ($remoteApps as $app) {
|
||||
$potentialCleanId = self::getInternalAppIdByOcs($app['id']);
|
||||
// enhance app info (for example the description)
|
||||
$app1[$i] = OC_App::parseAppInfo($app);
|
||||
$app1[$i]['author'] = $app['personid'];
|
||||
$app1[$i]['ocs_id'] = $app['id'];
|
||||
$app1[$i]['internal'] = 0;
|
||||
$app1[$i]['active'] = ($potentialCleanId !== false) ? self::isEnabled($potentialCleanId) : false;
|
||||
$app1[$i]['update'] = false;
|
||||
$app1[$i]['groups'] = false;
|
||||
$app1[$i]['score'] = $app['score'];
|
||||
$app1[$i]['removable'] = false;
|
||||
$apps[$i] = OC_App::parseAppInfo($app);
|
||||
$apps[$i]['author'] = $app['personid'];
|
||||
$apps[$i]['ocs_id'] = $app['id'];
|
||||
$apps[$i]['internal'] = 0;
|
||||
$apps[$i]['active'] = ($potentialCleanId !== false) ? self::isEnabled($potentialCleanId) : false;
|
||||
$apps[$i]['update'] = false;
|
||||
$apps[$i]['groups'] = false;
|
||||
$apps[$i]['score'] = $app['score'];
|
||||
$apps[$i]['removable'] = false;
|
||||
if ($app['label'] == 'recommended') {
|
||||
$app1[$i]['internallabel'] = (string)$l->t('Recommended');
|
||||
$app1[$i]['internalclass'] = 'recommendedapp';
|
||||
$apps[$i]['internallabel'] = (string)$l->t('Recommended');
|
||||
$apps[$i]['internalclass'] = 'recommendedapp';
|
||||
}
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
if (empty($app1)) {
|
||||
|
||||
|
||||
if (empty($apps)) {
|
||||
return false;
|
||||
} else {
|
||||
return $app1;
|
||||
return $apps;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1084,7 +1073,12 @@ class OC_App {
|
|||
public static function installApp($app) {
|
||||
$l = \OC::$server->getL10N('core');
|
||||
$config = \OC::$server->getConfig();
|
||||
$appData=OCSClient::getApplication($app);
|
||||
$ocsClient = new OCSClient(
|
||||
\OC::$server->getHTTPClientService(),
|
||||
$config,
|
||||
\OC::$server->getLogger()
|
||||
);
|
||||
$appData = $ocsClient->getApplication($app);
|
||||
|
||||
// check if app is a shipped app or not. OCS apps have an integer as id, shipped apps use a string
|
||||
if (!is_numeric($app)) {
|
||||
|
|
|
@ -203,7 +203,7 @@ class AppManager implements IAppManager {
|
|||
/**
|
||||
* Clear the cached list of apps when enabling/disabling an app
|
||||
*/
|
||||
protected function clearAppsCache() {
|
||||
public function clearAppsCache() {
|
||||
$settingsMemCache = $this->memCacheFactory->create('settings');
|
||||
$settingsMemCache->clear('listApps');
|
||||
}
|
||||
|
|
|
@ -222,8 +222,13 @@ class OC_Installer{
|
|||
* @throws Exception
|
||||
*/
|
||||
public static function updateAppByOCSId($ocsId) {
|
||||
$appData = OCSClient::getApplication($ocsId);
|
||||
$download = OCSClient::getApplicationDownload($ocsId, 1);
|
||||
$ocsClient = new OCSClient(
|
||||
\OC::$server->getHTTPClientService(),
|
||||
\OC::$server->getConfig(),
|
||||
\OC::$server->getLogger()
|
||||
);
|
||||
$appData = $ocsClient->getApplication($ocsId);
|
||||
$download = $ocsClient->getApplicationDownload($ocsId);
|
||||
|
||||
if (isset($download['downloadlink']) && trim($download['downloadlink']) !== '') {
|
||||
$download['downloadlink'] = str_replace(' ', '%20', $download['downloadlink']);
|
||||
|
@ -385,8 +390,12 @@ class OC_Installer{
|
|||
$ocsid=OC_Appconfig::getValue( $app, 'ocsid', '');
|
||||
|
||||
if($ocsid<>'') {
|
||||
|
||||
$ocsdata=OCSClient::getApplication($ocsid);
|
||||
$ocsClient = new OCSClient(
|
||||
\OC::$server->getHTTPClientService(),
|
||||
\OC::$server->getConfig(),
|
||||
\OC::$server->getLogger()
|
||||
);
|
||||
$ocsdata = $ocsClient->getApplication($ocsid);
|
||||
$ocsversion= (string) $ocsdata['version'];
|
||||
$currentversion=OC_App::getAppVersion($app);
|
||||
if (version_compare($ocsversion, $currentversion, '>')) {
|
||||
|
|
|
@ -32,36 +32,52 @@
|
|||
|
||||
namespace OC;
|
||||
|
||||
/**
|
||||
* This class provides an easy way for apps to store config values in the
|
||||
* database.
|
||||
*/
|
||||
use OCP\Http\Client\IClientService;
|
||||
use OCP\IConfig;
|
||||
use OCP\ILogger;
|
||||
|
||||
/**
|
||||
* Class OCSClient is a class for communication with the ownCloud appstore
|
||||
*
|
||||
* @package OC
|
||||
*/
|
||||
class OCSClient {
|
||||
/** @var IClientService */
|
||||
private $httpClientService;
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
/** @var ILogger */
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* @param IClientService $httpClientService
|
||||
* @param IConfig $config
|
||||
* @param ILogger $logger
|
||||
*/
|
||||
public function __construct(IClientService $httpClientService,
|
||||
IConfig $config,
|
||||
ILogger $logger) {
|
||||
$this->httpClientService = $httpClientService;
|
||||
$this->config = $config;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the AppStore is enabled (i.e. because the AppStore is disabled for EE)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isAppStoreEnabled() {
|
||||
if (\OC::$server->getConfig()->getSystemValue('appstoreenabled', true) === false ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
public function isAppStoreEnabled() {
|
||||
return $this->config->getSystemValue('appstoreenabled', true) === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the url of the OCS AppStore server.
|
||||
*
|
||||
* @return string of the AppStore server
|
||||
*
|
||||
* This function returns the url of the OCS AppStore server. It´s possible
|
||||
* to set it in the config file or it will fallback to the default
|
||||
*/
|
||||
private static function getAppStoreURL() {
|
||||
return \OC::$server->getConfig()->getSystemValue('appstoreurl', 'https://api.owncloud.com/v1');
|
||||
private function getAppStoreUrl() {
|
||||
return $this->config->getSystemValue('appstoreurl', 'https://api.owncloud.com/v1');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -71,36 +87,50 @@ class OCSClient {
|
|||
* @note returns NULL if config value appstoreenabled is set to false
|
||||
* This function returns a list of all the application categories on the OCS server
|
||||
*/
|
||||
public static function getCategories() {
|
||||
if (!self::isAppStoreEnabled()) {
|
||||
public function getCategories() {
|
||||
if (!$this->isAppStoreEnabled()) {
|
||||
return null;
|
||||
}
|
||||
$url = self::getAppStoreURL() . '/content/categories';
|
||||
|
||||
$client = \OC::$server->getHTTPClientService()->newClient();
|
||||
$client = $this->httpClientService->newClient();
|
||||
try {
|
||||
$response = $client->get($url, ['timeout' => 5]);
|
||||
$response = $client->get(
|
||||
$this->getAppStoreUrl() . '/content/categories',
|
||||
[
|
||||
'timeout' => 5,
|
||||
]
|
||||
);
|
||||
} catch(\Exception $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if($response->getStatusCode() !== 200) {
|
||||
$this->logger->error(
|
||||
sprintf('Could not get categories: %s', $e->getMessage()),
|
||||
[
|
||||
'app' => 'core',
|
||||
]
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
$loadEntities = libxml_disable_entity_loader(true);
|
||||
$data = simplexml_load_string($response->getBody());
|
||||
$data = @simplexml_load_string($response->getBody());
|
||||
libxml_disable_entity_loader($loadEntities);
|
||||
|
||||
if($data === false) {
|
||||
$this->logger->error(
|
||||
'Could not get categories, content was no valid XML',
|
||||
[
|
||||
'app' => 'core',
|
||||
]
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
$tmp = $data->data;
|
||||
$cats = [];
|
||||
|
||||
foreach ($tmp->category as $value) {
|
||||
|
||||
$id = (int)$value->id;
|
||||
$name = (string)$value->name;
|
||||
$cats[$id] = $name;
|
||||
|
||||
}
|
||||
|
||||
return $cats;
|
||||
|
@ -108,50 +138,63 @@ class OCSClient {
|
|||
|
||||
/**
|
||||
* Get all the applications from the OCS server
|
||||
*
|
||||
* @return array|null an array of application data or null
|
||||
*
|
||||
* This function returns a list of all the applications on the OCS server
|
||||
* @param array|string $categories
|
||||
* @param array $categories
|
||||
* @param int $page
|
||||
* @param string $filter
|
||||
* @return array An array of application data
|
||||
*/
|
||||
public static function getApplications($categories, $page, $filter) {
|
||||
if (!self::isAppStoreEnabled()) {
|
||||
return (array());
|
||||
public function getApplications(array $categories, $page, $filter) {
|
||||
if (!$this->isAppStoreEnabled()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (is_array($categories)) {
|
||||
$categoriesString = implode('x', $categories);
|
||||
} else {
|
||||
$categoriesString = $categories;
|
||||
}
|
||||
|
||||
$version = '&version=' . implode('x', \OC_Util::getVersion());
|
||||
$filterUrl = '&filter=' . urlencode($filter);
|
||||
$url = self::getAppStoreURL() . '/content/data?categories=' . urlencode($categoriesString)
|
||||
. '&sortmode=new&page=' . urlencode($page) . '&pagesize=100' . $filterUrl . $version;
|
||||
$apps = [];
|
||||
|
||||
$client = \OC::$server->getHTTPClientService()->newClient();
|
||||
$client = $this->httpClientService->newClient();
|
||||
try {
|
||||
$response = $client->get($url, ['timeout' => 5]);
|
||||
$response = $client->get(
|
||||
$this->getAppStoreUrl() . '/content/data',
|
||||
[
|
||||
'timeout' => 5,
|
||||
'query' => [
|
||||
'version' => implode('x', \OC_Util::getVersion()),
|
||||
'filter' => $filter,
|
||||
'categories' => implode('x', $categories),
|
||||
'sortmode' => 'new',
|
||||
'page' => $page,
|
||||
'pagesize' => 100,
|
||||
'approved' => $filter
|
||||
],
|
||||
]
|
||||
);
|
||||
} catch(\Exception $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if($response->getStatusCode() !== 200) {
|
||||
return null;
|
||||
$this->logger->error(
|
||||
sprintf('Could not get applications: %s', $e->getMessage()),
|
||||
[
|
||||
'app' => 'core',
|
||||
]
|
||||
);
|
||||
return [];
|
||||
}
|
||||
|
||||
$loadEntities = libxml_disable_entity_loader(true);
|
||||
$data = simplexml_load_string($response->getBody());
|
||||
$data = @simplexml_load_string($response->getBody());
|
||||
libxml_disable_entity_loader($loadEntities);
|
||||
|
||||
if($data === false) {
|
||||
$this->logger->error(
|
||||
'Could not get applications, content was no valid XML',
|
||||
[
|
||||
'app' => 'core',
|
||||
]
|
||||
);
|
||||
return [];
|
||||
}
|
||||
|
||||
$tmp = $data->data->content;
|
||||
$tmpCount = count($tmp);
|
||||
|
||||
$apps = [];
|
||||
for ($i = 0; $i < $tmpCount; $i++) {
|
||||
$app = array();
|
||||
$app = [];
|
||||
$app['id'] = (string)$tmp[$i]->id;
|
||||
$app['name'] = (string)$tmp[$i]->name;
|
||||
$app['label'] = (string)$tmp[$i]->label;
|
||||
|
@ -167,9 +210,11 @@ class OCSClient {
|
|||
$app['description'] = (string)$tmp[$i]->description;
|
||||
$app['score'] = (string)$tmp[$i]->score;
|
||||
$app['downloads'] = (int)$tmp[$i]->downloads;
|
||||
$app['level'] = (int)$tmp[$i]->approved;
|
||||
|
||||
$apps[] = $app;
|
||||
}
|
||||
|
||||
return $apps;
|
||||
}
|
||||
|
||||
|
@ -182,84 +227,111 @@ class OCSClient {
|
|||
*
|
||||
* This function returns an applications from the OCS server
|
||||
*/
|
||||
public static function getApplication($id) {
|
||||
if (!self::isAppStoreEnabled()) {
|
||||
return null;
|
||||
}
|
||||
$url = self::getAppStoreURL() . '/content/data/' . urlencode($id);
|
||||
$client = \OC::$server->getHTTPClientService()->newClient();
|
||||
try {
|
||||
$response = $client->get($url, ['timeout' => 5]);
|
||||
} catch(\Exception $e) {
|
||||
public function getApplication($id) {
|
||||
if (!$this->isAppStoreEnabled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if($response->getStatusCode() !== 200) {
|
||||
$client = $this->httpClientService->newClient();
|
||||
try {
|
||||
$response = $client->get(
|
||||
$this->getAppStoreUrl() . '/content/data/' . urlencode($id),
|
||||
[
|
||||
'timeout' => 5,
|
||||
]
|
||||
);
|
||||
} catch(\Exception $e) {
|
||||
$this->logger->error(
|
||||
sprintf('Could not get application: %s', $e->getMessage()),
|
||||
[
|
||||
'app' => 'core',
|
||||
]
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
$loadEntities = libxml_disable_entity_loader(true);
|
||||
$data = simplexml_load_string($response->getBody());
|
||||
$data = @simplexml_load_string($response->getBody());
|
||||
libxml_disable_entity_loader($loadEntities);
|
||||
|
||||
$tmp = $data->data->content;
|
||||
if (is_null($tmp)) {
|
||||
\OC_Log::write('core', 'Invalid OCS content returned for app ' . $id, \OC_Log::FATAL);
|
||||
if($data === false) {
|
||||
$this->logger->error(
|
||||
'Could not get application, content was no valid XML',
|
||||
[
|
||||
'app' => 'core',
|
||||
]
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
$tmp = $data->data->content;
|
||||
|
||||
$app = [];
|
||||
$app['id'] = $tmp->id;
|
||||
$app['name'] = $tmp->name;
|
||||
$app['version'] = $tmp->version;
|
||||
$app['type'] = $tmp->typeid;
|
||||
$app['label'] = $tmp->label;
|
||||
$app['typename'] = $tmp->typename;
|
||||
$app['personid'] = $tmp->personid;
|
||||
$app['detailpage'] = $tmp->detailpage;
|
||||
$app['preview1'] = $tmp->smallpreviewpic1;
|
||||
$app['preview2'] = $tmp->smallpreviewpic2;
|
||||
$app['preview3'] = $tmp->smallpreviewpic3;
|
||||
$app['id'] = (int)$tmp->id;
|
||||
$app['name'] = (string)$tmp->name;
|
||||
$app['version'] = (string)$tmp->version;
|
||||
$app['type'] = (string)$tmp->typeid;
|
||||
$app['label'] = (string)$tmp->label;
|
||||
$app['typename'] = (string)$tmp->typename;
|
||||
$app['personid'] = (string)$tmp->personid;
|
||||
$app['detailpage'] = (string)$tmp->detailpage;
|
||||
$app['preview1'] = (string)$tmp->smallpreviewpic1;
|
||||
$app['preview2'] = (string)$tmp->smallpreviewpic2;
|
||||
$app['preview3'] = (string)$tmp->smallpreviewpic3;
|
||||
$app['changed'] = strtotime($tmp->changed);
|
||||
$app['description'] = $tmp->description;
|
||||
$app['detailpage'] = $tmp->detailpage;
|
||||
$app['score'] = $tmp->score;
|
||||
$app['description'] = (string)$tmp->description;
|
||||
$app['detailpage'] = (string)$tmp->detailpage;
|
||||
$app['score'] = (int)$tmp->score;
|
||||
|
||||
return $app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the download url for an application from the OCS server
|
||||
*
|
||||
* @param $id
|
||||
* @return array|null an array of application data or null
|
||||
*
|
||||
* This function returns an download url for an applications from the OCS server
|
||||
* @param string $id
|
||||
* @param integer $item
|
||||
*/
|
||||
public static function getApplicationDownload($id, $item) {
|
||||
if (!self::isAppStoreEnabled()) {
|
||||
public function getApplicationDownload($id) {
|
||||
if (!$this->isAppStoreEnabled()) {
|
||||
return null;
|
||||
}
|
||||
$url = self::getAppStoreURL() . '/content/download/' . urlencode($id) . '/' . urlencode($item);
|
||||
$client = \OC::$server->getHTTPClientService()->newClient();
|
||||
$url = $this->getAppStoreUrl() . '/content/download/' . urlencode($id) . '/1';
|
||||
$client = $this->httpClientService->newClient();
|
||||
try {
|
||||
$response = $client->get($url, ['timeout' => 5]);
|
||||
$response = $client->get(
|
||||
$url,
|
||||
[
|
||||
'timeout' => 5,
|
||||
]
|
||||
);
|
||||
} catch(\Exception $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if($response->getStatusCode() !== 200) {
|
||||
$this->logger->error(
|
||||
sprintf('Could not get application download URL: %s', $e->getMessage()),
|
||||
[
|
||||
'app' => 'core',
|
||||
]
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
$loadEntities = libxml_disable_entity_loader(true);
|
||||
$data = simplexml_load_string($response->getBody());
|
||||
$data = @simplexml_load_string($response->getBody());
|
||||
libxml_disable_entity_loader($loadEntities);
|
||||
|
||||
if($data === false) {
|
||||
$this->logger->error(
|
||||
'Could not get application download URL, content was no valid XML',
|
||||
[
|
||||
'app' => 'core',
|
||||
]
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
$tmp = $data->data->content;
|
||||
$app = array();
|
||||
$app = [];
|
||||
if (isset($tmp->downloadlink)) {
|
||||
$app['downloadlink'] = $tmp->downloadlink;
|
||||
$app['downloadlink'] = (string)$tmp->downloadlink;
|
||||
} else {
|
||||
$app['downloadlink'] = '';
|
||||
}
|
||||
|
|
|
@ -391,6 +391,13 @@ class Server extends SimpleContainer implements IServerContainer {
|
|||
new \OC_Defaults()
|
||||
);
|
||||
});
|
||||
$this->registerService('OcsClient', function(Server $c) {
|
||||
return new OCSClient(
|
||||
$this->getHTTPClientService(),
|
||||
$this->getConfig(),
|
||||
$this->getLogger()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -836,6 +843,13 @@ class Server extends SimpleContainer implements IServerContainer {
|
|||
return $this->webRoot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \OC\OCSClient
|
||||
*/
|
||||
public function getOcsClient() {
|
||||
return $this->query('OcsClient');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \OCP\IDateTimeZone
|
||||
*/
|
||||
|
|
|
@ -107,7 +107,7 @@ class OC_TemplateLayout extends OC_Template {
|
|||
$userDisplayName = OC_User::getDisplayName();
|
||||
$this->assign('user_displayname', $userDisplayName);
|
||||
$this->assign('user_uid', OC_User::getUser());
|
||||
$this->assign('appsmanagement_active', strpos(\OC::$server->getRequest()->getRequestUri(), OC_Helper::linkToRoute('settings_apps')) === 0 );
|
||||
$this->assign('appsmanagement_active', strpos(\OC::$server->getRequest()->getRequestUri(), \OC::$server->getURLGenerator()->linkToRoute('settings.AppSettings.viewApps')) === 0 );
|
||||
$this->assign('enableAvatars', $this->config->getSystemValue('enable_avatars', true));
|
||||
$this->assign('userAvatarSet', \OC_Helper::userAvatarSet(OC_User::getUser()));
|
||||
} else if ($renderAs == 'error') {
|
||||
|
|
|
@ -78,4 +78,9 @@ interface IAppManager {
|
|||
* @return string[]
|
||||
*/
|
||||
public function getInstalledApps();
|
||||
|
||||
/**
|
||||
* Clear the cached list of apps when enabling/disabling an app
|
||||
*/
|
||||
public function clearAppsCache();
|
||||
}
|
||||
|
|
|
@ -71,7 +71,10 @@ class Application extends App {
|
|||
$c->query('Request'),
|
||||
$c->query('L10N'),
|
||||
$c->query('Config'),
|
||||
$c->query('ICacheFactory')
|
||||
$c->query('ICacheFactory'),
|
||||
$c->query('INavigationManager'),
|
||||
$c->query('IAppManager'),
|
||||
$c->query('OcsClient')
|
||||
);
|
||||
});
|
||||
$container->registerService('SecuritySettingsController', function(IContainer $c) {
|
||||
|
@ -191,6 +194,15 @@ class Application extends App {
|
|||
$container->registerService('ClientService', function(IContainer $c) {
|
||||
return $c->query('ServerContainer')->getHTTPClientService();
|
||||
});
|
||||
$container->registerService('INavigationManager', function(IContainer $c) {
|
||||
return $c->query('ServerContainer')->getNavigationManager();
|
||||
});
|
||||
$container->registerService('IAppManager', function(IContainer $c) {
|
||||
return $c->query('ServerContainer')->getAppManager();
|
||||
});
|
||||
$container->registerService('OcsClient', function(IContainer $c) {
|
||||
return $c->query('ServerContainer')->getOcsClient();
|
||||
});
|
||||
$container->registerService('Util', function(IContainer $c) {
|
||||
return new \OC_Util();
|
||||
});
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Bart Visscher <bartv@thisnet.nl>
|
||||
* @author Frank Karlitschek <frank@owncloud.org>
|
||||
* @author Jan-Christoph Borchardt <hey@jancborchardt.net>
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
* @author Morris Jobke <hey@morrisjobke.de>
|
||||
* @author Robin Appelman <icewind@owncloud.com>
|
||||
* @author Thomas Müller <thomas.mueller@tmit.eu>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
OC_Util::checkAdminUser();
|
||||
\OC::$server->getSession()->close();
|
||||
|
||||
// Load the files we need
|
||||
\OC_Util::addVendorScript('handlebars/handlebars');
|
||||
\OCP\Util::addScript("settings", "settings");
|
||||
\OCP\Util::addStyle("settings", "settings");
|
||||
\OC_Util::addVendorScript('select2/select2');
|
||||
\OC_Util::addVendorStyle('select2/select2');
|
||||
\OCP\Util::addScript("settings", "apps");
|
||||
\OC_App::setActiveNavigationEntry( "core_apps" );
|
||||
|
||||
$tmpl = new OC_Template( "settings", "apps", "user" );
|
||||
$tmpl->printPage();
|
||||
|
|
@ -27,8 +27,13 @@ namespace OC\Settings\Controller;
|
|||
use OC\App\DependencyAnalyzer;
|
||||
use OC\App\Platform;
|
||||
use OC\OCSClient;
|
||||
use OCP\App\IAppManager;
|
||||
use \OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\ContentSecurityPolicy;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\ICacheFactory;
|
||||
use OCP\INavigationManager;
|
||||
use OCP\IRequest;
|
||||
use OCP\IL10N;
|
||||
use OCP\IConfig;
|
||||
|
@ -44,6 +49,12 @@ class AppSettingsController extends Controller {
|
|||
private $config;
|
||||
/** @var \OCP\ICache */
|
||||
private $cache;
|
||||
/** @var INavigationManager */
|
||||
private $navigationManager;
|
||||
/** @var IAppManager */
|
||||
private $appManager;
|
||||
/** @var OCSClient */
|
||||
private $ocsClient;
|
||||
|
||||
/**
|
||||
* @param string $appName
|
||||
|
@ -51,16 +62,53 @@ class AppSettingsController extends Controller {
|
|||
* @param IL10N $l10n
|
||||
* @param IConfig $config
|
||||
* @param ICacheFactory $cache
|
||||
* @param INavigationManager $navigationManager
|
||||
* @param IAppManager $appManager
|
||||
* @param OCSClient $ocsClient
|
||||
*/
|
||||
public function __construct($appName,
|
||||
IRequest $request,
|
||||
IL10N $l10n,
|
||||
IConfig $config,
|
||||
ICacheFactory $cache) {
|
||||
ICacheFactory $cache,
|
||||
INavigationManager $navigationManager,
|
||||
IAppManager $appManager,
|
||||
OCSClient $ocsClient) {
|
||||
parent::__construct($appName, $request);
|
||||
$this->l10n = $l10n;
|
||||
$this->config = $config;
|
||||
$this->cache = $cache->create($appName);
|
||||
$this->navigationManager = $navigationManager;
|
||||
$this->appManager = $appManager;
|
||||
$this->ocsClient = $ocsClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the display of experimental apps
|
||||
* @param bool $state
|
||||
* @return DataResponse
|
||||
*/
|
||||
public function changeExperimentalConfigState($state) {
|
||||
$this->config->setSystemValue('appstore.experimental.enabled', $state);
|
||||
$this->appManager->clearAppsCache();
|
||||
return new DataResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoCSRFRequired
|
||||
* @return TemplateResponse
|
||||
*/
|
||||
public function viewApps() {
|
||||
$params = [];
|
||||
$params['experimentalEnabled'] = $this->config->getSystemValue('appstore.experimental.enabled', false);
|
||||
$this->navigationManager->setActiveEntry('core_apps');
|
||||
|
||||
$templateResponse = new TemplateResponse($this->appName, 'apps', $params, 'user');
|
||||
$policy = new ContentSecurityPolicy();
|
||||
$policy->addAllowedImageDomain('https://apps.owncloud.com');
|
||||
$templateResponse->setContentSecurityPolicy($policy);
|
||||
|
||||
return $templateResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -77,16 +125,15 @@ class AppSettingsController extends Controller {
|
|||
['id' => 1, 'displayName' => (string)$this->l10n->t('Not enabled')],
|
||||
];
|
||||
|
||||
if(OCSClient::isAppStoreEnabled()) {
|
||||
$categories[] = ['id' => 2, 'displayName' => (string)$this->l10n->t('Recommended')];
|
||||
if($this->ocsClient->isAppStoreEnabled()) {
|
||||
// apps from external repo via OCS
|
||||
$ocs = OCSClient::getCategories();
|
||||
$ocs = $this->ocsClient->getCategories();
|
||||
if ($ocs) {
|
||||
foreach($ocs as $k => $v) {
|
||||
$categories[] = array(
|
||||
$categories[] = [
|
||||
'id' => $k,
|
||||
'displayName' => str_replace('ownCloud ', '', $v)
|
||||
);
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,7 +144,8 @@ class AppSettingsController extends Controller {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get all available categories
|
||||
* Get all available apps in a category
|
||||
*
|
||||
* @param int $category
|
||||
* @return array
|
||||
*/
|
||||
|
@ -134,16 +182,9 @@ class AppSettingsController extends Controller {
|
|||
});
|
||||
break;
|
||||
default:
|
||||
if ($category === 2) {
|
||||
$apps = \OC_App::getAppstoreApps('approved');
|
||||
if ($apps) {
|
||||
$apps = array_filter($apps, function ($app) {
|
||||
return isset($app['internalclass']) && $app['internalclass'] === 'recommendedapp';
|
||||
});
|
||||
}
|
||||
} else {
|
||||
$apps = \OC_App::getAppstoreApps('approved', $category);
|
||||
}
|
||||
$filter = $this->config->getSystemValue('appstore.experimental.enabled', false) ? 'all' : 'approved';
|
||||
|
||||
$apps = \OC_App::getAppstoreApps($filter, $category);
|
||||
if (!$apps) {
|
||||
$apps = array();
|
||||
} else {
|
||||
|
|
|
@ -210,6 +210,24 @@ span.version { margin-left:1em; margin-right:1em; color:#555; }
|
|||
opacity: .5;
|
||||
}
|
||||
|
||||
.app-level {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.app-level .official, .app-level .approved {
|
||||
background-color: #E8C805;
|
||||
border-radius: 2px;
|
||||
margin-left: 5px;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.app-level .experimental {
|
||||
background-color: #F02405;
|
||||
border-radius: 2px;
|
||||
margin-left: 5px;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
#apps-list {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
|
@ -236,6 +254,7 @@ span.version { margin-left:1em; margin-right:1em; color:#555; }
|
|||
.app-name,
|
||||
.app-version,
|
||||
.app-score,
|
||||
.app-level,
|
||||
.recommendedapp {
|
||||
display: inline-block;
|
||||
}
|
||||
|
@ -261,7 +280,7 @@ span.version { margin-left:1em; margin-right:1em; color:#555; }
|
|||
white-space: pre-line;
|
||||
}
|
||||
|
||||
#app-category-2 {
|
||||
#app-category-1 {
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,17 @@ Handlebars.registerHelper('score', function() {
|
|||
}
|
||||
return new Handlebars.SafeString('');
|
||||
});
|
||||
Handlebars.registerHelper('level', function() {
|
||||
if(typeof this.level !== 'undefined') {
|
||||
if(this.level === 200) {
|
||||
return new Handlebars.SafeString('<span class="official">Official</span>');
|
||||
} else if(this.level === 100) {
|
||||
return new Handlebars.SafeString('<span class="approved">Approved</span>');
|
||||
} else {
|
||||
return new Handlebars.SafeString('<span class="experimental">Experimental</span>');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
OC.Settings = OC.Settings || {};
|
||||
OC.Settings.Apps = OC.Settings.Apps || {
|
||||
|
@ -73,7 +84,6 @@ OC.Settings.Apps = OC.Settings.Apps || {
|
|||
this._loadCategoryCall = $.ajax(OC.generateUrl('settings/apps/list?category={categoryId}', {
|
||||
categoryId: categoryId
|
||||
}), {
|
||||
data:{},
|
||||
type:'GET',
|
||||
success: function (apps) {
|
||||
OC.Settings.Apps.State.apps = _.indexBy(apps.apps, 'id');
|
||||
|
@ -81,13 +91,27 @@ OC.Settings.Apps = OC.Settings.Apps || {
|
|||
var template = Handlebars.compile(source);
|
||||
|
||||
if (apps.apps.length) {
|
||||
apps.apps.sort(function(a,b) {
|
||||
return b.level - a.level;
|
||||
});
|
||||
|
||||
var firstExperimental = false;
|
||||
_.each(apps.apps, function(app) {
|
||||
OC.Settings.Apps.renderApp(app, template, null);
|
||||
if(app.level === 0 && firstExperimental === false) {
|
||||
firstExperimental = true;
|
||||
OC.Settings.Apps.renderApp(app, template, null, true);
|
||||
} else {
|
||||
OC.Settings.Apps.renderApp(app, template, null, false);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$('#apps-list').addClass('hidden');
|
||||
$('#apps-list-empty').removeClass('hidden');
|
||||
}
|
||||
|
||||
$('.app-level .official').tipsy({fallback: t('core', 'Official apps are developed by and within the ownCloud community and its GitHub repository and offer functionality central to ownCloud. They are ready for serious use.')});
|
||||
$('.app-level .approved').tipsy({fallback: t('core', 'Approved apps are developed by trusted developers and have passed a cursory security check. They are actively maintained in an open code repository and their maintainers deem them to be stable for casual to normal use.')});
|
||||
$('.app-level .experimental').tipsy({fallback: t('core', 'This app is not checked for security issues and is new or known to be unstable. Install on your own risk.')});
|
||||
},
|
||||
complete: function() {
|
||||
$('#apps-list').removeClass('icon-loading');
|
||||
|
@ -95,7 +119,7 @@ OC.Settings.Apps = OC.Settings.Apps || {
|
|||
});
|
||||
},
|
||||
|
||||
renderApp: function(app, template, selector) {
|
||||
renderApp: function(app, template, selector, firstExperimental) {
|
||||
if (!template) {
|
||||
var source = $("#app-template").html();
|
||||
template = Handlebars.compile(source);
|
||||
|
@ -103,6 +127,7 @@ OC.Settings.Apps = OC.Settings.Apps || {
|
|||
if (typeof app === 'string') {
|
||||
app = OC.Settings.Apps.State.apps[app];
|
||||
}
|
||||
app.firstExperimental = firstExperimental;
|
||||
|
||||
var html = template(app);
|
||||
if (selector) {
|
||||
|
@ -438,6 +463,16 @@ OC.Settings.Apps = OC.Settings.Apps || {
|
|||
$select.change();
|
||||
});
|
||||
|
||||
$(document).on('click', '#enable-experimental-apps', function () {
|
||||
var state = $('#enable-experimental-apps').prop('checked');
|
||||
$.ajax(OC.generateUrl('settings/apps/experimental'), {
|
||||
data: {state: state},
|
||||
type: 'POST',
|
||||
success:function () {
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -33,25 +33,27 @@
|
|||
namespace OC\Settings;
|
||||
|
||||
$application = new Application();
|
||||
$application->registerRoutes($this, array(
|
||||
'resources' => array(
|
||||
'groups' => array('url' => '/settings/users/groups'),
|
||||
'users' => array('url' => '/settings/users/users')
|
||||
),
|
||||
'routes' => array(
|
||||
array('name' => 'MailSettings#setMailSettings', 'url' => '/settings/admin/mailsettings', 'verb' => 'POST'),
|
||||
array('name' => 'MailSettings#storeCredentials', 'url' => '/settings/admin/mailsettings/credentials', 'verb' => 'POST'),
|
||||
array('name' => 'MailSettings#sendTestMail', 'url' => '/settings/admin/mailtest', 'verb' => 'POST'),
|
||||
array('name' => 'AppSettings#listCategories', 'url' => '/settings/apps/categories', 'verb' => 'GET'),
|
||||
array('name' => 'AppSettings#listApps', 'url' => '/settings/apps/list', 'verb' => 'GET'),
|
||||
array('name' => 'SecuritySettings#trustedDomains', 'url' => '/settings/admin/security/trustedDomains', 'verb' => 'POST'),
|
||||
array('name' => 'Users#setMailAddress', 'url' => '/settings/users/{id}/mailAddress', 'verb' => 'PUT'),
|
||||
array('name' => 'LogSettings#setLogLevel', 'url' => '/settings/admin/log/level', 'verb' => 'POST'),
|
||||
array('name' => 'LogSettings#getEntries', 'url' => '/settings/admin/log/entries', 'verb' => 'GET'),
|
||||
array('name' => 'LogSettings#download', 'url' => '/settings/admin/log/download', 'verb' => 'GET'),
|
||||
$application->registerRoutes($this, [
|
||||
'resources' => [
|
||||
'groups' => ['url' => '/settings/users/groups'],
|
||||
'users' => ['url' => '/settings/users/users']
|
||||
],
|
||||
'routes' => [
|
||||
['name' => 'MailSettings#setMailSettings', 'url' => '/settings/admin/mailsettings', 'verb' => 'POST'],
|
||||
['name' => 'MailSettings#storeCredentials', 'url' => '/settings/admin/mailsettings/credentials', 'verb' => 'POST'],
|
||||
['name' => 'MailSettings#sendTestMail', 'url' => '/settings/admin/mailtest', 'verb' => 'POST'],
|
||||
['name' => 'AppSettings#listCategories', 'url' => '/settings/apps/categories', 'verb' => 'GET'],
|
||||
['name' => 'AppSettings#viewApps', 'url' => '/settings/apps', 'verb' => 'GET'],
|
||||
['name' => 'AppSettings#listApps', 'url' => '/settings/apps/list', 'verb' => 'GET'],
|
||||
['name' => 'AppSettings#changeExperimentalConfigState', 'url' => '/settings/apps/experimental', 'verb' => 'POST'],
|
||||
['name' => 'SecuritySettings#trustedDomains', 'url' => '/settings/admin/security/trustedDomains', 'verb' => 'POST'],
|
||||
['name' => 'Users#setMailAddress', 'url' => '/settings/users/{id}/mailAddress', 'verb' => 'PUT'],
|
||||
['name' => 'LogSettings#setLogLevel', 'url' => '/settings/admin/log/level', 'verb' => 'POST'],
|
||||
['name' => 'LogSettings#getEntries', 'url' => '/settings/admin/log/entries', 'verb' => 'GET'],
|
||||
['name' => 'LogSettings#download', 'url' => '/settings/admin/log/download', 'verb' => 'GET'],
|
||||
['name' => 'CheckSetup#check', 'url' => '/settings/ajax/checksetup', 'verb' => 'GET'],
|
||||
)
|
||||
));
|
||||
]
|
||||
]);
|
||||
|
||||
/** @var $this \OCP\Route\IRouter */
|
||||
|
||||
|
@ -62,8 +64,6 @@ $this->create('settings_personal', '/settings/personal')
|
|||
->actionInclude('settings/personal.php');
|
||||
$this->create('settings_users', '/settings/users')
|
||||
->actionInclude('settings/users.php');
|
||||
$this->create('settings_apps', '/settings/apps')
|
||||
->actionInclude('settings/apps.php');
|
||||
$this->create('settings_admin', '/settings/admin')
|
||||
->actionInclude('settings/admin.php');
|
||||
// Settings ajax actions
|
||||
|
|
|
@ -1,3 +1,27 @@
|
|||
<?php
|
||||
style('settings', 'settings');
|
||||
vendor_style(
|
||||
'core',
|
||||
[
|
||||
'select2/select2',
|
||||
]
|
||||
);
|
||||
vendor_script(
|
||||
'core',
|
||||
[
|
||||
'handlebars/handlebars',
|
||||
'select2/select2'
|
||||
]
|
||||
);
|
||||
script(
|
||||
'settings',
|
||||
[
|
||||
'settings',
|
||||
'apps',
|
||||
]
|
||||
);
|
||||
/** @var array $_ */
|
||||
?>
|
||||
<script id="categories-template" type="text/x-handlebars-template">
|
||||
{{#each this}}
|
||||
<li id="app-category-{{id}}" data-category-id="{{id}}" tabindex="0">
|
||||
|
@ -16,6 +40,18 @@
|
|||
</script>
|
||||
|
||||
<script id="app-template" type="text/x-handlebars">
|
||||
{{#if firstExperimental}}
|
||||
<div style="background-color: lightyellow; border-top:1px solid black; border-bottom: 1px solid black;">
|
||||
<h2><?php p($l->t('Experimental applications ahead')) ?></h2>
|
||||
<p>
|
||||
<?php p($l->t('Experimental apps are not checked for security ' .
|
||||
'issues and are new or known to be unstable and under heavy ' .
|
||||
'development. Installing these can cause data loss or security ' .
|
||||
'breaches.')) ?>
|
||||
</p>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="section" id="app-{{id}}">
|
||||
{{#if preview}}
|
||||
<div class="app-image{{#if previewAsIcon}} app-image-icon{{/if}} hidden">
|
||||
|
@ -23,6 +59,9 @@
|
|||
{{/if}}
|
||||
<h2 class="app-name"><a href="{{detailpage}}" target="_blank">{{name}}</a></h2>
|
||||
<div class="app-version"> {{version}}</div>
|
||||
<div class="app-level">
|
||||
{{{level}}}
|
||||
</div>
|
||||
<div class="app-author"><?php p($l->t('by')); ?> {{author}}
|
||||
{{#if licence}}
|
||||
({{licence}}-<?php p($l->t('licensed')); ?>)
|
||||
|
@ -95,6 +134,24 @@
|
|||
<ul id="apps-categories">
|
||||
|
||||
</ul>
|
||||
<div id="app-settings">
|
||||
<div id="app-settings-header">
|
||||
<button class="settings-button" data-apps-slide-toggle="#app-settings-content"></button>
|
||||
</div>
|
||||
|
||||
<div id="app-settings-content" style="color: #c33">
|
||||
<input type="checkbox" id="enable-experimental-apps" <?php if($_['experimentalEnabled']) { print_unescaped('checked="checked"'); }?>>
|
||||
<label for="enable-experimental-apps"><?php p($l->t('Enable experimental apps')) ?></label>
|
||||
<p>
|
||||
<small>
|
||||
<?php p($l->t('Experimental apps are not checked for security ' .
|
||||
'issues and are new or known to be unstable and under heavy ' .
|
||||
'development. Installing these can cause data loss or security ' .
|
||||
'breaches.')) ?>
|
||||
</small>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="app-content">
|
||||
<div id="apps-list" class="icon-loading"></div>
|
||||
|
|
|
@ -0,0 +1,931 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use OC\OCSClient;
|
||||
use OCP\Http\Client\IClientService;
|
||||
use OCP\IConfig;
|
||||
use OCP\ILogger;
|
||||
|
||||
/**
|
||||
* Class OCSClientTest
|
||||
*/
|
||||
class OCSClientTest extends \Test\TestCase {
|
||||
/** @var OCSClient */
|
||||
private $ocsClient;
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
/** @var IClientService */
|
||||
private $clientService;
|
||||
/** @var ILogger */
|
||||
private $logger;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->config = $this->getMockBuilder('\OCP\IConfig')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->clientService = $this->getMock('\OCP\Http\Client\IClientService');
|
||||
$this->logger = $this->getMock('\OCP\ILogger');
|
||||
|
||||
$this->ocsClient = new OCSClient(
|
||||
$this->clientService,
|
||||
$this->config,
|
||||
$this->logger
|
||||
);
|
||||
}
|
||||
|
||||
public function testIsAppStoreEnabledSuccess() {
|
||||
$this->config
|
||||
->expects($this->once())
|
||||
->method('getSystemValue')
|
||||
->with('appstoreenabled', true)
|
||||
->will($this->returnValue(true));
|
||||
$this->assertTrue($this->ocsClient->isAppStoreEnabled());
|
||||
}
|
||||
|
||||
public function testIsAppStoreEnabledFail() {
|
||||
$this->config
|
||||
->expects($this->once())
|
||||
->method('getSystemValue')
|
||||
->with('appstoreenabled', true)
|
||||
->will($this->returnValue(false));
|
||||
$this->assertFalse($this->ocsClient->isAppStoreEnabled());
|
||||
}
|
||||
|
||||
public function testGetAppStoreUrl() {
|
||||
$this->config
|
||||
->expects($this->once())
|
||||
->method('getSystemValue')
|
||||
->with('appstoreurl', 'https://api.owncloud.com/v1')
|
||||
->will($this->returnValue('https://api.owncloud.com/v1'));
|
||||
$this->assertSame('https://api.owncloud.com/v1', Test_Helper::invokePrivate($this->ocsClient, 'getAppStoreUrl'));
|
||||
}
|
||||
|
||||
public function testGetCategoriesDisabledAppStore() {
|
||||
$this->config
|
||||
->expects($this->once())
|
||||
->method('getSystemValue')
|
||||
->with('appstoreenabled', true)
|
||||
->will($this->returnValue(false));
|
||||
$this->assertNull($this->ocsClient->getCategories());
|
||||
}
|
||||
|
||||
public function testGetCategoriesExceptionClient() {
|
||||
$this->config
|
||||
->expects($this->at(0))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreenabled', true)
|
||||
->will($this->returnValue(true));
|
||||
$this->config
|
||||
->expects($this->at(1))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreurl', 'https://api.owncloud.com/v1')
|
||||
->will($this->returnValue('https://api.owncloud.com/v1'));
|
||||
|
||||
$client = $this->getMock('\OCP\Http\Client\IClient');
|
||||
$client
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with(
|
||||
'https://api.owncloud.com/v1/content/categories',
|
||||
[
|
||||
'timeout' => 5,
|
||||
]
|
||||
)
|
||||
->will($this->throwException(new \Exception('TheErrorMessage')));
|
||||
|
||||
$this->clientService
|
||||
->expects($this->once())
|
||||
->method('newClient')
|
||||
->will($this->returnValue($client));
|
||||
|
||||
$this->logger
|
||||
->expects($this->once())
|
||||
->method('error')
|
||||
->with(
|
||||
'Could not get categories: TheErrorMessage',
|
||||
[
|
||||
'app' => 'core',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertNull($this->ocsClient->getCategories());
|
||||
}
|
||||
|
||||
public function testGetCategoriesParseError() {
|
||||
$this->config
|
||||
->expects($this->at(0))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreenabled', true)
|
||||
->will($this->returnValue(true));
|
||||
$this->config
|
||||
->expects($this->at(1))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreurl', 'https://api.owncloud.com/v1')
|
||||
->will($this->returnValue('https://api.owncloud.com/v1'));
|
||||
|
||||
$response = $this->getMock('\OCP\Http\Client\IResponse');
|
||||
$response
|
||||
->expects($this->once())
|
||||
->method('getBody')
|
||||
->will($this->returnValue('MyInvalidXml'));
|
||||
|
||||
$client = $this->getMock('\OCP\Http\Client\IClient');
|
||||
$client
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with(
|
||||
'https://api.owncloud.com/v1/content/categories',
|
||||
[
|
||||
'timeout' => 5,
|
||||
]
|
||||
)
|
||||
->will($this->returnValue($response));
|
||||
|
||||
$this->clientService
|
||||
->expects($this->once())
|
||||
->method('newClient')
|
||||
->will($this->returnValue($client));
|
||||
|
||||
$this->logger
|
||||
->expects($this->once())
|
||||
->method('error')
|
||||
->with(
|
||||
'Could not get categories, content was no valid XML',
|
||||
[
|
||||
'app' => 'core',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertNull($this->ocsClient->getCategories());
|
||||
}
|
||||
|
||||
public function testGetCategoriesSuccessful() {
|
||||
$this->config
|
||||
->expects($this->at(0))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreenabled', true)
|
||||
->will($this->returnValue(true));
|
||||
$this->config
|
||||
->expects($this->at(1))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreurl', 'https://api.owncloud.com/v1')
|
||||
->will($this->returnValue('https://api.owncloud.com/v1'));
|
||||
|
||||
$response = $this->getMock('\OCP\Http\Client\IResponse');
|
||||
$response
|
||||
->expects($this->once())
|
||||
->method('getBody')
|
||||
->will($this->returnValue('<?xml version="1.0"?>
|
||||
<ocs>
|
||||
<meta>
|
||||
<status>ok</status>
|
||||
<statuscode>100</statuscode>
|
||||
<message></message>
|
||||
<totalitems>6</totalitems>
|
||||
</meta>
|
||||
<data>
|
||||
<category>
|
||||
<id>920</id>
|
||||
<name>ownCloud Multimedia</name>
|
||||
</category>
|
||||
<category>
|
||||
<id>921</id>
|
||||
<name>ownCloud PIM</name>
|
||||
</category>
|
||||
<category>
|
||||
<id>922</id>
|
||||
<name>ownCloud Productivity</name>
|
||||
</category>
|
||||
<category>
|
||||
<id>923</id>
|
||||
<name>ownCloud Game</name>
|
||||
</category>
|
||||
<category>
|
||||
<id>924</id>
|
||||
<name>ownCloud Tool</name>
|
||||
</category>
|
||||
<category>
|
||||
<id>925</id>
|
||||
<name>ownCloud other</name>
|
||||
</category>
|
||||
</data>
|
||||
</ocs>
|
||||
'));
|
||||
|
||||
$client = $this->getMock('\OCP\Http\Client\IClient');
|
||||
$client
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with(
|
||||
'https://api.owncloud.com/v1/content/categories',
|
||||
[
|
||||
'timeout' => 5,
|
||||
]
|
||||
)
|
||||
->will($this->returnValue($response));
|
||||
|
||||
$this->clientService
|
||||
->expects($this->once())
|
||||
->method('newClient')
|
||||
->will($this->returnValue($client));
|
||||
|
||||
$expected = [
|
||||
920 => 'ownCloud Multimedia',
|
||||
921 => 'ownCloud PIM',
|
||||
922 => 'ownCloud Productivity',
|
||||
923 => 'ownCloud Game',
|
||||
924 => 'ownCloud Tool',
|
||||
925 => 'ownCloud other',
|
||||
];
|
||||
$this->assertSame($expected, $this->ocsClient->getCategories());
|
||||
}
|
||||
|
||||
public function testGetApplicationsDisabledAppStore() {
|
||||
$this->config
|
||||
->expects($this->once())
|
||||
->method('getSystemValue')
|
||||
->with('appstoreenabled', true)
|
||||
->will($this->returnValue(false));
|
||||
$this->assertSame([], $this->ocsClient->getApplications([], 1, 'approved'));
|
||||
}
|
||||
|
||||
public function testGetApplicationsExceptionClient() {
|
||||
$this->config
|
||||
->expects($this->at(0))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreenabled', true)
|
||||
->will($this->returnValue(true));
|
||||
$this->config
|
||||
->expects($this->at(1))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreurl', 'https://api.owncloud.com/v1')
|
||||
->will($this->returnValue('https://api.owncloud.com/v1'));
|
||||
|
||||
$client = $this->getMock('\OCP\Http\Client\IClient');
|
||||
$client
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with(
|
||||
'https://api.owncloud.com/v1/content/data',
|
||||
[
|
||||
'timeout' => 5,
|
||||
'query' => [
|
||||
'version' => implode('x', \OC_Util::getVersion()),
|
||||
'filter' => 'approved',
|
||||
'categories' => '815x1337',
|
||||
'sortmode' => 'new',
|
||||
'page' => 1,
|
||||
'pagesize' => 100,
|
||||
'approved' => 'approved',
|
||||
],
|
||||
]
|
||||
)
|
||||
->will($this->throwException(new \Exception('TheErrorMessage')));
|
||||
|
||||
$this->clientService
|
||||
->expects($this->once())
|
||||
->method('newClient')
|
||||
->will($this->returnValue($client));
|
||||
|
||||
$this->logger
|
||||
->expects($this->once())
|
||||
->method('error')
|
||||
->with(
|
||||
'Could not get applications: TheErrorMessage',
|
||||
[
|
||||
'app' => 'core',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertSame([], $this->ocsClient->getApplications([815, 1337], 1, 'approved'));
|
||||
}
|
||||
|
||||
public function testGetApplicationsParseError() {
|
||||
$this->config
|
||||
->expects($this->at(0))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreenabled', true)
|
||||
->will($this->returnValue(true));
|
||||
$this->config
|
||||
->expects($this->at(1))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreurl', 'https://api.owncloud.com/v1')
|
||||
->will($this->returnValue('https://api.owncloud.com/v1'));
|
||||
|
||||
$response = $this->getMock('\OCP\Http\Client\IResponse');
|
||||
$response
|
||||
->expects($this->once())
|
||||
->method('getBody')
|
||||
->will($this->returnValue('MyInvalidXml'));
|
||||
|
||||
$client = $this->getMock('\OCP\Http\Client\IClient');
|
||||
$client
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with(
|
||||
'https://api.owncloud.com/v1/content/data',
|
||||
[
|
||||
'timeout' => 5,
|
||||
'query' => [
|
||||
'version' => implode('x', \OC_Util::getVersion()),
|
||||
'filter' => 'approved',
|
||||
'categories' => '815x1337',
|
||||
'sortmode' => 'new',
|
||||
'page' => 1,
|
||||
'pagesize' => 100,
|
||||
'approved' => 'approved',
|
||||
],
|
||||
]
|
||||
)
|
||||
->will($this->returnValue($response));
|
||||
|
||||
$this->clientService
|
||||
->expects($this->once())
|
||||
->method('newClient')
|
||||
->will($this->returnValue($client));
|
||||
|
||||
$this->logger
|
||||
->expects($this->once())
|
||||
->method('error')
|
||||
->with(
|
||||
'Could not get applications, content was no valid XML',
|
||||
[
|
||||
'app' => 'core',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertSame([], $this->ocsClient->getApplications([815, 1337], 1, 'approved'));
|
||||
}
|
||||
|
||||
public function testGetApplicationsSuccessful() {
|
||||
$this->config
|
||||
->expects($this->at(0))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreenabled', true)
|
||||
->will($this->returnValue(true));
|
||||
$this->config
|
||||
->expects($this->at(1))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreurl', 'https://api.owncloud.com/v1')
|
||||
->will($this->returnValue('https://api.owncloud.com/v1'));
|
||||
|
||||
$response = $this->getMock('\OCP\Http\Client\IResponse');
|
||||
$response
|
||||
->expects($this->once())
|
||||
->method('getBody')
|
||||
->will($this->returnValue('<?xml version="1.0"?>
|
||||
<ocs>
|
||||
<meta>
|
||||
<status>ok</status>
|
||||
<statuscode>100</statuscode>
|
||||
<message></message>
|
||||
<totalitems>2</totalitems>
|
||||
<itemsperpage>100</itemsperpage>
|
||||
</meta>
|
||||
<data>
|
||||
<content details="summary">
|
||||
<id>168707</id>
|
||||
<name>Calendar 8.0</name>
|
||||
<version>0.6.4</version>
|
||||
<label>recommended</label>
|
||||
<changed>2015-02-09T15:23:56+01:00</changed>
|
||||
<created>2015-01-26T04:35:19+01:00</created>
|
||||
<typeid>921</typeid>
|
||||
<typename>ownCloud PIM</typename>
|
||||
<language></language>
|
||||
<personid>owncloud</personid>
|
||||
<profilepage>http://opendesktop.org/usermanager/search.php?username=owncloud</profilepage>
|
||||
<downloads>5393</downloads>
|
||||
<score>60</score>
|
||||
<description>Calendar App for ownCloud</description>
|
||||
<comments>7</comments>
|
||||
<fans>10</fans>
|
||||
<licensetype>16</licensetype>
|
||||
<approved>0</approved>
|
||||
<category>1</category>
|
||||
<license>AGPL</license>
|
||||
<preview1></preview1>
|
||||
<detailpage>https://apps.owncloud.com/content/show.php?content=168707</detailpage>
|
||||
<downloadtype1></downloadtype1>
|
||||
<downloadway1>0</downloadway1>
|
||||
<downloadprice1>0</downloadprice1>
|
||||
<downloadlink1>http://apps.owncloud.com/content/download.php?content=168707&id=1</downloadlink1>
|
||||
<downloadgpgsignature1></downloadgpgsignature1>
|
||||
<downloadgpgfingerprint1></downloadgpgfingerprint1>
|
||||
<downloadpackagename1></downloadpackagename1>
|
||||
<downloadrepository1></downloadrepository1>
|
||||
<downloadname1></downloadname1>
|
||||
<downloadsize1>885</downloadsize1>
|
||||
</content>
|
||||
<content details="summary">
|
||||
<id>168708</id>
|
||||
<name>Contacts 8.0</name>
|
||||
<version>0.3.0.18</version>
|
||||
<label>recommended</label>
|
||||
<changed>2015-02-09T15:18:58+01:00</changed>
|
||||
<created>2015-01-26T04:45:17+01:00</created>
|
||||
<typeid>921</typeid>
|
||||
<typename>ownCloud PIM</typename>
|
||||
<language></language>
|
||||
<personid>owncloud</personid>
|
||||
<profilepage>http://opendesktop.org/usermanager/search.php?username=owncloud</profilepage>
|
||||
<downloads>4237</downloads>
|
||||
<score>58</score>
|
||||
<description></description>
|
||||
<comments>3</comments>
|
||||
<fans>6</fans>
|
||||
<licensetype>16</licensetype>
|
||||
<approved>200</approved>
|
||||
<category>1</category>
|
||||
<license>AGPL</license>
|
||||
<preview1></preview1>
|
||||
<detailpage>https://apps.owncloud.com/content/show.php?content=168708</detailpage>
|
||||
<downloadtype1></downloadtype1>
|
||||
<downloadway1>0</downloadway1>
|
||||
<downloadprice1>0</downloadprice1>
|
||||
<downloadlink1>http://apps.owncloud.com/content/download.php?content=168708&id=1</downloadlink1>
|
||||
<downloadgpgsignature1></downloadgpgsignature1>
|
||||
<downloadgpgfingerprint1></downloadgpgfingerprint1>
|
||||
<downloadpackagename1></downloadpackagename1>
|
||||
<downloadrepository1></downloadrepository1>
|
||||
<downloadname1></downloadname1>
|
||||
<downloadsize1>1409</downloadsize1>
|
||||
</content>
|
||||
</data>
|
||||
</ocs> '));
|
||||
|
||||
$client = $this->getMock('\OCP\Http\Client\IClient');
|
||||
$client
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with(
|
||||
'https://api.owncloud.com/v1/content/data',
|
||||
[
|
||||
'timeout' => 5,
|
||||
'query' => [
|
||||
'version' => implode('x', \OC_Util::getVersion()),
|
||||
'filter' => 'approved',
|
||||
'categories' => '815x1337',
|
||||
'sortmode' => 'new',
|
||||
'page' => 1,
|
||||
'pagesize' => 100,
|
||||
'approved' => 'approved',
|
||||
],
|
||||
]
|
||||
)
|
||||
->will($this->returnValue($response));
|
||||
|
||||
$this->clientService
|
||||
->expects($this->once())
|
||||
->method('newClient')
|
||||
->will($this->returnValue($client));
|
||||
|
||||
$expected = [
|
||||
[
|
||||
'id' => '168707',
|
||||
'name' => 'Calendar 8.0',
|
||||
'label' => 'recommended',
|
||||
'version' => '0.6.4',
|
||||
'type' => '921',
|
||||
'typename' => 'ownCloud PIM',
|
||||
'personid' => 'owncloud',
|
||||
'license' => 'AGPL',
|
||||
'detailpage' => 'https://apps.owncloud.com/content/show.php?content=168707',
|
||||
'preview' => '',
|
||||
'preview-full' => '',
|
||||
'changed' => 1423491836,
|
||||
'description' => 'Calendar App for ownCloud',
|
||||
'score' => '60',
|
||||
'downloads' => 5393,
|
||||
'level' => 0,
|
||||
],
|
||||
[
|
||||
'id' => '168708',
|
||||
'name' => 'Contacts 8.0',
|
||||
'label' => 'recommended',
|
||||
'version' => '0.3.0.18',
|
||||
'type' => '921',
|
||||
'typename' => 'ownCloud PIM',
|
||||
'personid' => 'owncloud',
|
||||
'license' => 'AGPL',
|
||||
'detailpage' => 'https://apps.owncloud.com/content/show.php?content=168708',
|
||||
'preview' => '',
|
||||
'preview-full' => '',
|
||||
'changed' => 1423491538,
|
||||
'description' => '',
|
||||
'score' => '58',
|
||||
'downloads' => 4237,
|
||||
'level' => 200,
|
||||
],
|
||||
];
|
||||
$this->assertEquals($expected, $this->ocsClient->getApplications([815, 1337], 1, 'approved'));
|
||||
}
|
||||
|
||||
public function tesGetApplicationDisabledAppStore() {
|
||||
$this->config
|
||||
->expects($this->once())
|
||||
->method('getSystemValue')
|
||||
->with('appstoreenabled', true)
|
||||
->will($this->returnValue(false));
|
||||
$this->assertNull($this->ocsClient->getApplication('MyId'));
|
||||
}
|
||||
|
||||
public function testGetApplicationExceptionClient() {
|
||||
$this->config
|
||||
->expects($this->at(0))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreenabled', true)
|
||||
->will($this->returnValue(true));
|
||||
$this->config
|
||||
->expects($this->at(1))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreurl', 'https://api.owncloud.com/v1')
|
||||
->will($this->returnValue('https://api.owncloud.com/v1'));
|
||||
|
||||
$client = $this->getMock('\OCP\Http\Client\IClient');
|
||||
$client
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with(
|
||||
'https://api.owncloud.com/v1/content/data/MyId',
|
||||
[
|
||||
'timeout' => 5,
|
||||
]
|
||||
)
|
||||
->will($this->throwException(new \Exception('TheErrorMessage')));
|
||||
|
||||
$this->clientService
|
||||
->expects($this->once())
|
||||
->method('newClient')
|
||||
->will($this->returnValue($client));
|
||||
|
||||
$this->logger
|
||||
->expects($this->once())
|
||||
->method('error')
|
||||
->with(
|
||||
'Could not get application: TheErrorMessage',
|
||||
[
|
||||
'app' => 'core',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertNull($this->ocsClient->getApplication('MyId'));
|
||||
}
|
||||
|
||||
public function testGetApplicationParseError() {
|
||||
$this->config
|
||||
->expects($this->at(0))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreenabled', true)
|
||||
->will($this->returnValue(true));
|
||||
$this->config
|
||||
->expects($this->at(1))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreurl', 'https://api.owncloud.com/v1')
|
||||
->will($this->returnValue('https://api.owncloud.com/v1'));
|
||||
|
||||
$response = $this->getMock('\OCP\Http\Client\IResponse');
|
||||
$response
|
||||
->expects($this->once())
|
||||
->method('getBody')
|
||||
->will($this->returnValue('MyInvalidXml'));
|
||||
|
||||
$client = $this->getMock('\OCP\Http\Client\IClient');
|
||||
$client
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with(
|
||||
'https://api.owncloud.com/v1/content/data/MyId',
|
||||
[
|
||||
'timeout' => 5,
|
||||
]
|
||||
)
|
||||
->will($this->returnValue($response));
|
||||
|
||||
$this->clientService
|
||||
->expects($this->once())
|
||||
->method('newClient')
|
||||
->will($this->returnValue($client));
|
||||
|
||||
$this->logger
|
||||
->expects($this->once())
|
||||
->method('error')
|
||||
->with(
|
||||
'Could not get application, content was no valid XML',
|
||||
[
|
||||
'app' => 'core',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertNull($this->ocsClient->getApplication('MyId'));
|
||||
}
|
||||
|
||||
public function testGetApplicationSuccessful() {
|
||||
$this->config
|
||||
->expects($this->at(0))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreenabled', true)
|
||||
->will($this->returnValue(true));
|
||||
$this->config
|
||||
->expects($this->at(1))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreurl', 'https://api.owncloud.com/v1')
|
||||
->will($this->returnValue('https://api.owncloud.com/v1'));
|
||||
|
||||
$response = $this->getMock('\OCP\Http\Client\IResponse');
|
||||
$response
|
||||
->expects($this->once())
|
||||
->method('getBody')
|
||||
->will($this->returnValue('<?xml version="1.0"?>
|
||||
<ocs>
|
||||
<meta>
|
||||
<status>ok</status>
|
||||
<statuscode>100</statuscode>
|
||||
<message></message>
|
||||
</meta>
|
||||
<data>
|
||||
<content details="full">
|
||||
<id>166053</id>
|
||||
<name>Versioning</name>
|
||||
<version>0.0.1</version>
|
||||
<label>recommended</label>
|
||||
<typeid>925</typeid>
|
||||
<typename>ownCloud other</typename>
|
||||
<language></language>
|
||||
<personid>owncloud</personid>
|
||||
<profilepage>http://opendesktop.org/usermanager/search.php?username=owncloud</profilepage>
|
||||
<created>2014-07-07T16:34:40+02:00</created>
|
||||
<changed>2014-07-07T16:34:40+02:00</changed>
|
||||
<downloads>140</downloads>
|
||||
<score>50</score>
|
||||
<description>Placeholder for future updates</description>
|
||||
<summary></summary>
|
||||
<feedbackurl></feedbackurl>
|
||||
<changelog></changelog>
|
||||
<homepage></homepage>
|
||||
<homepagetype></homepagetype>
|
||||
<homepage2></homepage2>
|
||||
<homepagetype2></homepagetype2>
|
||||
<homepage3></homepage3>
|
||||
<homepagetype3></homepagetype3>
|
||||
<homepage4></homepage4>
|
||||
<homepagetype4></homepagetype4>
|
||||
<homepage5></homepage5>
|
||||
<homepagetype5></homepagetype5>
|
||||
<homepage6></homepage6>
|
||||
<homepagetype6></homepagetype6>
|
||||
<homepage7></homepage7>
|
||||
<homepagetype7></homepagetype7>
|
||||
<homepage8></homepage8>
|
||||
<homepagetype8></homepagetype8>
|
||||
<homepage9></homepage9>
|
||||
<homepagetype9></homepagetype9>
|
||||
<homepage10></homepage10>
|
||||
<homepagetype10></homepagetype10>
|
||||
<licensetype>16</licensetype>
|
||||
<license>AGPL</license>
|
||||
<donationpage></donationpage>
|
||||
<comments>0</comments>
|
||||
<commentspage>http://apps.owncloud.com/content/show.php?content=166053</commentspage>
|
||||
<fans>0</fans>
|
||||
<fanspage>http://apps.owncloud.com/content/show.php?action=fan&content=166053</fanspage>
|
||||
<knowledgebaseentries>0</knowledgebaseentries>
|
||||
<knowledgebasepage>http://apps.owncloud.com/content/show.php?action=knowledgebase&content=166053</knowledgebasepage>
|
||||
<depend>ownCloud 7</depend>
|
||||
<preview1></preview1>
|
||||
<preview2></preview2>
|
||||
<preview3></preview3>
|
||||
<previewpic1></previewpic1>
|
||||
<previewpic2></previewpic2>
|
||||
<previewpic3></previewpic3>
|
||||
<picsmall1></picsmall1>
|
||||
<picsmall2></picsmall2>
|
||||
<picsmall3></picsmall3>
|
||||
<detailpage>https://apps.owncloud.com/content/show.php?content=166053</detailpage>
|
||||
<downloadtype1></downloadtype1>
|
||||
<downloadprice1>0</downloadprice1>
|
||||
<downloadlink1>http://apps.owncloud.com/content/download.php?content=166053&id=1</downloadlink1>
|
||||
<downloadname1></downloadname1>
|
||||
<downloadgpgfingerprint1></downloadgpgfingerprint1>
|
||||
<downloadgpgsignature1></downloadgpgsignature1>
|
||||
<downloadpackagename1></downloadpackagename1>
|
||||
<downloadrepository1></downloadrepository1>
|
||||
<downloadsize1>1</downloadsize1>
|
||||
</content>
|
||||
</data>
|
||||
</ocs>
|
||||
'));
|
||||
|
||||
$client = $this->getMock('\OCP\Http\Client\IClient');
|
||||
$client
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with(
|
||||
'https://api.owncloud.com/v1/content/data/MyId',
|
||||
[
|
||||
'timeout' => 5,
|
||||
]
|
||||
)
|
||||
->will($this->returnValue($response));
|
||||
|
||||
$this->clientService
|
||||
->expects($this->once())
|
||||
->method('newClient')
|
||||
->will($this->returnValue($client));
|
||||
|
||||
$expected = [
|
||||
'id' => 166053,
|
||||
'name' => 'Versioning',
|
||||
'version' => '0.0.1',
|
||||
'type' => '925',
|
||||
'label' => 'recommended',
|
||||
'typename' => 'ownCloud other',
|
||||
'personid' => 'owncloud',
|
||||
'detailpage' => 'https://apps.owncloud.com/content/show.php?content=166053',
|
||||
'preview1' => '',
|
||||
'preview2' => '',
|
||||
'preview3' => '',
|
||||
'changed' => 1404743680,
|
||||
'description' => 'Placeholder for future updates',
|
||||
'score' => 50,
|
||||
];
|
||||
$this->assertSame($expected, $this->ocsClient->getApplication('MyId'));
|
||||
}
|
||||
|
||||
public function testGetApplicationDownloadDisabledAppStore() {
|
||||
$this->config
|
||||
->expects($this->once())
|
||||
->method('getSystemValue')
|
||||
->with('appstoreenabled', true)
|
||||
->will($this->returnValue(false));
|
||||
$this->assertNull($this->ocsClient->getApplicationDownload('MyId'));
|
||||
}
|
||||
|
||||
public function testGetApplicationDownloadExceptionClient() {
|
||||
$this->config
|
||||
->expects($this->at(0))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreenabled', true)
|
||||
->will($this->returnValue(true));
|
||||
$this->config
|
||||
->expects($this->at(1))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreurl', 'https://api.owncloud.com/v1')
|
||||
->will($this->returnValue('https://api.owncloud.com/v1'));
|
||||
|
||||
$client = $this->getMock('\OCP\Http\Client\IClient');
|
||||
$client
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with(
|
||||
'https://api.owncloud.com/v1/content/download/MyId/1',
|
||||
[
|
||||
'timeout' => 5,
|
||||
]
|
||||
)
|
||||
->will($this->throwException(new \Exception('TheErrorMessage')));
|
||||
|
||||
$this->clientService
|
||||
->expects($this->once())
|
||||
->method('newClient')
|
||||
->will($this->returnValue($client));
|
||||
|
||||
$this->logger
|
||||
->expects($this->once())
|
||||
->method('error')
|
||||
->with(
|
||||
'Could not get application download URL: TheErrorMessage',
|
||||
[
|
||||
'app' => 'core',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertNull($this->ocsClient->getApplicationDownload('MyId'));
|
||||
}
|
||||
|
||||
public function testGetApplicationDownloadParseError() {
|
||||
$this->config
|
||||
->expects($this->at(0))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreenabled', true)
|
||||
->will($this->returnValue(true));
|
||||
$this->config
|
||||
->expects($this->at(1))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreurl', 'https://api.owncloud.com/v1')
|
||||
->will($this->returnValue('https://api.owncloud.com/v1'));
|
||||
|
||||
$response = $this->getMock('\OCP\Http\Client\IResponse');
|
||||
$response
|
||||
->expects($this->once())
|
||||
->method('getBody')
|
||||
->will($this->returnValue('MyInvalidXml'));
|
||||
|
||||
$client = $this->getMock('\OCP\Http\Client\IClient');
|
||||
$client
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with(
|
||||
'https://api.owncloud.com/v1/content/download/MyId/1',
|
||||
[
|
||||
'timeout' => 5,
|
||||
]
|
||||
)
|
||||
->will($this->returnValue($response));
|
||||
|
||||
$this->clientService
|
||||
->expects($this->once())
|
||||
->method('newClient')
|
||||
->will($this->returnValue($client));
|
||||
|
||||
$this->logger
|
||||
->expects($this->once())
|
||||
->method('error')
|
||||
->with(
|
||||
'Could not get application download URL, content was no valid XML',
|
||||
[
|
||||
'app' => 'core',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertNull($this->ocsClient->getApplicationDownload('MyId'));
|
||||
}
|
||||
|
||||
public function testGetApplicationDownloadUrlSuccessful() {
|
||||
$this->config
|
||||
->expects($this->at(0))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreenabled', true)
|
||||
->will($this->returnValue(true));
|
||||
$this->config
|
||||
->expects($this->at(1))
|
||||
->method('getSystemValue')
|
||||
->with('appstoreurl', 'https://api.owncloud.com/v1')
|
||||
->will($this->returnValue('https://api.owncloud.com/v1'));
|
||||
|
||||
$response = $this->getMock('\OCP\Http\Client\IResponse');
|
||||
$response
|
||||
->expects($this->once())
|
||||
->method('getBody')
|
||||
->will($this->returnValue('<?xml version="1.0"?>
|
||||
<ocs>
|
||||
<meta>
|
||||
<status>ok</status>
|
||||
<statuscode>100</statuscode>
|
||||
<message></message>
|
||||
</meta>
|
||||
<data>
|
||||
<content details="download">
|
||||
<downloadlink>https://apps.owncloud.com/CONTENT/content-files/166052-files_trashbin.zip</downloadlink>
|
||||
<mimetype>application/zip</mimetype>
|
||||
<gpgfingerprint></gpgfingerprint>
|
||||
<gpgsignature></gpgsignature>
|
||||
<packagename></packagename>
|
||||
<repository></repository>
|
||||
</content>
|
||||
</data>
|
||||
</ocs>
|
||||
'));
|
||||
|
||||
$client = $this->getMock('\OCP\Http\Client\IClient');
|
||||
$client
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with(
|
||||
'https://api.owncloud.com/v1/content/download/MyId/1',
|
||||
[
|
||||
'timeout' => 5,
|
||||
]
|
||||
)
|
||||
->will($this->returnValue($response));
|
||||
|
||||
$this->clientService
|
||||
->expects($this->once())
|
||||
->method('newClient')
|
||||
->will($this->returnValue($client));
|
||||
|
||||
$expected = [
|
||||
'downloadlink' => 'https://apps.owncloud.com/CONTENT/content-files/166052-files_trashbin.zip',
|
||||
];
|
||||
$this->assertSame($expected, $this->ocsClient->getApplicationDownload('MyId'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,231 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\Settings\Controller;
|
||||
|
||||
use OCP\AppFramework\Http\ContentSecurityPolicy;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use Test\TestCase;
|
||||
use OCP\IRequest;
|
||||
use OCP\IL10N;
|
||||
use OCP\IConfig;
|
||||
use OCP\ICache;
|
||||
use OCP\INavigationManager;
|
||||
use OCP\App\IAppManager;
|
||||
use OC\OCSClient;
|
||||
|
||||
/**
|
||||
* Class AppSettingsControllerTest
|
||||
*
|
||||
* @package OC\Settings\Controller
|
||||
*/
|
||||
class AppSettingsControllerTest extends TestCase {
|
||||
/** @var AppSettingsController */
|
||||
private $appSettingsController;
|
||||
/** @var IRequest */
|
||||
private $request;
|
||||
/** @var IL10N */
|
||||
private $l10n;
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
/** @var ICache */
|
||||
private $cache;
|
||||
/** @var INavigationManager */
|
||||
private $navigationManager;
|
||||
/** @var IAppManager */
|
||||
private $appManager;
|
||||
/** @var OCSClient */
|
||||
private $ocsClient;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->request = $this->getMockBuilder('\OCP\IRequest')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->l10n = $this->getMockBuilder('\OCP\IL10N')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->l10n->expects($this->any())
|
||||
->method('t')
|
||||
->will($this->returnArgument(0));
|
||||
$this->config = $this->getMockBuilder('\OCP\IConfig')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$cacheFactory = $this->getMockBuilder('\OCP\ICacheFactory')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->cache = $this->getMockBuilder('\OCP\ICache')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$cacheFactory
|
||||
->expects($this->once())
|
||||
->method('create')
|
||||
->with('settings')
|
||||
->will($this->returnValue($this->cache));
|
||||
|
||||
$this->navigationManager = $this->getMockBuilder('\OCP\INavigationManager')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->appManager = $this->getMockBuilder('\OCP\App\IAppManager')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->ocsClient = $this->getMockBuilder('\OC\OCSClient')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
|
||||
$this->appSettingsController = new AppSettingsController(
|
||||
'settings',
|
||||
$this->request,
|
||||
$this->l10n,
|
||||
$this->config,
|
||||
$cacheFactory,
|
||||
$this->navigationManager,
|
||||
$this->appManager,
|
||||
$this->ocsClient
|
||||
);
|
||||
}
|
||||
|
||||
public function testChangeExperimentalConfigStateTrue() {
|
||||
$this->config
|
||||
->expects($this->once())
|
||||
->method('setSystemValue')
|
||||
->with('appstore.experimental.enabled', true);
|
||||
$this->appManager
|
||||
->expects($this->once())
|
||||
->method('clearAppsCache');
|
||||
$this->assertEquals(new DataResponse(), $this->appSettingsController->changeExperimentalConfigState(true));
|
||||
}
|
||||
|
||||
public function testChangeExperimentalConfigStateFalse() {
|
||||
$this->config
|
||||
->expects($this->once())
|
||||
->method('setSystemValue')
|
||||
->with('appstore.experimental.enabled', false);
|
||||
$this->appManager
|
||||
->expects($this->once())
|
||||
->method('clearAppsCache');
|
||||
$this->assertEquals(new DataResponse(), $this->appSettingsController->changeExperimentalConfigState(false));
|
||||
}
|
||||
|
||||
public function testListCategoriesCached() {
|
||||
$this->cache
|
||||
->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->with('listCategories')
|
||||
->will($this->returnValue(['CachedArray']));
|
||||
$this->assertSame(['CachedArray'], $this->appSettingsController->listCategories());
|
||||
}
|
||||
|
||||
public function testListCategoriesNotCachedWithoutAppStore() {
|
||||
$expected = [
|
||||
[
|
||||
'id' => 0,
|
||||
'displayName' => 'Enabled',
|
||||
],
|
||||
[
|
||||
'id' => 1,
|
||||
'displayName' => 'Not enabled',
|
||||
],
|
||||
];
|
||||
$this->cache
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with('listCategories')
|
||||
->will($this->returnValue(null));
|
||||
$this->cache
|
||||
->expects($this->once())
|
||||
->method('set')
|
||||
->with('listCategories', $expected, 3600);
|
||||
|
||||
|
||||
$this->assertSame($expected, $this->appSettingsController->listCategories());
|
||||
}
|
||||
|
||||
public function testListCategoriesNotCachedWithAppStore() {
|
||||
$expected = [
|
||||
[
|
||||
'id' => 0,
|
||||
'displayName' => 'Enabled',
|
||||
],
|
||||
[
|
||||
'id' => 1,
|
||||
'displayName' => 'Not enabled',
|
||||
],
|
||||
[
|
||||
'id' => 0,
|
||||
'displayName' => 'Tools',
|
||||
],
|
||||
[
|
||||
'id' => 1,
|
||||
'displayName' => 'Awesome Games',
|
||||
],
|
||||
[
|
||||
'id' => 2,
|
||||
'displayName' => 'PIM',
|
||||
],
|
||||
[
|
||||
'id' => 3,
|
||||
'displayName' => 'Papershop',
|
||||
],
|
||||
];
|
||||
|
||||
$this->cache
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with('listCategories')
|
||||
->will($this->returnValue(null));
|
||||
$this->cache
|
||||
->expects($this->once())
|
||||
->method('set')
|
||||
->with('listCategories', $expected, 3600);
|
||||
|
||||
$this->ocsClient
|
||||
->expects($this->once())
|
||||
->method('isAppStoreEnabled')
|
||||
->will($this->returnValue(true));
|
||||
$this->ocsClient
|
||||
->expects($this->once())
|
||||
->method('getCategories')
|
||||
->will($this->returnValue(
|
||||
[
|
||||
'ownCloud Tools',
|
||||
'Awesome Games',
|
||||
'ownCloud PIM',
|
||||
'Papershop',
|
||||
]
|
||||
));
|
||||
|
||||
$this->assertSame($expected, $this->appSettingsController->listCategories());
|
||||
}
|
||||
|
||||
public function testViewApps() {
|
||||
$this->config
|
||||
->expects($this->once())
|
||||
->method('getSystemValue')
|
||||
->with('appstore.experimental.enabled', false);
|
||||
$this->navigationManager
|
||||
->expects($this->once())
|
||||
->method('setActiveEntry')
|
||||
->with('core_apps');
|
||||
|
||||
$policy = new ContentSecurityPolicy();
|
||||
$policy->addAllowedImageDomain('https://apps.owncloud.com');
|
||||
|
||||
$expected = new TemplateResponse('settings', 'apps', ['experimentalEnabled' => false], 'user');
|
||||
$expected->setContentSecurityPolicy($policy);
|
||||
|
||||
$this->assertEquals($expected, $this->appSettingsController->viewApps());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue