Merge branch 'stable-2.16' into stable-3.0 * stable-2.16: Upgrade bazlets to latest stable-2.16 Upgrade bazlets to latest stable-2.15 Upgrade bazlets to latest stable-2.14 Change-Id: I28d9a3c43a4a94ae3826dec8cce705307c86ff48
diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..3a9c4b9 --- /dev/null +++ b/.eslintrc.json
@@ -0,0 +1,79 @@ +{ + "extends": ["eslint:recommended", "google"], + "parserOptions": { + "ecmaVersion": 8 + }, + "env": { + "browser": true, + "es6": true + }, + "globals": { + "__dirname": false, + "app": false, + "page": false, + "Polymer": false, + "process": false, + "require": false, + "Gerrit": false, + "Promise": false, + "assert": false, + "test": false, + "flushAsynchronousOperations": false + }, + "rules": { + "arrow-parens": ["error", "as-needed"], + "block-spacing": ["error", "always"], + "brace-style": ["error", "1tbs", { "allowSingleLine": true }], + "camelcase": "off", + "comma-dangle": ["error", "always-multiline"], + "eol-last": "off", + "indent": "off", + "indent-legacy": ["error", 2, { + "MemberExpression": 2, + "FunctionDeclaration": {"body": 1, "parameters": 2}, + "FunctionExpression": {"body": 1, "parameters": 2}, + "CallExpression": {"arguments": 2}, + "ArrayExpression": 1, + "ObjectExpression": 1, + "SwitchCase": 1 + }], + "keyword-spacing": ["error", { "after": true, "before": true }], + "max-len": [ + "error", + 80, + 2, + {"ignoreComments": true} + ], + "new-cap": ["error", { "capIsNewExceptions": ["Polymer"] }], + "no-console": "off", + "no-restricted-syntax": [ + "error", + { + "selector": "ExpressionStatement > CallExpression > MemberExpression[object.name='test'][property.name='only']", + "message": "Remove test.only." + }, + { + "selector": "ExpressionStatement > CallExpression > MemberExpression[object.name='suite'][property.name='only']", + "message": "Remove suite.only." + } + ], + "no-undef": "off", + "no-useless-escape": "off", + "no-var": "error", + "object-shorthand": ["error", "always"], + "prefer-arrow-callback": "error", + "prefer-const": "error", + "prefer-spread": "error", + "quote-props": ["error", "consistent-as-needed"], + "require-jsdoc": "off", + "semi": [2, "always"], + "template-curly-spacing": "error", + "valid-jsdoc": "off" + }, + "plugins": [ + "html" + ], + "settings": { + "html/report-bad-indent": "error" + } + }
diff --git a/BUILD b/BUILD index f4c8d63..fcad0e5 100644 --- a/BUILD +++ b/BUILD
@@ -1,14 +1,26 @@ -load("//tools/bzl:plugin.bzl", "gerrit_plugin") +load("//tools/bzl:junit.bzl", "junit_tests") +load("//tools/bzl:plugin.bzl", "PLUGIN_DEPS", "PLUGIN_TEST_DEPS", "gerrit_plugin") gerrit_plugin( name = "serviceuser", srcs = glob(["src/main/java/**/*.java"]), - gwt_module = "com.googlesource.gerrit.plugins.serviceuser.CreateServiceUserForm", manifest_entries = [ "Gerrit-PluginName: serviceuser", "Gerrit-Module: com.googlesource.gerrit.plugins.serviceuser.Module", "Gerrit-HttpModule: com.googlesource.gerrit.plugins.serviceuser.HttpModule", "Gerrit-SshModule: com.googlesource.gerrit.plugins.serviceuser.SshModule", ], - resources = glob(["src/main/**/*"]), + resources = glob(["src/main/resources/**/*"]), +) + +junit_tests( + name = "serviceuser_tests", + testonly = 1, + srcs = glob([ + "src/test/java/**/*Test.java", + ]), + tags = ["serviceuser"], + deps = PLUGIN_TEST_DEPS + PLUGIN_DEPS + [ + ":serviceuser__plugin", + ], )
diff --git a/WORKSPACE b/WORKSPACE index 96f4e2f..79bde89 100644 --- a/WORKSPACE +++ b/WORKSPACE
@@ -3,7 +3,7 @@ load("//:bazlets.bzl", "load_bazlets") load_bazlets( - commit = "620a4eb3bc0749301043fd6a69570b61b86e742e", + commit = "99d51724c816dc25f03c8ca96126716298a6ee38", #local_path = "/home/<user>/projects/bazlets", ) @@ -24,10 +24,3 @@ # Load release Plugin API gerrit_api() - -load( - "@com_googlesource_gerrit_bazlets//:gerrit_gwt.bzl", - "gerrit_gwt", -) - -gerrit_gwt()
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/AddSshKey.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/AddSshKey.java index 64a024d..c5ccadd 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/AddSshKey.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/AddSshKey.java
@@ -20,7 +20,6 @@ import com.google.gerrit.extensions.restapi.BadRequestException; import com.google.gerrit.extensions.restapi.Response; import com.google.gerrit.extensions.restapi.RestModifyView; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; @@ -38,7 +37,7 @@ @Override public Response<SshKeyInfo> apply(ServiceUserResource rsrc, SshKeyInput input) - throws AuthException, BadRequestException, OrmException, IOException, ConfigInvalidException { + throws AuthException, BadRequestException, IOException, ConfigInvalidException { return addSshKey.get().apply(rsrc.getUser(), input); } }
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 5b3ae51..80ddf1b 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUser.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUser.java
@@ -42,7 +42,6 @@ import com.google.gerrit.server.project.ProjectCache; import com.google.gerrit.server.project.ProjectLevelConfig; import com.google.gerrit.server.restapi.account.CreateAccount; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; @@ -123,8 +122,7 @@ @Override public Response<ServiceUserInfo> apply( ConfigResource parentResource, IdString id, CreateServiceUser.Input input) - throws RestApiException, OrmException, IOException, ConfigInvalidException, - PermissionBackendException { + throws RestApiException, IOException, ConfigInvalidException, PermissionBackendException { CurrentUser user = userProvider.get(); if (user == null || !user.isIdentifiedUser()) { throw new AuthException("authentication required"); @@ -137,10 +135,15 @@ if (input.username != null && !username.equals(input.username)) { throw new BadRequestException("username must match URL"); } + if (Strings.isNullOrEmpty(input.sshKey)) { throw new BadRequestException("sshKey not set"); } + if (!SshKeyValidator.validateFormat(input.sshKey)) { + throw new BadRequestException("sshKey invalid."); + } + if (blockedNames.contains(username.toLowerCase())) { throw new BadRequestException( "The username '" + username + "' is not allowed as name for service users.");
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 bebd520..3f27975 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserCommand.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserCommand.java
@@ -23,7 +23,6 @@ import com.google.gerrit.server.permissions.PermissionBackendException; import com.google.gerrit.sshd.CommandMetaData; import com.google.gerrit.sshd.SshCommand; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import java.io.BufferedReader; import java.io.IOException; @@ -50,8 +49,7 @@ @Override protected void run() - throws OrmException, IOException, UnloggedFailure, ConfigInvalidException, - PermissionBackendException { + throws IOException, UnloggedFailure, ConfigInvalidException, PermissionBackendException { CreateServiceUser.Input input = new CreateServiceUser.Input(); input.sshKey = readSshKey(); input.username = username;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserForm.gwt.xml b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserForm.gwt.xml deleted file mode 100644 index 9d921cb..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserForm.gwt.xml +++ /dev/null
@@ -1,32 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - 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. ---> -<module rename-to="serviceuser"> - <!-- Inherit the core Web Toolkit stuff. --> - <inherits name="com.google.gwt.user.User"/> - <!-- Other module inherits --> - <inherits name="com.google.gerrit.Plugin"/> - <inherits name="com.google.gwt.http.HTTP"/> - <inherits name="com.google.gwt.json.JSON"/> - <inherits name='com.google.gwtexpui.clippy.Clippy'/> - <inherits name='com.google.gwtexpui.globalkey.GlobalKey'/> - <!-- Using GWT built-in themes adds a number of static --> - <!-- resources to the plugin. No theme inherits lines were --> - <!-- added in order to make this plugin as simple as possible --> - <!-- Specify the app entry point class. --> - <entry-point class="com.googlesource.gerrit.plugins.serviceuser.client.ServiceUserPlugin"/> - <stylesheet src="serviceuser.css"/> -</module>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserNotes.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserNotes.java index c0e4c20..63cb875 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserNotes.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserNotes.java
@@ -27,7 +27,6 @@ import com.google.gerrit.server.config.AnonymousCowardName; import com.google.gerrit.server.git.NotesBranchUtil; import com.google.gerrit.server.permissions.PermissionBackendException; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import com.googlesource.gerrit.plugins.serviceuser.GetServiceUser.ServiceUserInfo; @@ -83,8 +82,7 @@ } void createNotes(String branch, ObjectId oldObjectId, ObjectId newObjectId) - throws IOException, OrmException, ConfigInvalidException, PermissionBackendException, - RestApiException { + throws IOException, ConfigInvalidException, PermissionBackendException, RestApiException { if (ObjectId.zeroId().equals(newObjectId)) { return; } @@ -156,13 +154,13 @@ } private ObjectId createNoteContent(String branch, ServiceUserInfo serviceUser) - throws IOException, OrmException, MethodNotAllowedException, PermissionBackendException { + throws IOException, MethodNotAllowedException, PermissionBackendException { return getInserter() .insert(Constants.OBJ_BLOB, createServiceUserNote(branch, serviceUser).getBytes(UTF_8)); } private String createServiceUserNote(String branch, ServiceUserInfo serviceUser) - throws OrmException, MethodNotAllowedException, PermissionBackendException { + throws MethodNotAllowedException, PermissionBackendException { HeaderFormatter fmt = new HeaderFormatter(gerritServerIdent.getTimeZone(), anonymousCowardName); fmt.appendDate(); fmt.append("Project", project.get());
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/DeleteActive.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/DeleteActive.java index 5393e03..ec5d063 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/DeleteActive.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/DeleteActive.java
@@ -18,7 +18,6 @@ import com.google.gerrit.extensions.restapi.Response; import com.google.gerrit.extensions.restapi.RestApiException; import com.google.gerrit.extensions.restapi.RestModifyView; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; @@ -36,7 +35,7 @@ @Override public Response<?> apply(ServiceUserResource rsrc, Input input) - throws RestApiException, OrmException, IOException, ConfigInvalidException { + throws RestApiException, IOException, ConfigInvalidException { return deleteActive.get().apply(rsrc, input); } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/DeleteSshKey.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/DeleteSshKey.java index 9092e74..9ce83d3 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/DeleteSshKey.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/DeleteSshKey.java
@@ -20,7 +20,6 @@ import com.google.gerrit.extensions.restapi.RestModifyView; import com.google.gerrit.server.account.AccountResource; import com.google.gerrit.server.permissions.PermissionBackendException; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; @@ -39,8 +38,8 @@ @Override public Response<?> apply(ServiceUserResource.SshKey rsrc, Input input) - throws OrmException, AuthException, RepositoryNotFoundException, IOException, - ConfigInvalidException, PermissionBackendException { + throws AuthException, RepositoryNotFoundException, IOException, ConfigInvalidException, + PermissionBackendException { return deleteSshKey .get() .apply(new AccountResource.SshKey(rsrc.getUser(), rsrc.getSshKey()), input);
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 28d7be3..85da7b0 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetConfig.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetConfig.java
@@ -27,7 +27,6 @@ import com.google.gerrit.server.group.InternalGroupDescription; import com.google.gerrit.server.permissions.PermissionBackendException; import com.google.gerrit.server.restapi.group.GroupJson; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Singleton; import java.util.Arrays; @@ -60,7 +59,7 @@ } @Override - public ConfigInfo apply(ConfigResource rsrc) throws OrmException, PermissionBackendException { + public ConfigInfo apply(ConfigResource rsrc) throws PermissionBackendException { PluginConfig cfg = cfgFactory.getFromGerritConfig(pluginName); ConfigInfo info = new ConfigInfo(); info.info = Strings.emptyToNull(cfg.getString("infoMessage"));
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetOwner.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetOwner.java index 47783f5..31c2eb6 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetOwner.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetOwner.java
@@ -30,7 +30,6 @@ import com.google.gerrit.server.project.ProjectLevelConfig; import com.google.gerrit.server.restapi.group.GroupJson; import com.google.gerrit.server.restapi.group.GroupsCollection; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Singleton; @@ -55,7 +54,7 @@ @Override public Response<GroupInfo> apply(ServiceUserResource rsrc) - throws RestApiException, OrmException, PermissionBackendException { + throws RestApiException, PermissionBackendException { ProjectLevelConfig storage = projectCache.getAllProjects().getConfig(pluginName + ".db"); String owner = storage.get().getString(USER, rsrc.getUser().getUserName().get(), KEY_OWNER); if (owner != null) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetServiceUser.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetServiceUser.java index a4ad837..3a2460f 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetServiceUser.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetServiceUser.java
@@ -32,7 +32,6 @@ import com.google.gerrit.server.project.ProjectCache; import com.google.gerrit.server.project.ProjectLevelConfig; import com.google.gerrit.server.restapi.account.GetAccount; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; @@ -62,7 +61,7 @@ @Override public ServiceUserInfo apply(ServiceUserResource rsrc) - throws RestApiException, OrmException, PermissionBackendException { + throws RestApiException, PermissionBackendException { ProjectLevelConfig storage = projectCache.getAllProjects().getConfig(pluginName + ".db"); String username = rsrc.getUser().getUserName().get(); Config db = storage.get();
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetSshKeys.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetSshKeys.java index 92a9430..60dfc15 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetSshKeys.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetSshKeys.java
@@ -17,7 +17,6 @@ import com.google.gerrit.extensions.common.SshKeyInfo; import com.google.gerrit.extensions.restapi.AuthException; import com.google.gerrit.extensions.restapi.RestReadView; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; @@ -37,8 +36,7 @@ @Override public List<SshKeyInfo> apply(ServiceUserResource rsrc) - throws AuthException, OrmException, RepositoryNotFoundException, IOException, - ConfigInvalidException { + throws AuthException, RepositoryNotFoundException, IOException, ConfigInvalidException { return getSshKeys.get().apply(rsrc.getUser()); } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/HttpModule.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/HttpModule.java index 80d86e2..a99987b 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/HttpModule.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/HttpModule.java
@@ -1,4 +1,4 @@ -// Copyright (C) 2013 The Android Open Source Project +// Copyright (C) 2019 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. @@ -15,14 +15,14 @@ package com.googlesource.gerrit.plugins.serviceuser; import com.google.gerrit.extensions.registration.DynamicSet; -import com.google.gerrit.extensions.webui.GwtPlugin; +import com.google.gerrit.extensions.webui.JavaScriptPlugin; import com.google.gerrit.extensions.webui.WebUiPlugin; -import com.google.inject.servlet.ServletModule; +import com.google.inject.AbstractModule; -class HttpModule extends ServletModule { - +public class HttpModule extends AbstractModule { @Override - protected void configureServlets() { - DynamicSet.bind(binder(), WebUiPlugin.class).toInstance(new GwtPlugin("serviceuser")); + protected void configure() { + DynamicSet.bind(binder(), WebUiPlugin.class) + .toInstance(new JavaScriptPlugin("gr-serviceuser.html")); } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ListServiceUsers.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ListServiceUsers.java index cf6ea40..0b93721 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ListServiceUsers.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ListServiceUsers.java
@@ -30,7 +30,6 @@ import com.google.gerrit.server.permissions.PermissionBackendException; import com.google.gerrit.server.project.ProjectCache; import com.google.gerrit.server.project.ProjectLevelConfig; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; @@ -68,8 +67,7 @@ @Override public Map<String, ServiceUserInfo> apply(ConfigResource rscr) - throws OrmException, IOException, RestApiException, PermissionBackendException, - ConfigInvalidException { + throws IOException, RestApiException, PermissionBackendException, ConfigInvalidException { ProjectLevelConfig storage = projectCache.getAllProjects().getConfig(pluginName + ".db"); CurrentUser user = userProvider.get(); if (user == null || !user.isIdentifiedUser()) { @@ -84,7 +82,12 @@ ServiceUserInfo info; try { ServiceUserResource serviceUserResource = - serviceUsers.get().parse(new ConfigResource(), IdString.fromDecoded(username)); + serviceUsers + .get() + .parse( + new ConfigResource(), + IdString.fromDecoded( + String.valueOf(account.get().getAccount().getId().get()))); info = getServiceUser.get().apply(serviceUserResource); info.username = null; accounts.put(username, info);
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 9ceba80..56d14e1 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/Module.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/Module.java
@@ -24,7 +24,6 @@ import com.google.gerrit.extensions.registration.DynamicMap; import com.google.gerrit.extensions.registration.DynamicSet; import com.google.gerrit.extensions.restapi.RestApiModule; -import com.google.gerrit.extensions.webui.TopMenu; import com.google.gerrit.server.git.validators.CommitValidationListener; import com.google.inject.AbstractModule; import com.google.inject.assistedinject.FactoryModuleBuilder; @@ -36,7 +35,6 @@ bind(CapabilityDefinition.class) .annotatedWith(Exports.named(CreateServiceUserCapability.ID)) .to(CreateServiceUserCapability.class); - DynamicSet.bind(binder(), TopMenu.class).to(ServiceUserMenu.class); DynamicSet.bind(binder(), GitReferenceUpdatedListener.class).to(RefUpdateListener.class); DynamicSet.bind(binder(), CommitValidationListener.class).to(ValidateServiceUserCommits.class); install(new FactoryModuleBuilder().build(CreateServiceUserNotes.Factory.class)); @@ -72,5 +70,6 @@ delete(SERVICE_USER_KIND, "owner").to(PutOwner.class); } }); + install(new HttpModule()); } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutActive.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutActive.java index 1282935..f4b0365 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutActive.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutActive.java
@@ -18,7 +18,6 @@ import com.google.gerrit.extensions.restapi.Response; import com.google.gerrit.extensions.restapi.RestApiException; import com.google.gerrit.extensions.restapi.RestModifyView; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; @@ -36,7 +35,7 @@ @Override public Response<String> apply(ServiceUserResource rsrc, Input input) - throws OrmException, IOException, ConfigInvalidException, RestApiException { + throws IOException, ConfigInvalidException, RestApiException { return putActive.get().apply(rsrc, input); } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutEmail.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutEmail.java index 4a5c6f6..986b2bb 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutEmail.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutEmail.java
@@ -17,7 +17,7 @@ import static com.google.gerrit.server.permissions.GlobalPermission.ADMINISTRATE_SERVER; import com.google.common.base.Strings; -import com.google.gerrit.common.errors.EmailException; +import com.google.gerrit.exceptions.EmailException; import com.google.gerrit.extensions.api.accounts.EmailInput; import com.google.gerrit.extensions.restapi.DefaultInput; import com.google.gerrit.extensions.restapi.IdString; @@ -31,7 +31,6 @@ import com.google.gerrit.server.restapi.account.CreateEmail; import com.google.gerrit.server.restapi.account.DeleteEmail; import com.google.gerrit.server.restapi.account.PutPreferred; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; @@ -73,8 +72,8 @@ @Override public Response<?> apply(ServiceUserResource rsrc, Input input) - throws OrmException, ConfigInvalidException, EmailException, IOException, - PermissionBackendException, RestApiException { + throws ConfigInvalidException, EmailException, IOException, PermissionBackendException, + RestApiException { Boolean emailAllowed = getConfig.get().apply(new ConfigResource()).allowEmail; if ((emailAllowed == null || !emailAllowed)) { permissionBackend.user(self.get()).check(ADMINISTRATE_SERVER);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutHttpPassword.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutHttpPassword.java index 61b5841..8d0110a 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutHttpPassword.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutHttpPassword.java
@@ -26,7 +26,6 @@ import com.google.gerrit.server.config.ConfigResource; import com.google.gerrit.server.permissions.PermissionBackend; import com.google.gerrit.server.permissions.PermissionBackendException; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; @@ -61,7 +60,7 @@ @Override public Response<String> apply(ServiceUserResource rsrc, Input input) throws AuthException, ResourceConflictException, ConfigInvalidException, - ResourceNotFoundException, OrmException, IOException, PermissionBackendException { + ResourceNotFoundException, IOException, PermissionBackendException { if (input == null) { input = new Input(); }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutName.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutName.java index 4bcdd6a..8b10d59 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutName.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutName.java
@@ -19,7 +19,6 @@ import com.google.gerrit.extensions.restapi.ResourceNotFoundException; import com.google.gerrit.extensions.restapi.Response; import com.google.gerrit.extensions.restapi.RestModifyView; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; @@ -37,7 +36,7 @@ @Override public Response<String> apply(ServiceUserResource rsrc, NameInput input) - throws MethodNotAllowedException, ResourceNotFoundException, OrmException, IOException, + throws MethodNotAllowedException, ResourceNotFoundException, IOException, ConfigInvalidException { return putName.get().apply(rsrc.getUser(), input); }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutOwner.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutOwner.java index 37bbf17..f444380 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutOwner.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutOwner.java
@@ -40,7 +40,6 @@ import com.google.gerrit.server.project.ProjectLevelConfig; import com.google.gerrit.server.restapi.group.GroupJson; import com.google.gerrit.server.restapi.group.GroupsCollection; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; @@ -87,7 +86,7 @@ @Override public Response<GroupInfo> apply(ServiceUserResource rsrc, Input input) - throws RestApiException, IOException, OrmException, PermissionBackendException { + throws RestApiException, IOException, PermissionBackendException { ProjectLevelConfig storage = projectCache.getAllProjects().getConfig(pluginName + ".db"); Boolean ownerAllowed = getConfig.get().apply(new ConfigResource()).allowOwner; if ((ownerAllowed == null || !ownerAllowed)) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/RefUpdateListener.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/RefUpdateListener.java index 69512c5..c4090ac 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/RefUpdateListener.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/RefUpdateListener.java
@@ -24,7 +24,6 @@ import com.google.gerrit.server.git.ProjectRunnable; import com.google.gerrit.server.git.WorkQueue; import com.google.gerrit.server.permissions.PermissionBackendException; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Singleton; import java.io.IOException; @@ -109,7 +108,6 @@ ObjectId.fromString(e.getNewObjectId())); crn.commitNotes(); } catch (IOException - | OrmException | ConfigInvalidException | PermissionBackendException | RestApiException x) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ServiceUserCollection.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ServiceUserCollection.java index 729282c..066898f 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ServiceUserCollection.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ServiceUserCollection.java
@@ -38,7 +38,6 @@ import com.google.gerrit.server.project.ProjectLevelConfig; import com.google.gerrit.server.restapi.account.AccountsCollection; import com.google.gerrit.server.restapi.group.GroupsCollection; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; @@ -79,8 +78,8 @@ @Override public ServiceUserResource parse(ConfigResource parent, IdString id) - throws ResourceNotFoundException, AuthException, IOException, OrmException, - PermissionBackendException, ConfigInvalidException { + throws ResourceNotFoundException, AuthException, IOException, PermissionBackendException, + ConfigInvalidException { ProjectLevelConfig storage = projectCache.getAllProjects().getConfig(pluginName + ".db"); IdentifiedUser serviceUser = accounts.get().parse(TopLevelResource.INSTANCE, id).getUser(); if (serviceUser == null @@ -92,7 +91,8 @@ throw new AuthException("Authentication required"); } if (!permissionBackend.user(user).testOrFalse(ADMINISTRATE_SERVER)) { - String owner = storage.get().getString(USER, id.get(), KEY_OWNER); + String username = serviceUser.getUserName().get(); + String owner = storage.get().getString(USER, username, KEY_OWNER); if (owner != null) { GroupDescription.Basic group = groups.parse(TopLevelResource.INSTANCE, IdString.fromDecoded(owner)).getGroup(); @@ -101,7 +101,7 @@ } } else if (!((IdentifiedUser) user) .getAccountId() - .equals(new Account.Id(storage.get().getInt(USER, id.get(), KEY_CREATOR_ID, -1)))) { + .equals(new Account.Id(storage.get().getInt(USER, username, KEY_CREATOR_ID, -1)))) { throw new ResourceNotFoundException(id); } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ServiceUserMenu.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ServiceUserMenu.java deleted file mode 100644 index df2cf8c..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ServiceUserMenu.java +++ /dev/null
@@ -1,94 +0,0 @@ -// 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 static com.google.gerrit.server.permissions.GlobalPermission.ADMINISTRATE_SERVER; - -import com.google.common.collect.Lists; -import com.google.gerrit.extensions.annotations.PluginName; -import com.google.gerrit.extensions.api.access.PluginPermission; -import com.google.gerrit.extensions.client.MenuItem; -import com.google.gerrit.extensions.restapi.AuthException; -import com.google.gerrit.extensions.restapi.RestApiException; -import com.google.gerrit.extensions.webui.TopMenu; -import com.google.gerrit.server.CurrentUser; -import com.google.gerrit.server.IdentifiedUser; -import com.google.gerrit.server.config.ConfigResource; -import com.google.gerrit.server.permissions.PermissionBackend; -import com.google.gerrit.server.permissions.PermissionBackendException; -import com.google.gwtorm.server.OrmException; -import com.google.inject.Inject; -import com.google.inject.Provider; -import java.io.IOException; -import java.util.List; -import org.eclipse.jgit.errors.ConfigInvalidException; - -class ServiceUserMenu implements TopMenu { - private final String pluginName; - private final Provider<CurrentUser> userProvider; - private final List<MenuEntry> menuEntries; - private final Provider<ListServiceUsers> listServiceUsers; - private final PermissionBackend permissionBackend; - - @Inject - ServiceUserMenu( - @PluginName String pluginName, - Provider<CurrentUser> userProvider, - Provider<ListServiceUsers> listServiceUsers, - PermissionBackend permissionBackend) - throws IOException, PermissionBackendException, ConfigInvalidException, RestApiException { - this.pluginName = pluginName; - this.userProvider = userProvider; - this.listServiceUsers = listServiceUsers; - menuEntries = Lists.newArrayList(); - this.permissionBackend = permissionBackend; - - List<MenuItem> peopleItems = Lists.newArrayListWithExpectedSize(2); - if (canCreateServiceUser()) { - peopleItems.add(new MenuItem("Create Service User", "#/x/" + pluginName + "/create", "")); - } - if (canCreateServiceUser() || hasServiceUser()) { - peopleItems.add(new MenuItem("List Service Users", "#/x/" + pluginName + "/list", "")); - } - if (!peopleItems.isEmpty()) { - menuEntries.add(new MenuEntry("People", peopleItems)); - } - } - - private boolean canCreateServiceUser() { - if (userProvider.get().isIdentifiedUser()) { - IdentifiedUser user = userProvider.get().asIdentifiedUser(); - return permissionBackend - .user(user) - .testOrFalse(new PluginPermission(pluginName, CreateServiceUserCapability.ID)) - || permissionBackend.user(user).testOrFalse(ADMINISTRATE_SERVER); - } - return false; - } - - private boolean hasServiceUser() - throws PermissionBackendException, IOException, ConfigInvalidException, RestApiException { - try { - return !listServiceUsers.get().apply(new ConfigResource()).isEmpty(); - } catch (AuthException | OrmException e) { - return false; - } - } - - @Override - public List<MenuEntry> getEntries() { - return menuEntries; - } -}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ServiceUserResolver.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ServiceUserResolver.java index 686b6ba..e2f16a6 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ServiceUserResolver.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ServiceUserResolver.java
@@ -21,11 +21,11 @@ import com.google.gerrit.extensions.restapi.RestApiException; import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.AccountGroup; -import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.account.AccountCache; import com.google.gerrit.server.account.AccountResolver; +import com.google.gerrit.server.account.AccountResolver.UnresolvableAccountException; import com.google.gerrit.server.account.AccountState; import com.google.gerrit.server.account.GroupControl; import com.google.gerrit.server.account.GroupMembership; @@ -35,8 +35,6 @@ import com.google.gerrit.server.restapi.group.ListMembers; import com.google.gerrit.server.util.RequestContext; import com.google.gerrit.server.util.ThreadLocalRequestContext; -import com.google.gwtorm.server.OrmException; -import com.google.gwtorm.server.SchemaFactory; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; @@ -56,7 +54,6 @@ private final IdentifiedUser.GenericFactory genericUserFactory; private final Provider<GetServiceUser> getServiceUser; private final Provider<ListMembers> listMembers; - private final SchemaFactory<ReviewDb> schema; private final ThreadLocalRequestContext tl; private final AccountCache accountCache; private final GroupControl.Factory groupControlFactory; @@ -68,7 +65,6 @@ IdentifiedUser.GenericFactory genericUserFactory, Provider<GetServiceUser> getServiceUser, Provider<ListMembers> listMembers, - SchemaFactory<ReviewDb> schema, ThreadLocalRequestContext tl, AccountCache accountCache, GroupControl.Factory groupControlFactory, @@ -77,7 +73,6 @@ this.genericUserFactory = genericUserFactory; this.getServiceUser = getServiceUser; this.listMembers = listMembers; - this.schema = schema; this.tl = tl; this.accountCache = accountCache; this.groupControlFactory = groupControlFactory; @@ -85,103 +80,86 @@ } ServiceUserInfo getAsServiceUser(PersonIdent committerIdent) - throws ConfigInvalidException, IOException, OrmException, PermissionBackendException, - RestApiException { + throws ConfigInvalidException, IOException, PermissionBackendException, RestApiException { StringBuilder committer = new StringBuilder(); committer.append(committerIdent.getName()); committer.append(" <"); committer.append(committerIdent.getEmailAddress()); committer.append("> "); - Account account = resolver.find(committer.toString()); - if (account == null) { - return null; - } try { + Account account = resolver.resolve(committer.toString()).asUnique().getAccount(); return getServiceUser .get() .apply(new ServiceUserResource(genericUserFactory.create(account.getId()))); - } catch (ResourceNotFoundException e) { + } catch (ResourceNotFoundException | UnresolvableAccountException e) { return null; } } List<AccountInfo> listOwners(ServiceUserInfo serviceUser) - throws OrmException, MethodNotAllowedException, PermissionBackendException { + throws MethodNotAllowedException, PermissionBackendException { if (serviceUser.owner == null) { return Collections.emptyList(); } - try (ReviewDb db = schema.open()) { - RequestContext context = - new RequestContext() { - @Override - public CurrentUser getUser() { - return new CurrentUser() { + RequestContext context = + new RequestContext() { + @Override + public CurrentUser getUser() { + return new CurrentUser() { - @Override - public GroupMembership getEffectiveGroups() { - return new GroupMembership() { - @Override - public Set<AccountGroup.UUID> intersection( - Iterable<AccountGroup.UUID> groupIds) { - return null; - } + @Override + public GroupMembership getEffectiveGroups() { + return new GroupMembership() { + @Override + public Set<AccountGroup.UUID> intersection(Iterable<AccountGroup.UUID> groupIds) { + return null; + } - @Override - public Set<AccountGroup.UUID> getKnownGroups() { - return null; - } + @Override + public Set<AccountGroup.UUID> getKnownGroups() { + return null; + } - @Override - public boolean containsAnyOf(Iterable<AccountGroup.UUID> groupIds) { - return true; - } + @Override + public boolean containsAnyOf(Iterable<AccountGroup.UUID> groupIds) { + return true; + } - @Override - public boolean contains(AccountGroup.UUID groupId) { - return true; - } - }; - } + @Override + public boolean contains(AccountGroup.UUID groupId) { + return true; + } + }; + } - @Override - public Object getCacheKey() { - return null; - } - }; - } - - @Override - public Provider<ReviewDb> getReviewDbProvider() { - return new Provider<ReviewDb>() { - @Override - public ReviewDb get() { - return db; - } - }; - } - }; - RequestContext old = tl.setContext(context); - try { - GroupDescription.Basic group = groupResolver.parseId(serviceUser.owner.id); - GroupControl ctl = groupControlFactory.controlFor(group); - ListMembers lm = listMembers.get(); - GroupResource rsrc = new GroupResource(ctl); - lm.setRecursive(true); - List<AccountInfo> owners = new ArrayList<>(); - for (AccountInfo a : lm.apply(rsrc)) { - owners.add(a); - } - return owners; - } finally { - tl.setContext(old); + @Override + public Object getCacheKey() { + return null; + } + }; + } + }; + RequestContext old = tl.setContext(context); + try { + GroupDescription.Basic group = groupResolver.parseId(serviceUser.owner.id); + GroupControl ctl = groupControlFactory.controlFor(group); + ListMembers lm = listMembers.get(); + GroupResource rsrc = new GroupResource(ctl); + lm.setRecursive(true); + List<AccountInfo> owners = new ArrayList<>(); + for (AccountInfo a : lm.apply(rsrc)) { + owners.add(a); } + return owners; + } finally { + tl.setContext(old); } } List<AccountInfo> listActiveOwners(ServiceUserInfo serviceUser) - throws OrmException, MethodNotAllowedException, PermissionBackendException { + throws MethodNotAllowedException, PermissionBackendException { List<AccountInfo> activeOwners = new ArrayList<>(); for (AccountInfo owner : listOwners(serviceUser)) { Optional<AccountState> accountState = accountCache.get(new Account.Id(owner._accountId));
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/SshKeyValidator.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/SshKeyValidator.java new file mode 100644 index 0000000..9a95db1 --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/SshKeyValidator.java
@@ -0,0 +1,51 @@ +// Copyright (C) 2019 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 java.util.regex.Matcher; +import java.util.regex.Pattern; + +class SshKeyValidator { + + private static final String OPENSSH_KEY_PREFIXES[] = { + "ssh-ed25519", "ssh-rsa", "ssh-dss", "ecdsa-sha2-" + }; + private static final Pattern RFC_KEY_FORMAT_PATTERN = + Pattern.compile( + "(?s)^-{4,5}\\s?BEGIN.* PUBLIC KEY\\s?-{4,5}.+-{4,5}\\s?END.* PUBLIC KEY\\s?-{4,5}$"); + + static boolean validateFormat(String sshKey) { + if (validateRfcFormat(sshKey)) { + return true; + } + + return validateOpenSshFormat(sshKey); + } + + private static boolean validateOpenSshFormat(String sshKey) { + for (String prefix : OPENSSH_KEY_PREFIXES) { + if (sshKey.startsWith(prefix)) { + return true; + } + } + + return false; + } + + private static boolean validateRfcFormat(String sshKey) { + Matcher matcher = RFC_KEY_FORMAT_PATTERN.matcher(sshKey); + return matcher.find(); + } +}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/SshKeys.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/SshKeys.java index 7858b12..70833ef 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/SshKeys.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/SshKeys.java
@@ -19,7 +19,6 @@ import com.google.gerrit.extensions.restapi.IdString; import com.google.gerrit.extensions.restapi.ResourceNotFoundException; import com.google.gerrit.extensions.restapi.RestView; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; @@ -49,7 +48,7 @@ @Override public ServiceUserResource.SshKey parse(ServiceUserResource parent, IdString id) - throws ResourceNotFoundException, OrmException, IOException, ConfigInvalidException { + throws ResourceNotFoundException, IOException, ConfigInvalidException { return new ServiceUserResource.SshKey(sshKeys.get().parse(parent.getUser(), id)); }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ValidateServiceUserCommits.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ValidateServiceUserCommits.java index ebf072b..d8c2176 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ValidateServiceUserCommits.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ValidateServiceUserCommits.java
@@ -23,7 +23,6 @@ import com.google.gerrit.server.git.validators.CommitValidationListener; import com.google.gerrit.server.git.validators.CommitValidationMessage; import com.google.gerrit.server.permissions.PermissionBackendException; -import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Singleton; import com.googlesource.gerrit.plugins.serviceuser.GetServiceUser.ServiceUserInfo; @@ -75,7 +74,6 @@ } } } catch (IOException - | OrmException | ConfigInvalidException | PermissionBackendException | RestApiException e) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/AccountCapabilities.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/AccountCapabilities.java deleted file mode 100644 index a6f7f84..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/AccountCapabilities.java +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright (C) 2014 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.client; - -import com.google.gerrit.plugin.client.rpc.RestApi; -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.user.client.rpc.AsyncCallback; - -/** Capabilities the caller has from {@code /accounts/self/capabilities}. */ -public class AccountCapabilities extends JavaScriptObject { - public static void all(AsyncCallback<AccountCapabilities> cb, String... filter) { - new RestApi("/accounts/self/capabilities").addParameter("q", filter).get(cb); - } - - protected AccountCapabilities() {} - - public final native boolean canPerform(String name) /*-{ return this[name] ? true : false; }-*/; -}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/AccountInfo.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/AccountInfo.java deleted file mode 100644 index ffc1953..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/AccountInfo.java +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright (C) 2014 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.client; - -import com.google.gwt.core.client.JavaScriptObject; - -public class AccountInfo extends JavaScriptObject { - public final native int _account_id() /*-{ return this._account_id || 0; }-*/; - - public final native String name() /*-{ return this.name; }-*/; - - public final native String username() /*-{ return this.username; }-*/; - - public final native String email() /*-{ return this.email; }-*/; - - protected AccountInfo() {} -}
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 deleted file mode 100644 index 6291319..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ConfigInfo.java +++ /dev/null
@@ -1,85 +0,0 @@ -// Copyright (C) 2014 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.client; - -import com.google.gerrit.client.rpc.NativeMap; -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.core.client.JsArrayString; -import java.util.List; - -public class ConfigInfo extends JavaScriptObject { - final native String getInfoMessage() /*-{ return this.info }-*/; - - final native String getOnSuccessMessage() /*-{ return this.on_success }-*/; - - final native boolean getAllowEmail() /*-{ return this.allow_email ? true : false; }-*/; - - final native boolean - getAllowHttpPassword() /*-{ return this.allow_http_password ? true : false; }-*/; - - final native boolean getAllowOwner() /*-{ return this.allow_owner ? true : false; }-*/; - - 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; }-*/; - - final native void setAllowEmail(boolean s) /*-{ this.allow_email = s; }-*/; - - final native void setAllowHttpPassword(boolean s) /*-{ this.allow_http_password = s; }-*/; - - final native void setAllowOwner(boolean s) /*-{ this.allow_owner = s; }-*/; - - final native void setCreateNotes(boolean s) /*-{ this.create_notes = s; }-*/; - - final native void setCreateNotesAsync(boolean s) /*-{ this.create_notes_async = s; }-*/; - - final void setBlockedNames(List<String> blockedNames) { - initBlockedNames(); - for (String n : blockedNames) { - addBlockedName(n); - } - } - - 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; - } - - protected ConfigInfo() {} -}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/CreateServiceUserScreen.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/CreateServiceUserScreen.java deleted file mode 100644 index c57eb5f..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/CreateServiceUserScreen.java +++ /dev/null
@@ -1,259 +0,0 @@ -// 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.client; - -import com.google.gerrit.plugin.client.Plugin; -import com.google.gerrit.plugin.client.rpc.RestApi; -import com.google.gerrit.plugin.client.screen.Screen; -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.google.gwt.user.client.ui.Button; -import com.google.gwt.user.client.ui.DialogBox; -import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.HorizontalPanel; -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.Panel; -import com.google.gwt.user.client.ui.TextArea; -import com.google.gwt.user.client.ui.TextBox; -import com.google.gwt.user.client.ui.VerticalPanel; - -public class CreateServiceUserScreen extends VerticalPanel { - static class Factory implements Screen.EntryPoint { - @Override - public void onLoad(Screen screen) { - screen.setPageTitle("Create Service User"); - screen.show(new CreateServiceUserScreen()); - } - } - - private TextBox usernameTxt; - private TextBox emailTxt; - private TextArea sshKeyTxt; - private String onSuccessMessage; - - CreateServiceUserScreen() { - setStyleName("serviceuser-panel"); - - Panel usernamePanel = new VerticalPanel(); - usernamePanel.add(new Label("Username:")); - usernameTxt = - new TextBox() { - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - if (event.getTypeInt() == Event.ONPASTE) { - Scheduler.get() - .scheduleDeferred( - new ScheduledCommand() { - @Override - public void execute() { - if (getValue().trim().length() != 0) { - setEnabled(true); - } - } - }); - } - } - }; - usernameTxt.addKeyPressHandler( - new KeyPressHandler() { - @Override - public void onKeyPress(final KeyPressEvent event) { - event.stopPropagation(); - } - }); - usernameTxt.sinkEvents(Event.ONPASTE); - usernameTxt.setVisibleLength(40); - usernamePanel.add(usernameTxt); - add(usernamePanel); - - Panel sshKeyPanel = new VerticalPanel(); - sshKeyPanel.add(new Label("Public SSH Key:")); - sshKeyPanel.add(new SshKeyHelpPanel()); - sshKeyTxt = new TextArea(); - sshKeyTxt.addKeyPressHandler( - new KeyPressHandler() { - @Override - public void onKeyPress(final KeyPressEvent event) { - event.stopPropagation(); - } - }); - sshKeyTxt.setVisibleLines(12); - sshKeyTxt.setCharacterWidth(80); - sshKeyTxt.getElement().setPropertyBoolean("spellcheck", false); - sshKeyPanel.add(sshKeyTxt); - add(sshKeyPanel); - - HorizontalPanel buttons = new HorizontalPanel(); - add(buttons); - - final Button createButton = new Button("Create"); - createButton.addStyleName("serviceuser-createButton"); - createButton.addClickHandler( - new ClickHandler() { - @Override - public void onClick(final ClickEvent event) { - doCreate(); - } - }); - buttons.add(createButton); - createButton.setEnabled(false); - new OnEditEnabler(createButton, usernameTxt); - - usernameTxt.setFocus(true); - createButton.setEnabled(false); - - new RestApi("config") - .id("server") - .view(Plugin.get().getPluginName(), "config") - .get( - new AsyncCallback<ConfigInfo>() { - @Override - public void onSuccess(ConfigInfo info) { - onSuccessMessage = info.getOnSuccessMessage(); - - String infoMessage = info.getInfoMessage(); - if (infoMessage != null && !"".equals(infoMessage)) { - insert(new HTML(infoMessage), 0); - } - - if (info.getAllowEmail()) { - Panel emailPanel = new VerticalPanel(); - emailPanel.add(new Label("Email:")); - emailTxt = - new TextBox() { - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - if (event.getTypeInt() == Event.ONPASTE) { - Scheduler.get() - .scheduleDeferred( - new ScheduledCommand() { - @Override - public void execute() { - if (getValue().trim().length() != 0) { - setEnabled(true); - } - } - }); - } - } - }; - emailTxt.addKeyPressHandler( - new KeyPressHandler() { - @Override - public void onKeyPress(final KeyPressEvent event) { - event.stopPropagation(); - } - }); - emailTxt.sinkEvents(Event.ONPASTE); - emailTxt.setVisibleLength(40); - emailPanel.add(emailTxt); - insert(emailPanel, 2); - } - } - - @Override - public void onFailure(Throwable caught) { - // never invoked - } - }); - } - - private void doCreate() { - final String username = usernameTxt.getValue().trim(); - String sshKey = sshKeyTxt.getText(); - if (sshKey != null) { - sshKey = sshKey.trim(); - } - - ServiceUserInput in = ServiceUserInput.create(); - in.ssh_key(sshKey); - if (emailTxt != null) { - in.email(emailTxt.getValue().trim()); - } - new RestApi("config") - .id("server") - .view("serviceuser", "serviceusers") - .id(username) - .post( - in, - new AsyncCallback<JavaScriptObject>() { - - @Override - public void onSuccess(JavaScriptObject result) { - clearForm(); - Plugin.get().go("/x/" + Plugin.get().getName() + "/user/" + username); - - final DialogBox successDialog = new DialogBox(); - successDialog.setText("Service User Created"); - successDialog.setAnimationEnabled(true); - - Panel p = new VerticalPanel(); - p.setStyleName("serviceuser-panel"); - p.add(new Label("The service user '" + username + "' was created.")); - Button okButton = new Button("OK"); - okButton.addClickHandler( - new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - successDialog.hide(); - } - }); - - if (onSuccessMessage != null && !"".equals(onSuccessMessage)) { - p.add(new HTML(onSuccessMessage)); - } - - p.add(okButton); - successDialog.add(p); - - successDialog.center(); - successDialog.show(); - } - - @Override - public void onFailure(Throwable caught) {} - }); - } - - private void clearForm() { - usernameTxt.setValue(""); - if (emailTxt != null) { - emailTxt.setValue(""); - } - sshKeyTxt.setValue(""); - } - - private static class ServiceUserInput extends JavaScriptObject { - final native void ssh_key(String s) /*-{ this.ssh_key = s; }-*/; - - final native void email(String e) /*-{ this.email = e; }-*/; - - static ServiceUserInput create() { - ServiceUserInput g = (ServiceUserInput) createObject(); - return g; - } - - protected ServiceUserInput() {} - } -}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/EditableValue.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/EditableValue.java deleted file mode 100644 index 0ab741f..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/EditableValue.java +++ /dev/null
@@ -1,169 +0,0 @@ -// Copyright (C) 2014 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.client; - -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.user.client.ui.Anchor; -import com.google.gwt.user.client.ui.Button; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.Image; -import com.google.gwt.user.client.ui.InlineLabel; -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.Widget; -import com.google.gwtexpui.globalkey.client.NpTextBox; - -public abstract class EditableValue extends FlowPanel { - private final Widget labelWidget; - private final Image edit; - private final NpTextBox input; - private final Button save; - private final Button cancel; - private Image warning; - - EditableValue(String serviceUser, String value) { - this(serviceUser, value, null); - } - - EditableValue(final String serviceUser, String value, String href) { - if (href != null) { - labelWidget = new Anchor(value, href); - } else { - labelWidget = new InlineLabel(value); - } - edit = new Image(ServiceUserPlugin.RESOURCES.edit()); - edit.addStyleName("serviceuser-editButton"); - edit.setTitle("Edit"); - - input = new NpTextBox(); - input.setVisibleLength(25); - input.setValue(value); - input.setVisible(false); - save = new Button(); - save.setText("Save"); - save.setVisible(false); - save.setEnabled(false); - cancel = new Button(); - cancel.setText("Cancel"); - cancel.setVisible(false); - - OnEditEnabler e = new OnEditEnabler(save); - e.listenTo(input); - - edit.addClickHandler( - new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - labelWidget.setVisible(false); - edit.setVisible(false); - input.setVisible(true); - input.setFocus(true); - save.setVisible(true); - if (warning != null) { - warning.setVisible(true); - } - cancel.setVisible(true); - } - }); - save.addClickHandler( - new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - save.setEnabled(false); - save(serviceUser, input.getValue().trim()); - } - }); - input.addKeyPressHandler( - new KeyPressHandler() { - @Override - public void onKeyPress(KeyPressEvent event) { - if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) { - save.setEnabled(false); - save(serviceUser, input.getValue().trim()); - } else if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ESCAPE) { - cancel(); - } - } - }); - cancel.addClickHandler( - new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - cancel(); - } - }); - - add(labelWidget); - add(edit); - add(input); - add(save); - add(cancel); - } - - private void cancel() { - labelWidget.setVisible(true); - edit.setVisible(true); - input.setVisible(false); - if (labelWidget instanceof Label) { - input.setValue(((Label) labelWidget).getText()); - } else { - input.setValue(((Anchor) labelWidget).getText()); - } - save.setVisible(false); - save.setEnabled(false); - if (warning != null) { - warning.setVisible(false); - } - cancel.setVisible(false); - } - - public void setWarning(String msg) { - if (warning == null) { - warning = new Image(ServiceUserPlugin.RESOURCES.warning()); - insert(warning, getWidgetIndex(save)); - warning.setVisible(save.isVisible()); - } - warning.setTitle(msg); - } - - protected void updateValue(String newValue) { - if (labelWidget instanceof Label) { - ((Label) labelWidget).setText(newValue); - } else { - ((Anchor) labelWidget).setText(newValue); - } - labelWidget.setVisible(true); - edit.setVisible(true); - input.setVisible(false); - input.setValue(newValue); - save.setVisible(false); - if (warning != null) { - warning.setVisible(false); - } - save.setEnabled(false); - cancel.setVisible(false); - } - - protected void updateHref(String newHref) { - if (labelWidget instanceof Anchor) { - ((Anchor) labelWidget).setHref(newHref); - } - } - - protected abstract void save(String serviceUser, final String newValue); -}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/GroupInfo.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/GroupInfo.java deleted file mode 100644 index b398092..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/GroupInfo.java +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright (C) 2014 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.client; - -import com.google.gwt.core.client.JavaScriptObject; - -public class GroupInfo extends JavaScriptObject { - public final native String name() /*-{ return this.name; }-*/; - - public final native String url() /*-{ return this.url; }-*/; - - protected GroupInfo() {} -}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/HttpPasswordInput.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/HttpPasswordInput.java deleted file mode 100644 index 5549597..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/HttpPasswordInput.java +++ /dev/null
@@ -1,27 +0,0 @@ -// 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.googlesource.gerrit.plugins.serviceuser.client; - -import com.google.gwt.core.client.JavaScriptObject; - -public class HttpPasswordInput extends JavaScriptObject { - final native void generate(boolean g) /*-{ if (g) this.generate = g; }-*/; - - public static HttpPasswordInput create() { - return createObject().cast(); - } - - protected HttpPasswordInput() {} -}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/OnEditEnabler.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/OnEditEnabler.java deleted file mode 100644 index 815962c..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/OnEditEnabler.java +++ /dev/null
@@ -1,188 +0,0 @@ -// Copyright (C) 2010 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.client; - -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.event.dom.client.ChangeEvent; -import com.google.gwt.event.dom.client.ChangeHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.event.dom.client.MouseUpEvent; -import com.google.gwt.event.dom.client.MouseUpHandler; -import com.google.gwt.event.logical.shared.ValueChangeEvent; -import com.google.gwt.event.logical.shared.ValueChangeHandler; -import com.google.gwt.event.shared.GwtEvent; -import com.google.gwt.user.client.ui.CheckBox; -import com.google.gwt.user.client.ui.FocusWidget; -import com.google.gwt.user.client.ui.ListBox; -import com.google.gwt.user.client.ui.TextBoxBase; -import com.google.gwt.user.client.ui.ValueBoxBase; -import java.util.HashMap; -import java.util.Map; - -/** - * Enables a FocusWidget (e.g. a Button) if an edit is detected from any registered input widget. - */ -public class OnEditEnabler - implements KeyPressHandler, - KeyDownHandler, - MouseUpHandler, - ChangeHandler, - ValueChangeHandler<Object> { - - private final FocusWidget widget; - private Map<TextBoxBase, String> strings = new HashMap<>(); - private String originalValue; - - // The first parameter to the constructors must be the FocusWidget to enable, - // subsequent parameters are widgets to listenTo. - - public OnEditEnabler(final FocusWidget w, final TextBoxBase tb) { - this(w); - originalValue = tb.getValue().trim(); - listenTo(tb); - } - - public OnEditEnabler(final FocusWidget w, final ListBox lb) { - this(w); - listenTo(lb); - } - - public OnEditEnabler(final FocusWidget w, final CheckBox cb) { - this(w); - listenTo(cb); - } - - public OnEditEnabler(final FocusWidget w) { - widget = w; - } - - // Register input widgets to be listened to - - public void listenTo(final TextBoxBase tb) { - strings.put(tb, tb.getText().trim()); - tb.addKeyPressHandler(this); - - // Is there another way to capture middle button X11 pastes in browsers - // which do not yet support ONPASTE events (Firefox)? - tb.addMouseUpHandler(this); - - // Resetting the "original text" on focus ensures that we are - // up to date with non-user updates of the text (calls to - // setText()...) and also up to date with user changes which - // occured after enabling "widget". - tb.addFocusHandler( - new FocusHandler() { - @Override - public void onFocus(FocusEvent event) { - strings.put(tb, tb.getText().trim()); - } - }); - - // CTRL-V Pastes in Chrome seem only detectable via BrowserEvents or - // KeyDownEvents, the latter is better. - tb.addKeyDownHandler(this); - } - - public void listenTo(final ListBox lb) { - lb.addChangeHandler(this); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - public void listenTo(final CheckBox cb) { - cb.addValueChangeHandler((ValueChangeHandler) this); - } - - // Handlers - - @Override - public void onKeyPress(final KeyPressEvent e) { - on(e); - } - - @Override - public void onKeyDown(final KeyDownEvent e) { - on(e); - } - - @Override - public void onMouseUp(final MouseUpEvent e) { - on(e); - } - - @Override - public void onChange(final ChangeEvent e) { - on(e); - } - - @SuppressWarnings("rawtypes") - @Override - public void onValueChange(final ValueChangeEvent e) { - on(e); - } - - private void on(final GwtEvent<?> e) { - if (widget.isEnabled() - || !(e.getSource() instanceof FocusWidget) - || !((FocusWidget) e.getSource()).isEnabled()) { - if (e.getSource() instanceof ValueBoxBase) { - final TextBoxBase box = ((TextBoxBase) e.getSource()); - Scheduler.get() - .scheduleDeferred( - new ScheduledCommand() { - @Override - public void execute() { - if (box.getValue().trim().equals(originalValue)) { - widget.setEnabled(false); - } - } - }); - } - return; - } - - if (e.getSource() instanceof TextBoxBase) { - onTextBoxBase((TextBoxBase) e.getSource()); - } else { - // For many widgets, we can assume that a change is an edit. If - // a widget does not work that way, it should be special cased - // above. - widget.setEnabled(true); - } - } - - private void onTextBoxBase(final TextBoxBase tb) { - // The text appears to not get updated until the handlers complete. - Scheduler.get() - .scheduleDeferred( - new ScheduledCommand() { - @Override - public void execute() { - String orig = strings.get(tb); - if (orig == null) { - orig = ""; - } - if (!orig.equals(tb.getText().trim())) { - widget.setEnabled(true); - } - } - }); - } -}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserInfo.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserInfo.java index 96c543d..47723f1 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserInfo.java +++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserInfo.java
@@ -14,34 +14,28 @@ package com.googlesource.gerrit.plugins.serviceuser.client; -import com.google.gwt.core.client.JavaScriptObject; +import com.google.gerrit.extensions.common.AccountInfo; +import com.google.gerrit.extensions.common.GroupInfo; -public class ServiceUserInfo extends JavaScriptObject { +public class ServiceUserInfo { public final String getDisplayName() { - if (created_by().username() != null) { - return created_by().username(); + if (created_by.username != null) { + return created_by.username; } - if (created_by()._account_id() != -1) { - return Integer.toString(created_by()._account_id()); + if (created_by._accountId != -1) { + return Integer.toString(created_by._accountId); } return "N/A"; } - public final native int _account_id() /*-{ return this._account_id || 0; }-*/; - - public final native String name() /*-{ return this.name; }-*/; - - public final native String username() /*-{ return this.username; }-*/; - - public final native String email() /*-{ return this.email; }-*/; - - public final native AccountInfo created_by() /*-{ return this.created_by; }-*/; - - public final native String created_at() /*-{ return this.created_at; }-*/; - - public final native boolean active() /*-{ return this.inactive ? false : true; }-*/; - - public final native GroupInfo owner() /*-{ return this.owner; }-*/; + public int _account_id; + public String name; + public String username; + public String email; + public AccountInfo created_by; + public String created_at; + public boolean active; + public GroupInfo owner; protected ServiceUserInfo() {} }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserListScreen.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserListScreen.java deleted file mode 100644 index 5c30bea..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserListScreen.java +++ /dev/null
@@ -1,110 +0,0 @@ -// Copyright (C) 2014 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.client; - -import com.google.gerrit.client.rpc.NativeMap; -import com.google.gerrit.plugin.client.Plugin; -import com.google.gerrit.plugin.client.rpc.RestApi; -import com.google.gerrit.plugin.client.screen.Screen; -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.google.gwt.user.client.ui.Anchor; -import com.google.gwt.user.client.ui.FlexTable; -import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter; -import com.google.gwt.user.client.ui.InlineHyperlink; -import com.google.gwt.user.client.ui.VerticalPanel; - -public class ServiceUserListScreen extends VerticalPanel { - static class Factory implements Screen.EntryPoint { - @Override - public void onLoad(Screen screen) { - screen.setPageTitle("Service Users"); - screen.show(new ServiceUserListScreen()); - } - } - - ServiceUserListScreen() { - setStyleName("serviceuser-panel"); - - new RestApi("config") - .id("server") - .view(Plugin.get().getPluginName(), "serviceusers") - .get( - NativeMap.copyKeysIntoChildren( - "username", - new AsyncCallback<NativeMap<ServiceUserInfo>>() { - @Override - public void onSuccess(NativeMap<ServiceUserInfo> info) { - display(info); - } - - @Override - public void onFailure(Throwable caught) { - // never invoked - } - })); - } - - private void display(NativeMap<ServiceUserInfo> info) { - int columns = 7; - FlexTable t = new FlexTable(); - t.setStyleName("serviceuser-serviceUserTable"); - FlexCellFormatter fmt = t.getFlexCellFormatter(); - for (int c = 0; c < columns; c++) { - fmt.addStyleName(0, c, "dataHeader"); - fmt.addStyleName(0, c, "topMostCell"); - } - fmt.addStyleName(0, 0, "leftMostCell"); - - t.setText(0, 0, "Username"); - t.setText(0, 1, "Full Name"); - t.setText(0, 2, "Email"); - t.setText(0, 3, "Owner"); - t.setText(0, 4, "Created By"); - t.setText(0, 5, "Created At"); - t.setText(0, 6, "Account State"); - - int row = 1; - for (String username : info.keySet()) { - ServiceUserInfo a = info.get(username); - - for (int c = 0; c < columns; c++) { - fmt.addStyleName(row, c, "dataCell"); - fmt.addStyleName(row, 0, "leftMostCell"); - } - - t.setWidget( - row, - 0, - new InlineHyperlink(username, "/x/" + Plugin.get().getName() + "/user/" + username)); - t.setText(row, 1, a.name()); - t.setText(row, 2, a.email()); - - if (a.owner() != null) { - if (a.owner().url() != null) { - t.setWidget(row, 3, new Anchor(a.owner().name(), a.owner().url())); - } else { - t.setText(row, 3, a.owner().name()); - } - } - - t.setText(row, 4, a.getDisplayName()); - t.setText(row, 5, a.created_at()); - t.setText(row, 6, !a.active() ? "Inactive" : ""); - row++; - } - - add(t); - } -}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserPlugin.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserPlugin.java deleted file mode 100644 index 393963d..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserPlugin.java +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright (C) 2014 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.client; - -import com.google.gerrit.client.Resources; -import com.google.gerrit.plugin.client.Plugin; -import com.google.gerrit.plugin.client.PluginEntryPoint; -import com.google.gwt.core.client.GWT; - -public class ServiceUserPlugin extends PluginEntryPoint { - public static final Resources RESOURCES = GWT.create(Resources.class); - - @Override - public void onPluginLoad() { - Plugin.get().screen("create", new CreateServiceUserScreen.Factory()); - Plugin.get().screen("settings", new ServiceUserSettingsScreen.Factory()); - Plugin.get().screen("list", new ServiceUserListScreen.Factory()); - Plugin.get().screenRegex("user/(.*)", new ServiceUserScreen.Factory()); - } -}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserScreen.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserScreen.java deleted file mode 100644 index 78cb65e..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserScreen.java +++ /dev/null
@@ -1,371 +0,0 @@ -// Copyright (C) 2014 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.client; - -import com.google.gerrit.client.rpc.NativeString; -import com.google.gerrit.plugin.client.Plugin; -import com.google.gerrit.plugin.client.rpc.NoContent; -import com.google.gerrit.plugin.client.rpc.RestApi; -import com.google.gerrit.plugin.client.screen.Screen; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.logical.shared.ValueChangeEvent; -import com.google.gwt.event.logical.shared.ValueChangeHandler; -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.google.gwt.user.client.ui.Anchor; -import com.google.gwt.user.client.ui.FlexTable; -import com.google.gwt.user.client.ui.HorizontalPanel; -import com.google.gwt.user.client.ui.Image; -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.ToggleButton; -import com.google.gwt.user.client.ui.VerticalPanel; -import com.google.gwt.user.client.ui.Widget; -import com.google.gwtexpui.clippy.client.CopyableLabel; - -public class ServiceUserScreen extends VerticalPanel { - static class Factory implements Screen.EntryPoint { - @Override - public void onLoad(Screen screen) { - screen.setPageTitle("Service User " + screen.getToken(1)); - screen.show(new ServiceUserScreen(screen.getToken(1))); - } - } - - ServiceUserScreen(final String serviceUser) { - setStyleName("serviceuser-panel"); - - new RestApi("config") - .id("server") - .view(Plugin.get().getPluginName(), "serviceusers") - .id(serviceUser) - .get( - new AsyncCallback<ServiceUserInfo>() { - @Override - public void onSuccess(final ServiceUserInfo serviceUserInfo) { - new RestApi("config") - .id("server") - .view(Plugin.get().getPluginName(), "config") - .get( - new AsyncCallback<ConfigInfo>() { - @Override - public void onSuccess(final ConfigInfo configInfo) { - AccountCapabilities.all( - new AsyncCallback<AccountCapabilities>() { - @Override - public void onSuccess(AccountCapabilities ac) { - boolean isAdmin = ac.canPerform("administrateServer"); - display( - serviceUserInfo, - configInfo.getAllowEmail() || isAdmin, - configInfo.getAllowOwner() || isAdmin, - configInfo.getAllowHttpPassword() || isAdmin); - } - - @Override - public void onFailure(Throwable caught) { - // never invoked - } - }, - "administrateServer"); - } - - @Override - public void onFailure(Throwable caught) { - // never invoked - } - }); - } - - @Override - public void onFailure(Throwable caught) { - // never invoked - } - }); - } - - private void display( - ServiceUserInfo info, boolean allowEmail, boolean allowOwner, boolean allowHttpPassword) { - MyTable t = new MyTable(); - t.setStyleName("serviceuser-serviceUserInfoTable"); - t.addRow("Account State", createActiveToggle(info)); - t.addRow("Username", info.username()); - t.addRow( - "Full Name", - new EditableValue(info.username(), info.name()) { - @Override - protected void save(String serviceUser, final String newValue) { - new RestApi("config") - .id("server") - .view(Plugin.get().getPluginName(), "serviceusers") - .id(serviceUser) - .view("name") - .put( - newValue, - new AsyncCallback<NativeString>() { - @Override - public void onSuccess(NativeString result) { - updateValue(newValue); - } - - @Override - public void onFailure(Throwable caught) { - // never invoked - } - }); - } - }); - if (allowEmail) { - t.addRow( - "Email Address", - new EditableValue(info.username(), info.email()) { - @Override - protected void save(String serviceUser, final String newValue) { - new RestApi("config") - .id("server") - .view(Plugin.get().getPluginName(), "serviceusers") - .id(serviceUser) - .view("email") - .put( - newValue, - new AsyncCallback<NativeString>() { - @Override - public void onSuccess(NativeString result) { - updateValue(newValue); - } - - @Override - public void onFailure(Throwable caught) { - // never invoked - } - }); - } - }); - } else { - t.addRow("Email Address", info.email()); - } - t.addRow("HTTP Password", createHttpPasswordWidget(info.username(), allowHttpPassword)); - t.addRow("Owner Group", createOwnerWidget(info, allowOwner)); - t.addRow("Created By", info.getDisplayName()); - t.addRow("Created At", info.created_at()); - add(t); - - add(new SshPanel(info.username())); - } - - private ToggleButton createActiveToggle(final ServiceUserInfo info) { - final ToggleButton activeToggle = new ToggleButton(); - activeToggle.setStyleName("serviceuser-toggleButton"); - activeToggle.setVisible(false); - activeToggle.setValue(true); - activeToggle.setText("Active"); - activeToggle.setValue(false); - activeToggle.setText("Inactive"); - activeToggle.setValue(info.active()); - activeToggle.setVisible(true); - - activeToggle.addValueChangeHandler( - new ValueChangeHandler<Boolean>() { - @Override - public void onValueChange(ValueChangeEvent<Boolean> event) { - if (event.getValue()) { - new RestApi("config") - .id("server") - .view(Plugin.get().getPluginName(), "serviceusers") - .id(info.username()) - .view("active") - .put( - new AsyncCallback<NoContent>() { - @Override - public void onSuccess(NoContent result) {} - - @Override - public void onFailure(Throwable caught) { - // never invoked - } - }); - } else { - new RestApi("config") - .id("server") - .view(Plugin.get().getPluginName(), "serviceusers") - .id(info.username()) - .view("active") - .delete( - new AsyncCallback<NoContent>() { - @Override - public void onSuccess(NoContent result) {} - - @Override - public void onFailure(Throwable caught) { - // never invoked - } - }); - } - } - }); - - return activeToggle; - } - - private Widget createHttpPasswordWidget(final String serviceUser, boolean allowHttpPassword) { - if (allowHttpPassword) { - HorizontalPanel p = new HorizontalPanel(); - final CopyableLabel label = new CopyableLabel(""); - label.setVisible(false); - p.add(label); - - // The redNot icon is only used as temporary measure until gerrit core - // provides a better icon that symbolizes "clear". - final Image delete = new Image(ServiceUserPlugin.RESOURCES.redNot()); - delete.addStyleName("serviceuser-deleteButton"); - delete.setTitle("Clear HTTP password"); - delete.addClickHandler( - new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - new RestApi("config") - .id("server") - .view(Plugin.get().getPluginName(), "serviceusers") - .id(serviceUser) - .view("password.http") - .delete( - new AsyncCallback<NoContent>() { - @Override - public void onSuccess(NoContent noContent) { - label.setText(""); - label.setVisible(false); - delete.setVisible(false); - } - - @Override - public void onFailure(Throwable caught) { - // never invoked - } - }); - } - }); - delete.setVisible(true); - p.add(delete); - - Image generate = new Image(ServiceUserPlugin.RESOURCES.gear()); - generate.addStyleName("serviceuser-generateButton"); - generate.setTitle("Generate new HTTP password"); - generate.addClickHandler( - new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - HttpPasswordInput in = HttpPasswordInput.create(); - in.generate(true); - new RestApi("config") - .id("server") - .view(Plugin.get().getPluginName(), "serviceusers") - .id(serviceUser) - .view("password.http") - .put( - in, - new AsyncCallback<NativeString>() { - @Override - public void onSuccess(NativeString newPassword) { - label.setText(newPassword.asString()); - label.setVisible(true); - delete.setVisible(true); - } - - @Override - public void onFailure(Throwable caught) { - // never invoked - } - }); - } - }); - p.add(generate); - return p; - } - return new CopyableLabel(""); - } - - private Widget createOwnerWidget(ServiceUserInfo info, boolean allowOwner) { - if (allowOwner) { - EditableValue ownerWidget = - new EditableValue( - info.username(), - info.owner() != null ? info.owner().name() : "", - info.owner() != null ? info.owner().url() : null) { - @Override - protected void save(String serviceUser, final String newValue) { - new RestApi("config") - .id("server") - .view(Plugin.get().getPluginName(), "serviceusers") - .id(serviceUser) - .view("owner") - .put( - newValue, - new AsyncCallback<GroupInfo>() { - @Override - public void onSuccess(GroupInfo result) { - updateValue(result != null ? result.name() : ""); - updateHref(result != null ? result.url() : ""); - Plugin.get().refresh(); - } - - @Override - public void onFailure(Throwable caught) { - // never invoked - } - }); - } - }; - StringBuilder ownerWarning = new StringBuilder(); - ownerWarning.append("If "); - ownerWarning.append( - info.owner() != null ? "the owner group is changed" : "an owner group is set"); - ownerWarning.append(" only members of the "); - ownerWarning.append(info.owner() != null ? "new " : ""); - ownerWarning.append("owner group can see and administrate" + " the service user."); - if (info.owner() != null) { - ownerWarning.append( - " If the owner group is removed only the" - + " creator of the service user can see and administrate" - + " the service user."); - } else { - ownerWarning.append( - " The creator of the service user can no" - + " longer see and administrate the service user if she/he" - + " is not member of the owner group."); - } - ownerWidget.setWarning(ownerWarning.toString()); - return ownerWidget; - } - if (info.owner() != null && info.owner().url() != null) { - return new Anchor(info.owner().name(), info.owner().url()); - } - return new Label(info.owner() != null ? info.owner().name() : ""); - } - - private static class MyTable extends FlexTable { - private static int row = 0; - - private void addRow(String label, String value) { - setWidget(row, 0, new Label(label + ":")); - setWidget(row, 1, new Label(value)); - row++; - } - - private void addRow(String label, Widget w) { - setWidget(row, 0, new Label(label + ":")); - setWidget(row, 1, w); - row++; - } - } -}
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 deleted file mode 100644 index 1755cda..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserSettingsScreen.java +++ /dev/null
@@ -1,268 +0,0 @@ -// Copyright (C) 2014 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.client; - -import com.google.gerrit.plugin.client.Plugin; -import com.google.gerrit.plugin.client.rpc.RestApi; -import com.google.gerrit.plugin.client.screen.Screen; -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.event.logical.shared.ValueChangeEvent; -import com.google.gwt.event.logical.shared.ValueChangeHandler; -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.google.gwt.user.client.ui.Button; -import com.google.gwt.user.client.ui.CheckBox; -import com.google.gwt.user.client.ui.HorizontalPanel; -import com.google.gwt.user.client.ui.Image; -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.Panel; -import com.google.gwt.user.client.ui.TextArea; -import com.google.gwt.user.client.ui.VerticalPanel; - -public class ServiceUserSettingsScreen extends VerticalPanel { - static class Factory implements Screen.EntryPoint { - @Override - public void onLoad(Screen screen) { - screen.setPageTitle("Service User Administration"); - screen.show(new ServiceUserSettingsScreen()); - } - } - - private TextArea infoMsgTxt; - private TextArea onSuccessMsgTxt; - private CheckBox allowEmailCheckBox; - private CheckBox allowHttpPasswordCheckBox; - private CheckBox allowOwnerCheckBox; - private CheckBox createNotesCheckBox; - private CheckBox createNotesAsyncCheckBox; - private StringListPanel blockedUsernamesPanel; - private StringListPanel groupsPanel; - private Button saveButton; - - ServiceUserSettingsScreen() { - setStyleName("serviceuser-panel"); - - new RestApi("config") - .id("server") - .view(Plugin.get().getPluginName(), "config") - .get( - new AsyncCallback<ConfigInfo>() { - @Override - public void onSuccess(ConfigInfo info) { - display(info); - } - - @Override - public void onFailure(Throwable caught) { - // never invoked - } - }); - } - - private void display(ConfigInfo info) { - Panel infoMsgPanel = new VerticalPanel(); - Panel infoMsgTitelPanel = new HorizontalPanel(); - infoMsgTitelPanel.add(new Label("Info Message")); - Image infoMsgInfo = new Image(ServiceUserPlugin.RESOURCES.info()); - infoMsgInfo.setTitle( - "HTML formatted message that should be" - + " displayed on the service user creation screen."); - infoMsgTitelPanel.add(infoMsgInfo); - infoMsgTitelPanel.add(new Label(":")); - infoMsgPanel.add(infoMsgTitelPanel); - infoMsgTxt = new TextArea(); - infoMsgTxt.setValue(info.getInfoMessage()); - infoMsgTxt.addKeyPressHandler( - new KeyPressHandler() { - @Override - public void onKeyPress(final KeyPressEvent event) { - event.stopPropagation(); - } - }); - infoMsgTxt.setVisibleLines(12); - infoMsgTxt.setCharacterWidth(80); - infoMsgTxt.getElement().setPropertyBoolean("spellcheck", false); - infoMsgPanel.add(infoMsgTxt); - add(infoMsgPanel); - - Panel onSuccessMsgPanel = new VerticalPanel(); - Panel onSuccessMsgTitelPanel = new HorizontalPanel(); - onSuccessMsgTitelPanel.add(new Label("On Success Message")); - Image onSuccessMsgInfo = new Image(ServiceUserPlugin.RESOURCES.info()); - onSuccessMsgInfo.setTitle( - "HTML formatted message that should be" - + " displayed after a service user was successfully created."); - onSuccessMsgTitelPanel.add(onSuccessMsgInfo); - onSuccessMsgTitelPanel.add(new Label(":")); - onSuccessMsgPanel.add(onSuccessMsgTitelPanel); - onSuccessMsgTxt = new TextArea(); - onSuccessMsgTxt.setValue(info.getOnSuccessMessage()); - onSuccessMsgTxt.addKeyPressHandler( - new KeyPressHandler() { - @Override - public void onKeyPress(final KeyPressEvent event) { - event.stopPropagation(); - } - }); - onSuccessMsgTxt.setVisibleLines(12); - onSuccessMsgTxt.setCharacterWidth(80); - onSuccessMsgTxt.getElement().setPropertyBoolean("spellcheck", false); - onSuccessMsgPanel.add(onSuccessMsgTxt); - add(onSuccessMsgPanel); - - Panel allowEmailPanel = new HorizontalPanel(); - allowEmailCheckBox = new CheckBox("Allow Email Address"); - allowEmailCheckBox.setValue(info.getAllowEmail()); - allowEmailPanel.add(allowEmailCheckBox); - Image allowEmailInfo = new Image(ServiceUserPlugin.RESOURCES.info()); - allowEmailInfo.setTitle( - "Whether it is allowed to provide an email address " - + "for a service user. E.g. having an email address allows a service user " - + "to push commits and tags."); - allowEmailPanel.add(allowEmailInfo); - add(allowEmailPanel); - - Panel allowHttpPasswordPanel = new HorizontalPanel(); - allowHttpPasswordCheckBox = new CheckBox("Allow HTTP password"); - allowHttpPasswordCheckBox.setValue(info.getAllowHttpPassword()); - allowHttpPasswordPanel.add(allowHttpPasswordCheckBox); - Image allowHttpPasswordInfo = new Image(ServiceUserPlugin.RESOURCES.info()); - allowHttpPasswordInfo.setTitle( - "Whether it is allowed to generate an HTTP password " - + "for a service user. E.g. having an HTTP password allows a service user " - + "to use the Gerrit REST API."); - allowHttpPasswordPanel.add(allowHttpPasswordInfo); - add(allowHttpPasswordPanel); - - Panel allowOwnerPanel = new HorizontalPanel(); - allowOwnerCheckBox = new CheckBox("Allow Owner Group"); - allowOwnerCheckBox.setValue(info.getAllowOwner()); - allowOwnerPanel.add(allowOwnerCheckBox); - Image allowOwnerInfo = new Image(ServiceUserPlugin.RESOURCES.info()); - allowOwnerInfo.setTitle("Whether it is allowed to set an owner group " + "for a service user."); - allowOwnerPanel.add(allowOwnerInfo); - add(allowOwnerPanel); - - Panel createNotesPanel = new HorizontalPanel(); - createNotesCheckBox = new CheckBox("Create Git Notes"); - createNotesCheckBox.setValue(info.getCreateNotes()); - createNotesPanel.add(createNotesCheckBox); - Image createNotesInfo = new Image(ServiceUserPlugin.RESOURCES.info()); - createNotesInfo.setTitle( - "Whether commits of a service user should be " - + "annotated by a Git note that contains information about the current " - + "owners of the service user. This allows to find a real person that " - + "is responsible for this commit. To get such a Git note for each commit " - + "of a service user the 'Forge Committer' access right must be blocked " - + "for service users."); - createNotesPanel.add(createNotesInfo); - add(createNotesPanel); - - Panel createNotesAsyncPanel = new HorizontalPanel(); - createNotesAsyncCheckBox = new CheckBox("Create Git Notes Asynchronously"); - createNotesAsyncCheckBox.setValue(info.getCreateNotesAsync()); - createNotesAsyncCheckBox.setEnabled(info.getCreateNotes()); - createNotesAsyncPanel.add(createNotesAsyncCheckBox); - Image createNotesAsyncInfo = new Image(ServiceUserPlugin.RESOURCES.info()); - createNotesAsyncInfo.setTitle( - "Whether the Git notes on commits that are " - + "pushed by a service user should be created asynchronously."); - createNotesAsyncPanel.add(createNotesAsyncInfo); - add(createNotesAsyncPanel); - - createNotesCheckBox.addValueChangeHandler( - new ValueChangeHandler<Boolean>() { - @Override - public void onValueChange(ValueChangeEvent<Boolean> event) { - createNotesAsyncCheckBox.setEnabled(event.getValue()); - } - }); - - saveButton = new Button("Save"); - saveButton.addStyleName("serviceuser-saveButton"); - saveButton.addClickHandler( - new ClickHandler() { - @Override - public void onClick(final ClickEvent event) { - doSave(); - } - }); - - blockedUsernamesPanel = - new StringListPanel("Blocked Usernames", "Username", info.getBlockedNames(), saveButton); - blockedUsernamesPanel.setInfo( - "List of usernames which are " - + "forbidden to be used as name for a service user. " - + "The blocked usernames are case insensitive."); - add(blockedUsernamesPanel); - - groupsPanel = - new StringListPanel("Groups", "Group Name", info.getGroups().keySet(), saveButton); - groupsPanel.setInfo( - "Names of groups to which newly created " + "service users should be added automatically."); - add(groupsPanel); - - HorizontalPanel buttons = new HorizontalPanel(); - add(buttons); - - buttons.add(saveButton); - saveButton.setEnabled(false); - OnEditEnabler onEditEnabler = new OnEditEnabler(saveButton, infoMsgTxt); - onEditEnabler.listenTo(onSuccessMsgTxt); - onEditEnabler.listenTo(allowEmailCheckBox); - onEditEnabler.listenTo(allowHttpPasswordCheckBox); - onEditEnabler.listenTo(allowOwnerCheckBox); - onEditEnabler.listenTo(createNotesCheckBox); - onEditEnabler.listenTo(createNotesAsyncCheckBox); - - infoMsgTxt.setFocus(true); - saveButton.setEnabled(false); - } - - private void doSave() { - ConfigInfo in = ConfigInfo.create(); - in.setInfoMessage(infoMsgTxt.getValue()); - in.setOnSuccessMessage(onSuccessMsgTxt.getValue()); - in.setAllowEmail(allowEmailCheckBox.getValue()); - in.setAllowHttpPassword(allowHttpPasswordCheckBox.getValue()); - in.setAllowOwner(allowOwnerCheckBox.getValue()); - in.setCreateNotes(createNotesCheckBox.getValue()); - if (createNotesAsyncCheckBox.isEnabled()) { - 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>() { - - @Override - public void onSuccess(JavaScriptObject result) { - saveButton.setEnabled(false); - } - - @Override - public void onFailure(Throwable caught) { - // never invoked - } - }); - } -}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/SshKeyHelpPanel.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/SshKeyHelpPanel.java deleted file mode 100644 index 9845b23..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/SshKeyHelpPanel.java +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright (C) 2014 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.client; - -import com.google.gwt.user.client.ui.DisclosurePanel; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.HTML; - -public class SshKeyHelpPanel extends FlowPanel { - - SshKeyHelpPanel() { - DisclosurePanel dp = new DisclosurePanel("How to generate an SSH Key"); - StringBuilder b = new StringBuilder(); - b.append("<ol>") - .append("<li>From the Terminal or Git Bash, run <em>ssh-keygen</em></li>") - .append("<li>") - .append( - "Enter a path for the key, e.g. <em>id_rsa</em>. If you are generating the key<br />") - .append("on your local system take care to not overwrite your own SSH key.") - .append("</li>") - .append("<li>") - .append("Enter a passphrase only if the service where you intend to use this<br />") - .append("service user is able to deal with passphrases, otherwise leave it blank.<br />") - .append("Remember this passphrase, as you will need it to unlock the key.") - .append("</li>") - .append("<li>") - .append( - "Open <em>id_rsa.pub</em> and copy & paste the contents into the box below.<br />") - .append("Note that <em>id_rsa.pub</em> is your public key and can be shared,<br />") - .append("while <em>id_rsa</em> is your private key and should be kept secret.") - .append("</li>") - .append("</ol>"); - dp.add(new HTML(b.toString())); - add(dp); - } -}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/SshKeyInfo.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/SshKeyInfo.java deleted file mode 100644 index 52a7044..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/SshKeyInfo.java +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright (C) 2014 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.client; - -import com.google.gwt.core.client.JavaScriptObject; - -public class SshKeyInfo extends JavaScriptObject { - public final native int seq() /*-{ return this.seq || 0; }-*/; - - public final native String sshPublicKey() /*-{ return this.ssh_public_key; }-*/; - - public final native String encodedKey() /*-{ return this.encoded_key; }-*/; - - public final native String algorithm() /*-{ return this.algorithm; }-*/; - - public final native String comment() /*-{ return this.comment; }-*/; - - public final native boolean isValid() /*-{ return this['valid'] ? true : false; }-*/; - - protected SshKeyInfo() {} -}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/SshPanel.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/SshPanel.java deleted file mode 100644 index 10acc65..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/SshPanel.java +++ /dev/null
@@ -1,382 +0,0 @@ -// Copyright (C) 2014 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.client; - -import com.google.gerrit.client.rpc.Natives; -import com.google.gerrit.plugin.client.Plugin; -import com.google.gerrit.plugin.client.rpc.NoContent; -import com.google.gerrit.plugin.client.rpc.RestApi; -import com.google.gwt.core.client.JsArray; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.logical.shared.ValueChangeEvent; -import com.google.gwt.event.logical.shared.ValueChangeHandler; -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.google.gwt.user.client.ui.Button; -import com.google.gwt.user.client.ui.CheckBox; -import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.FlexTable; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.HasHorizontalAlignment; -import com.google.gwt.user.client.ui.HorizontalPanel; -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.Panel; -import com.google.gwt.user.client.ui.VerticalPanel; -import com.google.gwtexpui.clippy.client.CopyableLabel; -import com.google.gwtexpui.globalkey.client.NpTextArea; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; - -class SshPanel extends Composite { - private final String serviceUser; - - private SshKeyTable keys; - - private Button showAddKeyBlock; - private Panel addKeyBlock; - private Button closeAddKeyBlock; - private Button clearNew; - private Button addNew; - private NpTextArea addTxt; - private Button deleteKey; - - private Panel serverKeys; - - private int loadCount; - - SshPanel(String serviceUser) { - this.serviceUser = serviceUser; - - FlowPanel body = new FlowPanel(); - - showAddKeyBlock = new Button("Add Key ..."); - showAddKeyBlock.addClickHandler( - new ClickHandler() { - @Override - public void onClick(final ClickEvent event) { - showAddKeyBlock(true); - } - }); - - keys = new SshKeyTable(); - body.add(keys); - { - final FlowPanel fp = new FlowPanel(); - deleteKey = new Button("Delete"); - deleteKey.setEnabled(false); - deleteKey.addClickHandler( - new ClickHandler() { - @Override - public void onClick(final ClickEvent event) { - keys.deleteChecked(); - } - }); - fp.add(deleteKey); - fp.add(showAddKeyBlock); - body.add(fp); - } - - addKeyBlock = new VerticalPanel(); - addKeyBlock.setVisible(false); - addKeyBlock.setStyleName("serviceuser-addSshKeyPanel"); - addKeyBlock.add(new Label("Add SSH Public Key")); - addKeyBlock.add(new SshKeyHelpPanel()); - - addTxt = new NpTextArea(); - addTxt.setVisibleLines(12); - addTxt.setCharacterWidth(80); - addTxt.setSpellCheck(false); - addKeyBlock.add(addTxt); - - final HorizontalPanel buttons = new HorizontalPanel(); - addKeyBlock.add(buttons); - - clearNew = new Button("Clear"); - clearNew.addClickHandler( - new ClickHandler() { - @Override - public void onClick(final ClickEvent event) { - addTxt.setText(""); - addTxt.setFocus(true); - } - }); - buttons.add(clearNew); - - addNew = new Button("Add"); - addNew.addClickHandler( - new ClickHandler() { - @Override - public void onClick(final ClickEvent event) { - doAddNew(); - } - }); - buttons.add(addNew); - - closeAddKeyBlock = new Button("Close"); - closeAddKeyBlock.addClickHandler( - new ClickHandler() { - @Override - public void onClick(final ClickEvent event) { - showAddKeyBlock(false); - } - }); - buttons.add(closeAddKeyBlock); - buttons.setCellWidth(closeAddKeyBlock, "100%"); - buttons.setCellHorizontalAlignment(closeAddKeyBlock, HasHorizontalAlignment.ALIGN_RIGHT); - - body.add(addKeyBlock); - - serverKeys = new FlowPanel(); - body.add(serverKeys); - - initWidget(body); - } - - void setKeyTableVisible(final boolean on) { - keys.setVisible(on); - deleteKey.setVisible(on); - closeAddKeyBlock.setVisible(on); - } - - void doAddNew() { - final String txt = addTxt.getText(); - if (txt != null && txt.length() > 0) { - new RestApi("config") - .id("server") - .view(Plugin.get().getPluginName(), "serviceusers") - .id(serviceUser) - .view("sshkeys") - .post( - txt, - new AsyncCallback<SshKeyInfo>() { - @Override - public void onSuccess(SshKeyInfo k) { - addTxt.setText(""); - keys.addOneKey(k); - if (!keys.isVisible()) { - showAddKeyBlock(false); - setKeyTableVisible(true); - keys.updateDeleteButton(); - } - } - - @Override - public void onFailure(final Throwable caught) { - // never invoked - } - }); - } - } - - @Override - protected void onLoad() { - super.onLoad(); - refreshSshKeys(); - } - - private void refreshSshKeys() { - new RestApi("config") - .id("server") - .view(Plugin.get().getPluginName(), "serviceusers") - .id(serviceUser) - .view("sshkeys") - .get( - new AsyncCallback<JsArray<SshKeyInfo>>() { - @Override - public void onSuccess(JsArray<SshKeyInfo> result) { - keys.display(Natives.asList(result)); - if (result.length() == 0 && keys.isVisible()) { - showAddKeyBlock(true); - } - if (++loadCount == 2) { - display(); - } - } - - @Override - public void onFailure(Throwable caught) { - // never invoked - } - }); - } - - void display() {} - - private void showAddKeyBlock(boolean show) { - showAddKeyBlock.setVisible(!show); - addKeyBlock.setVisible(show); - } - - private class SshKeyTable extends FlexTable { - private final Map<Integer, SshKeyInfo> sshKeyInfos; - private ValueChangeHandler<Boolean> updateDeleteHandler; - - SshKeyTable() { - this.sshKeyInfos = new HashMap<>(); - setStyleName("serviceuser-sshKeyTable"); - setWidth(""); - setText(0, 2, "Status"); - setText(0, 3, "Algorithm"); - setText(0, 4, "Key"); - setText(0, 5, "Comment"); - - FlexCellFormatter fmt = getFlexCellFormatter(); - fmt.addStyleName(0, 1, "iconHeader"); - fmt.addStyleName(0, 2, "dataHeader"); - fmt.addStyleName(0, 3, "dataHeader"); - fmt.addStyleName(0, 4, "dataHeader"); - fmt.addStyleName(0, 5, "dataHeader"); - - fmt.addStyleName(0, 1, "topMostCell"); - fmt.addStyleName(0, 2, "topMostCell"); - fmt.addStyleName(0, 3, "topMostCell"); - fmt.addStyleName(0, 4, "topMostCell"); - fmt.addStyleName(0, 5, "topMostCell"); - - updateDeleteHandler = - new ValueChangeHandler<Boolean>() { - @Override - public void onValueChange(ValueChangeEvent<Boolean> event) { - updateDeleteButton(); - } - }; - } - - void deleteChecked() { - final HashSet<Integer> sequenceNumbers = new HashSet<>(); - for (int row = 1; row < getRowCount(); row++) { - SshKeyInfo k = getRowItem(row); - if (k != null && ((CheckBox) getWidget(row, 1)).getValue()) { - sequenceNumbers.add(k.seq()); - } - } - if (sequenceNumbers.isEmpty()) { - updateDeleteButton(); - } else { - for (int seq : sequenceNumbers) { - new RestApi("config") - .id("server") - .view(Plugin.get().getPluginName(), "serviceusers") - .id(serviceUser) - .view("sshkeys") - .id(seq) - .delete( - new AsyncCallback<NoContent>() { - @Override - public void onSuccess(NoContent result) { - for (int row = 1; row < getRowCount(); ) { - SshKeyInfo k = getRowItem(row); - if (k != null && sequenceNumbers.contains(k.seq())) { - removeRow(row); - } else { - row++; - } - } - if (getRowCount() == 1) { - display(Collections.<SshKeyInfo>emptyList()); - } else { - updateDeleteButton(); - } - } - - @Override - public void onFailure(Throwable caught) { - // never invoked - } - }); - } - } - } - - void display(List<SshKeyInfo> result) { - if (result.isEmpty()) { - setKeyTableVisible(false); - showAddKeyBlock(true); - } else { - while (1 < getRowCount()) removeRow(getRowCount() - 1); - for (SshKeyInfo k : result) { - addOneKey(k); - } - setKeyTableVisible(true); - deleteKey.setEnabled(false); - } - } - - void addOneKey(SshKeyInfo k) { - FlexCellFormatter fmt = getFlexCellFormatter(); - int row = getRowCount(); - insertRow(row); - getCellFormatter().addStyleName(row, 0, "iconCell"); - getCellFormatter().addStyleName(row, 0, "leftMostCell"); - - CheckBox sel = new CheckBox(); - sel.addValueChangeHandler(updateDeleteHandler); - - setWidget(row, 1, sel); - if (k.isValid()) { - setText(row, 2, ""); - fmt.removeStyleName(row, 2, "serviceuser-sshKeyPanelInvalid"); - } else { - setText(row, 2, "Invalid Key"); - fmt.addStyleName(row, 2, "serviceuser-sshKeyPanelInvalid"); - } - setText(row, 3, k.algorithm()); - - CopyableLabel keyLabel = new CopyableLabel(k.sshPublicKey()); - keyLabel.setPreviewText(elide(k.encodedKey(), 40)); - setWidget(row, 4, keyLabel); - - setText(row, 5, k.comment()); - - fmt.addStyleName(row, 1, "iconCell"); - fmt.addStyleName(row, 4, "serviceuser-sshKeyPanelEncodedKey"); - for (int c = 2; c <= 5; c++) { - fmt.addStyleName(row, c, "dataCell"); - } - - setRowItem(row, k); - } - - void updateDeleteButton() { - boolean on = false; - for (int row = 1; row < getRowCount(); row++) { - CheckBox sel = (CheckBox) getWidget(row, 1); - if (sel.getValue()) { - on = true; - break; - } - } - deleteKey.setEnabled(on); - } - - private SshKeyInfo getRowItem(int row) { - return sshKeyInfos.get(row); - } - - private void setRowItem(int row, SshKeyInfo sshKeyInfo) { - sshKeyInfos.put(row, sshKeyInfo); - } - } - - static String elide(String s, int len) { - if (s == null || s.length() < len || len <= 10) { - return s; - } - return s.substring(0, len - 10) + "..." + s.substring(s.length() - 10); - } -}
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 deleted file mode 100644 index c2fff99..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/StringListPanel.java +++ /dev/null
@@ -1,202 +0,0 @@ -// Copyright (C) 2014 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.client; - -import com.google.gerrit.client.rpc.Natives; -import com.google.gwt.core.client.JsArrayString; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.event.logical.shared.ValueChangeEvent; -import com.google.gwt.event.logical.shared.ValueChangeHandler; -import com.google.gwt.user.client.ui.Button; -import com.google.gwt.user.client.ui.CheckBox; -import com.google.gwt.user.client.ui.FlexTable; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.FocusWidget; -import com.google.gwt.user.client.ui.HorizontalPanel; -import com.google.gwt.user.client.ui.Image; -import com.google.gwt.user.client.ui.Label; -import com.google.gwtexpui.globalkey.client.NpTextBox; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -public class StringListPanel extends FlowPanel { - private final NpTextBox input; - private final StringListTable t; - private final Button deleteButton; - private final HorizontalPanel titlePanel; - private Image info; - - 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) { - titlePanel = new HorizontalPanel(); - Label titleLabel = new Label(title); - titleLabel.setStyleName("serviceuser-smallHeading"); - titlePanel.add(titleLabel); - add(titlePanel); - input = new NpTextBox(); - input.addKeyPressHandler( - new KeyPressHandler() { - @Override - public void onKeyPress(KeyPressEvent event) { - if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) { - w.setEnabled(true); - add(); - } - } - }); - HorizontalPanel p = new HorizontalPanel(); - p.add(input); - Button addButton = new Button("Add"); - addButton.setEnabled(false); - new OnEditEnabler(addButton, input); - addButton.addClickHandler( - new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - w.setEnabled(true); - add(); - } - }); - p.add(addButton); - add(p); - - t = new StringListTable(fieldName); - add(t); - - deleteButton = new Button("Delete"); - deleteButton.setEnabled(false); - add(deleteButton); - deleteButton.addClickHandler( - new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - w.setEnabled(true); - t.deleteChecked(); - } - }); - - t.display(values); - } - - void setInfo(String msg) { - if (info == null) { - info = new Image(ServiceUserPlugin.RESOURCES.info()); - titlePanel.add(info); - } - info.setTitle(msg); - } - - List<String> getValues() { - return t.getValues(); - } - - private void add() { - String v = input.getValue().trim(); - if (!v.isEmpty()) { - input.setValue(""); - t.insert(v); - } - } - - private class StringListTable extends FlexTable { - StringListTable(String name) { - setStyleName("serviceuser-stringListTable"); - FlexCellFormatter fmt = getFlexCellFormatter(); - fmt.addStyleName(0, 0, "iconHeader"); - fmt.addStyleName(0, 0, "topMostCell"); - fmt.addStyleName(0, 0, "leftMostCell"); - fmt.addStyleName(0, 1, "dataHeader"); - fmt.addStyleName(0, 1, "topMostCell"); - - setText(0, 1, name); - } - - void display(Collection<String> values) { - int row = 1; - for (String v : values) { - populate(row, v); - row++; - } - } - - List<String> getValues() { - List<String> values = new ArrayList<>(); - for (int row = 1; row < getRowCount(); row++) { - values.add(getText(row, 1)); - } - return values; - } - - private void populate(int row, String value) { - FlexCellFormatter fmt = getFlexCellFormatter(); - fmt.addStyleName(row, 0, "leftMostCell"); - fmt.addStyleName(row, 0, "iconCell"); - fmt.addStyleName(row, 1, "dataCell"); - - CheckBox checkBox = new CheckBox(); - checkBox.addValueChangeHandler( - new ValueChangeHandler<Boolean>() { - @Override - public void onValueChange(ValueChangeEvent<Boolean> event) { - enableDelete(); - } - }); - setWidget(row, 0, checkBox); - setText(row, 1, value); - } - - void insert(String v) { - int insertPos = getRowCount(); - for (int row = 1; row < getRowCount(); row++) { - int compareResult = v.compareTo(getText(row, 1)); - if (compareResult < 0) { - insertPos = row; - break; - } else if (compareResult == 0) { - return; - } - } - insertRow(insertPos); - populate(insertPos, v); - } - - void enableDelete() { - for (int row = 1; row < getRowCount(); row++) { - if (((CheckBox) getWidget(row, 0)).getValue()) { - deleteButton.setEnabled(true); - return; - } - } - deleteButton.setEnabled(false); - } - - void deleteChecked() { - deleteButton.setEnabled(false); - for (int row = 1; row < getRowCount(); row++) { - if (((CheckBox) getWidget(row, 0)).getValue()) { - removeRow(row--); - } - } - } - } -}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/public/serviceuser.css b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/public/serviceuser.css deleted file mode 100644 index c996fa0..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/public/serviceuser.css +++ /dev/null
@@ -1,141 +0,0 @@ -.serviceuser-panel { - border-spacing: 0px 5px; -} - -.serviceuser-createButton, .serviceuser-saveButton { - margin-left: 10px !important; -} - -.serviceuser-serviceUserTable, -.serviceuser-sshKeyTable, -.serviceuser-stringListTable { - border-collapse: separate; - border-spacing: 0; -} - -.serviceuser-serviceUserTable .leftMostCell, -.serviceuser-sshKeyTable .leftMostCell, -.serviceuser-stringListTable .leftMostCell { - border-left: 1px solid #EEE; -} - -.serviceuser-serviceUserTable .topMostCell, -.serviceuser-sshKeyTable .topMostCell, -.serviceuser-stringListTable .topMostCell { - border-top: 1px solid #EEE; -} - -.serviceuser-serviceUserTable .dataHeader, -.serviceuser-sshKeyTable .dataHeader, -.serviceuser-stringListTable .dataHeader { - border: 1px solid #FFF; - padding: 2px 6px 1px; - background-color: #EEE; - font-style: italic; - white-space: nowrap; - color: textColor; -} - -.serviceuser-sshKeyTable .iconHeader, -.serviceuser-stringListTable .iconHeader { - border-top: 1px solid #FFF; - border-bottom: 1px solid #FFF; - background-color: #EEE; -} - -.serviceuser-serviceUserTable .dataCell, -.serviceuser-sshKeyTable .dataCell, -.serviceuser-stringListTable .dataCell { - padding-left: 5px; - padding-right: 5px; - border-right: 1px solid #EEE; - border-bottom: 1px solid #EEE; - vertical-align: middle; - height: 20px; -} - -.serviceuser-sshKeyTable .iconCell, -.serviceuser-stringListTable .iconCell { - width: 1px; - padding: 0px; - vertical-align: middle; - border-bottom: 1px solid #EEE; -} - -.serviceuser-sshKeyPanelEncodedKey { - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - font-family: mono-font; - font-size: small; -} - -.serviceuser-sshKeyPanelInvalid { - white-space: nowrap; - color: red; - font-weight: bold; -} - -.serviceuser-addSshKeyPanel { - margin-top: 10px; - background-color: #EEE; - padding: 5px 5px 5px 5px; -} - -.serviceuser-serviceUserInfoTable { - margin-bottom: 10px; -} - -.serviceuser-editButton, -.serviceuser-deleteButton, -.serviceuser-generateButton { - float: right; - cursor: pointer; - margin-left: 2px; -} - -.serviceuser-toggleButton { - position: relative; - height: 19px; - width: 140px; - background: #FFF; - color: #000; - text-shadow: none; - border: 1px solid #EEE !important; -} -.serviceuser-toggleButton .html-face { - position: absolute; - top: 0; - width: 68px; - height: 17px; - line-height: 17px; - text-align: center; - border-width: 1px; -} - -.serviceuser-toggleButton-up, -.serviceuser-toggleButton-up-hovering, -.serviceuser-toggleButton-up-disabled, -.serviceuser-toggleButton-down, -.serviceuser-toggleButton-down-hovering, -.serviceuser-toggleButton-down-disabled { - padding: 0; - border: 0; -} -.serviceuser-toggleButton-up .html-face, -.serviceuser-toggleButton-up-hovering .html-face { - left: 0; - background: #FCB; - border-style: outset; -} -.serviceuser-toggleButton-down .html-face, -.serviceuser-toggleButton-down-hovering .html-face { - right: 0; - background: #BFC; - border-style: inset; -} - -.serviceuser-smallHeading { - margin-top: 5px; - font-weight: bold; -}
diff --git a/src/main/resources/Documentation/about.md b/src/main/resources/Documentation/about.md index e5ad4c7..17a4e29 100644 --- a/src/main/resources/Documentation/about.md +++ b/src/main/resources/Documentation/about.md
@@ -6,8 +6,8 @@ in Jenkins. A service user is not able to login into the Gerrit WebUI and it cannot push commits or tags. -This plugin supports the creation of service users via [SSH](cmd-create.md), -[REST](rest-api-config.md) and in the [WebUI](#webui). +This plugin supports the creation of service users via [SSH](cmd-create.md) and +[REST](rest-api-config.md). To create a service user a user must be a member of a group that is granted the 'Create Service User' capability (provided by this plugin) @@ -20,12 +20,6 @@ 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 -----------------------
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md index 1380b73..f52421e 100644 --- a/src/main/resources/Documentation/config.md +++ b/src/main/resources/Documentation/config.md
@@ -29,8 +29,8 @@ <a id="onSuccessMessage"> `plugin.@PLUGIN@.onSuccessMessage` -: HTML formatted message that should be displayed after a service - user was successfully created. +: Message that should be displayed after a service user was + successfully created. <a id="allowEmail"> `plugin.@PLUGIN@.allowEmail`
diff --git a/src/main/resources/Documentation/rest-api-config.md b/src/main/resources/Documentation/rest-api-config.md index 302be07..3999e60 100644 --- a/src/main/resources/Documentation/rest-api-config.md +++ b/src/main/resources/Documentation/rest-api-config.md
@@ -706,8 +706,8 @@ * _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. +* _on\_success_: 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`). * _allow\_http\_password_: Whether it is allowed to generate an HTTP @@ -733,8 +733,8 @@ * _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. +* _on\_success_: 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`). * _allow\_http\_password_: Whether it is allowed to generate an HTTP
diff --git a/src/main/resources/static/gr-serviceuser-create.html b/src/main/resources/static/gr-serviceuser-create.html new file mode 100644 index 0000000..763c47d --- /dev/null +++ b/src/main/resources/static/gr-serviceuser-create.html
@@ -0,0 +1,91 @@ +<!-- +@license +Copyright (C) 2019 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. +--> + +<dom-module id="gr-serviceuser-create"> + <template> + <style include="shared-styles"></style> + <style include="gr-subpage-styles"></style> + <style include="gr-form-styles"></style> + <style> + main { + margin: 2em auto; + max-width: 50em; + } + </style> + <main class="gr-form-styles read-only"> + <div class="topHeader"> + <h2>Create Service User</h2> + </div> + <fieldset id="infoMessage" + hidden$="[[!_infoMessageEnabled]]"> + </fieldset> + <fieldset> + <section> + <span class="title">Username</span> + <span class="value"> + <input id="serviceUserNameInput" + bind-value="{{_newUsername}}" + is="iron-input" + type="text" + on-keyup="_validateData"> + </span> + </section> + <section hidden$="[[!_emailEnabled]]"> + <span class="title">Email</span> + <span class="value"> + <input id="serviceUserEmailInput" + bind-value="{{_newEmail}}" + is="iron-input" + type="text" + on-keyup="_validateData"> + </span> + </section> + </fieldset> + <fieldset> + <section> + <span class="title">Public SSH key</span> + <span class="value"> + <iron-autogrow-textarea id="newKey" + bind-value="{{_newKey}}" + placeholder="New SSH Key" + on-keyup="_validateData"> + </iron-autogrow-textarea> + </span> + </section> + </fieldset> + <gr-button id="createButton" + on-click="_handleCreateServiceUser" + disabled="[[!_enableButton]]"> + Create + </gr-button> + <gr-overlay id="successDialogOverlay" with-backdrop> + <gr-dialog id="successDialog" + confirm-label="OK" + cancel-label="" + on-confirm="_forwardToDetails" + confirm-on-enter> + <div slot="header"> + Success + </div> + <div id="successMessage" slot="main"> + </div> + </gr-dialog> + </gr-overlay> + </main> + </template> + <script src="gr-serviceuser-create.js"></script> +</dom-module>
diff --git a/src/main/resources/static/gr-serviceuser-create.js b/src/main/resources/static/gr-serviceuser-create.js new file mode 100644 index 0000000..df5d9a6 --- /dev/null +++ b/src/main/resources/static/gr-serviceuser-create.js
@@ -0,0 +1,150 @@ +/** + * @license + * Copyright (C) 2016 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. + */ + +(function() { + 'use strict'; + + Polymer({ + is: 'gr-serviceuser-create', + _legacyUndefinedCheck: true, + + properties: { + _infoMessageEnabled: { + type: Boolean, + value: false, + }, + _infoMessage: String, + _successMessageEnabled: { + type: Boolean, + value: false, + }, + _successMessage: String, + _newUsername: String, + _emailEnabled: { + type: Boolean, + value: false, + }, + _newEmail: String, + _newKey: String, + _dataValid: { + type: Boolean, + value: false, + }, + _isAdding: { + type: Boolean, + value: false, + }, + _enableButton: { + type: Boolean, + value: false, + }, + _accountId: String, + }, + + attached() { + this._getConfig(); + }, + + _forwardToDetails() { + page.show( + this.plugin.screenUrl() + + '/user/' + + this._accountId); + }, + + _getConfig() { + return this.plugin.restApi('/config/server/serviceuser~config/').get('') + .then(config => { + if (!config) { + return; + } + + if (config.info && config.info != '') { + this._infoMessageEnabled = true; + this._infoMessage = config.info; + this.$.infoMessage.innerHTML = this._infoMessage; + } + + if (config.on_success && config.on_success != '') { + this._successMessageEnabled = true; + this._successMessage = config.on_success; + this.$.successMessage.innerHTML = this._successMessage; + } + + this._emailEnabled = config.allow_email; + }); + }, + + _validateData() { + this._dataValid = this._validateName(this._newUsername) + && this._validateEmail(this._newEmail) + && this._validateKey(this._newKey); + this._computeButtonEnabled(); + }, + + _validateName(username) { + if (username && username.trim().length > 0) { + return true; + } + + return false; + }, + + _validateEmail(email) { + if (!email || email.trim().length == 0 || email.includes('@')) { + return true; + } + + return false; + }, + + _validateKey(key) { + if (!key || !key.trim()) { + return false; + } + + return true; + }, + + _computeButtonEnabled() { + this._enableButton = this._dataValid && !this._isAdding; + }, + + _handleCreateServiceUser() { + this._isAdding = true; + this._computeButtonEnabled(); + const body = { + ssh_key: this._newKey.trim(), + email: this._newEmail ? this._newEmail.trim() : null, + }; + return this.plugin.restApi('/config/server/serviceuser~serviceusers/') + .post(this._newUsername, body) + .then(response => { + this._accountId = response._account_id; + if (this._successMessage) { + this.$.successDialogOverlay.open(); + } else { + this._forwardToDetails(); + } + }).catch(response => { + this.fire('show-error', {message: response}); + this._isAdding = false; + this._computeButtonEnabled(); + }); + }, + }); +})();
diff --git a/src/main/resources/static/gr-serviceuser-detail.html b/src/main/resources/static/gr-serviceuser-detail.html new file mode 100644 index 0000000..d5ba86e --- /dev/null +++ b/src/main/resources/static/gr-serviceuser-detail.html
@@ -0,0 +1,164 @@ +<!-- +@license +Copyright (C) 2019 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. +--> + +<link rel="import" href="./gr-serviceuser-ssh-panel.html"> +<link rel="import" href="./gr-serviceuser-http-password.html"> + +<dom-module id="gr-serviceuser-detail"> + <template> + <style include="shared-styles"></style> + <style include="gr-subpage-styles"></style> + <style include="gr-form-styles"></style> + <style> + div.serviceuser-detail { + margin: 2em auto; + max-width: 50em; + } + + h1#Title { + margin-bottom: 1em; + } + + p#ownerChangeWarning { + margin-top: 1em; + margin-bottom: 1em; + } + + span#gr_serviceuser_activity { + border-radius: 1em; + width: 10em; + padding: 0.3em; + font-weight: bold; + text-align: center; + } + + span.value { + width: 50%; + } + + input.wide { + width: 100%; + } + + span.Active { + background-color: #9fcc6b; + } + + span.Inactive { + background-color: #f7a1ad; + } + </style> + <div class="serviceuser-detail"> + <main class="gr-form-styles read-only"> + <div id="loading" + class$="[[_computeLoadingClass(_loading)]]"> + Loading... + </div> + <div id="loadedContent" + class$="[[_computeLoadingClass(_loading)]]"> + <h1 id="Title">Service User "[[_serviceUser.name]]"</h1> + <div id="form"> + <fieldset> + <fieldset> + <h2 id="accountState">Account State</h2> + <section> + <span class="title">Current State</span> + <span id="gr_serviceuser_activity" + class$="value [[_active(_serviceUser)]]"> + [[_active(_serviceUser)]] + </span> + </section> + <gr-button id="statusToggleButton" on-click="_toggleStatus" disabled="[[_loading]]"> + [[_statusButtonText]]</gr-button> + </fieldset> + <fieldset> + <h2 id="userDataHeader">User Data</h2> + <section> + <span class="title">Username</span> + <span class="value">[[_serviceUser.username]]</span> + </section> + <section> + <span class="title">Full Name</span> + <span class="value" hidden$="[[!_allowFullName]]"> + <input id="serviceUserFullNameInput" class="wide" bind-value="{{_newFullName}}" + is="iron-input" type="text" disabled="[[_changingPrefs]]" + placeholder$="[[_serviceUser.name]]" on-keyup="_computePrefsChanged"> + </span> + <span class="value" hidden$="[[_allowFullName]]">[[_serviceUser.name]]</span> + </section> + <section> + <span class="title">Email Address</span> + <span class="value" hidden$="[[!_allowEmail]]"> + <input id="serviceUserEmailInput" class="wide" bind-value="{{_newEmail}}" + is="iron-input" type="text" disabled="[[_changingPrefs]]" + placeholder="[[_serviceUser.email]]" on-keyup="_computePrefsChanged"> + </span> + <span class="value" hidden$="[[_allowEmail]]">[[_serviceUser.email]]</span> + </section> + <section> + <span class="title">Owner Group</span> + <span class="value" hidden$="[[!_allowOwner]]"> + <gr-autocomplete id="serviceUserOwnerInput" text="{{_getOwnerGroup(_serviceUser)}}" + value="{{_newOwner}}" query="[[_query]]" disabled="[[_changingPrefs]]" + on-commit="_computePrefsChanged" on-keyup="_computePrefsChanged"> + [[_getOwnerGroup(_serviceUser)]] + </gr-autocomplete> + </span> + <span class="value" hidden$="[[_allowOwner]]">[[_getOwnerGroup(_serviceUser)]]</span> + </section> + <p id="ownerChangeWarning" class="style-scope gr-settings-view" hidden$="[[!_newOwner]]"> + [[_ownerChangeWarning]] + </p> + <gr-button id="savePrefs" on-click="_handleSavePreferences" disabled="[[!_prefsChanged]]"> + Save changes + </gr-button> + </fieldset> + <fieldset> + <h2 id="creationHeader">Creation</h2> + <section> + <span class="title">Created By</span> + <span class="value">[[_getCreator(_serviceUser)]]</span> + </section> + <section> + <span class="title">Created At</span> + <span class="value">[[_serviceUser.created_at]]</span> + </section> + </fieldset> + <fieldset> + <fieldset> + <h2 id="credentialsHeader">Credentials</h2> + </fieldset> + <fieldset hidden$="[[!_allowHttpPassword]]"> + <h3 id="HTTPCredentials">HTTP Credentials</h3> + <fieldset> + <gr-serviceuser-http-password id="httpPass"> + </gr-http-password> + </fieldset> + </fieldset> + <fieldset> + <h3 id="SSHKeys">SSH keys</h3> + <gr-serviceuser-ssh-panel id="sshEditor"></gr-serviceuser-ssh-panel> + </fieldset> + </fieldset> + </fieldset> + </div> + </div> + </main> + </div> + </template> + <script src="gr-serviceuser-detail.js"></script> +</dom-module>
diff --git a/src/main/resources/static/gr-serviceuser-detail.js b/src/main/resources/static/gr-serviceuser-detail.js new file mode 100644 index 0000000..53ec980 --- /dev/null +++ b/src/main/resources/static/gr-serviceuser-detail.js
@@ -0,0 +1,366 @@ +// Copyright (C) 2019 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. + +(function() { + 'use strict'; + + const NOT_FOUND_MESSAGE = 'Not Found'; + + Polymer({ + is: 'gr-serviceuser-detail', + _legacyUndefinedCheck: true, + + properties: { + _restApi: Object, + _serviceUserId: String, + _serviceUser: Object, + _serverConfig: Object, + _loading: { + type: Boolean, + value: true, + }, + _statusButtonText: { + type: String, + value: 'Activate', + }, + _prefsChanged: { + type: Boolean, + value: false, + }, + _changingPrefs: { + type: Boolean, + value: false, + }, + _isAdmin: { + type: Boolean, + value: false, + }, + _allowEmail: { + type: Boolean, + value: false, + }, + _allowFullName: { + type: Boolean, + value: false, + }, + _allowOwner: { + type: Boolean, + value: false, + }, + _allowHttpPassword: { + type: Boolean, + value: false, + }, + _newFullName: String, + _newEmail: String, + _availableOwners: Array, + _newOwner: String, + _ownerChangeWarning: String, + _query: { + type: Function, + value() { + return this._getGroupSuggestions.bind(this); + }, + }, + }, + + behaviors: [ + Gerrit.ListViewBehavior, + ], + + attached() { + this._getPermissions().then(() => { + this._extractUserId(); + this._loadServiceUser(); + }); + }, + + _loadServiceUser() { + if (!this._serviceUserId) { return; } + + const promises = []; + + promises.push(this._getPluginConfig()); + promises.push(this._getServiceUser()); + promises.push(this._getServerConfig()); + + Promise.all(promises).then(() => { + this.$.sshEditor.loadData(this._restApi, this._serviceUser); + this.$.httpPass.loadData(this._restApi, this._serviceUser); + + this.fire('title-change', {title: this._serviceUser.name}); + this._computeStatusButtonText(); + this._loading = false; + this._newFullName = this._serviceUser.name; + this._newEmail = this._serviceUser.email; + this._allowFullName = this._serverConfig.auth.editable_account_fields + .includes('FULL_NAME'); + this._allowEmail = this._allowEmail && + this._serverConfig.auth.editable_account_fields + .includes('REGISTER_NEW_EMAIL'); + }); + }, + + _computeLoadingClass(loading) { + return loading ? 'loading' : ''; + }, + + _extractUserId() { + this._serviceUserId = this.baseURI.split('/').pop(); + }, + + _getPermissions() { + return this.plugin.restApi('/accounts/self/capabilities/').get('') + .then(capabilities => { + this._isAdmin = capabilities && capabilities.administrateServer; + }); + }, + + _getPluginConfig() { + return this.plugin.restApi('/config/server/serviceuser~config/').get('') + .then(config => { + if (!config) { + return; + } + this._allowEmail = config.allow_email || this._isAdmin; + this._allowOwner = config.allow_owner || this._isAdmin; + this._allowHttpPassword = config.allow_http_password + || this._isAdmin; + }); + }, + + _getServerConfig() { + return this.plugin.restApi().getConfig().then(cfg => { + if (!cfg) { + return; + } + + this._serverConfig = cfg; + }); + }, + + _getServiceUser() { + this._restApi = this.plugin.restApi( + '/config/server/serviceuser~serviceusers/'); + return this._restApi.get(this._serviceUserId) + .then(serviceUser => { + if (!serviceUser) { + this._serviceUser = {}; + return; + } + this._serviceUser = serviceUser; + }); + }, + + _active(serviceUser) { + if (!serviceUser) { + return NOT_FOUND_MESSAGE; + } + + return serviceUser.inactive === true ? 'Inactive' : 'Active'; + }, + + _computeStatusButtonText() { + if (!this._serviceUser) { + return; + } + + this._statusButtonText = this._serviceUser.inactive === true + ? 'Activate' + : 'Deactivate'; + }, + + _toggleStatus() { + if (this._serviceUser.inactive === true) { + this._restApi.put(`${this._serviceUser._account_id}/active`) + .then(() => { + this._loadServiceUser(); + }); + } else { + this._restApi.delete(`${this._serviceUser._account_id}/active`) + .then(() => { + this._loadServiceUser(); + }); + } + }, + + _getCreator(serviceUser) { + if (!serviceUser || !serviceUser.created_by) { + return NOT_FOUND_MESSAGE; + } + + if (serviceUser.created_by.username != undefined) { + return serviceUser.created_by.username; + } + + if (serviceUser.created_by._account_id != -1) { + return serviceUser.created_by._account_id; + } + + return NOT_FOUND_MESSAGE; + }, + + _getOwnerGroup(serviceUser) { + return serviceUser && serviceUser.owner + ? serviceUser.owner.name + : NOT_FOUND_MESSAGE; + }, + + _isEmailValid(email) { + if (!email) { + return false; + } + return email.includes('@'); + }, + + _getGroupSuggestions(input) { + let query; + if (!input || input === this._getOwnerGroup(this._serviceUser)) { + query = ''; + } else { + query = `?suggest=${input}`; + } + + return this.plugin.restApi('/a/groups/').get(query) + .then(response => { + const groups = []; + for (const key in response) { + if (!response.hasOwnProperty(key)) { continue; } + groups.push({ + name: key, + value: decodeURIComponent(response[key].id), + }); + } + this._availableOwners = groups; + return groups; + }); + }, + + _isOwnerValid(owner) { + if (!owner) { + return false; + } + + return this._getOwnerName(owner); + }, + + _isNewOwner() { + return this._getOwnerName(this._newOwner) + === this._getOwnerGroup(this._serviceUser); + }, + + _getOwnerName(id) { + return this._availableOwners.find(o => { return o.value === id; }).name; + }, + + _computeOwnerWarning() { + let message = 'If '; + message += this._getOwnerGroup(this._serviceUser) != NOT_FOUND_MESSAGE + ? 'the owner group is changed' : 'an owner group is set'; + message += ' only members of the '; + message += this._getOwnerGroup(this._serviceUser) != NOT_FOUND_MESSAGE + ? 'new ' : ''; + message += 'owner group can see and administrate the service user.'; + message += this._getOwnerGroup(this._serviceUser) != NOT_FOUND_MESSAGE + ? '' : ' The creator of the service user can no' + + ' longer see and administrate the service user if she/he' + + ' is not member of the owner group.'; + this._ownerChangeWarning = message; + }, + + _computePrefsChanged() { + if (this.loading || this._changingPrefs) { + return; + } + + if (!this._newOwner && !this._newEmail && !this._newFullName) { + this._prefsChanged = false; + return; + } + + if (this._newEmail && !this._isEmailValid(this._newEmail)) { + this._prefsChanged = false; + return; + } + + if (this._newOwner + && (this._isNewOwner() || !this._isOwnerValid(this._newOwner))) { + this._prefsChanged = false; + return; + } + + if (this._newOwner) { + this._computeOwnerWarning(); + } + + this._prefsChanged = true; + }, + + _applyNewFullName() { + return this._restApi + .put(`${this._serviceUser._account_id}/name`, + {name: this._newFullName}) + .then(() => { + this.$.serviceUserFullNameInput.value = ''; + }); + }, + + _applyNewEmail(email) { + if (!this._isEmailValid(email)) { + return; + } + return this._restApi + .put(`${this._serviceUser._account_id}/email`, {email}) + .then(() => { + this.$.serviceUserEmailInput.value = ''; + }); + }, + + _applyNewOwner(owner) { + if (this._isNewOwner() || !this._isOwnerValid(this._newOwner)) { + return; + } + return this._restApi + .put(`${this._serviceUser._account_id}/owner`, {group: owner}) + .then(() => { + this.$.serviceUserOwnerInput.text = this._getOwnerGroup( + this._serviceUser); + }); + }, + + _handleSavePreferences() { + const promises = []; + this._changingPrefs = true; + + if (this._newFullName) { + promises.push(this._applyNewFullName()); + } + + if (this._newEmail) { + promises.push(this._applyNewEmail(this._newEmail)); + } + + if (this._newOwner) { + promises.push(this._applyNewOwner(this._newOwner)); + } + + Promise.all(promises).then(() => { + this._changingPrefs = false; + this._prefsChanged = false; + this._ownerChangeWarning = ''; + this._loadServiceUser(); + }); + }, + }); +})();
diff --git a/src/main/resources/static/gr-serviceuser-http-password.html b/src/main/resources/static/gr-serviceuser-http-password.html new file mode 100644 index 0000000..8cebbe5 --- /dev/null +++ b/src/main/resources/static/gr-serviceuser-http-password.html
@@ -0,0 +1,81 @@ +<!-- +@license +Copyright (C) 2019 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. +--> + +<dom-module id="gr-serviceuser-http-password"> + <template> + <style include="shared-styles"> + .password { + font-family: var(--monospace-font-family); + } + + #generatedPasswordOverlay { + padding: 2em; + width: 50em; + } + + #generatedPasswordDisplay { + margin: 1em 0; + } + + #generatedPasswordDisplay .value { + font-family: var(--monospace-font-family); + } + + #passwordWarning { + font-style: italic; + text-align: center; + } + + .closeButton { + bottom: 2em; + position: absolute; + right: 2em; + } + </style> + <style include="gr-form-styles"></style> + <div class="gr-form-styles"> + <div> + <section> + <span class="title">Username</span> + <span class="value">[[_serviceUser.username]]</span> + </section> + <gr-button id="generateButton" + on-click="_handleGenerateTap">Generate new password</gr-button> + <gr-button id="deleteButton" + on-click="_handleDelete">Delete password</gr-button> + </div> + </div> + <gr-overlay id="generatedPasswordOverlay" + on-iron-overlay-closed="_generatedPasswordOverlayClosed" + with-backdrop> + <div class="gr-form-styles"> + <section id="generatedPasswordDisplay"> + <span class="title">New Password:</span> + <span class="value">[[_generatedPassword]]</span> + </section> + <section id="passwordWarning"> + This password will not be displayed again.<br> + If you lose it, you will need to generate a new one. + </section> + <gr-button link + class="closeButton" + on-click="_closeOverlay">Close</gr-button> + </div> + </gr-overlay> + </template> + <script src="gr-serviceuser-http-password.js"></script> +</dom-module>
diff --git a/src/main/resources/static/gr-serviceuser-http-password.js b/src/main/resources/static/gr-serviceuser-http-password.js new file mode 100644 index 0000000..87e1543 --- /dev/null +++ b/src/main/resources/static/gr-serviceuser-http-password.js
@@ -0,0 +1,60 @@ +/** + * @license + * Copyright (C) 2019 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. + */ + +(function() { + 'use strict'; + + Polymer({ + is: 'gr-serviceuser-http-password', + _legacyUndefinedCheck: true, + + properties: { + _restApi: Object, + _serviceUser: Object, + _generatedPassword: String, + _passwordUrl: String, + }, + + loadData(restApi, serviceUser) { + this._restApi = restApi; + this._serviceUser = serviceUser; + }, + + _handleGenerateTap() { + this._generatedPassword = 'Generating...'; + this.$.generatedPasswordOverlay.open(); + this._restApi + .put(`${this._serviceUser._account_id}/password.http`, + {generate: true}) + .then(newPassword => { + this._generatedPassword = newPassword; + }); + }, + + _closeOverlay() { + this.$.generatedPasswordOverlay.close(); + }, + + _generatedPasswordOverlayClosed() { + this._generatedPassword = ''; + }, + + _handleDelete() { + this._restApi.delete(`${this._serviceUser._account_id}/password.http`); + }, + }); +})();
diff --git a/src/main/resources/static/gr-serviceuser-list.html b/src/main/resources/static/gr-serviceuser-list.html new file mode 100644 index 0000000..e927d63 --- /dev/null +++ b/src/main/resources/static/gr-serviceuser-list.html
@@ -0,0 +1,84 @@ +<!-- +@license +Copyright (C) 2019 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. +--> + +<dom-module id="gr-serviceuser-list"> + <template> + <style include="shared-styles"></style> + <style include="gr-table-styles"></style> + <style> + .topHeader { + padding: 8px; + } + + #topContainer { + align-items: center; + display: flex; + height: 3rem; + justify-content: space-between; + margin: 0 1em; + } + </style> + <div class="topHeader"> + <h2>Service Users</h2> + </div> + <div id="topContainer"> + <div></div> + <div id="createNewContainer" + class$="[[_computeCreateClass(createNew)]]"> + <gr-button primary + link + id="createNew" + on-click="_createNewServiceUser"> + Create New + </gr-button> + </div> + </div> + <table id="list" + class="genericList"> + <tr class="headerRow"> + <th class="name topHeader">Username</th> + <th class="fullName topHeader">Full Name</th> + <th class="email topHeader">Email</th> + <th class="owner topHeader">Owner</th> + <th class="createdBy topHeader">Created By</th> + <th class="createdAt topHeader">Created At</th> + <th class="accountState topHeader">Account State</th> + </tr> + <tr id="loading" + class$="loadingMsg [[computeLoadingClass(_loading)]]"> + <td>Loading...</td> + </tr> + <tbody class$="[[computeLoadingClass(_loading)]]"> + <template is="dom-repeat" + items="[[_serviceUsers]]"> + <tr class="table"> + <td class="name"> + <a href$="[[_computeServiceUserUrl(item._account_id)]]">[[item.username]]</a> + </td> + <td class="fullName">[[item.name]]</td> + <td class="email">[[item.email]]</td> + <td class="owner">[[_getOwnerGroup(item)]]</td> + <td class="createdBy">[[_getCreator(item)]]</td> + <td class="createdAt">[[item.created_at]]</td> + <td class="accountState">[[_active(item)]]</td> + </tr> + </template> + </tbody> + </table> + </template> + <script src="gr-serviceuser-list.js"></script> +</dom-module>
diff --git a/src/main/resources/static/gr-serviceuser-list.js b/src/main/resources/static/gr-serviceuser-list.js new file mode 100644 index 0000000..8f35dd4 --- /dev/null +++ b/src/main/resources/static/gr-serviceuser-list.js
@@ -0,0 +1,95 @@ +// Copyright (C) 2019 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. + +(function() { + 'use strict'; + + const NOT_FOUND_MESSAGE = 'Not Found'; + + Polymer({ + is: 'gr-serviceuser-list', + _legacyUndefinedCheck: true, + + properties: { + _serviceUsers: Array, + _loading: { + type: Boolean, + value: true, + }, + }, + + behaviors: [ + Gerrit.ListViewBehavior, + ], + + attached() { + this.fire('title-change', {title: 'Service Users'}); + this._getServiceUsers(); + }, + + _getServiceUsers() { + return this.plugin.restApi('/config/server/serviceuser~serviceusers/') + .get('') + .then(serviceUsers => { + if (!serviceUsers) { + this._serviceUsers = []; + return; + } + this._serviceUsers = Object.keys(serviceUsers) + .map(key => { + const serviceUser = serviceUsers[key]; + serviceUser.username = key; + return serviceUser; + }); + this._loading = false; + }); + }, + + _active(item) { + if (!item) { + return NOT_FOUND_MESSAGE; + } + + return item.inactive === true ? 'Inactive' : 'Active'; + }, + + _getCreator(item) { + if (!item || !item.created_by) { + return NOT_FOUND_MESSAGE; + } + + if (item.created_by.username != undefined) { + return item.created_by.username; + } + + if (item.created_by._account_id != -1) { + return item.created_by._account_id; + } + + return NOT_FOUND_MESSAGE; + }, + + _getOwnerGroup(item) { + return item && item.owner ? item.owner.name : NOT_FOUND_MESSAGE; + }, + + _computeServiceUserUrl(id) { + return `${this.plugin.screenUrl()}/user/${id}`; + }, + + _createNewServiceUser() { + page.show(this.plugin.screenUrl() + '/create'); + }, + }); +})();
diff --git a/src/main/resources/static/gr-serviceuser-ssh-panel.html b/src/main/resources/static/gr-serviceuser-ssh-panel.html new file mode 100644 index 0000000..2906a10 --- /dev/null +++ b/src/main/resources/static/gr-serviceuser-ssh-panel.html
@@ -0,0 +1,132 @@ +<!-- +@license +Copyright (C) 2019 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. +--> + +<dom-module id="gr-serviceuser-ssh-panel"> + <template> + <style include="shared-styles"></style> + <style include="gr-form-styles"> + .statusHeader { + width: 4em; + } + + .keyHeader { + width: 7.5em; + } + + #viewKeyOverlay { + padding: 2em; + width: 50em; + } + + .publicKey { + font-family: var(--monospace-font-family); + overflow-x: scroll; + overflow-wrap: break-word; + width: 30em; + } + + .closeButton { + bottom: 2em; + position: absolute; + right: 2em; + } + + #existing { + margin-bottom: 1em; + } + + #existing .commentColumn { + min-width: 27em; + width: auto; + } + </style> + <div class="gr-form-styles"> + <fieldset id="existing"> + <table> + <thead> + <tr> + <th class="commentColumn">Comment</th> + <th class="statusHeader">Status</th> + <th class="keyHeader">Public key</th> + <th></th> + </tr> + </thead> + <tbody> + <template is="dom-repeat" + items="[[_keys]]" + as="key"> + <tr> + <td class="commentColumn">[[key.comment]]</td> + <td>[[_getStatusLabel(key.valid)]]</td> + <td> + <gr-button link + on-click="_showKey" + data-index$="[[index]]" + link>Click to View</gr-button> + </td> + <td> + <gr-button link + data-index$="[[index]]" + on-click="_handleDeleteKey">Delete</gr-button> + </td> + </tr> + </template> + </tbody> + </table> + <gr-overlay id="viewKeyOverlay" + with-backdrop> + <fieldset> + <section> + <span class="title">Algorithm</span> + <span class="value">[[_keyToView.algorithm]]</span> + </section> + <section> + <span class="title">Public key</span> + <span class="value publicKey">[[_keyToView.encoded_key]]</span> + </section> + <section> + <span class="title">Comment</span> + <span class="value">[[_keyToView.comment]]</span> + </section> + </fieldset> + <gr-button class="closeButton" + on-click="_closeOverlay">Close</gr-button> + </gr-overlay> + </fieldset> + <fieldset> + <section> + <span class="title">New SSH key</span> + <span class="value"> + <iron-autogrow-textarea id="newKey" + autocomplete="on" + bind-value="{{_newKey}}" + placeholder="New SSH Key"> + </iron-autogrow-textarea> + </span> + </section> + <gr-button id="addButton" + link + disabled$="[[_computeAddButtonDisabled(_newKey)]]" + on-click="_handleAddKey"> + Add new SSH key + </gr-button> + </fieldset> + </div> + <gr-rest-api-interface id="restAPI"></gr-rest-api-interface> + </template> + <script src="gr-serviceuser-ssh-panel.js"></script> +</dom-module>
diff --git a/src/main/resources/static/gr-serviceuser-ssh-panel.js b/src/main/resources/static/gr-serviceuser-ssh-panel.js new file mode 100644 index 0000000..e1e8dd0 --- /dev/null +++ b/src/main/resources/static/gr-serviceuser-ssh-panel.js
@@ -0,0 +1,101 @@ +/** + * @license + * Copyright (C) 2016 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. + */ + +(function() { + 'use strict'; + + Polymer({ + is: 'gr-serviceuser-ssh-panel', + _legacyUndefinedCheck: true, + + properties: { + _restApi: Object, + _serviceUser: Object, + _keys: Array, + /** @type {?} */ + _keyToView: Object, + _newKey: { + type: String, + value: '', + }, + _keysToRemove: { + type: Array, + value() { return []; }, + }, + }, + + loadData(restApi, serviceUser) { + this._restApi = restApi; + this._serviceUser = serviceUser; + return this._restApi.get(`${this._serviceUser._account_id}/sshkeys`) + .then(keys => { + if (!keys) { + this._keys = []; + return; + } + this._keys = keys; + }); + }, + + _getStatusLabel(isValid) { + return isValid ? 'Valid' : 'Invalid'; + }, + + _showKey(e) { + const el = Polymer.dom(e).localTarget; + const index = parseInt(el.getAttribute('data-index'), 10); + this._keyToView = this._keys[index]; + this.$.viewKeyOverlay.open(); + }, + + _closeOverlay() { + this.$.viewKeyOverlay.close(); + }, + + _handleDeleteKey(e) { + const el = Polymer.dom(e).localTarget; + const index = parseInt(el.getAttribute('data-index'), 10); + this.push('_keysToRemove', this._keys[index]); + + const promises = this._keysToRemove.map(key => { + this._restApi.delete(`${this._serviceUser._account_id}/sshkeys/${key.seq}`); + }); + + return Promise.all(promises).then(() => { + this.splice('_keys', index, 1); + this._keysToRemove = []; + }); + }, + + _handleAddKey() { + this.$.addButton.disabled = true; + this.$.newKey.disabled = true; + return this._restApi.post(`${this._serviceUser._account_id}/sshkeys`, + this._newKey.trim(), null, 'plain/text') + .then(key => { + this.push('_keys', key); + }).catch(() => { + this.$.addButton.disabled = false; + this.$.newKey.disabled = false; + }); + }, + + _computeAddButtonDisabled(newKey) { + return !newKey.length; + }, + }); +})();
diff --git a/src/main/resources/static/gr-serviceuser.html b/src/main/resources/static/gr-serviceuser.html new file mode 100644 index 0000000..92714a2 --- /dev/null +++ b/src/main/resources/static/gr-serviceuser.html
@@ -0,0 +1,46 @@ +<!-- +@license +Copyright (C) 2019 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. +--> + + +<link rel="import" + href="./gr-serviceuser-list.html"> +<link rel="import" + href="./gr-serviceuser-detail.html"> +<link rel="import" + href="./gr-serviceuser-create.html"> + +<dom-module id="gr-serviceuser"> + <script> + Gerrit.install(plugin => { + plugin.restApi('/accounts/self/capabilities/').get('') + .then(capabilities => { + if (capabilities + && (capabilities.administrateServer + || capabilities['serviceuser-createServiceUser'])) { + plugin.screen('list', 'gr-serviceuser-list'); + plugin.screen('user', 'gr-serviceuser-detail'); + plugin.screen('create', 'gr-serviceuser-create'); + } + plugin.admin() + .addMenuLink( + 'Service Users', + '/x/serviceuser/list', + 'serviceuser-createServiceUser'); + }); + }); + </script> +</dom-module>
diff --git a/src/test/java/com/googlesource/gerrit/plugins/serviceuser/SshKeyValidatorTest.java b/src/test/java/com/googlesource/gerrit/plugins/serviceuser/SshKeyValidatorTest.java new file mode 100644 index 0000000..619ab98 --- /dev/null +++ b/src/test/java/com/googlesource/gerrit/plugins/serviceuser/SshKeyValidatorTest.java
@@ -0,0 +1,60 @@ +// Copyright (C) 2019 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 static com.google.common.truth.Truth.assertThat; + +import org.junit.Test; + +public class SshKeyValidatorTest { + + private final String[] VALID_PUBLIC_KEYS = { + "---- BEGIN SSH2 PUBLIC KEY ----\n" + + " Comment: comment\n" + + " AAAAB3NzaC1\n" + + " ---- END SSH2 PUBLIC KEY ----", + "---- BEGIN PUBLIC KEY ----\n" + + " Comment: comment\n" + + " AAAAB3NzaC1\n" + + " ---- END PUBLIC KEY ----", + "-----BEGIN RSA PUBLIC KEY-----\nMIIBC\n-----END RSA PUBLIC KEY-----", + "ssh-rsa AAAAB3NzaC1", + "ssh-dss AAAAB3NzaC1", + "ssh-ed25519 AAAAB3NzaC1", + "ecdsa-sha2-nistp256 AAAAB3NzaC1" + }; + + private final String[] INVALID_PUBLIC_KEYS = { + "---- BEGIN SSH2 PUBLIC KEY ----\n Comment: comment\n AAAAB3NzaC1\n", + "-----BEGIN PRIVATE KEY-----\nMIIBC\n-----END PRIVATE KEY-----", + "AAAAB3NzaC1\n ---- END SSH2 PUBLIC KEY ----", + "", + "invalid key" + }; + + @Test + public void testValidateSshKeyFormat_Valid() { + for (String keyToTest : VALID_PUBLIC_KEYS) { + assertThat(SshKeyValidator.validateFormat(keyToTest)).isTrue(); + } + } + + @Test + public void testValidateSshKeyFormat_Invalid() { + for (String keyToTest : INVALID_PUBLIC_KEYS) { + assertThat(SshKeyValidator.validateFormat(keyToTest)).isFalse(); + } + } +}
diff --git a/tools/bzl/junit.bzl b/tools/bzl/junit.bzl new file mode 100644 index 0000000..240c448 --- /dev/null +++ b/tools/bzl/junit.bzl
@@ -0,0 +1,5 @@ +load( + "@com_googlesource_gerrit_bazlets//tools:junit.bzl", + _junit_tests = "junit_tests", +) +junit_tests = _junit_tests
diff --git a/tools/bzl/plugin.bzl b/tools/bzl/plugin.bzl index 9568c84..4d2dbdd 100644 --- a/tools/bzl/plugin.bzl +++ b/tools/bzl/plugin.bzl
@@ -1,10 +1,10 @@ load( "@com_googlesource_gerrit_bazlets//:gerrit_plugin.bzl", _gerrit_plugin = "gerrit_plugin", - _gwt_plugin_deps = "GWT_PLUGIN_DEPS", _plugin_deps = "PLUGIN_DEPS", + _plugin_test_deps = "PLUGIN_TEST_DEPS", ) gerrit_plugin = _gerrit_plugin -GWT_PLUGIN_DEPS = _gwt_plugin_deps PLUGIN_DEPS = _plugin_deps +PLUGIN_TEST_DEPS = _plugin_test_deps
diff --git a/tools/eclipse/BUILD b/tools/eclipse/BUILD index 9b694c1..a38b222 100644 --- a/tools/eclipse/BUILD +++ b/tools/eclipse/BUILD
@@ -1,16 +1,10 @@ load("//tools/bzl:classpath.bzl", "classpath_collector") -load( - "//tools/bzl:plugin.bzl", - "GWT_PLUGIN_DEPS", - "PLUGIN_DEPS", -) +load("//tools/bzl:plugin.bzl", "PLUGIN_DEPS") classpath_collector( name = "main_classpath_collect", testonly = 1, - deps = PLUGIN_DEPS + GWT_PLUGIN_DEPS + [ - "//external:gwt-dev", - "//external:gwt-user", + deps = PLUGIN_DEPS + [ "//:serviceuser__plugin", ], )