diff --git a/contrib/themes/diffy/etc/GerritSite.css b/contrib/themes/diffy/etc/GerritSite.css index 6fe8a3e88f..d4769579c2 100644 --- a/contrib/themes/diffy/etc/GerritSite.css +++ b/contrib/themes/diffy/etc/GerritSite.css @@ -12,19 +12,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#gerrit_topmenu { + left: 60px; + margin-right: 60px; + padding-right: 10px; + position: relative; +} -#gerrit_header { +#diffy_logo { display: block !important; margin-bottom: -55px; padding-left: 20px; position: relative; top: -45px; - width: 100px; -} - -#gerrit_topmenu { - left: 100px; - margin-right: 100px; - padding-right: 10px; - position: relative; + width: 60px; } diff --git a/contrib/themes/diffy/etc/GerritSiteHeader.html b/contrib/themes/diffy/etc/GerritSiteHeader.html index 48ccfeceaf..89b4db5149 100644 --- a/contrib/themes/diffy/etc/GerritSiteHeader.html +++ b/contrib/themes/diffy/etc/GerritSiteHeader.html @@ -1,3 +1,5 @@
- +
diff --git a/contrib/trivial_rebase.py b/contrib/trivial_rebase.py index ff90b6c7c4..e5005a3f4a 100755 --- a/contrib/trivial_rebase.py +++ b/contrib/trivial_rebase.py @@ -226,7 +226,7 @@ class TrivialRebase: # We don't care about previous submit attempts continue else: - self.AppendAcctApproval(acct_approvals, approval['account_id'], '--%s %s' % + self.AppendAcctApproval(approval['account_id'], '--%s %s' % (approval['category_id'].lower().replace(' ', '-'), approval['value'])) diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java index 83f4088fe0..932f8f0b4b 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java @@ -21,6 +21,7 @@ import com.google.common.base.Strings; import com.google.gerrit.common.PageLinks; import com.google.gerrit.httpd.HtmlDomUtil; import com.google.gerrit.httpd.WebSession; +import com.google.gerrit.httpd.template.SiteHeaderFooter; import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.AccountExternalId; import com.google.gerrit.reviewdb.server.ReviewDb; @@ -60,14 +61,18 @@ class BecomeAnyAccountLoginServlet extends HttpServlet { private final SchemaFactory schema; private final Provider webSession; private final AccountManager accountManager; + private final SiteHeaderFooter headers; @Inject BecomeAnyAccountLoginServlet(final Provider ws, final SchemaFactory sf, - final AccountManager am, final ServletContext servletContext) { + final AccountManager am, + final ServletContext servletContext, + SiteHeaderFooter shf) { webSession = ws; schema = sf; accountManager = am; + headers = shf; } @Override @@ -149,7 +154,7 @@ class BecomeAnyAccountLoginServlet extends HttpServlet { private byte[] prepareHtmlOutput() throws IOException, OrmException { final String pageName = "BecomeAnyAccount.html"; - final Document doc = HtmlDomUtil.parseFile(getClass(), pageName); + Document doc = headers.parse(getClass(), pageName); if (doc == null) { throw new FileNotFoundException("No " + pageName + " in webapp"); } diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java index f6cd8c1805..adca95e66e 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java @@ -119,14 +119,17 @@ class HttpAuthFilter implements Filter { WebSession session = sessionProvider.get(); if (session.isSignedIn()) { String user = getRemoteUser(req); - AccountExternalId.Key id = session.getLastLoginExternalId(); - return user != null - && id != null - && id.equals(new AccountExternalId.Key(SCHEME_GERRIT, user)); + return user == null || correctUser(user, session); } return false; } + private static boolean correctUser(String user, WebSession session) { + AccountExternalId.Key id = session.getLastLoginExternalId(); + return id != null + && id.equals(new AccountExternalId.Key(SCHEME_GERRIT, user)); + } + String getRemoteUser(HttpServletRequest req) { if (AUTHORIZATION.equals(loginHeader)) { String user = emptyToNull(req.getRemoteUser()); diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/ldap/LdapLoginServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/ldap/LdapLoginServlet.java index 1d7b376850..cfae86c8ba 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/ldap/LdapLoginServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/ldap/LdapLoginServlet.java @@ -19,6 +19,7 @@ import com.google.common.base.Strings; import com.google.gerrit.common.PageLinks; import com.google.gerrit.httpd.HtmlDomUtil; import com.google.gerrit.httpd.WebSession; +import com.google.gerrit.httpd.template.SiteHeaderFooter; import com.google.gerrit.server.account.AccountException; import com.google.gerrit.server.account.AccountManager; import com.google.gerrit.server.account.AccountUserNameException; @@ -26,7 +27,6 @@ import com.google.gerrit.server.account.AuthRequest; import com.google.gerrit.server.account.AuthResult; import com.google.gerrit.server.auth.AuthenticationUnavailableException; import com.google.gerrit.server.config.CanonicalWebUrl; -import com.google.gerrit.server.config.SitePaths; import com.google.gwtexpui.server.CacheHeaders; import com.google.inject.Inject; import com.google.inject.Provider; @@ -37,7 +37,6 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import java.io.File; import java.io.IOException; import javax.annotation.Nullable; @@ -57,17 +56,17 @@ class LdapLoginServlet extends HttpServlet { private final AccountManager accountManager; private final Provider webSession; private final Provider urlProvider; - private final SitePaths sitePaths; + private final SiteHeaderFooter headers; @Inject LdapLoginServlet(AccountManager accountManager, Provider webSession, @CanonicalWebUrl @Nullable Provider urlProvider, - SitePaths sitePaths) { + SiteHeaderFooter headers) { this.accountManager = accountManager; this.webSession = webSession; this.urlProvider = urlProvider; - this.sitePaths = sitePaths; + this.headers = headers; if (Strings.isNullOrEmpty(urlProvider.get())) { log.error("gerrit.canonicalWebUrl must be set in gerrit.config"); @@ -83,13 +82,7 @@ class LdapLoginServlet extends HttpServlet { cancel += "#" + token; } - Document doc = - HtmlDomUtil.parseFile(LdapLoginServlet.class, "LoginForm.html"); - - injectCssFile(doc, "gerrit_sitecss", sitePaths.site_css); - injectXmlFile(doc, "gerrit_header", sitePaths.site_header); - injectXmlFile(doc, "gerrit_footer", sitePaths.site_footer); - + Document doc = headers.parse(LdapLoginServlet.class, "LoginForm.html"); HtmlDomUtil.find(doc, "hostName").setTextContent(req.getServerName()); HtmlDomUtil.find(doc, "login_form").setAttribute("action", self); HtmlDomUtil.find(doc, "cancel_link").setAttribute("href", cancel); @@ -114,42 +107,6 @@ class LdapLoginServlet extends HttpServlet { } } - private void injectCssFile(final Document hostDoc, final String id, - final File src) throws IOException { - final Element banner = HtmlDomUtil.find(hostDoc, id); - if (banner != null) { - while (banner.getFirstChild() != null) { - banner.removeChild(banner.getFirstChild()); - } - - String css = HtmlDomUtil.readFile(src.getParentFile(), src.getName()); - if (css == null) { - banner.getParentNode().removeChild(banner); - } else { - banner.removeAttribute("id"); - banner.appendChild(hostDoc.createCDATASection("\n" + css + "\n")); - } - } - } - - private void injectXmlFile(final Document hostDoc, final String id, - final File src) throws IOException { - final Element banner = HtmlDomUtil.find(hostDoc, id); - if (banner != null) { - while (banner.getFirstChild() != null) { - banner.removeChild(banner.getFirstChild()); - } - - Document html = HtmlDomUtil.parseFile(src); - if (html == null) { - banner.getParentNode().removeChild(banner); - } else { - final Element content = html.getDocumentElement(); - banner.appendChild(hostDoc.importNode(content, true)); - } - } - } - @Override protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException { diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/template/SiteHeaderFooter.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/template/SiteHeaderFooter.java new file mode 100644 index 0000000000..321f032ba4 --- /dev/null +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/template/SiteHeaderFooter.java @@ -0,0 +1,150 @@ +// Copyright (C) 2013 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.httpd.template; + +import com.google.common.base.Strings; +import com.google.gerrit.httpd.HtmlDomUtil; +import com.google.gerrit.server.config.GerritServerConfig; +import com.google.gerrit.server.config.SitePaths; +import com.google.inject.Inject; +import com.google.inject.Singleton; + +import org.eclipse.jgit.lib.Config; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.io.File; +import java.io.IOException; + +@Singleton +public class SiteHeaderFooter { + private static final Logger log = LoggerFactory.getLogger(SiteHeaderFooter.class); + + private final boolean refreshHeaderFooter; + private final SitePaths sitePaths; + private volatile Template template; + + @Inject + SiteHeaderFooter(@GerritServerConfig Config cfg, SitePaths sitePaths) { + this.refreshHeaderFooter = cfg.getBoolean("site", "refreshHeaderFooter", true); + this.sitePaths = sitePaths; + + Template t = new Template(sitePaths); + try { + t.load(); + } catch (IOException e) { + log.warn("Cannot load site header or footer", e); + } + template = t; + } + + public Document parse(Class clazz, String name) throws IOException { + Template t = template; + if (refreshHeaderFooter && t.isStale()) { + t = new Template(sitePaths); + try { + t.load(); + template = t; + } catch (IOException e) { + log.warn("Cannot refresh site header or footer", e); + t = template; + } + } + + Document doc = HtmlDomUtil.parseFile(clazz, name); + injectCss(doc, "gerrit_sitecss", t.css); + injectXml(doc, "gerrit_header", t.header); + injectXml(doc, "gerrit_footer", t.footer); + return doc; + } + + private void injectCss(Document doc, String id, String content) { + Element e = HtmlDomUtil.find(doc, id); + if (e != null) { + if (!Strings.isNullOrEmpty(content)) { + while (e.getFirstChild() != null) { + e.removeChild(e.getFirstChild()); + } + e.removeAttribute("id"); + e.appendChild(doc.createCDATASection("\n" + content + "\n")); + } else { + e.getParentNode().removeChild(e); + } + } + } + + private void injectXml(Document doc, String id, Element d) { + Element e = HtmlDomUtil.find(doc, id); + if (e != null) { + if (d != null) { + while (e.getFirstChild() != null) { + e.removeChild(e.getFirstChild()); + } + e.appendChild(doc.importNode(d, true)); + } else { + e.getParentNode().removeChild(e); + } + } + } + + private static class Template { + private final FileInfo cssFile; + private final FileInfo headerFile; + private final FileInfo footerFile; + + String css; + Element header; + Element footer; + + Template(SitePaths site) { + cssFile = new FileInfo(site.site_css); + headerFile = new FileInfo(site.site_header); + footerFile = new FileInfo(site.site_footer); + } + + void load() throws IOException { + css = HtmlDomUtil.readFile( + cssFile.path.getParentFile(), + cssFile.path.getName()); + header = readXml(headerFile); + footer = readXml(footerFile); + } + + boolean isStale() { + return cssFile.isStale() || headerFile.isStale() || footerFile.isStale(); + } + + private static Element readXml(FileInfo src) throws IOException { + Document d = HtmlDomUtil.parseFile(src.path); + return d != null ? d.getDocumentElement() : null; + } + } + + private static class FileInfo { + final File path; + final long time; + + FileInfo(File p) { + path = p; + time = path.lastModified(); + } + + boolean isStale() { + return time != path.lastModified(); + } + } +} diff --git a/gerrit-httpd/src/main/resources/com/google/gerrit/httpd/auth/become/BecomeAnyAccount.html b/gerrit-httpd/src/main/resources/com/google/gerrit/httpd/auth/become/BecomeAnyAccount.html index a4e3cca497..3548b9af93 100644 --- a/gerrit-httpd/src/main/resources/com/google/gerrit/httpd/auth/become/BecomeAnyAccount.html +++ b/gerrit-httpd/src/main/resources/com/google/gerrit/httpd/auth/become/BecomeAnyAccount.html @@ -29,51 +29,59 @@ } })(); + -

