Refactor SSH command permission checks to use CurrentUser
This is a step in the direction of whacking the static decision logic used by BaseServiceImplementation and making it based on the project and current user concepts instead. Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
@@ -29,6 +29,7 @@ import com.google.gerrit.client.reviewdb.ReviewDb;
|
||||
import com.google.gerrit.client.rpc.Common;
|
||||
import com.google.gerrit.server.ChangeUtil;
|
||||
import com.google.gerrit.server.GerritServer;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.config.CanonicalWebUrl;
|
||||
import com.google.gerrit.server.config.Nullable;
|
||||
import com.google.gerrit.server.mail.EmailException;
|
||||
@@ -116,6 +117,7 @@ public class MergeOp {
|
||||
private final Provider<String> urlProvider;
|
||||
private final GerritConfig gerritConfig;
|
||||
private final PatchSetInfoFactory patchSetInfoFactory;
|
||||
private final IdentifiedUser.Factory identifiedUserFactory;
|
||||
|
||||
private final PersonIdent myIdent;
|
||||
private final Branch.NameKey destBranch;
|
||||
@@ -137,7 +139,7 @@ public class MergeOp {
|
||||
final MergeFailSender.Factory mfsf,
|
||||
@CanonicalWebUrl @Nullable final Provider<String> cwu,
|
||||
final GerritConfig gc, final PatchSetInfoFactory psif,
|
||||
@Assisted final Branch.NameKey branch) {
|
||||
final IdentifiedUser.Factory iuf, @Assisted final Branch.NameKey branch) {
|
||||
server = gs;
|
||||
schemaFactory = sf;
|
||||
replication = rq;
|
||||
@@ -146,6 +148,7 @@ public class MergeOp {
|
||||
urlProvider = cwu;
|
||||
gerritConfig = gc;
|
||||
patchSetInfoFactory = psif;
|
||||
identifiedUserFactory = iuf;
|
||||
|
||||
myIdent = server.newGerritPersonIdent();
|
||||
destBranch = branch;
|
||||
@@ -524,16 +527,10 @@ public class MergeOp {
|
||||
}
|
||||
|
||||
private void setRefLogIdent(final ChangeApproval submitAudit) {
|
||||
if (submitAudit == null) {
|
||||
return;
|
||||
if (submitAudit != null) {
|
||||
branchUpdate.setRefLogIdent(identifiedUserFactory.create(
|
||||
submitAudit.getAccountId()).toPersonIdent());
|
||||
}
|
||||
|
||||
final Account a = Common.getAccountCache().get(submitAudit.getAccountId());
|
||||
if (a == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
branchUpdate.setRefLogIdent(ChangeUtil.toReflogIdent(a, null));
|
||||
}
|
||||
|
||||
private void cherryPickChanges() throws MergeException {
|
||||
|
||||
45
src/main/java/com/google/gerrit/server/AnonymousUser.java
Normal file
45
src/main/java/com/google/gerrit/server/AnonymousUser.java
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright (C) 2009 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.server;
|
||||
|
||||
import com.google.gerrit.client.reviewdb.AccountGroup;
|
||||
import com.google.gerrit.client.reviewdb.SystemConfig;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/** An anonymous user who has not yet authenticated. */
|
||||
@Singleton
|
||||
public class AnonymousUser extends CurrentUser {
|
||||
private final Set<AccountGroup.Id> effectiveGroups;
|
||||
|
||||
@Inject
|
||||
AnonymousUser(final SystemConfig cfg) {
|
||||
super(cfg);
|
||||
effectiveGroups = Collections.singleton(cfg.anonymousGroupId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<AccountGroup.Id> getEffectiveGroups() {
|
||||
return effectiveGroups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ANONYMOUS";
|
||||
}
|
||||
}
|
||||
@@ -14,26 +14,20 @@
|
||||
|
||||
package com.google.gerrit.server;
|
||||
|
||||
import com.google.gerrit.client.reviewdb.Account;
|
||||
import com.google.gerrit.client.reviewdb.Change;
|
||||
import com.google.gerrit.client.reviewdb.ReviewDb;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
|
||||
import org.spearce.jgit.lib.PersonIdent;
|
||||
import org.spearce.jgit.util.Base64;
|
||||
import org.spearce.jgit.util.NB;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
|
||||
public class ChangeUtil {
|
||||
private static int uuidPrefix;
|
||||
private static int uuidSeq;
|
||||
|
||||
/**
|
||||
* Generate a new unique identifier for change message entities.
|
||||
*
|
||||
*
|
||||
* @param db the database connection, used to increment the change message
|
||||
* allocation sequence.
|
||||
* @return the new unique identifier.
|
||||
@@ -45,55 +39,6 @@ public class ChangeUtil {
|
||||
return Base64.encodeBytes(raw);
|
||||
}
|
||||
|
||||
public static PersonIdent toPersonIdent(final Account userAccount) {
|
||||
String name = userAccount.getFullName();
|
||||
if (name == null) {
|
||||
name = userAccount.getPreferredEmail();
|
||||
}
|
||||
if (name == null) {
|
||||
name = "Anonymous Coward";
|
||||
}
|
||||
|
||||
String user = "account-" + userAccount.getId().toString();
|
||||
String host = "unknown";
|
||||
return new PersonIdent(name, user + "@" + host);
|
||||
}
|
||||
|
||||
public static PersonIdent toReflogIdent(final Account userAccount,
|
||||
final SocketAddress remotePeer) {
|
||||
String name = userAccount.getFullName();
|
||||
if (name == null) {
|
||||
name = userAccount.getPreferredEmail();
|
||||
}
|
||||
if (name == null) {
|
||||
name = "Anonymous Coward";
|
||||
}
|
||||
|
||||
final String userId = "account-" + userAccount.getId().toString();
|
||||
final String user;
|
||||
if (userAccount.getSshUserName() != null) {
|
||||
user = userAccount.getSshUserName() + "|" + userId;
|
||||
} else {
|
||||
user = userId;
|
||||
}
|
||||
|
||||
String host = null;
|
||||
if (remotePeer instanceof InetSocketAddress) {
|
||||
final InetSocketAddress sa = (InetSocketAddress) remotePeer;
|
||||
final InetAddress in = sa.getAddress();
|
||||
if (in != null) {
|
||||
host = in.getCanonicalHostName();
|
||||
} else {
|
||||
host = sa.getHostName();
|
||||
}
|
||||
}
|
||||
if (host == null) {
|
||||
host = "unknown";
|
||||
}
|
||||
|
||||
return new PersonIdent(name, user + "@" + host);
|
||||
}
|
||||
|
||||
private static synchronized void fill(byte[] raw, ReviewDb db)
|
||||
throws OrmException {
|
||||
if (uuidSeq == 0) {
|
||||
@@ -123,7 +68,7 @@ public class ChangeUtil {
|
||||
}
|
||||
|
||||
private static final char[] hexchar =
|
||||
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', //
|
||||
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', //
|
||||
'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
|
||||
private static void formatHexInt(final StringBuilder dst, final int p, int w) {
|
||||
|
||||
@@ -14,26 +14,83 @@
|
||||
|
||||
package com.google.gerrit.server;
|
||||
|
||||
import com.google.gerrit.client.data.ProjectCache;
|
||||
import com.google.gerrit.client.reviewdb.AccountGroup;
|
||||
import com.google.gerrit.client.reviewdb.ApprovalCategory;
|
||||
import com.google.gerrit.client.reviewdb.ProjectRight;
|
||||
import com.google.gerrit.client.reviewdb.SystemConfig;
|
||||
import com.google.gerrit.client.rpc.Common;
|
||||
import com.google.inject.servlet.RequestScoped;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Information about the currently logged in user.
|
||||
* <p>
|
||||
* This is a {@link RequestScoped} property managed by Guice.
|
||||
*
|
||||
* @see AnonymousUser
|
||||
* @see IdentifiedUser
|
||||
*/
|
||||
public abstract class CurrentUser {
|
||||
/** An anonymous user, the identity is not known. */
|
||||
public static final CurrentUser ANONYMOUS = new Anonymous();
|
||||
protected final SystemConfig systemConfig;
|
||||
|
||||
private static class Anonymous extends CurrentUser {
|
||||
private Anonymous() {
|
||||
protected CurrentUser(final SystemConfig cfg) {
|
||||
systemConfig = cfg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set of groups the user is currently a member of.
|
||||
* <p>
|
||||
* The returned set may be a subset of the user's actual groups; if the user's
|
||||
* account is currently deemed to be untrusted then the effective group set is
|
||||
* only the anonymous and registered user groups. To enable additional groups
|
||||
* (and gain their granted permissions) the user must update their account to
|
||||
* use only trusted authentication providers.
|
||||
*
|
||||
* @return active groups for this user.
|
||||
*/
|
||||
public abstract Set<AccountGroup.Id> getEffectiveGroups();
|
||||
|
||||
@Deprecated
|
||||
public final boolean isAdministrator() {
|
||||
return getEffectiveGroups().contains(systemConfig.adminGroupId);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean canPerform(final ProjectCache.Entry e,
|
||||
final ApprovalCategory.Id actionId, final short requireValue) {
|
||||
if (e == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ANONYMOUS";
|
||||
int val = Integer.MIN_VALUE;
|
||||
for (final ProjectRight pr : e.getRights()) {
|
||||
if (actionId.equals(pr.getApprovalCategoryId())
|
||||
&& getEffectiveGroups().contains(pr.getAccountGroupId())) {
|
||||
if (val < 0 && pr.getMaxValue() > 0) {
|
||||
// If one of the user's groups had denied them access, but
|
||||
// this group grants them access, prefer the grant over
|
||||
// the denial. We have to break the tie somehow and we
|
||||
// prefer being "more open" to being "more closed".
|
||||
//
|
||||
val = pr.getMaxValue();
|
||||
} else {
|
||||
// Otherwise we use the largest value we can get.
|
||||
//
|
||||
val = Math.max(pr.getMaxValue(), val);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (val == Integer.MIN_VALUE && actionId.canInheritFromWildProject()) {
|
||||
for (final ProjectRight pr : Common.getProjectCache().getWildcardRights()) {
|
||||
if (actionId.equals(pr.getApprovalCategoryId())
|
||||
&& getEffectiveGroups().contains(pr.getAccountGroupId())) {
|
||||
val = Math.max(pr.getMaxValue(), val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return val >= requireValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,26 +15,41 @@
|
||||
package com.google.gerrit.server;
|
||||
|
||||
import com.google.gerrit.client.reviewdb.Account;
|
||||
import com.google.gerrit.client.reviewdb.AccountGroup;
|
||||
import com.google.gerrit.client.reviewdb.SystemConfig;
|
||||
import com.google.gerrit.client.rpc.Common;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.inject.servlet.RequestScoped;
|
||||
|
||||
import org.spearce.jgit.lib.PersonIdent;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.Set;
|
||||
|
||||
/** An authenticated user. */
|
||||
@RequestScoped
|
||||
public class IdentifiedUser extends CurrentUser {
|
||||
public static final class Factory {
|
||||
public IdentifiedUser create(final Account.Id id) {
|
||||
return new IdentifiedUser(id);
|
||||
}
|
||||
public interface Factory {
|
||||
IdentifiedUser create(Account.Id id);
|
||||
}
|
||||
|
||||
private final Account.Id accountId;
|
||||
|
||||
@Inject(optional = true)
|
||||
@RemotePeer
|
||||
private Provider<SocketAddress> remotePeerProvider;
|
||||
|
||||
private Account account;
|
||||
private Set<AccountGroup.Id> effectiveGroups;
|
||||
|
||||
@Inject
|
||||
IdentifiedUser(@Assisted final Account.Id i) {
|
||||
accountId = i;
|
||||
IdentifiedUser(final SystemConfig cfg, @Assisted final Account.Id id) {
|
||||
super(cfg);
|
||||
accountId = id;
|
||||
}
|
||||
|
||||
/** The account identity for the user. */
|
||||
@@ -49,8 +64,54 @@ public class IdentifiedUser extends CurrentUser {
|
||||
return account;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<AccountGroup.Id> getEffectiveGroups() {
|
||||
if (effectiveGroups == null) {
|
||||
effectiveGroups =
|
||||
Common.getGroupCache().getEffectiveGroups(getAccountId());
|
||||
}
|
||||
return effectiveGroups;
|
||||
}
|
||||
|
||||
public PersonIdent toPersonIdent() {
|
||||
final Account ua = getAccount();
|
||||
String name = ua.getFullName();
|
||||
if (name == null) {
|
||||
name = ua.getPreferredEmail();
|
||||
}
|
||||
if (name == null) {
|
||||
name = "Anonymous Coward";
|
||||
}
|
||||
|
||||
final String userId = "account-" + ua.getId().toString();
|
||||
final String user;
|
||||
if (ua.getSshUserName() != null) {
|
||||
user = ua.getSshUserName() + "|" + userId;
|
||||
} else {
|
||||
user = userId;
|
||||
}
|
||||
|
||||
String host = null;
|
||||
final SocketAddress remotePeer =
|
||||
remotePeerProvider != null ? remotePeerProvider.get() : null;
|
||||
if (remotePeer instanceof InetSocketAddress) {
|
||||
final InetSocketAddress sa = (InetSocketAddress) remotePeer;
|
||||
final InetAddress in = sa.getAddress();
|
||||
if (in != null) {
|
||||
host = in.getCanonicalHostName();
|
||||
} else {
|
||||
host = sa.getHostName();
|
||||
}
|
||||
}
|
||||
if (host == null) {
|
||||
host = "unknown";
|
||||
}
|
||||
|
||||
return new PersonIdent(name, user + "@" + host);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CurrentUser[" + getAccountId() + "]";
|
||||
return "IdentifiedUser[account " + getAccountId() + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.google.gerrit.git.PushReplication;
|
||||
import com.google.gerrit.git.ReloadSubmitQueueOp;
|
||||
import com.google.gerrit.git.ReplicationQueue;
|
||||
import com.google.gerrit.git.WorkQueue;
|
||||
import com.google.gerrit.server.AnonymousUser;
|
||||
import com.google.gerrit.server.ContactStore;
|
||||
import com.google.gerrit.server.EncryptedContactStoreProvider;
|
||||
import com.google.gerrit.server.FileTypeRegistry;
|
||||
@@ -61,6 +62,7 @@ public class GerritServerModule extends FactoryModule {
|
||||
bind(Config.class).annotatedWith(GerritServerConfig.class).toProvider(
|
||||
GerritServerConfigProvider.class).in(SINGLETON);
|
||||
bind(AuthConfig.class).in(SINGLETON);
|
||||
bind(AnonymousUser.class);
|
||||
|
||||
// Note that the CanonicalWebUrl itself must not be a singleton, but its
|
||||
// provider must be.
|
||||
@@ -95,7 +97,7 @@ public class GerritServerModule extends FactoryModule {
|
||||
bind(EmailSender.class).to(SmtpEmailSender.class).in(SINGLETON);
|
||||
factory(PatchSetImporter.Factory.class);
|
||||
bind(PatchSetInfoFactory.class);
|
||||
bind(IdentifiedUser.Factory.class);
|
||||
factory(IdentifiedUser.Factory.class);
|
||||
|
||||
factory(AbandonedSender.Factory.class);
|
||||
factory(AddReviewerSender.Factory.class);
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.google.gerrit.client.rpc.Common.CurrentAccountImpl;
|
||||
import com.google.gerrit.git.PushAllProjectsOp;
|
||||
import com.google.gerrit.git.ReloadSubmitQueueOp;
|
||||
import com.google.gerrit.git.WorkQueue;
|
||||
import com.google.gerrit.server.AnonymousUser;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.config.AuthConfig;
|
||||
@@ -172,7 +173,7 @@ public class GerritServletConfig extends GuiceServletContextListener {
|
||||
CurrentUser u = webUser.get();
|
||||
if (u instanceof IdentifiedUser) {
|
||||
return ((IdentifiedUser) u).getAccountId();
|
||||
} else if (u == CurrentUser.ANONYMOUS) {
|
||||
} else if (u instanceof AnonymousUser) {
|
||||
return null;
|
||||
} else {
|
||||
throw new OutOfScopeException("Cannot determine current user");
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package com.google.gerrit.server.http;
|
||||
|
||||
import com.google.gerrit.client.reviewdb.Account;
|
||||
import com.google.gerrit.server.AnonymousUser;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.inject.Inject;
|
||||
@@ -24,17 +25,20 @@ import com.google.inject.servlet.RequestScoped;
|
||||
@RequestScoped
|
||||
class HttpCurrentUserProvider implements Provider<CurrentUser> {
|
||||
private final GerritCall call;
|
||||
private final IdentifiedUser.Factory factory;
|
||||
private final AnonymousUser anonymous;
|
||||
private final IdentifiedUser.Factory identified;
|
||||
|
||||
@Inject
|
||||
HttpCurrentUserProvider(final GerritCall c, final IdentifiedUser.Factory f) {
|
||||
HttpCurrentUserProvider(final GerritCall c, final AnonymousUser a,
|
||||
final IdentifiedUser.Factory f) {
|
||||
call = c;
|
||||
factory = f;
|
||||
anonymous = a;
|
||||
identified = f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CurrentUser get() {
|
||||
final Account.Id id = call.getAccountId();
|
||||
return id != null ? factory.create(id) : CurrentUser.ANONYMOUS;
|
||||
return id != null ? identified.create(id) : anonymous;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import com.google.gerrit.git.ReplicationQueue;
|
||||
import com.google.gerrit.server.BaseServiceImplementation;
|
||||
import com.google.gerrit.server.ChangeUtil;
|
||||
import com.google.gerrit.server.GerritServer;
|
||||
import com.google.gerrit.server.RemotePeer;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwtjsonrpc.client.VoidResult;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
@@ -58,7 +58,6 @@ import org.spearce.jgit.revwalk.RevCommit;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -72,16 +71,16 @@ class ProjectAdminServiceImpl extends BaseServiceImplementation implements
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private final GerritServer server;
|
||||
private final ReplicationQueue replication;
|
||||
private final Provider<SocketAddress> remotePeer;
|
||||
private final Provider<IdentifiedUser> identifiedUser;
|
||||
|
||||
@Inject
|
||||
ProjectAdminServiceImpl(final SchemaFactory<ReviewDb> sf,
|
||||
final GerritServer gs, final ReplicationQueue rq,
|
||||
@RemotePeer final Provider<SocketAddress> rp) {
|
||||
final Provider<IdentifiedUser> iu) {
|
||||
super(sf);
|
||||
server = gs;
|
||||
replication = rq;
|
||||
remotePeer = rp;
|
||||
identifiedUser = iu;
|
||||
}
|
||||
|
||||
public void ownedProjects(final AsyncCallback<List<Project>> callback) {
|
||||
@@ -423,7 +422,7 @@ class ProjectAdminServiceImpl extends BaseServiceImplementation implements
|
||||
final RefUpdate u = repo.updateRef(refname);
|
||||
u.setExpectedOldObjectId(ObjectId.zeroId());
|
||||
u.setNewObjectId(revid);
|
||||
u.setRefLogIdent(ChangeUtil.toReflogIdent(me, remotePeer.get()));
|
||||
u.setRefLogIdent(identifiedUser.get().toPersonIdent());
|
||||
u.setRefLogMessage("created via web from " + startingRevision,
|
||||
false);
|
||||
final RefUpdate.Result result = u.update(rw);
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
// Copyright (C) 2008 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.server.ssh;
|
||||
|
||||
import com.google.gerrit.client.data.ProjectCache;
|
||||
import com.google.gerrit.client.reviewdb.Account;
|
||||
import com.google.gerrit.client.reviewdb.AccountGroup;
|
||||
import com.google.gerrit.client.reviewdb.ApprovalCategory;
|
||||
import com.google.gerrit.client.rpc.Common;
|
||||
import com.google.gerrit.server.BaseServiceImplementation;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class AbstractCommand extends BaseCommand {
|
||||
private static final String ENC = "UTF-8";
|
||||
|
||||
@Inject
|
||||
private IdentifiedUser currentUser;
|
||||
|
||||
private Set<AccountGroup.Id> userGroups;
|
||||
|
||||
protected PrintWriter toPrintWriter(final OutputStream o)
|
||||
throws UnsupportedEncodingException {
|
||||
return new PrintWriter(new BufferedWriter(new OutputStreamWriter(o, ENC)));
|
||||
}
|
||||
|
||||
protected Account.Id getAccountId() {
|
||||
return currentUser.getAccountId();
|
||||
}
|
||||
|
||||
protected Set<AccountGroup.Id> getGroups() {
|
||||
if (userGroups == null) {
|
||||
userGroups = Common.getGroupCache().getEffectiveGroups(getAccountId());
|
||||
}
|
||||
return userGroups;
|
||||
}
|
||||
|
||||
protected boolean canRead(final ProjectCache.Entry project) {
|
||||
return canPerform(project, ApprovalCategory.READ, (short) 1);
|
||||
}
|
||||
|
||||
protected boolean canPerform(final ProjectCache.Entry project,
|
||||
final ApprovalCategory.Id actionId, final short val) {
|
||||
return BaseServiceImplementation.canPerform(getGroups(), project, actionId,
|
||||
val);
|
||||
}
|
||||
|
||||
protected void assertIsAdministrator() throws Failure {
|
||||
if (!Common.getGroupCache().isAdministrator(getAccountId())) {
|
||||
throw new Failure(1, "fatal: Not a Gerrit administrator");
|
||||
}
|
||||
}
|
||||
|
||||
public void start() {
|
||||
startThread(new CommandRunnable() {
|
||||
public void run() throws Exception {
|
||||
parseCommandLine();
|
||||
AbstractCommand.this.run();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract void run() throws Exception;
|
||||
}
|
||||
32
src/main/java/com/google/gerrit/server/ssh/AdminCommand.java
Normal file
32
src/main/java/com/google/gerrit/server/ssh/AdminCommand.java
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright (C) 2009 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.server.ssh;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation tagged on a concrete Command that requires administrator access.
|
||||
* <p>
|
||||
* Currently this annotation is only enforced by DispatchCommand after it has
|
||||
* created the command object, but before it populates it or starts execution.
|
||||
*/
|
||||
@Target( {ElementType.TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface AdminCommand {
|
||||
}
|
||||
@@ -30,15 +30,20 @@ import org.kohsuke.args4j.Option;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class BaseCommand implements Command {
|
||||
private static final Logger log = LoggerFactory.getLogger(BaseCommand.class);
|
||||
public static final String ENC = "UTF-8";
|
||||
|
||||
@Option(name = "--help", usage = "display this help text", aliases = {"-h"})
|
||||
private boolean help;
|
||||
@@ -267,6 +272,18 @@ public abstract class BaseCommand implements Command {
|
||||
cleanup.run();
|
||||
}
|
||||
|
||||
/** Wrap the supplied output stream in a UTF-8 encoded PrintWriter. */
|
||||
protected static PrintWriter toPrintWriter(final OutputStream o) {
|
||||
try {
|
||||
return new PrintWriter(new BufferedWriter(new OutputStreamWriter(o, ENC)));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// Our default encoding is required by the specifications for the
|
||||
// runtime APIs, this should never, ever happen.
|
||||
//
|
||||
throw new RuntimeException("JVM lacks " + ENC + " encoding", e);
|
||||
}
|
||||
}
|
||||
|
||||
private String threadName() {
|
||||
final ServerSession session = SshScopes.getContext().session;
|
||||
final String who = session.getUsername();
|
||||
@@ -310,7 +327,7 @@ public abstract class BaseCommand implements Command {
|
||||
if (e instanceof Failure) {
|
||||
final Failure f = (Failure) e;
|
||||
try {
|
||||
err.write((f.getMessage() + "\n").getBytes("UTF-8"));
|
||||
err.write((f.getMessage() + "\n").getBytes(ENC));
|
||||
err.flush();
|
||||
} catch (IOException e2) {
|
||||
} catch (Throwable e2) {
|
||||
@@ -320,7 +337,7 @@ public abstract class BaseCommand implements Command {
|
||||
|
||||
} else {
|
||||
try {
|
||||
err.write("fatal: internal server error\n".getBytes("UTF-8"));
|
||||
err.write("fatal: internal server error\n".getBytes(ENC));
|
||||
err.flush();
|
||||
} catch (IOException e2) {
|
||||
} catch (Throwable e2) {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package com.google.gerrit.server.ssh;
|
||||
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
@@ -27,17 +28,19 @@ import java.util.Map;
|
||||
/**
|
||||
* Command that dispatches to a subcommand from its command table.
|
||||
*/
|
||||
class DispatchCommand extends BaseCommand {
|
||||
final class DispatchCommand extends BaseCommand {
|
||||
interface Factory {
|
||||
DispatchCommand create(String prefix, Map<String, Provider<Command>> map);
|
||||
}
|
||||
|
||||
private final Provider<CurrentUser> currentUser;
|
||||
private final String prefix;
|
||||
private final Map<String, Provider<Command>> commands;
|
||||
|
||||
@Inject
|
||||
DispatchCommand(@Assisted final String pfx,
|
||||
DispatchCommand(final Provider<CurrentUser> cu, @Assisted final String pfx,
|
||||
@Assisted final Map<String, Provider<Command>> all) {
|
||||
currentUser = cu;
|
||||
prefix = pfx;
|
||||
commands = all;
|
||||
}
|
||||
@@ -65,6 +68,16 @@ class DispatchCommand extends BaseCommand {
|
||||
final Provider<Command> p = commands.get(name);
|
||||
if (p != null) {
|
||||
final Command cmd = p.get();
|
||||
if (cmd.getClass().getAnnotation(AdminCommand.class) != null) {
|
||||
final CurrentUser u = currentUser.get();
|
||||
if (!u.isAdministrator()) {
|
||||
err.write("fatal: Not a Gerrit administrator\n".getBytes(ENC));
|
||||
err.flush();
|
||||
onExit(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
provideStateTo(cmd);
|
||||
if (cmd instanceof BaseCommand) {
|
||||
final BaseCommand bc = (BaseCommand) cmd;
|
||||
@@ -77,7 +90,7 @@ class DispatchCommand extends BaseCommand {
|
||||
cmd.start();
|
||||
} else {
|
||||
final String msg = prefix + ": " + name + ": not found\n";
|
||||
err.write(msg.getBytes("UTF-8"));
|
||||
err.write(msg.getBytes(ENC));
|
||||
err.flush();
|
||||
onExit(127);
|
||||
}
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
package com.google.gerrit.server.ssh.commands;
|
||||
|
||||
import com.google.gerrit.client.data.ProjectCache;
|
||||
import com.google.gerrit.client.reviewdb.Account;
|
||||
import com.google.gerrit.client.reviewdb.ApprovalCategory;
|
||||
import com.google.gerrit.client.reviewdb.Project;
|
||||
import com.google.gerrit.client.reviewdb.ProjectRight;
|
||||
import com.google.gerrit.client.rpc.Common;
|
||||
import com.google.gerrit.server.GerritServer;
|
||||
import com.google.gerrit.server.ssh.AbstractCommand;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.ssh.BaseCommand;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.kohsuke.args4j.Argument;
|
||||
@@ -30,20 +30,32 @@ import org.spearce.jgit.lib.Repository;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
abstract class AbstractGitCommand extends AbstractCommand {
|
||||
abstract class AbstractGitCommand extends BaseCommand {
|
||||
@Argument(index = 0, metaVar = "PROJECT.git", required = true, usage = "project name")
|
||||
private String reqProjName;
|
||||
|
||||
@Inject
|
||||
protected GerritServer server;
|
||||
|
||||
@Inject
|
||||
private IdentifiedUser currentUser;
|
||||
|
||||
protected Repository repo;
|
||||
protected ProjectCache.Entry cachedProj;
|
||||
protected Project proj;
|
||||
protected Account userAccount;
|
||||
|
||||
@Override
|
||||
protected final void run() throws IOException, Failure {
|
||||
public void start() {
|
||||
startThread(new CommandRunnable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
parseCommandLine();
|
||||
AbstractGitCommand.this.service();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void service() throws IOException, Failure {
|
||||
String projectName = reqProjName;
|
||||
if (projectName.endsWith(".git")) {
|
||||
// Be nice and drop the trailing ".git" suffix, which we never keep
|
||||
@@ -70,17 +82,11 @@ abstract class AbstractGitCommand extends AbstractCommand {
|
||||
throw new Failure(1, "fatal: '" + reqProjName + "': not a valid project",
|
||||
new IllegalArgumentException("Cannot access the wildcard project"));
|
||||
}
|
||||
if (!canRead(cachedProj)) {
|
||||
if (!canPerform(ApprovalCategory.READ, (short) 1)) {
|
||||
throw new Failure(1, "fatal: '" + reqProjName + "': unknown project",
|
||||
new SecurityException("Account lacks Read permission"));
|
||||
}
|
||||
|
||||
userAccount = Common.getAccountCache().get(getAccountId());
|
||||
if (userAccount == null) {
|
||||
throw new Failure(1, "fatal: cannot query user database",
|
||||
new IllegalStateException("Account record no longer in database"));
|
||||
}
|
||||
|
||||
try {
|
||||
repo = server.openRepository(proj.getName());
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
@@ -95,7 +101,7 @@ abstract class AbstractGitCommand extends AbstractCommand {
|
||||
|
||||
protected boolean canPerform(final ApprovalCategory.Id actionId,
|
||||
final short val) {
|
||||
return canPerform(cachedProj, actionId, val);
|
||||
return currentUser.canPerform(cachedProj, actionId, val);
|
||||
}
|
||||
|
||||
protected abstract void runImpl() throws IOException, Failure;
|
||||
|
||||
@@ -16,6 +16,7 @@ package com.google.gerrit.server.ssh.commands;
|
||||
|
||||
import com.google.gerrit.client.rpc.Common;
|
||||
import com.google.gerrit.server.patch.DiffCache;
|
||||
import com.google.gerrit.server.ssh.AdminCommand;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
@@ -23,13 +24,13 @@ import net.sf.ehcache.Ehcache;
|
||||
import org.kohsuke.args4j.Option;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
|
||||
/** Causes the caches to purge all entries and reload. */
|
||||
class AdminFlushCaches extends AbstractAdminCacheCommand {
|
||||
@AdminCommand
|
||||
final class AdminFlushCaches extends CacheCommand {
|
||||
@Option(name = "--cache", usage = "flush named cache", metaVar = "NAME")
|
||||
private List<String> caches = new ArrayList<String>();
|
||||
|
||||
@@ -42,12 +43,20 @@ class AdminFlushCaches extends AbstractAdminCacheCommand {
|
||||
@Inject
|
||||
private DiffCache diffCache;
|
||||
|
||||
PrintWriter p;
|
||||
private PrintWriter p;
|
||||
|
||||
@Override
|
||||
protected void run() throws Failure, UnsupportedEncodingException {
|
||||
assertIsAdministrator();
|
||||
public void start() {
|
||||
startThread(new CommandRunnable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
parseCommandLine();
|
||||
flush();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void flush() throws Failure {
|
||||
p = toPrintWriter(err);
|
||||
if (list) {
|
||||
if (all || caches.size() > 0) {
|
||||
|
||||
@@ -18,7 +18,8 @@ import com.google.gerrit.client.reviewdb.Project;
|
||||
import com.google.gerrit.client.rpc.Common;
|
||||
import com.google.gerrit.git.PushAllProjectsOp;
|
||||
import com.google.gerrit.git.ReplicationQueue;
|
||||
import com.google.gerrit.server.ssh.AbstractCommand;
|
||||
import com.google.gerrit.server.ssh.AdminCommand;
|
||||
import com.google.gerrit.server.ssh.BaseCommand;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.kohsuke.args4j.Argument;
|
||||
@@ -29,7 +30,8 @@ import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/** Force a project to replicate, again. */
|
||||
class AdminReplicate extends AbstractCommand {
|
||||
@AdminCommand
|
||||
final class AdminReplicate extends BaseCommand {
|
||||
@Option(name = "--all", usage = "push all known projects")
|
||||
private boolean all;
|
||||
|
||||
@@ -46,9 +48,17 @@ class AdminReplicate extends AbstractCommand {
|
||||
private ReplicationQueue replication;
|
||||
|
||||
@Override
|
||||
protected void run() throws Failure {
|
||||
assertIsAdministrator();
|
||||
public void start() {
|
||||
startThread(new CommandRunnable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
parseCommandLine();
|
||||
AdminReplicate.this.schedule();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void schedule() throws Failure {
|
||||
if (all && projectNames.size() > 0) {
|
||||
throw new Failure(1, "error: cannot combine --all and PROJECT");
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
package com.google.gerrit.server.ssh.commands;
|
||||
|
||||
import com.google.gerrit.server.ssh.AdminCommand;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.Statistics;
|
||||
import net.sf.ehcache.config.CacheConfiguration;
|
||||
@@ -21,15 +23,24 @@ import net.sf.ehcache.config.CacheConfiguration;
|
||||
import org.spearce.jgit.lib.WindowCacheStatAccessor;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
/** Show the current cache states. */
|
||||
class AdminShowCaches extends AbstractAdminCacheCommand {
|
||||
PrintWriter p;
|
||||
@AdminCommand
|
||||
final class AdminShowCaches extends CacheCommand {
|
||||
private PrintWriter p;
|
||||
|
||||
@Override
|
||||
protected void run() throws Failure, UnsupportedEncodingException {
|
||||
assertIsAdministrator();
|
||||
public void start() {
|
||||
startThread(new CommandRunnable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
parseCommandLine();
|
||||
display();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void display() {
|
||||
p = toPrintWriter(out);
|
||||
|
||||
for (final Ehcache cache : getAllCaches()) {
|
||||
|
||||
@@ -16,7 +16,8 @@ package com.google.gerrit.server.ssh.commands;
|
||||
|
||||
import com.google.gerrit.client.reviewdb.Account;
|
||||
import com.google.gerrit.client.rpc.Common;
|
||||
import com.google.gerrit.server.ssh.AbstractCommand;
|
||||
import com.google.gerrit.server.ssh.AdminCommand;
|
||||
import com.google.gerrit.server.ssh.BaseCommand;
|
||||
import com.google.gerrit.server.ssh.SshDaemon;
|
||||
import com.google.gerrit.server.ssh.SshUtil;
|
||||
import com.google.inject.Inject;
|
||||
@@ -28,7 +29,6 @@ import org.apache.sshd.server.CommandFactory.Command;
|
||||
import org.kohsuke.args4j.Option;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
@@ -40,18 +40,28 @@ import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/** Show the current SSH connections. */
|
||||
class AdminShowConnections extends AbstractCommand {
|
||||
@AdminCommand
|
||||
final class AdminShowConnections extends BaseCommand {
|
||||
@Option(name = "--numeric", aliases = {"-n"}, usage = "don't resolve names")
|
||||
private boolean numeric;
|
||||
|
||||
PrintWriter p;
|
||||
private PrintWriter p;
|
||||
|
||||
@Inject
|
||||
private SshDaemon daemon;
|
||||
|
||||
@Override
|
||||
protected void run() throws Failure, UnsupportedEncodingException {
|
||||
assertIsAdministrator();
|
||||
public void start() {
|
||||
startThread(new CommandRunnable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
parseCommandLine();
|
||||
AdminShowConnections.this.display();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void display() throws Failure {
|
||||
p = toPrintWriter(out);
|
||||
|
||||
final IoAcceptor acceptor = daemon.getIoAcceptor();
|
||||
|
||||
@@ -16,11 +16,11 @@ package com.google.gerrit.server.ssh.commands;
|
||||
|
||||
import com.google.gerrit.git.WorkQueue;
|
||||
import com.google.gerrit.git.WorkQueue.Task;
|
||||
import com.google.gerrit.server.ssh.AbstractCommand;
|
||||
import com.google.gerrit.server.ssh.AdminCommand;
|
||||
import com.google.gerrit.server.ssh.BaseCommand;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@@ -29,15 +29,25 @@ import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/** Display the current work queue. */
|
||||
class AdminShowQueue extends AbstractCommand {
|
||||
@AdminCommand
|
||||
final class AdminShowQueue extends BaseCommand {
|
||||
@Inject
|
||||
private WorkQueue workQueue;
|
||||
|
||||
PrintWriter p;
|
||||
private PrintWriter p;
|
||||
|
||||
@Override
|
||||
protected void run() throws Failure, UnsupportedEncodingException {
|
||||
assertIsAdministrator();
|
||||
public void start() {
|
||||
startThread(new CommandRunnable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
parseCommandLine();
|
||||
AdminShowQueue.this.display();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void display() {
|
||||
p = toPrintWriter(out);
|
||||
|
||||
final List<Task<?>> pending = workQueue.getTasks();
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package com.google.gerrit.server.ssh.commands;
|
||||
|
||||
import com.google.gerrit.server.ssh.AbstractCommand;
|
||||
import com.google.gerrit.server.ssh.BaseCommand;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import net.sf.ehcache.CacheManager;
|
||||
@@ -24,7 +24,7 @@ import java.util.Arrays;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
abstract class AbstractAdminCacheCommand extends AbstractCommand {
|
||||
abstract class CacheCommand extends BaseCommand {
|
||||
@Inject
|
||||
protected CacheManager cacheMgr;
|
||||
|
||||
@@ -14,24 +14,39 @@
|
||||
|
||||
package com.google.gerrit.server.ssh.commands;
|
||||
|
||||
import static com.google.gerrit.client.reviewdb.ApprovalCategory.READ;
|
||||
|
||||
import com.google.gerrit.client.data.ProjectCache;
|
||||
import com.google.gerrit.client.reviewdb.Project;
|
||||
import com.google.gerrit.client.reviewdb.ProjectRight;
|
||||
import com.google.gerrit.client.reviewdb.ReviewDb;
|
||||
import com.google.gerrit.client.rpc.Common;
|
||||
import com.google.gerrit.server.ssh.AbstractCommand;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.ssh.BaseCommand;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
class ListProjects extends AbstractCommand {
|
||||
final class ListProjects extends BaseCommand {
|
||||
@Inject
|
||||
private ReviewDb db;
|
||||
|
||||
@Inject
|
||||
private IdentifiedUser currentUser;
|
||||
|
||||
@Override
|
||||
protected void run() throws IOException, Failure {
|
||||
public void start() {
|
||||
startThread(new CommandRunnable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
parseCommandLine();
|
||||
ListProjects.this.display();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void display() throws Failure {
|
||||
final PrintWriter stdout = toPrintWriter(out);
|
||||
try {
|
||||
final ProjectCache cache = Common.getProjectCache();
|
||||
@@ -43,7 +58,7 @@ class ListProjects extends AbstractCommand {
|
||||
}
|
||||
|
||||
final ProjectCache.Entry e = cache.get(p.getId());
|
||||
if (e != null && canRead(e)) {
|
||||
if (e != null && currentUser.canPerform(e, READ, (short) 1)) {
|
||||
stdout.print(p.getName());
|
||||
stdout.println();
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ import com.google.gerrit.client.reviewdb.ReviewDb;
|
||||
import com.google.gerrit.git.PatchSetImporter;
|
||||
import com.google.gerrit.git.ReplicationQueue;
|
||||
import com.google.gerrit.server.ChangeUtil;
|
||||
import com.google.gerrit.server.RemotePeer;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.config.AuthConfig;
|
||||
import com.google.gerrit.server.config.CanonicalWebUrl;
|
||||
import com.google.gerrit.server.config.Nullable;
|
||||
@@ -81,7 +81,6 @@ import org.spearce.jgit.transport.ReceiveCommand.Type;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.SocketAddress;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
@@ -98,7 +97,7 @@ import java.util.regex.Pattern;
|
||||
import javax.security.auth.login.AccountNotFoundException;
|
||||
|
||||
/** Receives change upload over SSH using the Git receive-pack protocol. */
|
||||
class Receive extends AbstractGitCommand {
|
||||
final class Receive extends AbstractGitCommand {
|
||||
private static final Logger log = LoggerFactory.getLogger(Receive.class);
|
||||
|
||||
private static final String NEW_CHANGE = "refs/for/";
|
||||
@@ -134,8 +133,7 @@ class Receive extends AbstractGitCommand {
|
||||
}
|
||||
|
||||
@Inject
|
||||
@RemotePeer
|
||||
private SocketAddress remoteAddress;
|
||||
private IdentifiedUser currentUser;
|
||||
|
||||
@Inject
|
||||
private ReviewDb db;
|
||||
@@ -190,7 +188,7 @@ class Receive extends AbstractGitCommand {
|
||||
verifyActiveContributorAgreement();
|
||||
}
|
||||
loadMyEmails();
|
||||
refLogIdent = ChangeUtil.toReflogIdent(userAccount, remoteAddress);
|
||||
refLogIdent = currentUser.toPersonIdent();
|
||||
|
||||
rp = new ReceivePack(repo);
|
||||
rp.setAllowCreates(true);
|
||||
@@ -261,7 +259,7 @@ class Receive extends AbstractGitCommand {
|
||||
AbstractAgreement bestAgreement = null;
|
||||
ContributorAgreement bestCla = null;
|
||||
try {
|
||||
OUTER: for (final AccountGroup.Id groupId : getGroups()) {
|
||||
OUTER: for (AccountGroup.Id groupId : currentUser.getEffectiveGroups()) {
|
||||
for (final AccountGroupAgreement a : db.accountGroupAgreements()
|
||||
.byGroup(groupId)) {
|
||||
final ContributorAgreement cla =
|
||||
@@ -278,7 +276,7 @@ class Receive extends AbstractGitCommand {
|
||||
|
||||
if (bestAgreement == null) {
|
||||
for (final AccountAgreement a : db.accountAgreements().byAccount(
|
||||
userAccount.getId()).toList()) {
|
||||
currentUser.getAccountId()).toList()) {
|
||||
final ContributorAgreement cla =
|
||||
db.contributorAgreements().get(a.getAgreementId());
|
||||
if (cla == null) {
|
||||
@@ -313,9 +311,9 @@ class Receive extends AbstractGitCommand {
|
||||
|
||||
if (bestCla != null && bestCla.isRequireContactInformation()) {
|
||||
boolean fail = false;
|
||||
fail |= missing(userAccount.getFullName());
|
||||
fail |= missing(userAccount.getPreferredEmail());
|
||||
fail |= !userAccount.isContactFiled();
|
||||
fail |= missing(currentUser.getAccount().getFullName());
|
||||
fail |= missing(currentUser.getAccount().getPreferredEmail());
|
||||
fail |= !currentUser.getAccount().isContactFiled();
|
||||
|
||||
if (fail) {
|
||||
final StringBuilder msg = new StringBuilder();
|
||||
@@ -372,10 +370,10 @@ class Receive extends AbstractGitCommand {
|
||||
}
|
||||
|
||||
private void loadMyEmails() throws Failure {
|
||||
addEmail(userAccount.getPreferredEmail());
|
||||
addEmail(currentUser.getAccount().getPreferredEmail());
|
||||
try {
|
||||
for (final AccountExternalId id : db.accountExternalIds().byAccount(
|
||||
userAccount.getId())) {
|
||||
currentUser.getAccountId())) {
|
||||
addEmail(id.getEmailAddress());
|
||||
}
|
||||
} catch (OrmException e) {
|
||||
@@ -718,7 +716,7 @@ class Receive extends AbstractGitCommand {
|
||||
walk.parseBody(c);
|
||||
|
||||
final Transaction txn = db.beginTransaction();
|
||||
final Account.Id me = userAccount.getId();
|
||||
final Account.Id me = currentUser.getAccountId();
|
||||
final Change change =
|
||||
new Change(new Change.Id(db.nextChangeId()), me, destBranch
|
||||
.getNameKey());
|
||||
@@ -850,7 +848,7 @@ class Receive extends AbstractGitCommand {
|
||||
return;
|
||||
}
|
||||
|
||||
final Account.Id me = userAccount.getId();
|
||||
final Account.Id me = currentUser.getAccountId();
|
||||
final Set<Account.Id> reviewers = new HashSet<Account.Id>(reviewerId);
|
||||
final Set<Account.Id> cc = new HashSet<Account.Id>(ccId);
|
||||
for (final FooterLine footerLine : c.getFooterLines()) {
|
||||
@@ -938,7 +936,7 @@ class Receive extends AbstractGitCommand {
|
||||
|
||||
final PatchSet ps = new PatchSet(change.newPatchSetId());
|
||||
ps.setCreatedOn(new Timestamp(System.currentTimeMillis()));
|
||||
ps.setUploader(userAccount.getId());
|
||||
ps.setUploader(currentUser.getAccountId());
|
||||
|
||||
final PatchSetImporter imp =
|
||||
importFactory.create(db, proj.getNameKey(), repo, c, ps, true);
|
||||
@@ -1313,7 +1311,7 @@ class Receive extends AbstractGitCommand {
|
||||
msgBuf.append(".");
|
||||
final ChangeMessage msg =
|
||||
new ChangeMessage(new ChangeMessage.Key(change.getId(), ChangeUtil
|
||||
.messageUUID(db)), getAccountId());
|
||||
.messageUUID(db)), currentUser.getAccountId());
|
||||
msg.setMessage(msgBuf.toString());
|
||||
|
||||
db.changeApprovals().update(result.approvals, txn);
|
||||
@@ -1324,9 +1322,8 @@ class Receive extends AbstractGitCommand {
|
||||
private void sendMergedEmail(final ReplaceResult result) {
|
||||
if (result != null && result.mergedIntoRef != null) {
|
||||
try {
|
||||
final MergedSender cm;
|
||||
cm = mergedSenderFactory.create(result.change);
|
||||
cm.setFrom(getAccountId());
|
||||
final MergedSender cm = mergedSenderFactory.create(result.change);
|
||||
cm.setFrom(currentUser.getAccountId());
|
||||
cm.setReviewDb(db);
|
||||
cm.setPatchSet(result.patchSet, result.info);
|
||||
cm.setDest(new Branch.NameKey(proj.getNameKey(), result.mergedIntoRef));
|
||||
|
||||
@@ -39,7 +39,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.TreeMap;
|
||||
|
||||
class ScpCommand extends BaseCommand {
|
||||
final class ScpCommand extends BaseCommand {
|
||||
private static final String TYPE_DIR = "D";
|
||||
private static final String TYPE_FILE = "C";
|
||||
private static final Logger log = LoggerFactory.getLogger(ScpCommand.class);
|
||||
|
||||
@@ -19,7 +19,7 @@ import org.spearce.jgit.transport.UploadPack;
|
||||
import java.io.IOException;
|
||||
|
||||
/** Publishes Git repositories over SSH using the Git upload-pack protocol. */
|
||||
class Upload extends AbstractGitCommand {
|
||||
final class Upload extends AbstractGitCommand {
|
||||
@Override
|
||||
protected void runImpl() throws IOException {
|
||||
final UploadPack up = new UploadPack(repo);
|
||||
|
||||
Reference in New Issue
Block a user