001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.ui.login; 029 030import org.opencms.file.CmsObject; 031import org.opencms.file.CmsUser; 032import org.opencms.flex.CmsFlexController; 033import org.opencms.gwt.shared.CmsGwtConstants; 034import org.opencms.i18n.CmsEncoder; 035import org.opencms.main.CmsException; 036import org.opencms.main.CmsLog; 037import org.opencms.main.CmsRuntimeException; 038import org.opencms.main.OpenCms; 039import org.opencms.security.CmsOrganizationalUnit; 040import org.opencms.ui.A_CmsUI; 041import org.opencms.ui.CmsVaadinErrorHandler; 042import org.opencms.ui.CmsVaadinUtils; 043import org.opencms.ui.Messages; 044import org.opencms.ui.apps.CmsAppWorkplaceUi; 045import org.opencms.ui.components.CmsBasicDialog; 046import org.opencms.ui.components.CmsBasicDialog.DialogWidth; 047import org.opencms.ui.login.CmsLoginHelper.LoginParameters; 048import org.opencms.ui.shared.CmsVaadinConstants; 049import org.opencms.util.CmsFileUtil; 050import org.opencms.util.CmsMacroResolver; 051import org.opencms.util.CmsStringUtil; 052import org.opencms.workplace.CmsWorkplace; 053import org.opencms.workplace.CmsWorkplaceManager; 054import org.opencms.workplace.CmsWorkplaceSettings; 055 056import java.io.IOException; 057import java.io.Serializable; 058import java.util.List; 059import java.util.Locale; 060 061import javax.servlet.http.HttpServletRequest; 062import javax.servlet.http.HttpServletResponse; 063import javax.servlet.http.HttpSession; 064 065import org.apache.commons.logging.Log; 066 067import com.vaadin.annotations.Theme; 068import com.vaadin.server.VaadinRequest; 069import com.vaadin.server.VaadinService; 070import com.vaadin.server.VaadinSession; 071import com.vaadin.shared.Version; 072import com.vaadin.ui.Alignment; 073import com.vaadin.ui.Button; 074import com.vaadin.ui.Notification; 075import com.vaadin.ui.Notification.Type; 076import com.vaadin.ui.Window; 077import com.vaadin.ui.Window.CloseEvent; 078import com.vaadin.ui.Window.CloseListener; 079import com.vaadin.v7.ui.Label; 080import com.vaadin.v7.ui.VerticalLayout; 081 082/** 083 * The UI class for the Vaadin-based login dialog.<p> 084 */ 085@Theme("opencms") 086public class CmsLoginUI extends A_CmsUI { 087 088 /** 089 * Parameters which are initialized during the initial page load of the login dialog.<p> 090 */ 091 public static class Parameters implements Serializable { 092 093 /** The serial version id. */ 094 private static final long serialVersionUID = -4885232184680664315L; 095 096 /** The locale. */ 097 public Locale m_locale; 098 099 /** The PC type (public or private). */ 100 public String m_pcType; 101 102 /** The preselected OU. */ 103 public String m_preselectedOu; 104 105 /** The requested resource. */ 106 public String m_requestedResource; 107 108 /** The requested workplace app path. */ 109 public String m_requestedWorkplaceApp; 110 111 /** 112 * Creates a new instance.<p> 113 * 114 * @param pcType the PC type 115 * @param preselectedOu the preselected OU 116 * @param locale the locale 117 * @param requestedResource the requested resource 118 * @param requestedWorkplaceApp the requested workplace app path 119 */ 120 public Parameters( 121 String pcType, 122 String preselectedOu, 123 Locale locale, 124 String requestedResource, 125 String requestedWorkplaceApp) { 126 127 m_pcType = pcType; 128 m_preselectedOu = preselectedOu; 129 m_locale = locale; 130 m_requestedResource = requestedResource; 131 m_requestedWorkplaceApp = requestedWorkplaceApp; 132 } 133 134 /** 135 * Gets the locale.<p> 136 * 137 * @return the locale 138 */ 139 public Locale getLocale() { 140 141 return m_locale; 142 } 143 144 /** 145 * Gets the PC type (private or public).<p> 146 * 147 * @return the pc type 148 */ 149 public String getPcType() { 150 151 return m_pcType; 152 153 } 154 155 /** 156 * Gets the preselected OU.<p> 157 * 158 * @return the preselected OU 159 */ 160 public String getPreselectedOu() { 161 162 return m_preselectedOu; 163 } 164 165 /** 166 * Gets the requested resource path.<p> 167 * 168 * @return the requested resource path 169 */ 170 public String getRequestedResource() { 171 172 return m_requestedResource; 173 } 174 175 /** 176 * Returns the requested workplace app path.<p> 177 * 178 * @return the requested workplace app path 179 */ 180 public String getRequestedWorkplaceApp() { 181 182 return m_requestedWorkplaceApp; 183 } 184 185 } 186 187 /** 188 * Attribute used to store initialization data when the UI is first loaded. 189 */ 190 public static final String INIT_DATA_SESSION_ATTR = "CmsLoginUI_initData"; 191 192 /** The admin CMS context. */ 193 static CmsObject m_adminCms; 194 195 /** Logger instance for this class. */ 196 private static final Log LOG = CmsLog.getLog(CmsLoginUI.class); 197 198 /** Serial version id. */ 199 private static final long serialVersionUID = 1L; 200 201 /** 202 * Returns the initial HTML for the Vaadin based login dialog.<p> 203 * 204 * @param request the request 205 * @param response the response 206 * 207 * @return the initial page HTML for the Vaadin login dialog 208 * 209 * @throws IOException in case writing to the response fails 210 * @throws CmsException in case the user has not the required role 211 */ 212 public static String displayVaadinLoginDialog(HttpServletRequest request, HttpServletResponse response) 213 throws IOException, CmsException { 214 215 CmsFlexController controller = CmsFlexController.getController(request); 216 if (controller == null) { 217 // controller not found - this request was not initialized properly 218 throw new CmsRuntimeException( 219 org.opencms.jsp.Messages.get().container( 220 org.opencms.jsp.Messages.ERR_MISSING_CMS_CONTROLLER_1, 221 CmsLoginUI.class.getName())); 222 } 223 CmsObject cms = controller.getCmsObject(); 224 if ((OpenCms.getSiteManager().getSites().size() > 1) && !OpenCms.getSiteManager().isWorkplaceRequest(request)) { 225 // do not send any redirects to the workplace site for security reasons 226 response.sendError(HttpServletResponse.SC_NOT_FOUND); 227 return null; 228 } 229 String logout = request.getParameter(CmsLoginHelper.PARAM_ACTION_LOGOUT); 230 if (Boolean.valueOf(logout).booleanValue()) { 231 CmsLoginController.logout(cms, request, response); 232 return null; 233 } 234 235 if (!cms.getRequestContext().getCurrentUser().isGuestUser()) { 236 String target = request.getParameter(CmsGwtConstants.PARAM_LOGIN_REDIRECT); 237 if (CmsStringUtil.isEmptyOrWhitespaceOnly(target)) { 238 target = CmsLoginController.getLoginTarget(cms, getWorkplaceSettings(cms, request.getSession()), null); 239 } 240 response.sendRedirect(target); 241 return null; 242 } 243 244 CmsLoginHelper.LoginParameters params = CmsLoginHelper.getLoginParameters(cms, request, false); 245 request.getSession().setAttribute(CmsLoginUI.INIT_DATA_SESSION_ATTR, params); 246 try { 247 byte[] pageBytes = CmsFileUtil.readFully( 248 Thread.currentThread().getContextClassLoader().getResourceAsStream( 249 "org/opencms/ui/login/login-page.html")); 250 String page = new String(pageBytes, "UTF-8"); 251 CmsMacroResolver resolver = new CmsMacroResolver(); 252 String context = OpenCms.getSystemInfo().getContextPath(); 253 String vaadinDir = CmsStringUtil.joinPaths(context, "VAADIN/"); 254 String vaadinVersion = Version.getFullVersion(); 255 String vaadinServlet = CmsStringUtil.joinPaths(context, "workplace/dialogs/"); 256 String vaadinBootstrap = CmsStringUtil.joinPaths( 257 context, 258 "VAADIN/vaadinBootstrap.js?v=" + OpenCms.getSystemInfo().getVersionNumber()); 259 String autocomplete = params.isPrivatePc() ? "on" : "off"; 260 StringBuffer workplaceCssBuffer = null; 261 if (!OpenCms.getWorkplaceAppManager().getWorkplaceCssUris().isEmpty()) { 262 workplaceCssBuffer = new StringBuffer(); 263 workplaceCssBuffer.append("\n<style type=\"text/css\">\n"); 264 for (String cssURI : OpenCms.getWorkplaceAppManager().getWorkplaceCssUris()) { 265 workplaceCssBuffer.append("@import url(\"").append(CmsWorkplace.getResourceUri(cssURI)).append( 266 "\");\n"); 267 } 268 workplaceCssBuffer.append("</style>\n"); 269 } 270 String cmsLogo = OpenCms.getSystemInfo().getContextPath() 271 + CmsWorkplace.RFS_PATH_RESOURCES 272 + "commons/login_logo.png"; 273 resolver.addMacro("workplaceCss", workplaceCssBuffer != null ? workplaceCssBuffer.toString() : ""); 274 resolver.addMacro("loadingHtml", CmsVaadinConstants.LOADING_INDICATOR_HTML); 275 resolver.addMacro("vaadinDir", vaadinDir); 276 resolver.addMacro("vaadinVersion", vaadinVersion); 277 resolver.addMacro("vaadinServlet", vaadinServlet); 278 resolver.addMacro("vaadinBootstrap", vaadinBootstrap); 279 resolver.addMacro("cmsLogo", cmsLogo); 280 resolver.addMacro("autocomplete", autocomplete); 281 resolver.addMacro("title", CmsLoginHelper.getTitle(params.getLocale())); 282 if (params.isPrivatePc()) { 283 resolver.addMacro( 284 "hiddenPasswordField", 285 " <input type=\"password\" id=\"hidden-password\" name=\"ocPword\" autocomplete=\"%(autocomplete)\" >"); 286 } 287 if (params.getUsername() != null) { 288 resolver.addMacro("predefUser", "value=\"" + CmsEncoder.escapeXml(params.getUsername()) + "\""); 289 } 290 page = resolver.resolveMacros(page); 291 return page; 292 } catch (Exception e) { 293 LOG.error("Failed to display login dialog.", e); 294 return "<!--Error-->"; 295 } 296 } 297 298 /** 299 * Returns the bootstrap html fragment required to display the login dialog.<p> 300 * 301 * @param cms the cms context 302 * @param request the request 303 * 304 * @return the html fragment 305 * 306 * @throws IOException in case reading the html template fails 307 */ 308 public static String generateLoginHtmlFragment(CmsObject cms, VaadinRequest request) throws IOException { 309 310 LoginParameters parameters = CmsLoginHelper.getLoginParameters(cms, (HttpServletRequest)request, true); 311 request.getWrappedSession().setAttribute(CmsLoginUI.INIT_DATA_SESSION_ATTR, parameters); 312 byte[] pageBytes; 313 314 pageBytes = CmsFileUtil.readFully( 315 Thread.currentThread().getContextClassLoader().getResourceAsStream( 316 "org/opencms/ui/login/login-fragment.html")); 317 318 String html = new String(pageBytes, "UTF-8"); 319 String autocomplete = ((parameters.getPcType() == null) 320 || parameters.getPcType().equals(CmsLoginHelper.PCTYPE_PRIVATE)) ? "on" : "off"; 321 CmsMacroResolver resolver = new CmsMacroResolver(); 322 resolver.addMacro("autocompplete", autocomplete); 323 if ((parameters.getPcType() == null) || parameters.getPcType().equals(CmsLoginHelper.PCTYPE_PRIVATE)) { 324 resolver.addMacro( 325 "hiddenPasswordField", 326 " <input type=\"password\" id=\"hidden-password\" name=\"ocPword\" autocomplete=\"%(autocomplete)\" >"); 327 } 328 if (parameters.getUsername() != null) { 329 resolver.addMacro("predefUser", "value=\"" + CmsEncoder.escapeXml(parameters.getUsername()) + "\""); 330 } 331 html = resolver.resolveMacros(html); 332 return html; 333 } 334 335 /** 336 * Returns the current users workplace settings.<p> 337 * 338 * @param cms the CMS context 339 * @param session the session 340 * 341 * @return the settings 342 */ 343 private static CmsWorkplaceSettings getWorkplaceSettings(CmsObject cms, HttpSession session) { 344 345 CmsWorkplaceSettings settings = (CmsWorkplaceSettings)session.getAttribute( 346 CmsWorkplaceManager.SESSION_WORKPLACE_SETTINGS); 347 if (settings == null) { 348 settings = CmsLoginHelper.initSiteAndProject(cms); 349 if (VaadinService.getCurrentRequest() != null) { 350 VaadinService.getCurrentRequest().getWrappedSession().setAttribute( 351 CmsWorkplaceManager.SESSION_WORKPLACE_SETTINGS, 352 settings); 353 } else { 354 session.setAttribute(CmsWorkplaceManager.SESSION_WORKPLACE_SETTINGS, settings); 355 } 356 } 357 return settings; 358 } 359 360 /** 361 * Sets the admin CMS object.<p> 362 * 363 * @param cms the admin cms object 364 */ 365 public static void setAdminCmsObject(CmsObject cms) { 366 367 m_adminCms = cms; 368 } 369 370 /** The login controller. */ 371 private CmsLoginController m_controller; 372 373 /** The login form. */ 374 private CmsLoginForm m_loginForm; 375 376 /** The widget used to open the login target. */ 377 private CmsLoginTargetOpener m_targetOpener; 378 379 /** 380 * Gets the selected org unit.<p> 381 * 382 * @return the selected org unit 383 */ 384 public String getOrgUnit() { 385 386 String result = m_loginForm.getOrgUnit(); 387 if (result == null) { 388 result = ""; 389 } 390 return result; 391 392 } 393 394 /** 395 * Gets the password.<p> 396 * 397 * @return the password 398 */ 399 public String getPassword() { 400 401 return m_loginForm.getPassword(); 402 } 403 404 /** 405 * Gets the selected PC type.<p> 406 * 407 * @return the PC type 408 */ 409 public String getPcType() { 410 411 String result = m_loginForm.getPcType(); 412 if (result == null) { 413 result = CmsLoginForm.PC_TYPE_PUBLIC; 414 } 415 return result; 416 } 417 418 /** 419 * Gets the user name.<p> 420 * 421 * @return the user name 422 */ 423 public String getUser() { 424 425 return m_loginForm.getUser(); 426 } 427 428 /** 429 * @see com.vaadin.ui.UI#init(com.vaadin.server.VaadinRequest) 430 */ 431 @Override 432 protected void init(VaadinRequest request) { 433 434 addStyleName("login-dialog"); 435 LoginParameters params = (LoginParameters)(request.getWrappedSession().getAttribute(INIT_DATA_SESSION_ATTR)); 436 if (params == null) { 437 params = CmsLoginHelper.getLoginParameters(getCmsObject(), (HttpServletRequest)request, true); 438 request.getWrappedSession().setAttribute(CmsLoginUI.INIT_DATA_SESSION_ATTR, params); 439 } 440 VaadinSession.getCurrent().setErrorHandler(new CmsVaadinErrorHandler()); 441 m_controller = new CmsLoginController(m_adminCms, params); 442 m_controller.setUi(this); 443 setLocale(params.getLocale()); 444 m_loginForm = new CmsLoginForm(m_controller, params.getLocale()); 445 m_controller.onInit(); 446 getPage().setTitle( 447 CmsAppWorkplaceUi.WINDOW_TITLE_PREFIX 448 + CmsVaadinUtils.getMessageText(org.opencms.workplace.Messages.GUI_LOGIN_HEADLINE_0)); 449 } 450 451 /** 452 * Opens the login target for a logged in user.<p> 453 * 454 * @param loginTarget the login target 455 * @param isPublicPC the public PC flag 456 */ 457 public void openLoginTarget(String loginTarget, boolean isPublicPC) { 458 459 // login was successful, remove login init data from session 460 VaadinService.getCurrentRequest().getWrappedSession().removeAttribute(INIT_DATA_SESSION_ATTR); 461 m_targetOpener.openTarget(loginTarget, isPublicPC); 462 } 463 464 /** 465 * Sets the org units which should be selectable by the user.<p> 466 * 467 * @param ous the selectable org units 468 */ 469 public void setSelectableOrgUnits(List<CmsOrganizationalUnit> ous) { 470 471 m_loginForm.setSelectableOrgUnits(ous); 472 } 473 474 /** 475 * Show notification that the user is already loogged in.<p> 476 */ 477 public void showAlreadyLoggedIn() { 478 479 // TODO: do something useful 480 Notification.show("You are already logged in"); 481 } 482 483 /** 484 * Shows the 'forgot password view'.<p> 485 * 486 * @param authToken the authorization token given as a request parameter 487 */ 488 public void showForgotPasswordView(String authToken) { 489 490 try { 491 CmsTokenValidator validator = new CmsTokenValidator(); 492 String validationResult = validator.validateToken( 493 A_CmsUI.getCmsObject(), 494 authToken, 495 OpenCms.getLoginManager().getTokenLifetime()); 496 if (validationResult == null) { 497 CmsUser user = validator.getUser(); 498 if (!user.isManaged()) { 499 CmsSetPasswordDialog dlg = new CmsSetPasswordDialog(m_adminCms, user, getLocale()); 500 A_CmsUI.get().setContentToDialog( 501 Messages.get().getBundle(A_CmsUI.get().getLocale()).key(Messages.GUI_PWCHANGE_HEADER_0) 502 + user.getName(), 503 dlg); 504 } else { 505 Notification.show( 506 CmsVaadinUtils.getMessageText(Messages.ERR_USER_NOT_SELF_MANAGED_1, user.getName()), 507 Type.ERROR_MESSAGE); 508 } 509 } else { 510 A_CmsUI.get().setError( 511 Messages.get().getBundle(A_CmsUI.get().getLocale()).key(Messages.GUI_PWCHANGE_INVALID_TOKEN_0)); 512 LOG.info("Invalid authorization token: " + authToken + " / " + validationResult); 513 } 514 } catch (Exception e) { 515 LOG.error(e.getLocalizedMessage(), e); 516 } 517 } 518 519 /** 520 * Shows the given login error message.<p> 521 * 522 * @param messageHtml the message HTML 523 */ 524 public void showLoginError(String messageHtml) { 525 526 m_loginForm.displayError(messageHtml); 527 m_loginForm.resetPassword(); 528 } 529 530 /** 531 * Initializes the login view.<p> 532 * 533 * @param preselectedOu a potential preselected OU 534 */ 535 public void showLoginView(String preselectedOu) { 536 537 VerticalLayout content = new VerticalLayout(); 538 content.setSizeFull(); 539 540 m_targetOpener = new CmsLoginTargetOpener(A_CmsUI.get()); 541 //content.setExpandRatio(m_targetOpener, 0f); 542 content.addComponent(m_loginForm); 543 content.setComponentAlignment(m_loginForm, Alignment.MIDDLE_CENTER); 544 content.setExpandRatio(m_loginForm, 1); 545 546 setContent(content); 547 if (preselectedOu == null) { 548 preselectedOu = "/"; 549 } 550 m_loginForm.selectOrgUnit(preselectedOu); 551 552 } 553 554 /** 555 * Shows the password reset dialog.<p> 556 */ 557 public void showPasswordResetDialog() { 558 559 String caption = CmsVaadinUtils.getMessageText(Messages.GUI_PWCHANGE_FORGOT_PASSWORD_0); 560 A_CmsUI r = A_CmsUI.get(); 561 r.setContent(new Label()); 562 Window window = CmsBasicDialog.prepareWindow(DialogWidth.narrow); 563 CmsBasicDialog dialog = new CmsBasicDialog(); 564 VerticalLayout result = new VerticalLayout(); 565 dialog.setContent(result); 566 window.setContent(dialog); 567 window.setCaption(caption); 568 window.setClosable(true); 569 final CmsForgotPasswordDialog forgotPassword = new CmsForgotPasswordDialog(); 570 window.addCloseListener(new CloseListener() { 571 572 /** Serial version id. */ 573 private static final long serialVersionUID = 1L; 574 575 public void windowClose(CloseEvent e) { 576 577 forgotPassword.cancel(); 578 } 579 580 }); 581 for (Button button : forgotPassword.getButtons()) { 582 dialog.addButton(button); 583 } 584 585 r.addWindow(window); 586 window.center(); 587 VerticalLayout vl = result; 588 vl.addComponent(forgotPassword); 589 } 590}