Merge branch 'stable-3.2' into stable-3.3
* stable-3.2:
Fix formatting of documentation
Remove unsused variable
Allow blocking of usernames using wildcards and regex
Add command to register existing user as service user
Change-Id: Ib9dfe4cac48acefd85a103a7241c2abbc9c2f675
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 7f8b3de..b63cf8b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUser.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUser.java
@@ -75,19 +75,21 @@
}
private final PluginConfig cfg;
+ private final Provider<ProjectLevelConfig.Bare> configProvider;
private final CreateAccount createAccount;
private final Provider<CurrentUser> userProvider;
private final MetaDataUpdate.User metaDataUpdateFactory;
private final Project.NameKey allProjects;
- private final ProjectLevelConfig storage;
private final DateFormat rfc2822DateFormatter;
private final Provider<GetConfig> getConfig;
private final AccountLoader.Factory accountLoader;
+ private final StorageCache storageCache;
private final BlockedNameFilter blockedNameFilter;
@Inject
CreateServiceUser(
PluginConfigFactory cfgFactory,
+ Provider<ProjectLevelConfig.Bare> configProvider,
@PluginName String pluginName,
CreateAccount createAccount,
Provider<CurrentUser> userProvider,
@@ -96,18 +98,20 @@
ProjectCache projectCache,
Provider<GetConfig> getConfig,
AccountLoader.Factory accountLoader,
+ StorageCache storageCache,
BlockedNameFilter blockedNameFilter) {
this.cfg = cfgFactory.getFromGerritConfig(pluginName);
+ this.configProvider = configProvider;
this.createAccount = createAccount;
this.userProvider = userProvider;
this.metaDataUpdateFactory = metaDataUpdateFactory;
- this.storage = projectCache.getAllProjects().getConfig(pluginName + ".db");
this.allProjects = projectCache.getAllProjects().getProject().getNameKey();
this.rfc2822DateFormatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
this.rfc2822DateFormatter.setCalendar(
Calendar.getInstance(gerritIdent.getTimeZone(), Locale.US));
this.getConfig = getConfig;
this.accountLoader = accountLoader;
+ this.storageCache = storageCache;
this.blockedNameFilter = blockedNameFilter;
}
@@ -168,16 +172,21 @@
Account.Id creatorId = ((IdentifiedUser) user).getAccountId();
String creationDate = rfc2822DateFormatter.format(new Date());
- Config db = storage.get();
- db.setInt(USER, username, KEY_CREATOR_ID, creatorId.get());
- if (creator != null) {
- db.setString(USER, username, KEY_CREATED_BY, creator);
- }
- db.setString(USER, username, KEY_CREATED_AT, creationDate);
+ try (MetaDataUpdate md = metaDataUpdateFactory.create(allProjects)) {
+ ProjectLevelConfig.Bare update = configProvider.get();
+ update.load(md);
- MetaDataUpdate md = metaDataUpdateFactory.create(allProjects);
- md.setMessage("Create service user '" + username + "'\n");
- storage.commit(md);
+ Config db = update.getConfig();
+ db.setInt(USER, username, KEY_CREATOR_ID, creatorId.get());
+ if (creator != null) {
+ db.setString(USER, username, KEY_CREATED_BY, creator);
+ }
+ db.setString(USER, username, KEY_CREATED_AT, creationDate);
+
+ md.setMessage("Create service user '" + username + "'\n");
+ update.commit(md);
+ storageCache.invalidate();
+ }
ServiceUserInfo info = new ServiceUserInfo(response);
AccountLoader al = accountLoader.create(true);
info.createdBy = al.get(creatorId);
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 93fc84c..d60203b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserNotes.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUserNotes.java
@@ -131,8 +131,9 @@
}
}
- private void markUninteresting(Repository git, String branch, RevWalk rw, ObjectId oldObjectId) {
- for (Ref r : git.getAllRefs().values()) {
+ private void markUninteresting(Repository git, String branch, RevWalk rw, ObjectId oldObjectId)
+ throws IOException {
+ for (Ref r : git.getRefDatabase().getRefs()) {
try {
if (r.getName().equals(branch)) {
if (!ObjectId.zeroId().equals(oldObjectId)) {
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 f89f047..3cca663 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetConfig.java
@@ -95,7 +95,7 @@
return v ? v : null;
}
- public class ConfigInfo {
+ static class ConfigInfo {
public String info;
public String onSuccess;
public Boolean allowEmail;
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 31c2eb6..bf7227b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetOwner.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetOwner.java
@@ -17,8 +17,7 @@
import static com.googlesource.gerrit.plugins.serviceuser.CreateServiceUser.KEY_OWNER;
import static com.googlesource.gerrit.plugins.serviceuser.CreateServiceUser.USER;
-import com.google.gerrit.common.data.GroupDescription;
-import com.google.gerrit.extensions.annotations.PluginName;
+import com.google.gerrit.entities.GroupDescription;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.Response;
@@ -26,37 +25,30 @@
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gerrit.server.project.ProjectCache;
-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.inject.Inject;
import com.google.inject.Singleton;
+import java.io.IOException;
@Singleton
class GetOwner implements RestReadView<ServiceUserResource> {
private final GroupsCollection groups;
- private final String pluginName;
- private final ProjectCache projectCache;
private final GroupJson json;
+ private final StorageCache storageCache;
@Inject
- GetOwner(
- GroupsCollection groups,
- @PluginName String pluginName,
- ProjectCache projectCache,
- GroupJson json) {
+ GetOwner(GroupsCollection groups, GroupJson json, StorageCache storageCache) {
this.groups = groups;
- this.pluginName = pluginName;
- this.projectCache = projectCache;
this.json = json;
+ this.storageCache = storageCache;
}
@Override
public Response<GroupInfo> apply(ServiceUserResource rsrc)
- throws RestApiException, PermissionBackendException {
- ProjectLevelConfig storage = projectCache.getAllProjects().getConfig(pluginName + ".db");
- String owner = storage.get().getString(USER, rsrc.getUser().getUserName().get(), KEY_OWNER);
+ throws IOException, RestApiException, PermissionBackendException {
+ String owner =
+ storageCache.get().getString(USER, rsrc.getUser().getUserName().get(), KEY_OWNER);
if (owner != null) {
GroupDescription.Basic group =
groups.parse(TopLevelResource.INSTANCE, IdString.fromDecoded(owner)).getGroup();
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 c700da8..784c6b0 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetServiceUser.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/GetServiceUser.java
@@ -21,7 +21,6 @@
import static javax.servlet.http.HttpServletResponse.SC_OK;
import com.google.gerrit.entities.Account;
-import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
@@ -30,42 +29,37 @@
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.permissions.PermissionBackendException;
-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.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
+import java.io.IOException;
import org.eclipse.jgit.lib.Config;
@Singleton
class GetServiceUser implements RestReadView<ServiceUserResource> {
private final Provider<GetAccount> getAccount;
- private final String pluginName;
- private final ProjectCache projectCache;
private final GetOwner getOwner;
private final AccountLoader.Factory accountLoader;
+ private final StorageCache storageCache;
@Inject
GetServiceUser(
Provider<GetAccount> getAccount,
- @PluginName String pluginName,
- ProjectCache projectCache,
GetOwner getOwner,
- AccountLoader.Factory accountLoader) {
+ AccountLoader.Factory accountLoader,
+ StorageCache storageCache) {
this.getAccount = getAccount;
- this.pluginName = pluginName;
- this.projectCache = projectCache;
this.getOwner = getOwner;
this.accountLoader = accountLoader;
+ this.storageCache = storageCache;
}
@Override
public Response<ServiceUserInfo> apply(ServiceUserResource rsrc)
- throws RestApiException, PermissionBackendException {
- ProjectLevelConfig storage = projectCache.getAllProjects().getConfig(pluginName + ".db");
+ throws IOException, RestApiException, PermissionBackendException {
String username = rsrc.getUser().getUserName().get();
- Config db = storage.get();
+ Config db = storageCache.get();
if (!db.getSubsections(USER).contains(username)) {
throw new ResourceNotFoundException(username);
}
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 5e77ce2..a40b989 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ListServiceUsers.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ListServiceUsers.java
@@ -18,7 +18,6 @@
import static com.googlesource.gerrit.plugins.serviceuser.CreateServiceUser.USER;
import com.google.common.collect.Maps;
-import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
@@ -30,8 +29,6 @@
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.config.ConfigResource;
import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gerrit.server.project.ProjectCache;
-import com.google.gerrit.server.project.ProjectLevelConfig;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
@@ -45,39 +42,35 @@
@Singleton
class ListServiceUsers implements RestReadView<ConfigResource> {
private final Provider<CurrentUser> userProvider;
- private final String pluginName;
- private final ProjectCache projectCache;
private final AccountCache accountCache;
private final Provider<ServiceUserCollection> serviceUsers;
private final Provider<GetServiceUser> getServiceUser;
+ private final StorageCache storageCache;
@Inject
ListServiceUsers(
Provider<CurrentUser> userProvider,
- @PluginName String pluginName,
- ProjectCache projectCache,
AccountCache accountCache,
Provider<ServiceUserCollection> serviceUsers,
- Provider<GetServiceUser> getServiceUser) {
+ Provider<GetServiceUser> getServiceUser,
+ StorageCache storageCache) {
this.userProvider = userProvider;
- this.pluginName = pluginName;
- this.projectCache = projectCache;
this.accountCache = accountCache;
this.serviceUsers = serviceUsers;
this.getServiceUser = getServiceUser;
+ this.storageCache = storageCache;
}
@Override
public Response<Map<String, ServiceUserInfo>> apply(ConfigResource rscr)
throws IOException, RestApiException, PermissionBackendException, ConfigInvalidException {
- ProjectLevelConfig storage = projectCache.getAllProjects().getConfig(pluginName + ".db");
CurrentUser user = userProvider.get();
if (user == null || !user.isIdentifiedUser()) {
throw new AuthException("Authentication required");
}
Map<String, ServiceUserInfo> accounts = Maps.newTreeMap();
- Config db = storage.get();
+ Config db = storageCache.get();
for (String username : db.getSubsections(USER)) {
Optional<AccountState> account = accountCache.getByUsername(username);
if (account.isPresent()) {
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 56d14e1..89510bb 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/Module.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/Module.java
@@ -19,13 +19,16 @@
import static com.googlesource.gerrit.plugins.serviceuser.ServiceUserResource.SERVICE_USER_SSH_KEY_KIND;
import com.google.gerrit.extensions.annotations.Exports;
+import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.config.CapabilityDefinition;
import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
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.server.git.validators.CommitValidationListener;
+import com.google.gerrit.server.project.ProjectLevelConfig;
import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
import com.google.inject.assistedinject.FactoryModuleBuilder;
class Module extends AbstractModule {
@@ -71,5 +74,11 @@
}
});
install(new HttpModule());
+ install(StorageCache.module());
+ }
+
+ @Provides
+ ProjectLevelConfig.Bare createProjectLevelConfig(@PluginName String pluginName) {
+ return new ProjectLevelConfig.Bare(pluginName + ".db");
}
}
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 fd8bbbf..32ee082 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutOwner.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutOwner.java
@@ -20,11 +20,10 @@
import static com.googlesource.gerrit.plugins.serviceuser.CreateServiceUser.USER;
import com.google.common.base.Strings;
-import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.AccountGroup.UUID;
+import com.google.gerrit.entities.GroupDescription;
import com.google.gerrit.entities.Project;
-import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.restapi.DefaultInput;
import com.google.gerrit.extensions.restapi.IdString;
@@ -47,6 +46,7 @@
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.serviceuser.PutOwner.Input;
import java.io.IOException;
+import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
@Singleton
@@ -57,39 +57,39 @@
private final Provider<GetConfig> getConfig;
private final GroupsCollection groups;
- private final String pluginName;
- private final ProjectCache projectCache;
+ private final Provider<ProjectLevelConfig.Bare> configProvider;
private final Project.NameKey allProjects;
private final MetaDataUpdate.User metaDataUpdateFactory;
private final GroupJson json;
private final Provider<CurrentUser> self;
private final PermissionBackend permissionBackend;
+ private final StorageCache storageCache;
@Inject
PutOwner(
Provider<GetConfig> getConfig,
GroupsCollection groups,
- @PluginName String pluginName,
+ Provider<ProjectLevelConfig.Bare> configProvider,
ProjectCache projectCache,
MetaDataUpdate.User metaDataUpdateFactory,
GroupJson json,
Provider<CurrentUser> self,
- PermissionBackend permissionBackend) {
+ PermissionBackend permissionBackend,
+ StorageCache storageCache) {
this.getConfig = getConfig;
this.groups = groups;
- this.pluginName = pluginName;
- this.projectCache = projectCache;
+ this.configProvider = configProvider;
this.allProjects = projectCache.getAllProjects().getProject().getNameKey();
this.metaDataUpdateFactory = metaDataUpdateFactory;
this.json = json;
this.self = self;
this.permissionBackend = permissionBackend;
+ this.storageCache = storageCache;
}
@Override
public Response<GroupInfo> apply(ServiceUserResource rsrc, Input input)
throws RestApiException, IOException, PermissionBackendException {
- ProjectLevelConfig storage = projectCache.getAllProjects().getConfig(pluginName + ".db");
Boolean ownerAllowed;
try {
ownerAllowed = getConfig.get().apply(new ConfigResource()).value().allowOwner;
@@ -103,22 +103,33 @@
if (input == null) {
input = new Input();
}
- Config db = storage.get();
- String oldGroup = db.getString(USER, rsrc.getUser().getUserName().get(), KEY_OWNER);
+
GroupDescription.Basic group = null;
- if (Strings.isNullOrEmpty(input.group)) {
- db.unset(USER, rsrc.getUser().getUserName().get(), KEY_OWNER);
- } else {
- group = groups.parse(TopLevelResource.INSTANCE, IdString.fromDecoded(input.group)).getGroup();
- UUID groupUUID = group.getGroupUUID();
- if (!AccountGroup.uuid(groupUUID.get()).isInternalGroup()) {
- throw new MethodNotAllowedException("Group with UUID '" + groupUUID + "' is external");
+ String oldGroup;
+ try (MetaDataUpdate md = metaDataUpdateFactory.create(allProjects)) {
+ ProjectLevelConfig.Bare update = configProvider.get();
+ update.load(md);
+
+ Config db = update.getConfig();
+ oldGroup = db.getString(USER, rsrc.getUser().getUserName().get(), KEY_OWNER);
+ if (Strings.isNullOrEmpty(input.group)) {
+ db.unset(USER, rsrc.getUser().getUserName().get(), KEY_OWNER);
+ } else {
+ group =
+ groups.parse(TopLevelResource.INSTANCE, IdString.fromDecoded(input.group)).getGroup();
+ UUID groupUUID = group.getGroupUUID();
+ if (!AccountGroup.uuid(groupUUID.get()).isInternalGroup()) {
+ throw new MethodNotAllowedException("Group with UUID '" + groupUUID + "' is external");
+ }
+ db.setString(USER, rsrc.getUser().getUserName().get(), KEY_OWNER, groupUUID.get());
}
- db.setString(USER, rsrc.getUser().getUserName().get(), KEY_OWNER, groupUUID.get());
+ md.setMessage("Set owner for service user '" + rsrc.getUser().getUserName() + "'\n");
+ update.commit(md);
+ storageCache.invalidate();
+ } catch (ConfigInvalidException e) {
+ throw asRestApiException("Invalid configuration", e);
}
- MetaDataUpdate md = metaDataUpdateFactory.create(allProjects);
- md.setMessage("Set owner for service user '" + rsrc.getUser().getUserName() + "'\n");
- storage.commit(md);
+
return group != null
? (oldGroup != null
? Response.ok(json.format(group))
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 31d1a56..421b326 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/RefUpdateListener.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/RefUpdateListener.java
@@ -26,6 +26,7 @@
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
+import java.util.concurrent.Future;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.slf4j.Logger;
@@ -90,7 +91,8 @@
}
};
if (cfg.getBoolean("createNotesAsync", false)) {
- workQueue.getDefaultQueue().submit(task);
+ @SuppressWarnings("unused")
+ Future<?> possiblyIgnoredError = workQueue.getDefaultQueue().submit(task);
} else {
task.run();
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/RegisterServiceUser.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/RegisterServiceUser.java
index c1ebb9a..f0319f1 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/RegisterServiceUser.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/RegisterServiceUser.java
@@ -24,7 +24,6 @@
import com.google.common.base.Strings;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Project;
-import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.restapi.AuthException;
@@ -73,39 +72,42 @@
String owner;
}
+ private final Provider<ProjectLevelConfig.Bare> configProvider;
private final AccountResolver accountResolver;
private final GroupResolver groupResolver;
private final Provider<CurrentUser> userProvider;
private final MetaDataUpdate.User metaDataUpdateFactory;
private final Project.NameKey allProjects;
- private final ProjectLevelConfig storage;
private final DateFormat rfc2822DateFormatter;
private final AccountLoader.Factory accountLoader;
+ private final StorageCache storageCache;
private final PermissionBackend permissionBackend;
private final BlockedNameFilter blockedNameFilter;
@Inject
RegisterServiceUser(
+ Provider<ProjectLevelConfig.Bare> configProvider,
AccountResolver accountResolver,
GroupResolver groupResolver,
- @PluginName String pluginName,
Provider<CurrentUser> userProvider,
@GerritPersonIdent PersonIdent gerritIdent,
MetaDataUpdate.User metaDataUpdateFactory,
ProjectCache projectCache,
AccountLoader.Factory accountLoader,
+ StorageCache storageCache,
PermissionBackend permissionBackend,
BlockedNameFilter blockedNameFilter) {
+ this.configProvider = configProvider;
this.accountResolver = accountResolver;
this.groupResolver = groupResolver;
this.userProvider = userProvider;
this.metaDataUpdateFactory = metaDataUpdateFactory;
- this.storage = projectCache.getAllProjects().getConfig(pluginName + ".db");
this.allProjects = projectCache.getAllProjects().getProject().getNameKey();
this.rfc2822DateFormatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
this.rfc2822DateFormatter.setCalendar(
Calendar.getInstance(gerritIdent.getTimeZone(), Locale.US));
this.accountLoader = accountLoader;
+ this.storageCache = storageCache;
this.permissionBackend = permissionBackend;
this.blockedNameFilter = blockedNameFilter;
}
@@ -134,11 +136,6 @@
throw new MethodNotAllowedException("Forbidden");
}
- Config db = storage.get();
- if (db.getSubsections(USER).contains(input.username)) {
- return Response.none();
- }
-
if (blockedNameFilter.isBlocked(input.username)) {
throw new BadRequestException(
"The username '" + input.username + "' is not allowed as name for service users.");
@@ -164,18 +161,27 @@
}
}
- db.setInt(USER, input.username, KEY_CREATOR_ID, creatorId.get());
- if (creator != null) {
- db.setString(USER, input.username, KEY_CREATED_BY, creator);
- }
- if (owner != null) {
- db.setString(USER, input.username, KEY_OWNER, owner);
- }
- db.setString(USER, input.username, KEY_CREATED_AT, creationDate);
+ try (MetaDataUpdate md = metaDataUpdateFactory.create(allProjects)) {
+ ProjectLevelConfig.Bare update = configProvider.get();
+ update.load(md);
- MetaDataUpdate md = metaDataUpdateFactory.create(allProjects);
- md.setMessage("Create service user '" + input.username + "'\n");
- storage.commit(md);
+ Config db = update.getConfig();
+ if (db.getSubsections(USER).contains(input.username)) {
+ return Response.none();
+ }
+ db.setInt(USER, input.username, KEY_CREATOR_ID, creatorId.get());
+ if (creator != null) {
+ db.setString(USER, input.username, KEY_CREATED_BY, creator);
+ }
+ if (owner != null) {
+ db.setString(USER, input.username, KEY_OWNER, owner);
+ }
+ db.setString(USER, input.username, KEY_CREATED_AT, creationDate);
+
+ md.setMessage("Create service user '" + input.username + "'\n");
+ update.commit(md);
+ storageCache.invalidate();
+ }
ServiceUserInfo info = new ServiceUserInfo(new AccountInfo(user.getAccountId().get()));
AccountLoader al = accountLoader.create(true);
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 bce9e37..f6f50ac 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ServiceUserCollection.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ServiceUserCollection.java
@@ -19,14 +19,14 @@
import static com.googlesource.gerrit.plugins.serviceuser.CreateServiceUser.KEY_OWNER;
import static com.googlesource.gerrit.plugins.serviceuser.CreateServiceUser.USER;
-import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.entities.Account;
-import com.google.gerrit.extensions.annotations.PluginName;
+import com.google.gerrit.entities.GroupDescription;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ChildCollection;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
+import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.server.CurrentUser;
@@ -34,8 +34,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.gerrit.server.project.ProjectCache;
-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.inject.Inject;
@@ -43,6 +41,7 @@
import com.google.inject.Singleton;
import java.io.IOException;
import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.lib.Config;
@Singleton
class ServiceUserCollection implements ChildCollection<ConfigResource, ServiceUserResource> {
@@ -50,40 +49,36 @@
private final DynamicMap<RestView<ServiceUserResource>> views;
private final Provider<ListServiceUsers> list;
private final Provider<AccountsCollection> accounts;
- private final String pluginName;
- private final ProjectCache projectCache;
private final Provider<CurrentUser> userProvider;
private final GroupsCollection groups;
private final PermissionBackend permissionBackend;
+ private final StorageCache storageCache;
@Inject
ServiceUserCollection(
DynamicMap<RestView<ServiceUserResource>> views,
Provider<ListServiceUsers> list,
Provider<AccountsCollection> accounts,
- @PluginName String pluginName,
- ProjectCache projectCache,
Provider<CurrentUser> userProvider,
GroupsCollection groups,
- PermissionBackend permissionBackend) {
+ PermissionBackend permissionBackend,
+ StorageCache storageCache) {
this.views = views;
this.list = list;
this.accounts = accounts;
- this.pluginName = pluginName;
- this.projectCache = projectCache;
this.userProvider = userProvider;
this.groups = groups;
this.permissionBackend = permissionBackend;
+ this.storageCache = storageCache;
}
@Override
public ServiceUserResource parse(ConfigResource parent, IdString id)
throws ResourceNotFoundException, AuthException, IOException, PermissionBackendException,
- ConfigInvalidException {
- ProjectLevelConfig storage = projectCache.getAllProjects().getConfig(pluginName + ".db");
+ ConfigInvalidException, RestApiException {
IdentifiedUser serviceUser = accounts.get().parse(TopLevelResource.INSTANCE, id).getUser();
- if (serviceUser == null
- || !storage.get().getSubsections(USER).contains(serviceUser.getUserName().get())) {
+ Config db = storageCache.get();
+ if (serviceUser == null || !db.getSubsections(USER).contains(serviceUser.getUserName().get())) {
throw new ResourceNotFoundException(id);
}
CurrentUser user = userProvider.get();
@@ -92,7 +87,7 @@
}
if (!permissionBackend.user(user).testOrFalse(ADMINISTRATE_SERVER)) {
String username = serviceUser.getUserName().get();
- String owner = storage.get().getString(USER, username, KEY_OWNER);
+ String owner = db.getString(USER, username, KEY_OWNER);
if (owner != null) {
GroupDescription.Basic group =
groups.parse(TopLevelResource.INSTANCE, IdString.fromDecoded(owner)).getGroup();
@@ -101,7 +96,7 @@
}
} else if (!((IdentifiedUser) user)
.getAccountId()
- .equals(Account.id(storage.get().getInt(USER, username, KEY_CREATOR_ID, -1)))) {
+ .equals(Account.id(db.getInt(USER, username, KEY_CREATOR_ID, -1)))) {
throw new ResourceNotFoundException(id);
}
}
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 65ac232..0c46e26 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ServiceUserResolver.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/ServiceUserResolver.java
@@ -16,9 +16,9 @@
import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
-import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AccountGroup;
+import com.google.gerrit.entities.GroupDescription;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestApiException;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/StorageCache.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/StorageCache.java
new file mode 100644
index 0000000..0378347
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/StorageCache.java
@@ -0,0 +1,93 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.googlesource.gerrit.plugins.serviceuser;
+
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.server.cache.CacheModule;
+import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.git.meta.MetaDataUpdate;
+import com.google.gerrit.server.project.ProjectLevelConfig;
+import com.google.gerrit.server.project.ProjectLevelConfig.Bare;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.name.Named;
+import java.util.concurrent.ExecutionException;
+import org.eclipse.jgit.lib.Config;
+
+@Singleton
+public class StorageCache {
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
+ private static final String CACHE_NAME = "storage";
+ private static final Object ALL = new Object();
+
+ static CacheModule module() {
+ return new CacheModule() {
+ @Override
+ protected void configure() {
+ cache(CACHE_NAME, Object.class, Config.class).loader(Loader.class);
+ bind(StorageCache.class);
+ }
+ };
+ }
+
+ private final LoadingCache<Object, Config> cache;
+
+ @Inject
+ StorageCache(@Named(CACHE_NAME) LoadingCache<Object, Config> cache) {
+ this.cache = cache;
+ }
+
+ public Config get() {
+ try {
+ return cache.get(ALL);
+ } catch (ExecutionException e) {
+ logger.atSevere().withCause(e).log("Cannot load service users");
+ return new Config();
+ }
+ }
+
+ public void invalidate() {
+ cache.invalidate(ALL);
+ }
+
+ static class Loader extends CacheLoader<Object, Config> {
+ private final Provider<Bare> configProvider;
+ private final MetaDataUpdate.Server metaDataUpdateFactory;
+ private final AllProjectsName allProjects;
+
+ @Inject
+ Loader(
+ Provider<ProjectLevelConfig.Bare> configProvider,
+ MetaDataUpdate.Server metaDataUpdateFactory,
+ AllProjectsName allProjects) {
+ this.configProvider = configProvider;
+ this.metaDataUpdateFactory = metaDataUpdateFactory;
+ this.allProjects = allProjects;
+ }
+
+ @Override
+ public Config load(Object key) throws Exception {
+ ProjectLevelConfig.Bare storage = configProvider.get();
+ try (MetaDataUpdate md = metaDataUpdateFactory.create(allProjects)) {
+ storage.load(md);
+ }
+ return storage.getConfig();
+ }
+ }
+}