mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-23 21:18:19 +01:00
(stable) Promote 2019 Week 7
This commit is contained in:
commit
dd060b94f0
129 changed files with 2004 additions and 904 deletions
|
@ -9,7 +9,7 @@ return array(
|
||||||
'names' => array(
|
'names' => array(
|
||||||
'conpherence.pkg.css' => '3c8a0668',
|
'conpherence.pkg.css' => '3c8a0668',
|
||||||
'conpherence.pkg.js' => '020aebcf',
|
'conpherence.pkg.js' => '020aebcf',
|
||||||
'core.pkg.css' => '7a73ffc5',
|
'core.pkg.css' => '85a1da99',
|
||||||
'core.pkg.js' => '5c737607',
|
'core.pkg.js' => '5c737607',
|
||||||
'differential.pkg.css' => 'b8df73d4',
|
'differential.pkg.css' => 'b8df73d4',
|
||||||
'differential.pkg.js' => '67c9ea4c',
|
'differential.pkg.js' => '67c9ea4c',
|
||||||
|
@ -30,7 +30,7 @@ return array(
|
||||||
'rsrc/css/aphront/notification.css' => '30240bd2',
|
'rsrc/css/aphront/notification.css' => '30240bd2',
|
||||||
'rsrc/css/aphront/panel-view.css' => '46923d46',
|
'rsrc/css/aphront/panel-view.css' => '46923d46',
|
||||||
'rsrc/css/aphront/phabricator-nav-view.css' => 'f8a0c1bf',
|
'rsrc/css/aphront/phabricator-nav-view.css' => 'f8a0c1bf',
|
||||||
'rsrc/css/aphront/table-view.css' => 'daa1f9df',
|
'rsrc/css/aphront/table-view.css' => '205053cd',
|
||||||
'rsrc/css/aphront/tokenizer.css' => 'b52d0668',
|
'rsrc/css/aphront/tokenizer.css' => 'b52d0668',
|
||||||
'rsrc/css/aphront/tooltip.css' => 'e3f2412f',
|
'rsrc/css/aphront/tooltip.css' => 'e3f2412f',
|
||||||
'rsrc/css/aphront/typeahead-browse.css' => 'b7ed02d2',
|
'rsrc/css/aphront/typeahead-browse.css' => 'b7ed02d2',
|
||||||
|
@ -46,7 +46,7 @@ return array(
|
||||||
'rsrc/css/application/config/config-options.css' => '16c920ae',
|
'rsrc/css/application/config/config-options.css' => '16c920ae',
|
||||||
'rsrc/css/application/config/config-template.css' => '20babf50',
|
'rsrc/css/application/config/config-template.css' => '20babf50',
|
||||||
'rsrc/css/application/config/setup-issue.css' => '5eed85b2',
|
'rsrc/css/application/config/setup-issue.css' => '5eed85b2',
|
||||||
'rsrc/css/application/config/unhandled-exception.css' => '9da8fdab',
|
'rsrc/css/application/config/unhandled-exception.css' => '9ecfc00d',
|
||||||
'rsrc/css/application/conpherence/color.css' => 'b17746b0',
|
'rsrc/css/application/conpherence/color.css' => 'b17746b0',
|
||||||
'rsrc/css/application/conpherence/durable-column.css' => '2d57072b',
|
'rsrc/css/application/conpherence/durable-column.css' => '2d57072b',
|
||||||
'rsrc/css/application/conpherence/header-pane.css' => 'c9a3db8e',
|
'rsrc/css/application/conpherence/header-pane.css' => 'c9a3db8e',
|
||||||
|
@ -151,7 +151,7 @@ return array(
|
||||||
'rsrc/css/phui/phui-document.css' => '52b748a5',
|
'rsrc/css/phui/phui-document.css' => '52b748a5',
|
||||||
'rsrc/css/phui/phui-feed-story.css' => 'a0c05029',
|
'rsrc/css/phui/phui-feed-story.css' => 'a0c05029',
|
||||||
'rsrc/css/phui/phui-fontkit.css' => '9b714a5e',
|
'rsrc/css/phui/phui-fontkit.css' => '9b714a5e',
|
||||||
'rsrc/css/phui/phui-form-view.css' => '0807e7ac',
|
'rsrc/css/phui/phui-form-view.css' => '01b796c0',
|
||||||
'rsrc/css/phui/phui-form.css' => '159e2d9c',
|
'rsrc/css/phui/phui-form.css' => '159e2d9c',
|
||||||
'rsrc/css/phui/phui-head-thing.css' => 'd7f293df',
|
'rsrc/css/phui/phui-head-thing.css' => 'd7f293df',
|
||||||
'rsrc/css/phui/phui-header-view.css' => '93cea4ec',
|
'rsrc/css/phui/phui-header-view.css' => '93cea4ec',
|
||||||
|
@ -164,7 +164,7 @@ return array(
|
||||||
'rsrc/css/phui/phui-left-right.css' => '68513c34',
|
'rsrc/css/phui/phui-left-right.css' => '68513c34',
|
||||||
'rsrc/css/phui/phui-lightbox.css' => '4ebf22da',
|
'rsrc/css/phui/phui-lightbox.css' => '4ebf22da',
|
||||||
'rsrc/css/phui/phui-list.css' => '470b1adb',
|
'rsrc/css/phui/phui-list.css' => '470b1adb',
|
||||||
'rsrc/css/phui/phui-object-box.css' => '9b58483d',
|
'rsrc/css/phui/phui-object-box.css' => 'f434b6be',
|
||||||
'rsrc/css/phui/phui-pager.css' => 'd022c7ad',
|
'rsrc/css/phui/phui-pager.css' => 'd022c7ad',
|
||||||
'rsrc/css/phui/phui-pinboard-view.css' => '1f08f5d8',
|
'rsrc/css/phui/phui-pinboard-view.css' => '1f08f5d8',
|
||||||
'rsrc/css/phui/phui-property-list-view.css' => 'cad62236',
|
'rsrc/css/phui/phui-property-list-view.css' => 'cad62236',
|
||||||
|
@ -502,6 +502,7 @@ return array(
|
||||||
'rsrc/js/phui/behavior-phui-selectable-list.js' => 'b26a41e4',
|
'rsrc/js/phui/behavior-phui-selectable-list.js' => 'b26a41e4',
|
||||||
'rsrc/js/phui/behavior-phui-submenu.js' => 'b5e9bff9',
|
'rsrc/js/phui/behavior-phui-submenu.js' => 'b5e9bff9',
|
||||||
'rsrc/js/phui/behavior-phui-tab-group.js' => '242aa08b',
|
'rsrc/js/phui/behavior-phui-tab-group.js' => '242aa08b',
|
||||||
|
'rsrc/js/phui/behavior-phui-timer-control.js' => 'f84bcbf4',
|
||||||
'rsrc/js/phuix/PHUIXActionListView.js' => 'c68f183f',
|
'rsrc/js/phuix/PHUIXActionListView.js' => 'c68f183f',
|
||||||
'rsrc/js/phuix/PHUIXActionView.js' => 'aaa08f3b',
|
'rsrc/js/phuix/PHUIXActionView.js' => 'aaa08f3b',
|
||||||
'rsrc/js/phuix/PHUIXAutocomplete.js' => '58cc4ab8',
|
'rsrc/js/phuix/PHUIXAutocomplete.js' => '58cc4ab8',
|
||||||
|
@ -519,7 +520,7 @@ return array(
|
||||||
'aphront-list-filter-view-css' => 'feb64255',
|
'aphront-list-filter-view-css' => 'feb64255',
|
||||||
'aphront-multi-column-view-css' => 'fbc00ba3',
|
'aphront-multi-column-view-css' => 'fbc00ba3',
|
||||||
'aphront-panel-view-css' => '46923d46',
|
'aphront-panel-view-css' => '46923d46',
|
||||||
'aphront-table-view-css' => 'daa1f9df',
|
'aphront-table-view-css' => '205053cd',
|
||||||
'aphront-tokenizer-control-css' => 'b52d0668',
|
'aphront-tokenizer-control-css' => 'b52d0668',
|
||||||
'aphront-tooltip-css' => 'e3f2412f',
|
'aphront-tooltip-css' => 'e3f2412f',
|
||||||
'aphront-typeahead-control-css' => '8779483d',
|
'aphront-typeahead-control-css' => '8779483d',
|
||||||
|
@ -650,6 +651,7 @@ return array(
|
||||||
'javelin-behavior-phui-selectable-list' => 'b26a41e4',
|
'javelin-behavior-phui-selectable-list' => 'b26a41e4',
|
||||||
'javelin-behavior-phui-submenu' => 'b5e9bff9',
|
'javelin-behavior-phui-submenu' => 'b5e9bff9',
|
||||||
'javelin-behavior-phui-tab-group' => '242aa08b',
|
'javelin-behavior-phui-tab-group' => '242aa08b',
|
||||||
|
'javelin-behavior-phui-timer-control' => 'f84bcbf4',
|
||||||
'javelin-behavior-phuix-example' => 'c2c500a7',
|
'javelin-behavior-phuix-example' => 'c2c500a7',
|
||||||
'javelin-behavior-policy-control' => '0eaa33a9',
|
'javelin-behavior-policy-control' => '0eaa33a9',
|
||||||
'javelin-behavior-policy-rule-editor' => '9347f172',
|
'javelin-behavior-policy-rule-editor' => '9347f172',
|
||||||
|
@ -817,7 +819,7 @@ return array(
|
||||||
'phui-font-icon-base-css' => 'd7994e06',
|
'phui-font-icon-base-css' => 'd7994e06',
|
||||||
'phui-fontkit-css' => '9b714a5e',
|
'phui-fontkit-css' => '9b714a5e',
|
||||||
'phui-form-css' => '159e2d9c',
|
'phui-form-css' => '159e2d9c',
|
||||||
'phui-form-view-css' => '0807e7ac',
|
'phui-form-view-css' => '01b796c0',
|
||||||
'phui-head-thing-view-css' => 'd7f293df',
|
'phui-head-thing-view-css' => 'd7f293df',
|
||||||
'phui-header-view-css' => '93cea4ec',
|
'phui-header-view-css' => '93cea4ec',
|
||||||
'phui-hovercard' => '074f0783',
|
'phui-hovercard' => '074f0783',
|
||||||
|
@ -831,7 +833,7 @@ return array(
|
||||||
'phui-left-right-css' => '68513c34',
|
'phui-left-right-css' => '68513c34',
|
||||||
'phui-lightbox-css' => '4ebf22da',
|
'phui-lightbox-css' => '4ebf22da',
|
||||||
'phui-list-view-css' => '470b1adb',
|
'phui-list-view-css' => '470b1adb',
|
||||||
'phui-object-box-css' => '9b58483d',
|
'phui-object-box-css' => 'f434b6be',
|
||||||
'phui-oi-big-ui-css' => '9e037c7a',
|
'phui-oi-big-ui-css' => '9e037c7a',
|
||||||
'phui-oi-color-css' => 'b517bfa0',
|
'phui-oi-color-css' => 'b517bfa0',
|
||||||
'phui-oi-drag-ui-css' => 'da15d3dc',
|
'phui-oi-drag-ui-css' => 'da15d3dc',
|
||||||
|
@ -877,7 +879,7 @@ return array(
|
||||||
'syntax-highlighting-css' => '8a16f91b',
|
'syntax-highlighting-css' => '8a16f91b',
|
||||||
'tokens-css' => 'ce5a50bd',
|
'tokens-css' => 'ce5a50bd',
|
||||||
'typeahead-browse-css' => 'b7ed02d2',
|
'typeahead-browse-css' => 'b7ed02d2',
|
||||||
'unhandled-exception-css' => '9da8fdab',
|
'unhandled-exception-css' => '9ecfc00d',
|
||||||
),
|
),
|
||||||
'requires' => array(
|
'requires' => array(
|
||||||
'01384686' => array(
|
'01384686' => array(
|
||||||
|
@ -2111,6 +2113,11 @@ return array(
|
||||||
'javelin-stratcom',
|
'javelin-stratcom',
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
),
|
),
|
||||||
|
'f84bcbf4' => array(
|
||||||
|
'javelin-behavior',
|
||||||
|
'javelin-stratcom',
|
||||||
|
'javelin-dom',
|
||||||
|
),
|
||||||
'f8c4e135' => array(
|
'f8c4e135' => array(
|
||||||
'javelin-install',
|
'javelin-install',
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE {$NAMESPACE}_user.user_externalaccount
|
||||||
|
ADD providerConfigPHID VARBINARY(64) NOT NULL;
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$account_table = new PhabricatorExternalAccount();
|
||||||
|
$account_conn = $account_table->establishConnection('w');
|
||||||
|
$table_name = $account_table->getTableName();
|
||||||
|
|
||||||
|
$config_table = new PhabricatorAuthProviderConfig();
|
||||||
|
$config_conn = $config_table->establishConnection('w');
|
||||||
|
|
||||||
|
foreach (new LiskRawMigrationIterator($account_conn, $table_name) as $row) {
|
||||||
|
if (strlen($row['providerConfigPHID'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$config_row = queryfx_one(
|
||||||
|
$config_conn,
|
||||||
|
'SELECT phid
|
||||||
|
FROM %R
|
||||||
|
WHERE providerType = %s AND providerDomain = %s
|
||||||
|
LIMIT 1',
|
||||||
|
$config_table,
|
||||||
|
$row['accountType'],
|
||||||
|
$row['accountDomain']);
|
||||||
|
if (!$config_row) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
queryfx(
|
||||||
|
$account_conn,
|
||||||
|
'UPDATE %R
|
||||||
|
SET providerConfigPHID = %s
|
||||||
|
WHERE id = %d',
|
||||||
|
$account_table,
|
||||||
|
$config_row['phid'],
|
||||||
|
$row['id']);
|
||||||
|
}
|
|
@ -1714,6 +1714,7 @@ phutil_register_library_map(array(
|
||||||
'ManiphestTaskFerretEngine' => 'applications/maniphest/search/ManiphestTaskFerretEngine.php',
|
'ManiphestTaskFerretEngine' => 'applications/maniphest/search/ManiphestTaskFerretEngine.php',
|
||||||
'ManiphestTaskFulltextEngine' => 'applications/maniphest/search/ManiphestTaskFulltextEngine.php',
|
'ManiphestTaskFulltextEngine' => 'applications/maniphest/search/ManiphestTaskFulltextEngine.php',
|
||||||
'ManiphestTaskGraph' => 'infrastructure/graph/ManiphestTaskGraph.php',
|
'ManiphestTaskGraph' => 'infrastructure/graph/ManiphestTaskGraph.php',
|
||||||
|
'ManiphestTaskGraphController' => 'applications/maniphest/controller/ManiphestTaskGraphController.php',
|
||||||
'ManiphestTaskHasCommitEdgeType' => 'applications/maniphest/edge/ManiphestTaskHasCommitEdgeType.php',
|
'ManiphestTaskHasCommitEdgeType' => 'applications/maniphest/edge/ManiphestTaskHasCommitEdgeType.php',
|
||||||
'ManiphestTaskHasCommitRelationship' => 'applications/maniphest/relationship/ManiphestTaskHasCommitRelationship.php',
|
'ManiphestTaskHasCommitRelationship' => 'applications/maniphest/relationship/ManiphestTaskHasCommitRelationship.php',
|
||||||
'ManiphestTaskHasDuplicateTaskEdgeType' => 'applications/maniphest/edge/ManiphestTaskHasDuplicateTaskEdgeType.php',
|
'ManiphestTaskHasDuplicateTaskEdgeType' => 'applications/maniphest/edge/ManiphestTaskHasDuplicateTaskEdgeType.php',
|
||||||
|
@ -2195,6 +2196,8 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorAuthChallengeGarbageCollector' => 'applications/auth/garbagecollector/PhabricatorAuthChallengeGarbageCollector.php',
|
'PhabricatorAuthChallengeGarbageCollector' => 'applications/auth/garbagecollector/PhabricatorAuthChallengeGarbageCollector.php',
|
||||||
'PhabricatorAuthChallengePHIDType' => 'applications/auth/phid/PhabricatorAuthChallengePHIDType.php',
|
'PhabricatorAuthChallengePHIDType' => 'applications/auth/phid/PhabricatorAuthChallengePHIDType.php',
|
||||||
'PhabricatorAuthChallengeQuery' => 'applications/auth/query/PhabricatorAuthChallengeQuery.php',
|
'PhabricatorAuthChallengeQuery' => 'applications/auth/query/PhabricatorAuthChallengeQuery.php',
|
||||||
|
'PhabricatorAuthChallengeStatusController' => 'applications/auth/controller/mfa/PhabricatorAuthChallengeStatusController.php',
|
||||||
|
'PhabricatorAuthChallengeUpdate' => 'applications/auth/view/PhabricatorAuthChallengeUpdate.php',
|
||||||
'PhabricatorAuthChangePasswordAction' => 'applications/auth/action/PhabricatorAuthChangePasswordAction.php',
|
'PhabricatorAuthChangePasswordAction' => 'applications/auth/action/PhabricatorAuthChangePasswordAction.php',
|
||||||
'PhabricatorAuthConduitAPIMethod' => 'applications/auth/conduit/PhabricatorAuthConduitAPIMethod.php',
|
'PhabricatorAuthConduitAPIMethod' => 'applications/auth/conduit/PhabricatorAuthConduitAPIMethod.php',
|
||||||
'PhabricatorAuthConduitTokenRevoker' => 'applications/auth/revoker/PhabricatorAuthConduitTokenRevoker.php',
|
'PhabricatorAuthConduitTokenRevoker' => 'applications/auth/revoker/PhabricatorAuthConduitTokenRevoker.php',
|
||||||
|
@ -2270,6 +2273,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorAuthInviteVerifyException' => 'applications/auth/exception/PhabricatorAuthInviteVerifyException.php',
|
'PhabricatorAuthInviteVerifyException' => 'applications/auth/exception/PhabricatorAuthInviteVerifyException.php',
|
||||||
'PhabricatorAuthInviteWorker' => 'applications/auth/worker/PhabricatorAuthInviteWorker.php',
|
'PhabricatorAuthInviteWorker' => 'applications/auth/worker/PhabricatorAuthInviteWorker.php',
|
||||||
'PhabricatorAuthLinkController' => 'applications/auth/controller/PhabricatorAuthLinkController.php',
|
'PhabricatorAuthLinkController' => 'applications/auth/controller/PhabricatorAuthLinkController.php',
|
||||||
|
'PhabricatorAuthLinkMessageType' => 'applications/auth/message/PhabricatorAuthLinkMessageType.php',
|
||||||
'PhabricatorAuthListController' => 'applications/auth/controller/config/PhabricatorAuthListController.php',
|
'PhabricatorAuthListController' => 'applications/auth/controller/config/PhabricatorAuthListController.php',
|
||||||
'PhabricatorAuthLoginController' => 'applications/auth/controller/PhabricatorAuthLoginController.php',
|
'PhabricatorAuthLoginController' => 'applications/auth/controller/PhabricatorAuthLoginController.php',
|
||||||
'PhabricatorAuthLoginMessageType' => 'applications/auth/message/PhabricatorAuthLoginMessageType.php',
|
'PhabricatorAuthLoginMessageType' => 'applications/auth/message/PhabricatorAuthLoginMessageType.php',
|
||||||
|
@ -2368,6 +2372,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorAuthSessionPHIDType' => 'applications/auth/phid/PhabricatorAuthSessionPHIDType.php',
|
'PhabricatorAuthSessionPHIDType' => 'applications/auth/phid/PhabricatorAuthSessionPHIDType.php',
|
||||||
'PhabricatorAuthSessionQuery' => 'applications/auth/query/PhabricatorAuthSessionQuery.php',
|
'PhabricatorAuthSessionQuery' => 'applications/auth/query/PhabricatorAuthSessionQuery.php',
|
||||||
'PhabricatorAuthSessionRevoker' => 'applications/auth/revoker/PhabricatorAuthSessionRevoker.php',
|
'PhabricatorAuthSessionRevoker' => 'applications/auth/revoker/PhabricatorAuthSessionRevoker.php',
|
||||||
|
'PhabricatorAuthSetExternalController' => 'applications/auth/controller/PhabricatorAuthSetExternalController.php',
|
||||||
'PhabricatorAuthSetPasswordController' => 'applications/auth/controller/PhabricatorAuthSetPasswordController.php',
|
'PhabricatorAuthSetPasswordController' => 'applications/auth/controller/PhabricatorAuthSetPasswordController.php',
|
||||||
'PhabricatorAuthSetupCheck' => 'applications/config/check/PhabricatorAuthSetupCheck.php',
|
'PhabricatorAuthSetupCheck' => 'applications/config/check/PhabricatorAuthSetupCheck.php',
|
||||||
'PhabricatorAuthStartController' => 'applications/auth/controller/PhabricatorAuthStartController.php',
|
'PhabricatorAuthStartController' => 'applications/auth/controller/PhabricatorAuthStartController.php',
|
||||||
|
@ -3867,7 +3872,6 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorPeopleInviteController' => 'applications/people/controller/PhabricatorPeopleInviteController.php',
|
'PhabricatorPeopleInviteController' => 'applications/people/controller/PhabricatorPeopleInviteController.php',
|
||||||
'PhabricatorPeopleInviteListController' => 'applications/people/controller/PhabricatorPeopleInviteListController.php',
|
'PhabricatorPeopleInviteListController' => 'applications/people/controller/PhabricatorPeopleInviteListController.php',
|
||||||
'PhabricatorPeopleInviteSendController' => 'applications/people/controller/PhabricatorPeopleInviteSendController.php',
|
'PhabricatorPeopleInviteSendController' => 'applications/people/controller/PhabricatorPeopleInviteSendController.php',
|
||||||
'PhabricatorPeopleLdapController' => 'applications/people/controller/PhabricatorPeopleLdapController.php',
|
|
||||||
'PhabricatorPeopleListController' => 'applications/people/controller/PhabricatorPeopleListController.php',
|
'PhabricatorPeopleListController' => 'applications/people/controller/PhabricatorPeopleListController.php',
|
||||||
'PhabricatorPeopleLogQuery' => 'applications/people/query/PhabricatorPeopleLogQuery.php',
|
'PhabricatorPeopleLogQuery' => 'applications/people/query/PhabricatorPeopleLogQuery.php',
|
||||||
'PhabricatorPeopleLogSearchEngine' => 'applications/people/query/PhabricatorPeopleLogSearchEngine.php',
|
'PhabricatorPeopleLogSearchEngine' => 'applications/people/query/PhabricatorPeopleLogSearchEngine.php',
|
||||||
|
@ -4987,6 +4991,7 @@ phutil_register_library_map(array(
|
||||||
'PhortuneAccountViewController' => 'applications/phortune/controller/account/PhortuneAccountViewController.php',
|
'PhortuneAccountViewController' => 'applications/phortune/controller/account/PhortuneAccountViewController.php',
|
||||||
'PhortuneAdHocCart' => 'applications/phortune/cart/PhortuneAdHocCart.php',
|
'PhortuneAdHocCart' => 'applications/phortune/cart/PhortuneAdHocCart.php',
|
||||||
'PhortuneAdHocProduct' => 'applications/phortune/product/PhortuneAdHocProduct.php',
|
'PhortuneAdHocProduct' => 'applications/phortune/product/PhortuneAdHocProduct.php',
|
||||||
|
'PhortuneAddPaymentMethodAction' => 'applications/phortune/action/PhortuneAddPaymentMethodAction.php',
|
||||||
'PhortuneCart' => 'applications/phortune/storage/PhortuneCart.php',
|
'PhortuneCart' => 'applications/phortune/storage/PhortuneCart.php',
|
||||||
'PhortuneCartAcceptController' => 'applications/phortune/controller/cart/PhortuneCartAcceptController.php',
|
'PhortuneCartAcceptController' => 'applications/phortune/controller/cart/PhortuneCartAcceptController.php',
|
||||||
'PhortuneCartCancelController' => 'applications/phortune/controller/cart/PhortuneCartCancelController.php',
|
'PhortuneCartCancelController' => 'applications/phortune/controller/cart/PhortuneCartCancelController.php',
|
||||||
|
@ -7397,6 +7402,7 @@ phutil_register_library_map(array(
|
||||||
'ManiphestTaskFerretEngine' => 'PhabricatorFerretEngine',
|
'ManiphestTaskFerretEngine' => 'PhabricatorFerretEngine',
|
||||||
'ManiphestTaskFulltextEngine' => 'PhabricatorFulltextEngine',
|
'ManiphestTaskFulltextEngine' => 'PhabricatorFulltextEngine',
|
||||||
'ManiphestTaskGraph' => 'PhabricatorObjectGraph',
|
'ManiphestTaskGraph' => 'PhabricatorObjectGraph',
|
||||||
|
'ManiphestTaskGraphController' => 'ManiphestController',
|
||||||
'ManiphestTaskHasCommitEdgeType' => 'PhabricatorEdgeType',
|
'ManiphestTaskHasCommitEdgeType' => 'PhabricatorEdgeType',
|
||||||
'ManiphestTaskHasCommitRelationship' => 'ManiphestTaskRelationship',
|
'ManiphestTaskHasCommitRelationship' => 'ManiphestTaskRelationship',
|
||||||
'ManiphestTaskHasDuplicateTaskEdgeType' => 'PhabricatorEdgeType',
|
'ManiphestTaskHasDuplicateTaskEdgeType' => 'PhabricatorEdgeType',
|
||||||
|
@ -7925,6 +7931,8 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorAuthChallengeGarbageCollector' => 'PhabricatorGarbageCollector',
|
'PhabricatorAuthChallengeGarbageCollector' => 'PhabricatorGarbageCollector',
|
||||||
'PhabricatorAuthChallengePHIDType' => 'PhabricatorPHIDType',
|
'PhabricatorAuthChallengePHIDType' => 'PhabricatorPHIDType',
|
||||||
'PhabricatorAuthChallengeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'PhabricatorAuthChallengeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
|
'PhabricatorAuthChallengeStatusController' => 'PhabricatorAuthController',
|
||||||
|
'PhabricatorAuthChallengeUpdate' => 'Phobject',
|
||||||
'PhabricatorAuthChangePasswordAction' => 'PhabricatorSystemAction',
|
'PhabricatorAuthChangePasswordAction' => 'PhabricatorSystemAction',
|
||||||
'PhabricatorAuthConduitAPIMethod' => 'ConduitAPIMethod',
|
'PhabricatorAuthConduitAPIMethod' => 'ConduitAPIMethod',
|
||||||
'PhabricatorAuthConduitTokenRevoker' => 'PhabricatorAuthRevoker',
|
'PhabricatorAuthConduitTokenRevoker' => 'PhabricatorAuthRevoker',
|
||||||
|
@ -8019,6 +8027,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorAuthInviteVerifyException' => 'PhabricatorAuthInviteDialogException',
|
'PhabricatorAuthInviteVerifyException' => 'PhabricatorAuthInviteDialogException',
|
||||||
'PhabricatorAuthInviteWorker' => 'PhabricatorWorker',
|
'PhabricatorAuthInviteWorker' => 'PhabricatorWorker',
|
||||||
'PhabricatorAuthLinkController' => 'PhabricatorAuthController',
|
'PhabricatorAuthLinkController' => 'PhabricatorAuthController',
|
||||||
|
'PhabricatorAuthLinkMessageType' => 'PhabricatorAuthMessageType',
|
||||||
'PhabricatorAuthListController' => 'PhabricatorAuthProviderConfigController',
|
'PhabricatorAuthListController' => 'PhabricatorAuthProviderConfigController',
|
||||||
'PhabricatorAuthLoginController' => 'PhabricatorAuthController',
|
'PhabricatorAuthLoginController' => 'PhabricatorAuthController',
|
||||||
'PhabricatorAuthLoginMessageType' => 'PhabricatorAuthMessageType',
|
'PhabricatorAuthLoginMessageType' => 'PhabricatorAuthMessageType',
|
||||||
|
@ -8138,6 +8147,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorAuthSessionPHIDType' => 'PhabricatorPHIDType',
|
'PhabricatorAuthSessionPHIDType' => 'PhabricatorPHIDType',
|
||||||
'PhabricatorAuthSessionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'PhabricatorAuthSessionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'PhabricatorAuthSessionRevoker' => 'PhabricatorAuthRevoker',
|
'PhabricatorAuthSessionRevoker' => 'PhabricatorAuthRevoker',
|
||||||
|
'PhabricatorAuthSetExternalController' => 'PhabricatorAuthController',
|
||||||
'PhabricatorAuthSetPasswordController' => 'PhabricatorAuthController',
|
'PhabricatorAuthSetPasswordController' => 'PhabricatorAuthController',
|
||||||
'PhabricatorAuthSetupCheck' => 'PhabricatorSetupCheck',
|
'PhabricatorAuthSetupCheck' => 'PhabricatorSetupCheck',
|
||||||
'PhabricatorAuthStartController' => 'PhabricatorAuthController',
|
'PhabricatorAuthStartController' => 'PhabricatorAuthController',
|
||||||
|
@ -9866,7 +9876,6 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorPeopleInviteController' => 'PhabricatorPeopleController',
|
'PhabricatorPeopleInviteController' => 'PhabricatorPeopleController',
|
||||||
'PhabricatorPeopleInviteListController' => 'PhabricatorPeopleInviteController',
|
'PhabricatorPeopleInviteListController' => 'PhabricatorPeopleInviteController',
|
||||||
'PhabricatorPeopleInviteSendController' => 'PhabricatorPeopleInviteController',
|
'PhabricatorPeopleInviteSendController' => 'PhabricatorPeopleInviteController',
|
||||||
'PhabricatorPeopleLdapController' => 'PhabricatorPeopleController',
|
|
||||||
'PhabricatorPeopleListController' => 'PhabricatorPeopleController',
|
'PhabricatorPeopleListController' => 'PhabricatorPeopleController',
|
||||||
'PhabricatorPeopleLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'PhabricatorPeopleLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'PhabricatorPeopleLogSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
'PhabricatorPeopleLogSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||||
|
@ -11229,6 +11238,7 @@ phutil_register_library_map(array(
|
||||||
'PhortuneAccountViewController' => 'PhortuneAccountProfileController',
|
'PhortuneAccountViewController' => 'PhortuneAccountProfileController',
|
||||||
'PhortuneAdHocCart' => 'PhortuneCartImplementation',
|
'PhortuneAdHocCart' => 'PhortuneCartImplementation',
|
||||||
'PhortuneAdHocProduct' => 'PhortuneProductImplementation',
|
'PhortuneAdHocProduct' => 'PhortuneProductImplementation',
|
||||||
|
'PhortuneAddPaymentMethodAction' => 'PhabricatorSystemAction',
|
||||||
'PhortuneCart' => array(
|
'PhortuneCart' => array(
|
||||||
'PhortuneDAO',
|
'PhortuneDAO',
|
||||||
'PhabricatorApplicationTransactionInterface',
|
'PhabricatorApplicationTransactionInterface',
|
||||||
|
|
|
@ -594,7 +594,7 @@ final class AphrontRequest extends Phobject {
|
||||||
$request_uri = idx($_SERVER, 'REQUEST_URI', '/');
|
$request_uri = idx($_SERVER, 'REQUEST_URI', '/');
|
||||||
|
|
||||||
$uri = new PhutilURI($request_uri);
|
$uri = new PhutilURI($request_uri);
|
||||||
$uri->setQueryParam('__path__', null);
|
$uri->removeQueryParam('__path__');
|
||||||
|
|
||||||
$path = phutil_escape_uri($this->getPath());
|
$path = phutil_escape_uri($this->getPath());
|
||||||
$uri->setPath($path);
|
$uri->setPath($path);
|
||||||
|
@ -829,7 +829,10 @@ final class AphrontRequest extends Phobject {
|
||||||
}
|
}
|
||||||
|
|
||||||
$uri->setPath($this->getPath());
|
$uri->setPath($this->getPath());
|
||||||
$uri->setQueryParams(self::flattenData($_GET));
|
$uri->removeAllQueryParams();
|
||||||
|
foreach (self::flattenData($_GET) as $query_key => $query_value) {
|
||||||
|
$uri->appendQueryParam($query_key, $query_value);
|
||||||
|
}
|
||||||
|
|
||||||
$input = PhabricatorStartup::getRawInput();
|
$input = PhabricatorStartup::getRawInput();
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,12 @@ final class AphrontApplicationConfiguration
|
||||||
$database_exception = $ex;
|
$database_exception = $ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we're in developer mode, set a flag so that top-level exception
|
||||||
|
// handlers can add more information.
|
||||||
|
if (PhabricatorEnv::getEnvConfig('phabricator.developer-mode')) {
|
||||||
|
$sink->setShowStackTraces(true);
|
||||||
|
}
|
||||||
|
|
||||||
if ($database_exception) {
|
if ($database_exception) {
|
||||||
$issue = PhabricatorSetupIssue::newDatabaseConnectionIssue(
|
$issue = PhabricatorSetupIssue::newDatabaseConnectionIssue(
|
||||||
$database_exception,
|
$database_exception,
|
||||||
|
@ -282,23 +288,69 @@ final class AphrontApplicationConfiguration
|
||||||
}
|
}
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
$original_exception = $ex;
|
$original_exception = $ex;
|
||||||
$response = $this->handleThrowable($ex);
|
|
||||||
} catch (Throwable $ex) {
|
} catch (Throwable $ex) {
|
||||||
$original_exception = $ex;
|
$original_exception = $ex;
|
||||||
$response = $this->handleThrowable($ex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$response_exception = null;
|
||||||
try {
|
try {
|
||||||
|
if ($original_exception) {
|
||||||
|
$response = $this->handleThrowable($original_exception);
|
||||||
|
}
|
||||||
|
|
||||||
$response = $this->produceResponse($request, $response);
|
$response = $this->produceResponse($request, $response);
|
||||||
$response = $controller->willSendResponse($response);
|
$response = $controller->willSendResponse($response);
|
||||||
$response->setRequest($request);
|
$response->setRequest($request);
|
||||||
|
|
||||||
self::writeResponse($sink, $response);
|
self::writeResponse($sink, $response);
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
|
$response_exception = $ex;
|
||||||
|
} catch (Throwable $ex) {
|
||||||
|
$response_exception = $ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($response_exception) {
|
||||||
|
// If we encountered an exception while building a normal response, then
|
||||||
|
// encountered another exception while building a response for the first
|
||||||
|
// exception, just throw the original exception. It is more likely to be
|
||||||
|
// useful and point at a root cause than the second exception we ran into
|
||||||
|
// while telling the user about it.
|
||||||
if ($original_exception) {
|
if ($original_exception) {
|
||||||
throw $original_exception;
|
throw $original_exception;
|
||||||
}
|
}
|
||||||
throw $ex;
|
|
||||||
|
// If we built a response successfully and then ran into an exception
|
||||||
|
// trying to render it, try to handle and present that exception to the
|
||||||
|
// user using the standard handler.
|
||||||
|
|
||||||
|
// The problem here might be in rendering (more common) or in the actual
|
||||||
|
// response mechanism (less common). If it's in rendering, we can likely
|
||||||
|
// still render a nice exception page: the majority of rendering issues
|
||||||
|
// are in main page content, not content shared with the exception page.
|
||||||
|
|
||||||
|
$handling_exception = null;
|
||||||
|
try {
|
||||||
|
$response = $this->handleThrowable($response_exception);
|
||||||
|
|
||||||
|
$response = $this->produceResponse($request, $response);
|
||||||
|
$response = $controller->willSendResponse($response);
|
||||||
|
$response->setRequest($request);
|
||||||
|
|
||||||
|
self::writeResponse($sink, $response);
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
$handling_exception = $ex;
|
||||||
|
} catch (Throwable $ex) {
|
||||||
|
$handling_exception = $ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we didn't have any luck with that, raise the original response
|
||||||
|
// exception. As above, this is the root cause exception and more likely
|
||||||
|
// to be useful. This will go to the fallback error handler at top
|
||||||
|
// level.
|
||||||
|
|
||||||
|
if ($handling_exception) {
|
||||||
|
throw $response_exception;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
|
|
|
@ -32,22 +32,21 @@ final class AphrontAjaxResponse extends AphrontResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildResponseString() {
|
public function buildResponseString() {
|
||||||
|
$request = $this->getRequest();
|
||||||
$console = $this->getConsole();
|
$console = $this->getConsole();
|
||||||
if ($console) {
|
if ($console) {
|
||||||
// NOTE: We're stripping query parameters here both for readability and
|
// NOTE: We're stripping query parameters here both for readability and
|
||||||
// to mitigate BREACH and similar attacks. The parameters are available
|
// to mitigate BREACH and similar attacks. The parameters are available
|
||||||
// in the "Request" tab, so this should not impact usability. See T3684.
|
// in the "Request" tab, so this should not impact usability. See T3684.
|
||||||
$uri = $this->getRequest()->getRequestURI();
|
$path = $request->getPath();
|
||||||
$uri = new PhutilURI($uri);
|
|
||||||
$uri->setQueryParams(array());
|
|
||||||
|
|
||||||
Javelin::initBehavior(
|
Javelin::initBehavior(
|
||||||
'dark-console',
|
'dark-console',
|
||||||
array(
|
array(
|
||||||
'uri' => (string)$uri,
|
'uri' => $path,
|
||||||
'key' => $console->getKey($this->getRequest()),
|
'key' => $console->getKey($request),
|
||||||
'color' => $console->getColor(),
|
'color' => $console->getColor(),
|
||||||
'quicksand' => $this->getRequest()->isQuicksand(),
|
'quicksand' => $request->isQuicksand(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +59,6 @@ final class AphrontAjaxResponse extends AphrontResponse {
|
||||||
|
|
||||||
$response = CelerityAPI::getStaticResourceResponse();
|
$response = CelerityAPI::getStaticResourceResponse();
|
||||||
|
|
||||||
$request = $this->getRequest();
|
|
||||||
if ($request) {
|
if ($request) {
|
||||||
$viewer = $request->getViewer();
|
$viewer = $request->getViewer();
|
||||||
if ($viewer) {
|
if ($viewer) {
|
||||||
|
|
|
@ -218,7 +218,7 @@ abstract class AphrontResponse extends Phobject {
|
||||||
$uri = id(new PhutilURI($uri))
|
$uri = id(new PhutilURI($uri))
|
||||||
->setPath(null)
|
->setPath(null)
|
||||||
->setFragment(null)
|
->setFragment(null)
|
||||||
->setQueryParams(array());
|
->removeAllQueryParams();
|
||||||
|
|
||||||
$uri = (string)$uri;
|
$uri = (string)$uri;
|
||||||
if (preg_match('/[ ;\']/', $uri)) {
|
if (preg_match('/[ ;\']/', $uri)) {
|
||||||
|
|
|
@ -4,8 +4,20 @@ final class AphrontUnhandledExceptionResponse
|
||||||
extends AphrontStandaloneHTMLResponse {
|
extends AphrontStandaloneHTMLResponse {
|
||||||
|
|
||||||
private $exception;
|
private $exception;
|
||||||
|
private $showStackTraces;
|
||||||
|
|
||||||
|
public function setShowStackTraces($show_stack_traces) {
|
||||||
|
$this->showStackTraces = $show_stack_traces;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getShowStackTraces() {
|
||||||
|
return $this->showStackTraces;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setException($exception) {
|
||||||
|
// NOTE: We accept an Exception or a Throwable.
|
||||||
|
|
||||||
public function setException(Exception $exception) {
|
|
||||||
// Log the exception unless it's specifically a silent malformed request
|
// Log the exception unless it's specifically a silent malformed request
|
||||||
// exception.
|
// exception.
|
||||||
|
|
||||||
|
@ -61,10 +73,36 @@ final class AphrontUnhandledExceptionResponse
|
||||||
$body = $ex->getMessage();
|
$body = $ex->getMessage();
|
||||||
$body = phutil_escape_html_newlines($body);
|
$body = phutil_escape_html_newlines($body);
|
||||||
|
|
||||||
|
$classes = array();
|
||||||
|
$classes[] = 'unhandled-exception-detail';
|
||||||
|
|
||||||
|
$stack = null;
|
||||||
|
if ($this->getShowStackTraces()) {
|
||||||
|
try {
|
||||||
|
$stack = id(new AphrontStackTraceView())
|
||||||
|
->setTrace($ex->getTrace());
|
||||||
|
|
||||||
|
$stack = hsprintf('%s', $stack);
|
||||||
|
|
||||||
|
$stack = phutil_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => 'unhandled-exception-stack',
|
||||||
|
),
|
||||||
|
$stack);
|
||||||
|
|
||||||
|
$classes[] = 'unhandled-exception-with-stack';
|
||||||
|
} catch (Exception $trace_exception) {
|
||||||
|
$stack = null;
|
||||||
|
} catch (Throwable $trace_exception) {
|
||||||
|
$stack = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return phutil_tag(
|
return phutil_tag(
|
||||||
'div',
|
'div',
|
||||||
array(
|
array(
|
||||||
'class' => 'unhandled-exception-detail',
|
'class' => implode(' ', $classes),
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
phutil_tag(
|
phutil_tag(
|
||||||
|
@ -79,6 +117,7 @@ final class AphrontUnhandledExceptionResponse
|
||||||
'class' => 'unhandled-exception-body',
|
'class' => 'unhandled-exception-body',
|
||||||
),
|
),
|
||||||
$body),
|
$body),
|
||||||
|
$stack,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,14 +5,22 @@
|
||||||
* Normally this is just @{class:AphrontPHPHTTPSink}, which uses "echo" and
|
* Normally this is just @{class:AphrontPHPHTTPSink}, which uses "echo" and
|
||||||
* "header()" to emit responses.
|
* "header()" to emit responses.
|
||||||
*
|
*
|
||||||
* Mostly, this class allows us to do install security or metrics hooks in the
|
|
||||||
* output pipeline.
|
|
||||||
*
|
|
||||||
* @task write Writing Response Components
|
* @task write Writing Response Components
|
||||||
* @task emit Emitting the Response
|
* @task emit Emitting the Response
|
||||||
*/
|
*/
|
||||||
abstract class AphrontHTTPSink extends Phobject {
|
abstract class AphrontHTTPSink extends Phobject {
|
||||||
|
|
||||||
|
private $showStackTraces = false;
|
||||||
|
|
||||||
|
final public function setShowStackTraces($show_stack_traces) {
|
||||||
|
$this->showStackTraces = $show_stack_traces;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function getShowStackTraces() {
|
||||||
|
return $this->showStackTraces;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( Writing Response Components )---------------------------------------- */
|
/* -( Writing Response Components )---------------------------------------- */
|
||||||
|
|
||||||
|
|
|
@ -67,19 +67,13 @@ abstract class AlmanacController
|
||||||
$is_builtin = isset($builtins[$key]);
|
$is_builtin = isset($builtins[$key]);
|
||||||
$is_persistent = (bool)$property->getID();
|
$is_persistent = (bool)$property->getID();
|
||||||
|
|
||||||
$delete_uri = id(new PhutilURI($delete_base))
|
$params = array(
|
||||||
->setQueryParams(
|
|
||||||
array(
|
|
||||||
'key' => $key,
|
'key' => $key,
|
||||||
'objectPHID' => $object->getPHID(),
|
'objectPHID' => $object->getPHID(),
|
||||||
));
|
);
|
||||||
|
|
||||||
$edit_uri = id(new PhutilURI($edit_base))
|
$delete_uri = new PhutilURI($delete_base, $params);
|
||||||
->setQueryParams(
|
$edit_uri = new PhutilURI($edit_base, $params);
|
||||||
array(
|
|
||||||
'key' => $key,
|
|
||||||
'objectPHID' => $object->getPHID(),
|
|
||||||
));
|
|
||||||
|
|
||||||
$delete = javelin_tag(
|
$delete = javelin_tag(
|
||||||
'a',
|
'a',
|
||||||
|
@ -143,7 +137,7 @@ abstract class AlmanacController
|
||||||
|
|
||||||
$phid = $object->getPHID();
|
$phid = $object->getPHID();
|
||||||
$add_uri = id(new PhutilURI($edit_base))
|
$add_uri = id(new PhutilURI($edit_base))
|
||||||
->setQueryParam('objectPHID', $object->getPHID());
|
->replaceQueryParam('objectPHID', $object->getPHID());
|
||||||
|
|
||||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||||
$viewer,
|
$viewer,
|
||||||
|
|
|
@ -105,10 +105,10 @@ final class PhabricatorAuditManagementDeleteWorkflow
|
||||||
$query->withPHIDs(mpull($commits, 'getPHID'));
|
$query->withPHIDs(mpull($commits, 'getPHID'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$commits = $query->execute();
|
$commit_iterator = new PhabricatorQueryIterator($query);
|
||||||
$commits = mpull($commits, null, 'getPHID');
|
|
||||||
$audits = array();
|
$audits = array();
|
||||||
foreach ($commits as $commit) {
|
foreach ($commit_iterator as $commit) {
|
||||||
$commit_audits = $commit->getAudits();
|
$commit_audits = $commit->getAudits();
|
||||||
foreach ($commit_audits as $key => $audit) {
|
foreach ($commit_audits as $key => $audit) {
|
||||||
if ($id_map && empty($id_map[$audit->getID()])) {
|
if ($id_map && empty($id_map[$audit->getID()])) {
|
||||||
|
@ -131,51 +131,87 @@ final class PhabricatorAuditManagementDeleteWorkflow
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$audits[] = $commit_audits;
|
|
||||||
}
|
|
||||||
$audits = array_mergev($audits);
|
|
||||||
|
|
||||||
$console = PhutilConsole::getConsole();
|
if (!$commit_audits) {
|
||||||
|
continue;
|
||||||
if (!$audits) {
|
|
||||||
$console->writeErr("%s\n", pht('No audits match the query.'));
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$handles = id(new PhabricatorHandleQuery())
|
$handles = id(new PhabricatorHandleQuery())
|
||||||
->setViewer($this->getViewer())
|
->setViewer($viewer)
|
||||||
->withPHIDs(mpull($audits, 'getAuditorPHID'))
|
->withPHIDs(mpull($commit_audits, 'getAuditorPHID'))
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
|
foreach ($commit_audits as $audit) {
|
||||||
|
$audit_id = $audit->getID();
|
||||||
|
|
||||||
foreach ($audits as $audit) {
|
$description = sprintf(
|
||||||
$commit = $commits[$audit->getCommitPHID()];
|
|
||||||
|
|
||||||
$console->writeOut(
|
|
||||||
"%s\n",
|
|
||||||
sprintf(
|
|
||||||
'%10d %-16s %-16s %s: %s',
|
'%10d %-16s %-16s %s: %s',
|
||||||
$audit->getID(),
|
$audit_id,
|
||||||
$handles[$audit->getAuditorPHID()]->getName(),
|
$handles[$audit->getAuditorPHID()]->getName(),
|
||||||
PhabricatorAuditStatusConstants::getStatusName(
|
PhabricatorAuditStatusConstants::getStatusName(
|
||||||
$audit->getAuditStatus()),
|
$audit->getAuditStatus()),
|
||||||
$commit->getRepository()->formatCommitName(
|
$commit->getRepository()->formatCommitName(
|
||||||
$commit->getCommitIdentifier()),
|
$commit->getCommitIdentifier()),
|
||||||
trim($commit->getSummary())));
|
trim($commit->getSummary()));
|
||||||
|
|
||||||
|
$audits[] = array(
|
||||||
|
'auditID' => $audit_id,
|
||||||
|
'commitPHID' => $commit->getPHID(),
|
||||||
|
'description' => $description,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$audits) {
|
||||||
|
echo tsprintf(
|
||||||
|
"%s\n",
|
||||||
|
pht('No audits match the query.'));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($audits as $audit_spec) {
|
||||||
|
echo tsprintf(
|
||||||
|
"%s\n",
|
||||||
|
$audit_spec['description']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($is_dry_run) {
|
||||||
|
echo tsprintf(
|
||||||
|
"%s\n",
|
||||||
|
pht('This is a dry run, so no changes will be made.'));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$is_dry_run) {
|
|
||||||
$message = pht(
|
$message = pht(
|
||||||
'Really delete these %d audit(s)? They will be permanently deleted '.
|
'Really delete these %s audit(s)? They will be permanently deleted '.
|
||||||
'and can not be recovered.',
|
'and can not be recovered.',
|
||||||
count($audits));
|
phutil_count($audits));
|
||||||
if ($console->confirm($message)) {
|
if (!phutil_console_confirm($message)) {
|
||||||
|
echo tsprintf(
|
||||||
|
"%s\n",
|
||||||
|
pht('User aborted the workflow.'));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$audits_by_commit = igroup($audits, 'commitPHID');
|
||||||
|
foreach ($audits_by_commit as $commit_phid => $audit_specs) {
|
||||||
|
$audit_ids = ipull($audit_specs, 'auditID');
|
||||||
|
|
||||||
|
$audits = id(new PhabricatorRepositoryAuditRequest())->loadAllWhere(
|
||||||
|
'id IN (%Ld)',
|
||||||
|
$audit_ids);
|
||||||
|
|
||||||
foreach ($audits as $audit) {
|
foreach ($audits as $audit) {
|
||||||
$id = $audit->getID();
|
$id = $audit->getID();
|
||||||
$console->writeOut("%s\n", pht('Deleting audit %d...', $id));
|
|
||||||
|
echo tsprintf(
|
||||||
|
"%s\n",
|
||||||
|
pht('Deleting audit %d...', $id));
|
||||||
|
|
||||||
$audit->delete();
|
$audit->delete();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
$this->synchronizeCommitAuditState($commit_phid);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -87,4 +87,39 @@ abstract class PhabricatorAuditManagementWorkflow
|
||||||
return $commits;
|
return $commits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function synchronizeCommitAuditState($commit_phid) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$commit = id(new DiffusionCommitQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withPHIDs(array($commit_phid))
|
||||||
|
->needAuditRequests(true)
|
||||||
|
->executeOne();
|
||||||
|
if (!$commit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$old_status = $commit->getAuditStatusObject();
|
||||||
|
$commit->updateAuditStatus($commit->getAudits());
|
||||||
|
$new_status = $commit->getAuditStatusObject();
|
||||||
|
|
||||||
|
if ($old_status->getKey() == $new_status->getKey()) {
|
||||||
|
echo tsprintf(
|
||||||
|
"%s\n",
|
||||||
|
pht(
|
||||||
|
'No synchronization changes for "%s".',
|
||||||
|
$commit->getDisplayName()));
|
||||||
|
} else {
|
||||||
|
echo tsprintf(
|
||||||
|
"%s\n",
|
||||||
|
pht(
|
||||||
|
'Synchronizing "%s": "%s" -> "%s".',
|
||||||
|
$commit->getDisplayName(),
|
||||||
|
$old_status->getName(),
|
||||||
|
$new_status->getName()));
|
||||||
|
|
||||||
|
$commit->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,16 @@ final class PhabricatorAuditSynchronizeManagementWorkflow
|
||||||
protected function didConstruct() {
|
protected function didConstruct() {
|
||||||
$this
|
$this
|
||||||
->setName('synchronize')
|
->setName('synchronize')
|
||||||
->setExamples('**synchronize** ...')
|
->setExamples(
|
||||||
->setSynopsis(pht('Update audit status for commits.'))
|
"**synchronize** __repository__ ...\n".
|
||||||
|
"**synchronize** __commit__ ...\n".
|
||||||
|
"**synchronize** --all")
|
||||||
|
->setSynopsis(
|
||||||
|
pht(
|
||||||
|
'Update commits to make their summary audit state reflect the '.
|
||||||
|
'state of their actual audit requests. This can fix inconsistencies '.
|
||||||
|
'in database state if audit requests have been mangled '.
|
||||||
|
'accidentally (or on purpose).'))
|
||||||
->setArguments(
|
->setArguments(
|
||||||
array_merge(
|
array_merge(
|
||||||
$this->getCommitConstraintArguments(),
|
$this->getCommitConstraintArguments(),
|
||||||
|
@ -21,36 +29,7 @@ final class PhabricatorAuditSynchronizeManagementWorkflow
|
||||||
foreach ($objects as $object) {
|
foreach ($objects as $object) {
|
||||||
$commits = $this->loadCommitsForConstraintObject($object);
|
$commits = $this->loadCommitsForConstraintObject($object);
|
||||||
foreach ($commits as $commit) {
|
foreach ($commits as $commit) {
|
||||||
$commit = id(new DiffusionCommitQuery())
|
$this->synchronizeCommitAuditState($commit->getPHID());
|
||||||
->setViewer($viewer)
|
|
||||||
->withPHIDs(array($commit->getPHID()))
|
|
||||||
->needAuditRequests(true)
|
|
||||||
->executeOne();
|
|
||||||
if (!$commit) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$old_status = $commit->getAuditStatusObject();
|
|
||||||
$commit->updateAuditStatus($commit->getAudits());
|
|
||||||
$new_status = $commit->getAuditStatusObject();
|
|
||||||
|
|
||||||
if ($old_status->getKey() == $new_status->getKey()) {
|
|
||||||
echo tsprintf(
|
|
||||||
"%s\n",
|
|
||||||
pht(
|
|
||||||
'No changes for "%s".',
|
|
||||||
$commit->getDisplayName()));
|
|
||||||
} else {
|
|
||||||
echo tsprintf(
|
|
||||||
"%s\n",
|
|
||||||
pht(
|
|
||||||
'Updating "%s": "%s" -> "%s".',
|
|
||||||
$commit->getDisplayName(),
|
|
||||||
$old_status->getName(),
|
|
||||||
$new_status->getName()));
|
|
||||||
|
|
||||||
$commit->save();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,8 +61,8 @@ final class PhabricatorAuthApplication extends PhabricatorApplication {
|
||||||
'start/' => 'PhabricatorAuthStartController',
|
'start/' => 'PhabricatorAuthStartController',
|
||||||
'validate/' => 'PhabricatorAuthValidateController',
|
'validate/' => 'PhabricatorAuthValidateController',
|
||||||
'finish/' => 'PhabricatorAuthFinishController',
|
'finish/' => 'PhabricatorAuthFinishController',
|
||||||
'unlink/(?P<pkey>[^/]+)/' => 'PhabricatorAuthUnlinkController',
|
'unlink/(?P<id>\d+)/' => 'PhabricatorAuthUnlinkController',
|
||||||
'(?P<action>link|refresh)/(?P<pkey>[^/]+)/'
|
'(?P<action>link|refresh)/(?P<id>\d+)/'
|
||||||
=> 'PhabricatorAuthLinkController',
|
=> 'PhabricatorAuthLinkController',
|
||||||
'confirmlink/(?P<akey>[^/]+)/'
|
'confirmlink/(?P<akey>[^/]+)/'
|
||||||
=> 'PhabricatorAuthConfirmLinkController',
|
=> 'PhabricatorAuthConfirmLinkController',
|
||||||
|
@ -86,7 +86,9 @@ final class PhabricatorAuthApplication extends PhabricatorApplication {
|
||||||
=> 'PhabricatorAuthSSHKeyRevokeController',
|
=> 'PhabricatorAuthSSHKeyRevokeController',
|
||||||
'view/(?P<id>\d+)/' => 'PhabricatorAuthSSHKeyViewController',
|
'view/(?P<id>\d+)/' => 'PhabricatorAuthSSHKeyViewController',
|
||||||
),
|
),
|
||||||
|
|
||||||
'password/' => 'PhabricatorAuthSetPasswordController',
|
'password/' => 'PhabricatorAuthSetPasswordController',
|
||||||
|
'external/' => 'PhabricatorAuthSetExternalController',
|
||||||
|
|
||||||
'mfa/' => array(
|
'mfa/' => array(
|
||||||
$this->getQueryRoutePattern() =>
|
$this->getQueryRoutePattern() =>
|
||||||
|
@ -97,6 +99,8 @@ final class PhabricatorAuthApplication extends PhabricatorApplication {
|
||||||
'PhabricatorAuthFactorProviderViewController',
|
'PhabricatorAuthFactorProviderViewController',
|
||||||
'message/(?P<id>[1-9]\d*)/' =>
|
'message/(?P<id>[1-9]\d*)/' =>
|
||||||
'PhabricatorAuthFactorProviderMessageController',
|
'PhabricatorAuthFactorProviderMessageController',
|
||||||
|
'challenge/status/(?P<id>[1-9]\d*)/' =>
|
||||||
|
'PhabricatorAuthChallengeStatusController',
|
||||||
),
|
),
|
||||||
|
|
||||||
'message/' => array(
|
'message/' => array(
|
||||||
|
|
|
@ -20,7 +20,15 @@ final class PhabricatorAuthConfirmLinkController
|
||||||
|
|
||||||
$panel_uri = '/settings/panel/external/';
|
$panel_uri = '/settings/panel/external/';
|
||||||
|
|
||||||
if ($request->isFormPost()) {
|
if ($request->isFormOrHisecPost()) {
|
||||||
|
$workflow_key = sprintf(
|
||||||
|
'account.link(%s)',
|
||||||
|
$account->getPHID());
|
||||||
|
|
||||||
|
$hisec_token = id(new PhabricatorAuthSessionEngine())
|
||||||
|
->setWorkflowKey($workflow_key)
|
||||||
|
->requireHighSecurityToken($viewer, $request, $panel_uri);
|
||||||
|
|
||||||
$account->setUserPHID($viewer->getPHID());
|
$account->setUserPHID($viewer->getPHID());
|
||||||
$account->save();
|
$account->save();
|
||||||
|
|
||||||
|
@ -31,14 +39,7 @@ final class PhabricatorAuthConfirmLinkController
|
||||||
return id(new AphrontRedirectResponse())->setURI($panel_uri);
|
return id(new AphrontRedirectResponse())->setURI($panel_uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Provide more information about the external account. Clicking
|
$dialog = $this->newDialog()
|
||||||
// through this form blindly is dangerous.
|
|
||||||
|
|
||||||
// TODO: If the user has password authentication, require them to retype
|
|
||||||
// their password here.
|
|
||||||
|
|
||||||
$dialog = id(new AphrontDialogView())
|
|
||||||
->setUser($viewer)
|
|
||||||
->setTitle(pht('Confirm %s Account Link', $provider->getProviderName()))
|
->setTitle(pht('Confirm %s Account Link', $provider->getProviderName()))
|
||||||
->addCancelButton($panel_uri)
|
->addCancelButton($panel_uri)
|
||||||
->addSubmitButton(pht('Confirm Account Link'));
|
->addSubmitButton(pht('Confirm Account Link'));
|
||||||
|
|
|
@ -95,7 +95,7 @@ abstract class PhabricatorAuthController extends PhabricatorController {
|
||||||
|
|
||||||
private function buildLoginValidateResponse(PhabricatorUser $user) {
|
private function buildLoginValidateResponse(PhabricatorUser $user) {
|
||||||
$validate_uri = new PhutilURI($this->getApplicationURI('validate/'));
|
$validate_uri = new PhutilURI($this->getApplicationURI('validate/'));
|
||||||
$validate_uri->setQueryParam('expect', $user->getUsername());
|
$validate_uri->replaceQueryParam('expect', $user->getUsername());
|
||||||
|
|
||||||
return id(new AphrontRedirectResponse())->setURI((string)$validate_uri);
|
return id(new AphrontRedirectResponse())->setURI((string)$validate_uri);
|
||||||
}
|
}
|
||||||
|
@ -213,19 +213,19 @@ abstract class PhabricatorAuthController extends PhabricatorController {
|
||||||
return array($account, $provider, $response);
|
return array($account, $provider, $response);
|
||||||
}
|
}
|
||||||
|
|
||||||
$provider = PhabricatorAuthProvider::getEnabledProviderByKey(
|
$config = $account->getProviderConfig();
|
||||||
$account->getProviderKey());
|
if (!$config->getIsEnabled()) {
|
||||||
|
|
||||||
if (!$provider) {
|
|
||||||
$response = $this->renderError(
|
$response = $this->renderError(
|
||||||
pht(
|
pht(
|
||||||
'The account you are attempting to register with uses a nonexistent '.
|
'The account you are attempting to register with uses a disabled '.
|
||||||
'or disabled authentication provider (with key "%s"). An '.
|
'authentication provider ("%s"). An administrator may have '.
|
||||||
'administrator may have recently disabled this provider.',
|
'recently disabled this provider.',
|
||||||
$account->getProviderKey()));
|
$config->getDisplayName()));
|
||||||
return array($account, $provider, $response);
|
return array($account, $provider, $response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$provider = $config->getProvider();
|
||||||
|
|
||||||
return array($account, $provider, null);
|
return array($account, $provider, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,20 @@ final class PhabricatorAuthLinkController
|
||||||
public function handleRequest(AphrontRequest $request) {
|
public function handleRequest(AphrontRequest $request) {
|
||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
$action = $request->getURIData('action');
|
$action = $request->getURIData('action');
|
||||||
$provider_key = $request->getURIData('pkey');
|
|
||||||
|
|
||||||
$provider = PhabricatorAuthProvider::getEnabledProviderByKey(
|
$id = $request->getURIData('id');
|
||||||
$provider_key);
|
|
||||||
if (!$provider) {
|
$config = id(new PhabricatorAuthProviderConfigQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withIDs(array($id))
|
||||||
|
->withIsEnabled(true)
|
||||||
|
->executeOne();
|
||||||
|
if (!$config) {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$provider = $config->getProvider();
|
||||||
|
|
||||||
switch ($action) {
|
switch ($action) {
|
||||||
case 'link':
|
case 'link':
|
||||||
if (!$provider->shouldAllowAccountLink()) {
|
if (!$provider->shouldAllowAccountLink()) {
|
||||||
|
@ -37,15 +43,15 @@ final class PhabricatorAuthLinkController
|
||||||
return new Aphront400Response();
|
return new Aphront400Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
$account = id(new PhabricatorExternalAccount())->loadOneWhere(
|
$accounts = id(new PhabricatorExternalAccountQuery())
|
||||||
'accountType = %s AND accountDomain = %s AND userPHID = %s',
|
->setViewer($viewer)
|
||||||
$provider->getProviderType(),
|
->withUserPHIDs(array($viewer->getPHID()))
|
||||||
$provider->getProviderDomain(),
|
->withProviderConfigPHIDs(array($config->getPHID()))
|
||||||
$viewer->getPHID());
|
->execute();
|
||||||
|
|
||||||
switch ($action) {
|
switch ($action) {
|
||||||
case 'link':
|
case 'link':
|
||||||
if ($account) {
|
if ($accounts) {
|
||||||
return $this->renderErrorPage(
|
return $this->renderErrorPage(
|
||||||
pht('Account Already Linked'),
|
pht('Account Already Linked'),
|
||||||
array(
|
array(
|
||||||
|
@ -56,7 +62,7 @@ final class PhabricatorAuthLinkController
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'refresh':
|
case 'refresh':
|
||||||
if (!$account) {
|
if (!$accounts) {
|
||||||
return $this->renderErrorPage(
|
return $this->renderErrorPage(
|
||||||
pht('No Account Linked'),
|
pht('No Account Linked'),
|
||||||
array(
|
array(
|
||||||
|
@ -76,11 +82,6 @@ final class PhabricatorAuthLinkController
|
||||||
|
|
||||||
switch ($action) {
|
switch ($action) {
|
||||||
case 'link':
|
case 'link':
|
||||||
id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
|
|
||||||
$viewer,
|
|
||||||
$request,
|
|
||||||
$panel_uri);
|
|
||||||
|
|
||||||
$form = $provider->buildLinkForm($this);
|
$form = $provider->buildLinkForm($this);
|
||||||
break;
|
break;
|
||||||
case 'refresh':
|
case 'refresh':
|
||||||
|
|
|
@ -35,6 +35,7 @@ final class PhabricatorAuthLoginController
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$invite = $this->loadInvite();
|
||||||
$provider = $this->provider;
|
$provider = $this->provider;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -103,7 +104,7 @@ final class PhabricatorAuthLoginController
|
||||||
// The account is not yet attached to a Phabricator user, so this is
|
// The account is not yet attached to a Phabricator user, so this is
|
||||||
// either a registration or an account link request.
|
// either a registration or an account link request.
|
||||||
if (!$viewer->isLoggedIn()) {
|
if (!$viewer->isLoggedIn()) {
|
||||||
if ($provider->shouldAllowRegistration()) {
|
if ($provider->shouldAllowRegistration() || $invite) {
|
||||||
return $this->processRegisterUser($account);
|
return $this->processRegisterUser($account);
|
||||||
} else {
|
} else {
|
||||||
return $this->renderError(
|
return $this->renderError(
|
||||||
|
|
|
@ -14,11 +14,6 @@ final class PhabricatorAuthOneTimeLoginController
|
||||||
$key = $request->getURIData('key');
|
$key = $request->getURIData('key');
|
||||||
$email_id = $request->getURIData('emailID');
|
$email_id = $request->getURIData('emailID');
|
||||||
|
|
||||||
if ($request->getUser()->isLoggedIn()) {
|
|
||||||
return $this->renderError(
|
|
||||||
pht('You are already logged in.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$target_user = id(new PhabricatorPeopleQuery())
|
$target_user = id(new PhabricatorPeopleQuery())
|
||||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||||
->withIDs(array($id))
|
->withIDs(array($id))
|
||||||
|
@ -27,6 +22,19 @@ final class PhabricatorAuthOneTimeLoginController
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: We allow you to use a one-time login link for your own current
|
||||||
|
// login account. This supports the "Set Password" flow.
|
||||||
|
|
||||||
|
$is_logged_in = false;
|
||||||
|
if ($viewer->isLoggedIn()) {
|
||||||
|
if ($viewer->getPHID() !== $target_user->getPHID()) {
|
||||||
|
return $this->renderError(
|
||||||
|
pht('You are already logged in.'));
|
||||||
|
} else {
|
||||||
|
$is_logged_in = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: As a convenience to users, these one-time login URIs may also
|
// NOTE: As a convenience to users, these one-time login URIs may also
|
||||||
// be associated with an email address which will be verified when the
|
// be associated with an email address which will be verified when the
|
||||||
// URI is used.
|
// URI is used.
|
||||||
|
@ -100,7 +108,7 @@ final class PhabricatorAuthOneTimeLoginController
|
||||||
->addCancelButton('/');
|
->addCancelButton('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->isFormPost()) {
|
if ($request->isFormPost() || $is_logged_in) {
|
||||||
// If we have an email bound into this URI, verify email so that clicking
|
// If we have an email bound into this URI, verify email so that clicking
|
||||||
// the link in the "Welcome" email is good enough, without requiring users
|
// the link in the "Welcome" email is good enough, without requiring users
|
||||||
// to go through a second round of email verification.
|
// to go through a second round of email verification.
|
||||||
|
@ -121,6 +129,12 @@ final class PhabricatorAuthOneTimeLoginController
|
||||||
|
|
||||||
$next_uri = $this->getNextStepURI($target_user);
|
$next_uri = $this->getNextStepURI($target_user);
|
||||||
|
|
||||||
|
// If the user is already logged in, we're just doing a "password set"
|
||||||
|
// flow. Skip directly to the next step.
|
||||||
|
if ($is_logged_in) {
|
||||||
|
return id(new AphrontRedirectResponse())->setURI($next_uri);
|
||||||
|
}
|
||||||
|
|
||||||
PhabricatorCookies::setNextURICookie($request, $next_uri, $force = true);
|
PhabricatorCookies::setNextURICookie($request, $next_uri, $force = true);
|
||||||
|
|
||||||
$force_full_session = false;
|
$force_full_session = false;
|
||||||
|
@ -204,24 +218,52 @@ final class PhabricatorAuthOneTimeLoginController
|
||||||
|
|
||||||
$request->setTemporaryCookie(PhabricatorCookies::COOKIE_HISEC, 'yes');
|
$request->setTemporaryCookie(PhabricatorCookies::COOKIE_HISEC, 'yes');
|
||||||
|
|
||||||
return (string)id(new PhutilURI($panel_uri))
|
$params = array(
|
||||||
->setQueryParams(
|
|
||||||
array(
|
|
||||||
'key' => $key,
|
'key' => $key,
|
||||||
));
|
);
|
||||||
|
|
||||||
|
return (string)new PhutilURI($panel_uri, $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
$providers = id(new PhabricatorAuthProviderConfigQuery())
|
// Check if the user already has external accounts linked. If they do,
|
||||||
|
// it's not obvious why they aren't using them to log in, but assume they
|
||||||
|
// know what they're doing. We won't send them to the link workflow.
|
||||||
|
$accounts = id(new PhabricatorExternalAccountQuery())
|
||||||
|
->setViewer($user)
|
||||||
|
->withUserPHIDs(array($user->getPHID()))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$configs = id(new PhabricatorAuthProviderConfigQuery())
|
||||||
->setViewer($user)
|
->setViewer($user)
|
||||||
->withIsEnabled(true)
|
->withIsEnabled(true)
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
|
$linkable = array();
|
||||||
|
foreach ($configs as $config) {
|
||||||
|
if (!$config->getShouldAllowLink()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$provider = $config->getProvider();
|
||||||
|
if (!$provider->isLoginFormAButton()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$linkable[] = $provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's at least one linkable provider, and the user doesn't already
|
||||||
|
// have accounts, send the user to the link workflow.
|
||||||
|
if (!$accounts && $linkable) {
|
||||||
|
return '/auth/external/';
|
||||||
|
}
|
||||||
|
|
||||||
// If there are no configured providers and the user is an administrator,
|
// If there are no configured providers and the user is an administrator,
|
||||||
// send them to Auth to configure a provider. This is probably where they
|
// send them to Auth to configure a provider. This is probably where they
|
||||||
// want to go. You can end up in this state by accidentally losing your
|
// want to go. You can end up in this state by accidentally losing your
|
||||||
// first session during initial setup, or after restoring exported data
|
// first session during initial setup, or after restoring exported data
|
||||||
// from a hosted instance.
|
// from a hosted instance.
|
||||||
if (!$providers && $user->getIsAdmin()) {
|
if (!$configs && $user->getIsAdmin()) {
|
||||||
return '/auth/';
|
return '/auth/';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,21 +11,25 @@ final class PhabricatorAuthRegisterController
|
||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
$account_key = $request->getURIData('akey');
|
$account_key = $request->getURIData('akey');
|
||||||
|
|
||||||
if ($request->getUser()->isLoggedIn()) {
|
if ($viewer->isLoggedIn()) {
|
||||||
return id(new AphrontRedirectResponse())->setURI('/');
|
return id(new AphrontRedirectResponse())->setURI('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$invite = $this->loadInvite();
|
||||||
|
|
||||||
$is_setup = false;
|
$is_setup = false;
|
||||||
if (strlen($account_key)) {
|
if (strlen($account_key)) {
|
||||||
$result = $this->loadAccountForRegistrationOrLinking($account_key);
|
$result = $this->loadAccountForRegistrationOrLinking($account_key);
|
||||||
list($account, $provider, $response) = $result;
|
list($account, $provider, $response) = $result;
|
||||||
$is_default = false;
|
$is_default = false;
|
||||||
} else if ($this->isFirstTimeSetup()) {
|
} else if ($this->isFirstTimeSetup()) {
|
||||||
list($account, $provider, $response) = $this->loadSetupAccount();
|
$account = null;
|
||||||
|
$provider = null;
|
||||||
|
$response = null;
|
||||||
$is_default = true;
|
$is_default = true;
|
||||||
$is_setup = true;
|
$is_setup = true;
|
||||||
} else {
|
} else {
|
||||||
list($account, $provider, $response) = $this->loadDefaultAccount();
|
list($account, $provider, $response) = $this->loadDefaultAccount($invite);
|
||||||
$is_default = true;
|
$is_default = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,8 +37,7 @@ final class PhabricatorAuthRegisterController
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
$invite = $this->loadInvite();
|
if (!$is_setup) {
|
||||||
|
|
||||||
if (!$provider->shouldAllowRegistration()) {
|
if (!$provider->shouldAllowRegistration()) {
|
||||||
if ($invite) {
|
if ($invite) {
|
||||||
// If the user has an invite, we allow them to register with any
|
// If the user has an invite, we allow them to register with any
|
||||||
|
@ -53,19 +56,25 @@ final class PhabricatorAuthRegisterController
|
||||||
$provider->getProviderName()));
|
$provider->getProviderName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$errors = array();
|
$errors = array();
|
||||||
|
|
||||||
$user = new PhabricatorUser();
|
$user = new PhabricatorUser();
|
||||||
|
|
||||||
|
if ($is_setup) {
|
||||||
|
$default_username = null;
|
||||||
|
$default_realname = null;
|
||||||
|
$default_email = null;
|
||||||
|
} else {
|
||||||
$default_username = $account->getUsername();
|
$default_username = $account->getUsername();
|
||||||
$default_realname = $account->getRealName();
|
$default_realname = $account->getRealName();
|
||||||
|
$default_email = $account->getEmail();
|
||||||
|
}
|
||||||
|
|
||||||
$account_type = PhabricatorAuthPassword::PASSWORD_TYPE_ACCOUNT;
|
$account_type = PhabricatorAuthPassword::PASSWORD_TYPE_ACCOUNT;
|
||||||
$content_source = PhabricatorContentSource::newFromRequest($request);
|
$content_source = PhabricatorContentSource::newFromRequest($request);
|
||||||
|
|
||||||
$default_email = $account->getEmail();
|
|
||||||
|
|
||||||
if ($invite) {
|
if ($invite) {
|
||||||
$default_email = $invite->getEmailAddress();
|
$default_email = $invite->getEmailAddress();
|
||||||
}
|
}
|
||||||
|
@ -212,7 +221,11 @@ final class PhabricatorAuthRegisterController
|
||||||
$can_edit_email = $profile->getCanEditEmail();
|
$can_edit_email = $profile->getCanEditEmail();
|
||||||
$can_edit_realname = $profile->getCanEditRealName();
|
$can_edit_realname = $profile->getCanEditRealName();
|
||||||
|
|
||||||
|
if ($is_setup) {
|
||||||
|
$must_set_password = false;
|
||||||
|
} else {
|
||||||
$must_set_password = $provider->shouldRequireRegistrationPassword();
|
$must_set_password = $provider->shouldRequireRegistrationPassword();
|
||||||
|
}
|
||||||
|
|
||||||
$can_edit_anything = $profile->getCanEditAnything() || $must_set_password;
|
$can_edit_anything = $profile->getCanEditAnything() || $must_set_password;
|
||||||
$force_verify = $profile->getShouldVerifyEmail();
|
$force_verify = $profile->getShouldVerifyEmail();
|
||||||
|
@ -334,10 +347,12 @@ final class PhabricatorAuthRegisterController
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$errors) {
|
if (!$errors) {
|
||||||
|
if (!$is_setup) {
|
||||||
$image = $this->loadProfilePicture($account);
|
$image = $this->loadProfilePicture($account);
|
||||||
if ($image) {
|
if ($image) {
|
||||||
$user->setProfileImagePHID($image->getPHID());
|
$user->setProfileImagePHID($image->getPHID());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$verify_email = false;
|
$verify_email = false;
|
||||||
|
@ -346,6 +361,7 @@ final class PhabricatorAuthRegisterController
|
||||||
$verify_email = true;
|
$verify_email = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$is_setup) {
|
||||||
if ($value_email === $default_email) {
|
if ($value_email === $default_email) {
|
||||||
if ($account->getEmailVerified()) {
|
if ($account->getEmailVerified()) {
|
||||||
$verify_email = true;
|
$verify_email = true;
|
||||||
|
@ -359,6 +375,7 @@ final class PhabricatorAuthRegisterController
|
||||||
$verify_email = true;
|
$verify_email = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$email_obj = null;
|
$email_obj = null;
|
||||||
if ($invite) {
|
if ($invite) {
|
||||||
|
@ -438,9 +455,11 @@ final class PhabricatorAuthRegisterController
|
||||||
$transaction_editor->applyTransactions($user, $xactions);
|
$transaction_editor->applyTransactions($user, $xactions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$is_setup) {
|
||||||
$account->setUserPHID($user->getPHID());
|
$account->setUserPHID($user->getPHID());
|
||||||
$provider->willRegisterAccount($account);
|
$provider->willRegisterAccount($account);
|
||||||
$account->save();
|
$account->save();
|
||||||
|
}
|
||||||
|
|
||||||
$user->saveTransaction();
|
$user->saveTransaction();
|
||||||
|
|
||||||
|
@ -501,7 +520,6 @@ final class PhabricatorAuthRegisterController
|
||||||
->setAuthProvider($provider)));
|
->setAuthProvider($provider)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($can_edit_username) {
|
if ($can_edit_username) {
|
||||||
$form->appendChild(
|
$form->appendChild(
|
||||||
id(new AphrontFormTextControl())
|
id(new AphrontFormTextControl())
|
||||||
|
@ -595,7 +613,7 @@ final class PhabricatorAuthRegisterController
|
||||||
pht(
|
pht(
|
||||||
'Installation is complete. Register your administrator account '.
|
'Installation is complete. Register your administrator account '.
|
||||||
'below to log in. You will be able to configure options and add '.
|
'below to log in. You will be able to configure options and add '.
|
||||||
'other authentication mechanisms (like LDAP or OAuth) later on.'));
|
'authentication mechanisms later on.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$object_box = id(new PHUIObjectBoxView())
|
$object_box = id(new PHUIObjectBoxView())
|
||||||
|
@ -612,7 +630,8 @@ final class PhabricatorAuthRegisterController
|
||||||
|
|
||||||
$view = id(new PHUITwoColumnView())
|
$view = id(new PHUITwoColumnView())
|
||||||
->setHeader($header)
|
->setHeader($header)
|
||||||
->setFooter(array(
|
->setFooter(
|
||||||
|
array(
|
||||||
$welcome_view,
|
$welcome_view,
|
||||||
$invite_header,
|
$invite_header,
|
||||||
$object_box,
|
$object_box,
|
||||||
|
@ -624,17 +643,20 @@ final class PhabricatorAuthRegisterController
|
||||||
->appendChild($view);
|
->appendChild($view);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function loadDefaultAccount() {
|
private function loadDefaultAccount($invite) {
|
||||||
$providers = PhabricatorAuthProvider::getAllEnabledProviders();
|
$providers = PhabricatorAuthProvider::getAllEnabledProviders();
|
||||||
$account = null;
|
$account = null;
|
||||||
$provider = null;
|
$provider = null;
|
||||||
$response = null;
|
$response = null;
|
||||||
|
|
||||||
foreach ($providers as $key => $candidate_provider) {
|
foreach ($providers as $key => $candidate_provider) {
|
||||||
|
if (!$invite) {
|
||||||
if (!$candidate_provider->shouldAllowRegistration()) {
|
if (!$candidate_provider->shouldAllowRegistration()) {
|
||||||
unset($providers[$key]);
|
unset($providers[$key]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!$candidate_provider->isDefaultRegistrationProvider()) {
|
if (!$candidate_provider->isDefaultRegistrationProvider()) {
|
||||||
unset($providers[$key]);
|
unset($providers[$key]);
|
||||||
}
|
}
|
||||||
|
@ -652,24 +674,11 @@ final class PhabricatorAuthRegisterController
|
||||||
}
|
}
|
||||||
|
|
||||||
$provider = head($providers);
|
$provider = head($providers);
|
||||||
$account = $provider->getDefaultExternalAccount();
|
$account = $provider->newDefaultExternalAccount();
|
||||||
|
|
||||||
return array($account, $provider, $response);
|
return array($account, $provider, $response);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function loadSetupAccount() {
|
|
||||||
$provider = new PhabricatorPasswordAuthProvider();
|
|
||||||
$provider->attachProviderConfig(
|
|
||||||
id(new PhabricatorAuthProviderConfig())
|
|
||||||
->setShouldAllowRegistration(1)
|
|
||||||
->setShouldAllowLogin(1)
|
|
||||||
->setIsEnabled(true));
|
|
||||||
|
|
||||||
$account = $provider->getDefaultExternalAccount();
|
|
||||||
$response = null;
|
|
||||||
return array($account, $provider, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function loadProfilePicture(PhabricatorExternalAccount $account) {
|
private function loadProfilePicture(PhabricatorExternalAccount $account) {
|
||||||
$phid = $account->getProfileImagePHID();
|
$phid = $account->getProfileImagePHID();
|
||||||
if (!$phid) {
|
if (!$phid) {
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorAuthSetExternalController
|
||||||
|
extends PhabricatorAuthController {
|
||||||
|
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$configs = id(new PhabricatorAuthProviderConfigQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withIsEnabled(true)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$linkable = array();
|
||||||
|
foreach ($configs as $config) {
|
||||||
|
if (!$config->getShouldAllowLink()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For now, only buttons get to appear here: for example, we can't
|
||||||
|
// reasonably embed an entire LDAP form into this UI.
|
||||||
|
$provider = $config->getProvider();
|
||||||
|
if (!$provider->isLoginFormAButton()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$linkable[] = $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$linkable) {
|
||||||
|
return $this->newDialog()
|
||||||
|
->setTitle(pht('No Linkable External Providers'))
|
||||||
|
->appendParagraph(
|
||||||
|
pht(
|
||||||
|
'Currently, there are no configured external auth providers '.
|
||||||
|
'which you can link your account to.'))
|
||||||
|
->addCancelButton('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
$text = PhabricatorAuthMessage::loadMessageText(
|
||||||
|
$viewer,
|
||||||
|
PhabricatorAuthLinkMessageType::MESSAGEKEY);
|
||||||
|
if (!strlen($text)) {
|
||||||
|
$text = pht(
|
||||||
|
'You can link your Phabricator account to an external account to '.
|
||||||
|
'allow you to log in more easily in the future. To continue, choose '.
|
||||||
|
'an account to link below. If you prefer not to link your account, '.
|
||||||
|
'you can skip this step.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$remarkup_view = new PHUIRemarkupView($viewer, $text);
|
||||||
|
$remarkup_view = phutil_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => 'phui-object-box-instructions',
|
||||||
|
),
|
||||||
|
$remarkup_view);
|
||||||
|
|
||||||
|
PhabricatorCookies::setClientIDCookie($request);
|
||||||
|
|
||||||
|
$view = array();
|
||||||
|
foreach ($configs as $config) {
|
||||||
|
$provider = $config->getProvider();
|
||||||
|
|
||||||
|
$form = $provider->buildLinkForm($this);
|
||||||
|
|
||||||
|
if ($provider->isLoginFormAButton()) {
|
||||||
|
require_celerity_resource('auth-css');
|
||||||
|
$form = phutil_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => 'phabricator-link-button pl',
|
||||||
|
),
|
||||||
|
$form);
|
||||||
|
}
|
||||||
|
|
||||||
|
$view[] = $form;
|
||||||
|
}
|
||||||
|
|
||||||
|
$form = id(new AphrontFormView())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->appendControl(
|
||||||
|
id(new AphrontFormSubmitControl())
|
||||||
|
->addCancelButton('/', pht('Skip This Step')));
|
||||||
|
|
||||||
|
$header = id(new PHUIHeaderView())
|
||||||
|
->setHeader(pht('Link External Account'));
|
||||||
|
|
||||||
|
$box = id(new PHUIObjectBoxView())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->setHeader($header)
|
||||||
|
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||||
|
->appendChild($remarkup_view)
|
||||||
|
->appendChild($view)
|
||||||
|
->appendChild($form);
|
||||||
|
|
||||||
|
$main_view = id(new PHUITwoColumnView())
|
||||||
|
->setFooter($box);
|
||||||
|
|
||||||
|
$crumbs = $this->buildApplicationCrumbs()
|
||||||
|
->addTextCrumb(pht('Link External Account'))
|
||||||
|
->setBorder(true);
|
||||||
|
|
||||||
|
return $this->newPage()
|
||||||
|
->setTitle(pht('Link External Account'))
|
||||||
|
->setCrumbs($crumbs)
|
||||||
|
->appendChild($main_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -54,7 +54,7 @@ final class PhabricatorAuthStartController
|
||||||
}
|
}
|
||||||
|
|
||||||
$redirect_uri = $request->getRequestURI();
|
$redirect_uri = $request->getRequestURI();
|
||||||
$redirect_uri->setQueryParam('cleared', 1);
|
$redirect_uri->replaceQueryParam('cleared', 1);
|
||||||
return id(new AphrontRedirectResponse())->setURI($redirect_uri);
|
return id(new AphrontRedirectResponse())->setURI($redirect_uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ final class PhabricatorAuthStartController
|
||||||
// the workflow will continue normally.
|
// the workflow will continue normally.
|
||||||
if ($did_clear) {
|
if ($did_clear) {
|
||||||
$redirect_uri = $request->getRequestURI();
|
$redirect_uri = $request->getRequestURI();
|
||||||
$redirect_uri->setQueryParam('cleared', null);
|
$redirect_uri->removeQueryParam('cleared');
|
||||||
return id(new AphrontRedirectResponse())->setURI($redirect_uri);
|
return id(new AphrontRedirectResponse())->setURI($redirect_uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,48 +3,45 @@
|
||||||
final class PhabricatorAuthUnlinkController
|
final class PhabricatorAuthUnlinkController
|
||||||
extends PhabricatorAuthController {
|
extends PhabricatorAuthController {
|
||||||
|
|
||||||
private $providerKey;
|
|
||||||
|
|
||||||
public function handleRequest(AphrontRequest $request) {
|
public function handleRequest(AphrontRequest $request) {
|
||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
$this->providerKey = $request->getURIData('pkey');
|
$id = $request->getURIData('id');
|
||||||
|
|
||||||
list($type, $domain) = explode(':', $this->providerKey, 2);
|
$account = id(new PhabricatorExternalAccountQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
// Check that this account link actually exists. We don't require the
|
->withIDs(array($id))
|
||||||
// provider to exist because we want users to be able to delete links to
|
->requireCapabilities(
|
||||||
// dead accounts if they want.
|
array(
|
||||||
$account = id(new PhabricatorExternalAccount())->loadOneWhere(
|
PhabricatorPolicyCapability::CAN_VIEW,
|
||||||
'accountType = %s AND accountDomain = %s AND userPHID = %s',
|
PhabricatorPolicyCapability::CAN_EDIT,
|
||||||
$type,
|
))
|
||||||
$domain,
|
->executeOne();
|
||||||
$viewer->getPHID());
|
|
||||||
if (!$account) {
|
if (!$account) {
|
||||||
return $this->renderNoAccountErrorDialog();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the provider (if it exists) allows accounts to be unlinked.
|
$done_uri = '/settings/panel/external/';
|
||||||
$provider_key = $this->providerKey;
|
|
||||||
$provider = PhabricatorAuthProvider::getEnabledProviderByKey($provider_key);
|
$config = $account->getProviderConfig();
|
||||||
if ($provider) {
|
$provider = $config->getProvider();
|
||||||
if (!$provider->shouldAllowAccountUnlink()) {
|
if (!$provider->shouldAllowAccountUnlink()) {
|
||||||
return $this->renderNotUnlinkableErrorDialog($provider);
|
return $this->renderNotUnlinkableErrorDialog($provider, $done_uri);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$confirmations = $request->getStrList('confirmations');
|
$confirmations = $request->getStrList('confirmations');
|
||||||
$confirmations = array_fuse($confirmations);
|
$confirmations = array_fuse($confirmations);
|
||||||
|
|
||||||
if (!$request->isFormPost() || !isset($confirmations['unlink'])) {
|
if (!$request->isFormOrHisecPost() || !isset($confirmations['unlink'])) {
|
||||||
return $this->renderConfirmDialog($confirmations);
|
return $this->renderConfirmDialog($confirmations, $config, $done_uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that this account isn't the only account which can be used to
|
// Check that this account isn't the only account which can be used to
|
||||||
// login. We warn you when you remove your only login account.
|
// login. We warn you when you remove your only login account.
|
||||||
if ($account->isUsableForLogin()) {
|
if ($account->isUsableForLogin()) {
|
||||||
$other_accounts = id(new PhabricatorExternalAccount())->loadAllWhere(
|
$other_accounts = id(new PhabricatorExternalAccountQuery())
|
||||||
'userPHID = %s',
|
->setViewer($viewer)
|
||||||
$viewer->getPHID());
|
->withUserPHIDs(array($viewer->getPHID()))
|
||||||
|
->execute();
|
||||||
|
|
||||||
$valid_accounts = 0;
|
$valid_accounts = 0;
|
||||||
foreach ($other_accounts as $other_account) {
|
foreach ($other_accounts as $other_account) {
|
||||||
|
@ -55,11 +52,21 @@ final class PhabricatorAuthUnlinkController
|
||||||
|
|
||||||
if ($valid_accounts < 2) {
|
if ($valid_accounts < 2) {
|
||||||
if (!isset($confirmations['only'])) {
|
if (!isset($confirmations['only'])) {
|
||||||
return $this->renderOnlyUsableAccountConfirmDialog($confirmations);
|
return $this->renderOnlyUsableAccountConfirmDialog(
|
||||||
|
$confirmations,
|
||||||
|
$done_uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$workflow_key = sprintf(
|
||||||
|
'account.unlink(%s)',
|
||||||
|
$account->getPHID());
|
||||||
|
|
||||||
|
$hisec_token = id(new PhabricatorAuthSessionEngine())
|
||||||
|
->setWorkflowKey($workflow_key)
|
||||||
|
->requireHighSecurityToken($viewer, $request, $done_uri);
|
||||||
|
|
||||||
$account->delete();
|
$account->delete();
|
||||||
|
|
||||||
id(new PhabricatorAuthSessionEngine())->terminateLoginSessions(
|
id(new PhabricatorAuthSessionEngine())->terminateLoginSessions(
|
||||||
|
@ -67,42 +74,27 @@ final class PhabricatorAuthUnlinkController
|
||||||
new PhutilOpaqueEnvelope(
|
new PhutilOpaqueEnvelope(
|
||||||
$request->getCookie(PhabricatorCookies::COOKIE_SESSION)));
|
$request->getCookie(PhabricatorCookies::COOKIE_SESSION)));
|
||||||
|
|
||||||
return id(new AphrontRedirectResponse())->setURI($this->getDoneURI());
|
return id(new AphrontRedirectResponse())->setURI($done_uri);
|
||||||
}
|
|
||||||
|
|
||||||
private function getDoneURI() {
|
|
||||||
return '/settings/panel/external/';
|
|
||||||
}
|
|
||||||
|
|
||||||
private function renderNoAccountErrorDialog() {
|
|
||||||
$dialog = id(new AphrontDialogView())
|
|
||||||
->setUser($this->getRequest()->getUser())
|
|
||||||
->setTitle(pht('No Such Account'))
|
|
||||||
->appendChild(
|
|
||||||
pht(
|
|
||||||
'You can not unlink this account because it is not linked.'))
|
|
||||||
->addCancelButton($this->getDoneURI());
|
|
||||||
|
|
||||||
return id(new AphrontDialogResponse())->setDialog($dialog);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderNotUnlinkableErrorDialog(
|
private function renderNotUnlinkableErrorDialog(
|
||||||
PhabricatorAuthProvider $provider) {
|
PhabricatorAuthProvider $provider,
|
||||||
|
$done_uri) {
|
||||||
|
|
||||||
$dialog = id(new AphrontDialogView())
|
return $this->newDialog()
|
||||||
->setUser($this->getRequest()->getUser())
|
|
||||||
->setTitle(pht('Permanent Account Link'))
|
->setTitle(pht('Permanent Account Link'))
|
||||||
->appendChild(
|
->appendChild(
|
||||||
pht(
|
pht(
|
||||||
'You can not unlink this account because the administrator has '.
|
'You can not unlink this account because the administrator has '.
|
||||||
'configured Phabricator to make links to %s accounts permanent.',
|
'configured Phabricator to make links to "%s" accounts permanent.',
|
||||||
$provider->getProviderName()))
|
$provider->getProviderName()))
|
||||||
->addCancelButton($this->getDoneURI());
|
->addCancelButton($done_uri);
|
||||||
|
|
||||||
return id(new AphrontDialogResponse())->setDialog($dialog);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderOnlyUsableAccountConfirmDialog(array $confirmations) {
|
private function renderOnlyUsableAccountConfirmDialog(
|
||||||
|
array $confirmations,
|
||||||
|
$done_uri) {
|
||||||
|
|
||||||
$confirmations[] = 'only';
|
$confirmations[] = 'only';
|
||||||
|
|
||||||
return $this->newDialog()
|
return $this->newDialog()
|
||||||
|
@ -116,28 +108,23 @@ final class PhabricatorAuthUnlinkController
|
||||||
pht(
|
pht(
|
||||||
'If you lose access to your account, you can recover access by '.
|
'If you lose access to your account, you can recover access by '.
|
||||||
'sending yourself an email login link from the login screen.'))
|
'sending yourself an email login link from the login screen.'))
|
||||||
->addCancelButton($this->getDoneURI())
|
->addCancelButton($done_uri)
|
||||||
->addSubmitButton(pht('Unlink External Account'));
|
->addSubmitButton(pht('Unlink External Account'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderConfirmDialog(array $confirmations) {
|
private function renderConfirmDialog(
|
||||||
|
array $confirmations,
|
||||||
|
PhabricatorAuthProviderConfig $config,
|
||||||
|
$done_uri) {
|
||||||
|
|
||||||
$confirmations[] = 'unlink';
|
$confirmations[] = 'unlink';
|
||||||
|
$provider = $config->getProvider();
|
||||||
|
|
||||||
$provider_key = $this->providerKey;
|
|
||||||
$provider = PhabricatorAuthProvider::getEnabledProviderByKey($provider_key);
|
|
||||||
|
|
||||||
if ($provider) {
|
|
||||||
$title = pht('Unlink "%s" Account?', $provider->getProviderName());
|
$title = pht('Unlink "%s" Account?', $provider->getProviderName());
|
||||||
$body = pht(
|
$body = pht(
|
||||||
'You will no longer be able to use your %s account to '.
|
'You will no longer be able to use your %s account to '.
|
||||||
'log in to Phabricator.',
|
'log in to Phabricator.',
|
||||||
$provider->getProviderName());
|
$provider->getProviderName());
|
||||||
} else {
|
|
||||||
$title = pht('Unlink Account?');
|
|
||||||
$body = pht(
|
|
||||||
'You will no longer be able to use this account to log in '.
|
|
||||||
'to Phabricator.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->newDialog()
|
return $this->newDialog()
|
||||||
->setTitle($title)
|
->setTitle($title)
|
||||||
|
@ -148,7 +135,7 @@ final class PhabricatorAuthUnlinkController
|
||||||
'Note: Unlinking an authentication provider will terminate any '.
|
'Note: Unlinking an authentication provider will terminate any '.
|
||||||
'other active login sessions.'))
|
'other active login sessions.'))
|
||||||
->addSubmitButton(pht('Unlink Account'))
|
->addSubmitButton(pht('Unlink Account'))
|
||||||
->addCancelButton($this->getDoneURI());
|
->addCancelButton($done_uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,21 +9,39 @@ final class PhabricatorEmailLoginController
|
||||||
|
|
||||||
public function handleRequest(AphrontRequest $request) {
|
public function handleRequest(AphrontRequest $request) {
|
||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
|
$is_logged_in = $viewer->isLoggedIn();
|
||||||
|
|
||||||
$e_email = true;
|
$e_email = true;
|
||||||
$e_captcha = true;
|
$e_captcha = true;
|
||||||
$errors = array();
|
$errors = array();
|
||||||
|
|
||||||
|
if ($is_logged_in) {
|
||||||
|
if (!$this->isPasswordAuthEnabled()) {
|
||||||
|
return $this->newDialog()
|
||||||
|
->setTitle(pht('No Password Auth'))
|
||||||
|
->appendParagraph(
|
||||||
|
pht(
|
||||||
|
'Password authentication is not enabled and you are already '.
|
||||||
|
'logged in. There is nothing for you here.'))
|
||||||
|
->addCancelButton('/', pht('Continue'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$v_email = $viewer->loadPrimaryEmailAddress();
|
||||||
|
} else {
|
||||||
$v_email = $request->getStr('email');
|
$v_email = $request->getStr('email');
|
||||||
|
}
|
||||||
|
|
||||||
if ($request->isFormPost()) {
|
if ($request->isFormPost()) {
|
||||||
$e_email = null;
|
$e_email = null;
|
||||||
$e_captcha = pht('Again');
|
$e_captcha = pht('Again');
|
||||||
|
|
||||||
|
if (!$is_logged_in) {
|
||||||
$captcha_ok = AphrontFormRecaptchaControl::processCaptcha($request);
|
$captcha_ok = AphrontFormRecaptchaControl::processCaptcha($request);
|
||||||
if (!$captcha_ok) {
|
if (!$captcha_ok) {
|
||||||
$errors[] = pht('Captcha response is incorrect, try again.');
|
$errors[] = pht('Captcha response is incorrect, try again.');
|
||||||
$e_captcha = pht('Invalid');
|
$e_captcha = pht('Invalid');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!strlen($v_email)) {
|
if (!strlen($v_email)) {
|
||||||
$errors[] = pht('You must provide an email address.');
|
$errors[] = pht('You must provide an email address.');
|
||||||
|
@ -76,10 +94,24 @@ final class PhabricatorEmailLoginController
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$errors) {
|
if (!$errors) {
|
||||||
$body = $this->newAccountLoginMailBody($target_user);
|
$body = $this->newAccountLoginMailBody(
|
||||||
|
$target_user,
|
||||||
|
$is_logged_in);
|
||||||
|
|
||||||
|
if ($is_logged_in) {
|
||||||
|
$subject = pht('[Phabricator] Account Password Link');
|
||||||
|
$instructions = pht(
|
||||||
|
'An email has been sent containing a link you can use to set '.
|
||||||
|
'a password for your account.');
|
||||||
|
} else {
|
||||||
|
$subject = pht('[Phabricator] Account Login Link');
|
||||||
|
$instructions = pht(
|
||||||
|
'An email has been sent containing a link you can use to log '.
|
||||||
|
'in to your account.');
|
||||||
|
}
|
||||||
|
|
||||||
$mail = id(new PhabricatorMetaMTAMail())
|
$mail = id(new PhabricatorMetaMTAMail())
|
||||||
->setSubject(pht('[Phabricator] Account Login Link'))
|
->setSubject($subject)
|
||||||
->setForceDelivery(true)
|
->setForceDelivery(true)
|
||||||
->addRawTos(array($target_email->getAddress()))
|
->addRawTos(array($target_email->getAddress()))
|
||||||
->setBody($body)
|
->setBody($body)
|
||||||
|
@ -88,8 +120,7 @@ final class PhabricatorEmailLoginController
|
||||||
return $this->newDialog()
|
return $this->newDialog()
|
||||||
->setTitle(pht('Check Your Email'))
|
->setTitle(pht('Check Your Email'))
|
||||||
->setShortTitle(pht('Email Sent'))
|
->setShortTitle(pht('Email Sent'))
|
||||||
->appendParagraph(
|
->appendParagraph($instructions)
|
||||||
pht('An email has been sent with a link you can use to log in.'))
|
|
||||||
->addCancelButton('/', pht('Done'));
|
->addCancelButton('/', pht('Done'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,33 +130,47 @@ final class PhabricatorEmailLoginController
|
||||||
->setViewer($viewer);
|
->setViewer($viewer);
|
||||||
|
|
||||||
if ($this->isPasswordAuthEnabled()) {
|
if ($this->isPasswordAuthEnabled()) {
|
||||||
|
if ($is_logged_in) {
|
||||||
|
$title = pht('Set Password');
|
||||||
|
$form->appendRemarkupInstructions(
|
||||||
|
pht(
|
||||||
|
'A password reset link will be sent to your primary email '.
|
||||||
|
'address. Follow the link to set an account password.'));
|
||||||
|
} else {
|
||||||
|
$title = pht('Password Reset');
|
||||||
$form->appendRemarkupInstructions(
|
$form->appendRemarkupInstructions(
|
||||||
pht(
|
pht(
|
||||||
'To reset your password, provide your email address. An email '.
|
'To reset your password, provide your email address. An email '.
|
||||||
'with a login link will be sent to you.'));
|
'with a login link will be sent to you.'));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
$title = pht('Email Login');
|
||||||
$form->appendRemarkupInstructions(
|
$form->appendRemarkupInstructions(
|
||||||
pht(
|
pht(
|
||||||
'To access your account, provide your email address. An email '.
|
'To access your account, provide your email address. An email '.
|
||||||
'with a login link will be sent to you.'));
|
'with a login link will be sent to you.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$form
|
if ($is_logged_in) {
|
||||||
->appendControl(
|
$address_control = new AphrontFormStaticControl();
|
||||||
id(new AphrontFormTextControl())
|
} else {
|
||||||
->setLabel(pht('Email Address'))
|
$address_control = id(new AphrontFormTextControl())
|
||||||
->setName('email')
|
->setName('email')
|
||||||
->setValue($v_email)
|
->setError($e_email);
|
||||||
->setError($e_email))
|
}
|
||||||
->appendControl(
|
|
||||||
|
$address_control
|
||||||
|
->setLabel(pht('Email Address'))
|
||||||
|
->setValue($v_email);
|
||||||
|
|
||||||
|
$form
|
||||||
|
->appendControl($address_control);
|
||||||
|
|
||||||
|
if (!$is_logged_in) {
|
||||||
|
$form->appendControl(
|
||||||
id(new AphrontFormRecaptchaControl())
|
id(new AphrontFormRecaptchaControl())
|
||||||
->setLabel(pht('Captcha'))
|
->setLabel(pht('Captcha'))
|
||||||
->setError($e_captcha));
|
->setError($e_captcha));
|
||||||
|
|
||||||
if ($this->isPasswordAuthEnabled()) {
|
|
||||||
$title = pht('Password Reset');
|
|
||||||
} else {
|
|
||||||
$title = pht('Email Login');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->newDialog()
|
return $this->newDialog()
|
||||||
|
@ -137,7 +182,10 @@ final class PhabricatorEmailLoginController
|
||||||
->addSubmitButton(pht('Send Email'));
|
->addSubmitButton(pht('Send Email'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function newAccountLoginMailBody(PhabricatorUser $user) {
|
private function newAccountLoginMailBody(
|
||||||
|
PhabricatorUser $user,
|
||||||
|
$is_logged_in) {
|
||||||
|
|
||||||
$engine = new PhabricatorAuthSessionEngine();
|
$engine = new PhabricatorAuthSessionEngine();
|
||||||
$uri = $engine->getOneTimeLoginURI(
|
$uri = $engine->getOneTimeLoginURI(
|
||||||
$user,
|
$user,
|
||||||
|
@ -148,7 +196,12 @@ final class PhabricatorEmailLoginController
|
||||||
$have_passwords = $this->isPasswordAuthEnabled();
|
$have_passwords = $this->isPasswordAuthEnabled();
|
||||||
|
|
||||||
if ($have_passwords) {
|
if ($have_passwords) {
|
||||||
if ($is_serious) {
|
if ($is_logged_in) {
|
||||||
|
$body = pht(
|
||||||
|
'You can use this link to set a password on your account:'.
|
||||||
|
"\n\n %s\n",
|
||||||
|
$uri);
|
||||||
|
} else if ($is_serious) {
|
||||||
$body = pht(
|
$body = pht(
|
||||||
"You can use this link to reset your Phabricator password:".
|
"You can use this link to reset your Phabricator password:".
|
||||||
"\n\n %s\n",
|
"\n\n %s\n",
|
||||||
|
|
|
@ -32,7 +32,7 @@ final class PhabricatorAuthNewController
|
||||||
$provider_class = get_class($provider);
|
$provider_class = get_class($provider);
|
||||||
|
|
||||||
$provider_uri = id(new PhutilURI('/config/edit/'))
|
$provider_uri = id(new PhutilURI('/config/edit/'))
|
||||||
->setQueryParam('provider', $provider_class);
|
->replaceQueryParam('provider', $provider_class);
|
||||||
$provider_uri = $this->getApplicationURI($provider_uri);
|
$provider_uri = $this->getApplicationURI($provider_uri);
|
||||||
|
|
||||||
$already_exists = isset($configured_classes[get_class($provider)]);
|
$already_exists = isset($configured_classes[get_class($provider)]);
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorAuthChallengeStatusController
|
||||||
|
extends PhabricatorAuthController {
|
||||||
|
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
$id = $request->getURIData('id');
|
||||||
|
$now = PhabricatorTime::getNow();
|
||||||
|
|
||||||
|
$result = new PhabricatorAuthChallengeUpdate();
|
||||||
|
|
||||||
|
$challenge = id(new PhabricatorAuthChallengeQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withIDs(array($id))
|
||||||
|
->withUserPHIDs(array($viewer->getPHID()))
|
||||||
|
->withChallengeTTLBetween($now, null)
|
||||||
|
->executeOne();
|
||||||
|
if ($challenge) {
|
||||||
|
$config = id(new PhabricatorAuthFactorConfigQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withPHIDs(array($challenge->getFactorPHID()))
|
||||||
|
->executeOne();
|
||||||
|
if ($config) {
|
||||||
|
$provider = $config->getFactorProvider();
|
||||||
|
$factor = $provider->getFactor();
|
||||||
|
|
||||||
|
$result = $factor->newChallengeStatusView(
|
||||||
|
$config,
|
||||||
|
$provider,
|
||||||
|
$viewer,
|
||||||
|
$challenge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return id(new AphrontAjaxResponse())
|
||||||
|
->setContent($result->newContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -45,7 +45,7 @@ final class PhabricatorAuthFactorProviderEditController
|
||||||
|
|
||||||
foreach ($factors as $factor_key => $factor) {
|
foreach ($factors as $factor_key => $factor) {
|
||||||
$factor_uri = id(new PhutilURI('/mfa/edit/'))
|
$factor_uri = id(new PhutilURI('/mfa/edit/'))
|
||||||
->setQueryParam('providerFactorKey', $factor_key);
|
->replaceQueryParam('providerFactorKey', $factor_key);
|
||||||
$factor_uri = $this->getApplicationURI($factor_uri);
|
$factor_uri = $this->getApplicationURI($factor_uri);
|
||||||
|
|
||||||
$is_enabled = $factor->canCreateNewProvider();
|
$is_enabled = $factor->canCreateNewProvider();
|
||||||
|
|
|
@ -42,7 +42,7 @@ final class PhabricatorAuthMainMenuBarExtension
|
||||||
$uri = new PhutilURI('/auth/start/');
|
$uri = new PhutilURI('/auth/start/');
|
||||||
if ($controller) {
|
if ($controller) {
|
||||||
$path = $controller->getRequest()->getPath();
|
$path = $controller->getRequest()->getPath();
|
||||||
$uri->setQueryParam('next', $path);
|
$uri->replaceQueryParam('next', $path);
|
||||||
}
|
}
|
||||||
|
|
||||||
return id(new PHUIButtonView())
|
return id(new PHUIButtonView())
|
||||||
|
|
|
@ -80,6 +80,14 @@ abstract class PhabricatorAuthFactor extends Phobject {
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function newChallengeStatusView(
|
||||||
|
PhabricatorAuthFactorConfig $config,
|
||||||
|
PhabricatorAuthFactorProvider $provider,
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
PhabricatorAuthChallenge $challenge) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this a factor which depends on the user's contact number?
|
* Is this a factor which depends on the user's contact number?
|
||||||
*
|
*
|
||||||
|
@ -210,8 +218,6 @@ abstract class PhabricatorAuthFactor extends Phobject {
|
||||||
get_class($this)));
|
get_class($this)));
|
||||||
}
|
}
|
||||||
|
|
||||||
$result->setIssuedChallenges($challenges);
|
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,8 +248,6 @@ abstract class PhabricatorAuthFactor extends Phobject {
|
||||||
get_class($this)));
|
get_class($this)));
|
||||||
}
|
}
|
||||||
|
|
||||||
$result->setIssuedChallenges($challenges);
|
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,9 +343,18 @@ abstract class PhabricatorAuthFactor extends Phobject {
|
||||||
->setIcon('fa-commenting', 'green');
|
->setIcon('fa-commenting', 'green');
|
||||||
}
|
}
|
||||||
|
|
||||||
return id(new PHUIFormTimerControl())
|
$control = id(new PHUIFormTimerControl())
|
||||||
->setIcon($icon)
|
->setIcon($icon)
|
||||||
->appendChild($error);
|
->appendChild($error);
|
||||||
|
|
||||||
|
$status_challenge = $result->getStatusChallenge();
|
||||||
|
if ($status_challenge) {
|
||||||
|
$id = $status_challenge->getID();
|
||||||
|
$uri = "/auth/mfa/challenge/status/{$id}/";
|
||||||
|
$control->setUpdateURI($uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $control;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ final class PhabricatorAuthFactorResult
|
||||||
private $value;
|
private $value;
|
||||||
private $issuedChallenges = array();
|
private $issuedChallenges = array();
|
||||||
private $icon;
|
private $icon;
|
||||||
|
private $statusChallenge;
|
||||||
|
|
||||||
public function setAnsweredChallenge(PhabricatorAuthChallenge $challenge) {
|
public function setAnsweredChallenge(PhabricatorAuthChallenge $challenge) {
|
||||||
if (!$challenge->getIsAnsweredChallenge()) {
|
if (!$challenge->getIsAnsweredChallenge()) {
|
||||||
|
@ -34,6 +35,15 @@ final class PhabricatorAuthFactorResult
|
||||||
return $this->answeredChallenge;
|
return $this->answeredChallenge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setStatusChallenge(PhabricatorAuthChallenge $challenge) {
|
||||||
|
$this->statusChallenge = $challenge;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStatusChallenge() {
|
||||||
|
return $this->statusChallenge;
|
||||||
|
}
|
||||||
|
|
||||||
public function getIsValid() {
|
public function getIsValid() {
|
||||||
return (bool)$this->getAnsweredChallenge();
|
return (bool)$this->getAnsweredChallenge();
|
||||||
}
|
}
|
||||||
|
@ -83,16 +93,6 @@ final class PhabricatorAuthFactorResult
|
||||||
return $this->value;
|
return $this->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setIssuedChallenges(array $issued_challenges) {
|
|
||||||
assert_instances_of($issued_challenges, 'PhabricatorAuthChallenge');
|
|
||||||
$this->issuedChallenges = $issued_challenges;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getIssuedChallenges() {
|
|
||||||
return $this->issuedChallenges;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setIcon(PHUIIconView $icon) {
|
public function setIcon(PHUIIconView $icon) {
|
||||||
$this->icon = $icon;
|
$this->icon = $icon;
|
||||||
return $this;
|
return $this;
|
||||||
|
|
|
@ -585,7 +585,7 @@ final class PhabricatorDuoAuthFactor
|
||||||
$result = $this->newDuoFuture($provider)
|
$result = $this->newDuoFuture($provider)
|
||||||
->setHTTPMethod('GET')
|
->setHTTPMethod('GET')
|
||||||
->setMethod('auth_status', $parameters)
|
->setMethod('auth_status', $parameters)
|
||||||
->setTimeout(5)
|
->setTimeout(3)
|
||||||
->resolve();
|
->resolve();
|
||||||
|
|
||||||
$state = $result['response']['result'];
|
$state = $result['response']['result'];
|
||||||
|
@ -661,15 +661,6 @@ final class PhabricatorDuoAuthFactor
|
||||||
PhabricatorAuthFactorResult $result) {
|
PhabricatorAuthFactorResult $result) {
|
||||||
|
|
||||||
$control = $this->newAutomaticControl($result);
|
$control = $this->newAutomaticControl($result);
|
||||||
if (!$control) {
|
|
||||||
$result = $this->newResult()
|
|
||||||
->setIsContinue(true)
|
|
||||||
->setErrorMessage(
|
|
||||||
pht(
|
|
||||||
'A challenge has been sent to your phone. Open the Duo '.
|
|
||||||
'application and confirm the challenge, then continue.'));
|
|
||||||
$control = $this->newAutomaticControl($result);
|
|
||||||
}
|
|
||||||
|
|
||||||
$control
|
$control
|
||||||
->setLabel(pht('Duo'))
|
->setLabel(pht('Duo'))
|
||||||
|
@ -689,7 +680,27 @@ final class PhabricatorDuoAuthFactor
|
||||||
PhabricatorUser $viewer,
|
PhabricatorUser $viewer,
|
||||||
AphrontRequest $request,
|
AphrontRequest $request,
|
||||||
array $challenges) {
|
array $challenges) {
|
||||||
return $this->newResult();
|
|
||||||
|
$result = $this->newResult()
|
||||||
|
->setIsContinue(true)
|
||||||
|
->setErrorMessage(
|
||||||
|
pht(
|
||||||
|
'A challenge has been sent to your phone. Open the Duo '.
|
||||||
|
'application and confirm the challenge, then continue.'));
|
||||||
|
|
||||||
|
$challenge = $this->getChallengeForCurrentContext(
|
||||||
|
$config,
|
||||||
|
$viewer,
|
||||||
|
$challenges);
|
||||||
|
if ($challenge) {
|
||||||
|
$result
|
||||||
|
->setStatusChallenge($challenge)
|
||||||
|
->setIcon(
|
||||||
|
id(new PHUIIconView())
|
||||||
|
->setIcon('fa-refresh', 'green ph-spin'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function newDuoFuture(PhabricatorAuthFactorProvider $provider) {
|
private function newDuoFuture(PhabricatorAuthFactorProvider $provider) {
|
||||||
|
@ -790,4 +801,54 @@ final class PhabricatorDuoAuthFactor
|
||||||
$hostname));
|
$hostname));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function newChallengeStatusView(
|
||||||
|
PhabricatorAuthFactorConfig $config,
|
||||||
|
PhabricatorAuthFactorProvider $provider,
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
PhabricatorAuthChallenge $challenge) {
|
||||||
|
|
||||||
|
$duo_xaction = $challenge->getChallengeKey();
|
||||||
|
|
||||||
|
$parameters = array(
|
||||||
|
'txid' => $duo_xaction,
|
||||||
|
);
|
||||||
|
|
||||||
|
$default_result = id(new PhabricatorAuthChallengeUpdate())
|
||||||
|
->setRetry(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $this->newDuoFuture($provider)
|
||||||
|
->setHTTPMethod('GET')
|
||||||
|
->setMethod('auth_status', $parameters)
|
||||||
|
->setTimeout(5)
|
||||||
|
->resolve();
|
||||||
|
|
||||||
|
$state = $result['response']['result'];
|
||||||
|
} catch (HTTPFutureCURLResponseStatus $exception) {
|
||||||
|
// If we failed or timed out, retry. Usually, this is a timeout.
|
||||||
|
return id(new PhabricatorAuthChallengeUpdate())
|
||||||
|
->setRetry(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For now, don't update the view for anything but an "Allow". Updates
|
||||||
|
// here are just about providing more visual feedback for user convenience.
|
||||||
|
if ($state !== 'allow') {
|
||||||
|
return id(new PhabricatorAuthChallengeUpdate())
|
||||||
|
->setRetry(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
$icon = id(new PHUIIconView())
|
||||||
|
->setIcon('fa-check-circle-o', 'green');
|
||||||
|
|
||||||
|
$view = id(new PHUIFormTimerControl())
|
||||||
|
->setIcon($icon)
|
||||||
|
->appendChild(pht('You responded to this challenge correctly.'))
|
||||||
|
->newTimerView();
|
||||||
|
|
||||||
|
return id(new PhabricatorAuthChallengeUpdate())
|
||||||
|
->setState('allow')
|
||||||
|
->setRetry(false)
|
||||||
|
->setMarkup($view);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,11 +80,6 @@ final class PhabricatorDuoFuture
|
||||||
$host = $this->apiHostname;
|
$host = $this->apiHostname;
|
||||||
$host = phutil_utf8_strtolower($host);
|
$host = phutil_utf8_strtolower($host);
|
||||||
|
|
||||||
$uri = id(new PhutilURI(''))
|
|
||||||
->setProtocol('https')
|
|
||||||
->setDomain($host)
|
|
||||||
->setPath($path);
|
|
||||||
|
|
||||||
$data = $this->parameters;
|
$data = $this->parameters;
|
||||||
$date = date('r');
|
$date = date('r');
|
||||||
|
|
||||||
|
@ -109,11 +104,19 @@ final class PhabricatorDuoFuture
|
||||||
$signature = new PhutilOpaqueEnvelope($signature);
|
$signature = new PhutilOpaqueEnvelope($signature);
|
||||||
|
|
||||||
if ($http_method === 'GET') {
|
if ($http_method === 'GET') {
|
||||||
$uri->setQueryParams($data);
|
$uri_data = $data;
|
||||||
$data = array();
|
$body_data = array();
|
||||||
|
} else {
|
||||||
|
$uri_data = array();
|
||||||
|
$body_data = $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
$future = id(new HTTPSFuture($uri, $data))
|
$uri = id(new PhutilURI('', $uri_data))
|
||||||
|
->setProtocol('https')
|
||||||
|
->setDomain($host)
|
||||||
|
->setPath($path);
|
||||||
|
|
||||||
|
$future = id(new HTTPSFuture($uri, $body_data))
|
||||||
->setHTTPBasicAuthCredentials($this->integrationKey, $signature)
|
->setHTTPBasicAuthCredentials($this->integrationKey, $signature)
|
||||||
->setMethod($http_method)
|
->setMethod($http_method)
|
||||||
->addHeader('Accept', 'application/json')
|
->addHeader('Accept', 'application/json')
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorAuthLinkMessageType
|
||||||
|
extends PhabricatorAuthMessageType {
|
||||||
|
|
||||||
|
const MESSAGEKEY = 'auth.link';
|
||||||
|
|
||||||
|
public function getDisplayName() {
|
||||||
|
return pht('Unlinked Account Instructions');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getShortDescription() {
|
||||||
|
return pht(
|
||||||
|
'Guidance shown after a user logs in with an email link and is '.
|
||||||
|
'prompted to link an external account.');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -161,7 +161,7 @@ abstract class PhabricatorAuthProvider extends Phobject {
|
||||||
abstract public function processLoginRequest(
|
abstract public function processLoginRequest(
|
||||||
PhabricatorAuthLoginController $controller);
|
PhabricatorAuthLoginController $controller);
|
||||||
|
|
||||||
public function buildLinkForm(PhabricatorAuthLinkController $controller) {
|
public function buildLinkForm($controller) {
|
||||||
return $this->renderLoginForm($controller->getRequest(), $mode = 'link');
|
return $this->renderLoginForm($controller->getRequest(), $mode = 'link');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,9 +220,7 @@ abstract class PhabricatorAuthProvider extends Phobject {
|
||||||
$adapter->getAdapterDomain(),
|
$adapter->getAdapterDomain(),
|
||||||
$account_id);
|
$account_id);
|
||||||
if (!$account) {
|
if (!$account) {
|
||||||
$account = id(new PhabricatorExternalAccount())
|
$account = $this->newExternalAccount()
|
||||||
->setAccountType($adapter->getAdapterType())
|
|
||||||
->setAccountDomain($adapter->getAdapterDomain())
|
|
||||||
->setAccountID($account_id);
|
->setAccountID($account_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,8 +297,18 @@ abstract class PhabricatorAuthProvider extends Phobject {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDefaultExternalAccount() {
|
public function newDefaultExternalAccount() {
|
||||||
throw new PhutilMethodNotImplementedException();
|
return $this->newExternalAccount();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function newExternalAccount() {
|
||||||
|
$config = $this->getProviderConfig();
|
||||||
|
$adapter = $this->getAdapter();
|
||||||
|
|
||||||
|
return id(new PhabricatorExternalAccount())
|
||||||
|
->setAccountType($adapter->getAdapterType())
|
||||||
|
->setAccountDomain($adapter->getAdapterDomain())
|
||||||
|
->setProviderConfigPHID($config->getPHID());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLoginOrder() {
|
public function getLoginOrder() {
|
||||||
|
@ -438,12 +446,13 @@ abstract class PhabricatorAuthProvider extends Phobject {
|
||||||
|
|
||||||
$uri = $attributes['uri'];
|
$uri = $attributes['uri'];
|
||||||
$uri = new PhutilURI($uri);
|
$uri = new PhutilURI($uri);
|
||||||
$params = $uri->getQueryParams();
|
$params = $uri->getQueryParamsAsPairList();
|
||||||
$uri->setQueryParams(array());
|
$uri->removeAllQueryParams();
|
||||||
|
|
||||||
$content = array($button);
|
$content = array($button);
|
||||||
|
|
||||||
foreach ($params as $key => $value) {
|
foreach ($params as $pair) {
|
||||||
|
list($key, $value) = $pair;
|
||||||
$content[] = phutil_tag(
|
$content[] = phutil_tag(
|
||||||
'input',
|
'input',
|
||||||
array(
|
array(
|
||||||
|
|
|
@ -159,8 +159,7 @@ final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider {
|
||||||
return $dialog;
|
return $dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildLinkForm(
|
public function buildLinkForm($controller) {
|
||||||
PhabricatorAuthLinkController $controller) {
|
|
||||||
throw new Exception(pht("Password providers can't be linked."));
|
throw new Exception(pht("Password providers can't be linked."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,14 +358,6 @@ final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDefaultExternalAccount() {
|
|
||||||
$adapter = $this->getAdapter();
|
|
||||||
|
|
||||||
return id(new PhabricatorExternalAccount())
|
|
||||||
->setAccountType($adapter->getAdapterType())
|
|
||||||
->setAccountDomain($adapter->getAdapterDomain());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function willSaveAccount(PhabricatorExternalAccount $account) {
|
protected function willSaveAccount(PhabricatorExternalAccount $account) {
|
||||||
parent::willSaveAccount($account);
|
parent::willSaveAccount($account);
|
||||||
$account->setUserPHID($account->getAccountID());
|
$account->setUserPHID($account->getAccountID());
|
||||||
|
|
|
@ -21,6 +21,7 @@ final class PhabricatorExternalAccountQuery
|
||||||
private $userPHIDs;
|
private $userPHIDs;
|
||||||
private $needImages;
|
private $needImages;
|
||||||
private $accountSecrets;
|
private $accountSecrets;
|
||||||
|
private $providerConfigPHIDs;
|
||||||
|
|
||||||
public function withUserPHIDs(array $user_phids) {
|
public function withUserPHIDs(array $user_phids) {
|
||||||
$this->userPHIDs = $user_phids;
|
$this->userPHIDs = $user_phids;
|
||||||
|
@ -62,6 +63,11 @@ final class PhabricatorExternalAccountQuery
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function withProviderConfigPHIDs(array $phids) {
|
||||||
|
$this->providerConfigPHIDs = $phids;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function newResultObject() {
|
public function newResultObject() {
|
||||||
return new PhabricatorExternalAccount();
|
return new PhabricatorExternalAccount();
|
||||||
}
|
}
|
||||||
|
@ -71,6 +77,26 @@ final class PhabricatorExternalAccountQuery
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function willFilterPage(array $accounts) {
|
protected function willFilterPage(array $accounts) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$configs = id(new PhabricatorAuthProviderConfigQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withPHIDs(mpull($accounts, 'getProviderConfigPHID'))
|
||||||
|
->execute();
|
||||||
|
$configs = mpull($configs, null, 'getPHID');
|
||||||
|
|
||||||
|
foreach ($accounts as $key => $account) {
|
||||||
|
$config_phid = $account->getProviderConfigPHID();
|
||||||
|
$config = idx($configs, $config_phid);
|
||||||
|
|
||||||
|
if (!$config) {
|
||||||
|
unset($accounts[$key]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$account->attachProviderConfig($config);
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->needImages) {
|
if ($this->needImages) {
|
||||||
$file_phids = mpull($accounts, 'getProfileImagePHID');
|
$file_phids = mpull($accounts, 'getProfileImagePHID');
|
||||||
$file_phids = array_filter($file_phids);
|
$file_phids = array_filter($file_phids);
|
||||||
|
@ -161,6 +187,13 @@ final class PhabricatorExternalAccountQuery
|
||||||
$this->accountSecrets);
|
$this->accountSecrets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->providerConfigPHIDs !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'providerConfigPHID IN (%Ls)',
|
||||||
|
$this->providerConfigPHIDs);
|
||||||
|
}
|
||||||
|
|
||||||
return $where;
|
return $where;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorAuthChallengeUpdate
|
||||||
|
extends Phobject {
|
||||||
|
|
||||||
|
private $retry = false;
|
||||||
|
private $state;
|
||||||
|
private $markup;
|
||||||
|
|
||||||
|
public function setRetry($retry) {
|
||||||
|
$this->retry = $retry;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRetry() {
|
||||||
|
return $this->retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setState($state) {
|
||||||
|
$this->state = $state;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getState() {
|
||||||
|
return $this->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setMarkup($markup) {
|
||||||
|
$this->markup = $markup;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMarkup() {
|
||||||
|
return $this->markup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newContent() {
|
||||||
|
return array(
|
||||||
|
'retry' => $this->getRetry(),
|
||||||
|
'state' => $this->getState(),
|
||||||
|
'markup' => $this->getMarkup(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -234,7 +234,7 @@ final class PhabricatorCalendarImportViewController
|
||||||
|
|
||||||
$all_uri = $this->getApplicationURI('import/log/');
|
$all_uri = $this->getApplicationURI('import/log/');
|
||||||
$all_uri = (string)id(new PhutilURI($all_uri))
|
$all_uri = (string)id(new PhutilURI($all_uri))
|
||||||
->setQueryParam('importSourcePHID', $import->getPHID());
|
->replaceQueryParam('importSourcePHID', $import->getPHID());
|
||||||
|
|
||||||
$all_button = id(new PHUIButtonView())
|
$all_button = id(new PHUIButtonView())
|
||||||
->setTag('a')
|
->setTag('a')
|
||||||
|
@ -273,8 +273,8 @@ final class PhabricatorCalendarImportViewController
|
||||||
|
|
||||||
$all_uri = $this->getApplicationURI();
|
$all_uri = $this->getApplicationURI();
|
||||||
$all_uri = (string)id(new PhutilURI($all_uri))
|
$all_uri = (string)id(new PhutilURI($all_uri))
|
||||||
->setQueryParam('importSourcePHID', $import->getPHID())
|
->replaceQueryParam('importSourcePHID', $import->getPHID())
|
||||||
->setQueryParam('display', 'list');
|
->replaceQueryParam('display', 'list');
|
||||||
|
|
||||||
$all_button = id(new PHUIButtonView())
|
$all_button = id(new PHUIButtonView())
|
||||||
->setTag('a')
|
->setTag('a')
|
||||||
|
|
|
@ -11,8 +11,7 @@ final class PhabricatorChatLogChannelLogController
|
||||||
$viewer = $request->getViewer();
|
$viewer = $request->getViewer();
|
||||||
$id = $request->getURIData('channelID');
|
$id = $request->getURIData('channelID');
|
||||||
|
|
||||||
$uri = clone $request->getRequestURI();
|
$uri = new PhutilURI($request->getPath());
|
||||||
$uri->setQueryParams(array());
|
|
||||||
|
|
||||||
$pager = new AphrontCursorPagerView();
|
$pager = new AphrontCursorPagerView();
|
||||||
$pager->setURI($uri);
|
$pager->setURI($uri);
|
||||||
|
|
|
@ -15,6 +15,9 @@ final class PhabricatorExtraConfigSetupCheck extends PhabricatorSetupCheck {
|
||||||
|
|
||||||
$defined_keys = PhabricatorApplicationConfigOptions::loadAllOptions();
|
$defined_keys = PhabricatorApplicationConfigOptions::loadAllOptions();
|
||||||
|
|
||||||
|
$stack = PhabricatorEnv::getConfigSourceStack();
|
||||||
|
$stack = $stack->getStack();
|
||||||
|
|
||||||
foreach ($all_keys as $key) {
|
foreach ($all_keys as $key) {
|
||||||
if (isset($defined_keys[$key])) {
|
if (isset($defined_keys[$key])) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -48,9 +51,6 @@ final class PhabricatorExtraConfigSetupCheck extends PhabricatorSetupCheck {
|
||||||
->setName($name)
|
->setName($name)
|
||||||
->setSummary($summary);
|
->setSummary($summary);
|
||||||
|
|
||||||
$stack = PhabricatorEnv::getConfigSourceStack();
|
|
||||||
$stack = $stack->getStack();
|
|
||||||
|
|
||||||
$found = array();
|
$found = array();
|
||||||
$found_local = false;
|
$found_local = false;
|
||||||
$found_database = false;
|
$found_database = false;
|
||||||
|
@ -85,6 +85,101 @@ final class PhabricatorExtraConfigSetupCheck extends PhabricatorSetupCheck {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$options = PhabricatorApplicationConfigOptions::loadAllOptions();
|
||||||
|
foreach ($defined_keys as $key => $value) {
|
||||||
|
$option = idx($options, $key);
|
||||||
|
if (!$option) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$option->getLocked()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$found_database = false;
|
||||||
|
foreach ($stack as $source_key => $source) {
|
||||||
|
$value = $source->getKeys(array($key));
|
||||||
|
if ($value) {
|
||||||
|
if ($source instanceof PhabricatorConfigDatabaseSource) {
|
||||||
|
$found_database = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$found_database) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: These are values which we don't let you edit directly, but edit
|
||||||
|
// via other UI workflows. For now, don't raise this warning about them.
|
||||||
|
// In the future, before we stop reading database configuration for
|
||||||
|
// locked values, we either need to add a flag which lets these values
|
||||||
|
// continue reading from the database or move them to some other storage
|
||||||
|
// mechanism.
|
||||||
|
$soft_locks = array(
|
||||||
|
'phabricator.uninstalled-applications',
|
||||||
|
'phabricator.application-settings',
|
||||||
|
'config.ignore-issues',
|
||||||
|
);
|
||||||
|
$soft_locks = array_fuse($soft_locks);
|
||||||
|
if (isset($soft_locks[$key])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$doc_name = 'Configuration Guide: Locked and Hidden Configuration';
|
||||||
|
$doc_href = PhabricatorEnv::getDoclink($doc_name);
|
||||||
|
|
||||||
|
$set_command = phutil_tag(
|
||||||
|
'tt',
|
||||||
|
array(),
|
||||||
|
csprintf(
|
||||||
|
'bin/config set %R <value>',
|
||||||
|
$key));
|
||||||
|
|
||||||
|
$summary = pht(
|
||||||
|
'Configuration value "%s" is locked, but has a value in the database.',
|
||||||
|
$key);
|
||||||
|
$message = pht(
|
||||||
|
'The configuration value "%s" is locked (so it can not be edited '.
|
||||||
|
'from the web UI), but has a database value. Usually, this means '.
|
||||||
|
'that it was previously not locked, you set it using the web UI, '.
|
||||||
|
'and it later became locked.'.
|
||||||
|
"\n\n".
|
||||||
|
'You should copy this configuration value in a local configuration '.
|
||||||
|
'source (usually by using %s) and then remove it from the database '.
|
||||||
|
'with the command below.'.
|
||||||
|
"\n\n".
|
||||||
|
'For more information on locked and hidden configuration, including '.
|
||||||
|
'details about this setup issue, see %s.'.
|
||||||
|
"\n\n".
|
||||||
|
'This database value is currently respected, but a future version '.
|
||||||
|
'of Phabricator will stop respecting database values for locked '.
|
||||||
|
'configuration options.',
|
||||||
|
$key,
|
||||||
|
$set_command,
|
||||||
|
phutil_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => $doc_href,
|
||||||
|
'target' => '_blank',
|
||||||
|
),
|
||||||
|
$doc_name));
|
||||||
|
$command = csprintf(
|
||||||
|
'phabricator/ $ ./bin/config delete --database %R',
|
||||||
|
$key);
|
||||||
|
|
||||||
|
$this->newIssue('config.locked.'.$key)
|
||||||
|
->setShortName(pht('Deprecated Config Source'))
|
||||||
|
->setName(
|
||||||
|
pht(
|
||||||
|
'Locked Configuration Option "%s" Has Database Value',
|
||||||
|
$key))
|
||||||
|
->setSummary($summary)
|
||||||
|
->setMessage($message)
|
||||||
|
->addCommand($command)
|
||||||
|
->addPhabricatorConfig($key);
|
||||||
|
}
|
||||||
|
|
||||||
if (PhabricatorEnv::getEnvConfig('feed.http-hooks')) {
|
if (PhabricatorEnv::getEnvConfig('feed.http-hooks')) {
|
||||||
$this->newIssue('config.deprecated.feed.http-hooks')
|
$this->newIssue('config.deprecated.feed.http-hooks')
|
||||||
|
|
|
@ -40,7 +40,7 @@ final class PhabricatorWebServerSetupCheck extends PhabricatorSetupCheck {
|
||||||
|
|
||||||
$base_uri = id(new PhutilURI($base_uri))
|
$base_uri = id(new PhutilURI($base_uri))
|
||||||
->setPath($send_path)
|
->setPath($send_path)
|
||||||
->setQueryParam($expect_key, $expect_value);
|
->replaceQueryParam($expect_key, $expect_value);
|
||||||
|
|
||||||
$self_future = id(new HTTPSFuture($base_uri))
|
$self_future = id(new HTTPSFuture($base_uri))
|
||||||
->addHeader('X-Phabricator-SelfCheck', 1)
|
->addHeader('X-Phabricator-SelfCheck', 1)
|
||||||
|
|
|
@ -41,7 +41,12 @@ final class PhabricatorPHDConfigOptions
|
||||||
"If you are running a cluster, this limit applies separately ".
|
"If you are running a cluster, this limit applies separately ".
|
||||||
"to each instance of `phd`. For example, if this limit is set ".
|
"to each instance of `phd`. For example, if this limit is set ".
|
||||||
"to `4` and you have three hosts running daemons, the effective ".
|
"to `4` and you have three hosts running daemons, the effective ".
|
||||||
"global limit will be 12.")),
|
"global limit will be 12.".
|
||||||
|
"\n\n".
|
||||||
|
"After changing this value, you must restart the daemons. Most ".
|
||||||
|
"configuration changes are picked up by the daemons ".
|
||||||
|
"automatically, but pool sizes can not be changed without a ".
|
||||||
|
"restart.")),
|
||||||
$this->newOption('phd.verbose', 'bool', false)
|
$this->newOption('phd.verbose', 'bool', false)
|
||||||
->setLocked(true)
|
->setLocked(true)
|
||||||
->setBoolOptions(
|
->setBoolOptions(
|
||||||
|
|
|
@ -188,7 +188,7 @@ final class ConpherenceViewController extends
|
||||||
} else {
|
} else {
|
||||||
// user not logged in so give them a login button.
|
// user not logged in so give them a login button.
|
||||||
$login_href = id(new PhutilURI('/auth/start/'))
|
$login_href = id(new PhutilURI('/auth/start/'))
|
||||||
->setQueryParam('next', '/'.$conpherence->getMonogram());
|
->replaceQueryParam('next', '/'.$conpherence->getMonogram());
|
||||||
return id(new PHUIFormLayoutView())
|
return id(new PHUIFormLayoutView())
|
||||||
->addClass('login-to-participate')
|
->addClass('login-to-participate')
|
||||||
->appendInstructions(pht('Log in to join this room and participate.'))
|
->appendInstructions(pht('Log in to join this room and participate.'))
|
||||||
|
|
|
@ -287,7 +287,7 @@ final class PhabricatorDashboardPanelRenderingEngine extends Phobject {
|
||||||
$edit_uri = "/dashboard/panel/edit/{$panel_id}/";
|
$edit_uri = "/dashboard/panel/edit/{$panel_id}/";
|
||||||
$edit_uri = new PhutilURI($edit_uri);
|
$edit_uri = new PhutilURI($edit_uri);
|
||||||
if ($dashboard_id) {
|
if ($dashboard_id) {
|
||||||
$edit_uri->setQueryParam('dashboardID', $dashboard_id);
|
$edit_uri->replaceQueryParam('dashboardID', $dashboard_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
$action_edit = id(new PHUIIconView())
|
$action_edit = id(new PHUIIconView())
|
||||||
|
@ -303,7 +303,7 @@ final class PhabricatorDashboardPanelRenderingEngine extends Phobject {
|
||||||
|
|
||||||
$remove_uri = "/dashboard/removepanel/{$dashboard_id}/";
|
$remove_uri = "/dashboard/removepanel/{$dashboard_id}/";
|
||||||
$remove_uri = id(new PhutilURI($remove_uri))
|
$remove_uri = id(new PhutilURI($remove_uri))
|
||||||
->setQueryParam('panelPHID', $panel_phid);
|
->replaceQueryParam('panelPHID', $panel_phid);
|
||||||
|
|
||||||
$action_remove = id(new PHUIIconView())
|
$action_remove = id(new PHUIIconView())
|
||||||
->setIcon('fa-trash-o')
|
->setIcon('fa-trash-o')
|
||||||
|
|
|
@ -113,11 +113,11 @@ final class PhabricatorDashboardRenderingEngine extends Phobject {
|
||||||
$dashboard_id = $this->dashboard->getID();
|
$dashboard_id = $this->dashboard->getID();
|
||||||
|
|
||||||
$create_uri = id(new PhutilURI('/dashboard/panel/create/'))
|
$create_uri = id(new PhutilURI('/dashboard/panel/create/'))
|
||||||
->setQueryParam('dashboardID', $dashboard_id)
|
->replaceQueryParam('dashboardID', $dashboard_id)
|
||||||
->setQueryParam('column', $column);
|
->replaceQueryParam('column', $column);
|
||||||
|
|
||||||
$add_uri = id(new PhutilURI('/dashboard/addpanel/'.$dashboard_id.'/'))
|
$add_uri = id(new PhutilURI('/dashboard/addpanel/'.$dashboard_id.'/'))
|
||||||
->setQueryParam('column', $column);
|
->replaceQueryParam('column', $column);
|
||||||
|
|
||||||
$create_button = id(new PHUIButtonView())
|
$create_button = id(new PHUIButtonView())
|
||||||
->setTag('a')
|
->setTag('a')
|
||||||
|
|
|
@ -71,7 +71,7 @@ final class DifferentialDiffCreateController extends DifferentialController {
|
||||||
$uri = $this->getApplicationURI("diff/{$diff_id}/");
|
$uri = $this->getApplicationURI("diff/{$diff_id}/");
|
||||||
$uri = new PhutilURI($uri);
|
$uri = new PhutilURI($uri);
|
||||||
if ($revision) {
|
if ($revision) {
|
||||||
$uri->setQueryParam('revisionID', $revision->getID());
|
$uri->replaceQueryParam('revisionID', $revision->getID());
|
||||||
}
|
}
|
||||||
|
|
||||||
return id(new AphrontRedirectResponse())->setURI($uri);
|
return id(new AphrontRedirectResponse())->setURI($uri);
|
||||||
|
|
|
@ -1098,7 +1098,8 @@ final class DifferentialRevisionViewController
|
||||||
// D123.vs123.id123.whitespaceignore-all.diff
|
// D123.vs123.id123.whitespaceignore-all.diff
|
||||||
// lame but nice to include these options
|
// lame but nice to include these options
|
||||||
$file_name = ltrim($request_uri->getPath(), '/').'.';
|
$file_name = ltrim($request_uri->getPath(), '/').'.';
|
||||||
foreach ($request_uri->getQueryParams() as $key => $value) {
|
foreach ($request_uri->getQueryParamsAsPairList() as $pair) {
|
||||||
|
list($key, $value) = $pair;
|
||||||
if ($key == 'download') {
|
if ($key == 'download') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,11 @@ final class DifferentialBuildableEngine
|
||||||
$object = $this->getObject();
|
$object = $this->getObject();
|
||||||
|
|
||||||
if ($object instanceof DifferentialDiff) {
|
if ($object instanceof DifferentialDiff) {
|
||||||
|
if ($object->getRevisionID()) {
|
||||||
return $object->getRevision();
|
return $object->getRevision();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $object;
|
return $object;
|
||||||
|
|
|
@ -358,7 +358,7 @@ final class DifferentialChangesetListView extends AphrontView {
|
||||||
|
|
||||||
if ($this->standaloneURI) {
|
if ($this->standaloneURI) {
|
||||||
$uri = new PhutilURI($this->standaloneURI);
|
$uri = new PhutilURI($this->standaloneURI);
|
||||||
$uri->setQueryParams($uri->getQueryParams() + $qparams);
|
$uri = $this->appendDefaultQueryParams($uri, $qparams);
|
||||||
$meta['standaloneURI'] = (string)$uri;
|
$meta['standaloneURI'] = (string)$uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,7 +381,7 @@ final class DifferentialChangesetListView extends AphrontView {
|
||||||
if ($this->leftRawFileURI) {
|
if ($this->leftRawFileURI) {
|
||||||
if ($change != DifferentialChangeType::TYPE_ADD) {
|
if ($change != DifferentialChangeType::TYPE_ADD) {
|
||||||
$uri = new PhutilURI($this->leftRawFileURI);
|
$uri = new PhutilURI($this->leftRawFileURI);
|
||||||
$uri->setQueryParams($uri->getQueryParams() + $qparams);
|
$uri = $this->appendDefaultQueryParams($uri, $qparams);
|
||||||
$meta['leftURI'] = (string)$uri;
|
$meta['leftURI'] = (string)$uri;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -390,7 +390,7 @@ final class DifferentialChangesetListView extends AphrontView {
|
||||||
if ($change != DifferentialChangeType::TYPE_DELETE &&
|
if ($change != DifferentialChangeType::TYPE_DELETE &&
|
||||||
$change != DifferentialChangeType::TYPE_MULTICOPY) {
|
$change != DifferentialChangeType::TYPE_MULTICOPY) {
|
||||||
$uri = new PhutilURI($this->rightRawFileURI);
|
$uri = new PhutilURI($this->rightRawFileURI);
|
||||||
$uri->setQueryParams($uri->getQueryParams() + $qparams);
|
$uri = $this->appendDefaultQueryParams($uri, $qparams);
|
||||||
$meta['rightURI'] = (string)$uri;
|
$meta['rightURI'] = (string)$uri;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -421,4 +421,23 @@ final class DifferentialChangesetListView extends AphrontView {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function appendDefaultQueryParams(PhutilURI $uri, array $params) {
|
||||||
|
// Add these default query parameters to the query string if they do not
|
||||||
|
// already exist.
|
||||||
|
|
||||||
|
$have = array();
|
||||||
|
foreach ($uri->getQueryParamsAsPairList() as $pair) {
|
||||||
|
list($key, $value) = $pair;
|
||||||
|
$have[$key] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($params as $key => $value) {
|
||||||
|
if (!isset($have[$key])) {
|
||||||
|
$uri->appendQueryParam($key, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $uri;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -709,8 +709,6 @@ final class DiffusionBrowseController extends DiffusionController {
|
||||||
'path' => $path,
|
'path' => $path,
|
||||||
));
|
));
|
||||||
|
|
||||||
$before_uri->setQueryParams($request->getRequestURI()->getQueryParams());
|
|
||||||
$before_uri = $before_uri->alter('before', null);
|
|
||||||
$before_uri = $before_uri->alter('renamed', $renamed);
|
$before_uri = $before_uri->alter('renamed', $renamed);
|
||||||
$before_uri = $before_uri->alter('follow', $follow);
|
$before_uri = $before_uri->alter('follow', $follow);
|
||||||
|
|
||||||
|
|
|
@ -81,12 +81,12 @@ abstract class DiffusionView extends AphrontView {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($details['external'])) {
|
if (isset($details['external'])) {
|
||||||
$href = id(new PhutilURI('/diffusion/external/'))
|
$params = array(
|
||||||
->setQueryParams(
|
|
||||||
array(
|
|
||||||
'uri' => idx($details, 'external'),
|
'uri' => idx($details, 'external'),
|
||||||
'id' => idx($details, 'hash'),
|
'id' => idx($details, 'hash'),
|
||||||
));
|
);
|
||||||
|
|
||||||
|
$href = new PhutilURI('/diffusion/external/', $params);
|
||||||
$tip = pht('Browse External');
|
$tip = pht('Browse External');
|
||||||
} else {
|
} else {
|
||||||
$href = $this->getDiffusionRequest()->generateURI(
|
$href = $this->getDiffusionRequest()->generateURI(
|
||||||
|
|
|
@ -111,15 +111,15 @@ final class DivinerSymbolRemarkupRule extends PhutilRemarkupRule {
|
||||||
// Here, we're generating comment text or something like that. Just
|
// Here, we're generating comment text or something like that. Just
|
||||||
// link to Diviner and let it sort things out.
|
// link to Diviner and let it sort things out.
|
||||||
|
|
||||||
$href = id(new PhutilURI('/diviner/find/'))
|
$params = array(
|
||||||
->setQueryParams(
|
|
||||||
array(
|
|
||||||
'book' => $ref->getBook(),
|
'book' => $ref->getBook(),
|
||||||
'name' => $ref->getName(),
|
'name' => $ref->getName(),
|
||||||
'type' => $ref->getType(),
|
'type' => $ref->getType(),
|
||||||
'context' => $ref->getContext(),
|
'context' => $ref->getContext(),
|
||||||
'jump' => true,
|
'jump' => true,
|
||||||
));
|
);
|
||||||
|
|
||||||
|
$href = new PhutilURI('/diviner/find/', $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This probably is not the best place to do this. Move it somewhere
|
// TODO: This probably is not the best place to do this. Move it somewhere
|
||||||
|
|
|
@ -11,7 +11,7 @@ final class PhabricatorFactHomeController extends PhabricatorFactController {
|
||||||
|
|
||||||
if ($request->isFormPost()) {
|
if ($request->isFormPost()) {
|
||||||
$uri = new PhutilURI('/fact/chart/');
|
$uri = new PhutilURI('/fact/chart/');
|
||||||
$uri->setQueryParam('y1', $request->getStr('y1'));
|
$uri->replaceQueryParam('y1', $request->getStr('y1'));
|
||||||
return id(new AphrontRedirectResponse())->setURI($uri);
|
return id(new AphrontRedirectResponse())->setURI($uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,7 +135,7 @@ final class PhabricatorFileDataController extends PhabricatorFileController {
|
||||||
$request_uri = id(clone $request->getAbsoluteRequestURI())
|
$request_uri = id(clone $request->getAbsoluteRequestURI())
|
||||||
->setPath(null)
|
->setPath(null)
|
||||||
->setFragment(null)
|
->setFragment(null)
|
||||||
->setQueryParams(array());
|
->removeAllQueryParams();
|
||||||
|
|
||||||
$response->addContentSecurityPolicyURI(
|
$response->addContentSecurityPolicyURI(
|
||||||
'object-src',
|
'object-src',
|
||||||
|
|
|
@ -70,7 +70,7 @@ final class PhabricatorFileLightboxController
|
||||||
|
|
||||||
if (!$viewer->isLoggedIn()) {
|
if (!$viewer->isLoggedIn()) {
|
||||||
$login_href = id(new PhutilURI('/auth/start/'))
|
$login_href = id(new PhutilURI('/auth/start/'))
|
||||||
->setQueryParam('next', '/'.$file->getMonogram());
|
->replaceQueryParam('next', '/'.$file->getMonogram());
|
||||||
return id(new PHUIFormLayoutView())
|
return id(new PHUIFormLayoutView())
|
||||||
->addClass('phui-comment-panel-empty')
|
->addClass('phui-comment-panel-empty')
|
||||||
->appendChild(
|
->appendChild(
|
||||||
|
|
|
@ -61,7 +61,7 @@ final class PhabricatorFileTransformListController
|
||||||
|
|
||||||
$view_href = $file->getURIForTransform($xform);
|
$view_href = $file->getURIForTransform($xform);
|
||||||
$view_href = new PhutilURI($view_href);
|
$view_href = new PhutilURI($view_href);
|
||||||
$view_href->setQueryParam('regenerate', 'true');
|
$view_href->replaceQueryParam('regenerate', 'true');
|
||||||
|
|
||||||
$view_text = pht('Regenerate');
|
$view_text = pht('Regenerate');
|
||||||
|
|
||||||
|
|
|
@ -149,7 +149,7 @@ final class PhabricatorImageRemarkupRule extends PhutilRemarkupRule {
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
$src_uri = id(new PhutilURI('/file/imageproxy/'))
|
$src_uri = id(new PhutilURI('/file/imageproxy/'))
|
||||||
->setQueryParam('uri', $uri);
|
->replaceQueryParam('uri', $uri);
|
||||||
|
|
||||||
$img = id(new PHUIRemarkupImageView())
|
$img = id(new PHUIRemarkupImageView())
|
||||||
->setURI($src_uri)
|
->setURI($src_uri)
|
||||||
|
|
|
@ -81,13 +81,13 @@ final class HeraldNewController extends HeraldController {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$errors && $done) {
|
if (!$errors && $done) {
|
||||||
$uri = id(new PhutilURI('edit/'))
|
$params = array(
|
||||||
->setQueryParams(
|
|
||||||
array(
|
|
||||||
'content_type' => $content_type,
|
'content_type' => $content_type,
|
||||||
'rule_type' => $rule_type,
|
'rule_type' => $rule_type,
|
||||||
'targetPHID' => $target_phid,
|
'targetPHID' => $target_phid,
|
||||||
));
|
);
|
||||||
|
|
||||||
|
$uri = new PhutilURI('edit/', $params);
|
||||||
$uri = $this->getApplicationURI($uri);
|
$uri = $this->getApplicationURI($uri);
|
||||||
return id(new AphrontRedirectResponse())->setURI($uri);
|
return id(new AphrontRedirectResponse())->setURI($uri);
|
||||||
}
|
}
|
||||||
|
@ -126,13 +126,13 @@ final class HeraldNewController extends HeraldController {
|
||||||
->addHiddenInput('step', 2)
|
->addHiddenInput('step', 2)
|
||||||
->appendChild($rule_types);
|
->appendChild($rule_types);
|
||||||
|
|
||||||
$cancel_text = pht('Back');
|
$params = array(
|
||||||
$cancel_uri = id(new PhutilURI('new/'))
|
|
||||||
->setQueryParams(
|
|
||||||
array(
|
|
||||||
'content_type' => $content_type,
|
'content_type' => $content_type,
|
||||||
'step' => 0,
|
'step' => '0',
|
||||||
));
|
);
|
||||||
|
|
||||||
|
$cancel_text = pht('Back');
|
||||||
|
$cancel_uri = new PhutilURI('new/', $params);
|
||||||
$cancel_uri = $this->getApplicationURI($cancel_uri);
|
$cancel_uri = $this->getApplicationURI($cancel_uri);
|
||||||
$title = pht('Create Herald Rule: %s',
|
$title = pht('Create Herald Rule: %s',
|
||||||
idx($content_type_map, $content_type));
|
idx($content_type_map, $content_type));
|
||||||
|
@ -173,14 +173,14 @@ final class HeraldNewController extends HeraldController {
|
||||||
->setValue($request->getStr('objectName'))
|
->setValue($request->getStr('objectName'))
|
||||||
->setLabel(pht('Object')));
|
->setLabel(pht('Object')));
|
||||||
|
|
||||||
$cancel_text = pht('Back');
|
$params = array(
|
||||||
$cancel_uri = id(new PhutilURI('new/'))
|
|
||||||
->setQueryParams(
|
|
||||||
array(
|
|
||||||
'content_type' => $content_type,
|
'content_type' => $content_type,
|
||||||
'rule_type' => $rule_type,
|
'rule_type' => $rule_type,
|
||||||
'step' => 1,
|
'step' => 1,
|
||||||
));
|
);
|
||||||
|
|
||||||
|
$cancel_text = pht('Back');
|
||||||
|
$cancel_uri = new PhutilURI('new/', $params);
|
||||||
$cancel_uri = $this->getApplicationURI($cancel_uri);
|
$cancel_uri = $this->getApplicationURI($cancel_uri);
|
||||||
$title = pht('Create Herald Rule: %s',
|
$title = pht('Create Herald Rule: %s',
|
||||||
idx($content_type_map, $content_type));
|
idx($content_type_map, $content_type));
|
||||||
|
|
|
@ -120,7 +120,7 @@ final class HeraldWebhookRequest
|
||||||
public function getErrorTypeForDisplay() {
|
public function getErrorTypeForDisplay() {
|
||||||
$map = array(
|
$map = array(
|
||||||
self::ERRORTYPE_HOOK => pht('Hook Error'),
|
self::ERRORTYPE_HOOK => pht('Hook Error'),
|
||||||
self::ERRORTYPE_HTTP => pht('HTTP Error'),
|
self::ERRORTYPE_HTTP => pht('HTTP Status Code'),
|
||||||
self::ERRORTYPE_TIMEOUT => pht('Request Timeout'),
|
self::ERRORTYPE_TIMEOUT => pht('Request Timeout'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -47,10 +47,13 @@ final class PhabricatorMemeEngine extends Phobject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getGenerateURI() {
|
public function getGenerateURI() {
|
||||||
return id(new PhutilURI('/macro/meme/'))
|
$params = array(
|
||||||
->alter('macro', $this->getTemplate())
|
'macro' => $this->getTemplate(),
|
||||||
->alter('above', $this->getAboveText())
|
'above' => $this->getAboveText(),
|
||||||
->alter('below', $this->getBelowText());
|
'below' => $this->getBelowText(),
|
||||||
|
);
|
||||||
|
|
||||||
|
return new PhutilURI('/macro/meme/', $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function newAsset() {
|
public function newAsset() {
|
||||||
|
|
|
@ -55,6 +55,7 @@ final class PhabricatorManiphestApplication extends PhabricatorApplication {
|
||||||
'subtask/(?P<id>[1-9]\d*)/' => 'ManiphestTaskSubtaskController',
|
'subtask/(?P<id>[1-9]\d*)/' => 'ManiphestTaskSubtaskController',
|
||||||
),
|
),
|
||||||
'subpriority/' => 'ManiphestSubpriorityController',
|
'subpriority/' => 'ManiphestSubpriorityController',
|
||||||
|
'graph/(?P<id>[1-9]\d*)/' => 'ManiphestTaskGraphController',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,4 +61,102 @@ abstract class ManiphestController extends PhabricatorController {
|
||||||
return $view;
|
return $view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final protected function newTaskGraphDropdownMenu(
|
||||||
|
ManiphestTask $task,
|
||||||
|
$has_parents,
|
||||||
|
$has_subtasks,
|
||||||
|
$include_standalone) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$parents_uri = urisprintf(
|
||||||
|
'/?subtaskIDs=%d#R',
|
||||||
|
$task->getID());
|
||||||
|
$parents_uri = $this->getApplicationURI($parents_uri);
|
||||||
|
|
||||||
|
$subtasks_uri = urisprintf(
|
||||||
|
'/?parentIDs=%d#R',
|
||||||
|
$task->getID());
|
||||||
|
$subtasks_uri = $this->getApplicationURI($subtasks_uri);
|
||||||
|
|
||||||
|
$dropdown_menu = id(new PhabricatorActionListView())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->addAction(
|
||||||
|
id(new PhabricatorActionView())
|
||||||
|
->setHref($parents_uri)
|
||||||
|
->setName(pht('Search Parent Tasks'))
|
||||||
|
->setDisabled(!$has_parents)
|
||||||
|
->setIcon('fa-chevron-circle-up'))
|
||||||
|
->addAction(
|
||||||
|
id(new PhabricatorActionView())
|
||||||
|
->setHref($subtasks_uri)
|
||||||
|
->setName(pht('Search Subtasks'))
|
||||||
|
->setDisabled(!$has_subtasks)
|
||||||
|
->setIcon('fa-chevron-circle-down'));
|
||||||
|
|
||||||
|
if ($include_standalone) {
|
||||||
|
$standalone_uri = urisprintf('/graph/%d/', $task->getID());
|
||||||
|
$standalone_uri = $this->getApplicationURI($standalone_uri);
|
||||||
|
|
||||||
|
$dropdown_menu->addAction(
|
||||||
|
id(new PhabricatorActionView())
|
||||||
|
->setHref($standalone_uri)
|
||||||
|
->setName(pht('View Standalone Graph'))
|
||||||
|
->setIcon('fa-code-fork'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$graph_menu = id(new PHUIButtonView())
|
||||||
|
->setTag('a')
|
||||||
|
->setIcon('fa-search')
|
||||||
|
->setText(pht('Search...'))
|
||||||
|
->setDropdownMenu($dropdown_menu);
|
||||||
|
|
||||||
|
return $graph_menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected function newTaskGraphOverflowView(
|
||||||
|
ManiphestTask $task,
|
||||||
|
$overflow_message,
|
||||||
|
$include_standalone) {
|
||||||
|
|
||||||
|
$id = $task->getID();
|
||||||
|
|
||||||
|
if ($include_standalone) {
|
||||||
|
$standalone_uri = $this->getApplicationURI("graph/{$id}/");
|
||||||
|
|
||||||
|
$standalone_link = id(new PHUIButtonView())
|
||||||
|
->setTag('a')
|
||||||
|
->setHref($standalone_uri)
|
||||||
|
->setColor(PHUIButtonView::GREY)
|
||||||
|
->setIcon('fa-code-fork')
|
||||||
|
->setText(pht('View Standalone Graph'));
|
||||||
|
} else {
|
||||||
|
$standalone_link = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$standalone_icon = id(new PHUIIconView())
|
||||||
|
->setIcon('fa-exclamation-triangle', 'yellow')
|
||||||
|
->addClass('object-graph-header-icon');
|
||||||
|
|
||||||
|
$standalone_view = phutil_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => 'object-graph-header',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
$standalone_link,
|
||||||
|
$standalone_icon,
|
||||||
|
phutil_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => 'object-graph-header-message',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
$overflow_message,
|
||||||
|
)),
|
||||||
|
));
|
||||||
|
|
||||||
|
return $standalone_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,8 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
||||||
$related_tabs = array();
|
$related_tabs = array();
|
||||||
$graph_menu = null;
|
$graph_menu = null;
|
||||||
|
|
||||||
$graph_limit = 100;
|
$graph_limit = 200;
|
||||||
|
$overflow_message = null;
|
||||||
$task_graph = id(new ManiphestTaskGraph())
|
$task_graph = id(new ManiphestTaskGraph())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->setSeedPHID($task->getPHID())
|
->setSeedPHID($task->getPHID())
|
||||||
|
@ -96,61 +97,55 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
||||||
$has_parents = (bool)$parent_list;
|
$has_parents = (bool)$parent_list;
|
||||||
$has_subtasks = (bool)$subtask_list;
|
$has_subtasks = (bool)$subtask_list;
|
||||||
|
|
||||||
$search_text = pht('Search...');
|
|
||||||
|
|
||||||
// First, get a count of direct parent tasks and subtasks. If there
|
// First, get a count of direct parent tasks and subtasks. If there
|
||||||
// are too many of these, we just don't draw anything. You can use
|
// are too many of these, we just don't draw anything. You can use
|
||||||
// the search button to browse tasks with the search UI instead.
|
// the search button to browse tasks with the search UI instead.
|
||||||
$direct_count = count($parent_list) + count($subtask_list);
|
$direct_count = count($parent_list) + count($subtask_list);
|
||||||
|
|
||||||
if ($direct_count > $graph_limit) {
|
if ($direct_count > $graph_limit) {
|
||||||
$message = pht(
|
$overflow_message = pht(
|
||||||
'Task graph too large to display (this task is directly connected '.
|
'This task is directly connected to more than %s other tasks. '.
|
||||||
'to more than %s other tasks). Use %s to explore connected tasks.',
|
'Use %s to browse parents or subtasks, or %s to show more of the '.
|
||||||
$graph_limit,
|
'graph.',
|
||||||
phutil_tag('strong', array(), $search_text));
|
new PhutilNumber($graph_limit),
|
||||||
$message = phutil_tag('em', array(), $message);
|
phutil_tag('strong', array(), pht('Search...')),
|
||||||
$graph_table = id(new PHUIPropertyListView())
|
phutil_tag('strong', array(), pht('View Standalone Graph')));
|
||||||
->addTextContent($message);
|
|
||||||
|
$graph_table = null;
|
||||||
} else {
|
} else {
|
||||||
// If there aren't too many direct tasks, but there are too many total
|
// If there aren't too many direct tasks, but there are too many total
|
||||||
// tasks, we'll only render directly connected tasks.
|
// tasks, we'll only render directly connected tasks.
|
||||||
if ($task_graph->isOverLimit()) {
|
if ($task_graph->isOverLimit()) {
|
||||||
$task_graph->setRenderOnlyAdjacentNodes(true);
|
$task_graph->setRenderOnlyAdjacentNodes(true);
|
||||||
|
|
||||||
|
$overflow_message = pht(
|
||||||
|
'This task is connected to more than %s other tasks. '.
|
||||||
|
'Only direct parents and subtasks are shown here. Use '.
|
||||||
|
'%s to show more of the graph.',
|
||||||
|
new PhutilNumber($graph_limit),
|
||||||
|
phutil_tag('strong', array(), pht('View Standalone Graph')));
|
||||||
}
|
}
|
||||||
|
|
||||||
$graph_table = $task_graph->newGraphTable();
|
$graph_table = $task_graph->newGraphTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
$parents_uri = urisprintf(
|
if ($overflow_message) {
|
||||||
'/?subtaskIDs=%d#R',
|
$overflow_view = $this->newTaskGraphOverflowView(
|
||||||
$task->getID());
|
$task,
|
||||||
$parents_uri = $this->getApplicationURI($parents_uri);
|
$overflow_message,
|
||||||
|
true);
|
||||||
|
|
||||||
$subtasks_uri = urisprintf(
|
$graph_table = array(
|
||||||
'/?parentIDs=%d#R',
|
$overflow_view,
|
||||||
$task->getID());
|
$graph_table,
|
||||||
$subtasks_uri = $this->getApplicationURI($subtasks_uri);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$dropdown_menu = id(new PhabricatorActionListView())
|
$graph_menu = $this->newTaskGraphDropdownMenu(
|
||||||
->setViewer($viewer)
|
$task,
|
||||||
->addAction(
|
$has_parents,
|
||||||
id(new PhabricatorActionView())
|
$has_subtasks,
|
||||||
->setHref($parents_uri)
|
true);
|
||||||
->setName(pht('Search Parent Tasks'))
|
|
||||||
->setDisabled(!$has_parents)
|
|
||||||
->setIcon('fa-chevron-circle-up'))
|
|
||||||
->addAction(
|
|
||||||
id(new PhabricatorActionView())
|
|
||||||
->setHref($subtasks_uri)
|
|
||||||
->setName(pht('Search Subtasks'))
|
|
||||||
->setDisabled(!$has_subtasks)
|
|
||||||
->setIcon('fa-chevron-circle-down'));
|
|
||||||
|
|
||||||
$graph_menu = id(new PHUIButtonView())
|
|
||||||
->setTag('a')
|
|
||||||
->setIcon('fa-search')
|
|
||||||
->setText($search_text)
|
|
||||||
->setDropdownMenu($dropdown_menu);
|
|
||||||
|
|
||||||
$related_tabs[] = id(new PHUITabView())
|
$related_tabs[] = id(new PHUITabView())
|
||||||
->setName(pht('Task Graph'))
|
->setName(pht('Task Graph'))
|
||||||
|
@ -300,9 +295,9 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
||||||
$subtask_form = head($subtask_options);
|
$subtask_form = head($subtask_options);
|
||||||
$form_key = $subtask_form->getIdentifier();
|
$form_key = $subtask_form->getIdentifier();
|
||||||
$subtask_uri = id(new PhutilURI("/task/edit/form/{$form_key}/"))
|
$subtask_uri = id(new PhutilURI("/task/edit/form/{$form_key}/"))
|
||||||
->setQueryParam('parent', $id)
|
->replaceQueryParam('parent', $id)
|
||||||
->setQueryParam('template', $id)
|
->replaceQueryParam('template', $id)
|
||||||
->setQueryParam('status', ManiphestTaskStatus::getDefaultStatus());
|
->replaceQueryParam('status', ManiphestTaskStatus::getDefaultStatus());
|
||||||
$subtask_workflow = false;
|
$subtask_workflow = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ManiphestTaskGraphController
|
||||||
|
extends ManiphestController {
|
||||||
|
|
||||||
|
public function shouldAllowPublic() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
$id = $request->getURIData('id');
|
||||||
|
|
||||||
|
$task = id(new ManiphestTaskQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withIDs(array($id))
|
||||||
|
->executeOne();
|
||||||
|
if (!$task) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$crumbs = $this->buildApplicationCrumbs()
|
||||||
|
->addTextCrumb($task->getMonogram(), $task->getURI())
|
||||||
|
->addTextCrumb(pht('Graph'))
|
||||||
|
->setBorder(true);
|
||||||
|
|
||||||
|
$graph_limit = 2000;
|
||||||
|
$overflow_message = null;
|
||||||
|
$task_graph = id(new ManiphestTaskGraph())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->setSeedPHID($task->getPHID())
|
||||||
|
->setLimit($graph_limit)
|
||||||
|
->loadGraph();
|
||||||
|
if (!$task_graph->isEmpty()) {
|
||||||
|
$parent_type = ManiphestTaskDependedOnByTaskEdgeType::EDGECONST;
|
||||||
|
$subtask_type = ManiphestTaskDependsOnTaskEdgeType::EDGECONST;
|
||||||
|
$parent_map = $task_graph->getEdges($parent_type);
|
||||||
|
$subtask_map = $task_graph->getEdges($subtask_type);
|
||||||
|
$parent_list = idx($parent_map, $task->getPHID(), array());
|
||||||
|
$subtask_list = idx($subtask_map, $task->getPHID(), array());
|
||||||
|
$has_parents = (bool)$parent_list;
|
||||||
|
$has_subtasks = (bool)$subtask_list;
|
||||||
|
|
||||||
|
// First, get a count of direct parent tasks and subtasks. If there
|
||||||
|
// are too many of these, we just don't draw anything. You can use
|
||||||
|
// the search button to browse tasks with the search UI instead.
|
||||||
|
$direct_count = count($parent_list) + count($subtask_list);
|
||||||
|
|
||||||
|
if ($direct_count > $graph_limit) {
|
||||||
|
$overflow_message = pht(
|
||||||
|
'This task is directly connected to more than %s other tasks, '.
|
||||||
|
'which is too many tasks to display. Use %s to browse parents '.
|
||||||
|
'or subtasks.',
|
||||||
|
new PhutilNumber($graph_limit),
|
||||||
|
phutil_tag('strong', array(), pht('Search...')));
|
||||||
|
|
||||||
|
$graph_table = null;
|
||||||
|
} else {
|
||||||
|
// If there aren't too many direct tasks, but there are too many total
|
||||||
|
// tasks, we'll only render directly connected tasks.
|
||||||
|
if ($task_graph->isOverLimit()) {
|
||||||
|
$task_graph->setRenderOnlyAdjacentNodes(true);
|
||||||
|
|
||||||
|
$overflow_message = pht(
|
||||||
|
'This task is connected to more than %s other tasks. '.
|
||||||
|
'Only direct parents and subtasks are shown here.',
|
||||||
|
new PhutilNumber($graph_limit));
|
||||||
|
}
|
||||||
|
|
||||||
|
$graph_table = $task_graph->newGraphTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
$graph_menu = $this->newTaskGraphDropdownMenu(
|
||||||
|
$task,
|
||||||
|
$has_parents,
|
||||||
|
$has_subtasks,
|
||||||
|
false);
|
||||||
|
} else {
|
||||||
|
$graph_menu = null;
|
||||||
|
$graph_table = null;
|
||||||
|
|
||||||
|
$overflow_message = pht(
|
||||||
|
'This task has no parent tasks and no subtasks, so there is no '.
|
||||||
|
'graph to draw.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($overflow_message) {
|
||||||
|
$overflow_view = $this->newTaskGraphOverflowView(
|
||||||
|
$task,
|
||||||
|
$overflow_message,
|
||||||
|
false);
|
||||||
|
|
||||||
|
$graph_table = array(
|
||||||
|
$overflow_view,
|
||||||
|
$graph_table,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = id(new PHUIHeaderView())
|
||||||
|
->setHeader(pht('Task Graph'));
|
||||||
|
|
||||||
|
if ($graph_menu) {
|
||||||
|
$header->addActionLink($graph_menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tab_view = id(new PHUIObjectBoxView())
|
||||||
|
->setHeader($header)
|
||||||
|
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||||
|
->appendChild($graph_table);
|
||||||
|
|
||||||
|
$view = id(new PHUITwoColumnView())
|
||||||
|
->setFooter($tab_view);
|
||||||
|
|
||||||
|
return $this->newPage()
|
||||||
|
->setTitle(
|
||||||
|
array(
|
||||||
|
$task->getMonogram(),
|
||||||
|
pht('Graph'),
|
||||||
|
))
|
||||||
|
->setCrumbs($crumbs)
|
||||||
|
->appendChild($view);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -47,9 +47,9 @@ final class ManiphestTaskSubtaskController
|
||||||
$subtype = $subtype_map->getSubtype($subtype_key);
|
$subtype = $subtype_map->getSubtype($subtype_key);
|
||||||
|
|
||||||
$subtask_uri = id(new PhutilURI("/task/edit/form/{$form_key}/"))
|
$subtask_uri = id(new PhutilURI("/task/edit/form/{$form_key}/"))
|
||||||
->setQueryParam('parent', $id)
|
->replaceQueryParam('parent', $id)
|
||||||
->setQueryParam('template', $id)
|
->replaceQueryParam('template', $id)
|
||||||
->setQueryParam('status', ManiphestTaskStatus::getDefaultStatus());
|
->replaceQueryParam('status', ManiphestTaskStatus::getDefaultStatus());
|
||||||
$subtask_uri = $this->getApplicationURI($subtask_uri);
|
$subtask_uri = $this->getApplicationURI($subtask_uri);
|
||||||
|
|
||||||
$item = id(new PHUIObjectItemView())
|
$item = id(new PHUIObjectItemView())
|
||||||
|
|
|
@ -135,7 +135,7 @@ final class ManiphestTaskListView extends ManiphestView {
|
||||||
if ($this->showBatchControls) {
|
if ($this->showBatchControls) {
|
||||||
$href = new PhutilURI('/maniphest/task/edit/'.$task->getID().'/');
|
$href = new PhutilURI('/maniphest/task/edit/'.$task->getID().'/');
|
||||||
if (!$this->showSubpriorityControls) {
|
if (!$this->showSubpriorityControls) {
|
||||||
$href->setQueryParam('ungrippable', 'true');
|
$href->replaceQueryParam('ungrippable', 'true');
|
||||||
}
|
}
|
||||||
$item->addAction(
|
$item->addAction(
|
||||||
id(new PHUIListItemView())
|
id(new PHUIListItemView())
|
||||||
|
|
|
@ -24,6 +24,7 @@ final class PhabricatorMailMailgunAdapter
|
||||||
array(
|
array(
|
||||||
'api-key' => 'string',
|
'api-key' => 'string',
|
||||||
'domain' => 'string',
|
'domain' => 'string',
|
||||||
|
'api-hostname' => 'string',
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,12 +32,14 @@ final class PhabricatorMailMailgunAdapter
|
||||||
return array(
|
return array(
|
||||||
'api-key' => null,
|
'api-key' => null,
|
||||||
'domain' => null,
|
'domain' => null,
|
||||||
|
'api-hostname' => 'api.mailgun.net',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function sendMessage(PhabricatorMailExternalMessage $message) {
|
public function sendMessage(PhabricatorMailExternalMessage $message) {
|
||||||
$api_key = $this->getOption('api-key');
|
$api_key = $this->getOption('api-key');
|
||||||
$domain = $this->getOption('domain');
|
$domain = $this->getOption('domain');
|
||||||
|
$api_hostname = $this->getOption('api-hostname');
|
||||||
$params = array();
|
$params = array();
|
||||||
|
|
||||||
$subject = $message->getSubject();
|
$subject = $message->getSubject();
|
||||||
|
@ -92,7 +95,8 @@ final class PhabricatorMailMailgunAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
$mailgun_uri = urisprintf(
|
$mailgun_uri = urisprintf(
|
||||||
'https://api.mailgun.net/v2/%s/messages',
|
'https://%s/v2/%s/messages',
|
||||||
|
$api_hostname,
|
||||||
$domain);
|
$domain);
|
||||||
|
|
||||||
$future = id(new HTTPSFuture($mailgun_uri, $params))
|
$future = id(new HTTPSFuture($mailgun_uri, $params))
|
||||||
|
|
|
@ -54,8 +54,7 @@ final class PhabricatorMetaMTAApplicationEmailPanel
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
$uri = $request->getRequestURI();
|
$uri = new PhutilURI($request->getPath());
|
||||||
$uri->setQueryParams(array());
|
|
||||||
|
|
||||||
$new = $request->getStr('new');
|
$new = $request->getStr('new');
|
||||||
$edit = $request->getInt('edit');
|
$edit = $request->getInt('edit');
|
||||||
|
|
|
@ -302,11 +302,11 @@ final class MultimeterSampleController extends MultimeterController {
|
||||||
if (!strlen($group)) {
|
if (!strlen($group)) {
|
||||||
$group = null;
|
$group = null;
|
||||||
}
|
}
|
||||||
$uri->setQueryParam('group', $group);
|
$uri->replaceQueryParam('group', $group);
|
||||||
|
|
||||||
if ($wipe) {
|
if ($wipe) {
|
||||||
foreach ($this->getColumnMap() as $key => $column) {
|
foreach ($this->getColumnMap() as $key => $column) {
|
||||||
$uri->setQueryParam($key, null);
|
$uri->removeQueryParam($key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,7 +317,7 @@ final class MultimeterSampleController extends MultimeterController {
|
||||||
$value = (array)$value;
|
$value = (array)$value;
|
||||||
|
|
||||||
$uri = clone $this->getRequest()->getRequestURI();
|
$uri = clone $this->getRequest()->getRequestURI();
|
||||||
$uri->setQueryParam($key, implode(',', $value));
|
$uri->replaceQueryParam($key, implode(',', $value));
|
||||||
|
|
||||||
return phutil_tag(
|
return phutil_tag(
|
||||||
'a',
|
'a',
|
||||||
|
|
|
@ -153,7 +153,7 @@ final class PhabricatorNotificationServerRef
|
||||||
|
|
||||||
$instance = PhabricatorEnv::getEnvConfig('cluster.instance');
|
$instance = PhabricatorEnv::getEnvConfig('cluster.instance');
|
||||||
if (strlen($instance)) {
|
if (strlen($instance)) {
|
||||||
$uri->setQueryParam('instance', $instance);
|
$uri->replaceQueryParam('instance', $instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $uri;
|
return $uri;
|
||||||
|
|
|
@ -25,7 +25,7 @@ final class PhabricatorNotificationPanelController
|
||||||
|
|
||||||
$notifications_view = $builder->buildView();
|
$notifications_view = $builder->buildView();
|
||||||
$content = $notifications_view->render();
|
$content = $notifications_view->render();
|
||||||
$clear_uri->setQueryParam(
|
$clear_uri->replaceQueryParam(
|
||||||
'chronoKey',
|
'chronoKey',
|
||||||
head($stories)->getChronologicalKey());
|
head($stories)->getChronologicalKey());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -111,7 +111,7 @@ final class PhabricatorNotificationSearchEngine
|
||||||
->setUser($viewer);
|
->setUser($viewer);
|
||||||
|
|
||||||
$view = $builder->buildView();
|
$view = $builder->buildView();
|
||||||
$clear_uri->setQueryParam(
|
$clear_uri->replaceQueryParam(
|
||||||
'chronoKey',
|
'chronoKey',
|
||||||
head($notifications)->getChronologicalKey());
|
head($notifications)->getChronologicalKey());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -36,7 +36,7 @@ final class PhabricatorOAuthResponse extends AphrontResponse {
|
||||||
$base_uri = $this->getClientURI();
|
$base_uri = $this->getClientURI();
|
||||||
$query_params = $this->buildResponseDict();
|
$query_params = $this->buildResponseDict();
|
||||||
foreach ($query_params as $key => $value) {
|
foreach ($query_params as $key => $value) {
|
||||||
$base_uri->setQueryParam($key, $value);
|
$base_uri->replaceQueryParam($key, $value);
|
||||||
}
|
}
|
||||||
return $base_uri;
|
return $base_uri;
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,8 +256,8 @@ final class PhabricatorOAuthServer extends Phobject {
|
||||||
|
|
||||||
// Any query parameters present in the first URI must be exactly present
|
// Any query parameters present in the first URI must be exactly present
|
||||||
// in the second URI.
|
// in the second URI.
|
||||||
$need_params = $primary_uri->getQueryParams();
|
$need_params = $primary_uri->getQueryParamsAsMap();
|
||||||
$have_params = $secondary_uri->getQueryParams();
|
$have_params = $secondary_uri->getQueryParamsAsMap();
|
||||||
|
|
||||||
foreach ($need_params as $key => $value) {
|
foreach ($need_params as $key => $value) {
|
||||||
if (!array_key_exists($key, $have_params)) {
|
if (!array_key_exists($key, $have_params)) {
|
||||||
|
|
|
@ -306,7 +306,7 @@ final class PhabricatorOAuthServerAuthController
|
||||||
|
|
||||||
foreach ($params as $key => $value) {
|
foreach ($params as $key => $value) {
|
||||||
if (strlen($value)) {
|
if (strlen($value)) {
|
||||||
$full_uri->setQueryParam($key, $value);
|
$full_uri->replaceQueryParam($key, $value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,11 +65,11 @@ final class PhabricatorOwnersDetailController
|
||||||
|
|
||||||
$commit_views = array();
|
$commit_views = array();
|
||||||
|
|
||||||
$commit_uri = id(new PhutilURI('/diffusion/commit/'))
|
$params = array(
|
||||||
->setQueryParams(
|
|
||||||
array(
|
|
||||||
'package' => $package->getPHID(),
|
'package' => $package->getPHID(),
|
||||||
));
|
);
|
||||||
|
|
||||||
|
$commit_uri = new PhutilURI('/diffusion/commit/', $params);
|
||||||
|
|
||||||
$status_concern = DiffusionCommitAuditStatus::CONCERN_RAISED;
|
$status_concern = DiffusionCommitAuditStatus::CONCERN_RAISED;
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,6 @@ final class PhabricatorPeopleApplication extends PhabricatorApplication {
|
||||||
'welcome/(?P<id>[1-9]\d*)/' => 'PhabricatorPeopleWelcomeController',
|
'welcome/(?P<id>[1-9]\d*)/' => 'PhabricatorPeopleWelcomeController',
|
||||||
'create/' => 'PhabricatorPeopleCreateController',
|
'create/' => 'PhabricatorPeopleCreateController',
|
||||||
'new/(?P<type>[^/]+)/' => 'PhabricatorPeopleNewController',
|
'new/(?P<type>[^/]+)/' => 'PhabricatorPeopleNewController',
|
||||||
'ldap/' => 'PhabricatorPeopleLdapController',
|
|
||||||
'editprofile/(?P<id>[1-9]\d*)/' =>
|
'editprofile/(?P<id>[1-9]\d*)/' =>
|
||||||
'PhabricatorPeopleProfileEditController',
|
'PhabricatorPeopleProfileEditController',
|
||||||
'badges/(?P<id>[1-9]\d*)/' =>
|
'badges/(?P<id>[1-9]\d*)/' =>
|
||||||
|
|
|
@ -28,10 +28,6 @@ abstract class PhabricatorPeopleController extends PhabricatorController {
|
||||||
|
|
||||||
if ($viewer->getIsAdmin()) {
|
if ($viewer->getIsAdmin()) {
|
||||||
$nav->addLabel(pht('User Administration'));
|
$nav->addLabel(pht('User Administration'));
|
||||||
if (PhabricatorLDAPAuthProvider::getLDAPProvider()) {
|
|
||||||
$nav->addFilter('ldap', pht('Import from LDAP'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$nav->addFilter('logs', pht('Activity Logs'));
|
$nav->addFilter('logs', pht('Activity Logs'));
|
||||||
$nav->addFilter('invite', pht('Email Invitations'));
|
$nav->addFilter('invite', pht('Email Invitations'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,214 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
final class PhabricatorPeopleLdapController
|
|
||||||
extends PhabricatorPeopleController {
|
|
||||||
|
|
||||||
public function handleRequest(AphrontRequest $request) {
|
|
||||||
$this->requireApplicationCapability(
|
|
||||||
PeopleCreateUsersCapability::CAPABILITY);
|
|
||||||
$admin = $request->getUser();
|
|
||||||
|
|
||||||
$content = array();
|
|
||||||
|
|
||||||
$form = id(new AphrontFormView())
|
|
||||||
->setAction($request->getRequestURI()
|
|
||||||
->alter('search', 'true')->alter('import', null))
|
|
||||||
->setUser($admin)
|
|
||||||
->appendChild(
|
|
||||||
id(new AphrontFormTextControl())
|
|
||||||
->setLabel(pht('LDAP username'))
|
|
||||||
->setName('username'))
|
|
||||||
->appendChild(
|
|
||||||
id(new AphrontFormPasswordControl())
|
|
||||||
->setDisableAutocomplete(true)
|
|
||||||
->setLabel(pht('Password'))
|
|
||||||
->setName('password'))
|
|
||||||
->appendChild(
|
|
||||||
id(new AphrontFormTextControl())
|
|
||||||
->setLabel(pht('LDAP query'))
|
|
||||||
->setCaption(pht('A filter such as %s.', '(objectClass=*)'))
|
|
||||||
->setName('query'))
|
|
||||||
->appendChild(
|
|
||||||
id(new AphrontFormSubmitControl())
|
|
||||||
->setValue(pht('Search')));
|
|
||||||
|
|
||||||
$panel = id(new PHUIObjectBoxView())
|
|
||||||
->setHeaderText(pht('Import LDAP Users'))
|
|
||||||
->setForm($form);
|
|
||||||
|
|
||||||
$crumbs = $this->buildApplicationCrumbs();
|
|
||||||
$crumbs->addTextCrumb(
|
|
||||||
pht('Import LDAP Users'),
|
|
||||||
$this->getApplicationURI('/ldap/'));
|
|
||||||
|
|
||||||
$nav = $this->buildSideNavView();
|
|
||||||
$nav->selectFilter('ldap');
|
|
||||||
$nav->appendChild($content);
|
|
||||||
|
|
||||||
if ($request->getStr('import')) {
|
|
||||||
$nav->appendChild($this->processImportRequest($request));
|
|
||||||
}
|
|
||||||
|
|
||||||
$nav->appendChild($panel);
|
|
||||||
|
|
||||||
if ($request->getStr('search')) {
|
|
||||||
$nav->appendChild($this->processSearchRequest($request));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->newPage()
|
|
||||||
->setTitle(pht('Import LDAP Users'))
|
|
||||||
->setCrumbs($crumbs)
|
|
||||||
->setNavigation($nav);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function processImportRequest($request) {
|
|
||||||
$admin = $request->getUser();
|
|
||||||
$usernames = $request->getArr('usernames');
|
|
||||||
$emails = $request->getArr('email');
|
|
||||||
$names = $request->getArr('name');
|
|
||||||
|
|
||||||
$notice_view = new PHUIInfoView();
|
|
||||||
$notice_view->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
|
|
||||||
$notice_view->setTitle(pht('Import Successful'));
|
|
||||||
$notice_view->setErrors(array(
|
|
||||||
pht('Successfully imported users from LDAP'),
|
|
||||||
));
|
|
||||||
|
|
||||||
$list = new PHUIObjectItemListView();
|
|
||||||
$list->setNoDataString(pht('No users imported?'));
|
|
||||||
|
|
||||||
foreach ($usernames as $username) {
|
|
||||||
$user = new PhabricatorUser();
|
|
||||||
$user->setUsername($username);
|
|
||||||
$user->setRealname($names[$username]);
|
|
||||||
|
|
||||||
$email_obj = id(new PhabricatorUserEmail())
|
|
||||||
->setAddress($emails[$username])
|
|
||||||
->setIsVerified(1);
|
|
||||||
try {
|
|
||||||
id(new PhabricatorUserEditor())
|
|
||||||
->setActor($admin)
|
|
||||||
->createNewUser($user, $email_obj);
|
|
||||||
|
|
||||||
id(new PhabricatorExternalAccount())
|
|
||||||
->setUserPHID($user->getPHID())
|
|
||||||
->setAccountType('ldap')
|
|
||||||
->setAccountDomain('self')
|
|
||||||
->setAccountID($username)
|
|
||||||
->save();
|
|
||||||
|
|
||||||
$header = pht('Successfully added %s', $username);
|
|
||||||
$attribute = null;
|
|
||||||
$color = 'fa-check green';
|
|
||||||
} catch (Exception $ex) {
|
|
||||||
$header = pht('Failed to add %s', $username);
|
|
||||||
$attribute = $ex->getMessage();
|
|
||||||
$color = 'fa-times red';
|
|
||||||
}
|
|
||||||
|
|
||||||
$item = id(new PHUIObjectItemView())
|
|
||||||
->setHeader($header)
|
|
||||||
->addAttribute($attribute)
|
|
||||||
->setStatusIcon($color);
|
|
||||||
|
|
||||||
$list->addItem($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return array(
|
|
||||||
$notice_view,
|
|
||||||
$list,
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private function processSearchRequest($request) {
|
|
||||||
$panel = new PHUIBoxView();
|
|
||||||
$admin = $request->getUser();
|
|
||||||
|
|
||||||
$search = $request->getStr('query');
|
|
||||||
|
|
||||||
$ldap_provider = PhabricatorLDAPAuthProvider::getLDAPProvider();
|
|
||||||
if (!$ldap_provider) {
|
|
||||||
throw new Exception(pht('No LDAP provider enabled!'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$ldap_adapter = $ldap_provider->getAdapter();
|
|
||||||
$ldap_adapter->setLoginUsername($request->getStr('username'));
|
|
||||||
$ldap_adapter->setLoginPassword(
|
|
||||||
new PhutilOpaqueEnvelope($request->getStr('password')));
|
|
||||||
|
|
||||||
// This causes us to connect and bind.
|
|
||||||
// TODO: Clean up this discard mode stuff.
|
|
||||||
DarkConsoleErrorLogPluginAPI::enableDiscardMode();
|
|
||||||
$ldap_adapter->getAccountID();
|
|
||||||
DarkConsoleErrorLogPluginAPI::disableDiscardMode();
|
|
||||||
|
|
||||||
$results = $ldap_adapter->searchLDAP('%Q', $search);
|
|
||||||
|
|
||||||
foreach ($results as $key => $record) {
|
|
||||||
$account_id = $ldap_adapter->readLDAPRecordAccountID($record);
|
|
||||||
if (!$account_id) {
|
|
||||||
unset($results[$key]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$info = array(
|
|
||||||
$account_id,
|
|
||||||
$ldap_adapter->readLDAPRecordEmail($record),
|
|
||||||
$ldap_adapter->readLDAPRecordRealName($record),
|
|
||||||
);
|
|
||||||
$results[$key] = $info;
|
|
||||||
$results[$key][] = $this->renderUserInputs($info);
|
|
||||||
}
|
|
||||||
|
|
||||||
$form = id(new AphrontFormView())
|
|
||||||
->setUser($admin);
|
|
||||||
|
|
||||||
$table = new AphrontTableView($results);
|
|
||||||
$table->setHeaders(
|
|
||||||
array(
|
|
||||||
pht('Username'),
|
|
||||||
pht('Email'),
|
|
||||||
pht('Real Name'),
|
|
||||||
pht('Import?'),
|
|
||||||
));
|
|
||||||
$form->appendChild($table);
|
|
||||||
$form->setAction($request->getRequestURI()
|
|
||||||
->alter('import', 'true')->alter('search', null))
|
|
||||||
->appendChild(
|
|
||||||
id(new AphrontFormSubmitControl())
|
|
||||||
->setValue(pht('Import')));
|
|
||||||
|
|
||||||
$panel->appendChild($form);
|
|
||||||
|
|
||||||
return $panel;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function renderUserInputs($user) {
|
|
||||||
$username = $user[0];
|
|
||||||
return hsprintf(
|
|
||||||
'%s%s%s',
|
|
||||||
phutil_tag(
|
|
||||||
'input',
|
|
||||||
array(
|
|
||||||
'type' => 'checkbox',
|
|
||||||
'name' => 'usernames[]',
|
|
||||||
'value' => $username,
|
|
||||||
)),
|
|
||||||
phutil_tag(
|
|
||||||
'input',
|
|
||||||
array(
|
|
||||||
'type' => 'hidden',
|
|
||||||
'name' => "email[$username]",
|
|
||||||
'value' => $user[1],
|
|
||||||
)),
|
|
||||||
phutil_tag(
|
|
||||||
'input',
|
|
||||||
array(
|
|
||||||
'type' => 'hidden',
|
|
||||||
'name' => "name[$username]",
|
|
||||||
'value' => $user[2],
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -157,13 +157,10 @@ final class PhabricatorPeopleProfilePictureController
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$provider = PhabricatorAuthProvider::getEnabledProviderByKey(
|
$config = $account->getProviderConfig();
|
||||||
$account->getProviderKey());
|
$provider = $config->getProvider();
|
||||||
if ($provider) {
|
|
||||||
$tip = pht('Picture From %s', $provider->getProviderName());
|
$tip = pht('Picture From %s', $provider->getProviderName());
|
||||||
} else {
|
|
||||||
$tip = pht('Picture From External Account');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($file->isTransformableImage()) {
|
if ($file->isTransformableImage()) {
|
||||||
$images[$file->getPHID()] = array(
|
$images[$file->getPHID()] = array(
|
||||||
|
|
|
@ -16,8 +16,10 @@ final class PhabricatorExternalAccount extends PhabricatorUserDAO
|
||||||
protected $accountURI;
|
protected $accountURI;
|
||||||
protected $profileImagePHID;
|
protected $profileImagePHID;
|
||||||
protected $properties = array();
|
protected $properties = array();
|
||||||
|
protected $providerConfigPHID;
|
||||||
|
|
||||||
private $profileImageFile = self::ATTACHABLE;
|
private $profileImageFile = self::ATTACHABLE;
|
||||||
|
private $providerConfig = self::ATTACHABLE;
|
||||||
|
|
||||||
public function getProfileImageFile() {
|
public function getProfileImageFile() {
|
||||||
return $this->assertAttached($this->profileImageFile);
|
return $this->assertAttached($this->profileImageFile);
|
||||||
|
@ -65,13 +67,6 @@ final class PhabricatorExternalAccount extends PhabricatorUserDAO
|
||||||
) + parent::getConfiguration();
|
) + parent::getConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPhabricatorUser() {
|
|
||||||
$tmp_usr = id(new PhabricatorUser())
|
|
||||||
->makeEphemeral()
|
|
||||||
->setPHID($this->getPHID());
|
|
||||||
return $tmp_usr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getProviderKey() {
|
public function getProviderKey() {
|
||||||
return $this->getAccountType().':'.$this->getAccountDomain();
|
return $this->getAccountType().':'.$this->getAccountDomain();
|
||||||
}
|
}
|
||||||
|
@ -93,13 +88,12 @@ final class PhabricatorExternalAccount extends PhabricatorUserDAO
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isUsableForLogin() {
|
public function isUsableForLogin() {
|
||||||
$key = $this->getProviderKey();
|
$config = $this->getProviderConfig();
|
||||||
$provider = PhabricatorAuthProvider::getEnabledProviderByKey($key);
|
if (!$config->getIsEnabled()) {
|
||||||
|
|
||||||
if (!$provider) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$provider = $config->getProvider();
|
||||||
if (!$provider->shouldAllowLogin()) {
|
if (!$provider->shouldAllowLogin()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -125,6 +119,14 @@ final class PhabricatorExternalAccount extends PhabricatorUserDAO
|
||||||
return idx($map, $type, pht('"%s" User', $type));
|
return idx($map, $type, pht('"%s" User', $type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function attachProviderConfig(PhabricatorAuthProviderConfig $config) {
|
||||||
|
$this->providerConfig = $config;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getProviderConfig() {
|
||||||
|
return $this->assertAttached($this->providerConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||||
|
|
|
@ -557,7 +557,7 @@ final class PhabricatorUser
|
||||||
|
|
||||||
public static function describeValidUsername() {
|
public static function describeValidUsername() {
|
||||||
return pht(
|
return pht(
|
||||||
'Usernames must contain only numbers, letters, period, underscore and '.
|
'Usernames must contain only numbers, letters, period, underscore, and '.
|
||||||
'hyphen, and can not end with a period. They must have no more than %d '.
|
'hyphen, and can not end with a period. They must have no more than %d '.
|
||||||
'characters.',
|
'characters.',
|
||||||
new PhutilNumber(self::MAXIMUM_USERNAME_LENGTH));
|
new PhutilNumber(self::MAXIMUM_USERNAME_LENGTH));
|
||||||
|
|
|
@ -83,9 +83,8 @@ final class PhabricatorUserEmail extends PhabricatorUserDAO {
|
||||||
*/
|
*/
|
||||||
public static function describeValidAddresses() {
|
public static function describeValidAddresses() {
|
||||||
return pht(
|
return pht(
|
||||||
"Email addresses should be in the form '%s'. The maximum ".
|
'Email addresses should be in the form "user@domain.com". The maximum '.
|
||||||
"length of an email address is %s character(s).",
|
'length of an email address is %s characters.',
|
||||||
'user@domain.com',
|
|
||||||
new PhutilNumber(self::MAX_ADDRESS_LENGTH));
|
new PhutilNumber(self::MAX_ADDRESS_LENGTH));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,7 @@ final class PholioMockImagesView extends AphrontView {
|
||||||
);
|
);
|
||||||
|
|
||||||
$login_uri = id(new PhutilURI('/login/'))
|
$login_uri = id(new PhutilURI('/login/'))
|
||||||
->setQueryParam('next', (string)$this->getRequestURI());
|
->replaceQueryParam('next', (string)$this->getRequestURI());
|
||||||
|
|
||||||
$config = array(
|
$config = array(
|
||||||
'mockID' => $mock->getID(),
|
'mockID' => $mock->getID(),
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhortuneAddPaymentMethodAction
|
||||||
|
extends PhabricatorSystemAction {
|
||||||
|
|
||||||
|
const TYPECONST = 'phortune.payment-method.add';
|
||||||
|
|
||||||
|
public function getActionConstant() {
|
||||||
|
return self::TYPECONST;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getScoreThreshold() {
|
||||||
|
return 60 / phutil_units('1 hour in seconds');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLimitExplanation() {
|
||||||
|
return pht(
|
||||||
|
'You are making too many attempts to add payment methods in a short '.
|
||||||
|
'period of time.');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -134,13 +134,13 @@ final class PhortuneCartCheckoutController
|
||||||
|
|
||||||
$account_id = $account->getID();
|
$account_id = $account->getID();
|
||||||
|
|
||||||
$payment_method_uri = $this->getApplicationURI("{$account_id}/card/new/");
|
$params = array(
|
||||||
$payment_method_uri = new PhutilURI($payment_method_uri);
|
|
||||||
$payment_method_uri->setQueryParams(
|
|
||||||
array(
|
|
||||||
'merchantID' => $merchant->getID(),
|
'merchantID' => $merchant->getID(),
|
||||||
'cartID' => $cart->getID(),
|
'cartID' => $cart->getID(),
|
||||||
));
|
);
|
||||||
|
|
||||||
|
$payment_method_uri = $this->getApplicationURI("{$account_id}/card/new/");
|
||||||
|
$payment_method_uri = new PhutilURI($payment_method_uri, $params);
|
||||||
|
|
||||||
$form = id(new AphrontFormView())
|
$form = id(new AphrontFormView())
|
||||||
->setUser($viewer)
|
->setUser($viewer)
|
||||||
|
|
|
@ -82,6 +82,15 @@ final class PhortunePaymentMethodCreateController
|
||||||
->setProviderPHID($provider->getProviderConfig()->getPHID())
|
->setProviderPHID($provider->getProviderConfig()->getPHID())
|
||||||
->setStatus(PhortunePaymentMethod::STATUS_ACTIVE);
|
->setStatus(PhortunePaymentMethod::STATUS_ACTIVE);
|
||||||
|
|
||||||
|
// Limit the rate at which you can attempt to add payment methods. This
|
||||||
|
// is intended as a line of defense against using Phortune to validate a
|
||||||
|
// large list of stolen credit card numbers.
|
||||||
|
|
||||||
|
PhabricatorSystemActionEngine::willTakeAction(
|
||||||
|
array($viewer->getPHID()),
|
||||||
|
new PhortuneAddPaymentMethodAction(),
|
||||||
|
1);
|
||||||
|
|
||||||
if (!$errors) {
|
if (!$errors) {
|
||||||
$errors = $this->processClientErrors(
|
$errors = $this->processClientErrors(
|
||||||
$provider,
|
$provider,
|
||||||
|
@ -134,7 +143,7 @@ final class PhortunePaymentMethodCreateController
|
||||||
"cart/{$cart_id}/checkout/?paymentMethodID=".$method->getID());
|
"cart/{$cart_id}/checkout/?paymentMethodID=".$method->getID());
|
||||||
} else if ($subscription_id) {
|
} else if ($subscription_id) {
|
||||||
$next_uri = new PhutilURI($cancel_uri);
|
$next_uri = new PhutilURI($cancel_uri);
|
||||||
$next_uri->setQueryParam('added', true);
|
$next_uri->replaceQueryParam('added', true);
|
||||||
} else {
|
} else {
|
||||||
$account_uri = $this->getApplicationURI($account->getID().'/');
|
$account_uri = $this->getApplicationURI($account->getID().'/');
|
||||||
$next_uri = new PhutilURI($account_uri);
|
$next_uri = new PhutilURI($account_uri);
|
||||||
|
|
|
@ -118,8 +118,8 @@ final class PhortuneSubscriptionEditController extends PhortuneController {
|
||||||
|
|
||||||
$uri = $this->getApplicationURI($account->getID().'/card/new/');
|
$uri = $this->getApplicationURI($account->getID().'/card/new/');
|
||||||
$uri = new PhutilURI($uri);
|
$uri = new PhutilURI($uri);
|
||||||
$uri->setQueryParam('merchantID', $merchant->getID());
|
$uri->replaceQueryParam('merchantID', $merchant->getID());
|
||||||
$uri->setQueryParam('subscriptionID', $subscription->getID());
|
$uri->replaceQueryParam('subscriptionID', $subscription->getID());
|
||||||
|
|
||||||
$add_method_button = phutil_tag(
|
$add_method_button = phutil_tag(
|
||||||
'a',
|
'a',
|
||||||
|
|
|
@ -348,12 +348,14 @@ final class PhortunePayPalPaymentProvider extends PhortunePaymentProvider {
|
||||||
->setRawPayPalQuery('SetExpressCheckout', $params)
|
->setRawPayPalQuery('SetExpressCheckout', $params)
|
||||||
->resolve();
|
->resolve();
|
||||||
|
|
||||||
$uri = new PhutilURI('https://www.sandbox.paypal.com/cgi-bin/webscr');
|
$params = array(
|
||||||
$uri->setQueryParams(
|
|
||||||
array(
|
|
||||||
'cmd' => '_express-checkout',
|
'cmd' => '_express-checkout',
|
||||||
'token' => $result['TOKEN'],
|
'token' => $result['TOKEN'],
|
||||||
));
|
);
|
||||||
|
|
||||||
|
$uri = new PhutilURI(
|
||||||
|
'https://www.sandbox.paypal.com/cgi-bin/webscr',
|
||||||
|
$params);
|
||||||
|
|
||||||
$cart->setMetadataValue('provider.checkoutURI', (string)$uri);
|
$cart->setMetadataValue('provider.checkoutURI', (string)$uri);
|
||||||
$cart->save();
|
$cart->save();
|
||||||
|
|
|
@ -273,8 +273,7 @@ abstract class PhortunePaymentProvider extends Phobject {
|
||||||
$app = PhabricatorApplication::getByClass('PhabricatorPhortuneApplication');
|
$app = PhabricatorApplication::getByClass('PhabricatorPhortuneApplication');
|
||||||
$path = $app->getBaseURI().'provider/'.$id.'/'.$action.'/';
|
$path = $app->getBaseURI().'provider/'.$id.'/'.$action.'/';
|
||||||
|
|
||||||
$uri = new PhutilURI($path);
|
$uri = new PhutilURI($path, $params);
|
||||||
$uri->setQueryParams($params);
|
|
||||||
|
|
||||||
if ($local) {
|
if ($local) {
|
||||||
return $uri;
|
return $uri;
|
||||||
|
|
|
@ -229,9 +229,14 @@ final class PhrictionTransactionEditor
|
||||||
foreach ($xactions as $xaction) {
|
foreach ($xactions as $xaction) {
|
||||||
switch ($xaction->getTransactionType()) {
|
switch ($xaction->getTransactionType()) {
|
||||||
case PhrictionDocumentContentTransaction::TRANSACTIONTYPE:
|
case PhrictionDocumentContentTransaction::TRANSACTIONTYPE:
|
||||||
$uri = id(new PhutilURI('/phriction/diff/'.$object->getID().'/'))
|
$params = array(
|
||||||
->alter('l', $this->getOldContent()->getVersion())
|
'l' => $this->getOldContent()->getVersion(),
|
||||||
->alter('r', $this->getNewContent()->getVersion());
|
'r' => $this->getNewContent()->getVersion(),
|
||||||
|
);
|
||||||
|
|
||||||
|
$path = '/phriction/diff/'.$object->getID().'/';
|
||||||
|
$uri = new PhutilURI($path, $params);
|
||||||
|
|
||||||
$this->contentDiffURI = (string)$uri;
|
$this->contentDiffURI = (string)$uri;
|
||||||
break 2;
|
break 2;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -66,7 +66,7 @@ final class PonderAddAnswerView extends AphrontView {
|
||||||
|
|
||||||
if (!$viewer->isLoggedIn()) {
|
if (!$viewer->isLoggedIn()) {
|
||||||
$login_href = id(new PhutilURI('/auth/start/'))
|
$login_href = id(new PhutilURI('/auth/start/'))
|
||||||
->setQueryParam('next', '/Q'.$question->getID());
|
->replaceQueryParam('next', '/Q'.$question->getID());
|
||||||
$form = id(new PHUIFormLayoutView())
|
$form = id(new PHUIFormLayoutView())
|
||||||
->addClass('login-to-participate')
|
->addClass('login-to-participate')
|
||||||
->appendChild(
|
->appendChild(
|
||||||
|
|
|
@ -284,7 +284,7 @@ final class PhabricatorProjectBoardViewController
|
||||||
$query_key = $saved_query->getQueryKey();
|
$query_key = $saved_query->getQueryKey();
|
||||||
|
|
||||||
$bulk_uri = new PhutilURI("/maniphest/bulk/query/{$query_key}/");
|
$bulk_uri = new PhutilURI("/maniphest/bulk/query/{$query_key}/");
|
||||||
$bulk_uri->setQueryParam('board', $this->id);
|
$bulk_uri->replaceQueryParam('board', $this->id);
|
||||||
|
|
||||||
return id(new AphrontRedirectResponse())
|
return id(new AphrontRedirectResponse())
|
||||||
->setURI($bulk_uri);
|
->setURI($bulk_uri);
|
||||||
|
@ -878,7 +878,7 @@ final class PhabricatorProjectBoardViewController
|
||||||
}
|
}
|
||||||
|
|
||||||
$uri = $this->getURIWithState($uri)
|
$uri = $this->getURIWithState($uri)
|
||||||
->setQueryParam('filter', null);
|
->removeQueryParam('filter');
|
||||||
$item->setHref($uri);
|
$item->setHref($uri);
|
||||||
|
|
||||||
$items[] = $item;
|
$items[] = $item;
|
||||||
|
@ -966,12 +966,12 @@ final class PhabricatorProjectBoardViewController
|
||||||
|
|
||||||
if ($show_hidden) {
|
if ($show_hidden) {
|
||||||
$hidden_uri = $this->getURIWithState()
|
$hidden_uri = $this->getURIWithState()
|
||||||
->setQueryParam('hidden', null);
|
->removeQueryParam('hidden');
|
||||||
$hidden_icon = 'fa-eye-slash';
|
$hidden_icon = 'fa-eye-slash';
|
||||||
$hidden_text = pht('Hide Hidden Columns');
|
$hidden_text = pht('Hide Hidden Columns');
|
||||||
} else {
|
} else {
|
||||||
$hidden_uri = $this->getURIWithState()
|
$hidden_uri = $this->getURIWithState()
|
||||||
->setQueryParam('hidden', 'true');
|
->replaceQueryParam('hidden', 'true');
|
||||||
$hidden_icon = 'fa-eye';
|
$hidden_icon = 'fa-eye';
|
||||||
$hidden_text = pht('Show Hidden Columns');
|
$hidden_text = pht('Show Hidden Columns');
|
||||||
}
|
}
|
||||||
|
@ -999,7 +999,7 @@ final class PhabricatorProjectBoardViewController
|
||||||
->setHref($manage_uri);
|
->setHref($manage_uri);
|
||||||
|
|
||||||
$batch_edit_uri = $request->getRequestURI();
|
$batch_edit_uri = $request->getRequestURI();
|
||||||
$batch_edit_uri->setQueryParam('batch', self::BATCH_EDIT_ALL);
|
$batch_edit_uri->replaceQueryParam('batch', self::BATCH_EDIT_ALL);
|
||||||
$can_batch_edit = PhabricatorPolicyFilter::hasCapability(
|
$can_batch_edit = PhabricatorPolicyFilter::hasCapability(
|
||||||
$viewer,
|
$viewer,
|
||||||
PhabricatorApplication::getByClass('PhabricatorManiphestApplication'),
|
PhabricatorApplication::getByClass('PhabricatorManiphestApplication'),
|
||||||
|
@ -1090,7 +1090,7 @@ final class PhabricatorProjectBoardViewController
|
||||||
}
|
}
|
||||||
|
|
||||||
$batch_edit_uri = $request->getRequestURI();
|
$batch_edit_uri = $request->getRequestURI();
|
||||||
$batch_edit_uri->setQueryParam('batch', $column->getID());
|
$batch_edit_uri->replaceQueryParam('batch', $column->getID());
|
||||||
$can_batch_edit = PhabricatorPolicyFilter::hasCapability(
|
$can_batch_edit = PhabricatorPolicyFilter::hasCapability(
|
||||||
$viewer,
|
$viewer,
|
||||||
PhabricatorApplication::getByClass('PhabricatorManiphestApplication'),
|
PhabricatorApplication::getByClass('PhabricatorManiphestApplication'),
|
||||||
|
@ -1103,7 +1103,7 @@ final class PhabricatorProjectBoardViewController
|
||||||
->setDisabled(!$can_batch_edit);
|
->setDisabled(!$can_batch_edit);
|
||||||
|
|
||||||
$batch_move_uri = $request->getRequestURI();
|
$batch_move_uri = $request->getRequestURI();
|
||||||
$batch_move_uri->setQueryParam('move', $column->getID());
|
$batch_move_uri->replaceQueryParam('move', $column->getID());
|
||||||
$column_items[] = id(new PhabricatorActionView())
|
$column_items[] = id(new PhabricatorActionView())
|
||||||
->setIcon('fa-arrow-right')
|
->setIcon('fa-arrow-right')
|
||||||
->setName(pht('Move Tasks to Column...'))
|
->setName(pht('Move Tasks to Column...'))
|
||||||
|
@ -1111,7 +1111,7 @@ final class PhabricatorProjectBoardViewController
|
||||||
->setWorkflow(true);
|
->setWorkflow(true);
|
||||||
|
|
||||||
$query_uri = $request->getRequestURI();
|
$query_uri = $request->getRequestURI();
|
||||||
$query_uri->setQueryParam('queryColumnID', $column->getID());
|
$query_uri->replaceQueryParam('queryColumnID', $column->getID());
|
||||||
|
|
||||||
$column_items[] = id(new PhabricatorActionView())
|
$column_items[] = id(new PhabricatorActionView())
|
||||||
->setName(pht('View as Query'))
|
->setName(pht('View as Query'))
|
||||||
|
@ -1188,18 +1188,22 @@ final class PhabricatorProjectBoardViewController
|
||||||
$base = new PhutilURI($base);
|
$base = new PhutilURI($base);
|
||||||
|
|
||||||
if ($force || ($this->sortKey != $this->getDefaultSort($project))) {
|
if ($force || ($this->sortKey != $this->getDefaultSort($project))) {
|
||||||
$base->setQueryParam('order', $this->sortKey);
|
$base->replaceQueryParam('order', $this->sortKey);
|
||||||
} else {
|
} else {
|
||||||
$base->setQueryParam('order', null);
|
$base->removeQueryParam('order');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($force || ($this->queryKey != $this->getDefaultFilter($project))) {
|
if ($force || ($this->queryKey != $this->getDefaultFilter($project))) {
|
||||||
$base->setQueryParam('filter', $this->queryKey);
|
$base->replaceQueryParam('filter', $this->queryKey);
|
||||||
} else {
|
} else {
|
||||||
$base->setQueryParam('filter', null);
|
$base->removeQueryParam('filter');
|
||||||
}
|
}
|
||||||
|
|
||||||
$base->setQueryParam('hidden', $this->showHidden ? 'true' : null);
|
if ($this->showHidden) {
|
||||||
|
$base->replaceQueryParam('hidden', 'true');
|
||||||
|
} else {
|
||||||
|
$base->removeQueryParam('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
return $base;
|
return $base;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ final class PhabricatorProjectColumnHideController
|
||||||
$view_uri = $this->getApplicationURI('/board/'.$project_id.'/');
|
$view_uri = $this->getApplicationURI('/board/'.$project_id.'/');
|
||||||
$view_uri = new PhutilURI($view_uri);
|
$view_uri = new PhutilURI($view_uri);
|
||||||
foreach ($request->getPassthroughRequestData() as $key => $value) {
|
foreach ($request->getPassthroughRequestData() as $key => $value) {
|
||||||
$view_uri->setQueryParam($key, $value);
|
$view_uri->replaceQueryParam($key, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($column->isDefaultColumn()) {
|
if ($column->isDefaultColumn()) {
|
||||||
|
|
|
@ -54,7 +54,7 @@ final class PhabricatorProjectDefaultController
|
||||||
$view_uri = $this->getApplicationURI("board/{$id}/");
|
$view_uri = $this->getApplicationURI("board/{$id}/");
|
||||||
$view_uri = new PhutilURI($view_uri);
|
$view_uri = new PhutilURI($view_uri);
|
||||||
foreach ($request->getPassthroughRequestData() as $key => $value) {
|
foreach ($request->getPassthroughRequestData() as $key => $value) {
|
||||||
$view_uri->setQueryParam($key, $value);
|
$view_uri->replaceQueryParam($key, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->isFormPost()) {
|
if ($request->isFormPost()) {
|
||||||
|
|
|
@ -96,7 +96,7 @@ final class ReleephRequestDifferentialCreateController
|
||||||
private function buildReleephRequestURI(ReleephBranch $branch) {
|
private function buildReleephRequestURI(ReleephBranch $branch) {
|
||||||
$uri = $branch->getURI('request/');
|
$uri = $branch->getURI('request/');
|
||||||
return id(new PhutilURI($uri))
|
return id(new PhutilURI($uri))
|
||||||
->setQueryParam('D', $this->revision->getID());
|
->replaceQueryParam('D', $this->revision->getID());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -820,8 +820,6 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
||||||
return $uri;
|
return $uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
$uri = new PhutilURI($uri);
|
|
||||||
|
|
||||||
if (isset($params['lint'])) {
|
if (isset($params['lint'])) {
|
||||||
$params['params'] = idx($params, 'params', array()) + array(
|
$params['params'] = idx($params, 'params', array()) + array(
|
||||||
'lint' => $params['lint'],
|
'lint' => $params['lint'],
|
||||||
|
@ -830,11 +828,7 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
||||||
|
|
||||||
$query = idx($params, 'params', array()) + $query;
|
$query = idx($params, 'params', array()) + $query;
|
||||||
|
|
||||||
if ($query) {
|
return new PhutilURI($uri, $query);
|
||||||
$uri->setQueryParams($query);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $uri;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateURIIndex() {
|
public function updateURIIndex() {
|
||||||
|
|
|
@ -905,7 +905,7 @@ final class PhabricatorApplicationSearchController
|
||||||
$engine = $this->getSearchEngine();
|
$engine = $this->getSearchEngine();
|
||||||
$nux_uri = $engine->getQueryBaseURI();
|
$nux_uri = $engine->getQueryBaseURI();
|
||||||
$nux_uri = id(new PhutilURI($nux_uri))
|
$nux_uri = id(new PhutilURI($nux_uri))
|
||||||
->setQueryParam('nux', true);
|
->replaceQueryParam('nux', true);
|
||||||
|
|
||||||
$actions[] = id(new PhabricatorActionView())
|
$actions[] = id(new PhabricatorActionView())
|
||||||
->setIcon('fa-user-plus')
|
->setIcon('fa-user-plus')
|
||||||
|
@ -915,7 +915,7 @@ final class PhabricatorApplicationSearchController
|
||||||
|
|
||||||
if ($is_dev) {
|
if ($is_dev) {
|
||||||
$overheated_uri = $this->getRequest()->getRequestURI()
|
$overheated_uri = $this->getRequest()->getRequestURI()
|
||||||
->setQueryParam('overheated', true);
|
->replaceQueryParam('overheated', true);
|
||||||
|
|
||||||
$actions[] = id(new PhabricatorActionView())
|
$actions[] = id(new PhabricatorActionView())
|
||||||
->setIcon('fa-fire')
|
->setIcon('fa-fire')
|
||||||
|
|
|
@ -14,7 +14,7 @@ final class PhabricatorSearchWorker extends PhabricatorWorker {
|
||||||
'parameters' => $parameters,
|
'parameters' => $parameters,
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'priority' => parent::PRIORITY_IMPORT,
|
'priority' => parent::PRIORITY_INDEX,
|
||||||
'objectPHID' => $phid,
|
'objectPHID' => $phid,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue