mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-18 12:52:42 +01:00
When Phabricator is in read-only mode, explain why
Summary: Ref T4571. Allows users to click the "read-only mode" notification to get more information about why an install is in read-only mode. Installs can be in this mode for several reasons (explicit administrative action, no masters defined, no masters reachable), and it's useful to be able to tell the difference. Test Plan: {F1212930} Reviewers: chad Reviewed By: chad Maniphest Tasks: T4571 Differential Revision: https://secure.phabricator.com/D15671
This commit is contained in:
parent
c178f29cdb
commit
071741c61d
8 changed files with 103 additions and 14 deletions
|
@ -8,7 +8,7 @@
|
||||||
return array(
|
return array(
|
||||||
'names' => array(
|
'names' => array(
|
||||||
'core.pkg.css' => '35e4a99a',
|
'core.pkg.css' => '35e4a99a',
|
||||||
'core.pkg.js' => '8a616602',
|
'core.pkg.js' => '08b41036',
|
||||||
'darkconsole.pkg.js' => 'e7393ebb',
|
'darkconsole.pkg.js' => 'e7393ebb',
|
||||||
'differential.pkg.css' => '7ba78475',
|
'differential.pkg.css' => '7ba78475',
|
||||||
'differential.pkg.js' => 'd0cd0df6',
|
'differential.pkg.js' => 'd0cd0df6',
|
||||||
|
@ -494,7 +494,7 @@ return array(
|
||||||
'rsrc/js/core/behavior-oncopy.js' => '2926fff2',
|
'rsrc/js/core/behavior-oncopy.js' => '2926fff2',
|
||||||
'rsrc/js/core/behavior-phabricator-nav.js' => '56a1ca03',
|
'rsrc/js/core/behavior-phabricator-nav.js' => '56a1ca03',
|
||||||
'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => '340c8eff',
|
'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => '340c8eff',
|
||||||
'rsrc/js/core/behavior-read-only-warning.js' => 'f8ea359c',
|
'rsrc/js/core/behavior-read-only-warning.js' => 'ba158207',
|
||||||
'rsrc/js/core/behavior-refresh-csrf.js' => 'ab2f381b',
|
'rsrc/js/core/behavior-refresh-csrf.js' => 'ab2f381b',
|
||||||
'rsrc/js/core/behavior-remarkup-preview.js' => '4b700e9e',
|
'rsrc/js/core/behavior-remarkup-preview.js' => '4b700e9e',
|
||||||
'rsrc/js/core/behavior-reorder-applications.js' => '76b9fc3e',
|
'rsrc/js/core/behavior-reorder-applications.js' => '76b9fc3e',
|
||||||
|
@ -667,7 +667,7 @@ return array(
|
||||||
'javelin-behavior-project-boards' => '14a1faae',
|
'javelin-behavior-project-boards' => '14a1faae',
|
||||||
'javelin-behavior-project-create' => '065227cc',
|
'javelin-behavior-project-create' => '065227cc',
|
||||||
'javelin-behavior-quicksand-blacklist' => '7927a7d3',
|
'javelin-behavior-quicksand-blacklist' => '7927a7d3',
|
||||||
'javelin-behavior-read-only-warning' => 'f8ea359c',
|
'javelin-behavior-read-only-warning' => 'ba158207',
|
||||||
'javelin-behavior-recurring-edit' => '5f1c4d5f',
|
'javelin-behavior-recurring-edit' => '5f1c4d5f',
|
||||||
'javelin-behavior-refresh-csrf' => 'ab2f381b',
|
'javelin-behavior-refresh-csrf' => 'ab2f381b',
|
||||||
'javelin-behavior-releeph-preview-branch' => 'b2b4fbaf',
|
'javelin-behavior-releeph-preview-branch' => 'b2b4fbaf',
|
||||||
|
@ -1783,6 +1783,11 @@ return array(
|
||||||
'javelin-json',
|
'javelin-json',
|
||||||
'phabricator-draggable-list',
|
'phabricator-draggable-list',
|
||||||
),
|
),
|
||||||
|
'ba158207' => array(
|
||||||
|
'javelin-behavior',
|
||||||
|
'javelin-uri',
|
||||||
|
'phabricator-notification',
|
||||||
|
),
|
||||||
'bae58312' => array(
|
'bae58312' => array(
|
||||||
'javelin-install',
|
'javelin-install',
|
||||||
'javelin-workboard-card',
|
'javelin-workboard-card',
|
||||||
|
@ -2111,11 +2116,6 @@ return array(
|
||||||
'javelin-util',
|
'javelin-util',
|
||||||
'phabricator-busy',
|
'phabricator-busy',
|
||||||
),
|
),
|
||||||
'f8ea359c' => array(
|
|
||||||
'javelin-behavior',
|
|
||||||
'javelin-uri',
|
|
||||||
'phabricator-notification',
|
|
||||||
),
|
|
||||||
'fa0f4fc2' => array(
|
'fa0f4fc2' => array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
|
|
|
@ -3425,6 +3425,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSystemDAO' => 'applications/system/storage/PhabricatorSystemDAO.php',
|
'PhabricatorSystemDAO' => 'applications/system/storage/PhabricatorSystemDAO.php',
|
||||||
'PhabricatorSystemDestructionGarbageCollector' => 'applications/system/garbagecollector/PhabricatorSystemDestructionGarbageCollector.php',
|
'PhabricatorSystemDestructionGarbageCollector' => 'applications/system/garbagecollector/PhabricatorSystemDestructionGarbageCollector.php',
|
||||||
'PhabricatorSystemDestructionLog' => 'applications/system/storage/PhabricatorSystemDestructionLog.php',
|
'PhabricatorSystemDestructionLog' => 'applications/system/storage/PhabricatorSystemDestructionLog.php',
|
||||||
|
'PhabricatorSystemReadOnlyController' => 'applications/system/controller/PhabricatorSystemReadOnlyController.php',
|
||||||
'PhabricatorSystemRemoveDestroyWorkflow' => 'applications/system/management/PhabricatorSystemRemoveDestroyWorkflow.php',
|
'PhabricatorSystemRemoveDestroyWorkflow' => 'applications/system/management/PhabricatorSystemRemoveDestroyWorkflow.php',
|
||||||
'PhabricatorSystemRemoveLogWorkflow' => 'applications/system/management/PhabricatorSystemRemoveLogWorkflow.php',
|
'PhabricatorSystemRemoveLogWorkflow' => 'applications/system/management/PhabricatorSystemRemoveLogWorkflow.php',
|
||||||
'PhabricatorSystemRemoveWorkflow' => 'applications/system/management/PhabricatorSystemRemoveWorkflow.php',
|
'PhabricatorSystemRemoveWorkflow' => 'applications/system/management/PhabricatorSystemRemoveWorkflow.php',
|
||||||
|
@ -8076,6 +8077,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSystemDAO' => 'PhabricatorLiskDAO',
|
'PhabricatorSystemDAO' => 'PhabricatorLiskDAO',
|
||||||
'PhabricatorSystemDestructionGarbageCollector' => 'PhabricatorGarbageCollector',
|
'PhabricatorSystemDestructionGarbageCollector' => 'PhabricatorGarbageCollector',
|
||||||
'PhabricatorSystemDestructionLog' => 'PhabricatorSystemDAO',
|
'PhabricatorSystemDestructionLog' => 'PhabricatorSystemDAO',
|
||||||
|
'PhabricatorSystemReadOnlyController' => 'PhabricatorController',
|
||||||
'PhabricatorSystemRemoveDestroyWorkflow' => 'PhabricatorSystemRemoveWorkflow',
|
'PhabricatorSystemRemoveDestroyWorkflow' => 'PhabricatorSystemRemoveWorkflow',
|
||||||
'PhabricatorSystemRemoveLogWorkflow' => 'PhabricatorSystemRemoveWorkflow',
|
'PhabricatorSystemRemoveLogWorkflow' => 'PhabricatorSystemRemoveWorkflow',
|
||||||
'PhabricatorSystemRemoveWorkflow' => 'PhabricatorManagementWorkflow',
|
'PhabricatorSystemRemoveWorkflow' => 'PhabricatorManagementWorkflow',
|
||||||
|
|
|
@ -23,6 +23,9 @@ final class PhabricatorSystemApplication extends PhabricatorApplication {
|
||||||
'encoding/' => 'PhabricatorSystemSelectEncodingController',
|
'encoding/' => 'PhabricatorSystemSelectEncodingController',
|
||||||
'highlight/' => 'PhabricatorSystemSelectHighlightController',
|
'highlight/' => 'PhabricatorSystemSelectHighlightController',
|
||||||
),
|
),
|
||||||
|
'/readonly/' => array(
|
||||||
|
'(?P<reason>[^/]+)/' => 'PhabricatorSystemReadOnlyController',
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSystemReadOnlyController
|
||||||
|
extends PhabricatorController {
|
||||||
|
|
||||||
|
public function shouldRequireLogin() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$reason = $request->getURIData('reason');
|
||||||
|
|
||||||
|
$body = array();
|
||||||
|
switch ($reason) {
|
||||||
|
case PhabricatorEnv::READONLY_CONFIG:
|
||||||
|
$title = pht('Administrative Read-Only Mode');
|
||||||
|
$body[] = pht(
|
||||||
|
'An administrator has placed Phabricator into read-only mode.');
|
||||||
|
$body[] = pht(
|
||||||
|
'This mode may be used to perform temporary maintenance, test '.
|
||||||
|
'configuration, or archive an installation permanently.');
|
||||||
|
$body[] = pht(
|
||||||
|
'Read-only mode was enabled by the explicit action of a human '.
|
||||||
|
'administrator, so you can get more information about why it '.
|
||||||
|
'has been turned on by rolling your chair away from your desk and '.
|
||||||
|
'yelling "Hey! Why is Phabricator in read-only mode??!" using '.
|
||||||
|
'your very loudest outside voice.');
|
||||||
|
$button = pht('Wait Patiently');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$body[] = pht(
|
||||||
|
'In read-only mode you can read existing information, but you will not '.
|
||||||
|
'be able to edit information or create new information until this mode '.
|
||||||
|
'is disabled.');
|
||||||
|
|
||||||
|
$dialog = $this->newDialog()
|
||||||
|
->setTitle($title)
|
||||||
|
->setWidth(AphrontDialogView::WIDTH_FORM)
|
||||||
|
->addCancelButton('/', $button);
|
||||||
|
|
||||||
|
foreach ($body as $paragraph) {
|
||||||
|
$dialog->appendParagraph($paragraph);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $dialog;
|
||||||
|
}
|
||||||
|
}
|
28
src/infrastructure/env/PhabricatorEnv.php
vendored
28
src/infrastructure/env/PhabricatorEnv.php
vendored
|
@ -57,6 +57,9 @@ final class PhabricatorEnv extends Phobject {
|
||||||
private static $cache;
|
private static $cache;
|
||||||
private static $localeCode;
|
private static $localeCode;
|
||||||
private static $readOnly;
|
private static $readOnly;
|
||||||
|
private static $readOnlyReason;
|
||||||
|
|
||||||
|
const READONLY_CONFIG = 'config';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @phutil-external-symbol class PhabricatorStartup
|
* @phutil-external-symbol class PhabricatorStartup
|
||||||
|
@ -447,8 +450,31 @@ final class PhabricatorEnv extends Phobject {
|
||||||
return self::getEnvConfig('cluster.read-only');
|
return self::getEnvConfig('cluster.read-only');
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function setReadOnly($read_only) {
|
public static function setReadOnly($read_only, $reason) {
|
||||||
self::$readOnly = $read_only;
|
self::$readOnly = $read_only;
|
||||||
|
self::$readOnlyReason = $reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getReadOnlyMessage() {
|
||||||
|
return pht('Phabricator is currently in read-only mode.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getReadOnlyURI() {
|
||||||
|
return urisprintf(
|
||||||
|
'/readonly/%s/',
|
||||||
|
self::getReadOnlyReason());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getReadOnlyReason() {
|
||||||
|
if (!self::isReadOnly()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::$readOnlyReason !== null) {
|
||||||
|
return self::$readOnlyReason;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::READONLY_CONFIG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ abstract class PhabricatorStorageManagementWorkflow
|
||||||
|
|
||||||
if (PhabricatorEnv::isReadOnly()) {
|
if (PhabricatorEnv::isReadOnly()) {
|
||||||
if ($this->isForce()) {
|
if ($this->isForce()) {
|
||||||
PhabricatorEnv::setReadOnly(false);
|
PhabricatorEnv::setReadOnly(false, null);
|
||||||
} else {
|
} else {
|
||||||
throw new PhutilArgumentUsageException(
|
throw new PhutilArgumentUsageException(
|
||||||
pht(
|
pht(
|
||||||
|
|
|
@ -276,7 +276,8 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView
|
||||||
Javelin::initBehavior(
|
Javelin::initBehavior(
|
||||||
'read-only-warning',
|
'read-only-warning',
|
||||||
array(
|
array(
|
||||||
'message' => pht('Phabricator is currently in read-only mode.'),
|
'message' => PhabricatorEnv::getReadOnlyMessage(),
|
||||||
|
'uri' => PhabricatorEnv::getReadOnlyURI(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,17 @@
|
||||||
|
|
||||||
JX.behavior('read-only-warning', function(config) {
|
JX.behavior('read-only-warning', function(config) {
|
||||||
|
|
||||||
new JX.Notification()
|
var n = new JX.Notification()
|
||||||
.setContent(config.message)
|
.setContent(config.message)
|
||||||
.setDuration(0)
|
.setDuration(0)
|
||||||
.alterClassName('jx-notification-read-only', true)
|
.alterClassName('jx-notification-read-only', true);
|
||||||
.show();
|
|
||||||
|
n.listen(
|
||||||
|
'activate',
|
||||||
|
function() {
|
||||||
|
JX.$U(config.uri).go();
|
||||||
|
});
|
||||||
|
|
||||||
|
n.show();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue