diff --git a/resources/celerity/map.php b/resources/celerity/map.php --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -8,7 +8,7 @@ return array( 'names' => array( 'core.pkg.css' => '8378907a', - 'core.pkg.js' => 'c60f35d8', + 'core.pkg.js' => '5058979d', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', 'differential.pkg.js' => '6223dd9d', @@ -227,14 +227,14 @@ 'rsrc/externals/javelin/lib/JSON.js' => '69adf288', 'rsrc/externals/javelin/lib/Leader.js' => '331b1611', 'rsrc/externals/javelin/lib/Mask.js' => '8a41885b', - 'rsrc/externals/javelin/lib/Quicksand.js' => '4cebc641', + 'rsrc/externals/javelin/lib/Quicksand.js' => '6b8ef10b', 'rsrc/externals/javelin/lib/Request.js' => '94b750d2', 'rsrc/externals/javelin/lib/Resource.js' => '44959b73', 'rsrc/externals/javelin/lib/Routable.js' => 'b3e7d692', 'rsrc/externals/javelin/lib/Router.js' => '29274e2b', 'rsrc/externals/javelin/lib/Scrollbar.js' => '087e919c', 'rsrc/externals/javelin/lib/Sound.js' => '949c0fe5', - 'rsrc/externals/javelin/lib/URI.js' => '6eff08aa', + 'rsrc/externals/javelin/lib/URI.js' => 'c989ade3', 'rsrc/externals/javelin/lib/Vector.js' => '2caa8fb8', 'rsrc/externals/javelin/lib/WebSocket.js' => 'e292eaf4', 'rsrc/externals/javelin/lib/Workflow.js' => '5b2e3e2b', @@ -487,7 +487,7 @@ 'rsrc/js/core/behavior-oncopy.js' => '2926fff2', 'rsrc/js/core/behavior-phabricator-nav.js' => '56a1ca03', 'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => 'eeaa9e5a', - 'rsrc/js/core/behavior-refresh-csrf.js' => '7814b593', + 'rsrc/js/core/behavior-refresh-csrf.js' => 'ab2f381b', 'rsrc/js/core/behavior-remarkup-preview.js' => 'f7379f45', 'rsrc/js/core/behavior-reorder-applications.js' => '76b9fc3e', 'rsrc/js/core/behavior-reveal-content.js' => '60821bc7', @@ -657,7 +657,7 @@ 'javelin-behavior-project-create' => '065227cc', 'javelin-behavior-quicksand-blacklist' => '7927a7d3', 'javelin-behavior-recurring-edit' => '5f1c4d5f', - 'javelin-behavior-refresh-csrf' => '7814b593', + 'javelin-behavior-refresh-csrf' => 'ab2f381b', 'javelin-behavior-releeph-preview-branch' => 'b2b4fbaf', 'javelin-behavior-releeph-request-state-change' => 'a0b57eb8', 'javelin-behavior-releeph-request-typeahead' => 'de2e896f', @@ -690,7 +690,7 @@ 'javelin-leader' => '331b1611', 'javelin-magical-init' => '3010e992', 'javelin-mask' => '8a41885b', - 'javelin-quicksand' => '4cebc641', + 'javelin-quicksand' => '6b8ef10b', 'javelin-reactor' => '2b8de964', 'javelin-reactor-dom' => 'c90a04fc', 'javelin-reactor-node-calmer' => '76f4ebed', @@ -710,7 +710,7 @@ 'javelin-typeahead-preloaded-source' => '54f314a0', 'javelin-typeahead-source' => '2818f5ce', 'javelin-typeahead-static-source' => '6c0e62fa', - 'javelin-uri' => '6eff08aa', + 'javelin-uri' => 'c989ade3', 'javelin-util' => '93cc50d6', 'javelin-vector' => '2caa8fb8', 'javelin-view' => '0f764c35', @@ -1130,9 +1130,6 @@ 'javelin-request', 'javelin-util', ), - '4cebc641' => array( - 'javelin-install', - ), '4e3e79a6' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1302,6 +1299,9 @@ '69adf288' => array( 'javelin-install', ), + '6b8ef10b' => array( + 'javelin-install', + ), '6c0e62fa' => array( 'javelin-install', 'javelin-typeahead-source', @@ -1329,11 +1329,6 @@ 'phabricator-drag-and-drop-file-upload', 'phabricator-textareautils', ), - '6eff08aa' => array( - 'javelin-install', - 'javelin-util', - 'javelin-stratcom', - ), '70baed2f' => array( 'javelin-install', 'javelin-dom', @@ -1368,14 +1363,6 @@ 'javelin-reactor', 'javelin-util', ), - '7814b593' => array( - 'javelin-request', - 'javelin-behavior', - 'javelin-dom', - 'javelin-router', - 'javelin-util', - 'phabricator-busy', - ), '782ab6e7' => array( 'javelin-behavior', 'javelin-dom', @@ -1642,6 +1629,14 @@ 'javelin-util', 'phabricator-prefab', ), + 'ab2f381b' => array( + 'javelin-request', + 'javelin-behavior', + 'javelin-dom', + 'javelin-router', + 'javelin-util', + 'phabricator-busy', + ), 'ad10aeac' => array( 'javelin-install', 'javelin-util', @@ -1803,6 +1798,11 @@ 'javelin-install', 'javelin-util', ), + 'c989ade3' => array( + 'javelin-install', + 'javelin-util', + 'javelin-stratcom', + ), 'ca3f91eb' => array( 'javelin-behavior', 'javelin-dom', diff --git a/src/aphront/AphrontRequest.php b/src/aphront/AphrontRequest.php --- a/src/aphront/AphrontRequest.php +++ b/src/aphront/AphrontRequest.php @@ -236,6 +236,10 @@ return 'X-Phabricator-Csrf'; } + public static function getViaHeaderName() { + return 'X-Phabricator-Via'; + } + public function validateCSRF() { $token_name = self::getCSRFTokenName(); $token = $this->getStr($token_name); diff --git a/src/applications/auth/controller/PhabricatorAuthStartController.php b/src/applications/auth/controller/PhabricatorAuthStartController.php --- a/src/applications/auth/controller/PhabricatorAuthStartController.php +++ b/src/applications/auth/controller/PhabricatorAuthStartController.php @@ -214,14 +214,24 @@ $request->getRequestURI()); } - $dialog = new AphrontDialogView(); - $dialog->setUser($viewer); - $dialog->setTitle(pht('Login Required')); - $dialog->appendChild(pht('You must login to continue.')); - $dialog->addSubmitButton(pht('Login')); - $dialog->addCancelButton('/'); - - return id(new AphrontDialogResponse())->setDialog($dialog); + // Often, users end up here by clicking a disabled action link in the UI + // (for example, they might click "Edit Blocking Tasks" on a Maniphest + // task page). After they log in we want to send them back to that main + // object page if we can, since it's confusing to end up on a standalone + // page with only a dialog (particularly if that dialog is another error, + // like a policy exception). + + $via_header = AphrontRequest::getViaHeaderName(); + $via_uri = AphrontRequest::getHTTPHeader($via_header); + if (strlen($via_uri)) { + PhabricatorCookies::setNextURICookie($request, $via_uri, $force = true); + } + + return $this->newDialog() + ->setTitle(pht('Login Required')) + ->appendParagraph(pht('You must login to continue.')) + ->addSubmitButton(pht('Login')) + ->addCancelButton('/'); } diff --git a/src/view/page/PhabricatorStandardPageView.php b/src/view/page/PhabricatorStandardPageView.php --- a/src/view/page/PhabricatorStandardPageView.php +++ b/src/view/page/PhabricatorStandardPageView.php @@ -261,7 +261,8 @@ 'refresh-csrf', array( 'tokenName' => AphrontRequest::getCSRFTokenName(), - 'header' => AphrontRequest::getCSRFHeaderName(), + 'header' => AphrontRequest::getCSRFHeaderName(), + 'viaHeader' => AphrontRequest::getViaHeaderName(), 'current' => $current_token, )); diff --git a/webroot/rsrc/externals/javelin/lib/Quicksand.js b/webroot/rsrc/externals/javelin/lib/Quicksand.js --- a/webroot/rsrc/externals/javelin/lib/Quicksand.js +++ b/webroot/rsrc/externals/javelin/lib/Quicksand.js @@ -50,7 +50,7 @@ JX.Stratcom.listen('history:change', null, self._onchange); self._started = true; - var path = self._getRelativeURI(window.location); + var path = JX.$U(window.location).getRelativeURI(); self._id = window.history.state || 0; var id = self._id; self._onpage = id; @@ -157,7 +157,7 @@ } // Set up the new state and fire a request to fetch the page data. - var path = self._getRelativeURI(uri); + var path = JX.$U(uri).getRelativeURI(); var id = ++self._id; self._history.push({path: path, id: id}); @@ -297,18 +297,6 @@ /** - * Get just the relative part of a URI, for History operations. - */ - _getRelativeURI: function(uri) { - return JX.$U(uri) - .setProtocol(null) - .setPort(null) - .setDomain(null) - .toString(); - }, - - - /** * Set a list of regular expressions which blacklist URIs as not navigable * via Quicksand. * diff --git a/webroot/rsrc/externals/javelin/lib/URI.js b/webroot/rsrc/externals/javelin/lib/URI.js --- a/webroot/rsrc/externals/javelin/lib/URI.js +++ b/webroot/rsrc/externals/javelin/lib/URI.js @@ -178,6 +178,14 @@ return this._domain; }, + getRelativeURI: function() { + return JX.$U(this.toString()) + .setProtocol(null) + .setPort(null) + .setDomain(null) + .toString(); + }, + toString : function() { if (__DEV__) { if (this.getPath() && this.getPath().charAt(0) != '/') { diff --git a/webroot/rsrc/js/core/behavior-refresh-csrf.js b/webroot/rsrc/js/core/behavior-refresh-csrf.js --- a/webroot/rsrc/js/core/behavior-refresh-csrf.js +++ b/webroot/rsrc/js/core/behavior-refresh-csrf.js @@ -50,7 +50,12 @@ // Additionally, add the CSRF token as an HTTP header to every AJAX request. JX.Request.listen('open', function(r) { - r.getTransport().setRequestHeader(config.header, current_token); + var via = JX.$U(window.location).getRelativeURI(); + + var xport = r.getTransport(); + + xport.setRequestHeader(config.header, current_token); + xport.setRequestHeader(config.viaHeader, via); }); // Does this type of routable show the "Busy" spinner?