001/*
002 *  Copyright 2012 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.web.usermanagement;
017
018import java.io.UnsupportedEncodingException;
019import java.net.URLEncoder;
020import java.sql.Timestamp;
021import java.time.LocalDate;
022import java.time.ZoneId;
023import java.time.ZonedDateTime;
024import java.util.Arrays;
025import java.util.Date;
026import java.util.HashMap;
027import java.util.Iterator;
028import java.util.List;
029import java.util.Map;
030import java.util.Set;
031import java.util.UUID;
032
033import javax.mail.MessagingException;
034
035import org.apache.avalon.framework.configuration.Configuration;
036import org.apache.avalon.framework.configuration.ConfigurationException;
037import org.apache.avalon.framework.service.ServiceException;
038import org.apache.avalon.framework.service.ServiceManager;
039import org.apache.commons.lang.StringUtils;
040import org.apache.commons.lang3.RandomStringUtils;
041import org.apache.ibatis.session.SqlSession;
042
043import org.ametys.cms.repository.Content;
044import org.ametys.cms.transformation.URIResolver;
045import org.ametys.cms.transformation.URIResolverExtensionPoint;
046import org.ametys.core.datasource.AbstractMyBatisDAO;
047import org.ametys.core.user.InvalidModificationException;
048import org.ametys.core.user.User;
049import org.ametys.core.user.UserManager;
050import org.ametys.core.user.directory.ModifiableUserDirectory;
051import org.ametys.core.user.directory.NotUniqueUserException;
052import org.ametys.core.user.directory.UserDirectory;
053import org.ametys.core.user.population.PopulationContextHelper;
054import org.ametys.core.user.population.UserPopulation;
055import org.ametys.core.user.population.UserPopulationDAO;
056import org.ametys.core.util.I18nUtils;
057import org.ametys.core.util.mail.SendMailHelper;
058import org.ametys.plugins.repository.AmetysObjectIterable;
059import org.ametys.plugins.repository.AmetysObjectResolver;
060import org.ametys.plugins.repository.AmetysRepositoryException;
061import org.ametys.plugins.repository.query.expression.Expression;
062import org.ametys.plugins.repository.query.expression.Expression.Operator;
063import org.ametys.runtime.i18n.I18nizableText;
064import org.ametys.runtime.parameter.Errors;
065import org.ametys.web.repository.page.Page;
066import org.ametys.web.repository.page.PageQueryHelper;
067import org.ametys.web.repository.page.ZoneItem;
068import org.ametys.web.repository.site.Site;
069import org.ametys.web.repository.site.SiteManager;
070import org.ametys.web.site.SiteConfigurationExtensionPoint;
071import org.ametys.web.tags.TagExpression;
072
073import com.google.common.collect.Multimap;
074
075/**
076 * Manages registration and password recovery of users.
077 */
078public class UserSignupManager extends AbstractMyBatisDAO
079{
080
081    /** The component role. */
082    public static final String ROLE = UserSignupManager.class.getName();
083
084    /** Return code which indicates no error. */
085    public static final int SIGNUP_NO_ERROR = 0;
086
087    /** Temporary signup return code: a user tried to sign-up but the e-mail already exists in the temporary table. */
088    public static final int SIGNUP_ERROR_TEMP_EMAIL_ALREADY_EXISTS = 1;
089
090    /** Temporary signup return code: a user tried to sign-up but the FO UsersManager already possesses a user with this e-mail as login. */
091    public static final int SIGNUP_ERROR_USER_ALREADY_EXISTS = 2;
092
093    /** Token return code: a user provided a token, but it doesn't exist. */
094    public static final int SIGNUP_TOKEN_UNKNOWN = 3;
095
096    /** Token return code: a user provided a token, but it isn't valid anymore. */
097    public static final int SIGNUP_TOKEN_EXPIRED = 4;
098    
099    /** Token return code: undefined error. */
100    public static final int SIGNUP_ERROR = 5;
101    
102    /** Reset token return code: a user asked for a new token, but no subscription request can be found with this e-mail. */
103    public static final int SIGNUP_RESET_ERROR_EMAIL_UNKNOWN = 5;
104
105    /** The user manager. */
106    protected UserManager _userManager;
107    
108    /** The DAO for user populations */
109    protected UserPopulationDAO _userPopulationDAO;
110
111    /** The site manager. */
112    protected SiteManager _siteManager;
113
114    /** The site configuration extension point. */
115    protected SiteConfigurationExtensionPoint _siteConf;
116
117    /** The ametys object resolver. */
118    protected AmetysObjectResolver _resolver;
119
120    /** The ametys object resolver. */
121    protected URIResolverExtensionPoint _uriResolverEP;
122
123    /** The page URI resolver. */
124    protected URIResolver _pageUriResolver;
125
126    /** The i18n utils. */
127    protected I18nUtils _i18nUtils;
128
129    /** The user sign up configuration */
130    protected UserSignUpConfiguration _userSignUpConfiguration;
131    
132    /** The temporary users table. */
133    protected String _tempUsersTable;
134
135    /** The password change table. */
136    protected String _pwdChangeTable;
137
138    /** The population context helper. */
139    protected PopulationContextHelper _populationContextHelper;
140
141    /** Enumeration for different cases of lost password errors */
142    public enum LostPasswordError
143    {
144        /** User not connected */
145        NOT_CONNECTED,
146        /** Lost password return code: the login or e-mail the user provided doesn't correspond to a population. */
147        USER_UNKNOWN,
148        /** Lost password return code: the population the user provided doesn't correspond to a user. */
149        POPULATION_UNKNOWN,
150        /** Lost password return code: the user provided belongs to an unmodifiable user directory */
151        UNMODIFIABLE_USER_DIRECTORY,
152        /** Lost password return code: the user provided have an empty email */
153        EMPTY_EMAIL,
154        /** Lost password return code: the informations the user provided match several users */
155        SEVERAL_USERS,
156        /** Token return code: a user provided a token, but it doesn't exist. */
157        TOKEN_UNKNOWN,
158        /** Token return code: a user provided a token, but it isn't valid anymore. */
159        TOKEN_EXPIRED;
160    }
161    
162    @Override
163    public void service(ServiceManager serviceManager) throws ServiceException
164    {
165        super.service(serviceManager);
166        
167        _userManager = (UserManager) serviceManager.lookup(UserManager.ROLE);
168        _userPopulationDAO = (UserPopulationDAO) serviceManager.lookup(UserPopulationDAO.ROLE);
169        _siteManager = (SiteManager) serviceManager.lookup(SiteManager.ROLE);
170        _siteConf = (SiteConfigurationExtensionPoint) serviceManager.lookup(SiteConfigurationExtensionPoint.ROLE);
171        _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE);
172        _uriResolverEP = (URIResolverExtensionPoint) serviceManager.lookup(URIResolverExtensionPoint.ROLE);
173        _i18nUtils = (I18nUtils) serviceManager.lookup(I18nUtils.ROLE);
174        _userSignUpConfiguration = (UserSignUpConfiguration) serviceManager.lookup(UserSignUpConfiguration.ROLE);
175        _populationContextHelper = (PopulationContextHelper) serviceManager.lookup(PopulationContextHelper.ROLE);
176    }
177
178    @Override
179    public void configure(Configuration configuration) throws ConfigurationException
180    {
181        super.configure(configuration);
182        
183        // Configure pool and tables.
184        _tempUsersTable = configuration.getChild("temp-users-table").getValue();
185        _pwdChangeTable = configuration.getChild("pwd-change-table").getValue();
186    }
187
188    /**
189     * Test if public signup is allowed in a site.
190     * @param siteName the site to test.
191     * @return true if public signup is allowed, false otherwise.
192     */
193    public boolean isPublicSignupAllowed(String siteName)
194    {
195        Site site = _siteManager.getSite(siteName);
196        return site.getValue("public-signup", false, false);
197    }
198
199    /**
200     * Get the sign-up page in a given site and sitemap.<br>
201     * If more than one page are tagged "sign-up", return the first.
202     * @param siteName the site name.
203     * @param language the sitemap name.
204     * @return the sign-up page or null if not found.
205     */
206    public Page getSignupPage(String siteName, String language)
207    {
208        Page page = null;
209
210        try (AmetysObjectIterable<Page> pages = getSignupPages(siteName, language);)
211        {
212            Iterator<Page> it = pages.iterator();
213            if (it.hasNext())
214            {
215                page = it.next();
216            }
217        }
218
219        return page;
220    }
221
222    /**
223     * Get all the pages tagged "sign-up".
224     * @param siteName the site name.
225     * @param language the sitemap name.
226     * @return an iterable on all the pages tagged "sign-up".
227     */
228    public AmetysObjectIterable<Page> getSignupPages(String siteName, String language)
229    {
230        Expression expression = new TagExpression(Operator.EQ, "USER_SIGNUP");
231        String query = PageQueryHelper.getPageXPathQuery(siteName, language, null, expression, null);
232
233        return _resolver.query(query);
234    }
235
236    /**
237     * Get the password change page in a given site and sitemap.
238     * If more than one page are tagged "password change", return the first.
239     * @param siteName the site name.
240     * @param language the sitemap name.
241     * @return the password change page or null if not found.
242     */
243    public Page getPwdChangePage(String siteName, String language)
244    {
245        Page page = null;
246
247        try (AmetysObjectIterable<Page> pages = getPwdChangePages(siteName, language);)
248        {
249            Iterator<Page> it = pages.iterator();
250            if (it.hasNext())
251            {
252                page = it.next();
253            }
254        }
255
256        return page;
257    }
258    
259    /**
260     * Get the GTU page
261     * Returns null if not found or empty
262     * @param zoneItem the zone item
263     * @return the GTU page or null.
264     */
265    public Page getGTUPage(ZoneItem zoneItem)
266    {
267        Page page = null;
268
269        try
270        {
271            String tosMode = zoneItem.getServiceParameters().getValue("terms-of-service-mode");
272            if ("PAGE".equals(tosMode))
273            {
274                String tosPageId = zoneItem.getServiceParameters().getValue("terms-of-service-page");
275                if (StringUtils.isNotEmpty(tosPageId))
276                {
277                    page = _resolver.resolveById(tosPageId);
278                }
279            }
280        }
281        catch (AmetysRepositoryException e)
282        {
283            // Nothing
284        }
285
286        return page;
287    }
288    
289    /**
290     * Get the GTU content
291     * Returns null if not found or empty
292     * @param zoneItem the zone item
293     * @return the GTU content or null.
294     */
295    public Content getGTUContent(ZoneItem zoneItem)
296    {
297        Content content = null;
298
299        try
300        {
301            String tosMode = zoneItem.getServiceParameters().getValue("terms-of-service-mode");
302            if ("CONTENT".equals(tosMode))
303            {
304                String tosContentId = zoneItem.getServiceParameters().getValue("terms-of-service-content");
305                if (StringUtils.isNotEmpty(tosContentId))
306                {
307                    content = _resolver.resolveById(tosContentId);
308                }
309            }
310            
311        }
312        catch (AmetysRepositoryException e)
313        {
314            // Nothing
315        }
316
317        return content;
318    }
319    
320    /**
321     * Get the GTU page
322     * Returns null if not found or empty
323     * @param zoneItem the zone item
324     * @return the success page or null.
325     */
326    public Page getSuccessPage(ZoneItem zoneItem)
327    {
328        Page page = null;
329
330        try
331        {
332            String successMode = zoneItem.getServiceParameters().getValue("success-mode");
333            if ("PAGE".equals(successMode))
334            {
335                String successPageId = zoneItem.getServiceParameters().getValue("success-page");
336                if (StringUtils.isNotEmpty(successPageId))
337                {
338                    page = _resolver.resolveById(successPageId);
339                }
340            }
341        }
342        catch (AmetysRepositoryException e)
343        {
344            // Nothing
345        }
346
347        return page;
348    }
349    
350    /**
351     * Get the success content
352     * Returns null if not found or empty
353     * @param zoneItem the zone item
354     * @return the success content or null.
355     */
356    public Content getSuccessContent(ZoneItem zoneItem)
357    {
358        Content content = null;
359
360        try
361        {
362            String successMode = zoneItem.getServiceParameters().getValue("success-mode");
363            if ("CONTENT".equals(successMode))
364            {
365                String successContentId = zoneItem.getServiceParameters().getValue("success-content");
366                if (StringUtils.isNotEmpty(successContentId))
367                {
368                    content = _resolver.resolveById(successContentId);
369                }
370            }
371        }
372        catch (AmetysRepositoryException e)
373        {
374            // Nothing
375        }
376
377        return content;
378    }
379
380    /**
381     * Get all the pages tagged "password change".
382     * @param siteName the site name.
383     * @param language the sitemap name.
384     * @return an iterable on all the pages tagged "password change".
385     */
386    public AmetysObjectIterable<Page> getPwdChangePages(String siteName, String language)
387    {
388        Expression expression = new TagExpression(Operator.EQ, "USER_PASSWORD_CHANGE");
389        String query = PageQueryHelper.getPageXPathQuery(siteName, language, null, expression, null);
390
391        return _resolver.query(query);
392    }
393    
394    /**
395     * Tests if the user already exists in the populations 
396     * @param email the e-mail to test.
397     * @param siteName The site name
398     * @return true if the user exists, false otherwise.
399     * @throws UserManagementException if an error occurs.
400     */
401    public boolean userExists(String email, String siteName) throws UserManagementException
402    {
403        try
404        {
405            Set<String> populationIds = _populationContextHelper.getUserPopulationsOnContexts(Arrays.asList("/sites/" + siteName, "/sites-fo/" + siteName), false, false);
406            for (String population : populationIds)
407            {
408                if (_userManager.getUser(population, email) != null || _userManager.getUserByEmail(population, email) != null)
409                {
410                    return true;
411                }
412            }
413            
414            return false;
415        }
416        catch (NotUniqueUserException e)
417        {
418            return true;
419        }
420    }
421
422    /**
423     * Validate the user subscription data.
424     * @param siteName the site name.
425     * @param email the user e-mail.
426     * @param additionalValues the additional user values.
427     * @return a Map of the Errors by field.
428     * @throws UserManagementException if an error occurs.
429     */
430    public Map<String, Errors> validate(String siteName, String email, Map<String, String> additionalValues) throws UserManagementException
431    {
432        Map<String, String> userInfos = new HashMap<>();
433        
434        userInfos.putAll(additionalValues);
435        
436        // Standard info for user (provide a dummy password, as we do not know it yet).
437        userInfos.put("login", email);
438        userInfos.put("email", email);
439        userInfos.put("password", "password");
440
441        Map<String, Errors> usersManagerErrors = new HashMap<>(); //foUsersManager.validate(userInfos);
442        Map<String, Errors> errors = new HashMap<>(usersManagerErrors);
443
444        // If there are errors on the login, do not return it except if
445        if (errors.containsKey("login"))
446        {
447            if (!errors.containsKey("email"))
448            {
449                errors.put("email", errors.get("login"));
450            }
451            errors.remove("login");
452        }
453
454        return errors;
455    }
456
457    /**
458     * Validate the user password.
459     * @param siteName the site name.
460     * @param password the password to validate.
461     * @param login the login of the user
462     * @param population The id of the population
463     * @return a Map of the Errors by field.
464     * @throws UserManagementException if an error occurs.
465     */
466    public Map<String, Errors> validatePassword(String siteName, String password, String login, String population) throws UserManagementException
467    {
468        Map<String, String> userInfos = new HashMap<>();
469
470        userInfos.put("password", password);
471
472        UserDirectory userDirectory = _userManager.getUserDirectory(population, login);
473        if (!(userDirectory instanceof ModifiableUserDirectory))
474        {
475            throw new UserManagementException("The user subscription feature can't be used, as the UserDirectory is not modifiable.");
476        }
477        Map<String, Errors> usersManagerErrors = ((ModifiableUserDirectory) userDirectory).validate(userInfos);
478        Map<String, Errors> errors = new HashMap<>();
479
480        // Keep only errors related to the password field.
481        if (usersManagerErrors.containsKey("password"))
482        {
483            errors.put("password", usersManagerErrors.get("password"));
484        }
485
486        return errors;
487    }
488
489    /**
490     * Validate and store a sign-up request and send a confirmation e-mail.
491     * @param siteName the site name.
492     * @param language the sitemap name.
493     * @param email the user e-mail address.
494     * @param population the population
495     * @param userDirectoryId the id of the user directory of the population
496     * @return a status code indicating success or error.
497     * @throws UserManagementException if an error occurs.
498     */
499    public int temporarySignup(String siteName, String language, String email, String population, String userDirectoryId) throws UserManagementException
500    {
501        return temporarySignup(siteName, language, email, population, userDirectoryId, true);
502    }
503    
504    /**
505     * Validate and store a sign-up request and send a confirmation e-mail.
506     * @param siteName the site name.
507     * @param language the sitemap name.
508     * @param email the user e-mail address.
509     * @param population the population
510     * @param userDirectoryId the id of the user directory of the population
511     * @param sendMail Set to false to not send mail at end of process
512     * @return a status code indicating success or error.
513     * @throws UserManagementException if an error occurs.
514     */
515    public int temporarySignup(String siteName, String language, String email, String population, String userDirectoryId, boolean sendMail) throws UserManagementException
516    {
517        // Verify that public sign-up is allowed and throw an exception otherwise.
518        checkPublicSignup(siteName);
519
520        if (getLogger().isDebugEnabled())
521        {
522            getLogger().debug("A user is requesting a sign-up: " + email);
523        }
524
525        // Generate unique token.
526        String token = UUID.randomUUID().toString().replace("-", "");
527
528        int status = addTemporaryUser(siteName, email, token, population, userDirectoryId);
529
530        // Send validation e-mail with token.
531        if (status == SIGNUP_NO_ERROR && sendMail)
532        {
533            sendSignupConfirmMail(siteName, language, email, token);
534        }
535
536        return status;
537    }
538    
539    /**
540     * Get a token for temp user
541     * @param siteName the site name.
542     * @param email the user e-mail address.
543     * @param population The id of the population
544     * @param userDirectoryId The id of the user directory of the population
545     * @return the user token or null if not found
546     * @throws UserManagementException if an error occurs.
547     */
548    public String getToken(String siteName, String email, String population, String userDirectoryId) throws UserManagementException
549    {
550        TempUser tempUser = getTempUser(siteName, email, population, userDirectoryId);
551        if (tempUser != null)
552        {
553            return tempUser.getToken();
554        }
555        
556        return null;
557    }
558
559    /**
560     * Reset a sign-up request: generate a new token and re-send the confirmation e-mail.
561     * @param siteName the site name.
562     * @param language the sitemap name.
563     * @param email the user e-mail address.
564     * @param population The id of the population
565     * @param userDirectoryId The id of the user directory of the population
566     * @return a status code indicating success or error.
567     * @throws UserManagementException if an error occurs.
568     */
569    public int resetTempSignup(String siteName, String language, String email, String population, String userDirectoryId) throws UserManagementException
570    {
571        // Verify that public sign-up is allowed and throw an exception otherwise.
572        checkPublicSignup(siteName);
573
574        if (getLogger().isDebugEnabled())
575        {
576            getLogger().debug("Resetting temporary signup for email: " + email + " in site " + siteName);
577        }
578
579        // Generate a new token.
580        String newToken = UUID.randomUUID().toString().replace("-", "");
581
582        // Test if the subscription request really exists.
583        TempUser tempUser = getTempUser(siteName, email, population, userDirectoryId);
584
585        if (tempUser == null)
586        {
587            // No subscription request with this e-mail.
588            return SIGNUP_RESET_ERROR_EMAIL_UNKNOWN;
589        }
590
591        updateTempToken(siteName, email, newToken, population, userDirectoryId);
592
593        sendSignupConfirmMail(siteName, language, email, newToken);
594
595        return SIGNUP_NO_ERROR;
596    }
597
598
599    /**
600     * Create the user in the FO UsersManager from his temporary request.
601     * @param siteName the site name.
602     * @param language the current language
603     * @param firstname the user firstname
604     * @param lastname the user lastname
605     * @param email the user e-mail address.
606     * @param token the request token.
607     * @param password the user password.
608     * @param population The id of the population
609     * @param userDirectoryId The id of the user directory of the population
610     * @param errors the errors
611     * @return a status code indicating success or error.
612     * @throws UserManagementException if an error occurs.
613     */
614    public int signup(String siteName, String language, String firstname, String lastname, String email, String token, String password, String population, String userDirectoryId, Multimap<String, I18nizableText> errors) throws UserManagementException
615    {
616        // Verify that public sign-up is allowed and throw an exception otherwise.
617        checkPublicSignup(siteName);
618
619        Map<String, String> userInfos = new HashMap<>();
620
621        TempUser tempUser = getTempUser(siteName, email, token, population, userDirectoryId);
622
623        if (tempUser == null)
624        {
625            return SIGNUP_TOKEN_UNKNOWN;
626        }
627        
628        // Generate login
629        String login = RandomStringUtils.randomNumeric(10);
630
631        // Standard info for user.
632        userInfos.put("login", login);
633        userInfos.put("email", email);
634        userInfos.put("firstname", firstname);
635        userInfos.put("lastname", lastname);
636        userInfos.put("password", password);
637
638        try
639        {
640            validationBeforeSignup(errors);
641            
642            if (errors.isEmpty())
643            {
644                // Add the user.
645                ModifiableUserDirectory userDirectory = (ModifiableUserDirectory) _userPopulationDAO.getUserPopulation(population).getUserDirectory(userDirectoryId);
646                userDirectory.add(userInfos);
647
648                // Remove the temporary user.
649                removeTempUser(siteName, email, token, population, userDirectoryId);
650                
651                User createdUser = userDirectory.getUser(login);
652                
653                // Do additional operations after signup
654                additionalSignupOperations(createdUser, errors);
655                
656                if (errors.isEmpty())
657                {
658                    sendSignupValidatedMail(siteName, language, createdUser);
659                    return SIGNUP_NO_ERROR;
660                }
661            }
662            
663            return SIGNUP_ERROR;
664        }
665        catch (InvalidModificationException e)
666        {
667            throw new UserManagementException("An error occurred signing up the user.", e);
668        }
669    }
670    
671    /**
672     * Do some validation before signup
673     * @param errors the map of errors to fill in cause of errors during validation
674     */
675    public void validationBeforeSignup(Multimap<String, I18nizableText> errors)
676    {
677        // Nothing
678    }
679    
680    /**
681     * Process additional operations after creation of user
682     * @param createdUser the created user
683     * @param errors the map of errors to fill in case of errors during additional operations
684     * @throws UserManagementException if an error occurs.
685     */
686    public void additionalSignupOperations(User createdUser, Multimap<String, I18nizableText> errors) throws UserManagementException
687    {
688        // Nothing
689    }
690    
691
692    /**
693     * Create a reset password request and send a confirmation e-mail.
694     * @param siteName the site name.
695     * @param language the sitemap name.
696     * @param loginOrEmail the user login or email.
697     * @param populationId the population
698     * @return a status code indicating success or error.
699     * @throws UserManagementException if an error occurs.
700     */
701    public LostPasswordError resetPassword(String siteName, String language, String loginOrEmail, String populationId) throws UserManagementException
702    {
703        // Check if the population exists
704        UserPopulation population = _userPopulationDAO.getUserPopulation(populationId);
705        if (population == null)
706        {
707            return LostPasswordError.POPULATION_UNKNOWN;
708        }
709        
710        // Check if the user exists and get it
711        User user = _userManager.getUser(populationId, loginOrEmail);
712        if (user == null)
713        {
714            try
715            {
716                user = _userManager.getUserByEmail(populationId, loginOrEmail);
717                if (user == null)
718                {
719                    // No user with this e-mail or login.
720                    return LostPasswordError.USER_UNKNOWN;
721                }
722            }
723            catch (NotUniqueUserException e)
724            {
725                return LostPasswordError.SEVERAL_USERS;
726            }
727        }
728        
729        // Check if the user directory is modifiable
730        if (!(user.getUserDirectory() instanceof ModifiableUserDirectory))
731        {
732            return LostPasswordError.UNMODIFIABLE_USER_DIRECTORY;
733        }
734        
735        if (StringUtils.isEmpty(user.getEmail()))
736        {
737            return LostPasswordError.EMPTY_EMAIL;
738        }
739
740        // Generate a new token.
741        String token = UUID.randomUUID().toString().replace("-", "");
742
743        // Insert the token in the database.
744        addPasswordToken(siteName, user.getIdentity().getLogin(), token, populationId);
745
746        // Send the e-mail.
747        sendResetPasswordMail(siteName, language, user, token);
748
749        return null;
750    }
751
752    /**
753     * Change the user password.
754     * @param siteName the site name.
755     * @param login the user login.
756     * @param token the password change request token.
757     * @param newPassword the new password.
758     * @param population the population
759     * @return a status code indicating success or error.
760     * @throws UserManagementException if an error occurs.
761     */
762    public int changeUserPassword(String siteName, String login, String token, String newPassword, String population) throws UserManagementException
763    {
764        int tokenStatus = checkPasswordToken(siteName, login, token, population);
765
766        if (tokenStatus != SIGNUP_NO_ERROR)
767        {
768            return tokenStatus;
769        }
770
771        Map<String, String> userInfos = new HashMap<>();
772
773        userInfos.put("login", login);
774        userInfos.put("password", newPassword);
775
776        try
777        {
778            UserDirectory userDirectory = _userManager.getUserDirectory(population, login);
779            if (!(userDirectory instanceof ModifiableUserDirectory))
780            {
781                throw new UserManagementException("The user's password can't be changed, as the UserDirectory is not modifiable.");
782            }
783            ((ModifiableUserDirectory) userDirectory).update(userInfos);
784
785            removePasswordToken(siteName, login, token, population);
786
787            return SIGNUP_NO_ERROR;
788        }
789        catch (InvalidModificationException e)
790        {
791            throw new UserManagementException("An error occurred signing up the user.", e);
792        }
793    }
794    
795    /**
796     * Check the sign-up request token.
797     * @param siteName the site name.
798     * @param email the user e-mail.
799     * @param token the sign-up request token.
800     * @param population The id of the population
801     * @param userDirectoryId The id of the user directory of the population
802     * @return a status code indicating success or error.
803     * @throws UserManagementException if an error occurs.
804     */
805    public int checkToken(String siteName, String email, String token, String population, String userDirectoryId) throws UserManagementException
806    {
807        removeExpiredTokens();
808
809        try (SqlSession sqlSession = getSession())
810        {
811            String stmtId = "UserSignupManager.getSubscriptionDate";
812            
813            Map<String, Object> params = new HashMap<>();
814            params.put("tempUsersTable", _tempUsersTable);
815            
816            params.put("site", siteName);
817            params.put("email", email);
818            params.put("token", token);
819            params.put("population", population);
820            params.put("userDirectory", userDirectoryId);
821            
822            Date rawSubscriptionDate = sqlSession.selectOne(stmtId, params);
823
824            // Date verification.
825            if (rawSubscriptionDate == null)
826            {
827                return SIGNUP_TOKEN_UNKNOWN;
828            }
829            
830            // The validity limit
831            ZonedDateTime limit = LocalDate.now().atStartOfDay(ZoneId.systemDefault()).minusDays(_userSignUpConfiguration.getTokenValidity());
832            ZonedDateTime subscriptionDate = rawSubscriptionDate.toInstant().atZone(ZoneId.systemDefault());
833
834            if (subscriptionDate.isBefore(limit))
835            {
836                return SIGNUP_TOKEN_EXPIRED;
837            }
838
839            return SIGNUP_NO_ERROR;
840        }
841        catch (Exception e)
842        {
843            throw new UserManagementException("Database error while testing the token for user [" + email + "]", e);
844        }
845    }
846
847    /**
848     * Check the password change request token.
849     * @param siteName the site name.
850     * @param login the user login.
851     * @param token the password change request token.
852     * @param population the population
853     * @return a status code indicating success or error.
854     * @throws UserManagementException if an error occurs.
855     */
856    public int checkPasswordToken(String siteName, String login, String token, String population) throws UserManagementException
857    {
858        removeExpiredPasswordTokens();
859
860        try (SqlSession sqlSession = getSession())
861        {
862            String stmtId = "UserSignupManager.getRequestDate";
863            
864            Map<String, Object> params = new HashMap<>();
865            params.put("pwdChangeTable", _pwdChangeTable);
866            
867            params.put("site", siteName);
868            params.put("login", login);
869            params.put("token", token);
870            params.put("population", population);
871            
872            Date rawRequestDate = sqlSession.selectOne(stmtId, params);
873
874            // Date verification.
875            if (rawRequestDate == null)
876            {
877                return SIGNUP_TOKEN_UNKNOWN;
878            }
879
880            // Check the validity.
881            ZonedDateTime limit = LocalDate.now().atStartOfDay(ZoneId.systemDefault()).minusDays(_userSignUpConfiguration.getTokenValidity());
882            ZonedDateTime requestDate = rawRequestDate.toInstant().atZone(ZoneId.systemDefault());
883
884            if (requestDate.isBefore(limit))
885            {
886                return SIGNUP_TOKEN_EXPIRED;
887            }
888
889            return SIGNUP_NO_ERROR;
890        }
891        catch (Exception e)
892        {
893            throw new UserManagementException("Database error while testing the password token for user " + login, e);
894        }
895    }
896
897    /**
898     * Remove the expired sign-up request tokens.
899     * @throws UserManagementException if an error occurs.
900     */
901    public void removeExpiredTokens() throws UserManagementException
902    {
903        try (SqlSession sqlSession = getSession())
904        {
905            String stmtId = "UserSignupManager.deleteExpiredTokens";
906            
907            Map<String, Object> params = new HashMap<>();
908            params.put("tempUsersTable", _tempUsersTable);
909            
910            ZonedDateTime limit = LocalDate.now().atStartOfDay(ZoneId.systemDefault()).minusDays(_userSignUpConfiguration.getTokenValidity());
911            Timestamp limitTimestamp = Timestamp.from(limit.toInstant());
912            params.put("threshold", limitTimestamp);
913            
914            sqlSession.delete(stmtId, params);
915            sqlSession.commit();
916        }
917        catch (Exception e)
918        {
919            throw new UserManagementException("Database error while removing the expired tokens.", e);
920        }
921    }
922
923    /**
924     * Remove the expired change password request tokens.
925     * @throws UserManagementException if an error occurs.
926     */
927    public void removeExpiredPasswordTokens() throws UserManagementException
928    {
929        try (SqlSession sqlSession = getSession())
930        {
931            String stmtId = "UserSignupManager.deleteExpiredPasswordTokens";
932            
933            Map<String, Object> params = new HashMap<>();
934            params.put("pwdChangeTable", _pwdChangeTable);
935            
936            ZonedDateTime limit = LocalDate.now().atStartOfDay(ZoneId.systemDefault()).minusDays(_userSignUpConfiguration.getTokenValidity());
937            Timestamp limitTimestamp = Timestamp.from(limit.toInstant());
938            params.put("threshold", limitTimestamp);
939            
940            sqlSession.delete(stmtId, params);
941            sqlSession.commit();
942        }
943        catch (Exception e)
944        {
945            throw new UserManagementException("Database error while removing the expired tokens.", e);
946        }
947    }
948
949    /**
950     * Verify that public sign-up is allowed. If not, throw an exception.
951     * @param siteName the site name.
952     * @throws UserManagementException if public sign-up is not enabled.
953     */
954    protected void checkPublicSignup(String siteName) throws UserManagementException
955    {
956        if (!isPublicSignupAllowed(siteName))
957        {
958            throw new UserManagementException("Public signup is disabled for this site.");
959        }
960    }
961
962    /**
963     * Create a user sign-up request ("temporary" user) in the database.
964     * @param siteName the site name.
965     * @param email the user e-mail.
966     * @param token the generated token.
967     * @param population the population
968     * @param userDirectoryId the id of the user directory of the population
969     * @return a status code indicating success or error.
970     * @throws UserManagementException if an error occurs.
971     */
972    protected int addTemporaryUser(String siteName, String email, String token, String population, String userDirectoryId) throws UserManagementException
973    {
974        try (SqlSession sqlSession = getSession())
975        {
976            // Does this email already exists
977            String stmtId = "UserSignupManager.tempEmailExists";
978            
979            Map<String, Object> params = new HashMap<>();
980            params.put("tempUsersTable", _tempUsersTable);
981            
982            params.put("site", siteName);
983            params.put("email", email);
984            params.put("population", population);
985            params.put("userDirectory", userDirectoryId);
986            
987            List<String> emails = sqlSession.selectList(stmtId, params);
988            
989            if (!emails.isEmpty())
990            {
991                return SIGNUP_ERROR_TEMP_EMAIL_ALREADY_EXISTS;
992            }
993            
994            // Add temp user
995            stmtId = "UserSignupManager.addTempUser";
996            params = new HashMap<>();
997            params.put("tempUsersTable", _tempUsersTable);
998            
999            Timestamp now = new Timestamp(System.currentTimeMillis());
1000            
1001            params.put("site", siteName);
1002            params.put("email", email);
1003            params.put("population", population);
1004            params.put("userDirectory", userDirectoryId);
1005            params.put("subscription_date", now);
1006            params.put("token", token);
1007            
1008            sqlSession.insert(stmtId, params);
1009            sqlSession.commit();
1010            
1011            return SIGNUP_NO_ERROR;
1012        }
1013        catch (Exception e)
1014        {
1015            throw new UserManagementException("Database error while signing up a new user [" + email + "]", e);
1016        }
1017    }
1018
1019    /**
1020     * Send a sign-up confirmation link by e-mail.
1021     * @param siteName the site name.
1022     * @param language the e-mail language.
1023     * @param email the user e-mail.
1024     * @param token the generated token.
1025     * @throws UserManagementException if an error occurs.
1026     */
1027    protected void sendSignupConfirmMail(String siteName, String language, String email, String token) throws UserManagementException
1028    {
1029        if (getLogger().isDebugEnabled())
1030        {
1031            getLogger().debug("Sending signup confirmation e-mail to " + email);
1032        }
1033
1034        Site site = _siteManager.getSite(siteName);
1035        String from = site.getValue("site-mail-from");
1036
1037        // Prepare mail.
1038        Map<String, I18nizableText> i18nParams = new HashMap<>();
1039        i18nParams.put("siteName", new I18nizableText(siteName));
1040        i18nParams.put("email", new I18nizableText(email));
1041        i18nParams.put("token", new I18nizableText(token));
1042
1043        Page signupPage = getSignupPage(siteName, language);
1044        if (signupPage != null)
1045        {
1046            if (_pageUriResolver == null)
1047            {
1048                _pageUriResolver = _uriResolverEP.getResolverForType("page");
1049            }
1050
1051            String encodedEmail;
1052            try
1053            {
1054                encodedEmail = URLEncoder.encode(email, "UTF-8");
1055            }
1056            catch (UnsupportedEncodingException e)
1057            {
1058                // Should never happen.
1059                throw new UserManagementException("Encoding error while sending a sign-up confirmation e-mail.", e);
1060            }
1061
1062            // Compute the confirmation URI and add it to the parameters.
1063            String confirmUri = _pageUriResolver.resolve(signupPage.getId(), false, true, false);
1064            confirmUri = confirmUri + "?email=" + encodedEmail + "&token=" + token;
1065
1066            i18nParams.put("confirmUri", new I18nizableText(confirmUri));
1067        }
1068
1069        // Add site information in the parameters.
1070        i18nParams.put("siteTitle", new I18nizableText(site.getTitle()));
1071        i18nParams.put("siteUrl", new I18nizableText(site.getUrl()));
1072
1073        String subject = _userSignUpConfiguration.getSubjectForSignUpEmail(i18nParams, language);
1074        String textBody = _userSignUpConfiguration.getTextBodyForSignUpEmail(i18nParams, language);
1075        String htmlBody = _userSignUpConfiguration.getHtmlBodyForSignUpEmail(i18nParams, language);
1076
1077        try
1078        {
1079            // Send the e-mail.
1080            SendMailHelper.sendMail(subject, htmlBody, textBody, email, from);
1081        }
1082        catch (MessagingException e)
1083        {
1084            throw new UserManagementException("Error sending the sign-up confirmation mail.", e);
1085        }
1086    }
1087    
1088    /**
1089     * Send a sign-up confirmation link by e-mail.
1090     * @param siteName the site name.
1091     * @param language the e-mail language.
1092     * @param user the created user
1093     * @throws UserManagementException if an error occurs.
1094     */
1095    protected void sendSignupValidatedMail(String siteName, String language, User user) throws UserManagementException
1096    {
1097        Site site = _siteManager.getSite(siteName);
1098        String from = site.getValue("site-mail-from");
1099        String email = user.getEmail();
1100
1101        if (getLogger().isDebugEnabled())
1102        {
1103            getLogger().debug("Sending signup validation e-mail to " + email);
1104        }
1105        
1106        // Prepare mail.
1107        Map<String, I18nizableText> i18nParams = new HashMap<>();
1108        i18nParams.put("siteName", new I18nizableText(siteName));
1109        i18nParams.put("fullName", new I18nizableText(user.getFullName()));
1110        i18nParams.put("email", new I18nizableText(user.getEmail()));
1111        i18nParams.put("login", new I18nizableText(user.getIdentity().getLogin()));
1112
1113        // Add site information in the parameters.
1114        i18nParams.put("siteTitle", new I18nizableText(site.getTitle()));
1115        i18nParams.put("siteUrl", new I18nizableText(site.getUrl()));
1116
1117        String subject = _userSignUpConfiguration.getSubjectForSignUpValidatedEmail(i18nParams, language);
1118        String textBody = _userSignUpConfiguration.getTextBodyForSignUpValidatedEmail(i18nParams, language);
1119        String htmlBody = _userSignUpConfiguration.getHtmlBodyForSignUpValidatedEmail(i18nParams, language);
1120
1121        try
1122        {
1123            // Send the e-mail.
1124            SendMailHelper.sendMail(subject, htmlBody, textBody, email, from);
1125        }
1126        catch (MessagingException e)
1127        {
1128            throw new UserManagementException("Error sending the sign-up validation mail.", e);
1129        }
1130    }
1131
1132    /**
1133     * Update the sign-up request token: reset the date and set a new token.
1134     * @param siteName the site name.
1135     * @param email the user e-mail.
1136     * @param newToken the new token.
1137     * @param population The id of the population
1138     * @param userDirectoryId The id of the user directory of the population
1139     * @throws UserManagementException if an error occurs.
1140     */
1141    protected void updateTempToken(String siteName, String email, String newToken, String population, String userDirectoryId) throws UserManagementException
1142    {
1143        try (SqlSession sqlSession = getSession())
1144        {
1145            String stmtId = "UserSignupManager.updateTempToken";
1146            
1147            Map<String, Object> params = new HashMap<>();
1148            params.put("tempUsersTable", _tempUsersTable);
1149            
1150            Timestamp now = new Timestamp(System.currentTimeMillis());
1151            params.put("subscription_date", now);
1152            params.put("token", newToken);
1153            params.put("site", siteName);
1154            params.put("email", email);
1155            params.put("population", population);
1156            params.put("userDirectory", userDirectoryId);
1157            
1158            sqlSession.update(stmtId, params);
1159            sqlSession.commit();
1160        }
1161        catch (Exception e)
1162        {
1163            throw new UserManagementException("Database error while resetting the subscription for user [" + email + "]", e);
1164        }
1165    }
1166
1167    /**
1168     * Create a user password change request in the database.
1169     * @param siteName the site name.
1170     * @param login the user login.
1171     * @param token the generated token.
1172     * @param population the population
1173     * @throws UserManagementException if an error occurs.
1174     */
1175    protected void addPasswordToken(String siteName, String login, String token, String population) throws UserManagementException
1176    {
1177        try (SqlSession sqlSession = getSession())
1178        {
1179            String stmtId = "UserSignupManager.hasToken";
1180            
1181            Map<String, Object> params = new HashMap<>();
1182            params.put("pwdChangeTable", _pwdChangeTable);
1183            
1184            params.put("site", siteName);
1185            params.put("login", login);
1186            params.put("population", population);
1187            
1188            List<Object> pwdEntries = sqlSession.selectList(stmtId, params);
1189            
1190            if (pwdEntries.isEmpty())
1191            {
1192                // Insert a new token.
1193                stmtId = "UserSignupManager.addPasswordToken";
1194                params = new HashMap<>();
1195                params.put("pwdChangeTable", _pwdChangeTable);
1196                
1197                Timestamp now = new Timestamp(System.currentTimeMillis());
1198                params.put("site", siteName);
1199                params.put("login", login);
1200                params.put("request_date", now);
1201                params.put("token", token);
1202                params.put("population", population);
1203                
1204                sqlSession.insert(stmtId, params);
1205            }
1206            else
1207            {
1208                // Update the existing token.
1209                stmtId = "UserSignupManager.updatePasswordToken";
1210                params = new HashMap<>();
1211                params.put("pwdChangeTable", _pwdChangeTable);
1212                
1213                Timestamp now = new Timestamp(System.currentTimeMillis());
1214                params.put("request_date", now);
1215                params.put("token", token);
1216                params.put("site", siteName);
1217                params.put("login", login);
1218                params.put("population", population);
1219                
1220                sqlSession.update(stmtId, params);
1221            }
1222            
1223            // commit insert or update
1224            sqlSession.commit();
1225        }
1226        catch (Exception e)
1227        {
1228            throw new UserManagementException("Database error while inserting a password change token for " + login, e);
1229        }
1230    }
1231
1232    /**
1233     * Get a temporary user from his site name and e-mail.
1234     * @param siteName the site name.
1235     * @param email The temporary user e-mail. Cannot be null.
1236     * @param population the population
1237     * @param userDirectoryId the id of the user directory of the population
1238     * @return the temporary user or null if not found.
1239     * @throws UserManagementException if an error occurs.
1240     */
1241    protected TempUser getTempUser(String siteName, String email, String population, String userDirectoryId) throws UserManagementException
1242    {
1243        return getTempUser(siteName, email, null, population, userDirectoryId);
1244    }
1245
1246    /**
1247     * Get a temporary user from his site name, e-mail and/or token.
1248     * At least one of e-mail and token must be provided.
1249     * @param siteName the site name.
1250     * @param email The temporary user e-mail. Can be null.
1251     * @param token The temporary user token. Can be null.
1252     * @param population the population. Must be not null if email is not null
1253     * @param userDirectoryId the id of the user directory of the population. Must be not null if email is not null
1254     * @return the temporary user or null if not found.
1255     * @throws UserManagementException if an error occurs.
1256     */
1257    protected TempUser getTempUser(String siteName, String email, String token, String population, String userDirectoryId) throws UserManagementException
1258    {
1259        if (StringUtils.isEmpty(email) && StringUtils.isEmpty(token))
1260        {
1261            throw new UserManagementException("Either e-mail or token must be provided.");
1262        }
1263        
1264        try (SqlSession sqlSession = getSession())
1265        {
1266            // Does this email already exists
1267            String stmtId = "UserSignupManager.getTempUser";
1268            
1269            Map<String, Object> params = new HashMap<>();
1270            params.put("tempUsersTable", _tempUsersTable);
1271            
1272            params.put("site", siteName);
1273            if (StringUtils.isNotEmpty(email))
1274            {
1275                params.put("email", email);
1276                params.put("population", population);
1277                params.put("userDirectory", userDirectoryId);
1278            }
1279            if (StringUtils.isNotEmpty(token))
1280            {
1281                params.put("token", token);
1282            }
1283            
1284            return sqlSession.selectOne(stmtId, params);
1285        }
1286        catch (Exception e)
1287        {
1288            throw new UserManagementException("Database error while getting the request for user [" + email + "] and token [" + token + "]", e);
1289        }
1290    }
1291
1292    /**
1293     * Remove the temporary .
1294     * @param siteName the site name.
1295     * @param email the user e-mail address.
1296     * @param token the request token.
1297     * @param population the population
1298     * @param userDirectoryId the id of the user directory of the population
1299     * @throws UserManagementException if an error occurs.
1300     */
1301    protected void removeTempUser(String siteName, String email, String token, String population, String userDirectoryId) throws UserManagementException
1302    {
1303        try (SqlSession sqlSession = getSession())
1304        {
1305            String stmtId = "UserSignupManager.removeTempUser";
1306            
1307            Map<String, Object> params = new HashMap<>();
1308            params.put("tempUsersTable", _tempUsersTable);
1309            
1310            params.put("site", siteName);
1311            params.put("email", email);
1312            params.put("token", token);
1313            params.put("population", population);
1314            params.put("userDirectory", userDirectoryId);
1315            
1316            sqlSession.delete(stmtId, params);
1317            sqlSession.commit();
1318        }
1319        catch (Exception e)
1320        {
1321            throw new UserManagementException("Database error while removing the token of user " + email, e);
1322        }
1323    }
1324
1325    /**
1326     * Remove the password change request.
1327     * @param siteName the site name.
1328     * @param login the user login.
1329     * @param token the request token.
1330     * @param population the population
1331     * @throws UserManagementException if an error occurs.
1332     */
1333    protected void removePasswordToken(String siteName, String login, String token, String population) throws UserManagementException
1334    {
1335        try (SqlSession sqlSession = getSession())
1336        {
1337            String stmtId = "UserSignupManager.removePasswordToken";
1338            
1339            Map<String, Object> params = new HashMap<>();
1340            params.put("pwdChangeTable", _pwdChangeTable);
1341            
1342            params.put("site", siteName);
1343            params.put("login", login);
1344            params.put("token", token);
1345            params.put("population", population);
1346            
1347            sqlSession.delete(stmtId, params);
1348            sqlSession.commit();
1349        }
1350        catch (Exception e)
1351        {
1352            throw new UserManagementException("Database error while removing the token of user " + login, e);
1353        }
1354    }
1355
1356    /**
1357     * Send a sign-up confirmation link by e-mail.
1358     * @param siteName the site name.
1359     * @param language the e-mail language.
1360     * @param user the user object.
1361     * @param token the generated token.
1362     * @throws UserManagementException if an error occurs.
1363     */
1364    protected void sendResetPasswordMail(String siteName, String language, User user, String token) throws UserManagementException
1365    {
1366        String login = user.getIdentity().getLogin();
1367        String population = user.getIdentity().getPopulationId();
1368
1369        if (getLogger().isDebugEnabled())
1370        {
1371            getLogger().debug("Sending reset password e-mail to " + login);
1372        }
1373
1374        Site site = _siteManager.getSite(siteName);
1375        String from = site.getValue("site-mail-from");
1376
1377        // Prepare mail
1378        Map<String, I18nizableText> i18nParams = new HashMap<>();
1379        i18nParams.put("siteName", new I18nizableText(siteName));
1380        i18nParams.put("login", new I18nizableText(login));
1381        i18nParams.put("email", new I18nizableText(user.getEmail()));
1382        i18nParams.put("fullName", new I18nizableText(user.getFullName()));
1383        i18nParams.put("token", new I18nizableText(token));
1384
1385        Page passwordPage = getPwdChangePage(siteName, language);
1386        if (passwordPage != null)
1387        {
1388            if (_pageUriResolver == null)
1389            {
1390                _pageUriResolver = _uriResolverEP.getResolverForType("page");
1391            }
1392
1393            String encodedLogin;
1394            String encodedPopulation;
1395            try
1396            {
1397                encodedLogin = URLEncoder.encode(login, "UTF-8");
1398                encodedPopulation = URLEncoder.encode(population, "UTF-8");
1399            }
1400            catch (UnsupportedEncodingException e)
1401            {
1402                // Should never happen.
1403                throw new UserManagementException("Encoding error while sending a password reset confirmation e-mail.", e);
1404            }
1405
1406            // Compute the confirmation URI and add it to the parameters.
1407            String confirmUri = _pageUriResolver.resolve(passwordPage.getId(), false, true, false);
1408            confirmUri = confirmUri + "?login=" + encodedLogin + "&population=" + encodedPopulation + "&token=" + token;
1409
1410            i18nParams.put("confirmUri", new I18nizableText(confirmUri));
1411        }
1412
1413        // Add site information in the parameters.
1414        i18nParams.put("siteTitle", new I18nizableText(site.getTitle()));
1415        i18nParams.put("siteUrl", new I18nizableText(site.getUrl()));
1416
1417        String subject = _userSignUpConfiguration.getSubjectForResetPwdEmail(i18nParams, language);
1418        String textBody = _userSignUpConfiguration.getTextBodyForResetPwdEmail(i18nParams, language);
1419        String htmlBody = _userSignUpConfiguration.getHtmlBodyForResetPwdEmail(i18nParams, language);
1420
1421        try
1422        {
1423            // Send the e-mail.
1424            SendMailHelper.sendMail(subject, htmlBody, textBody, user.getEmail(), from);
1425        }
1426        catch (MessagingException e)
1427        {
1428            throw new UserManagementException("Error sending a password reset e-mail.", e);
1429        }
1430    }
1431
1432    /**
1433     * Bean representing a user sign-up request.
1434     */
1435    public static class TempUser
1436    {
1437        /** The site name. */
1438        protected String _site;
1439        
1440        /** The user e-mail. */
1441        protected String _email;
1442
1443        /** The user subscription date. */
1444        protected Date _subscriptionDate;
1445
1446        /** The request token. */
1447        protected String _token;
1448
1449        /** The id of the population */
1450        protected String _population;
1451
1452        /** The id of the user directory of the population */
1453        protected String _userDirectoryId;
1454
1455        /**
1456         * Constructor.
1457         * @param site the site
1458         * @param email the user's email
1459         * @param subscriptionDate the date of subscription
1460         * @param token the user's token
1461         * @param population The id of the population
1462         * @param userDirectoryId The id of the user directory of the population
1463         */
1464        public TempUser(String site, String email, Date subscriptionDate, String token, String population, String userDirectoryId)
1465        {
1466            this._site = site;
1467            this._email = email;
1468            this._subscriptionDate = subscriptionDate;
1469            this._token = token;
1470            this._population = population;
1471            this._userDirectoryId = userDirectoryId;
1472        }
1473        /**
1474         * Get the site.
1475         * @return the site
1476         */
1477        public String getSite()
1478        {
1479            return _site;
1480        }
1481        /**
1482         * Set the site.
1483         * @param site the site to set
1484         */
1485        public void setSite(String site)
1486        {
1487            this._site = site;
1488        }
1489        /**
1490         * Get the email.
1491         * @return _the email
1492         */
1493        public String getEmail()
1494        {
1495            return _email;
1496        }
1497        /**
1498         * Set the email.
1499         * @param email the email to set
1500         */
1501        public void setEmail(String email)
1502        {
1503            this._email = email;
1504        }
1505        /**
1506         * Get the subscriptionDate.
1507         * @return _the subscriptionDate
1508         */
1509        public Date getSubscriptionDate()
1510        {
1511            return _subscriptionDate;
1512        }
1513        /**
1514         * Set the subscriptionDate.
1515         * @param subscriptionDate the subscriptionDate to set
1516         */
1517        public void setSubscriptionDate(Date subscriptionDate)
1518        {
1519            this._subscriptionDate = subscriptionDate;
1520        }
1521        /**
1522         * Get the token.
1523         * @return _the token
1524         */
1525        public String getToken()
1526        {
1527            return _token;
1528        }
1529        /**
1530         * Set the token.
1531         * @param token the token to set
1532         */
1533        public void setToken(String token)
1534        {
1535            this._token = token;
1536        }
1537        /**
1538         * Get the population.
1539         * @return the population
1540         */
1541        public String getPopulation()
1542        {
1543            return _population;
1544        }
1545        /**
1546         * Set the population.
1547         * @param population the population to set
1548         */
1549        public void setPopulation(String population)
1550        {
1551            this._population = population;
1552        }
1553        /**
1554         * Get the user directory id.
1555         * @return the user directory id
1556         */
1557        public String getUserDirectoryId()
1558        {
1559            return _userDirectoryId;
1560        }
1561        /**
1562         * Set the user directory index.
1563         * @param userDirectoryId the user directory id to set
1564         */
1565        public void setUserDirectoryIndex(String userDirectoryId)
1566        {
1567            this._userDirectoryId = userDirectoryId;
1568        }
1569
1570    }
1571
1572}