Check required capabilities during UiAction gathering

Currently UiAction imlementation has to provide isVisible() method.
If UiAction specifies RequiresCapability annotation, then that check
can be done during UiAction gathering.  The following prerequisities
must be met, to satisfy the check:

 1. user has to be authenticated
 2.1 user is a member of the Administrators group or
 2.2 user is a member of a group, which has the required capability

Change-Id: I0bfb8dd5048bd2a52583f83aa38105bc176f1cca
This commit is contained in:
David Ostrovsky
2013-08-31 22:23:05 +02:00
committed by Shawn Pearce
parent c544351617
commit eb47db12fe
3 changed files with 31 additions and 11 deletions

View File

@@ -48,6 +48,7 @@ import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
import com.google.inject.util.Providers;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -179,7 +180,8 @@ class PatchSetDetailFactory extends Handler<PatchSetDetail> {
detail.setCommands(Lists.newArrayList(Iterables.transform( detail.setCommands(Lists.newArrayList(Iterables.transform(
UiActions.sorted(UiActions.plugins(UiActions.from( UiActions.sorted(UiActions.plugins(UiActions.from(
revisions, revisions,
new RevisionResource(new ChangeResource(control), patchSet)))), new RevisionResource(new ChangeResource(control), patchSet),
Providers.of(user)))),
new Function<UiAction.Description, UiCommandDetail>() { new Function<UiAction.Description, UiCommandDetail>() {
@Override @Override
public UiCommandDetail apply(UiAction.Description in) { public UiCommandDetail apply(UiAction.Description in) {

View File

@@ -123,7 +123,7 @@ public class ChangeJson {
private final Provider<ReviewDb> db; private final Provider<ReviewDb> db;
private final LabelNormalizer labelNormalizer; private final LabelNormalizer labelNormalizer;
private final CurrentUser user; private final Provider<CurrentUser> user;
private final AnonymousUser anonymous; private final AnonymousUser anonymous;
private final IdentifiedUser.GenericFactory userFactory; private final IdentifiedUser.GenericFactory userFactory;
private final ChangeControl.GenericFactory changeControlGenericFactory; private final ChangeControl.GenericFactory changeControlGenericFactory;
@@ -144,7 +144,7 @@ public class ChangeJson {
ChangeJson( ChangeJson(
Provider<ReviewDb> db, Provider<ReviewDb> db,
LabelNormalizer ln, LabelNormalizer ln,
CurrentUser u, Provider<CurrentUser> userProvider,
AnonymousUser au, AnonymousUser au,
IdentifiedUser.GenericFactory uf, IdentifiedUser.GenericFactory uf,
ChangeControl.GenericFactory ccf, ChangeControl.GenericFactory ccf,
@@ -157,7 +157,7 @@ public class ChangeJson {
Revisions revisions) { Revisions revisions) {
this.db = db; this.db = db;
this.labelNormalizer = ln; this.labelNormalizer = ln;
this.user = u; this.user = userProvider;
this.anonymous = au; this.anonymous = au;
this.userFactory = uf; this.userFactory = uf;
this.changeControlGenericFactory = ccf; this.changeControlGenericFactory = ccf;
@@ -256,7 +256,9 @@ public class ChangeJson {
out.updated = in.getLastUpdatedOn(); out.updated = in.getLastUpdatedOn();
out._number = in.getId().get(); out._number = in.getId().get();
out._sortkey = in.getSortKey(); out._sortkey = in.getSortKey();
out.starred = user.getStarredChanges().contains(in.getId()) ? true : null; out.starred = user.get().getStarredChanges().contains(in.getId())
? true
: null;
out.reviewed = in.getStatus().isOpen() && isChangeReviewed(cd) ? true : null; out.reviewed = in.getStatus().isOpen() && isChangeReviewed(cd) ? true : null;
out.labels = labelsFor(cd, has(LABELS), has(DETAILED_LABELS)); out.labels = labelsFor(cd, has(LABELS), has(DETAILED_LABELS));
@@ -290,7 +292,8 @@ public class ChangeJson {
out.actions = Maps.newTreeMap(); out.actions = Maps.newTreeMap();
for (UiAction.Description d : UiActions.from( for (UiAction.Description d : UiActions.from(
changes, changes,
new ChangeResource(control(cd)))) { new ChangeResource(control(cd)),
user)) {
out.actions.put(d.getId(), new ActionInfo(d)); out.actions.put(d.getId(), new ActionInfo(d));
} }
} }
@@ -311,7 +314,8 @@ public class ChangeJson {
if (changeControlUserFactory != null) { if (changeControlUserFactory != null) {
ctrl = changeControlUserFactory.controlFor(cd.change(db)); ctrl = changeControlUserFactory.controlFor(cd.change(db));
} else { } else {
ctrl = changeControlGenericFactory.controlFor(cd.change(db), user); ctrl = changeControlGenericFactory.controlFor(cd.change(db),
user.get());
} }
} catch (NoSuchChangeException e) { } catch (NoSuchChangeException e) {
return null; return null;
@@ -776,7 +780,8 @@ public class ChangeJson {
out.actions = Maps.newTreeMap(); out.actions = Maps.newTreeMap();
for (UiAction.Description d : UiActions.from( for (UiAction.Description d : UiActions.from(
revisions, revisions,
new RevisionResource(new ChangeResource(control(cd)), in))) { new RevisionResource(new ChangeResource(control(cd)), in),
user)) {
out.actions.put(d.getId(), new ActionInfo(d)); out.actions.put(d.getId(), new ActionInfo(d));
} }
} }

View File

@@ -20,11 +20,15 @@ import com.google.common.base.Predicates;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.gerrit.extensions.registration.DynamicMap; import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.RestCollection; import com.google.gerrit.extensions.restapi.RestCollection;
import com.google.gerrit.extensions.restapi.RestResource; import com.google.gerrit.extensions.restapi.RestResource;
import com.google.gerrit.extensions.restapi.RestView; import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.extensions.webui.PrivateInternals_UiActionDescription; import com.google.gerrit.extensions.webui.PrivateInternals_UiActionDescription;
import com.google.gerrit.extensions.webui.UiAction; import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.CapabilityUtils;
import com.google.inject.Provider;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -70,13 +74,15 @@ public class UiActions {
public static <R extends RestResource> Iterable<UiAction.Description> from( public static <R extends RestResource> Iterable<UiAction.Description> from(
RestCollection<?, R> collection, RestCollection<?, R> collection,
R resource) { R resource,
return from(collection.views(), resource); Provider<CurrentUser> userProvider) {
return from(collection.views(), resource, userProvider);
} }
public static <R extends RestResource> Iterable<UiAction.Description> from( public static <R extends RestResource> Iterable<UiAction.Description> from(
DynamicMap<RestView<R>> views, DynamicMap<RestView<R>> views,
final R resource) { final R resource,
final Provider<CurrentUser> userProvider) {
return Iterables.filter( return Iterables.filter(
Iterables.transform( Iterables.transform(
views, views,
@@ -103,6 +109,13 @@ public class UiActions {
return null; return null;
} }
try {
CapabilityUtils.checkRequiresCapability(userProvider,
e.getPluginName(), view.getClass());
} catch (AuthException exc) {
return null;
}
UiAction.Description dsc = UiAction.Description dsc =
((UiAction<R>) view).getDescription(resource); ((UiAction<R>) view).getDescription(resource);
if (dsc == null || !dsc.isVisible()) { if (dsc == null || !dsc.isVisible()) {