/* * ConcourseConnect * Copyright 2009 Concursive Corporation * http://www.concursive.com * * This file is part of ConcourseConnect, an open source social business * software and community platform. * * Concursive ConcourseConnect 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, version 3 of the License. * * Under the terms of the GNU Affero General Public License you must release the * complete source code for any application that uses any part of ConcourseConnect * (system header files and libraries used by the operating system are excluded). * These terms must be included in any work that has ConcourseConnect components. * If you are developing and distributing open source applications under the * GNU Affero General Public License, then you are free to use ConcourseConnect * under the GNU Affero General Public License. * * If you are deploying a web site in which users interact with any portion of * ConcourseConnect over a network, the complete source code changes must be made * available. For example, include a link to the source archive directly from * your web site. * * For OEMs, ISVs, SIs and VARs who distribute ConcourseConnect with their * products, and do not license and distribute their source code under the GNU * Affero General Public License, Concursive provides a flexible commercial * license. * * To anyone in doubt, we recommend the commercial license. Our commercial license * is competitively priced and will eliminate any confusion about how * ConcourseConnect can be used and distributed. * * ConcourseConnect 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 ConcourseConnect. If not, see <http://www.gnu.org/licenses/>. * * Attribution Notice: ConcourseConnect is an Original Work of software created * by Concursive Corporation */ package com.concursive.connect.web.modules.register.beans; import com.concursive.commons.codec.PasswordHash; import com.concursive.commons.db.DatabaseUtils; import com.concursive.commons.email.EmailUtils; import com.concursive.commons.text.StringUtils; import com.concursive.commons.web.mvc.beans.GenericBean; import com.concursive.connect.Constants; import com.concursive.connect.cache.utils.CacheUtils; import com.concursive.connect.config.ApplicationPrefs; import com.concursive.connect.web.modules.common.social.geotagging.utils.LocationBean; import com.concursive.connect.web.modules.common.social.geotagging.utils.LocationUtils; import com.concursive.connect.web.modules.login.dao.User; import com.concursive.connect.web.modules.login.utils.UserUtils; import com.concursive.connect.web.modules.profile.dao.Project; import com.concursive.connect.web.modules.profile.utils.ProjectUtils; import nl.captcha.Captcha; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.portlet.ActionRequest; import javax.portlet.PortletSession; import java.sql.*; /** * HTML form bean for the registration process * * @author matt rajkowski * @version $Id$ * @created September 30, 2003 */ public class RegisterBean extends GenericBean { private static Log LOG = LogFactory.getLog(RegisterBean.class); public final static String lf = System.getProperty("line.separator"); // Bean properties private int instanceId = -1; // Form properties private String city = null; private String state = null; private String country = null; private String requestIteams = null; private String email = null; private String nameFirst = null; private String nameLast = null; private String organization = null; private String password = null; private String encryptedPassword = null; private boolean terms = false; private String captcha = null; private String postalCode = null; private String data = null; private Timestamp entered = null; private Timestamp modified = null; // Resulting user private User user = null; /** * Constructor for the RegisterBean object */ public RegisterBean() { } public int getInstanceId() { return instanceId; } public void setInstanceId(int instanceId) { this.instanceId = instanceId; } /** * Sets the request iteams the RegisterBean object * * @param tmp the request iteams value */ public void setRequestIteams(String tmp) { this.requestIteams = tmp; } /** * Sets the country attribute of the RegisterBean object * * @param tmp The new country value */ public void setCountry(String tmp) { this.country = tmp; } /** * Sets the email attribute of the RegisterBean object * * @param tmp The new email value */ public void setEmail(String tmp) { if (tmp != null) { email = tmp.trim(); } else { this.email = tmp; } } /** * Sets the nameFirst attribute of the RegisterBean object * * @param tmp The new nameFirst value */ public void setNameFirst(String tmp) { this.nameFirst = tmp; } /** * Sets the nameLast attribute of the RegisterBean object * * @param tmp The new nameLast value */ public void setNameLast(String tmp) { this.nameLast = tmp; } /** * Sets the organization attribute of the RegisterBean object * * @param tmp The new organization value */ public void setOrganization(String tmp) { this.organization = tmp; } /** * Sets the password attribute of the RegisterBean object * * @param tmp The new password value */ public void setPassword(String tmp) { this.password = tmp; } /** * Sets the encryptedPassword attribute of the RegisterBean object * * @param tmp The new encryptedPassword value */ public void setEncryptedPassword(String tmp) { this.encryptedPassword = tmp; } /** * Sets the terms attribute of the RegisterBean object * * @param tmp The new terms value */ public void setTerms(boolean tmp) { this.terms = tmp; } /** * Sets the terms attribute of the RegisterBean object * * @param tmp The new terms value */ public void setTerms(String tmp) { this.terms = (tmp.equals("accept") || DatabaseUtils.parseBoolean(tmp)); } /** * Sets the user attribute of the RegisterBean object * * @param tmp The new user value */ public void setUser(User tmp) { this.user = tmp; } /** * Gets the country attribute of the RegisterBean object * * @return The country value */ public String getCountry() { return country; } /** * Gets the request iteams attribute of the RegisterBean object * * @return The request iteams value */ public String getRequestIteams() { return requestIteams; } /** * Gets the email attribute of the RegisterBean object * * @return The email value */ public String getEmail() { return email; } /** * Gets the nameFirst attribute of the RegisterBean object * * @return The nameFirst value */ public String getNameFirst() { return nameFirst; } /** * Gets the nameLast attribute of the RegisterBean object * * @return The nameLast value */ public String getNameLast() { return nameLast; } /** * Gets the organization attribute of the RegisterBean object * * @return The organization value */ public String getOrganization() { return organization; } /** * Gets the password attribute of the RegisterBean object * * @return The password value */ public String getPassword() { return password; } /** * Gets the encryptedPassword attribute of the RegisterBean object * * @return The encryptedPassword value */ public String getEncryptedPassword() { return encryptedPassword; } /** * Gets the terms attribute of the RegisterBean object * * @return The terms value */ public boolean getTerms() { return terms; } public String getCaptcha() { return captcha; } public void setCaptcha(String captcha) { this.captcha = captcha; } public String getPostalCode() { return postalCode; } public void setPostalCode(String postalCode) { this.postalCode = postalCode; } public String getData() { return data; } public void setData(String data) { this.data = data; } /** * Gets the user attribute of the RegisterBean object * * @return The user value */ public User getUser() { return user; } public Project getProject() { if (user != null && user.getProfileProjectId() > -1) { return ProjectUtils.loadProject(user.getProfileProjectId()); } return null; } /** * @return the city */ public String getCity() { return city; } /** * @param city the city to set */ public void setCity(String city) { this.city = city; } /** * @return the state */ public String getState() { return state; } /** * @param state the state to set */ public void setState(String state) { this.state = state; } /** * @return the entered */ public Timestamp getEntered() { return entered; } /** * @param entered the entered to set */ public void setEntered(Timestamp entered) { this.entered = entered; } public void setEntered(String entered) { this.entered = DatabaseUtils.parseTimestamp(entered); } /** * @return the modified */ public Timestamp getModified() { return modified; } /** * @param modified the modified to set */ public void setModified(Timestamp modified) { this.modified = modified; } public void setModified(String modified) { this.modified = DatabaseUtils.parseTimestamp(modified); } /** * Gets the valid attribute of the RegisterBean object * * @param session http session for captcha check * @return The valid value */ public boolean isValid(PortletSession session) { String captchaPassed = (String) session.getAttribute("TE-REGISTER-CAPTCHA-PASSED"); if (!"passed".equals(captchaPassed)) { Captcha captchaValue = (Captcha) session.getAttribute(Captcha.NAME); session.removeAttribute(Captcha.NAME); if (captchaValue == null) { LOG.warn("RegisterBean-> Could not find captcha session variable for comparison to user input"); } if (captchaValue == null || captcha == null || !captchaValue.isCorrect(captcha)) { errors.put("captchaError", "Text did not match image"); } else { session.setAttribute("TE-REGISTER-CAPTCHA-PASSED", "passed"); } } if (!StringUtils.hasText(email)) { errors.put("emailError", "Required field"); } else { if (!EmailUtils.checkEmail(email)) { errors.put("emailError", "Check the email address entered"); } } if (!StringUtils.hasText(nameFirst)) { errors.put("nameFirstError", "Required field"); } if (!StringUtils.hasText(nameLast)) { errors.put("nameLastError", "Required field"); } if (!StringUtils.hasText(country)) { errors.put("countryError", "Required field"); } if ("UNITED STATES".equals(country)) { if (!StringUtils.hasText(postalCode)) { errors.put("postalCodeError", "Required field"); } else { LocationBean location = LocationUtils.findLocationByZipCode(postalCode); if (location == null) { errors.put("postalCodeError", "Could not locate this zip or postal code"); } } } return (!hasErrors()); } /** * Gets the alreadyRegistered attribute of the RegisterBean object * * @param db Description of the Parameter * @return The alreadyRegistered value * @throws SQLException Description of the Exception */ public boolean isAlreadyRegistered(Connection db) throws SQLException { PreparedStatement pst = db.prepareStatement( "SELECT count(*) AS records " + "FROM users " + "WHERE lower(email) = ? " + "AND registered = ?"); pst.setString(1, email.toLowerCase()); pst.setBoolean(2, true); ResultSet rs = pst.executeQuery(); rs.next(); int count = rs.getInt("records"); rs.close(); pst.close(); return count >= 1; } /** * Description of the Method * * @param db Description of the Parameter * @param prefs Description of the Parameter * @param request Description of the Parameter * @param userIp The user's ip address in which the registration was made from * @return Description of the Return Value * @throws SQLException Description of the Exception */ public boolean save(Connection db, ApplicationPrefs prefs, ActionRequest request, String userIp) throws SQLException { // Remove the captcha's session value request.getPortletSession().removeAttribute("TE-REGISTER-CAPTCHA-PASSED"); // Determine the user's password password = String.valueOf(StringUtils.rand(100000, 999999)); encryptedPassword = PasswordHash.encrypt(password); // NOTE: A confirmation message will be sent by the workflow boolean commit = db.getAutoCommit(); try { if (commit) { db.setAutoCommit(false); } // Store the user in the database user = new User(); user.setId(User.getIdByEmailAddress(db, email)); user.setInstanceId(instanceId); user.setGroupId(1); user.setDepartmentId(1); user.setFirstName(nameFirst); user.setLastName(nameLast); user.setCompany(organization); user.setEmail(email); user.setUsername(email); user.setPassword(encryptedPassword); user.setEnteredBy(0); user.setModifiedBy(0); user.setEnabled(true); user.setStartPage(1); user.setRegistered(true); user.setTerms(terms); user.setAccountSize(prefs.get("ACCOUNT.SIZE")); user.setAccessAddProjects(prefs.get(ApplicationPrefs.USERS_CAN_START_PROJECTS)); user.setCity(city); user.setState(state); user.setCountry(country); user.setPostalCode(postalCode); if (user.getId() == -1) { // This is a new user, so insert user.insert(db, userIp, prefs); } else { // Else set the status as registered and update the info updateRegisteredStatus(db, user); } if (commit) { db.commit(); } } catch (Exception e) { LOG.error("save", e); if (commit) { db.rollback(); } throw new SQLException(e.getMessage()); } finally { if (commit) { db.setAutoCommit(true); } } // After the commit, reload the complete user record CacheUtils.invalidateValue(Constants.SYSTEM_USER_CACHE, user.getId()); CacheUtils.invalidateValue(Constants.SYSTEM_PROJECT_CACHE, user.getProfileProjectId()); user = UserUtils.loadUser(user.getId()); this.setEntered(user.getEntered()); this.setModified(user.getModified()); return true; } /** * Description of the Method * * @param db Description of the Parameter * @param partialUserRecord Description of the Parameter * @return Description of the Return Value * @throws SQLException Description of the Exception */ private static void updateRegisteredStatus(Connection db, User partialUserRecord) throws SQLException { // NOTE: Assume the user object isn't complete, so can't load it, etc. { // Approve the user PreparedStatement pst = db.prepareStatement( "UPDATE users " + "SET first_name = ?, last_name = ?, password = ?, " + "company = ?, registered = ?, enabled = ?, terms = ? " + "WHERE user_id = ? "); int i = 0; pst.setString(++i, partialUserRecord.getFirstName()); pst.setString(++i, partialUserRecord.getLastName()); pst.setString(++i, partialUserRecord.getPassword()); pst.setString(++i, partialUserRecord.getCompany()); pst.setBoolean(++i, true); pst.setBoolean(++i, true); pst.setBoolean(++i, partialUserRecord.getTerms()); pst.setInt(++i, partialUserRecord.getId()); pst.executeUpdate(); pst.close(); CacheUtils.invalidateValue(Constants.SYSTEM_USER_CACHE, partialUserRecord.getId()); } { // Approve the user's profile and update their location User user = UserUtils.loadUser(partialUserRecord.getId()); if (user == null) { LOG.warn("updateRegisteredStatus - USER RECORD IS NULL"); } else { Project profile = ProjectUtils.loadProject(user.getProfileProjectId()); if (profile == null) { LOG.warn("updateRegisteredStatus - PROFILE RECORD IS NULL"); } else { profile.setApproved(true); profile.setCity(partialUserRecord.getCity()); profile.setState(partialUserRecord.getState()); profile.setCountry(partialUserRecord.getCountry()); profile.setPostalCode(partialUserRecord.getPostalCode()); profile.update(db); } } } } }