From 8835076f8c63e736a38904cb3aff6156568dfdf0 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Tue, 7 Jul 2015 17:29:54 +0200 Subject: [PATCH] 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. --- lib/base.php | 20 ++++++++++-- settings/js/apps.js | 77 ++++++++++++++++++++++++++++++--------------- 2 files changed, 70 insertions(+), 27 deletions(-) diff --git a/lib/base.php b/lib/base.php index df4e91dda9f8..6da3deb5d2a9 100644 --- a/lib/base.php +++ b/lib/base.php @@ -823,12 +823,28 @@ public static function handleRequest() { exit(); } - $request = \OC::$server->getRequest()->getPathInfo(); - if (substr($request, -3) !== '.js') { // we need these files during the upgrade + $request = \OC::$server->getRequest(); + $requestPath = $request->getPathInfo(); + if (substr($requestPath, -3) !== '.js') { // we need these files during the upgrade self::checkMaintenanceMode(); self::checkUpgrade(); } + // emergency app disabling + if ($requestPath === '/disableapp' + && $request->getMethod() === 'POST' + && $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 OC_App::loadApps(['authentication']); diff --git a/settings/js/apps.js b/settings/js/apps.js index a99df65e3c19..520a6add7e44 100644 --- a/settings/js/apps.js +++ b/settings/js/apps.js @@ -212,7 +212,19 @@ OC.Settings.Apps = OC.Settings.Apps || { 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) { + var self = this; OC.Settings.Apps.hideErrorMessage(appId); groups = groups || []; var appItem = $('div#app-'+appId+''); @@ -242,6 +254,8 @@ OC.Settings.Apps = OC.Settings.Apps || { } },'json'); } 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) { if(!result || result.status !== 'success') { if (result.data && result.data.message) { @@ -254,35 +268,48 @@ OC.Settings.Apps = OC.Settings.Apps || { element.val(t('settings','Enable')); appItem.addClass('appwarning'); } else { - if (result.data.update_required) { - OC.Settings.Apps.showReloadMessage(); + self._checkServerHealth().done(function() { + if (result.data.update_required) { + OC.Settings.Apps.showReloadMessage(); - setTimeout(function() { - location.reload(); - }, 5000); - } + setTimeout(function() { + location.reload(); + }, 5000); + } - OC.Settings.Apps.rebuildNavigation(); - appItem.data('active',true); - element.data('active',true); - appItem.addClass('active'); - element.val(t('settings','Disable')); - var app = OC.Settings.Apps.State.apps[appId]; - app.active = true; - - if (OC.Settings.Apps.isType(app, 'filesystem') || OC.Settings.Apps.isType(app, 'prelogin') || - OC.Settings.Apps.isType(app, 'authentication') || OC.Settings.Apps.isType(app, 'logging')) { - element.parent().find(".groups-enable").attr('checked', null); - element.parent().find(".groups-enable").hide(); - element.parent().find('#group_select').hide().val(null); - } else { - element.parent().find("#groups-enable").show(); - if (groups) { - appItem.data('groups', JSON.stringify(groups)); + OC.Settings.Apps.rebuildNavigation(); + appItem.data('active',true); + element.data('active',true); + appItem.addClass('active'); + element.val(t('settings','Disable')); + var app = OC.Settings.Apps.State.apps[appId]; + app.active = true; + + if (OC.Settings.Apps.isType(app, 'filesystem') || OC.Settings.Apps.isType(app, 'prelogin') || + OC.Settings.Apps.isType(app, 'authentication') || OC.Settings.Apps.isType(app, 'logging')) { + element.parent().find(".groups-enable").attr('checked', null); + element.parent().find(".groups-enable").hide(); + element.parent().find('#group_select').hide().val(null); } else { - appItem.data('groups', ''); + element.parent().find("#groups-enable").show(); + if (groups) { + appItem.data('groups', JSON.stringify(groups)); + } else { + 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 disabling app')); + element.val(t('settings','Enable')); + appItem.addClass('appwarning'); + }); + }); } },'json') .fail(function() {