@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 400 lines 13 kB view raw
1<?php 2 3final class PhabricatorAuthEditController 4 extends PhabricatorAuthProviderConfigController { 5 6 /** 7 * @return PhabricatorStandardPageView|AphrontResponse 8 */ 9 public function handleRequest(AphrontRequest $request) { 10 $this->requireApplicationCapability( 11 AuthManageProvidersCapability::CAPABILITY); 12 13 $viewer = $this->getViewer(); 14 $provider_class = $request->getStr('provider'); 15 $config_id = $request->getURIData('id'); 16 17 if ($config_id) { 18 $config = id(new PhabricatorAuthProviderConfigQuery()) 19 ->setViewer($viewer) 20 ->requireCapabilities( 21 array( 22 PhabricatorPolicyCapability::CAN_VIEW, 23 PhabricatorPolicyCapability::CAN_EDIT, 24 )) 25 ->withIDs(array($config_id)) 26 ->executeOne(); 27 if (!$config) { 28 return new Aphront404Response(); 29 } 30 31 $provider = $config->getProvider(); 32 if (!$provider) { 33 return new Aphront404Response(); 34 } 35 36 $is_new = false; 37 } else { 38 $provider = null; 39 40 $providers = PhabricatorAuthProvider::getAllBaseProviders(); 41 foreach ($providers as $candidate_provider) { 42 if (get_class($candidate_provider) === $provider_class) { 43 $provider = $candidate_provider; 44 break; 45 } 46 } 47 48 if (!$provider) { 49 return new Aphront404Response(); 50 } 51 52 // TODO: When we have multi-auth providers, support them here. 53 54 $configs = id(new PhabricatorAuthProviderConfigQuery()) 55 ->setViewer($viewer) 56 ->withProviderClasses(array(get_class($provider))) 57 ->execute(); 58 59 if ($configs) { 60 $id = head($configs)->getID(); 61 $dialog = id(new AphrontDialogView()) 62 ->setUser($viewer) 63 ->setMethod('GET') 64 ->setSubmitURI($this->getApplicationURI('config/edit/'.$id.'/')) 65 ->setTitle(pht('Provider Already Configured')) 66 ->appendChild( 67 pht( 68 'This provider ("%s") already exists, and you can not add more '. 69 'than one instance of it. You can edit the existing provider, '. 70 'or you can choose a different provider.', 71 $provider->getProviderName())) 72 ->addCancelButton($this->getApplicationURI('config/new/')) 73 ->addSubmitButton(pht('Edit Existing Provider')); 74 75 return id(new AphrontDialogResponse())->setDialog($dialog); 76 } 77 78 $config = $provider->getDefaultProviderConfig(); 79 $provider->attachProviderConfig($config); 80 81 $is_new = true; 82 } 83 84 $errors = array(); 85 $validation_exception = null; 86 87 $v_login = $config->getShouldAllowLogin(); 88 $v_registration = $config->getShouldAllowRegistration(); 89 $v_link = $config->getShouldAllowLink(); 90 $v_unlink = $config->getShouldAllowUnlink(); 91 $v_trust_email = $config->getShouldTrustEmails(); 92 $v_auto_login = $config->getShouldAutoLogin(); 93 94 if ($request->isFormPost()) { 95 96 $properties = $provider->readFormValuesFromRequest($request); 97 list($errors, $issues, $properties) = $provider->processEditForm( 98 $request, 99 $properties); 100 101 $xactions = array(); 102 103 if (!$errors) { 104 if ($is_new) { 105 if (!phutil_nonempty_string($config->getProviderType())) { 106 $config->setProviderType($provider->getProviderType()); 107 } 108 if (!phutil_nonempty_string($config->getProviderDomain())) { 109 $config->setProviderDomain($provider->getProviderDomain()); 110 } 111 } 112 113 $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) 114 ->setTransactionType( 115 PhabricatorAuthProviderConfigTransaction::TYPE_LOGIN) 116 ->setNewValue($request->getInt('allowLogin', 0)); 117 118 $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) 119 ->setTransactionType( 120 PhabricatorAuthProviderConfigTransaction::TYPE_REGISTRATION) 121 ->setNewValue($request->getInt('allowRegistration', 0)); 122 123 $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) 124 ->setTransactionType( 125 PhabricatorAuthProviderConfigTransaction::TYPE_LINK) 126 ->setNewValue($request->getInt('allowLink', 0)); 127 128 $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) 129 ->setTransactionType( 130 PhabricatorAuthProviderConfigTransaction::TYPE_UNLINK) 131 ->setNewValue($request->getInt('allowUnlink', 0)); 132 133 $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) 134 ->setTransactionType( 135 PhabricatorAuthProviderConfigTransaction::TYPE_TRUST_EMAILS) 136 ->setNewValue($request->getInt('trustEmails', 0)); 137 138 if ($provider->supportsAutoLogin()) { 139 $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) 140 ->setTransactionType( 141 PhabricatorAuthProviderConfigTransaction::TYPE_AUTO_LOGIN) 142 ->setNewValue($request->getInt('autoLogin', 0)); 143 } 144 145 foreach ($properties as $key => $value) { 146 $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) 147 ->setTransactionType( 148 PhabricatorAuthProviderConfigTransaction::TYPE_PROPERTY) 149 ->setMetadataValue('auth:property', $key) 150 ->setNewValue($value); 151 } 152 153 if ($is_new) { 154 $config->save(); 155 } 156 157 $editor = id(new PhabricatorAuthProviderConfigEditor()) 158 ->setActor($viewer) 159 ->setContentSourceFromRequest($request) 160 ->setContinueOnNoEffect(true); 161 162 try { 163 $editor->applyTransactions($config, $xactions); 164 $next_uri = $config->getURI(); 165 166 return id(new AphrontRedirectResponse())->setURI($next_uri); 167 } catch (Exception $ex) { 168 $validation_exception = $ex; 169 } 170 } 171 } else { 172 $properties = $provider->readFormValuesFromProvider(); 173 $issues = array(); 174 } 175 176 if ($is_new) { 177 if ($provider->hasSetupStep()) { 178 $button = pht('Next Step'); 179 } else { 180 $button = pht('Add Provider'); 181 } 182 $crumb = pht('Add Provider'); 183 $title = pht('Add Auth Provider'); 184 $header_icon = 'fa-plus-square'; 185 $cancel_uri = $this->getApplicationURI('/config/new/'); 186 } else { 187 $button = pht('Save'); 188 $crumb = pht('Edit Provider'); 189 $title = pht('Edit Auth Provider'); 190 $header_icon = 'fa-pencil'; 191 $cancel_uri = $config->getURI(); 192 } 193 194 $header = id(new PHUIHeaderView()) 195 ->setHeader(pht('%s: %s', $title, $provider->getProviderName())) 196 ->setHeaderIcon($header_icon); 197 198 if (!$is_new) { 199 if ($config->getIsEnabled()) { 200 $status_name = pht('Enabled'); 201 $status_color = 'green'; 202 $status_icon = 'fa-check'; 203 $header->setStatus($status_icon, $status_color, $status_name); 204 } else { 205 $status_name = pht('Disabled'); 206 $status_color = 'indigo'; 207 $status_icon = 'fa-ban'; 208 $header->setStatus($status_icon, $status_color, $status_name); 209 } 210 } 211 212 $config_name = 'auth.email-domains'; 213 $config_href = '/config/edit/'.$config_name.'/'; 214 215 $email_domains = PhabricatorEnv::getEnvConfig($config_name); 216 if ($email_domains) { 217 $registration_warning = pht( 218 'Users will only be able to register with a verified email address '. 219 'at one of the configured [[ %s | %s ]] domains: **%s**', 220 $config_href, 221 $config_name, 222 implode(', ', $email_domains)); 223 } else { 224 $registration_warning = pht( 225 "NOTE: Any user who can browse to this install's login page will be ". 226 "able to register an account. To restrict who can register ". 227 "an account, configure [[ %s | %s ]].", 228 $config_href, 229 $config_name); 230 } 231 232 $str_login = array( 233 phutil_tag('strong', array(), pht('Allow Login:')), 234 ' ', 235 pht( 236 'Allow users to log in using this provider. If you disable login, '. 237 'users can still use account integrations for this provider.'), 238 ); 239 240 $str_registration = array( 241 phutil_tag('strong', array(), pht('Allow Registration:')), 242 ' ', 243 pht( 244 'Allow users to register new accounts using this provider. If you '. 245 'disable registration, users can still use this provider to log in '. 246 'to existing accounts, but will not be able to create new accounts.'), 247 ); 248 249 $str_link = hsprintf( 250 '<strong>%s:</strong> %s', 251 pht('Allow Linking Accounts'), 252 pht( 253 'Allow users to link account credentials for this provider to '. 254 'existing accounts. There is normally no reason to disable this '. 255 'unless you are trying to move away from a provider and want to '. 256 'stop users from creating new account links.')); 257 258 $str_unlink = hsprintf( 259 '<strong>%s:</strong> %s', 260 pht('Allow Unlinking Accounts'), 261 pht( 262 'Allow users to unlink account credentials for this provider from '. 263 'existing accounts. If you disable this, accounts will be '. 264 'permanently bound to provider accounts.')); 265 266 $str_trusted_email = hsprintf( 267 '<strong>%s:</strong> %s', 268 pht('Trust Email Addresses'), 269 pht( 270 'Skip email verification for accounts registered '. 271 'through this provider.')); 272 $str_auto_login = hsprintf( 273 '<strong>%s:</strong> %s', 274 pht('Allow Auto Login'), 275 pht( 276 'Automatically log in with this provider if it is '. 277 'the only available provider.')); 278 279 $form = id(new AphrontFormView()) 280 ->setUser($viewer) 281 ->addHiddenInput('provider', $provider_class) 282 ->appendChild( 283 id(new AphrontFormCheckboxControl()) 284 ->setLabel(pht('Allow')) 285 ->addCheckbox( 286 'allowLogin', 287 1, 288 $str_login, 289 $v_login)) 290 ->appendChild( 291 id(new AphrontFormCheckboxControl()) 292 ->addCheckbox( 293 'allowRegistration', 294 1, 295 $str_registration, 296 $v_registration)) 297 ->appendRemarkupInstructions($registration_warning) 298 ->appendChild( 299 id(new AphrontFormCheckboxControl()) 300 ->addCheckbox( 301 'allowLink', 302 1, 303 $str_link, 304 $v_link)) 305 ->appendChild( 306 id(new AphrontFormCheckboxControl()) 307 ->addCheckbox( 308 'allowUnlink', 309 1, 310 $str_unlink, 311 $v_unlink)); 312 313 if ($provider->shouldAllowEmailTrustConfiguration()) { 314 $form->appendChild( 315 id(new AphrontFormCheckboxControl()) 316 ->addCheckbox( 317 'trustEmails', 318 1, 319 $str_trusted_email, 320 $v_trust_email)); 321 } 322 323 if ($provider->supportsAutoLogin()) { 324 $form->appendChild( 325 id(new AphrontFormCheckboxControl()) 326 ->addCheckbox( 327 'autoLogin', 328 1, 329 $str_auto_login, 330 $v_auto_login)); 331 } 332 333 $provider->extendEditForm($request, $form, $properties, $issues); 334 335 $locked_config_key = 'auth.lock-config'; 336 $is_locked = PhabricatorEnv::getEnvConfig($locked_config_key); 337 338 $locked_warning = null; 339 if ($is_locked && !$validation_exception) { 340 $message = pht( 341 'Authentication provider configuration is locked, and can not be '. 342 'changed without being unlocked. See the configuration setting %s '. 343 'for details.', 344 phutil_tag( 345 'a', 346 array( 347 'href' => '/config/edit/'.$locked_config_key, 348 ), 349 $locked_config_key)); 350 $locked_warning = id(new PHUIInfoView()) 351 ->setViewer($viewer) 352 ->setSeverity(PHUIInfoView::SEVERITY_WARNING) 353 ->setErrors(array($message)); 354 } 355 356 $form 357 ->appendChild( 358 id(new AphrontFormSubmitControl()) 359 ->addCancelButton($cancel_uri) 360 ->setDisabled($is_locked) 361 ->setValue($button)); 362 363 364 $help = $provider->getConfigurationHelp(); 365 if ($help) { 366 $form->appendChild(id(new PHUIFormDividerControl())); 367 $form->appendRemarkupInstructions($help); 368 } 369 370 $footer = $provider->renderConfigurationFooter(); 371 372 $crumbs = $this->buildApplicationCrumbs(); 373 $crumbs->addTextCrumb($crumb); 374 $crumbs->setBorder(true); 375 376 $form_box = id(new PHUIObjectBoxView()) 377 ->setHeaderText(pht('Provider')) 378 ->setFormErrors($errors) 379 ->setValidationException($validation_exception) 380 ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 381 ->setForm($form); 382 383 384 385 $view = id(new PHUITwoColumnView()) 386 ->setHeader($header) 387 ->setFooter(array( 388 $locked_warning, 389 $form_box, 390 $footer, 391 )); 392 393 return $this->newPage() 394 ->setTitle($title) 395 ->setCrumbs($crumbs) 396 ->appendChild($view); 397 398 } 399 400}