Merge "Implement Buck driven build"
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUser.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUser.java
index a13e2f1..30f45fa 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUser.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUser.java
@@ -14,7 +14,9 @@
package com.googlesource.gerrit.plugins.serviceuser;
+import com.google.common.base.Function;
import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.extensions.restapi.BadRequestException;
@@ -22,17 +24,41 @@
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.account.CreateAccount;
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.git.MetaDataUpdate;
+import com.google.gerrit.server.git.ProjectLevelConfig;
+import com.google.gerrit.server.project.ProjectCache;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
+import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
import com.googlesource.gerrit.plugins.serviceuser.CreateServiceUser.Input;
+import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.PersonIdent;
+
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
@RequiresCapability(CreateServiceUserCapability.ID)
public class CreateServiceUser implements RestModifyView<ConfigResource, Input> {
+ private static final String USER = "user";
+ private static final String KEY_CREATED_BY = "createdBy";
+ private static final String KEY_CREATED_AT = "createdAt";
+
static class Input {
String username;
String sshKey;
@@ -42,37 +68,80 @@
CreateServiceUser create(String username);
}
- private final PluginConfigFactory cfg;
- private final String pluginName;
+ private final PluginConfig cfg;
private final CreateAccount.Factory createAccountFactory;
private final String username;
+ private final List<String> blockedNames;
+ private final Provider<CurrentUser> userProvider;
+ private final MetaDataUpdate.User metaDataUpdateFactory;
+ private final Project.NameKey allProjects;
+ private final ProjectLevelConfig storage;
+ private final DateFormat rfc2822DateFormatter;
@Inject
- CreateServiceUser(PluginConfigFactory cfg, @PluginName String pluginName,
- CreateAccount.Factory createAccountFactory, @Assisted String username) {
- this.cfg = cfg;
- this.pluginName = pluginName;
+ CreateServiceUser(PluginConfigFactory cfgFactory,
+ @PluginName String pluginName,
+ CreateAccount.Factory createAccountFactory,
+ Provider<CurrentUser> userProvider,
+ @GerritPersonIdent PersonIdent gerritIdent,
+ MetaDataUpdate.User metaDataUpdateFactory,
+ ProjectCache projectCache,
+ @Assisted String username) {
+ this.cfg = cfgFactory.getFromGerritConfig(pluginName);
this.createAccountFactory = createAccountFactory;
this.username = username;
+ this.blockedNames =
+ Lists.transform(Arrays.asList(cfg.getStringList("block")),
+ new Function<String, String>() {
+ @Override
+ public String apply(String blockedName) {
+ return blockedName.toLowerCase();
+ }
+ });
+ this.userProvider = userProvider;
+ this.metaDataUpdateFactory = metaDataUpdateFactory;
+ this.storage = projectCache.getAllProjects().getConfig(pluginName + ".db");
+ this.allProjects = projectCache.getAllProjects().getProject().getNameKey();
+ this.rfc2822DateFormatter =
+ new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
+ this.rfc2822DateFormatter.setCalendar(Calendar.getInstance(
+ gerritIdent.getTimeZone(), Locale.US));
}
@Override
public Object apply(ConfigResource resource, Input input)
throws BadRequestException, ResourceConflictException,
- UnprocessableEntityException, OrmException {
+ UnprocessableEntityException, OrmException, IOException {
if (input == null) {
input = new Input();
}
- if (input.username != null && !username.equals(input.username)) {
+ if (!username.equals(input.username)) {
throw new BadRequestException("username must match URL");
}
if (Strings.isNullOrEmpty(input.sshKey)) {
throw new BadRequestException("sshKey not set");
}
+ if (blockedNames.contains(username.toLowerCase())) {
+ throw new BadRequestException("The username '" + username
+ + "' is not allowed as name for service users.");
+ }
+
CreateAccount.Input in =
- new ServiceUserInput(username, input.sshKey,
- cfg.getFromGerritConfig(pluginName));
- return createAccountFactory.create(username).apply(TopLevelResource.INSTANCE, in);
+ new ServiceUserInput(username, input.sshKey, cfg);
+ Object response = createAccountFactory.create(username)
+ .apply(TopLevelResource.INSTANCE, in);
+
+ Config db = storage.get();
+ db.setString(USER, username, KEY_CREATED_BY,
+ userProvider.get().getUserName());
+ db.setString(USER, username, KEY_CREATED_AT,
+ rfc2822DateFormatter.format(new Date()));
+
+ MetaDataUpdate md = metaDataUpdateFactory.create(allProjects);
+ md.setMessage("Create Service User '" + username + "'\n");
+ storage.commit(md);
+
+ return response;
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserCommand.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserCommand.java
index e151105..d86c93e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserCommand.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserCommand.java
@@ -14,12 +14,9 @@
package com.googlesource.gerrit.plugins.serviceuser;
-import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.TopLevelResource;
-import com.google.gerrit.server.account.CreateAccount;
-import com.google.gerrit.server.config.PluginConfigFactory;
+import com.google.gerrit.server.config.ConfigResource;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
import com.google.gwtorm.server.OrmException;
@@ -44,21 +41,15 @@
private String sshKey;
@Inject
- private CreateAccount.Factory createAccountFactory;
-
- @Inject
- private PluginConfigFactory cfg;
-
- @Inject
- private @PluginName String pluginName;
+ private CreateServiceUser.Factory createServiceUser;
@Override
protected void run() throws OrmException, IOException, UnloggedFailure {
- CreateAccount.Input input =
- new ServiceUserInput(username, readSshKey(),
- cfg.getFromGerritConfig(pluginName));
+ CreateServiceUser.Input input = new CreateServiceUser.Input();
+ input.sshKey = readSshKey();
+
try {
- createAccountFactory.create(username).apply(TopLevelResource.INSTANCE, input);
+ createServiceUser.create(username).apply(new ConfigResource(), input);
} catch (RestApiException e) {
throw die(e.getMessage());
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserMenu.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserMenu.java
index 3dac6d1..51cc8d9 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserMenu.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserMenu.java
@@ -14,6 +14,7 @@
package com.googlesource.gerrit.plugins.serviceuser;
+import com.google.common.collect.Lists;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.webui.TopMenu;
import com.google.gerrit.server.CurrentUser;
@@ -21,7 +22,6 @@
import com.google.inject.Inject;
import com.google.inject.Provider;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -36,7 +36,7 @@
Provider<CurrentUser> userProvider) {
this.pluginName = pluginName;
this.userProvider = userProvider;
- menuEntries = new ArrayList<TopMenu.MenuEntry>();
+ menuEntries = Lists.newArrayList();
if (canCreateServiceUser()) {
menuEntries.add(new MenuEntry("People", Collections
.singletonList(new MenuItem("Create Service User", "", "", MENU_ID))));
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetMessages.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetMessages.java
new file mode 100644
index 0000000..1ce5ad7
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetMessages.java
@@ -0,0 +1,47 @@
+// Copyright (C) 2013 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.googlesource.gerrit.plugins.serviceuser;
+
+import com.google.common.base.Strings;
+import com.google.gerrit.extensions.annotations.PluginName;
+import com.google.gerrit.extensions.restapi.RestReadView;
+import com.google.gerrit.server.config.ConfigResource;
+import com.google.gerrit.server.config.PluginConfig;
+import com.google.gerrit.server.config.PluginConfigFactory;
+import com.google.inject.Inject;
+
+public class GetMessages implements RestReadView<ConfigResource> {
+
+ private final PluginConfig cfg;
+
+ @Inject
+ public GetMessages(PluginConfigFactory cfgFactory,
+ @PluginName String pluginName) {
+ this.cfg = cfgFactory.getFromGerritConfig(pluginName);
+ }
+
+ @Override
+ public MessagesInfo apply(ConfigResource rsrc) {
+ MessagesInfo info = new MessagesInfo();
+ info.info = Strings.emptyToNull(cfg.getString("infoMessage"));
+ info.onSuccess = Strings.emptyToNull(cfg.getString("onSuccessMessage"));
+ return info;
+ }
+
+ public class MessagesInfo {
+ String info;
+ String onSuccess;
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/Module.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/Module.java
index 697b573..4a45a89 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/Module.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/Module.java
@@ -38,6 +38,7 @@
bind(ServiceUserCollection.class);
child(CONFIG_KIND, "serviceusers").to(ServiceUserCollection.class);
install(new FactoryModuleBuilder().build(CreateServiceUser.Factory.class));
+ get(CONFIG_KIND, "messages").to(GetMessages.class);
}
});
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/CreateServiceUserForm.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/CreateServiceUserForm.java
index 2dfbe18..2363efa 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/CreateServiceUserForm.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/CreateServiceUserForm.java
@@ -43,6 +43,7 @@
private DialogBox dialogBox;
private TextBox usernameTxt;
private TextArea sshKeyTxt;
+ private String onSuccessMessage;
@Override
public void onModuleLoad() {
@@ -50,7 +51,7 @@
dialogBox.setText("Create Service User");
dialogBox.setAnimationEnabled(true);
- Panel p = new VerticalPanel();
+ final VerticalPanel p = new VerticalPanel();
p.setStyleName("panel");
Panel usernamePanel = new VerticalPanel();
@@ -154,6 +155,24 @@
createButton.setEnabled(false);
}
}, ClickEvent.getType());
+
+ new RestApi("config").id("server").view("serviceuser", "messages")
+ .get(new AsyncCallback<MessagesInfo>() {
+ @Override
+ public void onSuccess(MessagesInfo info) {
+ onSuccessMessage = info.getOnSuccessMessage();
+
+ String infoMessage = info.getInfoMessage();
+ if (infoMessage != null && !"".equals(infoMessage)) {
+ p.insert(new HTML(onSuccessMessage), 0);
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {
+ // never invoked
+ }
+ });
}
private void doCreate() {
@@ -185,6 +204,11 @@
successDialog.hide();
}
});
+
+ if (onSuccessMessage != null && !"".equals(onSuccessMessage)) {
+ p.add(new HTML(onSuccessMessage));
+ }
+
p.add(okButton);
successDialog.add(p);
@@ -204,6 +228,14 @@
sshKeyTxt.setValue("");
}
+ private static class MessagesInfo extends JavaScriptObject {
+ public final native String getOnSuccessMessage() /*-{ return this.on_success }-*/;
+ public final native String getInfoMessage() /*-{ return this.info }-*/;
+
+ protected MessagesInfo() {
+ }
+ }
+
private static class ServiceUserInput extends JavaScriptObject {
final native void ssh_key(String s) /*-{ this.ssh_key = s; }-*/;
diff --git a/src/main/resources/Documentation/about.md b/src/main/resources/Documentation/about.md
index d428721..bb91d0e 100644
--- a/src/main/resources/Documentation/about.md
+++ b/src/main/resources/Documentation/about.md
@@ -17,8 +17,36 @@
groups](config.html#group). This allows to automatically assign or
block certain access rights for the service users.
+For each created service user the plugin stores some
+[properties](#properties).
+
<a id="webui"></a>
Create Service User in WebUI
----------------------------
In the `People` top menu there is a menu item `Create Service User`
that opens a dialog for creating a service user.
+
+<a id="properties"></a>
+Service User Properties
+-----------------------
+The service user properties are stored in the `refs/meta/config` branch
+of the `All-Projects` project in the file `@PLUGIN@.db`, which is a
+Git config file:
+
+```
+ [user "build-bot"]
+ createdBy = jdoe
+ createdAt = Wed, 13 Nov 2013 14:31:11 +0100
+ [user "voter"]
+ createdBy = jroe
+ createdAt = Wed, 13 Nov 2013 14:45:00 +0100
+```
+
+<a id="createdBy">
+`user.<service-user-name>.createdBy`
+: The username of the user who created the service user.
+
+<a id="createdAt">
+`user.<service-user-name>.createdAt`
+: The date when the service user was created.
+
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index 793158d..ff65add 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -9,8 +9,25 @@
group = Service Users
```
+<a id="block">
+`plugin.@PLUGIN@.block`
+: A username which is forbidden to be used as name for a service
+ user. The blocked username is case insensitive. Multiple
+ usernames can be blocked by specifying multiple
+ `plugin.@PLUGIN@.block` entries.
+
<a id="group">
`plugin.@PLUGIN@.group`
: A group to which newly created service users should be
- automatically added. Multiple groups can be specified by having
- multiple `plugin.@PLUGIN@.group` entries.
+ automatically added. Multiple groups can be specified by having
+ multiple `plugin.@PLUGIN@.group` entries.
+
+<a id="infoMessage">
+`plugin.@PLUGIN@.infoMessage`
+: HTML formatted message that should be displayed in the service user
+ creation dialog.
+
+<a id="onSuccessMessage">
+`plugin.@PLUGIN@.onSuccessMessage`
+: HTML formatted message that should be displayed after a service
+ user was successfully created.
diff --git a/src/main/resources/Documentation/rest-api-config.md b/src/main/resources/Documentation/rest-api-config.md
index f6bfaf9..b3642bc 100644
--- a/src/main/resources/Documentation/rest-api-config.md
+++ b/src/main/resources/Documentation/rest-api-config.md
@@ -31,7 +31,6 @@
{
"ssh_key": "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0T...YImydZAw=="
}
-----
```
As response a detailed [AccountInfo](../../../Documentation/rest-api-accounts.html#account-info)
@@ -52,10 +51,48 @@
}
```
+### <a id="get-messages"> Get Messages
+_GET /config/server/@PLUGIN@~messages_
+
+Gets help messages to be displayed for the service user creation in the
+Web UI.
+
+#### Request
+
+```
+ GET /config/server/@PLUGIN@~messages HTTP/1.0
+```
+
+As response a [MessagesInfo](#messages-info) entity is returned that
+contains the messages.
+
+#### Response
+
+```
+ HTTP/1.1 200 OK
+ Content-Disposition: attachment
+ Content-Type: application/json;charset=UTF-8
+
+ )]}'
+ {
+ "on_success": "Don't forget to assign \u003ca href\u003d\"Documentation/access-control.html\"\u003eaccess rights\u003c/a\u003e to the service user."
+ }
+```
+
<a id="json-entities">JSON Entities
-----------------------------------
+### <a id="messages-info"></a>MessagesInfo
+
+The `MessagesInfo` entity contains help messages that should be
+displayed for the service user creation in the Web UI.
+
+* _info_: HTML formatted message that should be displayed in the
+ service user creation dialog.
+* _on\_success_: HTML formatted message that should be displayed after
+ a service user was successfully created.
+
### <a id="service-user-input"></a>ServiceUserInput
The `ServiceUserInput` entity contains options for creating a service