Disable app that bricks the server after enabling

If an app is getting enabled in the web UI, an ajax call is now made to
make sure the server still works. If it doesn't, it sends an emergency
app disabling call to disable the breaking app.
This commit is contained in:
Vincent Petry 2015-07-07 17:29:54 +02:00
parent 32f4bea0ae
commit 1dbe240b0e
2 changed files with 80 additions and 30 deletions

View File

@ -823,12 +823,28 @@ class OC {
exit(); exit();
} }
$request = \OC::$server->getRequest()->getPathInfo(); $request = \OC::$server->getRequest();
if (substr($request, -3) !== '.js') { // we need these files during the upgrade $requestPath = $request->getPathInfo();
if (substr($requestPath, -3) !== '.js') { // we need these files during the upgrade
self::checkMaintenanceMode(); self::checkMaintenanceMode();
self::checkUpgrade(); self::checkUpgrade();
} }
// emergency app disabling
if ($requestPath === '/disableapp'
&& $request->getMethod() === 'POST'
&& ((string)$request->getParam('appid')) !== ''
) {
\OCP\JSON::callCheck();
\OCP\JSON::checkAdminUser();
$appId = (string)$request->getParam('appid');
$appId = \OC_App::cleanAppId($appId);
\OC_App::disable($appId);
\OC_JSON::success();
exit();
}
// Always load authentication apps // Always load authentication apps
OC_App::loadApps(['authentication']); OC_App::loadApps(['authentication']);

View File

@ -212,7 +212,19 @@ OC.Settings.Apps = OC.Settings.Apps || {
return app.types && app.types.indexOf(type) !== -1; return app.types && app.types.indexOf(type) !== -1;
}, },
/**
* Checks the server health.
*
* If the promise fails, the server is broken.
*
* @return {Promise} promise
*/
_checkServerHealth: function() {
return $.get(OC.generateUrl('apps/files'));
},
enableApp:function(appId, active, element, groups) { enableApp:function(appId, active, element, groups) {
var self = this;
OC.Settings.Apps.hideErrorMessage(appId); OC.Settings.Apps.hideErrorMessage(appId);
groups = groups || []; groups = groups || [];
var appItem = $('div#app-'+appId+''); var appItem = $('div#app-'+appId+'');
@ -242,6 +254,8 @@ OC.Settings.Apps = OC.Settings.Apps || {
} }
},'json'); },'json');
} else { } else {
// TODO: display message to admin to not refresh the page!
// TODO: lock UI to prevent further operations
$.post(OC.filePath('settings','ajax','enableapp.php'),{appid: appId, groups: groups},function(result) { $.post(OC.filePath('settings','ajax','enableapp.php'),{appid: appId, groups: groups},function(result) {
if(!result || result.status !== 'success') { if(!result || result.status !== 'success') {
if (result.data && result.data.message) { if (result.data && result.data.message) {
@ -254,6 +268,7 @@ OC.Settings.Apps = OC.Settings.Apps || {
element.val(t('settings','Enable')); element.val(t('settings','Enable'));
appItem.addClass('appwarning'); appItem.addClass('appwarning');
} else { } else {
self._checkServerHealth().done(function() {
if (result.data.update_required) { if (result.data.update_required) {
OC.Settings.Apps.showReloadMessage(); OC.Settings.Apps.showReloadMessage();
@ -283,6 +298,25 @@ OC.Settings.Apps = OC.Settings.Apps || {
appItem.data('groups', ''); appItem.data('groups', '');
} }
} }
}).fail(function() {
// server borked, emergency disable app
$.post(OC.webroot + '/index.php/disableapp', {appid: appId}, function() {
OC.Settings.Apps.showErrorMessage(
appId,
t('settings', 'Error: this app cannot be enabled because it makes the server unstable')
);
appItem.data('errormsg', t('settings', 'Error while enabling app'));
element.val(t('settings','Enable'));
appItem.addClass('appwarning');
}).fail(function() {
OC.Settings.Apps.showErrorMessage(
appId,
t('settings', 'Error: could not disable broken app')
);
appItem.data('errormsg', t('settings', 'Error while disabling broken app'));
element.val(t('settings','Enable'));
});
});
} }
},'json') },'json')
.fail(function() { .fail(function() {