Merge branch 'stable-2.12'
* stable-2.12: Add 2.12 release notes to release notes index Make email validation case insensitive Add tooltip with subject message in related changes tab Correct timezone logged for DST changes Add hmac-sha2-256 and hmac-sha2-512 as MACs for sshd Fix double slash on URL when switching account. commit-msg: Do not add Change-Id to temp commits Use image instead of Unicode Character for Copy Button Change-Id: I6dc9c93e0962a19e2c32dbcf86f0389b5e2a7acc
This commit is contained in:
commit
e132903bc8
@ -3515,7 +3515,8 @@ configuration file, one MAC per key. MAC names starting with `+`
|
||||
are enabled in addition to the default MACs, MAC names starting with
|
||||
`-` are removed from the default MACs.
|
||||
+
|
||||
Supported MACs: hmac-md5, hmac-md5-96, hmac-sha1, hmac-sha1-96.
|
||||
Supported MACs: hmac-md5, hmac-md5-96, hmac-sha1, hmac-sha1-96,
|
||||
hmac-sha2-256, hmac-sha2-512.
|
||||
+
|
||||
By default, all supported MACs are available.
|
||||
|
||||
|
@ -1,6 +1,11 @@
|
||||
Gerrit Code Review - Release Notes
|
||||
==================================
|
||||
|
||||
[[2_12]]
|
||||
Version 2.12.x
|
||||
--------------
|
||||
* link:ReleaseNotes-2.12.html[2.12]
|
||||
|
||||
[[2_11]]
|
||||
Version 2.11.x
|
||||
--------------
|
||||
|
@ -7,6 +7,7 @@ gwt_module(
|
||||
resources = [
|
||||
SRC + 'clippy/client/clippy.css',
|
||||
SRC + 'clippy/client/clippy.swf',
|
||||
SRC + 'clippy/client/clipboard-16.png',
|
||||
SRC + 'clippy/client/CopyableLabelText.properties',
|
||||
],
|
||||
provided_deps = ['//lib/gwt:user'],
|
||||
@ -14,6 +15,7 @@ gwt_module(
|
||||
':SafeHtml',
|
||||
':UserAgent',
|
||||
'//lib:LICENSE-clippy',
|
||||
'//lib:LICENSE-drifty',
|
||||
],
|
||||
visibility = ['PUBLIC'],
|
||||
)
|
||||
|
@ -18,6 +18,7 @@ import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.resources.client.ClientBundle;
|
||||
import com.google.gwt.resources.client.DataResource;
|
||||
import com.google.gwt.resources.client.DataResource.DoNotEmbed;
|
||||
import com.google.gwt.resources.client.ImageResource;
|
||||
|
||||
public interface ClippyResources extends ClientBundle {
|
||||
public static final ClippyResources I = GWT.create(ClippyResources.class);
|
||||
@ -28,4 +29,7 @@ public interface ClippyResources extends ClientBundle {
|
||||
@Source("clippy.swf")
|
||||
@DoNotEmbed
|
||||
DataResource swf();
|
||||
|
||||
@Source("clipboard-16.png")
|
||||
ImageResource clipboard();
|
||||
}
|
||||
|
@ -119,7 +119,12 @@ public class CopyableLabel extends Composite implements HasText {
|
||||
}
|
||||
|
||||
if (UserAgent.hasJavaScriptClipboard()) {
|
||||
copier = new Button("📋"); // CLIPBOARD
|
||||
copier = new Button(new SafeHtmlBuilder()
|
||||
.openElement("img")
|
||||
.setAttribute("src", ClippyResources.I.clipboard().getSafeUri().asString())
|
||||
.setWidth(14)
|
||||
.setHeight(14)
|
||||
.closeSelf());
|
||||
copier.setStyleName(ClippyResources.I.css().copier());
|
||||
Tooltip.addStyle(copier);
|
||||
Tooltip.setLabel(copier, CopyableLabelText.I.tooltip());
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 623 B |
@ -54,7 +54,7 @@ public class UserPopupPanel extends PopupPanel {
|
||||
switchAccount.setHref(Gerrit.info().auth().switchAccountUrl());
|
||||
} else if (Gerrit.info().auth().isDev()
|
||||
|| Gerrit.info().auth().isOpenId()) {
|
||||
switchAccount.setHref(Gerrit.selfRedirect("/login/"));
|
||||
switchAccount.setHref(Gerrit.selfRedirect("/login"));
|
||||
} else {
|
||||
switchAccount.removeFromParent();
|
||||
switchAccount = null;
|
||||
|
@ -292,6 +292,7 @@ class RelatedChangesTab implements IsWidget {
|
||||
if (url.startsWith("#")) {
|
||||
sb.setAttribute("onclick", OPEN);
|
||||
}
|
||||
sb.setAttribute("title", info.commit().subject());
|
||||
if (showProjects) {
|
||||
sb.append(info.project()).append(": ");
|
||||
}
|
||||
|
@ -196,7 +196,8 @@ public class IdentifiedUser extends CurrentUser {
|
||||
private final GroupBackend groupBackend;
|
||||
private final String anonymousCowardName;
|
||||
private final Boolean disableReverseDnsLookup;
|
||||
private final Set<String> validEmails = Sets.newHashSetWithExpectedSize(4);
|
||||
private final Set<String> validEmails =
|
||||
Sets.newTreeSet(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
@Nullable
|
||||
private final Provider<SocketAddress> remotePeerProvider;
|
||||
@ -284,7 +285,7 @@ public class IdentifiedUser extends CurrentUser {
|
||||
validEmails.add(email);
|
||||
return true;
|
||||
} else if (invalidEmails == null) {
|
||||
invalidEmails = Sets.newHashSetWithExpectedSize(4);
|
||||
invalidEmails = Sets.newTreeSet(String.CASE_INSENSITIVE_ORDER);
|
||||
}
|
||||
invalidEmails.add(email);
|
||||
return false;
|
||||
|
@ -25,7 +25,6 @@ import com.google.inject.Inject;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/** Basic implementation of {@link Realm}. */
|
||||
@ -57,7 +56,7 @@ public abstract class AbstractRealm implements Realm {
|
||||
@Override
|
||||
public boolean hasEmailAddress(IdentifiedUser user, String email) {
|
||||
for (AccountExternalId ext : user.state().getExternalIds()) {
|
||||
if (Objects.equals(ext.getEmailAddress(), email)) {
|
||||
if (email != null && email.equalsIgnoreCase(ext.getEmailAddress())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,12 @@ add_ChangeId() {
|
||||
return
|
||||
fi
|
||||
|
||||
# Do not add Change-Id to temp commits
|
||||
if echo "$clean_message" | head -1 | grep -q '^\(fixup\|squash\)!'
|
||||
then
|
||||
return
|
||||
fi
|
||||
|
||||
if test "false" = "`git config --bool --get gerrit.createChangeId`"
|
||||
then
|
||||
return
|
||||
|
@ -0,0 +1,131 @@
|
||||
// Copyright (C) 2015 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 static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.inject.Scopes.SINGLETON;
|
||||
|
||||
import com.google.gerrit.common.TimeUtil;
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
import com.google.gerrit.server.account.AccountCache;
|
||||
import com.google.gerrit.server.account.CapabilityControl;
|
||||
import com.google.gerrit.server.account.FakeRealm;
|
||||
import com.google.gerrit.server.account.GroupBackend;
|
||||
import com.google.gerrit.server.account.Realm;
|
||||
import com.google.gerrit.server.config.AnonymousCowardName;
|
||||
import com.google.gerrit.server.config.AnonymousCowardNameProvider;
|
||||
import com.google.gerrit.server.config.CanonicalWebUrl;
|
||||
import com.google.gerrit.server.config.DisableReverseDnsLookup;
|
||||
import com.google.gerrit.server.config.GerritServerConfig;
|
||||
import com.google.gerrit.server.group.SystemGroupBackend;
|
||||
import com.google.gerrit.testutil.ConfigSuite;
|
||||
import com.google.gerrit.testutil.FakeAccountCache;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.util.Providers;
|
||||
|
||||
import org.eclipse.jgit.lib.Config;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@RunWith(ConfigSuite.class)
|
||||
public class IdentifiedUserTest {
|
||||
@ConfigSuite.Parameter
|
||||
public Config config;
|
||||
|
||||
private IdentifiedUser identifiedUser;
|
||||
|
||||
@Inject
|
||||
private IdentifiedUser.GenericFactory identifiedUserFactory;
|
||||
|
||||
private static final String[] TEST_CASES = {
|
||||
"",
|
||||
"FirstName.LastName@Corporation.com",
|
||||
"!#$%&'+-/=.?^`{|}~@[IPv6:0123:4567:89AB:CDEF:0123:4567:89AB:CDEF]"
|
||||
};
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
final FakeAccountCache accountCache = new FakeAccountCache();
|
||||
final Realm mockRealm = new FakeRealm() {
|
||||
HashSet<String> emails = new HashSet<>(Arrays.asList(TEST_CASES));
|
||||
|
||||
@Override
|
||||
public boolean hasEmailAddress(IdentifiedUser who, String email) {
|
||||
return emails.contains(email);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getEmailAddresses(IdentifiedUser who) {
|
||||
return emails;
|
||||
}
|
||||
};
|
||||
|
||||
AbstractModule mod = new AbstractModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(Boolean.class).annotatedWith(DisableReverseDnsLookup.class)
|
||||
.toInstance(Boolean.FALSE);
|
||||
bind(Config.class).annotatedWith(GerritServerConfig.class).toInstance(config);
|
||||
bind(String.class).annotatedWith(AnonymousCowardName.class)
|
||||
.toProvider(AnonymousCowardNameProvider.class);
|
||||
bind(String.class).annotatedWith(CanonicalWebUrl.class)
|
||||
.toInstance("http://localhost:8080/");
|
||||
bind(AccountCache.class).toInstance(accountCache);
|
||||
bind(GroupBackend.class).to(SystemGroupBackend.class).in(SINGLETON);
|
||||
bind(CapabilityControl.Factory.class)
|
||||
.toProvider(Providers.<CapabilityControl.Factory>of(null));
|
||||
bind(Realm.class).toInstance(mockRealm);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
Injector injector = Guice.createInjector(mod);
|
||||
injector.injectMembers(this);
|
||||
|
||||
Account account = new Account(new Account.Id(1), TimeUtil.nowTs());
|
||||
Account.Id ownerId = account.getId();
|
||||
|
||||
identifiedUser = identifiedUserFactory.create(ownerId);
|
||||
|
||||
/* Trigger identifiedUser to load the email addresses from mockRealm */
|
||||
identifiedUser.getEmailAddresses();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmailsExistence() {
|
||||
assertThat(identifiedUser.hasEmailAddress(TEST_CASES[0])).isTrue();
|
||||
assertThat(identifiedUser.hasEmailAddress(TEST_CASES[1].toLowerCase())).isTrue();
|
||||
assertThat(identifiedUser.hasEmailAddress(TEST_CASES[1])).isTrue();
|
||||
assertThat(identifiedUser.hasEmailAddress(TEST_CASES[1].toUpperCase())).isTrue();
|
||||
/* assert again to test cached email address by IdentifiedUser.validEmails */
|
||||
assertThat(identifiedUser.hasEmailAddress(TEST_CASES[1])).isTrue();
|
||||
|
||||
assertThat(identifiedUser.hasEmailAddress(TEST_CASES[2])).isTrue();
|
||||
assertThat(identifiedUser.hasEmailAddress(TEST_CASES[2].toLowerCase())).isTrue();
|
||||
|
||||
|
||||
assertThat(identifiedUser.hasEmailAddress("non-exist@email.com")).isFalse();
|
||||
/* assert again to test cached email address by IdentifiedUser.invalidEmails */
|
||||
assertThat(identifiedUser.hasEmailAddress("non-exist@email.com")).isFalse();
|
||||
}
|
||||
}
|
@ -83,6 +83,8 @@ import org.apache.sshd.common.mac.HMACMD5;
|
||||
import org.apache.sshd.common.mac.HMACMD596;
|
||||
import org.apache.sshd.common.mac.HMACSHA1;
|
||||
import org.apache.sshd.common.mac.HMACSHA196;
|
||||
import org.apache.sshd.common.mac.HMACSHA256;
|
||||
import org.apache.sshd.common.mac.HMACSHA512;
|
||||
import org.apache.sshd.common.random.BouncyCastleRandom;
|
||||
import org.apache.sshd.common.random.JceRandom;
|
||||
import org.apache.sshd.common.random.SingletonRandomFactory;
|
||||
@ -552,9 +554,13 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
||||
}
|
||||
|
||||
private void initMacs(final Config cfg) {
|
||||
setMacFactories(filter(cfg, "mac", new HMACMD5.Factory(),
|
||||
new HMACSHA1.Factory(), new HMACMD596.Factory(),
|
||||
new HMACSHA196.Factory()));
|
||||
setMacFactories(filter(cfg, "mac",
|
||||
new HMACMD5.Factory(),
|
||||
new HMACSHA1.Factory(),
|
||||
new HMACMD596.Factory(),
|
||||
new HMACSHA196.Factory(),
|
||||
new HMACSHA256.Factory(),
|
||||
new HMACSHA512.Factory()));
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
|
@ -20,7 +20,6 @@ import org.eclipse.jgit.util.QuotedString;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public final class SshLogLayout extends Layout {
|
||||
@ -36,15 +35,15 @@ public final class SshLogLayout extends Layout {
|
||||
private final Calendar calendar;
|
||||
private long lastTimeMillis;
|
||||
private final char[] lastTimeString = new char[20];
|
||||
private final char[] timeZone;
|
||||
private final SimpleDateFormat tzFormat;
|
||||
private char[] timeZone;
|
||||
|
||||
public SshLogLayout() {
|
||||
final TimeZone tz = TimeZone.getDefault();
|
||||
calendar = Calendar.getInstance(tz);
|
||||
|
||||
final SimpleDateFormat sdf = new SimpleDateFormat("Z");
|
||||
sdf.setTimeZone(tz);
|
||||
timeZone = sdf.format(new Date()).toCharArray();
|
||||
tzFormat = new SimpleDateFormat("Z");
|
||||
tzFormat.setTimeZone(tz);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -53,8 +52,6 @@ public final class SshLogLayout extends Layout {
|
||||
|
||||
buf.append('[');
|
||||
formatDate(event.getTimeStamp(), buf);
|
||||
buf.append(' ');
|
||||
buf.append(timeZone);
|
||||
buf.append(']');
|
||||
|
||||
req(P_SESSION, buf, event);
|
||||
@ -94,11 +91,14 @@ public final class SshLogLayout extends Layout {
|
||||
sbuf.append(',');
|
||||
sbuf.getChars(start, sbuf.length(), lastTimeString, 0);
|
||||
lastTimeMillis = rounded;
|
||||
timeZone = tzFormat.format(calendar.getTime()).toCharArray();
|
||||
}
|
||||
} else {
|
||||
sbuf.append(lastTimeString);
|
||||
}
|
||||
sbuf.append(String.format("%03d", millis));
|
||||
sbuf.append(' ');
|
||||
sbuf.append(timeZone);
|
||||
}
|
||||
|
||||
private String toTwoDigits(int input) {
|
||||
|
1
lib/BUCK
1
lib/BUCK
@ -12,6 +12,7 @@ define_license(name = 'bouncycastle')
|
||||
define_license(name = 'clippy')
|
||||
define_license(name = 'codemirror')
|
||||
define_license(name = 'diffy')
|
||||
define_license(name = 'drifty')
|
||||
define_license(name = 'freebie_application_icon_set')
|
||||
define_license(name = 'h2')
|
||||
define_license(name = 'jgit')
|
||||
|
21
lib/LICENSE-drifty
Normal file
21
lib/LICENSE-drifty
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Drifty (http://drifty.com/)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
Loading…
Reference in New Issue
Block a user