Sign In

- - - - - +
+
+
+

Sign In

+
Username: -
- - -
-
+ + + + - - - - + + + + - - - - + + + + - - - -
Username: +
+ + +
+
Email Address: -
- - -
-
Email Address: +
+ + +
+
Account ID: -
- - -
-
Account ID: +
+ + +
+
Choose: -
+ + Choose: + + + -
-

Register

-
- - -
+
+

Register

+
+ + +
+ +
+ +
diff --git a/gerrit-httpd/src/main/resources/com/google/gerrit/httpd/auth/ldap/LoginForm.html b/gerrit-httpd/src/main/resources/com/google/gerrit/httpd/auth/ldap/LoginForm.html index f7a388eb9d..57bc7f4058 100644 --- a/gerrit-httpd/src/main/resources/com/google/gerrit/httpd/auth/ldap/LoginForm.html +++ b/gerrit-httpd/src/main/resources/com/google/gerrit/httpd/auth/ldap/LoginForm.html @@ -13,7 +13,7 @@ margin-left: 45px; } - +
@@ -56,28 +56,28 @@ - -
+ + diff --git a/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/LoginForm.java b/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/LoginForm.java index 525084ff6e..b8d31ee760 100644 --- a/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/LoginForm.java +++ b/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/LoginForm.java @@ -23,6 +23,7 @@ import com.google.gerrit.common.PageLinks; import com.google.gerrit.common.auth.openid.OpenIdUrls; import com.google.gerrit.extensions.restapi.Url; import com.google.gerrit.httpd.HtmlDomUtil; +import com.google.gerrit.httpd.template.SiteHeaderFooter; import com.google.gerrit.reviewdb.client.AuthType; import com.google.gerrit.server.config.AuthConfig; import com.google.gerrit.server.config.CanonicalWebUrl; @@ -62,15 +63,18 @@ class LoginForm extends HttpServlet { private final OpenIdServiceImpl impl; private final int maxRedirectUrlLength; private final String ssoUrl; + private final SiteHeaderFooter header; @Inject LoginForm( @CanonicalWebUrl @Nullable Provider urlProvider, @GerritServerConfig Config config, AuthConfig authConfig, - OpenIdServiceImpl impl) { + OpenIdServiceImpl impl, + SiteHeaderFooter header) { this.urlProvider = urlProvider; this.impl = impl; + this.header = header; this.maxRedirectUrlLength = config.getInt( "openid", "maxRedirectUrlLength", 10); @@ -231,7 +235,7 @@ class LoginForm extends HttpServlet { cancel += "#" + token; } - Document doc = HtmlDomUtil.parseFile(LoginForm.class, "LoginForm.html"); + Document doc = header.parse(LoginForm.class, "LoginForm.html"); HtmlDomUtil.find(doc, "hostName").setTextContent(req.getServerName()); HtmlDomUtil.find(doc, "login_form").setAttribute("action", self); HtmlDomUtil.find(doc, "cancel_link").setAttribute("href", cancel); diff --git a/gerrit-openid/src/main/resources/com/google/gerrit/httpd/auth/openid/LoginForm.html b/gerrit-openid/src/main/resources/com/google/gerrit/httpd/auth/openid/LoginForm.html index da6eb05e20..f5734ffe45 100644 --- a/gerrit-openid/src/main/resources/com/google/gerrit/httpd/auth/openid/LoginForm.html +++ b/gerrit-openid/src/main/resources/com/google/gerrit/httpd/auth/openid/LoginForm.html @@ -27,50 +27,58 @@ background: #fff url('data:image/gif;base64,R0lGODlhEAAQAMQAAO3t7eHh4srKyvz8/P5pDP9rENLS0v/28P/17tXV1dHEvPDw8M3Nzfn5+d3d3f5jA97Syvnv6MfLzcfHx/1mCPx4Kc/S1Pf189C+tP+xgv/k1N3OxfHy9NLV1/39/f///yH5BAAAAAAALAAAAAAQABAAAAVq4CeOZGme6KhlSDoexdO6H0IUR+otwUYRkMDCUwIYJhLFTyGZJACAwQcgEAQ4kVuEE2AIGAOPQQAQwXCfS8KQGAwMjIYIUSi03B7iJ+AcnmclHg4TAh0QDzIpCw4WGBUZeikDFzk0lpcjIQA7') no-repeat scroll 5px 50% } + -

Sign In to Gerrit Code Review at example.com

-
- -
-
Invalid OpenID identifier.
-
- -
-
- - -
-
- - Cancel -
+
+
+
+

Sign In to Gerrit Code Review at example.com

+ + +
+
Invalid OpenID identifier.
+
+ +
+
+ + +
+
+ + Cancel +
- - + + -
-

What is OpenID?

-

OpenID provides secure single-sign-on, without revealing your passwords to this website.

-

There are many OpenID providers available. You may already be member of one!

-

Get OpenID

-
- +
+

What is OpenID?

+

OpenID provides secure single-sign-on, without revealing your passwords to this website.

+

There are many OpenID providers available. You may already be member of one!

+

Get OpenID

+
+ +
+
+ +
-