@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
at recaptime-dev/main 268 lines 8.2 kB view raw
1<?php 2 3final class DiffusionSetPasswordSettingsPanel extends PhabricatorSettingsPanel { 4 5 public function isManagementPanel() { 6 if ($this->getUser()->getIsMailingList()) { 7 return false; 8 } 9 10 return true; 11 } 12 13 public function getPanelKey() { 14 return 'vcspassword'; 15 } 16 17 public function getPanelName() { 18 return pht('VCS Password'); 19 } 20 21 public function getPanelMenuIcon() { 22 return 'fa-code'; 23 } 24 25 public function getPanelGroupKey() { 26 return PhabricatorSettingsAuthenticationPanelGroup::PANELGROUPKEY; 27 } 28 29 public function isEnabled() { 30 return PhabricatorEnv::getEnvConfig('diffusion.allow-http-auth'); 31 } 32 33 public function processRequest(AphrontRequest $request) { 34 $viewer = $request->getUser(); 35 $user = $this->getUser(); 36 37 $token = id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession( 38 $viewer, 39 $request, 40 '/settings/'); 41 42 $vcs_type = PhabricatorAuthPassword::PASSWORD_TYPE_VCS; 43 44 $vcspasswords = id(new PhabricatorAuthPasswordQuery()) 45 ->setViewer($viewer) 46 ->withObjectPHIDs(array($user->getPHID())) 47 ->withPasswordTypes(array($vcs_type)) 48 ->withIsRevoked(false) 49 ->execute(); 50 if ($vcspasswords) { 51 $vcspassword = head($vcspasswords); 52 } else { 53 $vcspassword = PhabricatorAuthPassword::initializeNewPassword( 54 $user, 55 $vcs_type); 56 } 57 58 $panel_uri = $this->getPanelURI('?saved=true'); 59 60 $errors = array(); 61 62 $e_password = true; 63 $e_confirm = true; 64 65 $content_source = PhabricatorContentSource::newFromRequest($request); 66 67 // NOTE: This test is against $viewer (not $user), so that the error 68 // message below makes sense in the case that the two are different, 69 // and because an admin reusing their own password is bad, while 70 // system agents generally do not have passwords anyway. 71 72 $engine = id(new PhabricatorAuthPasswordEngine()) 73 ->setViewer($viewer) 74 ->setContentSource($content_source) 75 ->setObject($viewer) 76 ->setPasswordType($vcs_type); 77 78 if ($request->isFormPost()) { 79 if ($request->getBool('remove')) { 80 if ($vcspassword->getID()) { 81 $vcspassword->delete(); 82 return id(new AphrontRedirectResponse())->setURI($panel_uri); 83 } 84 } 85 86 $new_password = $request->getStr('password'); 87 $confirm = $request->getStr('confirm'); 88 89 $envelope = new PhutilOpaqueEnvelope($new_password); 90 $confirm_envelope = new PhutilOpaqueEnvelope($confirm); 91 92 try { 93 $engine->checkNewPassword($envelope, $confirm_envelope); 94 $e_password = null; 95 $e_confirm = null; 96 } catch (PhabricatorAuthPasswordException $ex) { 97 $errors[] = $ex->getMessage(); 98 $e_password = $ex->getPasswordError(); 99 $e_confirm = $ex->getConfirmError(); 100 } 101 102 if (!$errors) { 103 $vcspassword 104 ->setPassword($envelope, $user) 105 ->save(); 106 107 return id(new AphrontRedirectResponse())->setURI($panel_uri); 108 } 109 } 110 111 $title = pht('Set VCS Password'); 112 113 $form = id(new AphrontFormView()) 114 ->setUser($viewer) 115 ->appendRemarkupInstructions( 116 pht( 117 'To access repositories hosted on this server over HTTP, you must '. 118 'set a version control password. This password should be unique.'. 119 "\n\n". 120 "This password applies to all repositories available over ". 121 "HTTP.")); 122 123 if ($vcspassword->getID()) { 124 $form 125 ->appendChild( 126 id(new AphrontFormPasswordControl()) 127 ->setDisableAutocomplete(true) 128 ->setLabel(pht('Current Password')) 129 ->setDisabled(true) 130 ->setValue('********************')); 131 } else { 132 $form 133 ->appendChild( 134 id(new AphrontFormMarkupControl()) 135 ->setLabel(pht('Current Password')) 136 ->setValue(phutil_tag('em', array(), pht('No Password Set')))); 137 } 138 139 $form 140 ->appendChild( 141 id(new AphrontFormPasswordControl()) 142 ->setDisableAutocomplete(true) 143 ->setName('password') 144 ->setLabel(pht('New VCS Password')) 145 ->setError($e_password)) 146 ->appendChild( 147 id(new AphrontFormPasswordControl()) 148 ->setDisableAutocomplete(true) 149 ->setName('confirm') 150 ->setLabel(pht('Confirm VCS Password')) 151 ->setError($e_confirm)) 152 ->appendChild( 153 id(new AphrontFormSubmitControl()) 154 ->setValue(pht('Change Password'))); 155 156 157 if (!$vcspassword->getID()) { 158 $is_serious = PhabricatorEnv::getEnvConfig( 159 'phabricator.serious-business'); 160 161 $suggest = Filesystem::readRandomBytes(128); 162 $suggest = preg_replace('([^A-Za-z0-9/!().,;{}^&*%~])', '', $suggest); 163 $suggest = substr($suggest, 0, 20); 164 165 if ($is_serious) { 166 $form->appendRemarkupInstructions( 167 pht( 168 'Having trouble coming up with a good password? Try this randomly '. 169 'generated one, made by a computer:'. 170 "\n\n". 171 "`%s`", 172 $suggest)); 173 } else { 174 $form->appendRemarkupInstructions( 175 pht( 176 'Having trouble coming up with a good password? Try this '. 177 'artisanal password, hand made in small batches by our expert '. 178 'craftspeople: '. 179 "\n\n". 180 "`%s`", 181 $suggest)); 182 } 183 } 184 185 $hash_envelope = new PhutilOpaqueEnvelope($vcspassword->getPasswordHash()); 186 187 $form->appendChild( 188 id(new AphrontFormStaticControl()) 189 ->setLabel(pht('Current Algorithm')) 190 ->setValue( 191 PhabricatorPasswordHasher::getCurrentAlgorithmName($hash_envelope))); 192 193 $form->appendChild( 194 id(new AphrontFormStaticControl()) 195 ->setLabel(pht('Best Available Algorithm')) 196 ->setValue(PhabricatorPasswordHasher::getBestAlgorithmName())); 197 198 if (strlen($hash_envelope->openEnvelope())) { 199 try { 200 $can_upgrade = PhabricatorPasswordHasher::canUpgradeHash( 201 $hash_envelope); 202 } catch (PhabricatorPasswordHasherUnavailableException $ex) { 203 $can_upgrade = false; 204 $errors[] = pht( 205 'Your VCS password is currently hashed using an algorithm which is '. 206 'no longer available on this install.'); 207 $errors[] = pht( 208 'Because the algorithm implementation is missing, your password '. 209 'can not be used.'); 210 $errors[] = pht( 211 'You can set a new password to replace the old password.'); 212 } 213 214 if ($can_upgrade) { 215 $errors[] = pht( 216 'The strength of your stored VCS password hash can be upgraded. '. 217 'To upgrade, either: use the password to authenticate with a '. 218 'repository; or change your password.'); 219 } 220 } 221 222 $object_box = id(new PHUIObjectBoxView()) 223 ->setHeaderText($title) 224 ->setBackground(PHUIObjectBoxView::WHITE_CONFIG) 225 ->setForm($form) 226 ->setFormErrors($errors); 227 228 $remove_form = id(new AphrontFormView()) 229 ->setUser($viewer); 230 231 if ($vcspassword->getID()) { 232 $remove_form 233 ->addHiddenInput('remove', true) 234 ->appendRemarkupInstructions( 235 pht( 236 'You can remove your VCS password, which will prevent your '. 237 'account from accessing repositories.')) 238 ->appendChild( 239 id(new AphrontFormSubmitControl()) 240 ->setValue(pht('Remove Password'))); 241 } else { 242 $remove_form->appendRemarkupInstructions( 243 pht( 244 'You do not currently have a VCS password set. If you set one, you '. 245 'can remove it here later.')); 246 } 247 248 $remove_box = id(new PHUIObjectBoxView()) 249 ->setHeaderText(pht('Remove VCS Password')) 250 ->setBackground(PHUIObjectBoxView::WHITE_CONFIG) 251 ->setForm($remove_form); 252 253 $saved = null; 254 if ($request->getBool('saved')) { 255 $saved = id(new PHUIInfoView()) 256 ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) 257 ->setTitle(pht('Password Updated')) 258 ->appendChild(pht('Your VCS password has been updated.')); 259 } 260 261 return array( 262 $saved, 263 $object_box, 264 $remove_box, 265 ); 266 } 267 268}