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