@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add a bunch of Phacility-specific code to the upstream, thinly veiled as generic code

Summary:
Ref T9304. This adds a "GuidanceEngine" which can generate "Guidance".

In practice, this lets third-party code (rSERVICES) remove and replace instructions in the UI, which is basically only usefulf or us to tell users to go read the documentation in the Phacility cluster.

The next diff tailors the help on the "Auth Providers" and "Create New User" pages to say "PHACILITY PHACILITY PHACILITY PHACILITY".

Test Plan: Browed to "Auth Providers" and "Create New User" on instanced and non-instanced installs, saw appropriate guidance.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9304

Differential Revision: https://secure.phabricator.com/D16861

+333 -64
+14
src/__phutil_library_map__.php
··· 1917 1917 'PhabricatorAuthProviderConfigQuery' => 'applications/auth/query/PhabricatorAuthProviderConfigQuery.php', 1918 1918 'PhabricatorAuthProviderConfigTransaction' => 'applications/auth/storage/PhabricatorAuthProviderConfigTransaction.php', 1919 1919 'PhabricatorAuthProviderConfigTransactionQuery' => 'applications/auth/query/PhabricatorAuthProviderConfigTransactionQuery.php', 1920 + 'PhabricatorAuthProvidersGuidanceContext' => 'applications/auth/guidance/PhabricatorAuthProvidersGuidanceContext.php', 1921 + 'PhabricatorAuthProvidersGuidanceEngineExtension' => 'applications/auth/guidance/PhabricatorAuthProvidersGuidanceEngineExtension.php', 1920 1922 'PhabricatorAuthQueryPublicKeysConduitAPIMethod' => 'applications/auth/conduit/PhabricatorAuthQueryPublicKeysConduitAPIMethod.php', 1921 1923 'PhabricatorAuthRegisterController' => 'applications/auth/controller/PhabricatorAuthRegisterController.php', 1922 1924 'PhabricatorAuthRevokeTokenController' => 'applications/auth/controller/PhabricatorAuthRevokeTokenController.php', ··· 2728 2730 'PhabricatorGlobalLock' => 'infrastructure/util/PhabricatorGlobalLock.php', 2729 2731 'PhabricatorGlobalUploadTargetView' => 'applications/files/view/PhabricatorGlobalUploadTargetView.php', 2730 2732 'PhabricatorGoogleAuthProvider' => 'applications/auth/provider/PhabricatorGoogleAuthProvider.php', 2733 + 'PhabricatorGuidanceContext' => 'applications/guides/guidance/PhabricatorGuidanceContext.php', 2734 + 'PhabricatorGuidanceEngine' => 'applications/guides/guidance/PhabricatorGuidanceEngine.php', 2735 + 'PhabricatorGuidanceEngineExtension' => 'applications/guides/guidance/PhabricatorGuidanceEngineExtension.php', 2736 + 'PhabricatorGuidanceMessage' => 'applications/guides/guidance/PhabricatorGuidanceMessage.php', 2731 2737 'PhabricatorGuideApplication' => 'applications/guides/application/PhabricatorGuideApplication.php', 2732 2738 'PhabricatorGuideController' => 'applications/guides/controller/PhabricatorGuideController.php', 2733 2739 'PhabricatorGuideInstallModule' => 'applications/guides/module/PhabricatorGuideInstallModule.php', ··· 3218 3224 'PhabricatorPeopleApproveController' => 'applications/people/controller/PhabricatorPeopleApproveController.php', 3219 3225 'PhabricatorPeopleController' => 'applications/people/controller/PhabricatorPeopleController.php', 3220 3226 'PhabricatorPeopleCreateController' => 'applications/people/controller/PhabricatorPeopleCreateController.php', 3227 + 'PhabricatorPeopleCreateGuidanceContext' => 'applications/people/guidance/PhabricatorPeopleCreateGuidanceContext.php', 3221 3228 'PhabricatorPeopleDatasource' => 'applications/people/typeahead/PhabricatorPeopleDatasource.php', 3222 3229 'PhabricatorPeopleDeleteController' => 'applications/people/controller/PhabricatorPeopleDeleteController.php', 3223 3230 'PhabricatorPeopleDetailsProfilePanel' => 'applications/people/profilepanel/PhabricatorPeopleDetailsProfilePanel.php', ··· 6730 6737 'PhabricatorAuthProviderConfigQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 6731 6738 'PhabricatorAuthProviderConfigTransaction' => 'PhabricatorApplicationTransaction', 6732 6739 'PhabricatorAuthProviderConfigTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 6740 + 'PhabricatorAuthProvidersGuidanceContext' => 'PhabricatorGuidanceContext', 6741 + 'PhabricatorAuthProvidersGuidanceEngineExtension' => 'PhabricatorGuidanceEngineExtension', 6733 6742 'PhabricatorAuthQueryPublicKeysConduitAPIMethod' => 'PhabricatorAuthConduitAPIMethod', 6734 6743 'PhabricatorAuthRegisterController' => 'PhabricatorAuthController', 6735 6744 'PhabricatorAuthRevokeTokenController' => 'PhabricatorAuthController', ··· 7687 7696 'PhabricatorGlobalLock' => 'PhutilLock', 7688 7697 'PhabricatorGlobalUploadTargetView' => 'AphrontView', 7689 7698 'PhabricatorGoogleAuthProvider' => 'PhabricatorOAuth2AuthProvider', 7699 + 'PhabricatorGuidanceContext' => 'Phobject', 7700 + 'PhabricatorGuidanceEngine' => 'Phobject', 7701 + 'PhabricatorGuidanceEngineExtension' => 'Phobject', 7702 + 'PhabricatorGuidanceMessage' => 'Phobject', 7690 7703 'PhabricatorGuideApplication' => 'PhabricatorApplication', 7691 7704 'PhabricatorGuideController' => 'PhabricatorController', 7692 7705 'PhabricatorGuideInstallModule' => 'PhabricatorGuideModule', ··· 8256 8269 'PhabricatorPeopleApproveController' => 'PhabricatorPeopleController', 8257 8270 'PhabricatorPeopleController' => 'PhabricatorController', 8258 8271 'PhabricatorPeopleCreateController' => 'PhabricatorPeopleController', 8272 + 'PhabricatorPeopleCreateGuidanceContext' => 'PhabricatorGuidanceContext', 8259 8273 'PhabricatorPeopleDatasource' => 'PhabricatorTypeaheadDatasource', 8260 8274 'PhabricatorPeopleDeleteController' => 'PhabricatorPeopleController', 8261 8275 'PhabricatorPeopleDetailsProfilePanel' => 'PhabricatorProfilePanel',
+6 -62
src/applications/auth/controller/config/PhabricatorAuthListController.php
··· 94 94 $crumbs->addTextCrumb(pht('Auth Providers')); 95 95 $crumbs->setBorder(true); 96 96 97 - $domains_key = 'auth.email-domains'; 98 - $domains_link = $this->renderConfigLink($domains_key); 99 - $domains_value = PhabricatorEnv::getEnvConfig($domains_key); 100 - 101 - $approval_key = 'auth.require-approval'; 102 - $approval_link = $this->renderConfigLink($approval_key); 103 - $approval_value = PhabricatorEnv::getEnvConfig($approval_key); 104 - 105 - $issues = array(); 106 - if ($domains_value) { 107 - $issues[] = pht( 108 - 'Phabricator is configured with an email domain whitelist (in %s), so '. 109 - 'only users with a verified email address at one of these %s '. 110 - 'allowed domain(s) will be able to register an account: %s', 111 - $domains_link, 112 - phutil_count($domains_value), 113 - phutil_tag('strong', array(), implode(', ', $domains_value))); 114 - } else { 115 - $issues[] = pht( 116 - 'Anyone who can browse to this Phabricator install will be able to '. 117 - 'register an account. To add email domain restrictions, configure '. 118 - '%s.', 119 - $domains_link); 120 - } 121 - 122 - if ($approval_value) { 123 - $issues[] = pht( 124 - 'Administrative approvals are enabled (in %s), so all new users must '. 125 - 'have their accounts approved by an administrator.', 126 - $approval_link); 127 - } else { 128 - $issues[] = pht( 129 - 'Administrative approvals are disabled, so users who register will '. 130 - 'be able to use their accounts immediately. To enable approvals, '. 131 - 'configure %s.', 132 - $approval_link); 133 - } 97 + $guidance_context = new PhabricatorAuthProvidersGuidanceContext(); 134 98 135 - if (!$domains_value && !$approval_value) { 136 - $severity = PHUIInfoView::SEVERITY_WARNING; 137 - $issues[] = pht( 138 - 'You can safely ignore this warning if the install itself has '. 139 - 'access controls (for example, it is deployed on a VPN) or if all of '. 140 - 'the configured providers have access controls (for example, they are '. 141 - 'all private LDAP or OAuth servers).'); 142 - } else { 143 - $severity = PHUIInfoView::SEVERITY_NOTICE; 144 - } 145 - 146 - $warning = id(new PHUIInfoView()) 147 - ->setSeverity($severity) 148 - ->setErrors($issues); 99 + $guidance = id(new PhabricatorGuidanceEngine()) 100 + ->setViewer($viewer) 101 + ->setGuidanceContext($guidance_context) 102 + ->newInfoView(); 149 103 150 104 $button = id(new PHUIButtonView()) 151 105 ->setTag('a') ··· 170 124 $view = id(new PHUITwoColumnView()) 171 125 ->setHeader($header) 172 126 ->setFooter(array( 173 - $warning, 127 + $guidance, 174 128 $list, 175 129 )); 176 130 ··· 178 132 ->setTitle($title) 179 133 ->setCrumbs($crumbs) 180 134 ->appendChild($view); 181 - } 182 - 183 - private function renderConfigLink($key) { 184 - return phutil_tag( 185 - 'a', 186 - array( 187 - 'href' => '/config/edit/'.$key.'/', 188 - 'target' => '_blank', 189 - ), 190 - $key); 191 135 } 192 136 193 137 }
+4
src/applications/auth/guidance/PhabricatorAuthProvidersGuidanceContext.php
··· 1 + <?php 2 + 3 + final class PhabricatorAuthProvidersGuidanceContext 4 + extends PhabricatorGuidanceContext {}
+88
src/applications/auth/guidance/PhabricatorAuthProvidersGuidanceEngineExtension.php
··· 1 + <?php 2 + 3 + final class PhabricatorAuthProvidersGuidanceEngineExtension 4 + extends PhabricatorGuidanceEngineExtension { 5 + 6 + const GUIDANCEKEY = 'core.auth.providers'; 7 + 8 + public function canGenerateGuidance(PhabricatorGuidanceContext $context) { 9 + return ($context instanceof PhabricatorAuthProvidersGuidanceContext); 10 + } 11 + 12 + public function generateGuidance(PhabricatorGuidanceContext $context) { 13 + $domains_key = 'auth.email-domains'; 14 + $domains_link = $this->renderConfigLink($domains_key); 15 + $domains_value = PhabricatorEnv::getEnvConfig($domains_key); 16 + 17 + $approval_key = 'auth.require-approval'; 18 + $approval_link = $this->renderConfigLink($approval_key); 19 + $approval_value = PhabricatorEnv::getEnvConfig($approval_key); 20 + 21 + $results = array(); 22 + 23 + if ($domains_value) { 24 + $message = pht( 25 + 'Phabricator is configured with an email domain whitelist (in %s), so '. 26 + 'only users with a verified email address at one of these %s '. 27 + 'allowed domain(s) will be able to register an account: %s', 28 + $domains_link, 29 + phutil_count($domains_value), 30 + phutil_tag('strong', array(), implode(', ', $domains_value))); 31 + 32 + $results[] = $this->newGuidance('core.auth.email-domains.on') 33 + ->setMessage($message); 34 + } else { 35 + $message = pht( 36 + 'Anyone who can browse to this Phabricator install will be able to '. 37 + 'register an account. To add email domain restrictions, configure '. 38 + '%s.', 39 + $domains_link); 40 + 41 + $results[] = $this->newGuidance('core.auth.email-domains.off') 42 + ->setMessage($message); 43 + } 44 + 45 + if ($approval_value) { 46 + $message = pht( 47 + 'Administrative approvals are enabled (in %s), so all new users must '. 48 + 'have their accounts approved by an administrator.', 49 + $approval_link); 50 + 51 + $results[] = $this->newGuidance('core.auth.require-approval.on') 52 + ->setMessage($message); 53 + } else { 54 + $message = pht( 55 + 'Administrative approvals are disabled, so users who register will '. 56 + 'be able to use their accounts immediately. To enable approvals, '. 57 + 'configure %s.', 58 + $approval_link); 59 + 60 + $results[] = $this->newGuidance('core.auth.require-approval.off') 61 + ->setMessage($message); 62 + } 63 + 64 + if (!$domains_value && !$approval_value) { 65 + $message = pht( 66 + 'You can safely ignore these warnings if the install itself has '. 67 + 'access controls (for example, it is deployed on a VPN) or if all of '. 68 + 'the configured providers have access controls (for example, they are '. 69 + 'all private LDAP or OAuth servers).'); 70 + 71 + $results[] = $this->newWarning('core.auth.warning') 72 + ->setMessage($message); 73 + } 74 + 75 + return $results; 76 + } 77 + 78 + private function renderConfigLink($key) { 79 + return phutil_tag( 80 + 'a', 81 + array( 82 + 'href' => '/config/edit/'.$key.'/', 83 + 'target' => '_blank', 84 + ), 85 + $key); 86 + } 87 + 88 + }
+4
src/applications/guides/guidance/PhabricatorGuidanceContext.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorGuidanceContext 4 + extends Phobject {}
+96
src/applications/guides/guidance/PhabricatorGuidanceEngine.php
··· 1 + <?php 2 + 3 + final class PhabricatorGuidanceEngine 4 + extends Phobject { 5 + 6 + private $viewer; 7 + private $guidanceContext; 8 + 9 + public function setGuidanceContext( 10 + PhabricatorGuidanceContext $guidance_context) { 11 + $this->guidanceContext = $guidance_context; 12 + return $this; 13 + } 14 + 15 + public function getGuidanceContext() { 16 + return $this->guidanceContext; 17 + } 18 + 19 + public function setViewer(PhabricatorUser $viewer) { 20 + $this->viewer = $viewer; 21 + return $this; 22 + } 23 + 24 + public function getViewer() { 25 + return $this->viewer; 26 + } 27 + 28 + public function newInfoView() { 29 + $extensions = PhabricatorGuidanceEngineExtension::getAllExtensions(); 30 + $context = $this->getGuidanceContext(); 31 + 32 + $keep = array(); 33 + foreach ($extensions as $key => $extension) { 34 + if (!$extension->canGenerateGuidance($context)) { 35 + continue; 36 + } 37 + $keep[$key] = id(clone $extension); 38 + } 39 + 40 + $guidance_map = array(); 41 + foreach ($keep as $extension) { 42 + $guidance_list = $extension->generateGuidance($context); 43 + foreach ($guidance_list as $guidance) { 44 + $key = $guidance->getKey(); 45 + 46 + if (isset($guidance_map[$key])) { 47 + throw new Exception( 48 + pht( 49 + 'Two guidance extensions generated guidance with the same '. 50 + 'key ("%s"). Each piece of guidance must have a unique key.', 51 + $key)); 52 + } 53 + 54 + $guidance_map[$key] = $guidance; 55 + } 56 + } 57 + 58 + foreach ($keep as $extension) { 59 + $guidance_map = $extension->didGenerateGuidance($context, $guidance_map); 60 + } 61 + 62 + if (!$guidance_map) { 63 + return null; 64 + } 65 + 66 + $guidance_map = msortv($guidance_map, 'getSortVector'); 67 + 68 + $severity = PhabricatorGuidanceMessage::SEVERITY_NOTICE; 69 + $strength = null; 70 + foreach ($guidance_map as $guidance) { 71 + if ($strength !== null) { 72 + if ($guidance->getSeverityStrength() <= $strength) { 73 + continue; 74 + } 75 + } 76 + 77 + $strength = $guidance->getSeverityStrength(); 78 + $severity = $guidance->getSeverity(); 79 + } 80 + 81 + $severity_map = array( 82 + PhabricatorGuidanceMessage::SEVERITY_NOTICE 83 + => PHUIInfoView::SEVERITY_NOTICE, 84 + PhabricatorGuidanceMessage::SEVERITY_WARNING 85 + => PHUIInfoView::SEVERITY_WARNING, 86 + ); 87 + 88 + $messages = mpull($guidance_map, 'getMessage', 'getKey'); 89 + 90 + return id(new PHUIInfoView()) 91 + ->setViewer($this->getViewer()) 92 + ->setSeverity(idx($severity_map, $severity, $severity)) 93 + ->setErrors($messages); 94 + } 95 + 96 + }
+39
src/applications/guides/guidance/PhabricatorGuidanceEngineExtension.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorGuidanceEngineExtension 4 + extends Phobject { 5 + 6 + final public function getExtensionKey() { 7 + return $this->getPhobjectClassConstant('GUIDANCEKEY', 64); 8 + } 9 + 10 + abstract public function canGenerateGuidance( 11 + PhabricatorGuidanceContext $context); 12 + 13 + abstract public function generateGuidance( 14 + PhabricatorGuidanceContext $context); 15 + 16 + public function didGenerateGuidance( 17 + PhabricatorGuidanceContext $context, 18 + array $guidance) { 19 + return $guidance; 20 + } 21 + 22 + final protected function newGuidance($key) { 23 + return id(new PhabricatorGuidanceMessage()) 24 + ->setKey($key); 25 + } 26 + 27 + final protected function newWarning($key) { 28 + return $this->newGuidance($key) 29 + ->setSeverity(PhabricatorGuidanceMessage::SEVERITY_WARNING); 30 + } 31 + 32 + final public static function getAllExtensions() { 33 + return id(new PhutilClassMapQuery()) 34 + ->setAncestorClass(__CLASS__) 35 + ->setUniqueMethod('getExtensionKey') 36 + ->execute(); 37 + } 38 + 39 + }
+65
src/applications/guides/guidance/PhabricatorGuidanceMessage.php
··· 1 + <?php 2 + 3 + final class PhabricatorGuidanceMessage 4 + extends Phobject { 5 + 6 + private $key; 7 + private $message; 8 + private $severity = self::SEVERITY_NOTICE; 9 + private $priority = 1000; 10 + 11 + const SEVERITY_NOTICE = 'notice'; 12 + const SEVERITY_WARNING = 'warning'; 13 + 14 + public function setSeverity($severity) { 15 + $this->severity = $severity; 16 + return $this; 17 + } 18 + 19 + public function getSeverity() { 20 + return $this->severity; 21 + } 22 + 23 + public function setKey($key) { 24 + $this->key = $key; 25 + return $this; 26 + } 27 + 28 + public function getKey() { 29 + return $this->key; 30 + } 31 + 32 + public function setMessage($message) { 33 + $this->message = $message; 34 + return $this; 35 + } 36 + 37 + public function getMessage() { 38 + return $this->message; 39 + } 40 + 41 + public function getSortVector() { 42 + return id(new PhutilSortVector()) 43 + ->addInt($this->getPriority()); 44 + } 45 + 46 + public function setPriority($priority) { 47 + $this->priority = $priority; 48 + return $this; 49 + } 50 + 51 + public function getPriority() { 52 + return $this->priority; 53 + } 54 + 55 + public function getSeverityStrength() { 56 + $map = array( 57 + self::SEVERITY_NOTICE => 1, 58 + self::SEVERITY_WARNING => 2, 59 + ); 60 + 61 + return idx($map, $this->getSeverity(), 0); 62 + } 63 + 64 + 65 + }
+12 -1
src/applications/people/controller/PhabricatorPeopleCreateController.php
··· 101 101 ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 102 102 ->setForm($form); 103 103 104 + $guidance_context = new PhabricatorPeopleCreateGuidanceContext(); 105 + 106 + $guidance = id(new PhabricatorGuidanceEngine()) 107 + ->setViewer($admin) 108 + ->setGuidanceContext($guidance_context) 109 + ->newInfoView(); 110 + 104 111 $view = id(new PHUITwoColumnView()) 105 112 ->setHeader($header) 106 - ->setFooter($box); 113 + ->setFooter( 114 + array( 115 + $guidance, 116 + $box, 117 + )); 107 118 108 119 return $this->newPage() 109 120 ->setTitle($title)
+4
src/applications/people/guidance/PhabricatorPeopleCreateGuidanceContext.php
··· 1 + <?php 2 + 3 + final class PhabricatorPeopleCreateGuidanceContext 4 + extends PhabricatorGuidanceContext {}
+1 -1
src/view/form/PHUIInfoView.php
··· 130 130 ), 131 131 $list); 132 132 } else if (count($errors) == 1) { 133 - $list = $this->errors[0]; 133 + $list = head($this->errors); 134 134 } else { 135 135 $list = null; 136 136 }