Add support for ${path} in auth.switch_account_url

Provide client-side interpolation of ${path} in this string when
generating the "Switch account" link.

This change also updates the GWT version of this link to simply
remove any ${path} elements. There doesn't seem to be a good way
to ensure the path would be updated as the location changes.

Bug: Issue 4884
Change-Id: I2070208b540efb3f9fb527e23dbbd220fc2d2dce
This commit is contained in:
Logan Hanks
2017-03-16 14:12:23 -07:00
parent ab2fa7cc39
commit 71d1ffd580
4 changed files with 89 additions and 10 deletions

View File

@@ -397,8 +397,14 @@ the currently active account. This is disabled by default except when
the "Switch Account" link is displayed next to "Sign Out". the "Switch Account" link is displayed next to "Sign Out".
+ +
When `auth.type` does not normally enable this URL administrators may When `auth.type` does not normally enable this URL administrators may
set this to `login/` or `$canonicalWebUrl/login`, allowing users to set this to `login/`, allowing users to begin a new web session. This value
begin a new web session. is used as an href in PolyGerrit and the GWT UI, so absolute URLs like
`https://someotherhost/login` work as well.
+
If a ${path} parameter is included, then PolyGerrit will substitute the
currently viewed path in the link. Be aware that this path will include
a leading slash, so a value like this might be appropriate: `/login${path}`.
Note: in the GWT UI this substitution for ${path} is *always* `/`.
[[auth.cookiePath]]auth.cookiePath:: [[auth.cookiePath]]auth.cookiePath::
+ +

View File

@@ -52,8 +52,9 @@ public class UserPopupPanel extends PopupPanel {
userEmail.setText(account.email()); userEmail.setText(account.email());
} }
if (showSettingsLink) { if (showSettingsLink) {
if (Gerrit.info().auth().switchAccountUrl() != null) { String switchAccountUrl = Gerrit.info().auth().switchAccountUrl();
switchAccount.setHref(Gerrit.info().auth().switchAccountUrl()); if (switchAccountUrl != null) {
switchAccount.setHref(switchAccountUrl.replace("${path}", "/"));
} else if (Gerrit.info().auth().isDev() || Gerrit.info().auth().isOpenId()) { } else if (Gerrit.info().auth().isDev() || Gerrit.info().auth().isOpenId()) {
switchAccount.setHref(Gerrit.selfRedirect("/login")); switchAccount.setHref(Gerrit.selfRedirect("/login"));
} else { } else {

View File

@@ -14,37 +14,75 @@
(function() { (function() {
'use strict'; 'use strict';
var INTERPOLATE_URL_PATTERN = /\$\{([\w]+)\}/g;
Polymer({ Polymer({
is: 'gr-account-dropdown', is: 'gr-account-dropdown',
properties: { properties: {
account: Object, account: Object,
_hasAvatars: Boolean,
links: { links: {
type: Array, type: Array,
value: [ computed: '_getLinks(_switchAccountUrl)',
{name: 'Settings', url: '/settings'},
{name: 'Switch account', url: '/switch-account'},
{name: 'Sign out', url: '/logout'},
],
}, },
topContent: { topContent: {
type: Array, type: Array,
computed: '_getTopContent(account)', computed: '_getTopContent(account)',
}, },
_path: {
type: String,
value: '/',
},
_hasAvatars: Boolean,
_switchAccountUrl: String,
}, },
attached: function() { attached: function() {
this._handleLocationChange();
this.listen(window, 'location-change', '_handleLocationChange');
this.$.restAPI.getConfig().then(function(cfg) { this.$.restAPI.getConfig().then(function(cfg) {
if (cfg && cfg.auth && cfg.auth.switch_account_url) {
this._switchAccountUrl = cfg.auth.switch_account_url;
} else {
this._switchAccountUrl = null;
}
this._hasAvatars = !!(cfg && cfg.plugin && cfg.plugin.has_avatars); this._hasAvatars = !!(cfg && cfg.plugin && cfg.plugin.has_avatars);
}.bind(this)); }.bind(this));
}, },
detached: function() {
this.unlisten(window, 'location-change', '_handleLocationChange');
},
_getLinks: function(switchAccountUrl) {
var links = [{name: 'Settings', url: '/settings'}];
if (switchAccountUrl) {
var replacements = {path: this._path};
var url = this._interpolateUrl(switchAccountUrl, replacements);
links.push({name: 'Switch account', url: url});
}
links.push({name: 'Sign out', url: '/logout'});
return links;
},
_getTopContent: function(account) { _getTopContent: function(account) {
return [ return [
{text: account.name, bold: true}, {text: account.name, bold: true},
{text: account.email}, {text: account.email},
]; ];
}, },
_handleLocationChange: function() {
this._path =
window.location.pathname +
window.location.search +
window.location.hash;
},
_interpolateUrl: function(url, replacements) {
return url.replace(INTERPOLATE_URL_PATTERN, function(match, p1) {
return replacements[p1] || '';
});
},
}); });
})(); })();

View File

@@ -46,5 +46,39 @@ limitations under the License.
assert.deepEqual(element.topContent, assert.deepEqual(element.topContent,
[{text: 'John Doe', bold: true}, {text: 'john@doe.com'}]); [{text: 'John Doe', bold: true}, {text: 'john@doe.com'}]);
}); });
test('switch account', function() {
// No switch account link.
assert.equal(element._getLinks(null).length, 2);
// Unparameterized switch account link.
var links = element._getLinks('/switch-account');
assert.equal(links.length, 3);
assert.deepEqual(links[1],
{name: 'Switch account', url: '/switch-account'});
// Parameterized switch account link.
element._path = '/c/123';
links = element._getLinks('/switch-account${path}');
assert.equal(links.length, 3);
assert.deepEqual(links[1],
{name: 'Switch account', url: '/switch-account/c/123'});
});
test('_interpolateUrl', function() {
var replacements = {
'foo': 'bar',
'test': 'TEST',
};
var interpolate = function(url) {
return element._interpolateUrl(url, replacements);
};
assert.equal(interpolate('test'), 'test');
assert.equal(interpolate('${test}'), 'TEST');
assert.equal(
interpolate('${}, ${test}, ${TEST}, ${foo}'),
'${}, TEST, , bar');
});
}); });
</script> </script>