Merge "Allow to get/set service user groups from REST and WebUI"
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetConfig.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetConfig.java
index 8ec538b..1331c12 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetConfig.java
@@ -15,37 +15,68 @@
package com.googlesource.gerrit.plugins.serviceuser;
import com.google.common.base.Strings;
+import com.google.gerrit.common.data.GroupDescriptions;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.restapi.RestReadView;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.config.ConfigResource;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.config.PluginConfigFactory;
+import com.google.gerrit.server.group.GroupJson;
+import com.google.gerrit.server.group.GroupJson.GroupInfo;
+import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
public class GetConfig implements RestReadView<ConfigResource> {
+ private static final Logger log = LoggerFactory.getLogger(GetConfig.class);
private final PluginConfig cfg;
+ private final GroupCache groupCache;
+ private final GroupJson groupJson;
@Inject
public GetConfig(PluginConfigFactory cfgFactory,
- @PluginName String pluginName) {
+ @PluginName String pluginName, GroupCache groupCache, GroupJson groupJson) {
this.cfg = cfgFactory.getFromGerritConfig(pluginName);
+ this.groupCache = groupCache;
+ this.groupJson = groupJson;
}
@Override
- public ConfigInfo apply(ConfigResource rsrc) {
+ public ConfigInfo apply(ConfigResource rsrc) throws OrmException {
ConfigInfo info = new ConfigInfo();
info.info = Strings.emptyToNull(cfg.getString("infoMessage"));
info.onSuccess = Strings.emptyToNull(cfg.getString("onSuccessMessage"));
info.allowEmail = toBoolean(cfg.getBoolean("allowEmail", false));
info.createNotes = toBoolean(cfg.getBoolean("createNotes", true));
info.createNotesAsync = toBoolean(cfg.getBoolean("createNotesAsync", false));
+
String[] blocked = cfg.getStringList("block");
Arrays.sort(blocked);
info.blockedNames = Arrays.asList(blocked);
+
+ String[] groups = cfg.getStringList("group");
+ info.groups = new TreeMap<>();
+ for (String g : groups) {
+ AccountGroup group = groupCache.get(new AccountGroup.NameKey(g));
+ if (group != null) {
+ GroupInfo groupInfo = groupJson.format(GroupDescriptions.forAccountGroup(group));
+ groupInfo.name = null;
+ info.groups.put(g, groupInfo);
+ } else {
+ log.warn(String.format("Service user group %s does not exist.", g));
+ }
+ }
+
return info;
}
@@ -60,5 +91,6 @@
public Boolean createNotes;
public Boolean createNotesAsync;
public List<String> blockedNames;
+ public Map<String, GroupInfo> groups;
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutConfig.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutConfig.java
index 92694c5..f7648f4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutConfig.java
@@ -20,6 +20,9 @@
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestModifyView;
+import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.config.ConfigResource;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.config.SitePaths;
@@ -44,23 +47,27 @@
public Boolean createNotes;
public Boolean createNotesAsync;
public List<String> blockedNames;
+ public List<String> groups;
}
private final PluginConfigFactory cfgFactory;
private final SitePaths sitePaths;
private final String pluginName;
+ private final GroupCache groupCache;
@Inject
PutConfig(PluginConfigFactory cfgFactory, SitePaths sitePaths,
- @PluginName String pluginName) throws IOException, ConfigInvalidException {
+ @PluginName String pluginName, GroupCache groupCache) throws IOException,
+ ConfigInvalidException {
this.cfgFactory = cfgFactory;
this.sitePaths = sitePaths;
this.pluginName = pluginName;
+ this.groupCache = groupCache;
}
@Override
public Response<String> apply(ConfigResource rsrc, Input input)
- throws IOException, ConfigInvalidException {
+ throws IOException, ConfigInvalidException, UnprocessableEntityException {
FileBasedConfig cfg =
new FileBasedConfig(sitePaths.gerrit_config, FS.DETECTED);
cfg.load();
@@ -84,6 +91,15 @@
if (input.blockedNames != null) {
cfg.setStringList("plugin", pluginName, "block", input.blockedNames);
}
+ if (input.groups != null) {
+ for (String g : input.groups) {
+ if (groupCache.get(new AccountGroup.NameKey(g)) == null) {
+ throw new UnprocessableEntityException(
+ String.format("Group %s does not exist.", g));
+ }
+ }
+ cfg.setStringList("plugin", pluginName, "group", input.groups);
+ }
cfg.save();
cfgFactory.getFromGerritConfig(pluginName, true);
return Response.<String> ok("OK");
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ConfigInfo.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ConfigInfo.java
index 197cdae..8a01c1d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ConfigInfo.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ConfigInfo.java
@@ -14,6 +14,7 @@
package com.googlesource.gerrit.plugins.serviceuser.client;
+import com.google.gerrit.client.rpc.NativeMap;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArrayString;
@@ -26,6 +27,7 @@
final native boolean getCreateNotes() /*-{ return this.create_notes ? true : false; }-*/;
final native boolean getCreateNotesAsync() /*-{ return this.create_notes_async ? true : false; }-*/;
final native JsArrayString getBlockedNames() /*-{ return this.blocked_names; }-*/;
+ final native NativeMap<GroupInfo> getGroups() /*-{ return this.groups; }-*/;
final native void setInfoMessage(String s) /*-{ this.info = s; }-*/;
final native void setOnSuccessMessage(String s) /*-{ this.on_success = s; }-*/;
@@ -40,10 +42,19 @@
}
}
-
final native void initBlockedNames() /*-{ this.blocked_names = []; }-*/;
final native void addBlockedName(String n) /*-{ this.blocked_names.push(n); }-*/;
+ final void setGroups(List<String> groups) {
+ initGroups();
+ for (String g : groups) {
+ addGroup(g);
+ }
+
+ }
+ final native void initGroups() /*-{ this.groups = []; }-*/;
+ final native void addGroup(String g) /*-{ this.groups.push(g); }-*/;
+
static ConfigInfo create() {
ConfigInfo g = (ConfigInfo) createObject();
return g;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserSettingsScreen.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserSettingsScreen.java
index 7d2fc98..9b23513 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserSettingsScreen.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserSettingsScreen.java
@@ -49,6 +49,7 @@
private CheckBox createNotesCheckBox;
private CheckBox createNotesAsyncCheckBox;
private StringListPanel blockedUsernamesPanel;
+ private StringListPanel groupsPanel;
private Button saveButton;
ServiceUserSettingsScreen() {
@@ -172,6 +173,11 @@
info.getBlockedNames(), saveButton);
add(blockedUsernamesPanel);
+ groupsPanel =
+ new StringListPanel("Groups", "Group Name",
+ info.getGroups().keySet(), saveButton);
+ add(groupsPanel);
+
HorizontalPanel buttons = new HorizontalPanel();
add(buttons);
@@ -197,6 +203,7 @@
in.setCreateNotesAsync(createNotesAsyncCheckBox.getValue());
}
in.setBlockedNames(blockedUsernamesPanel.getValues());
+ in.setGroups(groupsPanel.getValues());
new RestApi("config").id("server").view(Plugin.get().getPluginName(), "config")
.put(in, new AsyncCallback<JavaScriptObject>() {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/StringListPanel.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/StringListPanel.java
index 27ca410..9aeaf6f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/StringListPanel.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/StringListPanel.java
@@ -33,6 +33,7 @@
import com.google.gwtexpui.globalkey.client.NpTextBox;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
public class StringListPanel extends FlowPanel {
@@ -42,6 +43,11 @@
StringListPanel(String title, String fieldName, JsArrayString values,
final FocusWidget w) {
+ this(title, fieldName, Natives.asList(values), w);
+ }
+
+ StringListPanel(String title, String fieldName, Collection<String> values,
+ final FocusWidget w) {
Label titleLabel = new Label(title);
titleLabel.setStyleName("serviceuser-smallHeading");
add(titleLabel);
@@ -112,9 +118,9 @@
setText(0, 1, name);
}
- void display(JsArrayString values) {
+ void display(Collection<String> values) {
int row = 1;
- for (String v : Natives.asList(values)) {
+ for (String v : values) {
populate(row, v);
row++;
}
diff --git a/src/main/resources/Documentation/rest-api-config.md b/src/main/resources/Documentation/rest-api-config.md
index 453299b..45388f7 100644
--- a/src/main/resources/Documentation/rest-api-config.md
+++ b/src/main/resources/Documentation/rest-api-config.md
@@ -622,7 +622,7 @@
Sets the configuration of the @PLUGIN@ plugin.
-The new configuration must be specified as a [ConfigInfo](#config-info)
+The new configuration must be specified as a [ConfigInput](#config-input)
entity in the request body. Not setting a parameter leaves the parameter
unchanged.
@@ -643,7 +643,8 @@
### <a id="config-info"></a>ConfigInfo
-The `ConfigInfo` entity contains configuration of the @PLUGIN@ plugin.
+The `ConfigInfo` entity contains the configuration of the @PLUGIN@
+plugin.
* _info_: HTML formatted message that should be displayed on the
service user creation screen.
@@ -659,6 +660,33 @@
`false`).
* _blocked\_names_: List of usernames which are forbidden to be used as
name for a service user. The blocked usernames are case insensitive.
+* _groups_: Map of groups to which newly created service users are
+ automatically added. The map maps the group name to a
+ [GroupInfo](../../../Documentation/rest-api-groups.html#group-info)
+ entity. The `name` field in the GroupInfo entities is not set since
+ the names are already available as map keys.
+
+### <a id="config-input"></a>ConfigInput
+
+The `ConfigInput` entity contains updates for the configuration of the
+@PLUGIN@ plugin.
+
+* _info_: HTML formatted message that should be displayed on the
+ service user creation screen.
+* _on\_success_: HTML formatted message that should be displayed after
+ a service user was successfully created.
+* _allow\_email_: Whether it is allowed to provide an email address for
+ a service user (not set if `false`).
+* _create\_notes_: Whether commits of a service user should be
+ annotated by a Git note that contains information about the current
+ owners of the service user (not set if `false`).
+* _create\_notes\_async_: Whether the Git notes on commits that are
+ pushed by a service user should be created asynchronously (not set if
+ `false`).
+* _blocked\_names_: List of usernames which are forbidden to be used as
+ name for a service user. The blocked usernames are case insensitive.
+* _groups_: List of names of internal groups to which newly created
+ service users should be automatically added.
### <a id="email-input"></a>EmailInput