/* * KBAccess - Collaborative database of accessibility examples * Copyright (C) 2012-2016 Open-S Company * * This file is part of KBAccess. * * KBAccess is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Contact us by mail: open-s AT open-s DOT com */ package org.opens.kbaccess.controller; import java.util.Calendar; import org.apache.commons.logging.LogFactory; import org.opens.kbaccess.command.AccountCommand; import org.opens.kbaccess.command.PasswordLostCommand; import org.opens.kbaccess.controller.utils.AMailerController; import org.opens.kbaccess.entity.authorization.AccessLevel; import org.opens.kbaccess.entity.authorization.AccessLevelEnumType; import org.opens.kbaccess.entity.authorization.Account; import org.opens.kbaccess.entity.service.authorization.AccessLevelDataService; import org.opens.kbaccess.entity.service.authorization.AccountDataService; import org.opens.kbaccess.keystore.MessageKeyStore; import org.opens.kbaccess.utils.AccountUtils; import org.opens.kbaccess.utils.MailingServiceProperties; import org.opens.kbaccess.utils.TgolTokenHelper; import org.opens.kbaccess.validator.NewAccountValidator; import org.opens.kbaccess.validator.PasswordLostValidator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; /** * * @author bcareil */ @Controller @RequestMapping("/guest/") public class GuestController extends AMailerController { @Autowired private AccessLevelDataService accessLevelDataService; @Autowired private MailingServiceProperties mailingServiceProperties; /* * private methods */ private String generateToken(Account account, boolean hasExpiration) { TgolTokenHelper tokenHelper = TgolTokenHelper.getInstance(); return tokenHelper.getTokenUser(account, hasExpiration); } private boolean sendAuthTokenAndSubscribeNotificationByMail(String lang, Account account) { if (!sendAuthToken(lang, account)) { LogFactory.getLog(GuestController.class).debug("Unable to send the auth token"); return false; } else if (!sendSubsciptionNotification(account)) { LogFactory.getLog(GuestController.class).error("Unable to send the subscription notification"); } return true; } private boolean sendNewPasswordTokenByMail(String lang, Account account) { if (!sendNewPasswordToken(lang, account)) { LogFactory.getLog(GuestController.class).error("Error sending new password token by mail to " + account.getEmail()); return false; } return true; } /** * Return true whether or not the user has the right to access this controller. * @return */ private boolean checkAuthority() { // we ban the authenticated user from the guest controller return (AccountUtils.getInstance().getCurrentUser() == null); } /** * The method called when checkAuthority return false : lead the user to * another page. * * @param model * @return */ private String forwardBannedUsers() { return "redirect:/"; } /* * Subscription handlers */ @RequestMapping(value="subscribe", method=RequestMethod.GET) public String subscribeHandler(Model model) { // check if the user has the right to be there if (!checkAuthority()) { return forwardBannedUsers(); } // handleUserLoginForm(model); handleBreadcrumbTrail(model); // model.addAttribute("newAccountCommand", new AccountCommand()); return "guest/subscribe"; } @RequestMapping(value="subscribe", method=RequestMethod.POST) public String subscribeHandler( @ModelAttribute("newAccountCommand") AccountCommand accountCommand, BindingResult result, Model model ) { NewAccountValidator newAccountValidator = new NewAccountValidator(accountDataService); Account newAccount; String authToken; // check if the user has the right to be there if (!checkAuthority()) { return forwardBannedUsers(); } // handle login form and breadcrumb handleUserLoginForm(model); handleBreadcrumbTrail(model); // validate the user input newAccountValidator.validate(accountCommand, result); if (result.hasErrors()) { model.addAttribute("newAccountCommand", accountCommand); return "guest/subscribe"; } // create account newAccount = accountDataService.create(); accountCommand.updateAccount(newAccount); AccessLevel al = accessLevelDataService.getByCode(AccessLevelEnumType.CONTRIBUTOR.getType()); newAccount.setAccessLevel(al); newAccount.setSubscriptionDate(Calendar.getInstance().getTime()); authToken = generateToken(newAccount, false); newAccount.setAuthCode(authToken); // send subscribe confirmation, with auth token, and notification if (!sendAuthTokenAndSubscribeNotificationByMail(null, newAccount)) { model.addAttribute("subscribeError", MessageKeyStore.SUBSCRIBE_ERROR); } else { accountDataService.saveOrUpdate(newAccount); model.addAttribute("newAccountCreated", true); } return "guest/subscribe"; } /* * Login handlers */ @RequestMapping(value="login", method=RequestMethod.GET) public String loginHandler(Model model) { // check if the user has the right to be there if (!checkAuthority()) { return forwardBannedUsers(); } // handleBreadcrumbTrail(model); return "guest/login"; } /* * password lost handler */ @RequestMapping(value="password-lost", method= RequestMethod.GET) public String passwordLostHandler(Model model) { // check if the user has the right to be there if (!checkAuthority()) { return forwardBannedUsers(); } // handle login form and breadcrumb handleUserLoginForm(model); handleBreadcrumbTrail(model); // model.addAttribute("passwordLostCommand", new PasswordLostCommand()); return "guest/password-lost"; } @RequestMapping(value="password-lost", method= RequestMethod.POST) public String passwordLostHandler( @ModelAttribute("passwordLostCommand") PasswordLostCommand passwordLostCommand, BindingResult result, Model model ) { PasswordLostValidator passwordLostValidator = new PasswordLostValidator(accountDataService); Account account; String token; // check if the user has the right to be there if (!checkAuthority()) { return forwardBannedUsers(); } // handle login form and breadcrumb handleUserLoginForm(model); handleBreadcrumbTrail(model); // validate form passwordLostValidator.validate(passwordLostCommand, result); if (result.hasErrors()) { model.addAttribute("passwordLostCommand", passwordLostCommand); return "guest/password-lost"; } // send new password token by mail account = accountDataService.getAccountFromEmail(passwordLostCommand.getEmail()); token = generateToken(account, true); if (account != null && sendNewPasswordTokenByMail(null, account)) { model.addAttribute("passwordSent", true); account.setAuthCode(token); accountDataService.update(account); } else { model.addAttribute("passwordLostError", MessageKeyStore.PASSWORD_LOST_ERROR); } return "guest/password-lost"; } /* * Account activation handler */ @RequestMapping(value="activate-account", method=RequestMethod.GET) public String activateAccountHandler( @RequestParam(value="token", required=false) String token, Model model ) { // check if the user has the right to be there if (!checkAuthority()) { return forwardBannedUsers(); } // handle login form and breadcrumb handleUserLoginForm(model); handleBreadcrumbTrail(model); // sanity check if (AccountUtils.getInstance().getCurrentUser() != null) { LogFactory.getLog(GuestController.class).error("An authentified user reached guest/activate-account. Check spring security configuration"); return "home"; } // TgolTokenHelper tokenHelper = TgolTokenHelper.getInstance(); String email = tokenHelper.getUserEmailFromToken(token); Account account = accountDataService.getAccountFromEmail(email); if (account == null) { LogFactory.getLog(AccountController.class).info("Token with an invalid email"); return "guest/login"; } else if (account.isActivated()) { LogFactory.getLog(AccountController.class).info("Account already activated"); return "guest/login"; } else if (!tokenHelper.checkUserToken(token)) { String newToken = generateToken(account, false); account.setAuthCode(newToken); sendAuthToken(null, account); accountDataService.saveOrUpdate(account); model.addAttribute("errorMessage", true); LogFactory.getLog(AccountController.class).info("Token expired, new token sent"); return "guest/activate-account"; } else { // otherwise, activate the associated account if (token.equals(account.getAuthCode())) { LogFactory.getLog(AccountController.class).info("account activation"); account.setActivated(true); account.setAuthCode(null); accountDataService.saveOrUpdate(account); } } return "guest/activate-account"; } /* * Accessors */ @Override public MailingServiceProperties getMailingServiceProperties() { return mailingServiceProperties; } @Override public void setMailingServiceProperties(MailingServiceProperties mailingServiceProperties) { this.mailingServiceProperties = mailingServiceProperties; } public AccessLevelDataService getAccessLevelDataService() { return accessLevelDataService; } public void setAccessLevelDataService(AccessLevelDataService accessLevelDataService) { this.accessLevelDataService = accessLevelDataService; } }