Merge "Allow admins to configure URL aliases"

This commit is contained in:
Edwin Kempin
2015-08-05 07:35:03 +00:00
committed by Gerrit Code Review
8 changed files with 140 additions and 1 deletions

View File

@@ -3767,6 +3767,46 @@ on the server. One or more groups can be set.
If no groups are added, any user will be allowed to execute
'upload-pack' on the server.
[[urlAlias]]
=== Section urlAlias
URL aliases define regular expressions for URL tokens that are mapped
to target URL tokens.
Each URL alias must be specified in its own subsection. The subsection
name should be a descriptive name. It must be unique, but is not
interpreted in any way.
The URL aliases are applied in no particular order. The first matching
URL alias is used and further matches are ignored.
URL aliases can be used to map plugin screens into the Gerrit URL
namespace, or to replace Gerrit screens by plugin screens.
Example:
----
[urlAlias "MyPluginScreen"]
match = /myscreen/(.*)
token = /x/myplugin/myscreen/$1
[urlAlias "MyChangeScreen"]
match = /c/(.*)
token = /x/myplugin/c/$1
----
[[urlAlias.match]]urlAlias.match::
+
A regular expression for a URL token.
+
The matched URL token is replaced by `urlAlias.token`.
[[urlAlias.token]]urlAlias.token::
+
The target URL token.
+
It can contain placeholders for the groups matched by the
`urlAlias.match` regular expression: `$1` for the first matched group,
`$2` for the second matched group, etc.
[[submodule]]
=== Section submodule

View File

@@ -1788,6 +1788,10 @@ public class MyPlugin extends PluginEntryPoint {
}
----
By defining an link:config-gerrit.html#urlAlias[urlAlias] Gerrit
administrators can map plugin screens into the Gerrit URL namespace or
even replace Gerrit screens by plugin screens.
[[settings-screen]]
== Plugin Settings Screen

View File

@@ -1352,6 +1352,11 @@ entity. Not set if SSHD is disabled.
Information about the configuration from the
link:config-gerrit.html#suggest[suggest] section as link:#suggest-info[
SuggestInfo] entity.
|`url_aliases` |optional|
A map of URL aliases, where a regular expression for an URL token is
mapped to a target URL token. The target URL token can contain
placeholders for the groups matched by the regular expression: `$1` for
the first matched group, `$2` for the second matched group, etc.
|`user` ||
Information about the configuration from the
link:config-gerrit.html#user[user] section as link:#user-config-info[

View File

