Allow administrators to see other user capabilities
Expand /accounts/{id}/capabilities to permit an administrator
to inspect another user's effective capabilities by identifying
the user with anything AccountResolver understands.
This is a stepping stone to making more data available about
other accounts.
Change-Id: I81c786825f6531844b36f6178e5ed7324ccebd3a
			
			
This commit is contained in:
		| @@ -14,35 +14,51 @@ | ||||
|  | ||||
| package com.google.gerrit.server.account; | ||||
|  | ||||
| import com.google.common.collect.Iterables; | ||||
| import com.google.gerrit.extensions.registration.DynamicMap; | ||||
| import com.google.gerrit.extensions.restapi.AuthException; | ||||
| import com.google.gerrit.extensions.restapi.ResourceNotFoundException; | ||||
| import com.google.gerrit.extensions.restapi.RestCollection; | ||||
| import com.google.gerrit.extensions.restapi.RestView; | ||||
| import com.google.gerrit.extensions.restapi.TopLevelResource; | ||||
| import com.google.gerrit.reviewdb.client.Account; | ||||
| import com.google.gerrit.server.AnonymousUser; | ||||
| import com.google.gerrit.server.CurrentUser; | ||||
| import com.google.gerrit.server.IdentifiedUser; | ||||
| import com.google.gerrit.server.util.Url; | ||||
| import com.google.gwtorm.server.OrmException; | ||||
| import com.google.inject.Inject; | ||||
| import com.google.inject.Provider; | ||||
|  | ||||
| import java.util.Set; | ||||
|  | ||||
| public class AccountsCollection implements | ||||
|     RestCollection<TopLevelResource, AccountResource> { | ||||
|   private final Provider<CurrentUser> self; | ||||
|   private final AccountResolver resolver; | ||||
|   private final AccountControl.Factory accountControlFactory; | ||||
|   private final IdentifiedUser.GenericFactory userFactory; | ||||
|   private final DynamicMap<RestView<AccountResource>> views; | ||||
|  | ||||
|   @Inject | ||||
|   AccountsCollection(Provider<CurrentUser> self, | ||||
|       AccountResolver resolver, | ||||
|       AccountControl.Factory accountControlFactory, | ||||
|       IdentifiedUser.GenericFactory userFactory, | ||||
|       DynamicMap<RestView<AccountResource>> views) { | ||||
|     this.self = self; | ||||
|     this.resolver = resolver; | ||||
|     this.accountControlFactory = accountControlFactory; | ||||
|     this.userFactory = userFactory; | ||||
|     this.views = views; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public AccountResource parse(TopLevelResource root, String id) | ||||
|       throws ResourceNotFoundException, AuthException { | ||||
|       throws ResourceNotFoundException, AuthException, OrmException { | ||||
|     CurrentUser user = self.get(); | ||||
|  | ||||
|     if ("self".equals(id)) { | ||||
|       CurrentUser user = self.get(); | ||||
|       if (user instanceof IdentifiedUser) { | ||||
|         return new AccountResource((IdentifiedUser) user); | ||||
|       } else if (user instanceof AnonymousUser) { | ||||
| @@ -50,6 +66,17 @@ public class AccountsCollection implements | ||||
|       } else { | ||||
|         throw new ResourceNotFoundException(id); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     Set<Account.Id> matches = resolver.findAll(Url.decode(id)); | ||||
|     if (matches.size() != 1) { | ||||
|       throw new ResourceNotFoundException(id); | ||||
|     } | ||||
|  | ||||
|     Account.Id a = Iterables.getOnlyElement(matches); | ||||
|     if (accountControlFactory.get().canSee(a) | ||||
|         || user.getCapabilities().canAdministrateServer()) { | ||||
|       return new AccountResource(userFactory.create(a)); | ||||
|     } else { | ||||
|       throw new ResourceNotFoundException(id); | ||||
|     } | ||||
|   | ||||
| @@ -16,22 +16,27 @@ package com.google.gerrit.server.account; | ||||
|  | ||||
| import com.google.gerrit.common.data.GlobalCapability; | ||||
| 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.ResourceNotFoundException; | ||||
| import com.google.gerrit.extensions.restapi.RestView; | ||||
| import com.google.gerrit.server.CurrentUser; | ||||
| import com.google.gerrit.server.account.AccountResource.Capability; | ||||
| import com.google.inject.Inject; | ||||
| import com.google.inject.Provider; | ||||
|  | ||||
| class Capabilities implements | ||||
|     ChildCollection<AccountResource, AccountResource.Capability> { | ||||
|   private final Provider<CurrentUser> self; | ||||
|   private final DynamicMap<RestView<AccountResource.Capability>> views; | ||||
|   private final Provider<GetCapabilities> get; | ||||
|  | ||||
|   @Inject | ||||
|   Capabilities( | ||||
|       Provider<CurrentUser> self, | ||||
|       DynamicMap<RestView<AccountResource.Capability>> views, | ||||
|       Provider<GetCapabilities> get) { | ||||
|     this.self = self; | ||||
|     this.views = views; | ||||
|     this.get = get; | ||||
|   } | ||||
| @@ -43,7 +48,12 @@ class Capabilities implements | ||||
|  | ||||
|   @Override | ||||
|   public Capability parse(AccountResource parent, String id) | ||||
|       throws ResourceNotFoundException, Exception { | ||||
|       throws ResourceNotFoundException, AuthException { | ||||
|     if (self.get() != parent.getUser() | ||||
|         && !self.get().getCapabilities().canAdministrateServer()) { | ||||
|       throw new AuthException("restricted to administrator"); | ||||
|     } | ||||
|  | ||||
|     CapabilityControl cap = parent.getUser().getCapabilities(); | ||||
|     if (cap.canPerform(id) | ||||
|         || (cap.canAdministrateServer() && GlobalCapability.isCapability(id))) { | ||||
|   | ||||
| @@ -32,13 +32,17 @@ import com.google.common.collect.Maps; | ||||
| import com.google.common.collect.Sets; | ||||
| import com.google.gerrit.common.data.GlobalCapability; | ||||
| import com.google.gerrit.common.data.PermissionRange; | ||||
| import com.google.gerrit.extensions.restapi.AuthException; | ||||
| import com.google.gerrit.extensions.restapi.BadRequestException; | ||||
| import com.google.gerrit.extensions.restapi.BinaryResult; | ||||
| import com.google.gerrit.extensions.restapi.RestReadView; | ||||
| import com.google.gerrit.server.CurrentUser; | ||||
| import com.google.gerrit.server.OutputFormat; | ||||
| import com.google.gerrit.server.account.AccountResource.Capability; | ||||
| import com.google.gerrit.server.git.QueueProvider; | ||||
| import com.google.gson.reflect.TypeToken; | ||||
| import com.google.inject.Inject; | ||||
| import com.google.inject.Provider; | ||||
|  | ||||
| import org.kohsuke.args4j.Option; | ||||
|  | ||||
| @@ -67,9 +71,21 @@ class GetCapabilities implements RestReadView<AccountResource> { | ||||
|   } | ||||
|   private Set<String> query; | ||||
|  | ||||
|   private final Provider<CurrentUser> self; | ||||
|  | ||||
|   @Inject | ||||
|   GetCapabilities(Provider<CurrentUser> self) { | ||||
|     this.self = self; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public Object apply(AccountResource resource) | ||||
|       throws BadRequestException, Exception { | ||||
|     if (self.get() != resource.getUser() | ||||
|         && !self.get().getCapabilities().canAdministrateServer()) { | ||||
|       throw new AuthException("restricted to administrator"); | ||||
|     } | ||||
|  | ||||
|     CapabilityControl cc = resource.getUser().getCapabilities(); | ||||
|     Map<String, Object> have = Maps.newLinkedHashMap(); | ||||
|     for (String name : GlobalCapability.getAllNames()) { | ||||
|   | ||||
| @@ -34,6 +34,7 @@ import com.google.gerrit.server.InternalUser; | ||||
| import com.google.gerrit.server.MimeUtilFileTypeRegistry; | ||||
| import com.google.gerrit.server.account.AccountByEmailCacheImpl; | ||||
| import com.google.gerrit.server.account.AccountCacheImpl; | ||||
| import com.google.gerrit.server.account.AccountControl; | ||||
| import com.google.gerrit.server.account.AccountInfoCacheFactory; | ||||
| import com.google.gerrit.server.account.AccountResolver; | ||||
| import com.google.gerrit.server.account.AccountVisibility; | ||||
| @@ -196,6 +197,7 @@ public class GerritGlobalModule extends FactoryModule { | ||||
|     bind(IdentifiedUser.GenericFactory.class).in(SINGLETON); | ||||
|     bind(ChangeControl.GenericFactory.class); | ||||
|     bind(ProjectControl.GenericFactory.class); | ||||
|     bind(AccountControl.Factory.class); | ||||
|     factory(FunctionState.Factory.class); | ||||
|  | ||||
|     install(new AuditModule()); | ||||
|   | ||||
| @@ -60,7 +60,6 @@ public class GerritRequestModule extends FactoryModule { | ||||
|     bind(PerRequestProjectControlCache.class).in(RequestScoped.class); | ||||
|     bind(ChangeControl.Factory.class).in(SINGLETON); | ||||
|     bind(ProjectControl.Factory.class).in(SINGLETON); | ||||
|     bind(AccountControl.Factory.class).in(SINGLETON); | ||||
|  | ||||
|     factory(SubmoduleOp.Factory.class); | ||||
|     factory(MergeOp.Factory.class); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Shawn Pearce
					Shawn Pearce