AdminUserService.java

  1. /*
  2.  * Copyright (c) 2002-2022, City of Paris
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  *  1. Redistributions of source code must retain the above copyright notice
  10.  *     and the following disclaimer.
  11.  *
  12.  *  2. Redistributions in binary form must reproduce the above copyright notice
  13.  *     and the following disclaimer in the documentation and/or other materials
  14.  *     provided with the distribution.
  15.  *
  16.  *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
  17.  *     contributors may be used to endorse or promote products derived from
  18.  *     this software without specific prior written permission.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  24.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  25.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  26.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30.  * POSSIBILITY OF SUCH DAMAGE.
  31.  *
  32.  * License 1.0
  33.  */
  34. package fr.paris.lutece.portal.service.admin;

  35. import java.sql.Timestamp;
  36. import java.text.DateFormat;
  37. import java.text.SimpleDateFormat;
  38. import java.util.ArrayList;
  39. import java.util.Arrays;
  40. import java.util.Calendar;
  41. import java.util.Collection;
  42. import java.util.Date;
  43. import java.util.GregorianCalendar;
  44. import java.util.HashMap;
  45. import java.util.List;
  46. import java.util.Locale;
  47. import java.util.Map;
  48. import java.util.Map.Entry;
  49. import java.util.Optional;
  50. import java.util.Set;
  51. import java.util.stream.Collectors;

  52. import javax.servlet.http.HttpServletRequest;

  53. import org.apache.commons.lang3.StringUtils;
  54. import org.apache.commons.lang3.ArrayUtils;

  55. import fr.paris.lutece.portal.business.rbac.RBACRole;
  56. import fr.paris.lutece.portal.business.rbac.RBAC;
  57. import fr.paris.lutece.portal.business.regularexpression.RegularExpression;
  58. import fr.paris.lutece.portal.business.right.Level;
  59. import fr.paris.lutece.portal.business.right.LevelHome;
  60. import fr.paris.lutece.portal.business.right.Right;
  61. import fr.paris.lutece.portal.business.user.AdminUser;
  62. import fr.paris.lutece.portal.business.user.AdminUserFilter;
  63. import fr.paris.lutece.portal.business.user.AdminUserHome;
  64. import fr.paris.lutece.portal.business.user.attribute.AdminUserField;
  65. import fr.paris.lutece.portal.business.user.attribute.AdminUserFieldFilter;
  66. import fr.paris.lutece.portal.business.user.attribute.AdminUserFieldHome;
  67. import fr.paris.lutece.portal.business.user.attribute.IAttribute;
  68. import fr.paris.lutece.portal.business.user.parameter.DefaultUserParameterHome;
  69. import fr.paris.lutece.portal.business.workgroup.AdminWorkgroupHome;
  70. import fr.paris.lutece.portal.service.datastore.DatastoreService;
  71. import fr.paris.lutece.portal.service.i18n.I18nService;
  72. import fr.paris.lutece.portal.service.mail.MailService;
  73. import fr.paris.lutece.portal.service.message.AdminMessage;
  74. import fr.paris.lutece.portal.service.message.AdminMessageService;
  75. import fr.paris.lutece.portal.service.plugin.PluginService;
  76. import fr.paris.lutece.portal.service.portal.PortalService;
  77. import fr.paris.lutece.portal.service.rbac.RBACService;
  78. import fr.paris.lutece.portal.service.regularexpression.RegularExpressionService;
  79. import fr.paris.lutece.portal.service.spring.SpringContextService;
  80. import fr.paris.lutece.portal.service.template.AppTemplateService;
  81. import fr.paris.lutece.portal.service.template.DatabaseTemplateService;
  82. import fr.paris.lutece.portal.service.user.AdminUserResourceIdService;
  83. import fr.paris.lutece.portal.service.user.attribute.AdminUserFieldService;
  84. import fr.paris.lutece.portal.service.user.attribute.AttributeService;
  85. import fr.paris.lutece.portal.service.util.AppPropertiesService;
  86. import fr.paris.lutece.portal.service.util.CryptoService;
  87. import fr.paris.lutece.portal.web.l10n.LocaleService;
  88. import fr.paris.lutece.util.ReferenceList;
  89. import fr.paris.lutece.util.date.DateUtil;
  90. import fr.paris.lutece.util.html.HtmlTemplate;
  91. import fr.paris.lutece.util.password.IPassword;
  92. import fr.paris.lutece.util.password.IPasswordFactory;
  93. import fr.paris.lutece.util.password.PasswordUtil;
  94. import fr.paris.lutece.util.url.UrlItem;
  95. import fr.paris.lutece.util.xml.XmlUtil;

  96. /**
  97.  * This service provides features concerning the administration users
  98.  */
  99. public final class AdminUserService
  100. {
  101.     // DataStore keys
  102.     public static final String DSKEY_ACCOUNT_REACTIVATED_MAIL_SENDER = "core.advanced_parameters.account_reactivated_mail_sender";
  103.     public static final String DSKEY_ACCOUNT_REACTIVATED_MAIL_SUBJECT = "core.advanced_parameters.account_reactivated_mail_subject";
  104.     public static final String DSKEY_ACCOUNT_REACTIVATED_MAIL_BODY = "core_account_reactivated_mail";
  105.     public static final String DSKEY_PASSWORD_DURATION = "core.advanced_parameters.password_duration";
  106.     public static final String DSKEY_MAXIMUM_NUMBER_PASSWORD_CHANGE = "core.advanced_parameters.maximum_number_password_change";
  107.     public static final String DSKEY_PASSWORD_HISTORY_SIZE = "core.advanced_parameters.password_history_size";
  108.     public static final String DSKEY_TSW_SIZE_PASSWORD_CHANGE = "core.advanced_parameters.tsw_size_password_change";
  109.     public static final String DSKEY_NOTIFY_USER_PASSWORD_EXPIRED = "core.advanced_parameters.notify_user_password_expired";
  110.     public static final String DSKEY_BANNED_DOMAIN_NAMES = "banned_domain_names";
  111.     public static final String DSKEY_ACCOUNT_LIFE_TIME = "core.advanced_parameters.account_life_time";
  112.     public static final String DSKEY_TIME_BEFORE_ALERT_ACCOUNT = "core.advanced_parameters.time_before_alert_account";
  113.     public static final String DSKEY_NB_ALERT_ACCOUNT = "core.advanced_parameters.nb_alert_account";
  114.     public static final String DSKEY_TIME_BETWEEN_ALERTS_ACCOUNT = "core.advanced_parameters.time_between_alerts_account";
  115.     public static final String DSKEY_ACCES_FAILURES_MAX = "core.advanced_parameters.access_failures_max";
  116.     public static final String DSKEY_ACCES_FAILURES_INTERVAL = "core.advanced_parameters.access_failures_interval";
  117.     public static final String DSKEY_EMAIL_PATTERN = "core.advanced_parameters.email_pattern";
  118.     public static final String DSKEY_EMAIL_PATTERN_VERIFY_BY = "core.advanced_parameters.email_pattern_verify_by";
  119.     public static final String DSKEY_PASSWORD_FORMAT_SPECIAL_CHARACTERS = "core.advanced_parameters.password_format_special_characters";
  120.     public static final String DSKEY_PASSWORD_FORMAT_NUMERO = "core.advanced_parameters.password_format_numero";
  121.     public static final String DSKEY_PASSWORD_FORMAT_UPPER_LOWER_CASE = "core.advanced_parameters.password_format_upper_lower_case";
  122.     public static final String DSKEY_FORCE_CHANGE_PASSWORD_REINIT = "core.advanced_parameters.force_change_password_reinit";
  123.     public static final String DSKEY_PASSWORD_MINIMUM_LENGTH = "core.advanced_parameters.password_minimum_length";
  124.     public static final String DSKEY_DEFAULT_USER_STATUS = "core.advanced_parameters.default_user_status";
  125.     public static final String DSKEY_DEFAULT_USER_LANGUAGE = "core.advanced_parameters.default_user_language";
  126.     public static final String DSKEY_DEFAULT_USER_NOTIFICATION = "core.advanced_parameters.default_user_notification";
  127.     public static final String DSKEY_DEFAULT_USER_LEVEL = "core.advanced_parameters.default_user_level";
  128.     public static final String DSKEY_USE_ADVANCED_SECURITY_PARAMETERS = "core.advanced_parameters.use_advanced_security_parameters";
  129.     public static final String DSKEY_RESET_TOKEN_VALIDITY = "core.advanced_parameters.reset_token_validity";
  130.     public static final String DSKEY_LOCK_RESET_TOKEN_TO_SESSION = "core.advanced_parameters.lock_reset_token_to_session";

  131.     // Parameter
  132.     private static final String PARAMETER_ACCESS_CODE = "access_code";
  133.     private static final String PARAMETER_LAST_NAME = "last_name";
  134.     private static final String PARAMETER_FIRST_NAME = "first_name";
  135.     private static final String PARAMETER_EMAIL = "email";

  136.     // Markers
  137.     private static final String MARK_DEFAULT_USER_LEVEL = "default_user_level";
  138.     private static final String MARK_DEFAULT_USER_NOTIFICATION = "default_user_notification";
  139.     private static final String MARK_DEFAULT_USER_LANGUAGE = "default_user_language";
  140.     private static final String MARK_DEFAULT_USER_STATUS = "default_user_status";
  141.     private static final String MARK_LANGUAGES_LIST = "languages_list";
  142.     private static final String MARK_USER_LEVELS_LIST = "user_levels";
  143.     private static final String MARK_SEARCH_IS_SEARCH = "search_is_search";
  144.     private static final String MARK_SEARCH_ADMIN_USER_FILTER = "search_admin_user_filter";
  145.     private static final String MARK_SEARCH_ADMIN_USER_FIELD_FILTER = "search_admin_user_field_filter";
  146.     private static final String MARK_ATTRIBUTES_LIST = "attributes_list";
  147.     private static final String MARK_LOCALE = "locale";
  148.     private static final String MARK_SORT_SEARCH_ATTRIBUTE = "sort_search_attribute";
  149.     private static final String MARK_MAP_ID_USER_LIST_USER_FIELDS = "map_id_user_list_user_fields";
  150.     private static final String MARK_EMAIL_PATTERN = "email_pattern";
  151.     private static final String MARK_AVAILABLE_REGULAREXPRESSIONS = "available_regularexpressions";
  152.     private static final String MARK_SELECTED_REGULAREXPRESSIONS = "selected_regularexpressions";
  153.     private static final String MARK_IS_EMAIL_PATTERN_SET_MANUALLY = "is_email_pattern_set_manually";
  154.     private static final String MARK_PLUGIN_REGULAREXPRESSION = "plugin_regularexpression";
  155.     private static final String MARK_FORCE_CHANGE_PASSWORD_REINIT = "force_change_password_reinit";
  156.     private static final String MARK_PASSWORD = "password";
  157.     private static final String MARK_PASSWORD_MINIMUM_LENGTH = "password_minimum_length";
  158.     private static final String MARK_PASSWORD_FORMAT_UPPER_LOWER_CASE = "password_format_upper_lower_case";
  159.     private static final String MARK_PASSWORD_FORMAT_NUMERO = "password_format_numero";
  160.     private static final String MARK_PASSWORD_FORMAT_SPECIAL_CHARACTERS = "password_format_special_characters";
  161.     private static final String MARK_PASSWORD_DURATION = "password_duration";
  162.     private static final String MARK_PASSWORD_HISTORY_SIZE = "password_history_size";
  163.     private static final String MARK_MAXIMUM_NUMBER_PASSWORD_CHANGE = "maximum_number_password_change";
  164.     private static final String MARK_TSW_SIZE_PASSWORD_CHANGE = "tsw_size_password_change";
  165.     private static final String MARK_USE_ADVANCED_SECURITY_PARAMETERS = "use_advanced_security_parameters";
  166.     private static final String MARK_ACCOUNT_LIFE_TIME = "account_life_time";
  167.     private static final String MARK_TIME_BEFORE_ALERT_ACCOUNT = "time_before_alert_account";
  168.     private static final String MARK_NB_ALERT_ACCOUNT = "nb_alert_account";
  169.     private static final String MARK_TIME_BETWEEN_ALERTS_ACCOUNT = "time_between_alerts_account";
  170.     private static final String MARK_ACCES_FAILURES_MAX = "access_failures_max";
  171.     private static final String MARK_ACCES_FAILURES_INTERVAL = "access_failures_interval";
  172.     private static final String MARK_NAME = "name";
  173.     private static final String MARK_FIRST_NAME = "first_name";
  174.     private static final String MARK_DATE_VALID = "date_valid";
  175.     private static final String MARK_BANNED_DOMAIN_NAMES = "banned_domain_names";
  176.     private static final String MARK_NOTIFY_USER_PASSWORD_EXPIRED = "notify_user_password_expired";
  177.     private static final String MARK_SITE_NAME = "site_name";
  178.     private static final String MARK_USER = "user";
  179.     private static final String MARK_SITE_LINK = "site_link";
  180.     private static final String MARK_LOGIN_URL = "login_url";
  181.     private static final String MARK_RESET_TOKEN_VALIDITY = "reset_token_validity";
  182.     private static final String MARK_LOCK_RESET_TOKEN_TO_SESSION = "lock_reset_token_to_session";

  183.     // Properties
  184.     private static final String PROPERTY_EMAIL_PATTERN = "lutece.email.pattern";
  185.     private static final String PROPERTY_MESSAGE_EMAIL_FORMAT = "portal.users.message.user.emailFormat";
  186.     private static final String PROPERTY_MESSAGE_EMAIL_FORMAT_BANNED_DOMAIN_NAME = "portal.users.message.user.emailFormatBannedDomainNames";
  187.     private static final String PROPERTY_MESSAGE_MINIMUM_PASSWORD_LENGTH = "portal.users.message.password.minimumPasswordLength";
  188.     private static final String PROPERTY_MESSAGE_PASSWORD_FORMAT = "portal.users.message.password.format";
  189.     private static final String PROPERTY_MESSAGE_PASSWORD_FORMAT_UPPER_LOWER_CASE = "portal.users.message.password.formatUpperLowerCase";
  190.     private static final String PROPERTY_MESSAGE_PASSWORD_FORMAT_NUMERO = "portal.users.message.password.formatNumero";
  191.     private static final String PROPERTY_MESSAGE_PASSWORD_FORMAT_SPECIAL_CHARACTERS = "portal.users.message.password.formatSpecialCharacters";
  192.     private static final String PROPERTY_MESSAGE_PASSWORD_ALREADY_USED = "portal.users.message.password.passwordAlreadyUsed";
  193.     private static final String PROPERTY_MESSAGE_MAX_PASSWORD_CHANGE = "portal.users.message.password.maxPasswordChange";
  194.     private static final String PROPERTY_ANONYMIZATION_ENCRYPT_ALGO = "security.anonymization.encryptAlgo";
  195.     private static final String PROPERTY_DEFAULT_PASSWORD_MINIMAL_LENGTH = "security.defaultValues.passwordMinimalLength";
  196.     private static final String PROPERTY_DEFAULT_MAXIMUM_NUMBER_PASSWORD_CHANGE = "security.defaultValues.maximumPasswordChange";
  197.     private static final String PROPERTY_DEFAULT_TSW_SIZE_PASSWORD_CHANGE = "security.defaultValues.maximumPasswordChangeTSWSize";
  198.     private static final String PROPERTY_DEFAULT_HISTORY_SIZE = "security.defaultValues.passwordHistorySize";
  199.     private static final String PROPERTY_DEFAULT_PASSWORD_DURATION = "security.defaultValues.passwordDuration";

  200.     // CONSTANTS
  201.     private static final String CONSTANT_DEFAULT_ENCRYPT_ALGO = "SHA-256";
  202.     private static final String COMMA = ",";
  203.     private static final String SEMICOLON = ";";
  204.     private static final String ZERO = "0";
  205.     private static final String CONSTANT_AT = "@";
  206.     private static final String CONSTANT_UNDERSCORE = "_";
  207.     private static final String CONSTANT_XML_USER = "user";
  208.     private static final String CONSTANT_XML_ACCESS_CODE = "access_code";
  209.     private static final String CONSTANT_XML_LAST_NAME = "last_name";
  210.     private static final String CONSTANT_XML_FIRST_NAME = "first_name";
  211.     private static final String CONSTANT_XML_EMAIL = "email";
  212.     private static final String CONSTANT_XML_STATUS = "status";
  213.     private static final String CONSTANT_XML_LOCALE = "locale";
  214.     private static final String CONSTANT_XML_LEVEL = "level";
  215.     private static final String CONSTANT_XML_MUST_CHANGE_PASSWORD = "must_change_password";
  216.     private static final String CONSTANT_XML_ACCESSIBILITY_MODE = "accessibility_mode";
  217.     private static final String CONSTANT_XML_PASSWORD_MAX_VALID_DATE = "password_max_valid_date";
  218.     private static final String CONSTANT_XML_ACCOUNT_MAX_VALID_DATE = "account_max_valid_date";
  219.     private static final String CONSTANT_XML_DATE_LAST_LOGIN = "date_last_login";
  220.     private static final String CONSTANT_XML_ROLES = "roles";
  221.     private static final String CONSTANT_XML_RIGHTS = "rights";
  222.     private static final String CONSTANT_XML_WORKGROUPS = "workgroups";
  223.     private static final String CONSTANT_XML_ROLE = "role";
  224.     private static final String CONSTANT_XML_RIGHT = "right";
  225.     private static final String CONSTANT_XML_WORKGROUP = "workgroup";
  226.     private static final String CONSTANT_XML_ATTRIBUTES = "attributes";
  227.     private static final String CONSTANT_XML_ATTRIBUTE = "attribute";
  228.     private static final String CONSTANT_XML_ATTRIBUTE_ID = "attribute-id";
  229.     private static final String CONSTANT_XML_ATTRIBUTE_FIELD_ID = "attribute-field-id";
  230.     private static final String CONSTANT_XML_ATTRIBUTE_VALUE = "attribute-value";

  231.     /** Private constructor */
  232.     private AdminUserService( )
  233.     {
  234.     }

  235.     /**
  236.      * Init
  237.      */
  238.     public static void init( )
  239.     {
  240.         AdminUser.init( );
  241.     }

  242.     /**
  243.      * Get the user in session
  244.      *
  245.      * @param request
  246.      *            The HTTP request
  247.      * @return the user in session
  248.      */
  249.     public static AdminUser getAdminUser( HttpServletRequest request )
  250.     {
  251.         return AdminAuthenticationService.getInstance( ).getRegisteredUser( request );
  252.     }

  253.     /**
  254.      * Get the locale for the current request
  255.      *
  256.      * @param request
  257.      *            The HTTP request
  258.      * @return the locale to use with this request
  259.      */
  260.     public static Locale getLocale( HttpServletRequest request )
  261.     {
  262.         Locale locale;
  263.         AdminUser user = getAdminUser( request );

  264.         if ( user != null )
  265.         {
  266.             // Take the locale of the current user if exists
  267.             locale = user.getLocale( );
  268.         }
  269.         else
  270.         {
  271.             // TODO : Add cookie search

  272.             // Take the locale of the browser
  273.             locale = request.getLocale( );
  274.         }

  275.         return locale;
  276.     }

  277.     /**
  278.      * Get the filtered list of admin users
  279.      *
  280.      * @param listUsers
  281.      *            the initial list of users
  282.      * @param request
  283.      *            HttpServletRequest
  284.      * @param model
  285.      *            map
  286.      * @param url
  287.      *            URL of the current interface
  288.      * @return The filtered list of admin users
  289.      */
  290.     public static List<AdminUser> getFilteredUsersInterface( Collection<AdminUser> listUsers, HttpServletRequest request, Map<String, Object> model,
  291.             UrlItem url )
  292.     {
  293.         AdminUser currentUser = getAdminUser( request );

  294.         // FILTER
  295.         AdminUserFilter auFilter = new AdminUserFilter( );
  296.         List<AdminUser> listFilteredUsers = new ArrayList<>( );
  297.         boolean bIsSearch = auFilter.setAdminUserFilter( request );
  298.         boolean bIsFiltered;

  299.         for ( AdminUser filteredUser : AdminUserHome.findUserByFilter( auFilter ) )
  300.         {
  301.             bIsFiltered = false;

  302.             for ( AdminUser user : listUsers )
  303.             {
  304.                 if ( user.getUserId( ) == filteredUser.getUserId( ) )
  305.                 {
  306.                     bIsFiltered = true;

  307.                     break;
  308.                 }
  309.             }

  310.             if ( bIsFiltered && ( currentUser.isParent( filteredUser ) || ( currentUser.isAdmin( ) ) ) )
  311.             {
  312.                 listFilteredUsers.add( filteredUser );
  313.             }
  314.         }

  315.         List<AdminUser> filteredUsers = new ArrayList<>( );

  316.         AdminUserFieldFilter auFieldFilter = new AdminUserFieldFilter( );
  317.         auFieldFilter.setAdminUserFieldFilter( request, currentUser.getLocale( ) );

  318.         List<AdminUser> listFilteredUsersByUserFields = AdminUserFieldHome.findUsersByFilter( auFieldFilter );

  319.         if ( listFilteredUsersByUserFields != null )
  320.         {
  321.             Set<Integer> listFilteredUsersByUserFieldsId = listFilteredUsersByUserFields.stream( ).map( AdminUser::getUserId ).collect( Collectors.toSet( ) );
  322.             filteredUsers.addAll( listFilteredUsers.stream( ).filter( user -> listFilteredUsersByUserFieldsId.contains( user.getUserId( ) ) )
  323.                     .collect( Collectors.toList( ) ) );
  324.         }
  325.         else
  326.         {
  327.             filteredUsers = listFilteredUsers;
  328.         }

  329.         Map<String, List<AdminUserField>> map = new HashMap<>( );

  330.         for ( AdminUser user : filteredUsers )
  331.         {
  332.             auFieldFilter.setIdUser( user.getUserId( ) );

  333.             List<AdminUserField> listAdminUserFields = AdminUserFieldHome.findByFilter( auFieldFilter );
  334.             map.put( String.valueOf( user.getUserId( ) ), listAdminUserFields );
  335.         }

  336.         List<IAttribute> listAttributes = AttributeService.getInstance( ).getAllAttributesWithFields( currentUser.getLocale( ) );

  337.         String strSortSearchAttribute = StringUtils.EMPTY;

  338.         if ( bIsSearch )
  339.         {
  340.             auFilter.setUrlAttributes( url );
  341.             auFieldFilter.setUrlAttributes( url );
  342.             strSortSearchAttribute = auFieldFilter.getUrlAttributes( );
  343.         }

  344.         model.put( MARK_SEARCH_ADMIN_USER_FILTER, auFilter );
  345.         model.put( MARK_SEARCH_IS_SEARCH, bIsSearch );
  346.         model.put( MARK_SEARCH_ADMIN_USER_FIELD_FILTER, auFieldFilter );
  347.         model.put( MARK_LOCALE, currentUser.getLocale( ) );
  348.         model.put( MARK_ATTRIBUTES_LIST, listAttributes );
  349.         model.put( MARK_SORT_SEARCH_ATTRIBUTE, strSortSearchAttribute );
  350.         model.put( MARK_MAP_ID_USER_LIST_USER_FIELDS, map );

  351.         return filteredUsers;
  352.     }

  353.     /**
  354.      * Build the advanced parameters management
  355.      *
  356.      * @param user
  357.      *            The AdminUser object
  358.      * @return The model for the advanced parameters
  359.      */
  360.     public static Map<String, Object> getManageAdvancedParameters( AdminUser user )
  361.     {
  362.         Map<String, Object> model = new HashMap<>( );

  363.         boolean bPermissionManageAdvancedParameters = RBACService.isAuthorized( AdminUser.RESOURCE_TYPE, RBAC.WILDCARD_RESOURCES_ID,
  364.                 AdminUserResourceIdService.PERMISSION_MANAGE_ADVANCED_PARAMETERS, user );

  365.         if ( bPermissionManageAdvancedParameters )
  366.         {
  367.             // USER LEVEL
  368.             String strDefaultLevel = DefaultUserParameterHome.findByKey( DSKEY_DEFAULT_USER_LEVEL );
  369.             Level defaultLevel = LevelHome.findByPrimaryKey( Integer.parseInt( strDefaultLevel ) );

  370.             // USER NOTIFICATION
  371.             int nDefaultUserNotification = Integer.parseInt( DefaultUserParameterHome.findByKey( DSKEY_DEFAULT_USER_NOTIFICATION ) );

  372.             // USER LANGUAGE
  373.             ReferenceList listLanguages = I18nService.getAdminLocales( user.getLocale( ) );
  374.             String strDefaultUserLanguage = DefaultUserParameterHome.findByKey( DSKEY_DEFAULT_USER_LANGUAGE );

  375.             // USER STATUS
  376.             int nDefaultUserStatus = Integer.parseInt( DefaultUserParameterHome.findByKey( DSKEY_DEFAULT_USER_STATUS ) );

  377.             model.put( MARK_USER_LEVELS_LIST, LevelHome.getLevelsList( ) );
  378.             model.put( MARK_DEFAULT_USER_LEVEL, defaultLevel );
  379.             model.put( MARK_DEFAULT_USER_NOTIFICATION, nDefaultUserNotification );
  380.             model.put( MARK_LANGUAGES_LIST, listLanguages );
  381.             model.put( MARK_DEFAULT_USER_LANGUAGE, strDefaultUserLanguage );
  382.             model.put( MARK_DEFAULT_USER_STATUS, nDefaultUserStatus );

  383.             // EMAIL PATTERN
  384.             model.put( MARK_PLUGIN_REGULAREXPRESSION, RegularExpressionService.getInstance( ).isAvailable( ) );
  385.             model.put( MARK_IS_EMAIL_PATTERN_SET_MANUALLY, isEmailPatternSetManually( ) );
  386.             model.put( MARK_EMAIL_PATTERN, getEmailPattern( ) );
  387.             model.put( MARK_AVAILABLE_REGULAREXPRESSIONS, getAvailableRegularExpressions( ) );
  388.             model.put( MARK_SELECTED_REGULAREXPRESSIONS, getSelectedRegularExpressions( ) );

  389.             boolean bUseAdvancesSecurityParameters = getBooleanSecurityParameter( DSKEY_USE_ADVANCED_SECURITY_PARAMETERS );

  390.             model.put( MARK_USE_ADVANCED_SECURITY_PARAMETERS, bUseAdvancesSecurityParameters );

  391.             model.put( MARK_FORCE_CHANGE_PASSWORD_REINIT, getBooleanSecurityParameter( DSKEY_FORCE_CHANGE_PASSWORD_REINIT ) );
  392.             model.put( MARK_PASSWORD_MINIMUM_LENGTH, getIntegerSecurityParameter( DSKEY_PASSWORD_MINIMUM_LENGTH ) );

  393.             model.put( MARK_RESET_TOKEN_VALIDITY, getIntegerSecurityParameter( DSKEY_RESET_TOKEN_VALIDITY ) );
  394.             model.put( MARK_LOCK_RESET_TOKEN_TO_SESSION, getBooleanSecurityParameter( DSKEY_LOCK_RESET_TOKEN_TO_SESSION ) );

  395.             if ( bUseAdvancesSecurityParameters )
  396.             {
  397.                 // SECURITY PARAMETERS
  398.                 model.put( MARK_PASSWORD_FORMAT_UPPER_LOWER_CASE, getBooleanSecurityParameter( DSKEY_PASSWORD_FORMAT_UPPER_LOWER_CASE ) );
  399.                 model.put( MARK_PASSWORD_FORMAT_NUMERO, getBooleanSecurityParameter( DSKEY_PASSWORD_FORMAT_NUMERO ) );
  400.                 model.put( MARK_PASSWORD_FORMAT_SPECIAL_CHARACTERS, getBooleanSecurityParameter( DSKEY_PASSWORD_FORMAT_SPECIAL_CHARACTERS ) );
  401.                 model.put( MARK_PASSWORD_DURATION, getIntegerSecurityParameter( DSKEY_PASSWORD_DURATION ) );
  402.                 model.put( MARK_PASSWORD_HISTORY_SIZE, getIntegerSecurityParameter( DSKEY_PASSWORD_HISTORY_SIZE ) );
  403.                 model.put( MARK_MAXIMUM_NUMBER_PASSWORD_CHANGE, getIntegerSecurityParameter( DSKEY_MAXIMUM_NUMBER_PASSWORD_CHANGE ) );
  404.                 model.put( MARK_TSW_SIZE_PASSWORD_CHANGE, getIntegerSecurityParameter( DSKEY_TSW_SIZE_PASSWORD_CHANGE ) );
  405.                 model.put( MARK_NOTIFY_USER_PASSWORD_EXPIRED, getBooleanSecurityParameter( DSKEY_NOTIFY_USER_PASSWORD_EXPIRED ) );
  406.             }

  407.             model.put( MARK_BANNED_DOMAIN_NAMES, getLargeSecurityParameter( DSKEY_BANNED_DOMAIN_NAMES ) );
  408.             model.put( MARK_ACCOUNT_LIFE_TIME, getIntegerSecurityParameter( DSKEY_ACCOUNT_LIFE_TIME ) );
  409.             model.put( MARK_TIME_BEFORE_ALERT_ACCOUNT, getIntegerSecurityParameter( DSKEY_TIME_BEFORE_ALERT_ACCOUNT ) );
  410.             model.put( MARK_NB_ALERT_ACCOUNT, getIntegerSecurityParameter( DSKEY_NB_ALERT_ACCOUNT ) );
  411.             model.put( MARK_TIME_BETWEEN_ALERTS_ACCOUNT, getIntegerSecurityParameter( DSKEY_TIME_BETWEEN_ALERTS_ACCOUNT ) );
  412.             model.put( MARK_ACCES_FAILURES_MAX, getIntegerSecurityParameter( DSKEY_ACCES_FAILURES_MAX ) );
  413.             model.put( MARK_ACCES_FAILURES_INTERVAL, getIntegerSecurityParameter( DSKEY_ACCES_FAILURES_INTERVAL ) );
  414.         }

  415.         return model;
  416.     }

  417.     /**
  418.      * Check if the given email is valid or not. <br>
  419.      * The given email is compared to the value of the parameter <i>'core_user_parameter.email_pattern'</i>.
  420.      *
  421.      * @param strEmail
  422.      *            the str email
  423.      * @return true, if successful
  424.      */
  425.     public static boolean checkEmail( String strEmail )
  426.     {
  427.         boolean bIsValid = true;

  428.         if ( isEmailPatternSetManually( ) )
  429.         {
  430.             if ( StringUtils.isBlank( strEmail ) || !strEmail.matches( getEmailPattern( ) ) )
  431.             {
  432.                 bIsValid = false;
  433.             }
  434.         }
  435.         else
  436.         {
  437.             for ( RegularExpression regularExpression : getSelectedRegularExpressions( ) )
  438.             {
  439.                 if ( !RegularExpressionService.getInstance( ).isMatches( strEmail, regularExpression ) )
  440.                 {
  441.                     bIsValid = false;

  442.                     break;
  443.                 }
  444.             }
  445.         }

  446.         if ( !bIsValid )
  447.         {
  448.             return false;
  449.         }

  450.         String strBannedDomainNames = AdminUserService.getSecurityParameter( DSKEY_BANNED_DOMAIN_NAMES );

  451.         if ( StringUtils.isEmpty( strBannedDomainNames ) )
  452.         {
  453.             return bIsValid;
  454.         }

  455.         String [ ] strListBannedDomainNames = strBannedDomainNames.split( SEMICOLON );
  456.         String strDomainName = strEmail.substring( strEmail.indexOf( CONSTANT_AT ) + 1 );

  457.         if ( strDomainName != null && ArrayUtils.isNotEmpty( strListBannedDomainNames ) && Arrays.asList( strListBannedDomainNames ).contains( strDomainName ) )
  458.         {
  459.             bIsValid = false;
  460.         }
  461.         return bIsValid;
  462.     }

  463.     /**
  464.      * Do modify the email pattern
  465.      *
  466.      * @param strEmailPattern
  467.      *            the email pattern
  468.      * @param bIsSetManually
  469.      *            true if it is know set manually, false otherwise
  470.      */
  471.     public static void doModifyEmailPattern( String strEmailPattern, boolean bIsSetManually )
  472.     {
  473.         if ( bIsSetManually )
  474.         {
  475.             DefaultUserParameterHome.update( DSKEY_EMAIL_PATTERN, strEmailPattern );
  476.             DefaultUserParameterHome.update( DSKEY_EMAIL_PATTERN_VERIFY_BY, StringUtils.EMPTY );
  477.         }
  478.         else
  479.         {
  480.             if ( isEmailPatternSetManually( ) )
  481.             {
  482.                 // If the previous email pattern is set manually, then the parameter
  483.                 // email_pattern_verify_by is set at 0
  484.                 // This way, the interface know the email pattern is not set manually
  485.                 // Indeed, the control is set on the content of the parameter
  486.                 // 'email_pattern_verify_by'
  487.                 DefaultUserParameterHome.update( DSKEY_EMAIL_PATTERN_VERIFY_BY, ZERO );
  488.             }
  489.         }
  490.     }

  491.     /**
  492.      * Reset the email pattern by putting the default email pattern that is set in the <b>lutece.properties</b>.
  493.      */
  494.     public static void doResetEmailPattern( )
  495.     {
  496.         DefaultUserParameterHome.update( DSKEY_EMAIL_PATTERN, getDefaultEmailPattern( ) );
  497.     }

  498.     /**
  499.      * Get the email error message url.
  500.      *
  501.      * @param request
  502.      *            the request
  503.      * @return the error message
  504.      */
  505.     public static String getEmailErrorMessageUrl( HttpServletRequest request )
  506.     {
  507.         String strMessage;

  508.         if ( isEmailPatternSetManually( ) )
  509.         {
  510.             strMessage = getEmailPattern( );
  511.         }
  512.         else
  513.         {
  514.             StringBuilder sbMessage = new StringBuilder( );
  515.             String emailPatternVerifyBy = DefaultUserParameterHome.findByKey( DSKEY_EMAIL_PATTERN_VERIFY_BY );
  516.             String [ ] regularExpressionIds = emailPatternVerifyBy.split( COMMA );

  517.             for ( String strRegularExpressionId : regularExpressionIds )
  518.             {
  519.                 String trimedId = strRegularExpressionId.trim( );

  520.                 if ( StringUtils.isNotBlank( trimedId ) && StringUtils.isNumeric( trimedId ) )
  521.                 {
  522.                     int nRegularExpressionId = Integer.parseInt( trimedId );
  523.                     RegularExpression regularExpression = RegularExpressionService.getInstance( ).getRegularExpressionByKey( nRegularExpressionId );

  524.                     if ( regularExpression != null )
  525.                     {
  526.                         sbMessage.append( regularExpression.getValidExemple( ) );
  527.                         sbMessage.append( COMMA );
  528.                     }
  529.                 }
  530.             }

  531.             // Get all message except the last character which is a comma
  532.             strMessage = sbMessage.toString( ).substring( 0, sbMessage.length( ) - 1 );
  533.         }

  534.         String strBannedDomainNames = getSecurityParameter( DSKEY_BANNED_DOMAIN_NAMES );
  535.         String strMessageProperty;

  536.         if ( !StringUtils.isEmpty( strBannedDomainNames ) )
  537.         {
  538.             strMessageProperty = PROPERTY_MESSAGE_EMAIL_FORMAT_BANNED_DOMAIN_NAME;
  539.         }
  540.         else
  541.         {
  542.             strMessageProperty = PROPERTY_MESSAGE_EMAIL_FORMAT;
  543.         }

  544.         Object [ ] param = {
  545.                 strMessage, strBannedDomainNames
  546.         };

  547.         return AdminMessageService.getMessageUrl( request, strMessageProperty, param, AdminMessage.TYPE_STOP );
  548.     }

  549.     /**
  550.      * Do insert a regular expression
  551.      *
  552.      * @param nRegularExpressionId
  553.      *            the ID of the regular expression
  554.      */
  555.     public static void doInsertRegularExpression( int nRegularExpressionId )
  556.     {
  557.         if ( !isEmailPatternSetManually( ) )
  558.         {
  559.             // Retrieve the rules from the database
  560.             String emailPatternVerifyBy = DefaultUserParameterHome.findByKey( DSKEY_EMAIL_PATTERN_VERIFY_BY );
  561.             String [ ] regularExpressionIds = emailPatternVerifyBy.split( COMMA );

  562.             // Check if the ID is already inserted
  563.             boolean bIsAlreadyInserted = false;

  564.             for ( String strRegularExpressionId : regularExpressionIds )
  565.             {
  566.                 String trimedId = strRegularExpressionId.trim( );

  567.                 if ( StringUtils.isNotBlank( trimedId ) && StringUtils.isNumeric( trimedId ) )
  568.                 {
  569.                     int nRegexId = Integer.parseInt( trimedId );

  570.                     if ( nRegexId == nRegularExpressionId )
  571.                     {
  572.                         bIsAlreadyInserted = true;

  573.                         break;
  574.                     }
  575.                 }
  576.             }

  577.             if ( !bIsAlreadyInserted )
  578.             {
  579.                 // If it is not inserted, then it is concatened to the list of regularExpression
  580.                 String strRegularExpressionIds = emailPatternVerifyBy + COMMA + nRegularExpressionId;
  581.                 emailPatternVerifyBy = strRegularExpressionIds;
  582.                 DefaultUserParameterHome.update( DSKEY_EMAIL_PATTERN_VERIFY_BY, emailPatternVerifyBy );
  583.             }
  584.         }
  585.     }

  586.     /**
  587.      * Do remove a regular expression
  588.      *
  589.      * @param nRegularExpressionId
  590.      *            the ID of the regularexpresion
  591.      */
  592.     public static void doRemoveRegularExpression( int nRegularExpressionId )
  593.     {
  594.         if ( !isEmailPatternSetManually( ) )
  595.         {
  596.             List<Integer> listRegularExpressionIds = new ArrayList<>( );

  597.             // Retrieve the rules from the database
  598.             String emailPatternVerifyBy = DefaultUserParameterHome.findByKey( DSKEY_EMAIL_PATTERN_VERIFY_BY );
  599.             String [ ] regularExpressionIds = emailPatternVerifyBy.split( COMMA );

  600.             // Build the list of regular expression without the regular expression id to
  601.             // delete
  602.             for ( String strRegularExpressionId : regularExpressionIds )
  603.             {
  604.                 String trimedId = strRegularExpressionId.trim( );

  605.                 if ( StringUtils.isNotBlank( trimedId ) && StringUtils.isNumeric( trimedId ) )
  606.                 {
  607.                     int nRegexId = Integer.parseInt( trimedId );

  608.                     if ( nRegexId != nRegularExpressionId )
  609.                     {
  610.                         listRegularExpressionIds.add( nRegexId );
  611.                     }
  612.                 }
  613.             }

  614.             DefaultUserParameterHome.update( DSKEY_EMAIL_PATTERN_VERIFY_BY,
  615.                     listRegularExpressionIds.stream( ).map( String::valueOf ).collect( Collectors.joining( COMMA ) ) );
  616.         }
  617.     }

  618.     /**
  619.      * Get the default email pattern defined in the <b>lutece.properties</b>.
  620.      *
  621.      * @return the default email pattern
  622.      */
  623.     private static String getDefaultEmailPattern( )
  624.     {
  625.         return AppPropertiesService.getProperty( PROPERTY_EMAIL_PATTERN );
  626.     }

  627.     /**
  628.      * Get the AdminUser email pattern that is stored in <b>'core_user_parameter.email_pattern'</b>. <br>
  629.      * If it does not exist, then it will retrieve the value in the <b>lutece.properties</b> file (parameter <b>email.pattern</b>)
  630.      *
  631.      * @return the AdminUser email pattern
  632.      */
  633.     private static String getEmailPattern( )
  634.     {
  635.         String strEmailPattern = getDefaultEmailPattern( );
  636.         String emailPattern = DefaultUserParameterHome.findByKey( DSKEY_EMAIL_PATTERN );

  637.         if ( emailPattern != null )
  638.         {
  639.             strEmailPattern = emailPattern;
  640.         }

  641.         return strEmailPattern;
  642.     }

  643.     /**
  644.      * Get the available rugalar expressions
  645.      *
  646.      * @return a list of {@link ReferenceList}
  647.      */
  648.     public static ReferenceList getAvailableRegularExpressions( )
  649.     {
  650.         ReferenceList regularExpressionsList = new ReferenceList( );

  651.         if ( !isEmailPatternSetManually( ) )
  652.         {
  653.             List<Integer> listRegularExpressionIds = new ArrayList<>( );

  654.             // Retrieve the rules from the database
  655.             String emailPatternVerifyBy = DefaultUserParameterHome.findByKey( DSKEY_EMAIL_PATTERN_VERIFY_BY );
  656.             String [ ] regularExpressionIds = emailPatternVerifyBy.split( COMMA );

  657.             for ( String strRegularExpressionId : regularExpressionIds )
  658.             {
  659.                 String trimedId = strRegularExpressionId.trim( );

  660.                 if ( StringUtils.isNotBlank( trimedId ) && StringUtils.isNumeric( trimedId ) )
  661.                 {
  662.                     int nRegexId = Integer.parseInt( trimedId );
  663.                     listRegularExpressionIds.add( nRegexId );
  664.                 }
  665.             }

  666.             // Fetch all regular expressions
  667.             List<RegularExpression> listRegularExpression = RegularExpressionService.getInstance( ).getAllRegularExpression( );

  668.             // Get only the expressions that are not already selected
  669.             for ( RegularExpression regularExpression : listRegularExpression )
  670.             {
  671.                 if ( !listRegularExpressionIds.contains( regularExpression.getIdExpression( ) ) )
  672.                 {
  673.                     regularExpressionsList.addItem( regularExpression.getIdExpression( ), regularExpression.getTitle( ) );
  674.                 }
  675.             }
  676.         }

  677.         return regularExpressionsList;
  678.     }

  679.     /**
  680.      * Get the list of selected regular expression
  681.      *
  682.      * @return a list of {@link RegularExpression}
  683.      */
  684.     public static List<RegularExpression> getSelectedRegularExpressions( )
  685.     {
  686.         List<RegularExpression> listRegularExpressions = new ArrayList<>( );

  687.         if ( !isEmailPatternSetManually( ) )
  688.         {
  689.             // Retrieve the rules from the database
  690.             String emailPatternVerifyBy = DefaultUserParameterHome.findByKey( DSKEY_EMAIL_PATTERN_VERIFY_BY );
  691.             String [ ] regularExpressionIds = emailPatternVerifyBy.split( COMMA );

  692.             for ( String strRegularExpressionId : regularExpressionIds )
  693.             {
  694.                 String trimedId = strRegularExpressionId.trim( );

  695.                 if ( StringUtils.isNotBlank( trimedId ) && StringUtils.isNumeric( trimedId ) )
  696.                 {
  697.                     int nRegularExpressionId = Integer.parseInt( trimedId );
  698.                     RegularExpression expression = RegularExpressionService.getInstance( ).getRegularExpressionByKey( nRegularExpressionId );

  699.                     if ( expression != null )
  700.                     {
  701.                         listRegularExpressions.add( expression );
  702.                     }
  703.                 }
  704.             }
  705.         }

  706.         return listRegularExpressions;
  707.     }

  708.     /**
  709.      * Check whether the email pattern is set manually or by a set of rules from the plugin-regularexpression.
  710.      *
  711.      * @return true if it is set manually, false otherwise
  712.      */
  713.     private static boolean isEmailPatternSetManually( )
  714.     {
  715.         boolean bIsSetManually = true;

  716.         if ( RegularExpressionService.getInstance( ).isAvailable( ) )
  717.         {
  718.             String emailPatternVerifyBy = DefaultUserParameterHome.findByKey( DSKEY_EMAIL_PATTERN_VERIFY_BY );

  719.             if ( StringUtils.isNotBlank( emailPatternVerifyBy ) )
  720.             {
  721.                 bIsSetManually = false;
  722.             }
  723.         }

  724.         return bIsSetManually;
  725.     }

  726.     /**
  727.      * Get an integer user parameter from its key.
  728.      *
  729.      * @param strParameterkey
  730.      *            Key of the parameter
  731.      * @return The value of the user parameter, or 0 if there is no value or an non integer value.
  732.      */
  733.     public static int getIntegerSecurityParameter( String strParameterkey )
  734.     {
  735.         String defaultUserParameter = DefaultUserParameterHome.findByKey( strParameterkey );

  736.         if ( StringUtils.isBlank( defaultUserParameter ) )
  737.         {
  738.             return 0;
  739.         }

  740.         try
  741.         {
  742.             return Integer.parseInt( defaultUserParameter );
  743.         }
  744.         catch( NumberFormatException e )
  745.         {
  746.             return 0;
  747.         }
  748.     }

  749.     /**
  750.      * Get a boolean user parameter from its key.
  751.      *
  752.      * @param strParameterkey
  753.      *            Key of the parameter
  754.      * @return The value of the user parameter, or false if there is no value or an non boolean value.
  755.      */
  756.     public static boolean getBooleanSecurityParameter( String strParameterkey )
  757.     {
  758.         String defaultUserParameter = DefaultUserParameterHome.findByKey( strParameterkey );

  759.         return defaultUserParameter != null && Boolean.parseBoolean( defaultUserParameter );
  760.     }

  761.     /**
  762.      * Get a user parameter from its key.
  763.      *
  764.      * @param strParameterkey
  765.      *            Key of the parameter
  766.      * @return The value of the user parameter.
  767.      */
  768.     public static String getSecurityParameter( String strParameterkey )
  769.     {
  770.         return DefaultUserParameterHome.findByKey( strParameterkey );
  771.     }

  772.     /**
  773.      * Get a user parameter from its key.
  774.      *
  775.      * @param strParameterKey
  776.      *            Key of the parameter
  777.      * @return The value of the user parameter.
  778.      */
  779.     public static String getLargeSecurityParameter( String strParameterKey )
  780.     {
  781.         return DatastoreService.getDataValue( PluginService.getCore( ).getName( ) + CONSTANT_UNDERSCORE + strParameterKey, StringUtils.EMPTY );
  782.     }

  783.     /**
  784.      * Update a security parameter value.
  785.      *
  786.      * @param strParameterKey
  787.      *            The key of the parameter
  788.      * @param strValue
  789.      *            The new value
  790.      */
  791.     public static void updateSecurityParameter( String strParameterKey, String strValue )
  792.     {
  793.         String strValueTmp = StringUtils.isNotBlank( strValue ) ? strValue : StringUtils.EMPTY;
  794.         DefaultUserParameterHome.update( strParameterKey, strValueTmp );
  795.     }

  796.     /**
  797.      * Update a security parameter value.
  798.      *
  799.      * @param strParameterKey
  800.      *            The key of the parameter
  801.      * @param strValue
  802.      *            The new value
  803.      */
  804.     public static void updateLargeSecurityParameter( String strParameterKey, String strValue )
  805.     {
  806.         DatastoreService.setDataValue( PluginService.getCore( ).getName( ) + CONSTANT_UNDERSCORE + strParameterKey, strValue );
  807.     }

  808.     /**
  809.      * Check that the password respect user parameters
  810.      *
  811.      * @param request
  812.      *            The request
  813.      * @param strPassword
  814.      *            The password to check
  815.      * @param nUserId
  816.      *            The id of the modified user
  817.      * @return Null if the password is correct, or the url of an admin message describing the error
  818.      */
  819.     public static String checkPassword( HttpServletRequest request, String strPassword, int nUserId )
  820.     {
  821.         return checkPassword( request, strPassword, nUserId, Boolean.FALSE );
  822.     }

  823.     /**
  824.      * Check that the password respect user parameters
  825.      *
  826.      * @param request
  827.      *            The request
  828.      * @param strPassword
  829.      *            The password to check
  830.      * @param nUserId
  831.      *            The id of the modified user
  832.      * @param bSkipHistoryCheck
  833.      *            Indicates if the password history should be checked or not.
  834.      * @return Null if the password is correct, or the url of an admin message describing the error
  835.      */
  836.     public static String checkPassword( HttpServletRequest request, String strPassword, int nUserId, boolean bSkipHistoryCheck )
  837.     {
  838.         // Minimum password length
  839.         int nMinimumLength = AdminUserService.getIntegerSecurityParameter( DSKEY_PASSWORD_MINIMUM_LENGTH );

  840.         if ( ( nMinimumLength > 0 ) && ( strPassword.length( ) < nMinimumLength ) )
  841.         {
  842.             Object [ ] param = {
  843.                     nMinimumLength
  844.             };

  845.             return AdminMessageService.getMessageUrl( request, PROPERTY_MESSAGE_MINIMUM_PASSWORD_LENGTH, param, AdminMessage.TYPE_STOP );
  846.         }

  847.         // Password format
  848.         String message = checkPasswordFormat( request, strPassword );
  849.         if ( message != null )
  850.         {
  851.             return message;
  852.         }

  853.         // Check password history
  854.         if ( nUserId <= 0 || bSkipHistoryCheck )
  855.         {
  856.             return null;
  857.         }
  858.         return checkPasswordHistory( request, strPassword, nUserId );
  859.     }

  860.     private static String checkPasswordHistory( HttpServletRequest request, String strPassword, int nUserId )
  861.     {
  862.         int nPasswordHistorySize = AdminUserService.getIntegerSecurityParameter( DSKEY_PASSWORD_HISTORY_SIZE );

  863.         if ( nPasswordHistorySize > 0 )
  864.         {
  865.             List<IPassword> passwordHistory = AdminUserHome.selectUserPasswordHistory( nUserId );

  866.             if ( nPasswordHistorySize < passwordHistory.size( ) )
  867.             {
  868.                 passwordHistory = passwordHistory.subList( 0, nPasswordHistorySize );
  869.             }

  870.             for ( IPassword password : passwordHistory )
  871.             {
  872.                 if ( password.check( strPassword ) )
  873.                 {
  874.                     return AdminMessageService.getMessageUrl( request, PROPERTY_MESSAGE_PASSWORD_ALREADY_USED, AdminMessage.TYPE_STOP );
  875.                 }
  876.             }
  877.         }

  878.         int nTSWSizePasswordChange = AdminUserService.getIntegerSecurityParameter( DSKEY_TSW_SIZE_PASSWORD_CHANGE );
  879.         int nMaximumNumberPasswordChange = AdminUserService.getIntegerSecurityParameter( DSKEY_MAXIMUM_NUMBER_PASSWORD_CHANGE );

  880.         if ( nMaximumNumberPasswordChange > 0 )
  881.         {
  882.             Timestamp minDate;

  883.             if ( nTSWSizePasswordChange > 0 )
  884.             {
  885.                 minDate = new Timestamp( new java.util.Date( ).getTime( ) - DateUtil.convertDaysInMiliseconds( nTSWSizePasswordChange ) );
  886.             }
  887.             else
  888.             {
  889.                 minDate = new Timestamp( 0 );
  890.             }

  891.             if ( AdminUserHome.countUserPasswordHistoryFromDate( minDate, nUserId ) >= nMaximumNumberPasswordChange )
  892.             {
  893.                 return AdminMessageService.getMessageUrl( request, PROPERTY_MESSAGE_MAX_PASSWORD_CHANGE, AdminMessage.TYPE_STOP );
  894.             }
  895.         }

  896.         return null;
  897.     }

  898.     private static String checkPasswordFormat( HttpServletRequest request, String strPassword )
  899.     {
  900.         boolean bUserPasswordFormatUpperLowerCase = AdminUserService.getBooleanSecurityParameter( DSKEY_PASSWORD_FORMAT_UPPER_LOWER_CASE );
  901.         boolean bUserPasswordFormatNumero = AdminUserService.getBooleanSecurityParameter( DSKEY_PASSWORD_FORMAT_NUMERO );
  902.         boolean bUserPasswordFormatSpecialCaracters = AdminUserService.getBooleanSecurityParameter( DSKEY_PASSWORD_FORMAT_SPECIAL_CHARACTERS );

  903.         if ( ( bUserPasswordFormatUpperLowerCase || bUserPasswordFormatNumero || bUserPasswordFormatSpecialCaracters ) && !PasswordUtil
  904.                 .checkPasswordFormat( strPassword, bUserPasswordFormatUpperLowerCase, bUserPasswordFormatNumero, bUserPasswordFormatSpecialCaracters ) )
  905.         {
  906.             List<String> messageList = new ArrayList<>( );

  907.             // Add Message Upper Lower Case
  908.             if ( bUserPasswordFormatUpperLowerCase )
  909.             {
  910.                 messageList.add( I18nService.getLocalizedString( PROPERTY_MESSAGE_PASSWORD_FORMAT_UPPER_LOWER_CASE, request.getLocale( ) ) );
  911.             }

  912.             // Add Message Numero
  913.             if ( bUserPasswordFormatNumero )
  914.             {
  915.                 messageList.add( I18nService.getLocalizedString( PROPERTY_MESSAGE_PASSWORD_FORMAT_NUMERO, request.getLocale( ) ) );
  916.             }

  917.             // Add Message Special Characters
  918.             if ( bUserPasswordFormatSpecialCaracters )
  919.             {
  920.                 messageList.add( I18nService.getLocalizedString( PROPERTY_MESSAGE_PASSWORD_FORMAT_SPECIAL_CHARACTERS, request.getLocale( ) ) );
  921.             }

  922.             String strParam = messageList.stream( ).collect( Collectors.joining( ", " ) );

  923.             Object [ ] param = {
  924.                     strParam
  925.             };

  926.             return AdminMessageService.getMessageUrl( request, PROPERTY_MESSAGE_PASSWORD_FORMAT, param, AdminMessage.TYPE_STOP );
  927.         }
  928.         return null;
  929.     }

  930.     /**
  931.      * Generate a new random password
  932.      *
  933.      * @return the new password
  934.      */
  935.     public static String makePassword( )
  936.     {
  937.         // Password format
  938.         boolean bUserPasswordFormatUpperLowerCase = AdminUserService.getBooleanSecurityParameter( DSKEY_PASSWORD_FORMAT_UPPER_LOWER_CASE );
  939.         boolean bUserPasswordFormatNumero = AdminUserService.getBooleanSecurityParameter( DSKEY_PASSWORD_FORMAT_NUMERO );
  940.         boolean bUserPasswordFormatSpecialCaracters = AdminUserService.getBooleanSecurityParameter( DSKEY_PASSWORD_FORMAT_SPECIAL_CHARACTERS );
  941.         int nMinPasswordSize = AdminUserService.getIntegerSecurityParameter( DSKEY_PASSWORD_MINIMUM_LENGTH );

  942.         return PasswordUtil.makePassword( nMinPasswordSize, bUserPasswordFormatUpperLowerCase, bUserPasswordFormatNumero, bUserPasswordFormatSpecialCaracters );
  943.     }

  944.     /**
  945.      * Encrypt a password
  946.      *
  947.      * @param strPassword
  948.      *            The password to encrypt
  949.      * @return The given password encrypted
  950.      */
  951.     public static IPassword encryptPassword( String strPassword )
  952.     {
  953.         IPasswordFactory passwordFactory = SpringContextService.getBean( IPasswordFactory.BEAN_NAME );

  954.         return passwordFactory.getPasswordFromCleartext( strPassword );
  955.     }

  956.     /**
  957.      * Enable advanced security parameters
  958.      */
  959.     public static void useAdvancedSecurityParameters( )
  960.     {
  961.         updateSecurityParameter( DSKEY_USE_ADVANCED_SECURITY_PARAMETERS, Boolean.TRUE.toString( ) );
  962.         updateSecurityParameter( DSKEY_FORCE_CHANGE_PASSWORD_REINIT, Boolean.TRUE.toString( ) );
  963.         updateSecurityParameter( DSKEY_MAXIMUM_NUMBER_PASSWORD_CHANGE, AppPropertiesService.getProperty( PROPERTY_DEFAULT_MAXIMUM_NUMBER_PASSWORD_CHANGE ) );
  964.         updateSecurityParameter( DSKEY_PASSWORD_DURATION, AppPropertiesService.getProperty( PROPERTY_DEFAULT_PASSWORD_DURATION ) );
  965.         updateSecurityParameter( DSKEY_PASSWORD_FORMAT_UPPER_LOWER_CASE, Boolean.TRUE.toString( ) );
  966.         updateSecurityParameter( DSKEY_PASSWORD_FORMAT_NUMERO, Boolean.TRUE.toString( ) );
  967.         updateSecurityParameter( DSKEY_PASSWORD_FORMAT_SPECIAL_CHARACTERS, Boolean.TRUE.toString( ) );
  968.         updateSecurityParameter( DSKEY_PASSWORD_HISTORY_SIZE, AppPropertiesService.getProperty( PROPERTY_DEFAULT_HISTORY_SIZE ) );
  969.         updateSecurityParameter( DSKEY_TSW_SIZE_PASSWORD_CHANGE, AppPropertiesService.getProperty( PROPERTY_DEFAULT_TSW_SIZE_PASSWORD_CHANGE ) );

  970.         int nMinPwdLength = getIntegerSecurityParameter( DSKEY_PASSWORD_MINIMUM_LENGTH );

  971.         if ( nMinPwdLength <= 0 )
  972.         {
  973.             updateSecurityParameter( DSKEY_PASSWORD_MINIMUM_LENGTH, AppPropertiesService.getProperty( PROPERTY_DEFAULT_PASSWORD_MINIMAL_LENGTH ) );
  974.         }

  975.         updateSecurityParameter( DSKEY_NOTIFY_USER_PASSWORD_EXPIRED, Boolean.TRUE.toString( ) );
  976.     }

  977.     /**
  978.      * Disable advances security parameters
  979.      */
  980.     public static void removeAdvancedSecurityParameters( )
  981.     {
  982.         updateSecurityParameter( DSKEY_USE_ADVANCED_SECURITY_PARAMETERS, StringUtils.EMPTY );
  983.         updateSecurityParameter( DSKEY_MAXIMUM_NUMBER_PASSWORD_CHANGE, StringUtils.EMPTY );
  984.         updateSecurityParameter( DSKEY_PASSWORD_DURATION, StringUtils.EMPTY );
  985.         updateSecurityParameter( DSKEY_PASSWORD_FORMAT_UPPER_LOWER_CASE, StringUtils.EMPTY );
  986.         updateSecurityParameter( DSKEY_PASSWORD_FORMAT_NUMERO, StringUtils.EMPTY );
  987.         updateSecurityParameter( DSKEY_PASSWORD_FORMAT_SPECIAL_CHARACTERS, StringUtils.EMPTY );
  988.         updateSecurityParameter( DSKEY_PASSWORD_HISTORY_SIZE, StringUtils.EMPTY );
  989.         updateSecurityParameter( DSKEY_TSW_SIZE_PASSWORD_CHANGE, StringUtils.EMPTY );
  990.         updateSecurityParameter( DSKEY_NOTIFY_USER_PASSWORD_EXPIRED, StringUtils.EMPTY );
  991.     }

  992.     /**
  993.      * Compute the maximum valid date of a password with the current time and the parameters in the database.
  994.      *
  995.      * @return The maximum valid date of a password
  996.      */
  997.     public static Timestamp getPasswordMaxValidDate( )
  998.     {
  999.         int nbDayPasswordValid = getIntegerSecurityParameter( DSKEY_PASSWORD_DURATION );

  1000.         if ( nbDayPasswordValid <= 0 )
  1001.         {
  1002.             return null;
  1003.         }

  1004.         return PasswordUtil.getPasswordMaxValidDate( nbDayPasswordValid );
  1005.     }

  1006.     /**
  1007.      * Compute the maximum valid date of an account with the current time and the parameters in the database.
  1008.      *
  1009.      * @return The maximum valid date of an account
  1010.      */
  1011.     public static Timestamp getAccountMaxValidDate( )
  1012.     {
  1013.         int nbMonthsAccountValid = getIntegerSecurityParameter( DSKEY_ACCOUNT_LIFE_TIME );

  1014.         if ( nbMonthsAccountValid <= 0 )
  1015.         {
  1016.             return null;
  1017.         }

  1018.         Calendar calendar = new GregorianCalendar( LocaleService.getDefault( ) );
  1019.         calendar.add( Calendar.MONTH, nbMonthsAccountValid );

  1020.         return new Timestamp( calendar.getTimeInMillis( ) );
  1021.     }

  1022.     /**
  1023.      * Anonymize user data from his id. His rights, roles and his passwords history are also deleted.
  1024.      *
  1025.      * @param nAdminUserId
  1026.      *            Id of the user to anonymize
  1027.      * @param locale
  1028.      *            The locale
  1029.      */
  1030.     public static void anonymizeUser( int nAdminUserId, Locale locale )
  1031.     {
  1032.         AdminUser user = AdminUserHome.findByPrimaryKey( nAdminUserId );

  1033.         String strEncryptionAlgorithme = AppPropertiesService.getProperty( PROPERTY_ANONYMIZATION_ENCRYPT_ALGO, CONSTANT_DEFAULT_ENCRYPT_ALGO );

  1034.         Map<String, Boolean> anonymizationStatus = AdminUserHome.getAnonymizationStatusUserStaticField( );

  1035.         if ( Boolean.TRUE.equals( anonymizationStatus.get( PARAMETER_ACCESS_CODE ) ) )
  1036.         {
  1037.             user.setAccessCode( CryptoService.encrypt( user.getAccessCode( ), strEncryptionAlgorithme ) );
  1038.         }

  1039.         if ( Boolean.TRUE.equals( anonymizationStatus.get( PARAMETER_FIRST_NAME ) ) )
  1040.         {
  1041.             user.setFirstName( CryptoService.encrypt( user.getFirstName( ), strEncryptionAlgorithme ) );
  1042.         }

  1043.         if ( Boolean.TRUE.equals( anonymizationStatus.get( PARAMETER_LAST_NAME ) ) )
  1044.         {
  1045.             user.setLastName( CryptoService.encrypt( user.getLastName( ), strEncryptionAlgorithme ) );
  1046.         }

  1047.         if ( Boolean.TRUE.equals( anonymizationStatus.get( PARAMETER_EMAIL ) ) )
  1048.         {
  1049.             user.setEmail( CryptoService.encrypt( user.getEmail( ), strEncryptionAlgorithme ) );
  1050.         }

  1051.         user.setStatus( AdminUser.ANONYMIZED_CODE );
  1052.         AdminUserHome.removeAllRightsForUser( nAdminUserId );
  1053.         AdminUserHome.removeAllRolesForUser( nAdminUserId );
  1054.         AdminUserHome.removeAllPasswordHistoryForUser( nAdminUserId );
  1055.         AdminUserHome.update( user );

  1056.         AttributeService attributeService = AttributeService.getInstance( );
  1057.         List<IAttribute> listAllAttributes = attributeService.getAllAttributesWithoutFields( locale );
  1058.         List<IAttribute> listAttributesText = new ArrayList<>( );

  1059.         for ( IAttribute attribut : listAllAttributes )
  1060.         {
  1061.             if ( attribut.isAnonymizable( ) )
  1062.             {
  1063.                 listAttributesText.add( attribut );
  1064.             }
  1065.         }

  1066.         for ( IAttribute attribute : listAttributesText )
  1067.         {
  1068.             List<AdminUserField> listAdminUserField = AdminUserFieldHome.selectUserFieldsByIdUserIdAttribute( nAdminUserId, attribute.getIdAttribute( ) );

  1069.             for ( AdminUserField adminUserField : listAdminUserField )
  1070.             {
  1071.                 adminUserField.setValue( CryptoService.encrypt( adminUserField.getValue( ), strEncryptionAlgorithme ) );
  1072.                 AdminUserFieldHome.update( adminUserField );
  1073.             }
  1074.         }
  1075.     }

  1076.     /**
  1077.      * Get the list of id of expired users
  1078.      *
  1079.      * @return the list of id of expired users
  1080.      */
  1081.     public static List<Integer> getExpiredUserIdList( )
  1082.     {
  1083.         return AdminUserHome.findAllExpiredUserId( );
  1084.     }

  1085.     /**
  1086.      * Update the user expiration date with new values, and notify him with an email if his account was close to expire.
  1087.      *
  1088.      * @param user
  1089.      *            The user to update
  1090.      */
  1091.     public static void updateUserExpirationDate( AdminUser user )
  1092.     {
  1093.         if ( user == null )
  1094.         {
  1095.             return;
  1096.         }

  1097.         Timestamp newExpirationDate = getAccountMaxValidDate( );
  1098.         Timestamp maxValidDate = user.getAccountMaxValidDate( );
  1099.         // We update the user account
  1100.         AdminUserHome.updateUserExpirationDate( user.getUserId( ), newExpirationDate );

  1101.         // We notify the user
  1102.         String strUserMail = user.getEmail( );
  1103.         int nbDaysBeforeFirstAlert = AdminUserService.getIntegerSecurityParameter( DSKEY_TIME_BEFORE_ALERT_ACCOUNT );

  1104.         if ( maxValidDate != null )
  1105.         {
  1106.             Timestamp firstAlertMaxDate = new Timestamp( maxValidDate.getTime( ) - DateUtil.convertDaysInMiliseconds( nbDaysBeforeFirstAlert ) );
  1107.             Timestamp currentTimestamp = new Timestamp( new java.util.Date( ).getTime( ) );

  1108.             if ( ( currentTimestamp.getTime( ) > firstAlertMaxDate.getTime( ) ) && StringUtils.isNotBlank( strUserMail ) )
  1109.             {
  1110.                 AdminUser completeUser = AdminUserHome.findByPrimaryKey( user.getUserId( ) );
  1111.                 String strBody = DatabaseTemplateService.getTemplateFromKey( DSKEY_ACCOUNT_REACTIVATED_MAIL_BODY );

  1112.                 String defaultUserParameter = DefaultUserParameterHome.findByKey( DSKEY_ACCOUNT_REACTIVATED_MAIL_SENDER );
  1113.                 String strSender = ( defaultUserParameter == null ) ? StringUtils.EMPTY : defaultUserParameter;

  1114.                 defaultUserParameter = DefaultUserParameterHome.findByKey( DSKEY_ACCOUNT_REACTIVATED_MAIL_SUBJECT );

  1115.                 String strSubject = ( defaultUserParameter == null ) ? StringUtils.EMPTY : defaultUserParameter;

  1116.                 Map<String, String> model = new HashMap<>( );

  1117.                 DateFormat dateFormat = DateFormat.getDateInstance( DateFormat.SHORT, LocaleService.getDefault( ) );

  1118.                 if ( newExpirationDate != null )
  1119.                 {
  1120.                     String accountMaxValidDate = dateFormat.format( new Date( newExpirationDate.getTime( ) ) );
  1121.                     model.put( MARK_DATE_VALID, accountMaxValidDate );
  1122.                 }
  1123.                 model.put( MARK_NAME, completeUser.getLastName( ) );
  1124.                 model.put( MARK_FIRST_NAME, completeUser.getFirstName( ) );

  1125.                 HtmlTemplate template = AppTemplateService.getTemplateFromStringFtl( strBody, LocaleService.getDefault( ), model );
  1126.                 MailService.sendMailHtml( strUserMail, strSender, strSender, strSubject, template.getHtml( ) );
  1127.             }
  1128.         }
  1129.     }

  1130.     /**
  1131.      * Update the date of last login of an admin user
  1132.      *
  1133.      * @param nIdUser
  1134.      *            Id of the user to update
  1135.      */
  1136.     public static void updateDateLastLogin( int nIdUser )
  1137.     {
  1138.         AdminUserHome.updateDateLastLogin( nIdUser, new Timestamp( new Date( ).getTime( ) ) );
  1139.     }

  1140.     /**
  1141.      * Notify an user by email
  1142.      *
  1143.      * @param strBaseUrl
  1144.      *            The base URL of the webapp
  1145.      * @param user
  1146.      *            The admin user to notify
  1147.      * @param strPropertyEmailSubject
  1148.      *            the property of the subject email
  1149.      * @param strTemplate
  1150.      *            the URL of the HTML Template
  1151.      */
  1152.     public static void notifyUser( String strBaseUrl, AdminUser user, String strPropertyEmailSubject, String strTemplate )
  1153.     {
  1154.         notifyUser( strBaseUrl, user, null, strPropertyEmailSubject, strTemplate );
  1155.     }

  1156.     /**
  1157.      * Notify an user by email
  1158.      *
  1159.      * @param strBaseUrl
  1160.      *            The base URL of the webapp
  1161.      * @param user
  1162.      *            The admin user to notify
  1163.      * @param strPassword
  1164.      *            the user password in cleartext
  1165.      * @param strPropertyEmailSubject
  1166.      *            the property of the subject email
  1167.      * @param strTemplate
  1168.      *            the URL of the HTML Template
  1169.      */
  1170.     public static void notifyUser( String strBaseUrl, AdminUser user, String strPassword, String strPropertyEmailSubject, String strTemplate )
  1171.     {
  1172.         String strSenderEmail = MailService.getNoReplyEmail( );
  1173.         String strSiteName = PortalService.getSiteName( );
  1174.         Locale locale = user.getLocale( );
  1175.         String strEmailSubject = I18nService.getLocalizedString( strPropertyEmailSubject, new String [ ] {
  1176.                 strSiteName
  1177.         }, locale );
  1178.         Map<String, Object> model = new HashMap<>( );
  1179.         model.put( MARK_USER, user );
  1180.         model.put( MARK_PASSWORD, strPassword );
  1181.         model.put( MARK_SITE_NAME, strSiteName );
  1182.         model.put( MARK_LOGIN_URL, strBaseUrl + AdminAuthenticationService.getInstance( ).getLoginPageUrl( ) );
  1183.         model.put( MARK_SITE_LINK, MailService.getSiteLink( strBaseUrl, false ) );

  1184.         HtmlTemplate template = AppTemplateService.getTemplate( strTemplate, locale, model );

  1185.         MailService.sendMailHtml( user.getEmail( ), strSenderEmail, strSenderEmail, strEmailSubject, template.getHtml( ) );
  1186.     }

  1187.     /**
  1188.      * Get a XML string describing a user.<br>
  1189.      * The XML is constructed as follow :<br>
  1190.      * <b>&lt;user&gt;</b><br>
  1191.      * &nbsp;&nbsp;<b>&lt;access_code&gt;</b>value<b>&lt;/value&gt;</b><br>
  1192.      * &nbsp;&nbsp;<b>&lt;last_name&gt;</b>value<b>&gt;/user&gt;</b><br>
  1193.      * &nbsp;&nbsp;<b>&lt;first_name&gt;</b>value<b>&lt;/value&gt;</b><br>
  1194.      * &nbsp;&nbsp;<b>&lt;email&gt;</b>value<b>&lt;/email&gt;</b><br>
  1195.      * &nbsp;&nbsp;<b>&lt;status&gt;</b>value<b>&lt;/status&gt;</b><br>
  1196.      * &nbsp;&nbsp;<b>&lt;locale&gt;</b>value<b>&lt;/locale&gt;</b><br>
  1197.      * &nbsp;&nbsp;<b>&lt;level&gt;</b>value<b>&lt;/level&gt;</b><br>
  1198.      * &nbsp;&nbsp;<b>&lt;must_change_password&gt;</b>value<b>&lt; must_change_password&gt;</b><br>
  1199.      * &nbsp;&nbsp;<b>&lt;accessibility_mode&gt;</b>value<b>&lt; accessibility_mode&gt;</b><br>
  1200.      * &nbsp;&nbsp;<b>&lt;password_max_valid_date&gt;</b>value<b>&lt; password_max_valid_date&gt;</b><br>
  1201.      * &nbsp;&nbsp;<b>&lt;account_max_valid_date&gt;</b>value<b>&lt; account_max_valid_date&gt;</b><br>
  1202.      * &nbsp;&nbsp;<b>&lt;date_last_login&gt;</b>value<b>&lt;/date_last_login&gt;</b><br>
  1203.      * &nbsp;&nbsp;<b>&lt;roles&gt;</b><br>
  1204.      * &nbsp;&nbsp;&nbsp;&nbsp;<b>&lt;role&gt;</b>value<b>&lt;/role&gt;</b><br>
  1205.      * &nbsp;&nbsp;&nbsp;&nbsp;...<br>
  1206.      * &nbsp;&nbsp;<b>&lt;/roles&gt;</b><br>
  1207.      * &nbsp;&nbsp;<b>&lt;rights&gt;</b><br>
  1208.      * &nbsp;&nbsp;&nbsp;&nbsp;<b>&lt;right&gt;</b>value<b>&lt;/right&gt;</b><br>
  1209.      * &nbsp;&nbsp;&nbsp;&nbsp;...<br>
  1210.      * &nbsp;&nbsp;<b>&lt;/rights&gt;</b><br>
  1211.      * &nbsp;&nbsp;<b>&lt;workspaces&gt;</b><br>
  1212.      * &nbsp;&nbsp;&nbsp;&nbsp;<b>&lt;workspace&gt;</b>value<b>&lt;/workspace&gt;</b><br>
  1213.      * &nbsp;&nbsp;&nbsp;&nbsp;...<br>
  1214.      * &nbsp;&nbsp;<b>&lt;/workspaces&gt;</b><br>
  1215.      * &nbsp;&nbsp;<b>&lt;attributes&gt;</b><br>
  1216.      * &nbsp;&nbsp;&nbsp;&nbsp;<b>&lt;attribute&gt;</b><br>
  1217.      * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>&lt;attribute-id&gt;</b>value<b>&lt;/attribute-id&gt;</b><br>
  1218.      * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>&lt;attribute-field-id&gt;</b> value<b>&lt;/attribute-id&gt;</b><br>
  1219.      * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>&lt;attribute-value&gt;</b>value<b >&lt;/attribute-value&gt;</b><br>
  1220.      * &nbsp;&nbsp;&nbsp;&nbsp;<b>&lt;/attribute&gt;</b><br>
  1221.      * &nbsp;&nbsp;&nbsp;&nbsp;...<br>
  1222.      * &nbsp;&nbsp;<b>&lt;/attributes&gt;</b><br>
  1223.      * <b>&lt;/user&gt;</b><br>
  1224.      * <br>
  1225.      * Sections <b>roles</b>, <b>rights</b>, <b>workspaces</b> and <b>attributes</b> are not included if data are not imported
  1226.      *
  1227.      * @param user
  1228.      *            The user to get the XML description of.
  1229.      * @param bIncludeRoles
  1230.      *            True to include roles of the user in the XML, false otherwise.
  1231.      * @param bIncludeRights
  1232.      *            True to include rights of the user in the XML, false otherwise.
  1233.      * @param bIncludeWorkgroups
  1234.      *            True to include workgroups of the user in the XML, false otherwise.
  1235.      * @param bIncludeAttributes
  1236.      *            True to include attributes of the user in the XML, false otherwise.
  1237.      * @param listAttributes
  1238.      *            The list of attributes to include in the XML if attributes are included.
  1239.      * @return A string of XML describing the user.
  1240.      */
  1241.     public static String getXmlFromUser( AdminUser user, boolean bIncludeRoles, boolean bIncludeRights, boolean bIncludeWorkgroups, boolean bIncludeAttributes,
  1242.             List<IAttribute> listAttributes )
  1243.     {
  1244.         StringBuffer sbXml = new StringBuffer( );
  1245.         DateFormat dateFormat = new SimpleDateFormat( );

  1246.         XmlUtil.beginElement( sbXml, CONSTANT_XML_USER );
  1247.         XmlUtil.addElement( sbXml, CONSTANT_XML_ACCESS_CODE, user.getAccessCode( ) );
  1248.         XmlUtil.addElement( sbXml, CONSTANT_XML_LAST_NAME, user.getLastName( ) );
  1249.         XmlUtil.addElement( sbXml, CONSTANT_XML_FIRST_NAME, user.getFirstName( ) );
  1250.         XmlUtil.addElement( sbXml, CONSTANT_XML_EMAIL, user.getEmail( ) );
  1251.         XmlUtil.addElement( sbXml, CONSTANT_XML_STATUS, Integer.toString( user.getRealStatus( ) ) );
  1252.         XmlUtil.addElement( sbXml, CONSTANT_XML_LOCALE, user.getLocale( ).toString( ) );
  1253.         XmlUtil.addElement( sbXml, CONSTANT_XML_LEVEL, Integer.toString( user.getUserLevel( ) ) );
  1254.         XmlUtil.addElement( sbXml, CONSTANT_XML_MUST_CHANGE_PASSWORD, Boolean.toString( user.isPasswordReset( ) ) );
  1255.         XmlUtil.addElement( sbXml, CONSTANT_XML_ACCESSIBILITY_MODE, Boolean.toString( user.getAccessibilityMode( ) ) );

  1256.         String strPasswordMaxValidDate = Optional.ofNullable( user.getPasswordMaxValidDate( ) ).map( dateFormat::format ).orElse( StringUtils.EMPTY );
  1257.         XmlUtil.addElement( sbXml, CONSTANT_XML_PASSWORD_MAX_VALID_DATE, strPasswordMaxValidDate );

  1258.         String strAccountMaxValidDate = Optional.ofNullable( user.getAccountMaxValidDate( ) ).map( dateFormat::format ).orElse( StringUtils.EMPTY );
  1259.         XmlUtil.addElement( sbXml, CONSTANT_XML_ACCOUNT_MAX_VALID_DATE, strAccountMaxValidDate );

  1260.         String strDateLastLogin = Optional.ofNullable( user.getDateLastLogin( ) ).map( dateFormat::format ).orElse( StringUtils.EMPTY );
  1261.         XmlUtil.addElement( sbXml, CONSTANT_XML_DATE_LAST_LOGIN, strDateLastLogin );

  1262.         if ( bIncludeRoles )
  1263.         {
  1264.             Map<String, RBACRole> mapRoles = AdminUserHome.getRolesListForUser( user.getUserId( ) );
  1265.             XmlUtil.beginElement( sbXml, CONSTANT_XML_ROLES );
  1266.             mapRoles.keySet( ).forEach( s -> XmlUtil.addElement( sbXml, CONSTANT_XML_ROLE, s ) );
  1267.             XmlUtil.endElement( sbXml, CONSTANT_XML_ROLES );
  1268.         }

  1269.         if ( bIncludeRights )
  1270.         {
  1271.             Map<String, Right> mapRights = AdminUserHome.getRightsListForUser( user.getUserId( ) );
  1272.             XmlUtil.beginElement( sbXml, CONSTANT_XML_RIGHTS );
  1273.             mapRights.keySet( ).forEach( s -> XmlUtil.addElement( sbXml, CONSTANT_XML_RIGHT, s ) );
  1274.             XmlUtil.endElement( sbXml, CONSTANT_XML_RIGHTS );
  1275.         }

  1276.         if ( bIncludeWorkgroups )
  1277.         {
  1278.             ReferenceList refListWorkgroups = AdminWorkgroupHome.getUserWorkgroups( user );
  1279.             XmlUtil.beginElement( sbXml, CONSTANT_XML_WORKGROUPS );
  1280.             refListWorkgroups.forEach( ri -> XmlUtil.addElement( sbXml, CONSTANT_XML_WORKGROUP, ri.getCode( ) ) );
  1281.             XmlUtil.endElement( sbXml, CONSTANT_XML_WORKGROUPS );
  1282.         }

  1283.         if ( bIncludeAttributes )
  1284.         {
  1285.             Map<String, Object> mapAttributes = AdminUserFieldService.getAdminUserFields( listAttributes, user.getUserId( ), LocaleService.getDefault( ) );
  1286.             XmlUtil.beginElement( sbXml, CONSTANT_XML_ATTRIBUTES );

  1287.             for ( Entry<String, Object> entry : mapAttributes.entrySet( ) )
  1288.             {
  1289.                 String strAttributeKey = entry.getKey( );
  1290.                 Object value = entry.getValue( );

  1291.                 if ( value instanceof List<?> )
  1292.                 {
  1293.                     List<AdminUserField> listFields = (List<AdminUserField>) value;
  1294.                     listFields = listFields.stream( ).filter( auf -> auf.getIdUserField( ) > 0 ).collect( Collectors.toList( ) );

  1295.                     for ( AdminUserField adminUserFields : listFields )
  1296.                     {
  1297.                         XmlUtil.beginElement( sbXml, CONSTANT_XML_ATTRIBUTE );
  1298.                         XmlUtil.addElement( sbXml, CONSTANT_XML_ATTRIBUTE_ID, strAttributeKey );
  1299.                         XmlUtil.addElement( sbXml, CONSTANT_XML_ATTRIBUTE_FIELD_ID, adminUserFields.getAttributeField( ).getIdField( ) );
  1300.                         XmlUtil.addElement( sbXml, CONSTANT_XML_ATTRIBUTE_VALUE, adminUserFields.getValue( ) );
  1301.                         XmlUtil.endElement( sbXml, CONSTANT_XML_ATTRIBUTE );
  1302.                     }
  1303.                 }
  1304.             }

  1305.             XmlUtil.endElement( sbXml, CONSTANT_XML_ATTRIBUTES );
  1306.         }

  1307.         XmlUtil.endElement( sbXml, CONSTANT_XML_USER );

  1308.         return sbXml.toString( );
  1309.     }

  1310.     /**
  1311.      * Get a user reset password token
  1312.      *
  1313.      * @param user
  1314.      *            the user
  1315.      * @param timestamp
  1316.      *            the timestamp of the token
  1317.      * @param request
  1318.      *            he request
  1319.      * @return the reset password token
  1320.      */
  1321.     public static String getUserPasswordResetToken( AdminUser user, Date timestamp, HttpServletRequest request )
  1322.     {
  1323.         String strSessionId = null;
  1324.         if ( getBooleanSecurityParameter( DSKEY_LOCK_RESET_TOKEN_TO_SESSION ) )
  1325.         {
  1326.             strSessionId = request.getSession( ).getId( );
  1327.         }
  1328.         return AdminUserHome.getUserPasswordResetToken( user.getUserId( ), timestamp, strSessionId );
  1329.     }

  1330. }