@@ -96,6 +96,8 @@ import com.google.gerrit.reviewdb.client.Project;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.RunAsyncCallback;
import com.google.gwt.http.client.URL;
import com.google.gwt.regexp.shared.MatchResult;
import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.user.client.Window;
import com.google.gwtorm.client.KeyUtil;
@@ -204,7 +206,9 @@ public class Dispatcher {
}
}
private static void select(final String token) {
private static void select(String token) {
token = Gerrit.getUrlAliasMatcher().replace(token);
if (matchPrefix(QUERY, token)) {
query(token);

View File

@@ -112,6 +112,7 @@ public class Gerrit implements EntryPoint {
private static String myHost;
private static ServerInfo myServerInfo;
private static AccountPreferencesInfo myPrefs;
private static UrlAliasMatcher urlAliasMatcher;
private static boolean hasDocumentation;
private static String docUrl;
private static HostPageData.Theme myTheme;
@@ -294,6 +295,10 @@ public class Gerrit implements EntryPoint {
return myServerInfo;
}
public static UrlAliasMatcher getUrlAliasMatcher() {
return urlAliasMatcher;
}
/** Site theme information (site specific colors)/ */
public static HostPageData.Theme getTheme() {
return myTheme;
@@ -446,6 +451,7 @@ public class Gerrit implements EntryPoint {
@Override
public void onSuccess(ServerInfo info) {
myServerInfo = info;
urlAliasMatcher = new UrlAliasMatcher(info.urlAliases());
String du = info.gerrit().docUrl();
if (du != null && !du.isEmpty()) {
hasDocumentation = true;

View File

@@ -0,0 +1,43 @@
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.client;
import com.google.gwt.regexp.shared.RegExp;
import java.util.HashMap;
import java.util.Map;
public class UrlAliasMatcher {
private final Map<RegExp, String> globalUrlAliases;
UrlAliasMatcher(Map<String, String> globalUrlAliases) {
this.globalUrlAliases = new HashMap<>();
if (globalUrlAliases != null) {
for (Map.Entry<String, String> e : globalUrlAliases.entrySet()) {
this.globalUrlAliases.put(RegExp.compile(e.getKey()), e.getValue());
}
}
}
public String replace(String token) {
for (Map.Entry<RegExp, String> e : globalUrlAliases.entrySet()) {
RegExp pat = e.getKey();
if (pat.exec(token) != null) {
return pat.replace(token, e.getValue());
}
}
return token;
}
}

View File

@@ -14,8 +14,15 @@
package com.google.gerrit.client.config;
import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.client.rpc.NativeString;
import com.google.gerrit.client.rpc.Natives;
import com.google.gwt.core.client.JavaScriptObject;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class ServerInfo extends JavaScriptObject {
public final native AuthInfo auth() /*-{ return this.auth; }-*/;
public final native ChangeConfigInfo change() /*-{ return this.change; }-*/;
@@ -29,6 +36,18 @@ public class ServerInfo extends JavaScriptObject {
public final native UserConfigInfo user() /*-{ return this.user; }-*/;
public final native ReceiveInfo receive() /*-{ return this.receive; }-*/;
public final Map<String, String> urlAliases() {
Map<String, String> urlAliases = new HashMap<>();
for (String k : Natives.keys(_urlAliases())) {
urlAliases.put(k, urlAliasToken(k));
}
return urlAliases;
}
public final native String urlAliasToken(String n) /*-{ return this.url_aliases[n]; }-*/;
private final native NativeMap<NativeString> _urlAliases() /*-{ return this.url_aliases; }-*/;
public final boolean hasContactStore() {
return contactStore() != null;
}

View File

@@ -47,6 +47,10 @@ import java.util.Map;
import java.util.concurrent.TimeUnit;
public class GetServerInfo implements RestReadView<ConfigResource> {
private final static String URL_ALIAS = "urlAlias";
private final static String KEY_MATCH = "match";
private final static String KEY_TOKEN = "token";
private final Config config;
private final AuthConfig authConfig;
private final Realm realm;
@@ -102,6 +106,10 @@ public class GetServerInfo implements RestReadView<ConfigResource> {
info.plugin = getPluginInfo();
info.sshd = getSshdInfo(config);
info.suggest = getSuggestInfo(config);
Map<String, String> urlAliases = getUrlAliasesInfo(config);
info.urlAliases = !urlAliases.isEmpty() ? urlAliases : null;
info.user = getUserInfo(anonymousCowardName);
info.receive = getReceiveInfo(config);
return info;
@@ -267,6 +275,15 @@ public class GetServerInfo implements RestReadView<ConfigResource> {
return info;
}
private Map<String, String> getUrlAliasesInfo(Config cfg) {
Map<String, String> urlAliases = new HashMap<>();
for (String subsection : cfg.getSubsections(URL_ALIAS)) {
urlAliases.put(cfg.getString(URL_ALIAS, subsection, KEY_MATCH),
cfg.getString(URL_ALIAS, subsection, KEY_TOKEN));
}
return urlAliases;
}
private SshdInfo getSshdInfo(Config cfg) {
String[] addr = cfg.getStringList("sshd", null, "listenAddress");
if (addr.length == 1 && isOff(addr[0])) {
@@ -313,6 +330,7 @@ public class GetServerInfo implements RestReadView<ConfigResource> {
public PluginConfigInfo plugin;
public SshdInfo sshd;
public SuggestInfo suggest;
public Map<String, String> urlAliases;
public UserConfigInfo user;
public ReceiveInfo receive;
}