Merge "Add support for user-specific URL aliases"
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt
index 24f34af..26072e3 100644
--- a/Documentation/dev-plugins.txt
+++ b/Documentation/dev-plugins.txt
@@ -1792,6 +1792,11 @@
administrators can map plugin screens into the Gerrit URL namespace or
even replace Gerrit screens by plugin screens.
+Plugins may also programatically add URL aliases in the preferences of
+of a user. This way certain screens can be replaced for certain users.
+E.g. the plugin may offer a user preferences setting for choosing a
+screen that then sets/unsets a URL alias for the user.
+
[[settings-screen]]
== Plugin Settings Screen
diff --git a/Documentation/rest-api-accounts.txt b/Documentation/rest-api-accounts.txt
index 096cf04..8268e6c 100644
--- a/Documentation/rest-api-accounts.txt
+++ b/Documentation/rest-api-accounts.txt
@@ -1638,6 +1638,9 @@
|`my` ||
The menu items of the `MY` top menu as a list of
link:rest-api-config.html#top-menu-item-info[TopMenuItemInfo] entities.
+|`url_aliases` |optional|
+A map of URL path pairs, where the first URL path is an alias for the
+second URL path.
|============================================
[[preferences-input]]
@@ -1684,6 +1687,9 @@
|`my` |optional|
The menu items of the `MY` top menu as a list of
link:rest-api-config.html#top-menu-item-info[TopMenuItemInfo] entities.
+|`url_aliases` |optional|
+A map of URL path pairs, where the first URL path is an alias for the
+second URL path.
|============================================
[[query-limit-info]]
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/AccountPreferencesInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/AccountPreferencesInfo.java
index 4482fd0..808726e 100644
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/AccountPreferencesInfo.java
+++ b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/AccountPreferencesInfo.java
@@ -14,6 +14,9 @@
package com.google.gerrit.client.info;
+import com.google.gerrit.client.rpc.NativeMap;
+import com.google.gerrit.client.rpc.NativeString;
+import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DateFormat;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DiffView;
@@ -24,7 +27,9 @@
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
public class AccountPreferencesInfo extends JavaScriptObject {
public static AccountPreferencesInfo create() {
@@ -197,6 +202,26 @@
final native void initMy() /*-{ this.my = []; }-*/;
final native void addMy(TopMenuItem m) /*-{ this.my.push(m); }-*/;
+ 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;
+ }
+
+ private final native String urlAliasToken(String m) /*-{ return this.url_aliases[m]; }-*/;
+ private final native NativeMap<NativeString> _urlAliases() /*-{ return this.url_aliases; }-*/;
+
+ public final void setUrlAliases(Map<String, String> urlAliases) {
+ initUrlAliases();
+ for (Map.Entry<String, String> e : urlAliases.entrySet()) {
+ putUrlAlias(e.getKey(), e.getValue());
+ }
+ }
+ private final native void putUrlAlias(String m, String t) /*-{ this.url_aliases[m] = t; }-*/;
+ private final native void initUrlAliases() /*-{ this.url_aliases = {}; }-*/;
+
protected AccountPreferencesInfo() {
}
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
index fb85f62..d52f2fc 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
@@ -391,6 +391,7 @@
myAccount = AccountInfo.create(0, null, null, null);
myAccountDiffPref = null;
myPrefs = AccountPreferencesInfo.createDefault();
+ urlAliasMatcher.clearUserAliases();
xGerritAuth = null;
refreshMenuBar();
@@ -880,6 +881,7 @@
siteFooter.setVisible(myPrefs.showSiteHeader());
}
FormatUtil.setPreferences(myPrefs);
+ urlAliasMatcher.updateUserAliases(myPrefs.urlAliases());
}
private static void getDocIndex(final AsyncCallback<DocInfo> cb) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/UrlAliasMatcher.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/UrlAliasMatcher.java
index adaee55..f4ba870 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/UrlAliasMatcher.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/UrlAliasMatcher.java
@@ -20,18 +20,41 @@
import java.util.Map;
public class UrlAliasMatcher {
+ private final Map<RegExp, String> userUrlAliases;
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());
+ this.globalUrlAliases = compile(globalUrlAliases);
+ this.userUrlAliases = new HashMap<>();
+ }
+
+ private static Map<RegExp, String> compile(Map<String, String> urlAliases) {
+ Map<RegExp, String> compiledUrlAliases = new HashMap<>();
+ if (urlAliases != null) {
+ for (Map.Entry<String, String> e : urlAliases.entrySet()) {
+ compiledUrlAliases.put(RegExp.compile(e.getKey()), e.getValue());
}
}
+ return compiledUrlAliases;
+ }
+
+ void clearUserAliases() {
+ this.userUrlAliases.clear();
+ }
+
+ void updateUserAliases(Map<String, String> userUrlAliases) {
+ clearUserAliases();
+ this.userUrlAliases.putAll(compile(userUrlAliases));
}
public String replace(String token) {
+ for (Map.Entry<RegExp, String> e : userUrlAliases.entrySet()) {
+ RegExp pat = e.getKey();
+ if (pat.exec(token) != null) {
+ return pat.replace(token, e.getValue());
+ }
+ }
+
for (Map.Entry<RegExp, String> e : globalUrlAliases.entrySet()) {
RegExp pat = e.getKey();
if (pat.exec(token) != null) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GetPreferences.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GetPreferences.java
index 28c3be6..1967a2b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GetPreferences.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GetPreferences.java
@@ -44,7 +44,9 @@
import java.io.IOException;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
@Singleton
public class GetPreferences implements RestReadView<AccountResource> {
@@ -54,6 +56,9 @@
public static final String KEY_URL = "url";
public static final String KEY_TARGET = "target";
public static final String KEY_ID = "id";
+ public static final String URL_ALIAS = "urlAlias";
+ public static final String KEY_MATCH = "match";
+ public static final String KEY_TOKEN = "token";
private final Provider<CurrentUser> self;
private final Provider<ReviewDb> db;
@@ -110,6 +115,7 @@
ReviewCategoryStrategy reviewCategoryStrategy;
DiffView diffView;
List<TopMenu.MenuItem> my;
+ Map<String, String> urlAliases;
public PreferenceInfo(AccountGeneralPreferences p,
VersionedAccountPreferences v, Repository allUsers) {
@@ -129,12 +135,12 @@
reviewCategoryStrategy = p.getReviewCategoryStrategy();
diffView = p.getDiffView();
}
- my = my(v, allUsers);
+ loadFromAllUsers(v, allUsers);
}
- private List<TopMenu.MenuItem> my(VersionedAccountPreferences v,
+ private void loadFromAllUsers(VersionedAccountPreferences v,
Repository allUsers) {
- List<TopMenu.MenuItem> my = my(v);
+ my = my(v);
if (my.isEmpty() && !v.isDefaults()) {
try {
VersionedAccountPreferences d = VersionedAccountPreferences.forDefault();
@@ -153,7 +159,8 @@
my.add(new TopMenu.MenuItem("Starred Changes", "#/q/is:starred", null));
my.add(new TopMenu.MenuItem("Groups", "#/groups/self", null));
}
- return my;
+
+ urlAliases = urlAliases(v);
}
private List<TopMenu.MenuItem> my(VersionedAccountPreferences v) {
@@ -175,5 +182,15 @@
String val = cfg.getString(MY, subsection, key);
return !Strings.isNullOrEmpty(val) ? val : defaultValue;
}
+
+ private static Map<String, String> urlAliases(VersionedAccountPreferences v) {
+ HashMap<String, String> urlAliases = new HashMap<>();
+ Config cfg = v.getConfig();
+ 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.isEmpty() ? urlAliases : null;
+ }
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/SetPreferences.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/SetPreferences.java
index d75c5a2..b927596 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/SetPreferences.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/SetPreferences.java
@@ -15,9 +15,12 @@
package com.google.gerrit.server.account;
import static com.google.gerrit.server.account.GetPreferences.KEY_ID;
+import static com.google.gerrit.server.account.GetPreferences.KEY_MATCH;
import static com.google.gerrit.server.account.GetPreferences.KEY_TARGET;
+import static com.google.gerrit.server.account.GetPreferences.KEY_TOKEN;
import static com.google.gerrit.server.account.GetPreferences.KEY_URL;
import static com.google.gerrit.server.account.GetPreferences.MY;
+import static com.google.gerrit.server.account.GetPreferences.URL_ALIAS;
import com.google.common.base.Strings;
import com.google.gerrit.extensions.restapi.AuthException;
@@ -48,6 +51,8 @@
import java.io.IOException;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
@Singleton
public class SetPreferences implements RestModifyView<AccountResource, Input> {
@@ -67,6 +72,7 @@
public ReviewCategoryStrategy reviewCategoryStrategy;
public DiffView diffView;
public List<TopMenu.MenuItem> my;
+ public Map<String, String> urlAliases;
}
private final Provider<CurrentUser> self;
@@ -164,11 +170,11 @@
db.get().accounts().update(Collections.singleton(a));
db.get().commit();
storeMyMenus(versionedPrefs, i.my);
+ storeUrlAliases(versionedPrefs, i.urlAliases);
versionedPrefs.commit(md);
cache.evict(accountId);
return new GetPreferences.PreferenceInfo(
- p, versionedPrefs,
- md.getRepository());
+ p, versionedPrefs, md.getRepository());
} finally {
md.close();
db.get().rollback();
@@ -202,4 +208,21 @@
cfg.unsetSection(section, subsection);
}
}
+
+ public static void storeUrlAliases(VersionedAccountPreferences prefs,
+ Map<String, String> urlAliases) {
+ if (urlAliases != null) {
+ Config cfg = prefs.getConfig();
+ for (String subsection : cfg.getSubsections(URL_ALIAS)) {
+ cfg.unsetSection(URL_ALIAS, subsection);
+ }
+
+ int i = 1;
+ for (Entry<String, String> e : urlAliases.entrySet()) {
+ cfg.setString(URL_ALIAS, URL_ALIAS + i, KEY_MATCH, e.getKey());
+ cfg.setString(URL_ALIAS, URL_ALIAS + i, KEY_TOKEN, e.getValue());
+ i++;
+ }
+ }
+ }
}
diff --git a/plugins/cookbook-plugin b/plugins/cookbook-plugin
index e49010b..d2f6bc3 160000
--- a/plugins/cookbook-plugin
+++ b/plugins/cookbook-plugin
@@ -1 +1 @@
-Subproject commit e49010bbbed9d941c35a9f1eed1178cd909c7e34
+Subproject commit d2f6bc3511185729d3ecc3b3df25b1e9cebe2b2d