Add fine-grained capabilities for administrative actions
The Global Capabilities section in All-Projects can now be used to grant subcommands that are available over SSH and were previously restricted to only Administrators. Bug: issue 48 Bug: issue 742 Change-Id: I7d8a931b174915191817ff845f1f9a846181d709
This commit is contained in:
@@ -27,7 +27,8 @@ created in Gerrit that do not exist in the underlying LDAP directory.
|
|||||||
|
|
||||||
ACCESS
|
ACCESS
|
||||||
------
|
------
|
||||||
Caller must be a member of the privileged 'Administrators' group.
|
Caller must be a member of the privileged 'Administrators' group,
|
||||||
|
or have been granted the 'Create Account' global capability.
|
||||||
|
|
||||||
SCRIPTING
|
SCRIPTING
|
||||||
---------
|
---------
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ becomes a member of the newly created group.
|
|||||||
|
|
||||||
ACCESS
|
ACCESS
|
||||||
------
|
------
|
||||||
Caller must be a member of the privileged 'Administrators' group.
|
Caller must be a member of the privileged 'Administrators' group,
|
||||||
|
or have been granted the 'Create Group' global capability.
|
||||||
|
|
||||||
SCRIPTING
|
SCRIPTING
|
||||||
---------
|
---------
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ If no options are supplied, defaults to `--all`.
|
|||||||
|
|
||||||
ACCESS
|
ACCESS
|
||||||
------
|
------
|
||||||
Caller must be a member of the privileged 'Administrators' group.
|
Caller must be a member of the privileged 'Administrators' group,
|
||||||
|
or have granted the 'Flush Caches' global capability.
|
||||||
|
|
||||||
SCRIPTING
|
SCRIPTING
|
||||||
---------
|
---------
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ its next cancellation point (which is usually blocking IO).
|
|||||||
|
|
||||||
ACCESS
|
ACCESS
|
||||||
------
|
------
|
||||||
Caller must be a member of the privileged 'Administrators' group.
|
Caller must be a member of the privileged 'Administrators' group,
|
||||||
|
or have been granted the 'Kill Task' global capability.
|
||||||
|
|
||||||
SCRIPTING
|
SCRIPTING
|
||||||
---------
|
---------
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ just the affected project can update the mirrors.
|
|||||||
|
|
||||||
ACCESS
|
ACCESS
|
||||||
------
|
------
|
||||||
Caller must be a member of the privileged 'Administrators' group.
|
Caller must be a member of the privileged 'Administrators' group,
|
||||||
|
or have been granted the 'Start Replication' global capability.
|
||||||
|
|
||||||
SCRIPTING
|
SCRIPTING
|
||||||
---------
|
---------
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ Display statistics about the size and hit ratio of in-memory caches.
|
|||||||
|
|
||||||
ACCESS
|
ACCESS
|
||||||
------
|
------
|
||||||
Caller must be a member of the privileged 'Administrators' group.
|
Caller must be a member of the privileged 'Administrators' group,
|
||||||
|
or have been granted the 'View Caches' global capability.
|
||||||
|
|
||||||
SCRIPTING
|
SCRIPTING
|
||||||
---------
|
---------
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ an activity.
|
|||||||
|
|
||||||
ACCESS
|
ACCESS
|
||||||
------
|
------
|
||||||
Caller must be a member of the privileged 'Administrators' group.
|
Caller must be a member of the privileged 'Administrators' group,
|
||||||
|
or have been granted the 'View Connections' global capability.
|
||||||
|
|
||||||
SCRIPTING
|
SCRIPTING
|
||||||
---------
|
---------
|
||||||
|
|||||||
@@ -24,7 +24,12 @@ in these states.
|
|||||||
|
|
||||||
ACCESS
|
ACCESS
|
||||||
------
|
------
|
||||||
Caller must be a member of the privileged 'Administrators' group.
|
End-users may see a task in the queue only if they can also see
|
||||||
|
the project the task is associated with. Tasks operating on other
|
||||||
|
projects, or that do not have a specific project are hidden.
|
||||||
|
|
||||||
|
Members of the group 'Administrators', or any group that has been
|
||||||
|
granted the 'View Queue' capability can see all queue entries.
|
||||||
|
|
||||||
SCRIPTING
|
SCRIPTING
|
||||||
---------
|
---------
|
||||||
|
|||||||
@@ -19,13 +19,46 @@ import java.util.List;
|
|||||||
|
|
||||||
/** Server wide capabilities. Represented as {@link Permission} objects. */
|
/** Server wide capabilities. Represented as {@link Permission} objects. */
|
||||||
public class GlobalCapability {
|
public class GlobalCapability {
|
||||||
|
/** Can create any group on the server. */
|
||||||
|
public static final String CREATE_GROUP = "createGroup";
|
||||||
|
|
||||||
|
/** Can create any account on the server. */
|
||||||
|
public static final String CREATE_ACCOUNT = "createAccount";
|
||||||
|
|
||||||
|
/** Can flush any cache except the active web_sessions cache. */
|
||||||
|
public static final String FLUSH_CACHES = "flushCaches";
|
||||||
|
|
||||||
|
/** Can terminate any task using the kill command. */
|
||||||
|
public static final String KILL_TASK = "killTask";
|
||||||
|
|
||||||
|
/** Maximum result limit per executed query. */
|
||||||
public static final String QUERY_LIMIT = "queryLimit";
|
public static final String QUERY_LIMIT = "queryLimit";
|
||||||
|
|
||||||
|
/** Forcefully restart replication to any configured destination. */
|
||||||
|
public static final String START_REPLICATION = "startReplication";
|
||||||
|
|
||||||
|
/** Can view the server's current cache states. */
|
||||||
|
public static final String VIEW_CACHES = "viewCaches";
|
||||||
|
|
||||||
|
/** Can view open connections to the server's SSH port. */
|
||||||
|
public static final String VIEW_CONNECTIONS = "viewConnections";
|
||||||
|
|
||||||
|
/** Can view all pending tasks in the queue (not just the filtered set). */
|
||||||
|
public static final String VIEW_QUEUE = "viewQueue";
|
||||||
|
|
||||||
private static final List<String> NAMES_LC;
|
private static final List<String> NAMES_LC;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
NAMES_LC = new ArrayList<String>();
|
NAMES_LC = new ArrayList<String>();
|
||||||
|
NAMES_LC.add(CREATE_GROUP.toLowerCase());
|
||||||
|
NAMES_LC.add(CREATE_ACCOUNT.toLowerCase());
|
||||||
|
NAMES_LC.add(FLUSH_CACHES.toLowerCase());
|
||||||
|
NAMES_LC.add(KILL_TASK.toLowerCase());
|
||||||
NAMES_LC.add(QUERY_LIMIT.toLowerCase());
|
NAMES_LC.add(QUERY_LIMIT.toLowerCase());
|
||||||
|
NAMES_LC.add(START_REPLICATION.toLowerCase());
|
||||||
|
NAMES_LC.add(VIEW_CACHES.toLowerCase());
|
||||||
|
NAMES_LC.add(VIEW_CONNECTIONS.toLowerCase());
|
||||||
|
NAMES_LC.add(VIEW_QUEUE.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the name is recognized as a capability name. */
|
/** @return true if the name is recognized as a capability name. */
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ import com.google.gerrit.reviewdb.AccountGroupMember;
|
|||||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||||
import com.google.gwtjsonrpc.client.RemoteJsonService;
|
import com.google.gwtjsonrpc.client.RemoteJsonService;
|
||||||
import com.google.gwtjsonrpc.client.RpcImpl;
|
import com.google.gwtjsonrpc.client.RpcImpl;
|
||||||
import com.google.gwtjsonrpc.client.RpcImpl.Version;
|
|
||||||
import com.google.gwtjsonrpc.client.VoidResult;
|
import com.google.gwtjsonrpc.client.VoidResult;
|
||||||
|
import com.google.gwtjsonrpc.client.RpcImpl.Version;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -30,7 +30,7 @@ import java.util.Set;
|
|||||||
@RpcImpl(version = Version.V2_0)
|
@RpcImpl(version = Version.V2_0)
|
||||||
public interface GroupAdminService extends RemoteJsonService {
|
public interface GroupAdminService extends RemoteJsonService {
|
||||||
@SignInRequired
|
@SignInRequired
|
||||||
void visibleGroups(AsyncCallback<List<AccountGroup>> callback);
|
void visibleGroups(AsyncCallback<GroupList> callback);
|
||||||
|
|
||||||
@SignInRequired
|
@SignInRequired
|
||||||
void createGroup(String newName, AsyncCallback<AccountGroup.Id> callback);
|
void createGroup(String newName, AsyncCallback<AccountGroup.Id> callback);
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// Copyright (C) 2011 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.google.gerrit.common.data;
|
||||||
|
|
||||||
|
import com.google.gerrit.reviewdb.AccountGroup;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GroupList {
|
||||||
|
protected List<AccountGroup> groups;
|
||||||
|
protected boolean canCreateGroup;
|
||||||
|
|
||||||
|
public List<AccountGroup> getGroups() {
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroups(List<AccountGroup> groups) {
|
||||||
|
this.groups = groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCanCreateGroup() {
|
||||||
|
return canCreateGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCanCreateGroup(boolean set) {
|
||||||
|
canCreateGroup = set;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
// Copyright (C) 2011 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.google.gerrit.common.errors;
|
||||||
|
|
||||||
|
/** Indicats the user cannot perform this task. */
|
||||||
|
public class PermissionDeniedException extends Exception {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public PermissionDeniedException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -119,8 +119,24 @@ errorsMustBeFixed = Errors must be fixed before committing changes.
|
|||||||
|
|
||||||
# Capability Names
|
# Capability Names
|
||||||
capabilityNames = \
|
capabilityNames = \
|
||||||
queryLimit
|
createAccount, \
|
||||||
|
createGroup, \
|
||||||
|
flushCaches, \
|
||||||
|
killTask, \
|
||||||
|
queryLimit, \
|
||||||
|
startReplication, \
|
||||||
|
viewCaches, \
|
||||||
|
viewConnections, \
|
||||||
|
viewQueue
|
||||||
|
createAccount = Create Account
|
||||||
|
createGroup = Create Group
|
||||||
|
flushCaches = Flush Caches
|
||||||
|
killTask = Kill Task
|
||||||
queryLimit = Query Limit
|
queryLimit = Query Limit
|
||||||
|
startReplication = Start Replication
|
||||||
|
viewCaches = View Caches
|
||||||
|
viewConnections = View Connections
|
||||||
|
viewQueue = View Queue
|
||||||
|
|
||||||
# Section Names
|
# Section Names
|
||||||
sectionTypeReference = Reference:
|
sectionTypeReference = Reference:
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import com.google.gerrit.client.ui.AccountScreen;
|
|||||||
import com.google.gerrit.client.ui.OnEditEnabler;
|
import com.google.gerrit.client.ui.OnEditEnabler;
|
||||||
import com.google.gerrit.client.ui.SmallHeading;
|
import com.google.gerrit.client.ui.SmallHeading;
|
||||||
import com.google.gerrit.common.PageLinks;
|
import com.google.gerrit.common.PageLinks;
|
||||||
|
import com.google.gerrit.common.data.GroupList;
|
||||||
import com.google.gerrit.reviewdb.AccountGroup;
|
import com.google.gerrit.reviewdb.AccountGroup;
|
||||||
import com.google.gwt.event.dom.client.BlurEvent;
|
import com.google.gwt.event.dom.client.BlurEvent;
|
||||||
import com.google.gwt.event.dom.client.BlurHandler;
|
import com.google.gwt.event.dom.client.BlurHandler;
|
||||||
@@ -42,6 +43,7 @@ import java.util.List;
|
|||||||
public class GroupListScreen extends AccountScreen {
|
public class GroupListScreen extends AccountScreen {
|
||||||
private GroupTable groups;
|
private GroupTable groups;
|
||||||
|
|
||||||
|
private VerticalPanel addPanel;
|
||||||
private NpTextBox addTxt;
|
private NpTextBox addTxt;
|
||||||
private Button addNew;
|
private Button addNew;
|
||||||
|
|
||||||
@@ -49,10 +51,11 @@ public class GroupListScreen extends AccountScreen {
|
|||||||
protected void onLoad() {
|
protected void onLoad() {
|
||||||
super.onLoad();
|
super.onLoad();
|
||||||
Util.GROUP_SVC
|
Util.GROUP_SVC
|
||||||
.visibleGroups(new ScreenLoadCallback<List<AccountGroup>>(this) {
|
.visibleGroups(new ScreenLoadCallback<GroupList>(this) {
|
||||||
@Override
|
@Override
|
||||||
protected void preDisplay(final List<AccountGroup> result) {
|
protected void preDisplay(GroupList result) {
|
||||||
groups.display(result);
|
addPanel.setVisible(result.isCanCreateGroup());
|
||||||
|
groups.display(result.getGroups());
|
||||||
groups.finishDisplay();
|
groups.finishDisplay();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -66,9 +69,9 @@ public class GroupListScreen extends AccountScreen {
|
|||||||
groups = new GroupTable(true /* hyperlink to admin */, PageLinks.ADMIN_GROUPS);
|
groups = new GroupTable(true /* hyperlink to admin */, PageLinks.ADMIN_GROUPS);
|
||||||
add(groups);
|
add(groups);
|
||||||
|
|
||||||
final VerticalPanel fp = new VerticalPanel();
|
addPanel = new VerticalPanel();
|
||||||
fp.setStyleName(Gerrit.RESOURCES.css().addSshKeyPanel());
|
addPanel.setStyleName(Gerrit.RESOURCES.css().addSshKeyPanel());
|
||||||
fp.add(new SmallHeading(Util.C.headingCreateGroup()));
|
addPanel.add(new SmallHeading(Util.C.headingCreateGroup()));
|
||||||
|
|
||||||
addTxt = new NpTextBox();
|
addTxt = new NpTextBox();
|
||||||
addTxt.setVisibleLength(60);
|
addTxt.setVisibleLength(60);
|
||||||
@@ -80,7 +83,7 @@ public class GroupListScreen extends AccountScreen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fp.add(addTxt);
|
addPanel.add(addTxt);
|
||||||
|
|
||||||
addNew = new Button(Util.C.buttonCreateGroup());
|
addNew = new Button(Util.C.buttonCreateGroup());
|
||||||
addNew.setEnabled(false);
|
addNew.setEnabled(false);
|
||||||
@@ -109,8 +112,8 @@ public class GroupListScreen extends AccountScreen {
|
|||||||
groups.setRegisterKeys(true);
|
groups.setRegisterKeys(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fp.add(addNew);
|
addPanel.add(addNew);
|
||||||
add(fp);
|
add(addPanel);
|
||||||
|
|
||||||
new OnEditEnabler(addNew, addTxt);
|
new OnEditEnabler(addNew, addTxt);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
package com.google.gerrit.httpd.rpc.account;
|
package com.google.gerrit.httpd.rpc.account;
|
||||||
|
|
||||||
import com.google.gerrit.common.errors.NameAlreadyUsedException;
|
import com.google.gerrit.common.errors.NameAlreadyUsedException;
|
||||||
|
import com.google.gerrit.common.errors.PermissionDeniedException;
|
||||||
import com.google.gerrit.httpd.rpc.Handler;
|
import com.google.gerrit.httpd.rpc.Handler;
|
||||||
import com.google.gerrit.reviewdb.Account;
|
import com.google.gerrit.reviewdb.Account;
|
||||||
import com.google.gerrit.reviewdb.AccountGroup;
|
import com.google.gerrit.reviewdb.AccountGroup;
|
||||||
@@ -44,7 +45,14 @@ class CreateGroup extends Handler<AccountGroup.Id> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AccountGroup.Id call() throws OrmException, NameAlreadyUsedException {
|
public AccountGroup.Id call() throws OrmException, NameAlreadyUsedException,
|
||||||
|
PermissionDeniedException {
|
||||||
|
if (!user.getCapabilities().canCreateGroup()) {
|
||||||
|
throw new PermissionDeniedException(String.format(
|
||||||
|
"%s does not have \"Create Group\" capability.",
|
||||||
|
user.getUserName()));
|
||||||
|
}
|
||||||
|
|
||||||
final PerformCreateGroup performCreateGroup = performCreateGroupFactory.create();
|
final PerformCreateGroup performCreateGroup = performCreateGroupFactory.create();
|
||||||
final Account.Id me = user.getAccountId();
|
final Account.Id me = user.getAccountId();
|
||||||
return performCreateGroup.createGroup(groupName, null, false, null, Collections.singleton(me), null);
|
return performCreateGroup.createGroup(groupName, null, false, null, Collections.singleton(me), null);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ package com.google.gerrit.httpd.rpc.account;
|
|||||||
|
|
||||||
import com.google.gerrit.common.data.GroupAdminService;
|
import com.google.gerrit.common.data.GroupAdminService;
|
||||||
import com.google.gerrit.common.data.GroupDetail;
|
import com.google.gerrit.common.data.GroupDetail;
|
||||||
|
import com.google.gerrit.common.data.GroupList;
|
||||||
import com.google.gerrit.common.data.GroupOptions;
|
import com.google.gerrit.common.data.GroupOptions;
|
||||||
import com.google.gerrit.common.errors.InactiveAccountException;
|
import com.google.gerrit.common.errors.InactiveAccountException;
|
||||||
import com.google.gerrit.common.errors.NameAlreadyUsedException;
|
import com.google.gerrit.common.errors.NameAlreadyUsedException;
|
||||||
@@ -88,28 +89,32 @@ class GroupAdminServiceImpl extends BaseServiceImplementation implements
|
|||||||
this.groupDetailFactory = groupDetailFactory;
|
this.groupDetailFactory = groupDetailFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visibleGroups(final AsyncCallback<List<AccountGroup>> callback) {
|
public void visibleGroups(final AsyncCallback<GroupList> callback) {
|
||||||
run(callback, new Action<List<AccountGroup>>() {
|
run(callback, new Action<GroupList>() {
|
||||||
public List<AccountGroup> run(ReviewDb db) throws OrmException {
|
public GroupList run(ReviewDb db) throws OrmException {
|
||||||
final IdentifiedUser user = identifiedUser.get();
|
final IdentifiedUser user = identifiedUser.get();
|
||||||
final List<AccountGroup> result;
|
final List<AccountGroup> list;
|
||||||
if (user.isAdministrator()) {
|
if (user.isAdministrator()) {
|
||||||
result = db.accountGroups().all().toList();
|
list = db.accountGroups().all().toList();
|
||||||
} else {
|
} else {
|
||||||
result = new ArrayList<AccountGroup>();
|
list = new ArrayList<AccountGroup>();
|
||||||
for(final AccountGroup group : db.accountGroups().all().toList()) {
|
for(final AccountGroup group : db.accountGroups().all().toList()) {
|
||||||
final GroupControl c = groupControlFactory.controlFor(group);
|
final GroupControl c = groupControlFactory.controlFor(group);
|
||||||
if (c.isVisible()) {
|
if (c.isVisible()) {
|
||||||
result.add(c.getAccountGroup());
|
list.add(c.getAccountGroup());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Collections.sort(result, new Comparator<AccountGroup>() {
|
Collections.sort(list, new Comparator<AccountGroup>() {
|
||||||
public int compare(final AccountGroup a, final AccountGroup b) {
|
public int compare(final AccountGroup a, final AccountGroup b) {
|
||||||
return a.getName().compareTo(b.getName());
|
return a.getName().compareTo(b.getName());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return result;
|
|
||||||
|
GroupList res = new GroupList();
|
||||||
|
res.setGroups(list);
|
||||||
|
res.setCanCreateGroup(user.getCapabilities().canCreateGroup());
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,46 @@ public class CapabilityControl {
|
|||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return true if the user can create an account for another user. */
|
||||||
|
public boolean canCreateAccount() {
|
||||||
|
return canPerform(GlobalCapability.CREATE_ACCOUNT) || user.isAdministrator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return true if the user can create a group. */
|
||||||
|
public boolean canCreateGroup() {
|
||||||
|
return canPerform(GlobalCapability.CREATE_GROUP) || user.isAdministrator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return true if the user can kill any running task. */
|
||||||
|
public boolean canKillTask() {
|
||||||
|
return canPerform(GlobalCapability.KILL_TASK) || user.isAdministrator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return true if the user can view the server caches. */
|
||||||
|
public boolean canViewCaches() {
|
||||||
|
return canPerform(GlobalCapability.VIEW_CACHES) || user.isAdministrator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return true if the user can flush the server's caches. */
|
||||||
|
public boolean canFlushCaches() {
|
||||||
|
return canPerform(GlobalCapability.FLUSH_CACHES) || user.isAdministrator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return true if the user can view open connections. */
|
||||||
|
public boolean canViewConnections() {
|
||||||
|
return canPerform(GlobalCapability.VIEW_CONNECTIONS) || user.isAdministrator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return true if the user can view the entire queue. */
|
||||||
|
public boolean canViewQueue() {
|
||||||
|
return canPerform(GlobalCapability.VIEW_QUEUE) || user.isAdministrator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return true if the user can force replication to any configured destination. */
|
||||||
|
public boolean canStartReplication() {
|
||||||
|
return canPerform(GlobalCapability.START_REPLICATION) || user.isAdministrator();
|
||||||
|
}
|
||||||
|
|
||||||
/** True if the user has this permission. Works only for non labels. */
|
/** True if the user has this permission. Works only for non labels. */
|
||||||
public boolean canPerform(String permissionName) {
|
public boolean canPerform(String permissionName) {
|
||||||
return !access(permissionName).isEmpty();
|
return !access(permissionName).isEmpty();
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public abstract class BaseCommand implements Command {
|
|||||||
private static final int PRIVATE_STATUS = 1 << 30;
|
private static final int PRIVATE_STATUS = 1 << 30;
|
||||||
static final int STATUS_CANCEL = PRIVATE_STATUS | 1;
|
static final int STATUS_CANCEL = PRIVATE_STATUS | 1;
|
||||||
static final int STATUS_NOT_FOUND = PRIVATE_STATUS | 2;
|
static final int STATUS_NOT_FOUND = PRIVATE_STATUS | 2;
|
||||||
static final int STATUS_NOT_ADMIN = PRIVATE_STATUS | 3;
|
public static final int STATUS_NOT_ADMIN = PRIVATE_STATUS | 3;
|
||||||
|
|
||||||
@Option(name = "--help", usage = "display this help text", aliases = {"-h"})
|
@Option(name = "--help", usage = "display this help text", aliases = {"-h"})
|
||||||
private boolean help;
|
private boolean help;
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import com.google.gerrit.server.IdentifiedUser;
|
|||||||
import com.google.gerrit.server.account.AccountByEmailCache;
|
import com.google.gerrit.server.account.AccountByEmailCache;
|
||||||
import com.google.gerrit.server.account.AccountCache;
|
import com.google.gerrit.server.account.AccountCache;
|
||||||
import com.google.gerrit.server.ssh.SshKeyCache;
|
import com.google.gerrit.server.ssh.SshKeyCache;
|
||||||
import com.google.gerrit.sshd.AdminCommand;
|
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.BaseCommand;
|
||||||
import com.google.gwtorm.client.OrmDuplicateKeyException;
|
import com.google.gwtorm.client.OrmDuplicateKeyException;
|
||||||
import com.google.gwtorm.client.OrmException;
|
import com.google.gwtorm.client.OrmException;
|
||||||
@@ -46,8 +45,7 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** Create a new user account. **/
|
/** Create a new user account. **/
|
||||||
@AdminCommand
|
final class CreateAccountCommand extends BaseCommand {
|
||||||
final class AdminCreateAccount extends BaseCommand {
|
|
||||||
@Option(name = "--group", aliases = {"-g"}, metaVar = "GROUP", usage = "groups to add account to")
|
@Option(name = "--group", aliases = {"-g"}, metaVar = "GROUP", usage = "groups to add account to")
|
||||||
private List<AccountGroup.Id> groups = new ArrayList<AccountGroup.Id>();
|
private List<AccountGroup.Id> groups = new ArrayList<AccountGroup.Id>();
|
||||||
|
|
||||||
@@ -83,6 +81,13 @@ final class AdminCreateAccount extends BaseCommand {
|
|||||||
startThread(new CommandRunnable() {
|
startThread(new CommandRunnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
|
if (!currentUser.getCapabilities().canCreateAccount()) {
|
||||||
|
String msg = String.format(
|
||||||
|
"fatal: %s does not have \"Create Account\" capability.",
|
||||||
|
currentUser.getUserName());
|
||||||
|
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
||||||
|
}
|
||||||
|
|
||||||
parseCommandLine();
|
parseCommandLine();
|
||||||
createAccount();
|
createAccount();
|
||||||
}
|
}
|
||||||
@@ -17,8 +17,8 @@ package com.google.gerrit.sshd.commands;
|
|||||||
import com.google.gerrit.common.errors.NameAlreadyUsedException;
|
import com.google.gerrit.common.errors.NameAlreadyUsedException;
|
||||||
import com.google.gerrit.reviewdb.Account;
|
import com.google.gerrit.reviewdb.Account;
|
||||||
import com.google.gerrit.reviewdb.AccountGroup;
|
import com.google.gerrit.reviewdb.AccountGroup;
|
||||||
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.account.PerformCreateGroup;
|
import com.google.gerrit.server.account.PerformCreateGroup;
|
||||||
import com.google.gerrit.sshd.AdminCommand;
|
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.BaseCommand;
|
||||||
import com.google.gwtorm.client.OrmException;
|
import com.google.gwtorm.client.OrmException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
@@ -27,7 +27,6 @@ import org.apache.sshd.server.Environment;
|
|||||||
import org.kohsuke.args4j.Argument;
|
import org.kohsuke.args4j.Argument;
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -36,8 +35,7 @@ import java.util.Set;
|
|||||||
* <p>
|
* <p>
|
||||||
* Optionally, puts an initial set of user in the newly created group.
|
* Optionally, puts an initial set of user in the newly created group.
|
||||||
*/
|
*/
|
||||||
@AdminCommand
|
final class CreateGroupCommand extends BaseCommand {
|
||||||
public class AdminCreateGroup extends BaseCommand {
|
|
||||||
@Option(name = "--owner", aliases = {"-o"}, metaVar = "GROUP", usage = "owning group, if not specified the group will be self-owning")
|
@Option(name = "--owner", aliases = {"-o"}, metaVar = "GROUP", usage = "owning group, if not specified the group will be self-owning")
|
||||||
private AccountGroup.Id ownerGroupId;
|
private AccountGroup.Id ownerGroupId;
|
||||||
|
|
||||||
@@ -64,14 +62,24 @@ public class AdminCreateGroup extends BaseCommand {
|
|||||||
initialGroups.add(id);
|
initialGroups.add(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private IdentifiedUser currentUser;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private PerformCreateGroup.Factory performCreateGroupFactory;
|
private PerformCreateGroup.Factory performCreateGroupFactory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(Environment env) throws IOException {
|
public void start(Environment env) {
|
||||||
startThread(new CommandRunnable() {
|
startThread(new CommandRunnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
|
if (!currentUser.getCapabilities().canCreateGroup()) {
|
||||||
|
String msg = String.format(
|
||||||
|
"fatal: %s does not have \"Create Group\" capability.",
|
||||||
|
currentUser.getUserName());
|
||||||
|
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
||||||
|
}
|
||||||
|
|
||||||
parseCommandLine();
|
parseCommandLine();
|
||||||
createGroup();
|
createGroup();
|
||||||
}
|
}
|
||||||
@@ -34,11 +34,11 @@ public class DefaultCommandModule extends CommandModule {
|
|||||||
// SlaveCommandModule.
|
// SlaveCommandModule.
|
||||||
|
|
||||||
command(gerrit).toProvider(new DispatchCommandProvider(gerrit));
|
command(gerrit).toProvider(new DispatchCommandProvider(gerrit));
|
||||||
command(gerrit, "flush-caches").to(AdminFlushCaches.class);
|
command(gerrit, "flush-caches").to(FlushCaches.class);
|
||||||
command(gerrit, "ls-projects").to(ListProjects.class);
|
command(gerrit, "ls-projects").to(ListProjects.class);
|
||||||
command(gerrit, "query").to(Query.class);
|
command(gerrit, "query").to(Query.class);
|
||||||
command(gerrit, "show-caches").to(AdminShowCaches.class);
|
command(gerrit, "show-caches").to(ShowCaches.class);
|
||||||
command(gerrit, "show-connections").to(AdminShowConnections.class);
|
command(gerrit, "show-connections").to(ShowConnections.class);
|
||||||
command(gerrit, "show-queue").to(ShowQueue.class);
|
command(gerrit, "show-queue").to(ShowQueue.class);
|
||||||
command(gerrit, "stream-events").to(StreamEvents.class);
|
command(gerrit, "stream-events").to(StreamEvents.class);
|
||||||
command(gerrit, "version").to(VersionCommand.class);
|
command(gerrit, "version").to(VersionCommand.class);
|
||||||
@@ -48,7 +48,7 @@ public class DefaultCommandModule extends CommandModule {
|
|||||||
command(git, "upload-pack").to(Upload.class);
|
command(git, "upload-pack").to(Upload.class);
|
||||||
|
|
||||||
command("ps").to(ShowQueue.class);
|
command("ps").to(ShowQueue.class);
|
||||||
command("kill").to(AdminKill.class);
|
command("kill").to(KillCommand.class);
|
||||||
command("scp").to(ScpCommand.class);
|
command("scp").to(ScpCommand.class);
|
||||||
|
|
||||||
// Honor the legacy hyphenated forms as aliases for the non-hyphenated forms
|
// Honor the legacy hyphenated forms as aliases for the non-hyphenated forms
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
|
|
||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
import com.google.gerrit.sshd.AdminCommand;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
|
import com.google.gerrit.sshd.BaseCommand;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import net.sf.ehcache.Ehcache;
|
import net.sf.ehcache.Ehcache;
|
||||||
|
|
||||||
@@ -27,8 +29,9 @@ import java.util.List;
|
|||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
|
|
||||||
/** Causes the caches to purge all entries and reload. */
|
/** Causes the caches to purge all entries and reload. */
|
||||||
@AdminCommand
|
final class FlushCaches extends CacheCommand {
|
||||||
final class AdminFlushCaches extends CacheCommand {
|
private static final String WEB_SESSIONS = "web_sessions";
|
||||||
|
|
||||||
@Option(name = "--cache", usage = "flush named cache", metaVar = "NAME")
|
@Option(name = "--cache", usage = "flush named cache", metaVar = "NAME")
|
||||||
private List<String> caches = new ArrayList<String>();
|
private List<String> caches = new ArrayList<String>();
|
||||||
|
|
||||||
@@ -38,6 +41,9 @@ final class AdminFlushCaches extends CacheCommand {
|
|||||||
@Option(name = "--list", usage = "list available caches")
|
@Option(name = "--list", usage = "list available caches")
|
||||||
private boolean list;
|
private boolean list;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
IdentifiedUser currentUser;
|
||||||
|
|
||||||
private PrintWriter p;
|
private PrintWriter p;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -45,6 +51,13 @@ final class AdminFlushCaches extends CacheCommand {
|
|||||||
startThread(new CommandRunnable() {
|
startThread(new CommandRunnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
|
if (!currentUser.getCapabilities().canFlushCaches()) {
|
||||||
|
String msg = String.format(
|
||||||
|
"fatal: %s does not have \"Flush Caches\" capability.",
|
||||||
|
currentUser.getUserName());
|
||||||
|
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
||||||
|
}
|
||||||
|
|
||||||
parseCommandLine();
|
parseCommandLine();
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
@@ -52,6 +65,13 @@ final class AdminFlushCaches extends CacheCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void flush() throws Failure {
|
private void flush() throws Failure {
|
||||||
|
if (caches.contains(WEB_SESSIONS) && !currentUser.isAdministrator()) {
|
||||||
|
String msg = String.format(
|
||||||
|
"fatal: only site administrators can flush %s",
|
||||||
|
WEB_SESSIONS);
|
||||||
|
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
||||||
|
}
|
||||||
|
|
||||||
p = toPrintWriter(err);
|
p = toPrintWriter(err);
|
||||||
if (list) {
|
if (list) {
|
||||||
if (all || caches.size() > 0) {
|
if (all || caches.size() > 0) {
|
||||||
@@ -113,7 +133,7 @@ final class AdminFlushCaches extends CacheCommand {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
} else if (all) {
|
} else if (all) {
|
||||||
if ("web_sessions".equals(cacheName)) {
|
if (WEB_SESSIONS.equals(cacheName)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -14,10 +14,10 @@
|
|||||||
|
|
||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.git.WorkQueue;
|
import com.google.gerrit.server.git.WorkQueue;
|
||||||
import com.google.gerrit.server.git.WorkQueue.Task;
|
import com.google.gerrit.server.git.WorkQueue.Task;
|
||||||
import com.google.gerrit.server.util.IdGenerator;
|
import com.google.gerrit.server.util.IdGenerator;
|
||||||
import com.google.gerrit.sshd.AdminCommand;
|
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.BaseCommand;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
@@ -29,8 +29,10 @@ import java.util.HashSet;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/** Kill a task in the work queue. */
|
/** Kill a task in the work queue. */
|
||||||
@AdminCommand
|
final class KillCommand extends BaseCommand {
|
||||||
final class AdminKill extends BaseCommand {
|
@Inject
|
||||||
|
private IdentifiedUser currentUser;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private WorkQueue workQueue;
|
private WorkQueue workQueue;
|
||||||
|
|
||||||
@@ -50,8 +52,15 @@ final class AdminKill extends BaseCommand {
|
|||||||
startThread(new CommandRunnable() {
|
startThread(new CommandRunnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
|
if (!currentUser.getCapabilities().canKillTask()) {
|
||||||
|
String msg = String.format(
|
||||||
|
"fatal: %s does not have \"Kill Task\" capability.",
|
||||||
|
currentUser.getUserName());
|
||||||
|
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
||||||
|
}
|
||||||
|
|
||||||
parseCommandLine();
|
parseCommandLine();
|
||||||
AdminKill.this.commitMurder();
|
KillCommand.this.commitMurder();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -26,13 +26,13 @@ public class MasterCommandModule extends CommandModule {
|
|||||||
final CommandName gerrit = Commands.named("gerrit");
|
final CommandName gerrit = Commands.named("gerrit");
|
||||||
|
|
||||||
command(gerrit, "approve").to(ReviewCommand.class);
|
command(gerrit, "approve").to(ReviewCommand.class);
|
||||||
command(gerrit, "create-account").to(AdminCreateAccount.class);
|
command(gerrit, "create-account").to(CreateAccountCommand.class);
|
||||||
command(gerrit, "create-group").to(AdminCreateGroup.class);
|
command(gerrit, "create-group").to(CreateGroupCommand.class);
|
||||||
command(gerrit, "create-project").to(CreateProject.class);
|
command(gerrit, "create-project").to(CreateProject.class);
|
||||||
command(gerrit, "gsql").to(AdminQueryShell.class);
|
command(gerrit, "gsql").to(AdminQueryShell.class);
|
||||||
command(gerrit, "modify-reviewers").to(ModifyReviewersCommand.class);
|
command(gerrit, "modify-reviewers").to(ModifyReviewersCommand.class);
|
||||||
command(gerrit, "receive-pack").to(Receive.class);
|
command(gerrit, "receive-pack").to(Receive.class);
|
||||||
command(gerrit, "replicate").to(AdminReplicate.class);
|
command(gerrit, "replicate").to(Replicate.class);
|
||||||
command(gerrit, "set-project-parent").to(AdminSetParent.class);
|
command(gerrit, "set-project-parent").to(AdminSetParent.class);
|
||||||
command(gerrit, "review").to(ReviewCommand.class);
|
command(gerrit, "review").to(ReviewCommand.class);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,10 @@
|
|||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
import com.google.gerrit.reviewdb.Project;
|
import com.google.gerrit.reviewdb.Project;
|
||||||
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.git.PushAllProjectsOp;
|
import com.google.gerrit.server.git.PushAllProjectsOp;
|
||||||
import com.google.gerrit.server.git.ReplicationQueue;
|
import com.google.gerrit.server.git.ReplicationQueue;
|
||||||
import com.google.gerrit.server.project.ProjectCache;
|
import com.google.gerrit.server.project.ProjectCache;
|
||||||
import com.google.gerrit.sshd.AdminCommand;
|
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.BaseCommand;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
@@ -31,8 +31,7 @@ import java.util.List;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/** Force a project to replicate, again. */
|
/** Force a project to replicate, again. */
|
||||||
@AdminCommand
|
final class Replicate extends BaseCommand {
|
||||||
final class AdminReplicate extends BaseCommand {
|
|
||||||
@Option(name = "--all", usage = "push all known projects")
|
@Option(name = "--all", usage = "push all known projects")
|
||||||
private boolean all;
|
private boolean all;
|
||||||
|
|
||||||
@@ -42,6 +41,9 @@ final class AdminReplicate extends BaseCommand {
|
|||||||
@Argument(index = 0, multiValued = true, metaVar = "PROJECT", usage = "project name")
|
@Argument(index = 0, multiValued = true, metaVar = "PROJECT", usage = "project name")
|
||||||
private List<String> projectNames = new ArrayList<String>(2);
|
private List<String> projectNames = new ArrayList<String>(2);
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
IdentifiedUser currentUser;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private PushAllProjectsOp.Factory pushAllOpFactory;
|
private PushAllProjectsOp.Factory pushAllOpFactory;
|
||||||
|
|
||||||
@@ -56,8 +58,15 @@ final class AdminReplicate extends BaseCommand {
|
|||||||
startThread(new CommandRunnable() {
|
startThread(new CommandRunnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
|
if (!currentUser.getCapabilities().canStartReplication()) {
|
||||||
|
String msg = String.format(
|
||||||
|
"fatal: %s does not have \"Start Replication\" capability.",
|
||||||
|
currentUser.getUserName());
|
||||||
|
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
||||||
|
}
|
||||||
|
|
||||||
parseCommandLine();
|
parseCommandLine();
|
||||||
AdminReplicate.this.schedule();
|
Replicate.this.schedule();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,9 @@
|
|||||||
|
|
||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
import com.google.gerrit.sshd.AdminCommand;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
|
import com.google.gerrit.sshd.BaseCommand;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import net.sf.ehcache.Ehcache;
|
import net.sf.ehcache.Ehcache;
|
||||||
import net.sf.ehcache.Statistics;
|
import net.sf.ehcache.Statistics;
|
||||||
@@ -26,8 +28,10 @@ import org.eclipse.jgit.storage.file.WindowCacheStatAccessor;
|
|||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
/** Show the current cache states. */
|
/** Show the current cache states. */
|
||||||
@AdminCommand
|
final class ShowCaches extends CacheCommand {
|
||||||
final class AdminShowCaches extends CacheCommand {
|
@Inject
|
||||||
|
IdentifiedUser currentUser;
|
||||||
|
|
||||||
private PrintWriter p;
|
private PrintWriter p;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -35,6 +39,13 @@ final class AdminShowCaches extends CacheCommand {
|
|||||||
startThread(new CommandRunnable() {
|
startThread(new CommandRunnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
|
if (!currentUser.getCapabilities().canViewCaches()) {
|
||||||
|
String msg = String.format(
|
||||||
|
"fatal: %s does not have \"View Caches\" capability.",
|
||||||
|
currentUser.getUserName());
|
||||||
|
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
||||||
|
}
|
||||||
|
|
||||||
parseCommandLine();
|
parseCommandLine();
|
||||||
display();
|
display();
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,6 @@ package com.google.gerrit.sshd.commands;
|
|||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.util.IdGenerator;
|
import com.google.gerrit.server.util.IdGenerator;
|
||||||
import com.google.gerrit.sshd.AdminCommand;
|
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.BaseCommand;
|
||||||
import com.google.gerrit.sshd.SshDaemon;
|
import com.google.gerrit.sshd.SshDaemon;
|
||||||
import com.google.gerrit.sshd.SshSession;
|
import com.google.gerrit.sshd.SshSession;
|
||||||
@@ -41,13 +40,15 @@ import java.util.Date;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** Show the current SSH connections. */
|
/** Show the current SSH connections. */
|
||||||
@AdminCommand
|
final class ShowConnections extends BaseCommand {
|
||||||
final class AdminShowConnections extends BaseCommand {
|
|
||||||
@Option(name = "--numeric", aliases = {"-n"}, usage = "don't resolve names")
|
@Option(name = "--numeric", aliases = {"-n"}, usage = "don't resolve names")
|
||||||
private boolean numeric;
|
private boolean numeric;
|
||||||
|
|
||||||
private PrintWriter p;
|
private PrintWriter p;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
IdentifiedUser currentUser;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private SshDaemon daemon;
|
private SshDaemon daemon;
|
||||||
|
|
||||||
@@ -56,8 +57,15 @@ final class AdminShowConnections extends BaseCommand {
|
|||||||
startThread(new CommandRunnable() {
|
startThread(new CommandRunnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
|
if (!currentUser.getCapabilities().canViewConnections()) {
|
||||||
|
String msg = String.format(
|
||||||
|
"fatal: %s does not have \"View Connections\" capability.",
|
||||||
|
currentUser.getUserName());
|
||||||
|
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
||||||
|
}
|
||||||
|
|
||||||
parseCommandLine();
|
parseCommandLine();
|
||||||
AdminShowConnections.this.display();
|
ShowConnections.this.display();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
import com.google.gerrit.reviewdb.Project;
|
import com.google.gerrit.reviewdb.Project;
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.git.WorkQueue;
|
import com.google.gerrit.server.git.WorkQueue;
|
||||||
import com.google.gerrit.server.git.WorkQueue.ProjectTask;
|
import com.google.gerrit.server.git.WorkQueue.ProjectTask;
|
||||||
import com.google.gerrit.server.git.WorkQueue.Task;
|
import com.google.gerrit.server.git.WorkQueue.Task;
|
||||||
@@ -50,7 +50,7 @@ final class ShowQueue extends BaseCommand {
|
|||||||
private ProjectCache projectCache;
|
private ProjectCache projectCache;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CurrentUser userProvider;
|
private IdentifiedUser currentUser;
|
||||||
|
|
||||||
private PrintWriter p;
|
private PrintWriter p;
|
||||||
private int columns = 80;
|
private int columns = 80;
|
||||||
@@ -110,7 +110,7 @@ final class ShowQueue extends BaseCommand {
|
|||||||
|
|
||||||
int numberOfPendingTasks = 0;
|
int numberOfPendingTasks = 0;
|
||||||
final long now = System.currentTimeMillis();
|
final long now = System.currentTimeMillis();
|
||||||
final boolean isAdministrator = userProvider.isAdministrator();
|
final boolean viewAll = currentUser.getCapabilities().canViewQueue();
|
||||||
|
|
||||||
for (final Task<?> task : pending) {
|
for (final Task<?> task : pending) {
|
||||||
final long delay = task.getDelay(TimeUnit.MILLISECONDS);
|
final long delay = task.getDelay(TimeUnit.MILLISECONDS);
|
||||||
@@ -137,7 +137,7 @@ final class ShowQueue extends BaseCommand {
|
|||||||
Project.NameKey projectName = null;
|
Project.NameKey projectName = null;
|
||||||
String remoteName = null;
|
String remoteName = null;
|
||||||
|
|
||||||
if (!isAdministrator) {
|
if (!viewAll) {
|
||||||
if (task instanceof ProjectTask<?>) {
|
if (task instanceof ProjectTask<?>) {
|
||||||
projectName = ((ProjectTask<?>)task).getProjectNameKey();
|
projectName = ((ProjectTask<?>)task).getProjectNameKey();
|
||||||
remoteName = ((ProjectTask<?>)task).getRemoteName();
|
remoteName = ((ProjectTask<?>)task).getRemoteName();
|
||||||
@@ -149,7 +149,7 @@ final class ShowQueue extends BaseCommand {
|
|||||||
e = projectCache.get(projectName);
|
e = projectCache.get(projectName);
|
||||||
}
|
}
|
||||||
|
|
||||||
regularUserCanSee = e != null && e.controlFor(userProvider).isVisible();
|
regularUserCanSee = e != null && e.controlFor(currentUser).isVisible();
|
||||||
|
|
||||||
if (regularUserCanSee) {
|
if (regularUserCanSee) {
|
||||||
numberOfPendingTasks++;
|
numberOfPendingTasks++;
|
||||||
@@ -157,7 +157,7 @@ final class ShowQueue extends BaseCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Shows information about tasks depending on the user rights
|
// Shows information about tasks depending on the user rights
|
||||||
if (isAdministrator || (!hasCustomizedPrint && regularUserCanSee)) {
|
if (viewAll || (!hasCustomizedPrint && regularUserCanSee)) {
|
||||||
p.print(String.format("%8s %-12s %-8s %s\n", //
|
p.print(String.format("%8s %-12s %-8s %s\n", //
|
||||||
id(task.getTaskId()), start, "", format(task)));
|
id(task.getTaskId()), start, "", format(task)));
|
||||||
} else if (regularUserCanSee) {
|
} else if (regularUserCanSee) {
|
||||||
@@ -174,7 +174,7 @@ final class ShowQueue extends BaseCommand {
|
|||||||
p.print("----------------------------------------------"
|
p.print("----------------------------------------------"
|
||||||
+ "--------------------------------\n");
|
+ "--------------------------------\n");
|
||||||
|
|
||||||
if (isAdministrator) {
|
if (viewAll) {
|
||||||
numberOfPendingTasks = pending.size();
|
numberOfPendingTasks = pending.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user