Use only the local-name of an email for the SSH usernames
This way users connect to "you@gerrit.com" rather than the much longer (and uglier) "you@gmail.com@gerrit.com". We still generate the user from the email, preventing end-users from selecting their own SSH name. We could in the future change this if there is sufficient demand. Because we validate both the username and the SSH public key we can only run into name duplication problems if multiple accounts have the same local name in their preferred email address and use the same SSH public key, which should only be possible if they are both using "root@..." as their email and both keys were created on Debian with the infamous broken ssh-keygen implementation. Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
@@ -21,6 +21,7 @@ public interface AccountConstants extends Constants {
|
||||
|
||||
String fullName();
|
||||
String preferredEmail();
|
||||
String sshUserName();
|
||||
String registeredOn();
|
||||
String defaultContext();
|
||||
|
||||
|
@@ -2,6 +2,7 @@ accountSettingsHeading = Account Settings
|
||||
|
||||
fullName = Full Name
|
||||
preferredEmail = Email Address
|
||||
sshUserName = SSH Username
|
||||
registeredOn = Registered
|
||||
defaultContext = Default Context
|
||||
|
||||
|
@@ -88,14 +88,15 @@ public class AccountSettings extends AccountScreen {
|
||||
fieldIdx = 1;
|
||||
}
|
||||
|
||||
info = new Grid(3, 2);
|
||||
info = new Grid(4, 2);
|
||||
info.setStyleName("gerrit-InfoBlock");
|
||||
info.addStyleName("gerrit-AccountInfoBlock");
|
||||
add(info);
|
||||
|
||||
infoRow(0, Util.C.fullName());
|
||||
infoRow(1, Util.C.preferredEmail());
|
||||
infoRow(2, Util.C.registeredOn());
|
||||
infoRow(2, Util.C.sshUserName());
|
||||
infoRow(3, Util.C.registeredOn());
|
||||
|
||||
final CellFormatter fmt = info.getCellFormatter();
|
||||
fmt.addStyleName(0, 0, "topmost");
|
||||
@@ -163,7 +164,8 @@ public class AccountSettings extends AccountScreen {
|
||||
void display(final Account account) {
|
||||
info.setText(0, fieldIdx, account.getFullName());
|
||||
info.setText(1, fieldIdx, account.getPreferredEmail());
|
||||
info.setText(2, fieldIdx, mediumFormat(account.getRegisteredOn()));
|
||||
info.setText(2, fieldIdx, account.getSshUserName());
|
||||
info.setText(3, fieldIdx, mediumFormat(account.getRegisteredOn()));
|
||||
prefsPanel.display(account);
|
||||
}
|
||||
}
|
||||
|
@@ -106,6 +106,14 @@ public final class Account {
|
||||
@Column(notNull = false)
|
||||
protected String preferredEmail;
|
||||
|
||||
/**
|
||||
* Username to authenticate as through SSH connections.
|
||||
* <p>
|
||||
* Note that this property tracks {@link #preferredEmail}.
|
||||
*/
|
||||
@Column(notNull = false)
|
||||
protected String sshUserName;
|
||||
|
||||
/** Default number of lines of context when viewing a patch. */
|
||||
@Column
|
||||
protected short defaultContext;
|
||||
@@ -150,9 +158,19 @@ public final class Account {
|
||||
|
||||
/** Set the email address the user prefers to be contacted through. */
|
||||
public void setPreferredEmail(final String addr) {
|
||||
if (addr != null && addr.contains("@")) {
|
||||
sshUserName = addr.substring(0, addr.indexOf('@')).toLowerCase();
|
||||
} else {
|
||||
sshUserName = null;
|
||||
}
|
||||
preferredEmail = addr;
|
||||
}
|
||||
|
||||
/** Get the name the user logins as through SSH. */
|
||||
public String getSshUserName() {
|
||||
return sshUserName;
|
||||
}
|
||||
|
||||
/** Get the date and time the user first registered. */
|
||||
public Timestamp getRegisteredOn() {
|
||||
return registeredOn;
|
||||
|
@@ -29,6 +29,9 @@ public interface AccountAccess extends Access<Account, Account.Id> {
|
||||
@Query("WHERE preferredEmail = ? LIMIT 2")
|
||||
ResultSet<Account> byPreferredEmail(String email) throws OrmException;
|
||||
|
||||
@Query("WHERE sshUserName = ?")
|
||||
ResultSet<Account> bySshUserName(String userName) throws OrmException;
|
||||
|
||||
@Query("WHERE fullName >= ? AND fullName <= ? ORDER BY fullName LIMIT ?")
|
||||
ResultSet<Account> suggestByFullName(String nameA, String nameB, int limit)
|
||||
throws OrmException;
|
||||
|
@@ -146,15 +146,15 @@ public class SshUtil {
|
||||
/** Invalidate all cached keys for the given account. */
|
||||
public static void invalidate(final Account acct) {
|
||||
if (acct != null) {
|
||||
invalidate(acct.getPreferredEmail());
|
||||
invalidate(acct.getSshUserName());
|
||||
}
|
||||
}
|
||||
|
||||
/** Invalidate all cached keys for the given account. */
|
||||
public static void invalidate(final String username){
|
||||
public static void invalidate(final String username) {
|
||||
synchronized (keys) {
|
||||
keys.remove(username);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Locate keys for the requested account whose email matches the name given. */
|
||||
@@ -172,7 +172,7 @@ public class SshUtil {
|
||||
final ReviewDb db = rdf.open();
|
||||
try {
|
||||
final List<Account> matches =
|
||||
db.accounts().byPreferredEmail(username).toList();
|
||||
db.accounts().bySshUserName(username).toList();
|
||||
if (matches.isEmpty()) {
|
||||
return Collections.<AccountSshKey> emptyList();
|
||||
}
|
||||
|
Reference in New Issue
Block a user