diff options
author | Shawn Pearce <sop@google.com> | 2013-04-23 13:49:57 -0700 |
---|---|---|
committer | Shawn Pearce <sop@google.com> | 2013-04-23 13:49:57 -0700 |
commit | b216ac07ecddc4f32de2af574b3ce1d8b11cb8de (patch) | |
tree | fa94a313483f72ecb2eb2b208c9b4a75bed4cd3e /gerrit-httpd | |
parent | 98c89249c574d7a37c52825b9bb368cda35eca33 (diff) |
Include site header, footer and CSS on OpenID login form
Bug: issue 1879
Change-Id: I1c583e01433d09627ac845288cd67db35029ae58
Diffstat (limited to 'gerrit-httpd')
5 files changed, 230 insertions, 110 deletions
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<ReviewDb> schema; private final Provider<WebSession> webSession; private final AccountManager accountManager; + private final SiteHeaderFooter headers; @Inject BecomeAnyAccountLoginServlet(final Provider<WebSession> ws, final SchemaFactory<ReviewDb> 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/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> webSession; private final Provider<String> urlProvider; - private final SitePaths sitePaths; + private final SiteHeaderFooter headers; @Inject LdapLoginServlet(AccountManager accountManager, Provider<WebSession> webSession, @CanonicalWebUrl @Nullable Provider<String> 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 @@ } })(); </script> + <style id="gerrit_sitecss" type="text/css"></style> </head> <body> - <h2>Sign In</h2> - <table border="0"> - <tr> - <th>Username:</th> - <td> - <form method="GET"> - <input type="text" size="30" name="user_name" /> - <input type="submit" value="Become Account" /> - </form> - </td> - </tr> + <div id="gerrit_topmenu" style="height:45px;" class="gerritTopMenu"></div> + <div id="gerrit_header"></div> + <div id="gerrit_body" class="gerritBody"> + <h2>Sign In</h2> + <table border="0"> + <tr> + <th>Username:</th> + <td> + <form method="GET"> + <input type="text" size="30" name="user_name" /> + <input type="submit" value="Become Account" /> + </form> + </td> + </tr> - <tr> - <th>Email Address:</th> - <td> - <form method="GET"> - <input type="text" size="30" name="preferred_email" /> - <input type="submit" value="Become Account" /> - </form> - </td> - </tr> + <tr> + <th>Email Address:</th> + <td> + <form method="GET"> + <input type="text" size="30" name="preferred_email" /> + <input type="submit" value="Become Account" /> + </form> + </td> + </tr> - <tr> - <th>Account ID:</th> - <td> - <form method="GET"> - <input type="text" size="12" name="account_id" /> - <input type="submit" value="Become Account" /> - </form> - </td> - </tr> + <tr> + <th>Account ID:</th> + <td> + <form method="GET"> + <input type="text" size="12" name="account_id" /> + <input type="submit" value="Become Account" /> + </form> + </td> + </tr> - <tr> - <th>Choose:</th> - <td id="userlist"/> - </tr> - </table> + <tr> + <th>Choose:</th> + <td id="userlist"/> + </tr> + </table> - <hr /> - <h2>Register</h2> - <form method="POST"> - <input type="hidden" name="action" value="create_account" /> - <input type="submit" value="New Account" /> - </form> + <hr /> + <h2>Register</h2> + <form method="POST"> + <input type="hidden" name="action" value="create_account" /> + <input type="submit" value="New Account" /> + </form> + </div> + <div style="clear: both; margin-top: 15px; padding-top: 2px; margin-bottom: 15px;"> + <div id="gerrit_footer"></div> + </div> </body> </html> 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; } </style> - <style id="gerrit_sitecss" type="text/css"></style> + <style id="gerrit_sitecss" type="text/css"></style> </head> <body> <div id="gerrit_topmenu" style="height:45px;" class="gerritTopMenu"></div> @@ -56,28 +56,28 @@ </tr> </table> </form> - - <script type="text/javascript"> - var login_form = document.getElementById('login_form'); - var f_user = document.getElementById('f_user'); - var f_pass = document.getElementById('f_pass'); - f_user.onkeydown = function(e) { - if (e.keyCode == 13) { - f_pass.focus(); - return false; - } - } - f_pass.onkeydown = function(e) { - if (e.keyCode == 13) { - login_form.submit(); - return false; - } - } - f_user.focus(); - </script> <div style="clear: both; margin-top: 15px; padding-top: 2px; margin-bottom: 15px;"> <div id="gerrit_footer"></div> </div> </div> + + <script type="text/javascript"> + var login_form = document.getElementById('login_form'); + var f_user = document.getElementById('f_user'); + var f_pass = document.getElementById('f_pass'); + f_user.onkeydown = function(e) { + if (e.keyCode == 13) { + f_pass.focus(); + return false; + } + } + f_pass.onkeydown = function(e) { + if (e.keyCode == 13) { + login_form.submit(); + return false; + } + } + f_user.focus(); + </script> </body> </html> |