001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.service.impl;
016    
017    import com.liferay.mail.service.MailService;
018    import com.liferay.portal.exception.CompanyMaxUsersException;
019    import com.liferay.portal.exception.ContactBirthdayException;
020    import com.liferay.portal.exception.ContactNameException;
021    import com.liferay.portal.exception.DuplicateOpenIdException;
022    import com.liferay.portal.exception.GroupFriendlyURLException;
023    import com.liferay.portal.exception.ModelListenerException;
024    import com.liferay.portal.exception.NoSuchImageException;
025    import com.liferay.portal.exception.NoSuchOrganizationException;
026    import com.liferay.portal.exception.NoSuchTicketException;
027    import com.liferay.portal.exception.NoSuchUserException;
028    import com.liferay.portal.exception.PasswordExpiredException;
029    import com.liferay.portal.exception.RequiredUserException;
030    import com.liferay.portal.exception.SendPasswordException;
031    import com.liferay.portal.exception.UserEmailAddressException;
032    import com.liferay.portal.exception.UserIdException;
033    import com.liferay.portal.exception.UserLockoutException;
034    import com.liferay.portal.exception.UserPasswordException;
035    import com.liferay.portal.exception.UserReminderQueryException;
036    import com.liferay.portal.exception.UserScreenNameException;
037    import com.liferay.portal.exception.UserSmsException;
038    import com.liferay.portal.kernel.bean.BeanReference;
039    import com.liferay.portal.kernel.cache.PortalCache;
040    import com.liferay.portal.kernel.cache.PortalCacheMapSynchronizeUtil;
041    import com.liferay.portal.kernel.cache.PortalCacheMapSynchronizeUtil.Synchronizer;
042    import com.liferay.portal.kernel.dao.orm.EntityCacheUtil;
043    import com.liferay.portal.kernel.dao.orm.QueryUtil;
044    import com.liferay.portal.kernel.dao.orm.WildcardMode;
045    import com.liferay.portal.kernel.exception.PortalException;
046    import com.liferay.portal.kernel.exception.SystemException;
047    import com.liferay.portal.kernel.language.LanguageUtil;
048    import com.liferay.portal.kernel.log.Log;
049    import com.liferay.portal.kernel.log.LogFactoryUtil;
050    import com.liferay.portal.kernel.messaging.DestinationNames;
051    import com.liferay.portal.kernel.messaging.Message;
052    import com.liferay.portal.kernel.messaging.MessageBusUtil;
053    import com.liferay.portal.kernel.search.BaseModelSearchResult;
054    import com.liferay.portal.kernel.search.Hits;
055    import com.liferay.portal.kernel.search.Indexer;
056    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
057    import com.liferay.portal.kernel.search.QueryConfig;
058    import com.liferay.portal.kernel.search.SearchContext;
059    import com.liferay.portal.kernel.search.SearchException;
060    import com.liferay.portal.kernel.search.Sort;
061    import com.liferay.portal.kernel.security.auth.Authenticator;
062    import com.liferay.portal.kernel.security.auth.EmailAddressGenerator;
063    import com.liferay.portal.kernel.security.auth.EmailAddressValidator;
064    import com.liferay.portal.kernel.security.auth.FullNameDefinition;
065    import com.liferay.portal.kernel.security.auth.FullNameDefinitionFactory;
066    import com.liferay.portal.kernel.security.auth.FullNameGenerator;
067    import com.liferay.portal.kernel.security.auth.FullNameGeneratorFactory;
068    import com.liferay.portal.kernel.security.auth.FullNameValidator;
069    import com.liferay.portal.kernel.security.auth.PasswordModificationThreadLocal;
070    import com.liferay.portal.kernel.security.auth.PrincipalException;
071    import com.liferay.portal.kernel.security.auth.PrincipalThreadLocal;
072    import com.liferay.portal.kernel.security.auth.ScreenNameGenerator;
073    import com.liferay.portal.kernel.security.auth.ScreenNameValidator;
074    import com.liferay.portal.kernel.security.ldap.LDAPSettingsUtil;
075    import com.liferay.portal.kernel.security.pwd.PasswordEncryptorUtil;
076    import com.liferay.portal.kernel.spring.aop.Skip;
077    import com.liferay.portal.kernel.transaction.Propagation;
078    import com.liferay.portal.kernel.transaction.TransactionCommitCallbackUtil;
079    import com.liferay.portal.kernel.transaction.Transactional;
080    import com.liferay.portal.kernel.util.ArrayUtil;
081    import com.liferay.portal.kernel.util.Digester;
082    import com.liferay.portal.kernel.util.DigesterUtil;
083    import com.liferay.portal.kernel.util.GetterUtil;
084    import com.liferay.portal.kernel.util.KeyValuePair;
085    import com.liferay.portal.kernel.util.ListUtil;
086    import com.liferay.portal.kernel.util.LocaleUtil;
087    import com.liferay.portal.kernel.util.LocalizationUtil;
088    import com.liferay.portal.kernel.util.MapUtil;
089    import com.liferay.portal.kernel.util.OrderByComparator;
090    import com.liferay.portal.kernel.util.ParamUtil;
091    import com.liferay.portal.kernel.util.PropsKeys;
092    import com.liferay.portal.kernel.util.PwdGenerator;
093    import com.liferay.portal.kernel.util.SetUtil;
094    import com.liferay.portal.kernel.util.StringBundler;
095    import com.liferay.portal.kernel.util.StringPool;
096    import com.liferay.portal.kernel.util.StringUtil;
097    import com.liferay.portal.kernel.util.UnicodeProperties;
098    import com.liferay.portal.kernel.util.Validator;
099    import com.liferay.portal.kernel.workflow.WorkflowConstants;
100    import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
101    import com.liferay.portal.kernel.workflow.WorkflowThreadLocal;
102    import com.liferay.portal.model.Account;
103    import com.liferay.portal.model.Company;
104    import com.liferay.portal.model.CompanyConstants;
105    import com.liferay.portal.model.Contact;
106    import com.liferay.portal.model.ContactConstants;
107    import com.liferay.portal.model.Group;
108    import com.liferay.portal.model.GroupConstants;
109    import com.liferay.portal.model.Layout;
110    import com.liferay.portal.model.Organization;
111    import com.liferay.portal.model.PasswordPolicy;
112    import com.liferay.portal.model.ResourceConstants;
113    import com.liferay.portal.model.Role;
114    import com.liferay.portal.model.RoleConstants;
115    import com.liferay.portal.model.Team;
116    import com.liferay.portal.model.Ticket;
117    import com.liferay.portal.model.TicketConstants;
118    import com.liferay.portal.model.User;
119    import com.liferay.portal.model.UserGroup;
120    import com.liferay.portal.model.UserGroupRole;
121    import com.liferay.portal.model.impl.LayoutImpl;
122    import com.liferay.portal.model.impl.UserCacheModel;
123    import com.liferay.portal.model.impl.UserImpl;
124    import com.liferay.portal.security.auth.AuthPipeline;
125    import com.liferay.portal.security.auth.EmailAddressGeneratorFactory;
126    import com.liferay.portal.security.auth.EmailAddressValidatorFactory;
127    import com.liferay.portal.security.auth.FullNameValidatorFactory;
128    import com.liferay.portal.security.auth.ScreenNameGeneratorFactory;
129    import com.liferay.portal.security.auth.ScreenNameValidatorFactory;
130    import com.liferay.portal.security.permission.PermissionCacheUtil;
131    import com.liferay.portal.security.pwd.PwdAuthenticator;
132    import com.liferay.portal.security.pwd.PwdToolkitUtil;
133    import com.liferay.portal.security.pwd.RegExpToolkit;
134    import com.liferay.portal.service.BaseServiceImpl;
135    import com.liferay.portal.service.ServiceContext;
136    import com.liferay.portal.service.ServiceContextThreadLocal;
137    import com.liferay.portal.service.base.UserLocalServiceBaseImpl;
138    import com.liferay.portal.util.PortalUtil;
139    import com.liferay.portal.util.PrefsPropsUtil;
140    import com.liferay.portal.util.PropsValues;
141    import com.liferay.portal.util.SubscriptionSender;
142    import com.liferay.portlet.messageboards.model.MBMessage;
143    import com.liferay.portlet.social.model.SocialRelation;
144    import com.liferay.portlet.social.model.SocialRelationConstants;
145    import com.liferay.users.admin.kernel.util.UsersAdminUtil;
146    import com.liferay.util.Encryptor;
147    import com.liferay.util.EncryptorException;
148    
149    import java.io.Serializable;
150    
151    import java.util.ArrayList;
152    import java.util.Arrays;
153    import java.util.Calendar;
154    import java.util.Collections;
155    import java.util.Date;
156    import java.util.HashMap;
157    import java.util.HashSet;
158    import java.util.LinkedHashMap;
159    import java.util.List;
160    import java.util.Locale;
161    import java.util.Map;
162    import java.util.Set;
163    import java.util.concurrent.Callable;
164    import java.util.concurrent.ConcurrentHashMap;
165    
166    import javax.portlet.PortletPreferences;
167    
168    /**
169     * Provides the local service for accessing, adding, authenticating, deleting,
170     * and updating users.
171     *
172     * @author Brian Wing Shun Chan
173     * @author Scott Lee
174     * @author Raymond Augé
175     * @author Jorge Ferrer
176     * @author Julio Camarero
177     * @author Wesley Gong
178     * @author Zsigmond Rab
179     */
180    public class UserLocalServiceImpl extends UserLocalServiceBaseImpl {
181    
182            /**
183             * Adds a default admin user for the company.
184             *
185             * @param  companyId the primary key of the user's company
186             * @param  screenName the user's screen name
187             * @param  emailAddress the user's email address
188             * @param  locale the user's locale
189             * @param  firstName the user's first name
190             * @param  middleName the user's middle name
191             * @param  lastName the user's last name
192             * @return the new default admin user
193             */
194            @Override
195            public User addDefaultAdminUser(
196                            long companyId, String screenName, String emailAddress,
197                            Locale locale, String firstName, String middleName, String lastName)
198                    throws PortalException {
199    
200                    long creatorUserId = 0;
201                    boolean autoPassword = false;
202                    String password1 = PropsValues.DEFAULT_ADMIN_PASSWORD;
203                    String password2 = password1;
204                    boolean autoScreenName = false;
205    
206                    screenName = getLogin(screenName);
207    
208                    for (int i = 1;; i++) {
209                            User screenNameUser = userPersistence.fetchByC_SN(
210                                    companyId, screenName);
211    
212                            if (screenNameUser == null) {
213                                    break;
214                            }
215    
216                            screenName = screenName + i;
217                    }
218    
219                    long facebookId = 0;
220                    String openId = StringPool.BLANK;
221                    long prefixId = 0;
222                    long suffixId = 0;
223                    boolean male = true;
224                    int birthdayMonth = Calendar.JANUARY;
225                    int birthdayDay = 1;
226                    int birthdayYear = 1970;
227                    String jobTitle = StringPool.BLANK;
228    
229                    Group guestGroup = groupLocalService.getGroup(
230                            companyId, GroupConstants.GUEST);
231    
232                    long[] groupIds = {guestGroup.getGroupId()};
233    
234                    long[] organizationIds = null;
235    
236                    Role adminRole = roleLocalService.getRole(
237                            companyId, RoleConstants.ADMINISTRATOR);
238    
239                    Role powerUserRole = roleLocalService.getRole(
240                            companyId, RoleConstants.POWER_USER);
241    
242                    long[] roleIds = {adminRole.getRoleId(), powerUserRole.getRoleId()};
243    
244                    long[] userGroupIds = null;
245                    boolean sendEmail = false;
246                    ServiceContext serviceContext = new ServiceContext();
247    
248                    User defaultAdminUser = addUser(
249                            creatorUserId, companyId, autoPassword, password1, password2,
250                            autoScreenName, screenName, emailAddress, facebookId, openId,
251                            locale, firstName, middleName, lastName, prefixId, suffixId, male,
252                            birthdayMonth, birthdayDay, birthdayYear, jobTitle, groupIds,
253                            organizationIds, roleIds, userGroupIds, sendEmail, serviceContext);
254    
255                    updateEmailAddressVerified(defaultAdminUser.getUserId(), true);
256    
257                    updateLastLogin(
258                            defaultAdminUser.getUserId(), defaultAdminUser.getLoginIP());
259    
260                    updatePasswordReset(defaultAdminUser.getUserId(), false);
261    
262                    return defaultAdminUser;
263            }
264    
265            /**
266             * Adds the user to the default groups, unless the user is already in these
267             * groups. The default groups can be specified in
268             * <code>portal.properties</code> with the key
269             * <code>admin.default.group.names</code>.
270             *
271             * @param userId the primary key of the user
272             */
273            @Override
274            public void addDefaultGroups(long userId) throws PortalException {
275                    User user = userPersistence.findByPrimaryKey(userId);
276    
277                    Set<Long> groupIdsSet = new HashSet<>();
278    
279                    String[] defaultGroupNames = PrefsPropsUtil.getStringArray(
280                            user.getCompanyId(), PropsKeys.ADMIN_DEFAULT_GROUP_NAMES,
281                            StringPool.NEW_LINE, PropsValues.ADMIN_DEFAULT_GROUP_NAMES);
282    
283                    for (String defaultGroupName : defaultGroupNames) {
284                            Company company = companyPersistence.findByPrimaryKey(
285                                    user.getCompanyId());
286    
287                            Account account = company.getAccount();
288    
289                            if (StringUtil.equalsIgnoreCase(
290                                            defaultGroupName, account.getName())) {
291    
292                                    defaultGroupName = GroupConstants.GUEST;
293                            }
294    
295                            Group group = groupPersistence.fetchByC_GK(
296                                    user.getCompanyId(), defaultGroupName);
297    
298                            if ((group != null) &&
299                                    !userPersistence.containsGroup(
300                                            userId, group.getGroupId())) {
301    
302                                    groupIdsSet.add(group.getGroupId());
303                            }
304                    }
305    
306                    String[] defaultOrganizationGroupNames = PrefsPropsUtil.getStringArray(
307                            user.getCompanyId(),
308                            PropsKeys.ADMIN_DEFAULT_ORGANIZATION_GROUP_NAMES,
309                            StringPool.NEW_LINE,
310                            PropsValues.ADMIN_DEFAULT_ORGANIZATION_GROUP_NAMES);
311    
312                    for (String defaultOrganizationGroupName :
313                                    defaultOrganizationGroupNames) {
314    
315                            defaultOrganizationGroupName +=
316                                    GroupLocalServiceImpl.ORGANIZATION_NAME_SUFFIX;
317    
318                            Group group = groupPersistence.fetchByC_GK(
319                                    user.getCompanyId(), defaultOrganizationGroupName);
320    
321                            if ((group != null) &&
322                                    !userPersistence.containsGroup(
323                                            userId, group.getGroupId())) {
324    
325                                    groupIdsSet.add(group.getGroupId());
326                            }
327                    }
328    
329                    long[] groupIds = ArrayUtil.toArray(
330                            groupIdsSet.toArray(new Long[groupIdsSet.size()]));
331    
332                    groupLocalService.addUserGroups(userId, groupIds);
333            }
334    
335            /**
336             * Adds the user to the default regular roles, unless the user already has
337             * these regular roles. The default regular roles can be specified in
338             * <code>portal.properties</code> with the key
339             * <code>admin.default.role.names</code>.
340             *
341             * @param userId the primary key of the user
342             */
343            @Override
344            public void addDefaultRoles(long userId) throws PortalException {
345                    User user = userPersistence.findByPrimaryKey(userId);
346    
347                    Set<Long> roleIdSet = new HashSet<>();
348    
349                    String[] defaultRoleNames = PrefsPropsUtil.getStringArray(
350                            user.getCompanyId(), PropsKeys.ADMIN_DEFAULT_ROLE_NAMES,
351                            StringPool.NEW_LINE, PropsValues.ADMIN_DEFAULT_ROLE_NAMES);
352    
353                    for (String defaultRoleName : defaultRoleNames) {
354                            Role role = rolePersistence.fetchByC_N(
355                                    user.getCompanyId(), defaultRoleName);
356    
357                            if ((role != null) &&
358                                    (role.getType() == RoleConstants.TYPE_REGULAR) &&
359                                    !userPersistence.containsRole(userId, role.getRoleId())) {
360    
361                                    roleIdSet.add(role.getRoleId());
362                            }
363                    }
364    
365                    long[] roleIds = ArrayUtil.toArray(
366                            roleIdSet.toArray(new Long[roleIdSet.size()]));
367    
368                    roleIds = UsersAdminUtil.addRequiredRoles(user, roleIds);
369    
370                    userPersistence.addRoles(userId, roleIds);
371            }
372    
373            /**
374             * Adds the user to the default user groups, unless the user is already in
375             * these user groups. The default user groups can be specified in
376             * <code>portal.properties</code> with the property
377             * <code>admin.default.user.group.names</code>.
378             *
379             * @param userId the primary key of the user
380             */
381            @Override
382            @SuppressWarnings("deprecation")
383            public void addDefaultUserGroups(long userId) throws PortalException {
384                    User user = userPersistence.findByPrimaryKey(userId);
385    
386                    Set<Long> userGroupIdSet = new HashSet<>();
387    
388                    String[] defaultUserGroupNames = PrefsPropsUtil.getStringArray(
389                            user.getCompanyId(), PropsKeys.ADMIN_DEFAULT_USER_GROUP_NAMES,
390                            StringPool.NEW_LINE, PropsValues.ADMIN_DEFAULT_USER_GROUP_NAMES);
391    
392                    for (String defaultUserGroupName : defaultUserGroupNames) {
393                            UserGroup userGroup = userGroupPersistence.fetchByC_N(
394                                    user.getCompanyId(), defaultUserGroupName);
395    
396                            if ((userGroup != null) &&
397                                    !userPersistence.containsUserGroup(
398                                            userId, userGroup.getUserGroupId())) {
399    
400                                    userGroupIdSet.add(userGroup.getUserGroupId());
401                            }
402                    }
403    
404                    long[] userGroupIds = ArrayUtil.toArray(
405                            userGroupIdSet.toArray(new Long[userGroupIdSet.size()]));
406    
407                    if (PropsValues.USER_GROUPS_COPY_LAYOUTS_TO_USER_PERSONAL_SITE) {
408                            for (long userGroupId : userGroupIds) {
409                                    userGroupLocalService.copyUserGroupLayouts(userGroupId, userId);
410                            }
411                    }
412    
413                    userPersistence.addUserGroups(userId, userGroupIds);
414            }
415    
416            /**
417             * Adds the users to the group.
418             *
419             * @param groupId the primary key of the group
420             * @param userIds the primary keys of the users
421             */
422            @Override
423            public void addGroupUsers(long groupId, long[] userIds)
424                    throws PortalException {
425    
426                    groupPersistence.addUsers(groupId, userIds);
427    
428                    reindex(userIds);
429    
430                    PermissionCacheUtil.clearCache(userIds);
431    
432                    addDefaultRolesAndTeams(groupId, userIds);
433            }
434    
435            /**
436             * Adds the users to the organization.
437             *
438             * @param organizationId the primary key of the organization
439             * @param userIds the primary keys of the users
440             */
441            @Override
442            public void addOrganizationUsers(long organizationId, long[] userIds)
443                    throws PortalException {
444    
445                    organizationPersistence.addUsers(organizationId, userIds);
446    
447                    reindex(userIds);
448    
449                    PermissionCacheUtil.clearCache(userIds);
450            }
451    
452            /**
453             * Assigns the password policy to the users, removing any other currently
454             * assigned password policies.
455             *
456             * @param passwordPolicyId the primary key of the password policy
457             * @param userIds the primary keys of the users
458             */
459            @Override
460            public void addPasswordPolicyUsers(long passwordPolicyId, long[] userIds) {
461                    passwordPolicyRelLocalService.addPasswordPolicyRels(
462                            passwordPolicyId, User.class.getName(), userIds);
463            }
464    
465            /**
466             * Adds the users to the role.
467             *
468             * @param roleId the primary key of the role
469             * @param userIds the primary keys of the users
470             */
471            @Override
472            public void addRoleUsers(long roleId, long[] userIds)
473                    throws PortalException {
474    
475                    rolePersistence.addUsers(roleId, userIds);
476    
477                    reindex(userIds);
478    
479                    PermissionCacheUtil.clearCache(userIds);
480            }
481    
482            /**
483             * Adds the users to the team.
484             *
485             * @param teamId the primary key of the team
486             * @param userIds the primary keys of the users
487             */
488            @Override
489            public void addTeamUsers(long teamId, long[] userIds)
490                    throws PortalException {
491    
492                    teamPersistence.addUsers(teamId, userIds);
493    
494                    reindex(userIds);
495    
496                    PermissionCacheUtil.clearCache(userIds);
497            }
498    
499            /**
500             * Adds a user.
501             *
502             * <p>
503             * This method handles the creation and bookkeeping of the user including
504             * its resources, metadata, and internal data structures. It is not
505             * necessary to make subsequent calls to any methods to setup default
506             * groups, resources, etc.
507             * </p>
508             *
509             * @param  creatorUserId the primary key of the creator
510             * @param  companyId the primary key of the user's company
511             * @param  autoPassword whether a password should be automatically generated
512             *         for the user
513             * @param  password1 the user's password
514             * @param  password2 the user's password confirmation
515             * @param  autoScreenName whether a screen name should be automatically
516             *         generated for the user
517             * @param  screenName the user's screen name
518             * @param  emailAddress the user's email address
519             * @param  facebookId the user's facebook ID
520             * @param  openId the user's OpenID
521             * @param  locale the user's locale
522             * @param  firstName the user's first name
523             * @param  middleName the user's middle name
524             * @param  lastName the user's last name
525             * @param  prefixId the user's name prefix ID
526             * @param  suffixId the user's name suffix ID
527             * @param  male whether the user is male
528             * @param  birthdayMonth the user's birthday month (0-based, meaning 0 for
529             *         January)
530             * @param  birthdayDay the user's birthday day
531             * @param  birthdayYear the user's birthday year
532             * @param  jobTitle the user's job title
533             * @param  groupIds the primary keys of the user's groups
534             * @param  organizationIds the primary keys of the user's organizations
535             * @param  roleIds the primary keys of the roles this user possesses
536             * @param  userGroupIds the primary keys of the user's user groups
537             * @param  sendEmail whether to send the user an email notification about
538             *         their new account
539             * @param  serviceContext the service context to be applied (optionally
540             *         <code>null</code>). Can set the UUID (with the <code>uuid</code>
541             *         attribute), asset category IDs, asset tag names, and expando
542             *         bridge attributes for the user.
543             * @return the new user
544             */
545            @Override
546            public User addUser(
547                            long creatorUserId, long companyId, boolean autoPassword,
548                            String password1, String password2, boolean autoScreenName,
549                            String screenName, String emailAddress, long facebookId,
550                            String openId, Locale locale, String firstName, String middleName,
551                            String lastName, long prefixId, long suffixId, boolean male,
552                            int birthdayMonth, int birthdayDay, int birthdayYear,
553                            String jobTitle, long[] groupIds, long[] organizationIds,
554                            long[] roleIds, long[] userGroupIds, boolean sendEmail,
555                            ServiceContext serviceContext)
556                    throws PortalException {
557    
558                    boolean workflowEnabled = WorkflowThreadLocal.isEnabled();
559    
560                    try {
561                            WorkflowThreadLocal.setEnabled(false);
562    
563                            if (serviceContext == null) {
564                                    serviceContext = new ServiceContext();
565                            }
566    
567                            if (serviceContext.getWorkflowAction() !=
568                                            WorkflowConstants.ACTION_PUBLISH) {
569    
570                                    serviceContext.setWorkflowAction(
571                                            WorkflowConstants.ACTION_PUBLISH);
572                            }
573    
574                            return addUserWithWorkflow(
575                                    creatorUserId, companyId, autoPassword, password1, password2,
576                                    autoScreenName, screenName, emailAddress, facebookId, openId,
577                                    locale, firstName, middleName, lastName, prefixId, suffixId,
578                                    male, birthdayMonth, birthdayDay, birthdayYear, jobTitle,
579                                    groupIds, organizationIds, roleIds, userGroupIds, sendEmail,
580                                    serviceContext);
581                    }
582                    finally {
583                            WorkflowThreadLocal.setEnabled(workflowEnabled);
584                    }
585            }
586    
587            /**
588             * Adds the users to the user group.
589             *
590             * @param userGroupId the primary key of the user group
591             * @param userIds the primary keys of the users
592             */
593            @Override
594            @SuppressWarnings("deprecation")
595            public void addUserGroupUsers(long userGroupId, long[] userIds)
596                    throws PortalException {
597    
598                    if (PropsValues.USER_GROUPS_COPY_LAYOUTS_TO_USER_PERSONAL_SITE) {
599                            userGroupLocalService.copyUserGroupLayouts(userGroupId, userIds);
600                    }
601    
602                    userGroupPersistence.addUsers(userGroupId, userIds);
603    
604                    reindex(userIds);
605    
606                    PermissionCacheUtil.clearCache(userIds);
607            }
608    
609            /**
610             * Adds a user with workflow.
611             *
612             * <p>
613             * This method handles the creation and bookkeeping of the user including
614             * its resources, metadata, and internal data structures. It is not
615             * necessary to make subsequent calls to any methods to setup default
616             * groups, resources, etc.
617             * </p>
618             *
619             * @param  creatorUserId the primary key of the creator
620             * @param  companyId the primary key of the user's company
621             * @param  autoPassword whether a password should be automatically generated
622             *         for the user
623             * @param  password1 the user's password
624             * @param  password2 the user's password confirmation
625             * @param  autoScreenName whether a screen name should be automatically
626             *         generated for the user
627             * @param  screenName the user's screen name
628             * @param  emailAddress the user's email address
629             * @param  facebookId the user's facebook ID
630             * @param  openId the user's OpenID
631             * @param  locale the user's locale
632             * @param  firstName the user's first name
633             * @param  middleName the user's middle name
634             * @param  lastName the user's last name
635             * @param  prefixId the user's name prefix ID
636             * @param  suffixId the user's name suffix ID
637             * @param  male whether the user is male
638             * @param  birthdayMonth the user's birthday month (0-based, meaning 0 for
639             *         January)
640             * @param  birthdayDay the user's birthday day
641             * @param  birthdayYear the user's birthday year
642             * @param  jobTitle the user's job title
643             * @param  groupIds the primary keys of the user's groups
644             * @param  organizationIds the primary keys of the user's organizations
645             * @param  roleIds the primary keys of the roles this user possesses
646             * @param  userGroupIds the primary keys of the user's user groups
647             * @param  sendEmail whether to send the user an email notification about
648             *         their new account
649             * @param  serviceContext the service context to be applied (optionally
650             *         <code>null</code>). Can set the UUID (with the <code>uuid</code>
651             *         attribute), asset category IDs, asset tag names, and expando
652             *         bridge attributes for the user.
653             * @return the new user
654             */
655            @Override
656            @SuppressWarnings("deprecation")
657            public User addUserWithWorkflow(
658                            long creatorUserId, long companyId, boolean autoPassword,
659                            String password1, String password2, boolean autoScreenName,
660                            String screenName, String emailAddress, long facebookId,
661                            String openId, Locale locale, String firstName, String middleName,
662                            String lastName, long prefixId, long suffixId, boolean male,
663                            int birthdayMonth, int birthdayDay, int birthdayYear,
664                            String jobTitle, long[] groupIds, long[] organizationIds,
665                            long[] roleIds, long[] userGroupIds, boolean sendEmail,
666                            ServiceContext serviceContext)
667                    throws PortalException {
668    
669                    // User
670    
671                    Company company = companyPersistence.findByPrimaryKey(companyId);
672                    screenName = getLogin(screenName);
673                    openId = StringUtil.trim(openId);
674    
675                    if (PrefsPropsUtil.getBoolean(
676                                    companyId, PropsKeys.USERS_SCREEN_NAME_ALWAYS_AUTOGENERATE)) {
677    
678                            autoScreenName = true;
679                    }
680    
681                    // PLACEHOLDER 01
682    
683                    long userId = counterLocalService.increment();
684    
685                    EmailAddressGenerator emailAddressGenerator =
686                            EmailAddressGeneratorFactory.getInstance();
687    
688                    if ((emailAddress == null) ||
689                            emailAddressGenerator.isGenerated(emailAddress)) {
690    
691                            emailAddress = StringPool.BLANK;
692                    }
693                    else {
694                            emailAddress = StringUtil.toLowerCase(emailAddress.trim());
695                    }
696    
697                    if (!PrefsPropsUtil.getBoolean(
698                                    companyId, PropsKeys.USERS_EMAIL_ADDRESS_REQUIRED) &&
699                            Validator.isNull(emailAddress)) {
700    
701                            emailAddress = emailAddressGenerator.generate(companyId, userId);
702                    }
703    
704                    validate(
705                            companyId, userId, autoPassword, password1, password2,
706                            autoScreenName, screenName, emailAddress, openId, firstName,
707                            middleName, lastName, organizationIds, locale);
708    
709                    if (!autoPassword) {
710                            if (Validator.isNull(password1) || Validator.isNull(password2)) {
711                                    throw new UserPasswordException.MustNotBeNull(userId);
712                            }
713                    }
714    
715                    if (autoScreenName) {
716                            ScreenNameGenerator screenNameGenerator =
717                                    ScreenNameGeneratorFactory.getInstance();
718    
719                            try {
720                                    screenName = screenNameGenerator.generate(
721                                            companyId, userId, emailAddress);
722                            }
723                            catch (Exception e) {
724                                    throw new SystemException(e);
725                            }
726                    }
727    
728                    User defaultUser = getDefaultUser(companyId);
729    
730                    FullNameGenerator fullNameGenerator =
731                            FullNameGeneratorFactory.getInstance();
732    
733                    String fullName = fullNameGenerator.getFullName(
734                            firstName, middleName, lastName);
735    
736                    String greeting = LanguageUtil.format(
737                            locale, "welcome-x", fullName, false);
738    
739                    User user = userPersistence.create(userId);
740    
741                    if (serviceContext != null) {
742                            String uuid = serviceContext.getUuid();
743    
744                            if (Validator.isNotNull(uuid)) {
745                                    user.setUuid(uuid);
746                            }
747                    }
748    
749                    user.setCompanyId(companyId);
750                    user.setDefaultUser(false);
751                    user.setContactId(counterLocalService.increment());
752    
753                    if (Validator.isNotNull(password1)) {
754                            user.setPassword(PasswordEncryptorUtil.encrypt(password1));
755                            user.setPasswordUnencrypted(password1);
756                    }
757    
758                    user.setPasswordEncrypted(true);
759    
760                    PasswordPolicy passwordPolicy = defaultUser.getPasswordPolicy();
761    
762                    if ((passwordPolicy != null) && passwordPolicy.isChangeable() &&
763                            passwordPolicy.isChangeRequired()) {
764    
765                            user.setPasswordReset(true);
766                    }
767                    else {
768                            user.setPasswordReset(false);
769                    }
770    
771                    user.setDigest(StringPool.BLANK);
772                    user.setScreenName(screenName);
773                    user.setEmailAddress(emailAddress);
774                    user.setFacebookId(facebookId);
775    
776                    Long ldapServerId = null;
777    
778                    if (serviceContext != null) {
779                            ldapServerId = (Long)serviceContext.getAttribute("ldapServerId");
780                    }
781    
782                    if (ldapServerId != null) {
783                            user.setLdapServerId(ldapServerId);
784                    }
785                    else {
786                            user.setLdapServerId(-1);
787                    }
788    
789                    user.setOpenId(openId);
790                    user.setLanguageId(LocaleUtil.toLanguageId(locale));
791                    user.setTimeZoneId(defaultUser.getTimeZoneId());
792                    user.setGreeting(greeting);
793                    user.setFirstName(firstName);
794                    user.setMiddleName(middleName);
795                    user.setLastName(lastName);
796                    user.setJobTitle(jobTitle);
797                    user.setStatus(WorkflowConstants.STATUS_DRAFT);
798                    user.setExpandoBridgeAttributes(serviceContext);
799    
800                    userPersistence.update(user, serviceContext);
801    
802                    // Contact
803    
804                    String creatorUserName = StringPool.BLANK;
805    
806                    if (creatorUserId <= 0) {
807                            creatorUserId = user.getUserId();
808    
809                            // Don't grab the full name from the User object because it doesn't
810                            // have a corresponding Contact object yet
811    
812                            //creatorUserName = user.getFullName();
813                    }
814                    else {
815                            User creatorUser = userPersistence.findByPrimaryKey(creatorUserId);
816    
817                            creatorUserName = creatorUser.getFullName();
818                    }
819    
820                    Date birthday = getBirthday(birthdayMonth, birthdayDay, birthdayYear);
821    
822                    Contact contact = contactPersistence.create(user.getContactId());
823    
824                    contact.setCompanyId(user.getCompanyId());
825                    contact.setUserId(creatorUserId);
826                    contact.setUserName(creatorUserName);
827                    contact.setClassName(User.class.getName());
828                    contact.setClassPK(user.getUserId());
829                    contact.setAccountId(company.getAccountId());
830                    contact.setParentContactId(ContactConstants.DEFAULT_PARENT_CONTACT_ID);
831                    contact.setEmailAddress(user.getEmailAddress());
832                    contact.setFirstName(firstName);
833                    contact.setMiddleName(middleName);
834                    contact.setLastName(lastName);
835                    contact.setPrefixId(prefixId);
836                    contact.setSuffixId(suffixId);
837                    contact.setMale(male);
838                    contact.setBirthday(birthday);
839                    contact.setJobTitle(jobTitle);
840    
841                    contactPersistence.update(contact, serviceContext);
842    
843                    // Group
844    
845                    groupLocalService.addGroup(
846                            user.getUserId(), GroupConstants.DEFAULT_PARENT_GROUP_ID,
847                            User.class.getName(), user.getUserId(),
848                            GroupConstants.DEFAULT_LIVE_GROUP_ID, (Map<Locale, String>)null,
849                            null, 0, true, GroupConstants.DEFAULT_MEMBERSHIP_RESTRICTION,
850                            StringPool.SLASH + screenName, false, true, null);
851    
852                    // Groups
853    
854                    if (!ArrayUtil.isEmpty(groupIds)) {
855                            List<Group> groups = new ArrayList<>();
856    
857                            for (long groupId : groupIds) {
858                                    Group group = groupLocalService.fetchGroup(groupId);
859    
860                                    if (group != null) {
861                                            groups.add(group);
862                                    }
863                                    else {
864                                            if (_log.isWarnEnabled()) {
865                                                    _log.warn("Group " + groupId + " does not exist");
866                                            }
867                                    }
868                            }
869    
870                            groupLocalService.addUserGroups(userId, groups);
871                    }
872    
873                    addDefaultGroups(userId);
874    
875                    // Organizations
876    
877                    updateOrganizations(userId, organizationIds, false);
878    
879                    // Roles
880    
881                    if (roleIds != null) {
882                            roleIds = UsersAdminUtil.addRequiredRoles(user, roleIds);
883    
884                            userPersistence.setRoles(userId, roleIds);
885                    }
886    
887                    addDefaultRoles(userId);
888    
889                    // User groups
890    
891                    if (userGroupIds != null) {
892                            if (PropsValues.USER_GROUPS_COPY_LAYOUTS_TO_USER_PERSONAL_SITE) {
893                                    for (long userGroupId : userGroupIds) {
894                                            userGroupLocalService.copyUserGroupLayouts(
895                                                    userGroupId, new long[] {userId});
896                                    }
897                            }
898    
899                            userPersistence.setUserGroups(userId, userGroupIds);
900                    }
901    
902                    addDefaultUserGroups(userId);
903    
904                    // Resources
905    
906                    resourceLocalService.addResources(
907                            companyId, 0, creatorUserId, User.class.getName(), user.getUserId(),
908                            false, false, false);
909    
910                    // Asset
911    
912                    if (serviceContext != null) {
913                            updateAsset(
914                                    creatorUserId, user, serviceContext.getAssetCategoryIds(),
915                                    serviceContext.getAssetTagNames());
916                    }
917    
918                    // Indexer
919    
920                    if ((serviceContext == null) || serviceContext.isIndexingEnabled()) {
921                            reindex(user);
922                    }
923    
924                    // Workflow
925    
926                    long workflowUserId = creatorUserId;
927    
928                    if (workflowUserId == userId) {
929                            workflowUserId = defaultUser.getUserId();
930                    }
931    
932                    ServiceContext workflowServiceContext = serviceContext;
933    
934                    if (workflowServiceContext == null) {
935                            workflowServiceContext = new ServiceContext();
936                    }
937    
938                    workflowServiceContext.setAttribute("autoPassword", autoPassword);
939                    workflowServiceContext.setAttribute("passwordUnencrypted", password1);
940                    workflowServiceContext.setAttribute("sendEmail", sendEmail);
941    
942                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
943                            companyId, workflowUserId, User.class.getName(), userId, user,
944                            workflowServiceContext);
945    
946                    if (serviceContext != null) {
947                            String passwordUnencrypted = (String)serviceContext.getAttribute(
948                                    "passwordUnencrypted");
949    
950                            if (Validator.isNotNull(passwordUnencrypted)) {
951                                    user.setPasswordUnencrypted(passwordUnencrypted);
952                            }
953                    }
954    
955                    return user;
956            }
957    
958            @Override
959            public void afterPropertiesSet() {
960                    super.afterPropertiesSet();
961    
962                    PortalCache<Serializable, Serializable> portalCache =
963                            EntityCacheUtil.getPortalCache(UserImpl.class);
964    
965                    PortalCacheMapSynchronizeUtil.synchronize(
966                            portalCache, _defaultUsers,
967                            new Synchronizer<Serializable, Serializable>() {
968    
969                                    @Override
970                                    public void onSynchronize(
971                                            Map<? extends Serializable, ? extends Serializable> map,
972                                            Serializable key, Serializable value, int timeToLive) {
973    
974                                            if (!(value instanceof UserCacheModel)) {
975                                                    return;
976                                            }
977    
978                                            UserCacheModel userCacheModel = (UserCacheModel)value;
979    
980                                            if (userCacheModel.defaultUser) {
981                                                    _defaultUsers.remove(userCacheModel.companyId);
982                                            }
983                                    }
984    
985                            });
986            }
987    
988            /**
989             * Attempts to authenticate the user by their email address and password,
990             * while using the AuthPipeline.
991             *
992             * @param  companyId the primary key of the user's company
993             * @param  emailAddress the user's email address
994             * @param  password the user's password
995             * @param  headerMap the header map from the authentication request
996             * @param  parameterMap the parameter map from the authentication request
997             * @param  resultsMap the map of authentication results (may be nil). After
998             *         a successful authentication the user's primary key will be placed
999             *         under the key <code>userId</code>.
1000             * @return the authentication status. This can be {@link
1001             *         Authenticator#FAILURE} indicating that the user's credentials are
1002             *         invalid, {@link Authenticator#SUCCESS} indicating a successful
1003             *         login, or {@link Authenticator#DNE} indicating that a user with
1004             *         that login does not exist.
1005             * @see    AuthPipeline
1006             */
1007            @Override
1008            public int authenticateByEmailAddress(
1009                            long companyId, String emailAddress, String password,
1010                            Map<String, String[]> headerMap, Map<String, String[]> parameterMap,
1011                            Map<String, Object> resultsMap)
1012                    throws PortalException {
1013    
1014                    return authenticate(
1015                            companyId, emailAddress, password, CompanyConstants.AUTH_TYPE_EA,
1016                            headerMap, parameterMap, resultsMap);
1017            }
1018    
1019            /**
1020             * Attempts to authenticate the user by their screen name and password,
1021             * while using the AuthPipeline.
1022             *
1023             * @param  companyId the primary key of the user's company
1024             * @param  screenName the user's screen name
1025             * @param  password the user's password
1026             * @param  headerMap the header map from the authentication request
1027             * @param  parameterMap the parameter map from the authentication request
1028             * @param  resultsMap the map of authentication results (may be nil). After
1029             *         a successful authentication the user's primary key will be placed
1030             *         under the key <code>userId</code>.
1031             * @return the authentication status. This can be {@link
1032             *         Authenticator#FAILURE} indicating that the user's credentials are
1033             *         invalid, {@link Authenticator#SUCCESS} indicating a successful
1034             *         login, or {@link Authenticator#DNE} indicating that a user with
1035             *         that login does not exist.
1036             * @see    AuthPipeline
1037             */
1038            @Override
1039            public int authenticateByScreenName(
1040                            long companyId, String screenName, String password,
1041                            Map<String, String[]> headerMap, Map<String, String[]> parameterMap,
1042                            Map<String, Object> resultsMap)
1043                    throws PortalException {
1044    
1045                    return authenticate(
1046                            companyId, screenName, password, CompanyConstants.AUTH_TYPE_SN,
1047                            headerMap, parameterMap, resultsMap);
1048            }
1049    
1050            /**
1051             * Attempts to authenticate the user by their primary key and password,
1052             * while using the AuthPipeline.
1053             *
1054             * @param  companyId the primary key of the user's company
1055             * @param  userId the user's primary key
1056             * @param  password the user's password
1057             * @param  headerMap the header map from the authentication request
1058             * @param  parameterMap the parameter map from the authentication request
1059             * @param  resultsMap the map of authentication results (may be nil). After
1060             *         a successful authentication the user's primary key will be placed
1061             *         under the key <code>userId</code>.
1062             * @return the authentication status. This can be {@link
1063             *         Authenticator#FAILURE} indicating that the user's credentials are
1064             *         invalid, {@link Authenticator#SUCCESS} indicating a successful
1065             *         login, or {@link Authenticator#DNE} indicating that a user with
1066             *         that login does not exist.
1067             * @see    AuthPipeline
1068             */
1069            @Override
1070            public int authenticateByUserId(
1071                            long companyId, long userId, String password,
1072                            Map<String, String[]> headerMap, Map<String, String[]> parameterMap,
1073                            Map<String, Object> resultsMap)
1074                    throws PortalException {
1075    
1076                    return authenticate(
1077                            companyId, String.valueOf(userId), password,
1078                            CompanyConstants.AUTH_TYPE_ID, headerMap, parameterMap, resultsMap);
1079            }
1080    
1081            /**
1082             * Attempts to authenticate the user using HTTP basic access authentication,
1083             * without using the AuthPipeline. Primarily used for authenticating users
1084             * of <code>tunnel-web</code>.
1085             *
1086             * <p>
1087             * Authentication type specifies what <code>login</code> contains.The valid
1088             * values are:
1089             * </p>
1090             *
1091             * <ul>
1092             * <li>
1093             * <code>CompanyConstants.AUTH_TYPE_EA</code> - <code>login</code> is the
1094             * user's email address
1095             * </li>
1096             * <li>
1097             * <code>CompanyConstants.AUTH_TYPE_SN</code> - <code>login</code> is the
1098             * user's screen name
1099             * </li>
1100             * <li>
1101             * <code>CompanyConstants.AUTH_TYPE_ID</code> - <code>login</code> is the
1102             * user's primary key
1103             * </li>
1104             * </ul>
1105             *
1106             * @param  companyId the primary key of the user's company
1107             * @param  authType the type of authentication to perform
1108             * @param  login either the user's email address, screen name, or primary
1109             *         key depending on the value of <code>authType</code>
1110             * @param  password the user's password
1111             * @return the user's primary key if authentication is successful;
1112             *         <code>0</code> otherwise
1113             */
1114            @Override
1115            @Transactional(propagation = Propagation.SUPPORTS)
1116            public long authenticateForBasic(
1117                            long companyId, String authType, String login, String password)
1118                    throws PortalException {
1119    
1120                    if (PropsValues.AUTH_LOGIN_DISABLED) {
1121                            return 0;
1122                    }
1123    
1124                    User user = null;
1125    
1126                    if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) {
1127                            user = fetchUserByEmailAddress(companyId, login);
1128                    }
1129                    else if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
1130                            user = fetchUserByScreenName(companyId, login);
1131                    }
1132                    else if (authType.equals(CompanyConstants.AUTH_TYPE_ID)) {
1133                            user = userPersistence.fetchByPrimaryKey(GetterUtil.getLong(login));
1134                    }
1135    
1136                    if (user == null) {
1137                            return 0;
1138                    }
1139    
1140                    if (!isUserAllowedToAuthenticate(user)) {
1141                            return 0;
1142                    }
1143    
1144                    if (!PropsValues.BASIC_AUTH_PASSWORD_REQUIRED) {
1145                            return user.getUserId();
1146                    }
1147    
1148                    String userPassword = user.getPassword();
1149    
1150                    if (!user.isPasswordEncrypted()) {
1151                            userPassword = PasswordEncryptorUtil.encrypt(userPassword);
1152                    }
1153    
1154                    String encPassword = PasswordEncryptorUtil.encrypt(
1155                            password, userPassword);
1156    
1157                    if (userPassword.equals(password) || userPassword.equals(encPassword)) {
1158                            resetFailedLoginAttempts(user);
1159    
1160                            return user.getUserId();
1161                    }
1162    
1163                    handleAuthenticationFailure(
1164                            login, authType, user, Collections.<String, String[]>emptyMap(),
1165                            Collections.<String, String[]>emptyMap());
1166    
1167                    return 0;
1168            }
1169    
1170            /**
1171             * Attempts to authenticate the user using HTTP digest access
1172             * authentication, without using the AuthPipeline. Primarily used for
1173             * authenticating users of <code>tunnel-web</code>.
1174             *
1175             * @param  companyId the primary key of the user's company
1176             * @param  username either the user's email address, screen name, or primary
1177             *         key
1178             * @param  realm unused
1179             * @param  nonce the number used once
1180             * @param  method the request method
1181             * @param  uri the request URI
1182             * @param  response the authentication response hash
1183             * @return the user's primary key if authentication is successful;
1184             *         <code>0</code> otherwise
1185             */
1186            @Override
1187            @Transactional(propagation = Propagation.SUPPORTS)
1188            public long authenticateForDigest(
1189                            long companyId, String username, String realm, String nonce,
1190                            String method, String uri, String response)
1191                    throws PortalException {
1192    
1193                    if (PropsValues.AUTH_LOGIN_DISABLED) {
1194                            return 0;
1195                    }
1196    
1197                    // Get User
1198    
1199                    User user = fetchUserByEmailAddress(companyId, username);
1200    
1201                    if (user == null) {
1202                            user = fetchUserByScreenName(companyId, username);
1203                    }
1204    
1205                    if (user == null) {
1206                            user = userPersistence.fetchByPrimaryKey(
1207                                    GetterUtil.getLong(username));
1208                    }
1209    
1210                    if (user == null) {
1211                            return 0;
1212                    }
1213    
1214                    if (!isUserAllowedToAuthenticate(user)) {
1215                            return 0;
1216                    }
1217    
1218                    // Verify digest
1219    
1220                    String digest = user.getDigest();
1221    
1222                    if (Validator.isNull(digest)) {
1223                            _log.error(
1224                                    "User must first login through the portal " + user.getUserId());
1225    
1226                            return 0;
1227                    }
1228    
1229                    String[] digestArray = StringUtil.split(user.getDigest());
1230    
1231                    for (String ha1 : digestArray) {
1232                            String ha2 = DigesterUtil.digestHex(Digester.MD5, method, uri);
1233    
1234                            String curResponse = DigesterUtil.digestHex(
1235                                    Digester.MD5, ha1, nonce, ha2);
1236    
1237                            if (response.equals(curResponse)) {
1238                                    resetFailedLoginAttempts(user);
1239    
1240                                    return user.getUserId();
1241                            }
1242                    }
1243    
1244                    Company company = companyPersistence.findByPrimaryKey(companyId);
1245    
1246                    handleAuthenticationFailure(
1247                            username, company.getAuthType(), user,
1248                            new HashMap<String, String[]>(), new HashMap<String, String[]>());
1249    
1250                    return 0;
1251            }
1252    
1253            /**
1254             * Attempts to authenticate the user using JAAS credentials, without using
1255             * the AuthPipeline.
1256             *
1257             * @param  userId the primary key of the user
1258             * @param  encPassword the encrypted password
1259             * @return <code>true</code> if authentication is successful;
1260             *         <code>false</code> otherwise
1261             */
1262            @Override
1263            @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
1264            public boolean authenticateForJAAS(long userId, String encPassword) {
1265                    if (PropsValues.AUTH_LOGIN_DISABLED) {
1266                            return false;
1267                    }
1268    
1269                    try {
1270                            User user = userPersistence.findByPrimaryKey(userId);
1271    
1272                            if (user.isDefaultUser()) {
1273                                    if (_log.isInfoEnabled()) {
1274                                            _log.info(
1275                                                    "JAAS authentication is disabled for the default user");
1276                                    }
1277    
1278                                    return false;
1279                            }
1280                            else if (!user.isActive()) {
1281                                    if (_log.isInfoEnabled()) {
1282                                            _log.info(
1283                                                    "JAAS authentication is disabled for inactive user " +
1284                                                            userId);
1285                                    }
1286    
1287                                    return false;
1288                            }
1289    
1290                            String userPassword = user.getPassword();
1291    
1292                            if (user.isPasswordEncrypted()) {
1293                                    if (userPassword.equals(encPassword)) {
1294                                            return true;
1295                                    }
1296    
1297                                    if (!PropsValues.PORTAL_JAAS_STRICT_PASSWORD) {
1298                                            encPassword = PasswordEncryptorUtil.encrypt(
1299                                                    encPassword, userPassword);
1300    
1301                                            if (userPassword.equals(encPassword)) {
1302                                                    return true;
1303                                            }
1304                                    }
1305                            }
1306                            else {
1307                                    if (!PropsValues.PORTAL_JAAS_STRICT_PASSWORD) {
1308                                            if (userPassword.equals(encPassword)) {
1309                                                    return true;
1310                                            }
1311                                    }
1312    
1313                                    userPassword = PasswordEncryptorUtil.encrypt(
1314                                            userPassword, encPassword);
1315    
1316                                    if (userPassword.equals(encPassword)) {
1317                                            return true;
1318                                    }
1319                            }
1320                    }
1321                    catch (Exception e) {
1322                            _log.error(e);
1323                    }
1324    
1325                    return false;
1326            }
1327    
1328            /**
1329             * Checks if the user is currently locked out based on the password policy,
1330             * and performs maintenance on the user's lockout and failed login data.
1331             *
1332             * @param user the user
1333             */
1334            @Override
1335            public void checkLockout(User user) throws PortalException {
1336                    if (LDAPSettingsUtil.isPasswordPolicyEnabled(user.getCompanyId())) {
1337                            return;
1338                    }
1339    
1340                    PasswordPolicy passwordPolicy = user.getPasswordPolicy();
1341    
1342                    if (!passwordPolicy.isLockout()) {
1343                            return;
1344                    }
1345    
1346                    // Reset failure count
1347    
1348                    Date now = new Date();
1349                    int failedLoginAttempts = user.getFailedLoginAttempts();
1350    
1351                    if (failedLoginAttempts > 0) {
1352                            long failedLoginTime = user.getLastFailedLoginDate().getTime();
1353                            long elapsedTime = now.getTime() - failedLoginTime;
1354                            long requiredElapsedTime =
1355                                    passwordPolicy.getResetFailureCount() * 1000;
1356    
1357                            if ((requiredElapsedTime != 0) &&
1358                                    (elapsedTime > requiredElapsedTime)) {
1359    
1360                                    user.setFailedLoginAttempts(0);
1361    
1362                                    userPersistence.update(user);
1363                            }
1364                    }
1365    
1366                    // Reset lockout
1367    
1368                    if (user.isLockout()) {
1369                            long lockoutTime = user.getLockoutDate().getTime();
1370                            long elapsedTime = now.getTime() - lockoutTime;
1371                            long requiredElapsedTime =
1372                                    passwordPolicy.getLockoutDuration() * 1000;
1373    
1374                            if ((requiredElapsedTime != 0) &&
1375                                    (elapsedTime > requiredElapsedTime)) {
1376    
1377                                    user.setLockout(false);
1378                                    user.setLockoutDate(null);
1379    
1380                                    userPersistence.update(user);
1381                            }
1382                    }
1383    
1384                    if (user.isLockout()) {
1385                            throw new UserLockoutException.PasswordPolicyLockout(
1386                                    user, passwordPolicy);
1387                    }
1388            }
1389    
1390            /**
1391             * Adds a failed login attempt to the user and updates the user's last
1392             * failed login date.
1393             *
1394             * @param user the user
1395             */
1396            @Override
1397            public void checkLoginFailure(User user) {
1398                    int failedLoginAttempts = user.getFailedLoginAttempts();
1399    
1400                    user.setLastFailedLoginDate(new Date());
1401                    user.setFailedLoginAttempts(++failedLoginAttempts);
1402    
1403                    userPersistence.update(user);
1404            }
1405    
1406            /**
1407             * Adds a failed login attempt to the user with the email address and
1408             * updates the user's last failed login date.
1409             *
1410             * @param companyId the primary key of the user's company
1411             * @param emailAddress the user's email address
1412             */
1413            @Override
1414            public void checkLoginFailureByEmailAddress(
1415                            long companyId, String emailAddress)
1416                    throws PortalException {
1417    
1418                    User user = getUserByEmailAddress(companyId, emailAddress);
1419    
1420                    checkLoginFailure(user);
1421            }
1422    
1423            /**
1424             * Adds a failed login attempt to the user and updates the user's last
1425             * failed login date.
1426             *
1427             * @param userId the primary key of the user
1428             */
1429            @Override
1430            public void checkLoginFailureById(long userId) throws PortalException {
1431                    User user = userPersistence.findByPrimaryKey(userId);
1432    
1433                    checkLoginFailure(user);
1434            }
1435    
1436            /**
1437             * Adds a failed login attempt to the user with the screen name and updates
1438             * the user's last failed login date.
1439             *
1440             * @param companyId the primary key of the user's company
1441             * @param screenName the user's screen name
1442             */
1443            @Override
1444            public void checkLoginFailureByScreenName(long companyId, String screenName)
1445                    throws PortalException {
1446    
1447                    User user = getUserByScreenName(companyId, screenName);
1448    
1449                    checkLoginFailure(user);
1450            }
1451    
1452            /**
1453             * Checks if the user's password is expired based on the password policy,
1454             * and performs maintenance on the user's grace login and password reset
1455             * data.
1456             *
1457             * @param user the user
1458             */
1459            @Override
1460            public void checkPasswordExpired(User user) throws PortalException {
1461                    if (LDAPSettingsUtil.isPasswordPolicyEnabled(user.getCompanyId())) {
1462                            return;
1463                    }
1464    
1465                    PasswordPolicy passwordPolicy = user.getPasswordPolicy();
1466    
1467                    // Check if password has expired
1468    
1469                    if (isPasswordExpired(user)) {
1470                            int graceLoginCount = user.getGraceLoginCount();
1471    
1472                            if (graceLoginCount < passwordPolicy.getGraceLimit()) {
1473                                    user.setGraceLoginCount(++graceLoginCount);
1474    
1475                                    userPersistence.update(user);
1476                            }
1477                            else {
1478                                    user.setDigest(StringPool.BLANK);
1479    
1480                                    userPersistence.update(user);
1481    
1482                                    throw new PasswordExpiredException();
1483                            }
1484                    }
1485    
1486                    // Check if user should be forced to change password on first login
1487    
1488                    if (passwordPolicy.isChangeable() &&
1489                            passwordPolicy.isChangeRequired()) {
1490    
1491                            if (user.getLastLoginDate() == null) {
1492                                    user.setPasswordReset(true);
1493    
1494                                    userPersistence.update(user);
1495                            }
1496                    }
1497            }
1498    
1499            /**
1500             * Removes all the users from the organization.
1501             *
1502             * @param organizationId the primary key of the organization
1503             */
1504            @Override
1505            public void clearOrganizationUsers(long organizationId) {
1506                    organizationPersistence.clearUsers(organizationId);
1507    
1508                    PermissionCacheUtil.clearCache();
1509            }
1510    
1511            /**
1512             * Removes all the users from the user group.
1513             *
1514             * @param userGroupId the primary key of the user group
1515             */
1516            @Override
1517            public void clearUserGroupUsers(long userGroupId) {
1518                    userGroupPersistence.clearUsers(userGroupId);
1519    
1520                    PermissionCacheUtil.clearCache();
1521            }
1522    
1523            /**
1524             * Completes the user's registration by generating a password and sending
1525             * the confirmation email.
1526             *
1527             * @param user the user
1528             * @param serviceContext the service context to be applied. You can specify
1529             *        an unencrypted custom password for the user via attribute
1530             *        <code>passwordUnencrypted</code>. You automatically generate a
1531             *        password for the user by setting attribute
1532             *        <code>autoPassword</code> to <code>true</code>. You can send a
1533             *        confirmation email to the user by setting attribute
1534             *        <code>sendEmail</code> to <code>true</code>.
1535             */
1536            @Override
1537            public void completeUserRegistration(
1538                            User user, ServiceContext serviceContext)
1539                    throws PortalException {
1540    
1541                    boolean autoPassword = ParamUtil.getBoolean(
1542                            serviceContext, "autoPassword");
1543    
1544                    String password = (String)serviceContext.getAttribute(
1545                            "passwordUnencrypted");
1546    
1547                    if (autoPassword) {
1548                            if (LDAPSettingsUtil.isPasswordPolicyEnabled(user.getCompanyId())) {
1549                                    if (_log.isWarnEnabled()) {
1550                                            StringBundler sb = new StringBundler(4);
1551    
1552                                            sb.append("When LDAP password policy is enabled, it is ");
1553                                            sb.append("possible that portal generated passwords will ");
1554                                            sb.append("not match the LDAP policy. Using ");
1555                                            sb.append("RegExpToolkit to generate new password.");
1556    
1557                                            _log.warn(sb.toString());
1558                                    }
1559    
1560                                    RegExpToolkit regExpToolkit = new RegExpToolkit();
1561    
1562                                    password = regExpToolkit.generate(null);
1563                            }
1564                            else {
1565                                    PasswordPolicy passwordPolicy =
1566                                            passwordPolicyLocalService.getPasswordPolicy(
1567                                                    user.getCompanyId(), user.getOrganizationIds());
1568    
1569                                    password = PwdToolkitUtil.generate(passwordPolicy);
1570                            }
1571    
1572                            serviceContext.setAttribute("passwordUnencrypted", password);
1573    
1574                            user.setPassword(PasswordEncryptorUtil.encrypt(password));
1575                            user.setPasswordUnencrypted(password);
1576                            user.setPasswordEncrypted(true);
1577                            user.setPasswordModified(true);
1578                            user.setPasswordModifiedDate(new Date());
1579    
1580                            userPersistence.update(user);
1581    
1582                            user.setPasswordModified(false);
1583                    }
1584    
1585                    if (user.hasCompanyMx()) {
1586                            mailService.addUser(
1587                                    user.getCompanyId(), user.getUserId(), password,
1588                                    user.getFirstName(), user.getMiddleName(), user.getLastName(),
1589                                    user.getEmailAddress());
1590                    }
1591    
1592                    boolean sendEmail = ParamUtil.getBoolean(serviceContext, "sendEmail");
1593    
1594                    if (sendEmail) {
1595                            notifyUser(user, password, serviceContext);
1596                    }
1597    
1598                    Company company = companyPersistence.findByPrimaryKey(
1599                            user.getCompanyId());
1600    
1601                    if (company.isStrangersVerify()) {
1602                            sendEmailAddressVerification(
1603                                    user, user.getEmailAddress(), serviceContext);
1604                    }
1605            }
1606    
1607            /**
1608             * Decrypts the user's primary key and password from their encrypted forms.
1609             * Used for decrypting a user's credentials from the values stored in an
1610             * automatic login cookie.
1611             *
1612             * @param  companyId the primary key of the user's company
1613             * @param  name the encrypted primary key of the user
1614             * @param  password the encrypted password of the user
1615             * @return the user's primary key and password
1616             */
1617            @Override
1618            public KeyValuePair decryptUserId(
1619                            long companyId, String name, String password)
1620                    throws PortalException {
1621    
1622                    Company company = companyPersistence.findByPrimaryKey(companyId);
1623    
1624                    try {
1625                            name = Encryptor.decrypt(company.getKeyObj(), name);
1626                    }
1627                    catch (EncryptorException ee) {
1628                            throw new SystemException(ee);
1629                    }
1630    
1631                    long userId = GetterUtil.getLong(name);
1632    
1633                    User user = userPersistence.findByPrimaryKey(userId);
1634    
1635                    try {
1636                            password = Encryptor.decrypt(company.getKeyObj(), password);
1637                    }
1638                    catch (EncryptorException ee) {
1639                            throw new SystemException(ee);
1640                    }
1641    
1642                    String userPassword = user.getPassword();
1643                    String encPassword = PasswordEncryptorUtil.encrypt(
1644                            password, userPassword);
1645    
1646                    if (userPassword.equals(encPassword)) {
1647                            if (isPasswordExpired(user)) {
1648                                    user.setPasswordReset(true);
1649    
1650                                    userPersistence.update(user);
1651                            }
1652    
1653                            return new KeyValuePair(name, password);
1654                    }
1655                    else {
1656                            throw new PrincipalException.MustBeAuthenticated(userId);
1657                    }
1658            }
1659    
1660            /**
1661             * Deletes the user's portrait image.
1662             *
1663             * @param userId the primary key of the user
1664             */
1665            @Override
1666            public void deletePortrait(long userId) throws PortalException {
1667                    User user = userPersistence.findByPrimaryKey(userId);
1668    
1669                    PortalUtil.updateImageId(user, false, null, "portraitId", 0, 0, 0);
1670            }
1671    
1672            /**
1673             * Removes the user from the role.
1674             *
1675             * @param roleId the primary key of the role
1676             * @param userId the primary key of the user
1677             */
1678            @Override
1679            public void deleteRoleUser(long roleId, long userId)
1680                    throws PortalException {
1681    
1682                    rolePersistence.removeUser(roleId, userId);
1683    
1684                    reindex(userId);
1685    
1686                    PermissionCacheUtil.clearCache(userId);
1687            }
1688    
1689            /**
1690             * Deletes the user.
1691             *
1692             * @param  userId the primary key of the user
1693             * @return the deleted user
1694             */
1695            @Override
1696            public User deleteUser(long userId) throws PortalException {
1697                    User user = userPersistence.findByPrimaryKey(userId);
1698    
1699                    return deleteUser(user);
1700            }
1701    
1702            /**
1703             * Deletes the user.
1704             *
1705             * @param  user the user
1706             * @return the deleted user
1707             */
1708            @Override
1709            public User deleteUser(User user) throws PortalException {
1710                    if (!PropsValues.USERS_DELETE) {
1711                            throw new RequiredUserException();
1712                    }
1713    
1714                    // Browser tracker
1715    
1716                    browserTrackerLocalService.deleteUserBrowserTracker(user.getUserId());
1717    
1718                    // Group
1719    
1720                    Group group = null;
1721    
1722                    if (!user.isDefaultUser()) {
1723                            group = user.getGroup();
1724                    }
1725    
1726                    if (group != null) {
1727                            groupLocalService.deleteGroup(group);
1728                    }
1729    
1730                    // Portrait
1731    
1732                    try {
1733                            imageLocalService.deleteImage(user.getPortraitId());
1734                    }
1735                    catch (NoSuchImageException nsie) {
1736                            if (_log.isWarnEnabled()) {
1737                                    _log.warn(
1738                                            "Unable to delete image " + user.getPortraitId(), nsie);
1739                            }
1740                    }
1741    
1742                    // Password policy relation
1743    
1744                    passwordPolicyRelLocalService.deletePasswordPolicyRel(
1745                            User.class.getName(), user.getUserId());
1746    
1747                    // Old passwords
1748    
1749                    passwordTrackerLocalService.deletePasswordTrackers(user.getUserId());
1750    
1751                    // Subscriptions
1752    
1753                    subscriptionLocalService.deleteSubscriptions(user.getUserId());
1754    
1755                    // External user ids
1756    
1757                    userIdMapperLocalService.deleteUserIdMappers(user.getUserId());
1758    
1759                    // Announcements
1760    
1761                    announcementsDeliveryLocalService.deleteDeliveries(user.getUserId());
1762    
1763                    // Asset
1764    
1765                    assetEntryLocalService.deleteEntry(
1766                            User.class.getName(), user.getUserId());
1767    
1768                    // Blogs
1769    
1770                    blogsStatsUserLocalService.deleteStatsUserByUserId(user.getUserId());
1771    
1772                    // Document library
1773    
1774                    dlFileRankLocalService.deleteFileRanksByUserId(user.getUserId());
1775    
1776                    // Expando
1777    
1778                    expandoRowLocalService.deleteRows(user.getUserId());
1779    
1780                    // Message boards
1781    
1782                    mbBanLocalService.deleteBansByBanUserId(user.getUserId());
1783                    mbStatsUserLocalService.deleteStatsUsersByUserId(user.getUserId());
1784                    mbThreadFlagLocalService.deleteThreadFlagsByUserId(user.getUserId());
1785    
1786                    // Membership requests
1787    
1788                    membershipRequestLocalService.deleteMembershipRequestsByUserId(
1789                            user.getUserId());
1790    
1791                    // Ratings
1792    
1793                    ratingsStatsLocalService.deleteStats(
1794                            User.class.getName(), user.getUserId());
1795    
1796                    // Social
1797    
1798                    socialActivityLocalService.deleteUserActivities(user.getUserId());
1799                    socialRequestLocalService.deleteReceiverUserRequests(user.getUserId());
1800                    socialRequestLocalService.deleteUserRequests(user.getUserId());
1801    
1802                    // Mail
1803    
1804                    mailService.deleteUser(user.getCompanyId(), user.getUserId());
1805    
1806                    // Contact
1807    
1808                    Contact contact = contactLocalService.fetchContact(user.getContactId());
1809    
1810                    if (contact != null) {
1811                            contactLocalService.deleteContact(contact);
1812                    }
1813    
1814                    // Group roles
1815    
1816                    userGroupRoleLocalService.deleteUserGroupRolesByUserId(
1817                            user.getUserId());
1818    
1819                    // Recent layouts
1820    
1821                    recentLayoutBranchLocalService.deleteUserRecentLayoutBranches(
1822                            user.getUserId());
1823                    recentLayoutRevisionLocalService.deleteUserRecentLayoutRevisions(
1824                            user.getUserId());
1825                    recentLayoutSetBranchLocalService.deleteUserRecentLayoutSetBranches(
1826                            user.getUserId());
1827    
1828                    // Resources
1829    
1830                    resourceLocalService.deleteResource(
1831                            user.getCompanyId(), User.class.getName(),
1832                            ResourceConstants.SCOPE_INDIVIDUAL, user.getUserId());
1833    
1834                    // User
1835    
1836                    userPersistence.remove(user);
1837    
1838                    // Permission cache
1839    
1840                    PermissionCacheUtil.clearCache(user.getUserId());
1841    
1842                    // Workflow
1843    
1844                    workflowInstanceLinkLocalService.deleteWorkflowInstanceLinks(
1845                            user.getCompanyId(), 0, User.class.getName(), user.getUserId());
1846    
1847                    return user;
1848            }
1849    
1850            /**
1851             * Removes the user from the user group.
1852             *
1853             * @param userGroupId the primary key of the user group
1854             * @param userId the primary key of the user
1855             */
1856            @Override
1857            public void deleteUserGroupUser(long userGroupId, long userId)
1858                    throws PortalException {
1859    
1860                    userGroupPersistence.removeUser(userGroupId, userId);
1861    
1862                    reindex(userId);
1863    
1864                    PermissionCacheUtil.clearCache(userId);
1865            }
1866    
1867            /**
1868             * Encrypts the primary key of the user. Used when encrypting the user's
1869             * credentials for storage in an automatic login cookie.
1870             *
1871             * @param  name the primary key of the user
1872             * @return the user's encrypted primary key
1873             */
1874            @Override
1875            @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
1876            public String encryptUserId(String name) throws PortalException {
1877                    long userId = GetterUtil.getLong(name);
1878    
1879                    User user = userPersistence.findByPrimaryKey(userId);
1880    
1881                    Company company = companyPersistence.findByPrimaryKey(
1882                            user.getCompanyId());
1883    
1884                    try {
1885                            return Encryptor.encrypt(company.getKeyObj(), name);
1886                    }
1887                    catch (EncryptorException ee) {
1888                            throw new SystemException(ee);
1889                    }
1890            }
1891    
1892            /**
1893             * Returns the user with the contact ID.
1894             *
1895             * @param  contactId the user's contact ID
1896             * @return the user with the contact ID, or <code>null</code> if a user with
1897             *         the contact ID could not be found
1898             */
1899            @Override
1900            public User fetchUserByContactId(long contactId) {
1901                    return userPersistence.fetchByContactId(contactId);
1902            }
1903    
1904            /**
1905             * Returns the user with the email address.
1906             *
1907             * @param  companyId the primary key of the user's company
1908             * @param  emailAddress the user's email address
1909             * @return the user with the email address, or <code>null</code> if a user
1910             *         with the email address could not be found
1911             */
1912            @Override
1913            public User fetchUserByEmailAddress(long companyId, String emailAddress) {
1914                    emailAddress = getLogin(emailAddress);
1915    
1916                    return userPersistence.fetchByC_EA(companyId, emailAddress);
1917            }
1918    
1919            /**
1920             * Returns the user with the Facebook ID.
1921             *
1922             * @param  companyId the primary key of the user's company
1923             * @param  facebookId the user's Facebook ID
1924             * @return the user with the Facebook ID, or <code>null</code> if a user
1925             *         with the Facebook ID could not be found
1926             */
1927            @Override
1928            public User fetchUserByFacebookId(long companyId, long facebookId) {
1929                    return userPersistence.fetchByC_FID(companyId, facebookId);
1930            }
1931    
1932            /**
1933             * Returns the user with the primary key.
1934             *
1935             * @param  userId the primary key of the user
1936             * @return the user with the primary key, or <code>null</code> if a user
1937             *         with the primary key could not be found
1938             */
1939            @Override
1940            public User fetchUserById(long userId) {
1941                    return userPersistence.fetchByPrimaryKey(userId);
1942            }
1943    
1944            /**
1945             * Returns the user with the OpenID.
1946             *
1947             * @param  companyId the primary key of the user's company
1948             * @param  openId the user's OpenID
1949             * @return the user with the OpenID, or <code>null</code> if a user with the
1950             *         OpenID could not be found
1951             */
1952            @Override
1953            public User fetchUserByOpenId(long companyId, String openId) {
1954                    return userPersistence.fetchByC_O(companyId, openId);
1955            }
1956    
1957            /**
1958             * Returns the user with the portrait ID.
1959             *
1960             * @param  portraitId the user's portrait ID
1961             * @return the user with the portrait ID, or <code>null</code> if a user
1962             *         with the portrait ID could not be found
1963             */
1964            @Override
1965            public User fetchUserByPortraitId(long portraitId) {
1966                    return userPersistence.fetchByPortraitId(portraitId);
1967            }
1968    
1969            /**
1970             * Returns the user with the screen name.
1971             *
1972             * @param  companyId the primary key of the user's company
1973             * @param  screenName the user's screen name
1974             * @return the user with the screen name, or <code>null</code> if a user
1975             *         with the screen name could not be found
1976             */
1977            @Override
1978            public User fetchUserByScreenName(long companyId, String screenName) {
1979                    screenName = getLogin(screenName);
1980    
1981                    return userPersistence.fetchByC_SN(companyId, screenName);
1982            }
1983    
1984            /**
1985             * Returns a range of all the users belonging to the company.
1986             *
1987             * <p>
1988             * Useful when paginating results. Returns a maximum of <code>end -
1989             * start</code> instances. <code>start</code> and <code>end</code> are not
1990             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1991             * refers to the first result in the set. Setting both <code>start</code>
1992             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
1993             * result set.
1994             * </p>
1995             *
1996             * @param  companyId the primary key of the company
1997             * @param  start the lower bound of the range of users
1998             * @param  end the upper bound of the range of users (not inclusive)
1999             * @return the range of users belonging to the company
2000             */
2001            @Override
2002            public List<User> getCompanyUsers(long companyId, int start, int end) {
2003                    return userPersistence.findByCompanyId(companyId, start, end);
2004            }
2005    
2006            /**
2007             * Returns the number of users belonging to the company.
2008             *
2009             * @param  companyId the primary key of the company
2010             * @return the number of users belonging to the company
2011             */
2012            @Override
2013            public int getCompanyUsersCount(long companyId) {
2014                    return userPersistence.countByCompanyId(companyId);
2015            }
2016    
2017            /**
2018             * Returns the default user for the company.
2019             *
2020             * @param  companyId the primary key of the company
2021             * @return the default user for the company
2022             */
2023            @Override
2024            @Skip
2025            public User getDefaultUser(long companyId) throws PortalException {
2026                    User userModel = _defaultUsers.get(companyId);
2027    
2028                    if (userModel == null) {
2029                            userModel = userLocalService.loadGetDefaultUser(companyId);
2030    
2031                            _defaultUsers.put(companyId, userModel);
2032                    }
2033    
2034                    return userModel;
2035            }
2036    
2037            /**
2038             * Returns the primary key of the default user for the company.
2039             *
2040             * @param  companyId the primary key of the company
2041             * @return the primary key of the default user for the company
2042             */
2043            @Override
2044            @Skip
2045            public long getDefaultUserId(long companyId) throws PortalException {
2046                    User user = getDefaultUser(companyId);
2047    
2048                    return user.getUserId();
2049            }
2050    
2051            /**
2052             * Returns the primary keys of all the users belonging to the group.
2053             *
2054             * @param  groupId the primary key of the group
2055             * @return the primary keys of the users belonging to the group
2056             */
2057            @Override
2058            public long[] getGroupUserIds(long groupId) {
2059                    return groupPersistence.getUserPrimaryKeys(groupId);
2060            }
2061    
2062            /**
2063             * Returns the number of users with the status belonging to the group.
2064             *
2065             * @param  groupId the primary key of the group
2066             * @param  status the workflow status
2067             * @return the number of users with the status belonging to the group
2068             */
2069            @Override
2070            public int getGroupUsersCount(long groupId, int status)
2071                    throws PortalException {
2072    
2073                    Group group = groupPersistence.findByPrimaryKey(groupId);
2074    
2075                    LinkedHashMap<String, Object> params = new LinkedHashMap<>();
2076    
2077                    params.put("usersGroups", Long.valueOf(groupId));
2078    
2079                    return searchCount(group.getCompanyId(), null, status, params);
2080            }
2081    
2082            @Override
2083            public List<User> getInheritedRoleUsers(
2084                            long roleId, int start, int end, OrderByComparator<User> obc)
2085                    throws PortalException {
2086    
2087                    Role role = rolePersistence.findByPrimaryKey(roleId);
2088    
2089                    LinkedHashMap<String, Object> params = new LinkedHashMap<>();
2090    
2091                    params.put("inherit", Boolean.TRUE);
2092                    params.put("usersRoles", roleId);
2093    
2094                    return search(
2095                            role.getCompanyId(), null, WorkflowConstants.STATUS_APPROVED,
2096                            params, start, end, obc);
2097            }
2098    
2099            /**
2100             * Returns all the users who have not had any announcements of the type
2101             * delivered, excluding the default user.
2102             *
2103             * @param  type the type of announcement
2104             * @return the users who have not had any annoucements of the type delivered
2105             */
2106            @Override
2107            public List<User> getNoAnnouncementsDeliveries(String type) {
2108                    return userFinder.findByNoAnnouncementsDeliveries(type);
2109            }
2110    
2111            /**
2112             * Returns all the users who do not have any contacts.
2113             *
2114             * @return the users who do not have any contacts
2115             */
2116            @Override
2117            public List<User> getNoContacts() {
2118                    return userFinder.findByNoContacts();
2119            }
2120    
2121            /**
2122             * Returns all the users who do not belong to any groups, excluding the
2123             * default user.
2124             *
2125             * @return the users who do not belong to any groups
2126             */
2127            @Override
2128            public List<User> getNoGroups() {
2129                    return userFinder.findByNoGroups();
2130            }
2131    
2132            /**
2133             * Returns the primary keys of all the users belonging to the organization.
2134             *
2135             * @param  organizationId the primary key of the organization
2136             * @return the primary keys of the users belonging to the organization
2137             */
2138            @Override
2139            public long[] getOrganizationUserIds(long organizationId) {
2140                    return organizationPersistence.getUserPrimaryKeys(organizationId);
2141            }
2142    
2143            /**
2144             * Returns the number of users with the status belonging to the
2145             * organization.
2146             *
2147             * @param  organizationId the primary key of the organization
2148             * @param  status the workflow status
2149             * @return the number of users with the status belonging to the organization
2150             */
2151            @Override
2152            public int getOrganizationUsersCount(long organizationId, int status)
2153                    throws PortalException {
2154    
2155                    Organization organization = organizationPersistence.findByPrimaryKey(
2156                            organizationId);
2157    
2158                    LinkedHashMap<String, Object> params = new LinkedHashMap<>();
2159    
2160                    params.put("usersOrgs", Long.valueOf(organizationId));
2161    
2162                    return searchCount(organization.getCompanyId(), null, status, params);
2163            }
2164    
2165            /**
2166             * Returns the primary keys of all the users belonging to the role.
2167             *
2168             * @param  roleId the primary key of the role
2169             * @return the primary keys of the users belonging to the role
2170             */
2171            @Override
2172            public long[] getRoleUserIds(long roleId) {
2173                    return rolePersistence.getUserPrimaryKeys(roleId);
2174            }
2175    
2176            /**
2177             * Returns the number of users with the status belonging to the role.
2178             *
2179             * @param  roleId the primary key of the role
2180             * @param  status the workflow status
2181             * @return the number of users with the status belonging to the role
2182             */
2183            @Override
2184            public int getRoleUsersCount(long roleId, int status)
2185                    throws PortalException {
2186    
2187                    Role role = rolePersistence.findByPrimaryKey(roleId);
2188    
2189                    LinkedHashMap<String, Object> params = new LinkedHashMap<>();
2190    
2191                    params.put("usersRoles", Long.valueOf(roleId));
2192    
2193                    return searchCount(role.getCompanyId(), null, status, params);
2194            }
2195    
2196            /**
2197             * Returns an ordered range of all the users with a social relation of the
2198             * type with the user.
2199             *
2200             * <p>
2201             * Useful when paginating results. Returns a maximum of <code>end -
2202             * start</code> instances. <code>start</code> and <code>end</code> are not
2203             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2204             * refers to the first result in the set. Setting both <code>start</code>
2205             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2206             * result set.
2207             * </p>
2208             *
2209             * @param      userId the primary key of the user
2210             * @param      socialRelationType the type of social relation. The possible
2211             *             types can be found in {@link SocialRelationConstants}.
2212             * @param      start the lower bound of the range of users
2213             * @param      end the upper bound of the range of users (not inclusive)
2214             * @param      obc the comparator to order the users by (optionally
2215             *             <code>null</code>)
2216             * @return     the ordered range of users with a social relation of the type
2217             *             with the user
2218             * @deprecated As of 7.0.0, replaced by {@link #getSocialUsers(long, int,
2219             *             String, int, int, OrderByComparator)}
2220             */
2221            @Deprecated
2222            @Override
2223            public List<User> getSocialUsers(
2224                            long userId, int socialRelationType, int start, int end,
2225                            OrderByComparator<User> obc)
2226                    throws PortalException {
2227    
2228                    return getSocialUsers(
2229                            userId, socialRelationType, StringPool.EQUAL, start, end, obc);
2230            }
2231    
2232            /**
2233             * Returns an ordered range of all the users with a social relation with the
2234             * user.
2235             *
2236             * <p>
2237             * Useful when paginating results. Returns a maximum of <code>end -
2238             * start</code> instances. <code>start</code> and <code>end</code> are not
2239             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2240             * refers to the first result in the set. Setting both <code>start</code>
2241             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2242             * result set.
2243             * </p>
2244             *
2245             * @param      userId the primary key of the user
2246             * @param      start the lower bound of the range of users
2247             * @param      end the upper bound of the range of users (not inclusive)
2248             * @param      obc the comparator to order the users by (optionally
2249             *             <code>null</code>)
2250             * @return     the ordered range of users with a social relation with the
2251             *             user
2252             * @deprecated As of 7.0.0, replaced by {@link #getSocialUsers(long, int,
2253             *             String, int, int, OrderByComparator)}
2254             */
2255            @Deprecated
2256            @Override
2257            public List<User> getSocialUsers(
2258                            long userId, int start, int end, OrderByComparator<User> obc)
2259                    throws PortalException {
2260    
2261                    return getSocialUsers(
2262                            userId, SocialRelationConstants.TYPE_UNI_ENEMY,
2263                            StringPool.NOT_EQUAL, start, end, obc);
2264            }
2265    
2266            @Override
2267            public List<User> getSocialUsers(
2268                            long userId, int socialRelationType,
2269                            String socialRelationTypeComparator, int start, int end,
2270                            OrderByComparator<User> obc)
2271                    throws PortalException {
2272    
2273                    if (!socialRelationTypeComparator.equals(StringPool.EQUAL) &&
2274                            !socialRelationTypeComparator.equals(StringPool.NOT_EQUAL)) {
2275    
2276                            throw new IllegalArgumentException(
2277                                    "Invalid social relation type comparator " +
2278                                            socialRelationTypeComparator);
2279                    }
2280    
2281                    if ((start == QueryUtil.ALL_POS) && (end == QueryUtil.ALL_POS)) {
2282                            List<SocialRelation> socialRelations =
2283                                    socialRelationPersistence.findByU1_T(
2284                                            userId, socialRelationType);
2285    
2286                            if (socialRelationTypeComparator.equals(StringPool.NOT_EQUAL)) {
2287                                    socialRelations = ListUtil.remove(
2288                                            socialRelationPersistence.findByUserId1(userId),
2289                                            socialRelations);
2290                            }
2291    
2292                            List<User> users = new ArrayList<>();
2293    
2294                            for (SocialRelation socialRelation : socialRelations) {
2295                                    User user = userPersistence.findByPrimaryKey(
2296                                            socialRelation.getUserId2());
2297    
2298                                    if (user.isDefaultUser() ||
2299                                            (user.getStatus() != WorkflowConstants.STATUS_APPROVED)) {
2300    
2301                                            continue;
2302                                    }
2303    
2304                                    if (!users.contains(user)) {
2305                                            users.add(user);
2306                                    }
2307                            }
2308    
2309                            if (obc != null) {
2310                                    users = ListUtil.sort(users, obc);
2311                            }
2312    
2313                            return users;
2314                    }
2315    
2316                    User user = userPersistence.findByPrimaryKey(userId);
2317    
2318                    return userFinder.findBySocialUsers(
2319                            user.getCompanyId(), userId, socialRelationType,
2320                            socialRelationTypeComparator, WorkflowConstants.STATUS_APPROVED,
2321                            start, end, obc);
2322            }
2323    
2324            /**
2325             * Returns an ordered range of all the users with a mutual social relation
2326             * of the type with both of the given users.
2327             *
2328             * <p>
2329             * Useful when paginating results. Returns a maximum of <code>end -
2330             * start</code> instances. <code>start</code> and <code>end</code> are not
2331             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2332             * refers to the first result in the set. Setting both <code>start</code>
2333             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2334             * result set.
2335             * </p>
2336             *
2337             * @param  userId1 the primary key of the first user
2338             * @param  userId2 the primary key of the second user
2339             * @param  socialRelationType the type of social relation. The possible
2340             *         types can be found in {@link SocialRelationConstants}.
2341             * @param  start the lower bound of the range of users
2342             * @param  end the upper bound of the range of users (not inclusive)
2343             * @param  obc the comparator to order the users by (optionally
2344             *         <code>null</code>)
2345             * @return the ordered range of users with a mutual social relation of the
2346             *         type with the user
2347             */
2348            @Override
2349            public List<User> getSocialUsers(
2350                            long userId1, long userId2, int socialRelationType, int start,
2351                            int end, OrderByComparator<User> obc)
2352                    throws PortalException {
2353    
2354                    User user1 = userPersistence.findByPrimaryKey(userId1);
2355    
2356                    LinkedHashMap<String, Object> params = new LinkedHashMap<>();
2357    
2358                    params.put(
2359                            "socialMutualRelationType",
2360                            new Long[] {
2361                                    userId1, Long.valueOf(socialRelationType), userId2,
2362                                    Long.valueOf(socialRelationType)
2363                            });
2364    
2365                    return search(
2366                            user1.getCompanyId(), null, WorkflowConstants.STATUS_APPROVED,
2367                            params, start, end, obc);
2368            }
2369    
2370            /**
2371             * Returns an ordered range of all the users with a mutual social relation
2372             * with both of the given users.
2373             *
2374             * <p>
2375             * Useful when paginating results. Returns a maximum of <code>end -
2376             * start</code> instances. <code>start</code> and <code>end</code> are not
2377             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2378             * refers to the first result in the set. Setting both <code>start</code>
2379             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2380             * result set.
2381             * </p>
2382             *
2383             * @param  userId1 the primary key of the first user
2384             * @param  userId2 the primary key of the second user
2385             * @param  start the lower bound of the range of users
2386             * @param  end the upper bound of the range of users (not inclusive)
2387             * @param  obc the comparator to order the users by (optionally
2388             *         <code>null</code>)
2389             * @return the ordered range of users with a mutual social relation with the
2390             *         user
2391             */
2392            @Override
2393            public List<User> getSocialUsers(
2394                            long userId1, long userId2, int start, int end,
2395                            OrderByComparator<User> obc)
2396                    throws PortalException {
2397    
2398                    User user1 = userPersistence.findByPrimaryKey(userId1);
2399    
2400                    LinkedHashMap<String, Object> params = new LinkedHashMap<>();
2401    
2402                    params.put("socialMutualRelation", new Long[] {userId1, userId2});
2403    
2404                    return search(
2405                            user1.getCompanyId(), null, WorkflowConstants.STATUS_APPROVED,
2406                            params, start, end, obc);
2407            }
2408    
2409            /**
2410             * Returns the number of users with a social relation with the user.
2411             *
2412             * @param      userId the primary key of the user
2413             * @return     the number of users with a social relation with the user
2414             * @deprecated As of 7.0.0, replaced by {@link #getSocialUsersCount(long,
2415             *             int, String)}
2416             */
2417            @Deprecated
2418            @Override
2419            public int getSocialUsersCount(long userId) throws PortalException {
2420                    return getSocialUsersCount(
2421                            userId, SocialRelationConstants.TYPE_UNI_ENEMY,
2422                            StringPool.NOT_EQUAL);
2423            }
2424    
2425            /**
2426             * Returns the number of users with a social relation of the type with the
2427             * user.
2428             *
2429             * @param      userId the primary key of the user
2430             * @param      socialRelationType the type of social relation. The possible
2431             *             types can be found in {@link SocialRelationConstants}.
2432             * @return     the number of users with a social relation of the type with
2433             *             the user
2434             * @deprecated As of 7.0.0, replaced by {@link #getSocialUsersCount(long,
2435             *             int, String)}
2436             */
2437            @Deprecated
2438            @Override
2439            public int getSocialUsersCount(long userId, int socialRelationType)
2440                    throws PortalException {
2441    
2442                    return getSocialUsersCount(
2443                            userId, socialRelationType, StringPool.EQUAL);
2444            }
2445    
2446            /**
2447             * Returns the number of users with a social relation with the user.
2448             *
2449             * @param  userId the primary key of the user
2450             * @param  socialRelationType the type of social relation. The possible
2451             *         types can be found in {@link SocialRelationConstants}.
2452             * @return the number of users with a social relation with the user
2453             */
2454            @Override
2455            public int getSocialUsersCount(
2456                            long userId, int socialRelationType,
2457                            String socialRelationTypeComparator)
2458                    throws PortalException {
2459    
2460                    User user = userPersistence.findByPrimaryKey(userId);
2461    
2462                    if (!socialRelationTypeComparator.equals(StringPool.EQUAL) &&
2463                            !socialRelationTypeComparator.equals(StringPool.NOT_EQUAL)) {
2464    
2465                            throw new IllegalArgumentException(
2466                                    "Invalid social relation type comparator " +
2467                                            socialRelationTypeComparator);
2468                    }
2469    
2470                    return userFinder.countBySocialUsers(
2471                            user.getCompanyId(), user.getUserId(), socialRelationType,
2472                            socialRelationTypeComparator, WorkflowConstants.STATUS_APPROVED);
2473            }
2474    
2475            /**
2476             * Returns the number of users with a mutual social relation with both of
2477             * the given users.
2478             *
2479             * @param  userId1 the primary key of the first user
2480             * @param  userId2 the primary key of the second user
2481             * @return the number of users with a mutual social relation with the user
2482             */
2483            @Override
2484            public int getSocialUsersCount(long userId1, long userId2)
2485                    throws PortalException {
2486    
2487                    User user1 = userPersistence.findByPrimaryKey(userId1);
2488    
2489                    LinkedHashMap<String, Object> params = new LinkedHashMap<>();
2490    
2491                    params.put("socialMutualRelation", new Long[] {userId1, userId2});
2492    
2493                    return searchCount(
2494                            user1.getCompanyId(), null, WorkflowConstants.STATUS_APPROVED,
2495                            params);
2496            }
2497    
2498            /**
2499             * Returns the number of users with a mutual social relation of the type
2500             * with both of the given users.
2501             *
2502             * @param  userId1 the primary key of the first user
2503             * @param  userId2 the primary key of the second user
2504             * @param  socialRelationType the type of social relation. The possible
2505             *         types can be found in {@link SocialRelationConstants}.
2506             * @return the number of users with a mutual social relation of the type
2507             *         with the user
2508             */
2509            @Override
2510            public int getSocialUsersCount(
2511                            long userId1, long userId2, int socialRelationType)
2512                    throws PortalException {
2513    
2514                    User user1 = userPersistence.findByPrimaryKey(userId1);
2515    
2516                    LinkedHashMap<String, Object> params = new LinkedHashMap<>();
2517    
2518                    params.put(
2519                            "socialMutualRelationType",
2520                            new Long[] {
2521                                    userId1, Long.valueOf(socialRelationType), userId2,
2522                                    Long.valueOf(socialRelationType)
2523                            });
2524    
2525                    return searchCount(
2526                            user1.getCompanyId(), null, WorkflowConstants.STATUS_APPROVED,
2527                            params);
2528            }
2529    
2530            /**
2531             * Returns the user with the contact ID.
2532             *
2533             * @param  contactId the user's contact ID
2534             * @return the user with the contact ID
2535             */
2536            @Override
2537            public User getUserByContactId(long contactId) throws PortalException {
2538                    return userPersistence.findByContactId(contactId);
2539            }
2540    
2541            /**
2542             * Returns the user with the email address.
2543             *
2544             * @param  companyId the primary key of the user's company
2545             * @param  emailAddress the user's email address
2546             * @return the user with the email address
2547             */
2548            @Override
2549            public User getUserByEmailAddress(long companyId, String emailAddress)
2550                    throws PortalException {
2551    
2552                    emailAddress = getLogin(emailAddress);
2553    
2554                    return userPersistence.findByC_EA(companyId, emailAddress);
2555            }
2556    
2557            /**
2558             * Returns the user with the Facebook ID.
2559             *
2560             * @param  companyId the primary key of the user's company
2561             * @param  facebookId the user's Facebook ID
2562             * @return the user with the Facebook ID
2563             */
2564            @Override
2565            public User getUserByFacebookId(long companyId, long facebookId)
2566                    throws PortalException {
2567    
2568                    return userPersistence.findByC_FID(companyId, facebookId);
2569            }
2570    
2571            /**
2572             * Returns the user with the primary key.
2573             *
2574             * @param  userId the primary key of the user
2575             * @return the user with the primary key
2576             */
2577            @Override
2578            public User getUserById(long userId) throws PortalException {
2579                    return userPersistence.findByPrimaryKey(userId);
2580            }
2581    
2582            /**
2583             * Returns the user with the primary key from the company.
2584             *
2585             * @param  companyId the primary key of the user's company
2586             * @param  userId the primary key of the user
2587             * @return the user with the primary key
2588             */
2589            @Override
2590            public User getUserById(long companyId, long userId)
2591                    throws PortalException {
2592    
2593                    return userPersistence.findByC_U(companyId, userId);
2594            }
2595    
2596            /**
2597             * Returns the user with the OpenID.
2598             *
2599             * @param  companyId the primary key of the user's company
2600             * @param  openId the user's OpenID
2601             * @return the user with the OpenID
2602             */
2603            @Override
2604            public User getUserByOpenId(long companyId, String openId)
2605                    throws PortalException {
2606    
2607                    return userPersistence.findByC_O(companyId, openId);
2608            }
2609    
2610            /**
2611             * Returns the user with the portrait ID.
2612             *
2613             * @param  portraitId the user's portrait ID
2614             * @return the user with the portrait ID
2615             */
2616            @Override
2617            public User getUserByPortraitId(long portraitId) throws PortalException {
2618                    return userPersistence.findByPortraitId(portraitId);
2619            }
2620    
2621            /**
2622             * Returns the user with the screen name.
2623             *
2624             * @param  companyId the primary key of the user's company
2625             * @param  screenName the user's screen name
2626             * @return the user with the screen name
2627             */
2628            @Override
2629            public User getUserByScreenName(long companyId, String screenName)
2630                    throws PortalException {
2631    
2632                    screenName = getLogin(screenName);
2633    
2634                    return userPersistence.findByC_SN(companyId, screenName);
2635            }
2636    
2637            /**
2638             * Returns the user with the UUID.
2639             *
2640             * @param  uuid the user's UUID
2641             * @param  companyId the primary key of the user's company
2642             * @return the user with the UUID
2643             */
2644            @Override
2645            public User getUserByUuidAndCompanyId(String uuid, long companyId)
2646                    throws PortalException {
2647    
2648                    List<User> users = userPersistence.findByUuid_C(uuid, companyId);
2649    
2650                    if (users.isEmpty()) {
2651                            StringBundler sb = new StringBundler(5);
2652    
2653                            sb.append("{uuid=");
2654                            sb.append(uuid);
2655                            sb.append(", companyId=");
2656                            sb.append(companyId);
2657                            sb.append("}");
2658    
2659                            throw new NoSuchUserException(sb.toString());
2660                    }
2661                    else {
2662                            return users.get(0);
2663                    }
2664            }
2665    
2666            /**
2667             * Returns the number of users with the status belonging to the user group.
2668             *
2669             * @param  userGroupId the primary key of the user group
2670             * @param  status the workflow status
2671             * @return the number of users with the status belonging to the user group
2672             */
2673            @Override
2674            public int getUserGroupUsersCount(long userGroupId, int status)
2675                    throws PortalException {
2676    
2677                    UserGroup userGroup = userGroupPersistence.findByPrimaryKey(
2678                            userGroupId);
2679    
2680                    LinkedHashMap<String, Object> params = new LinkedHashMap<>();
2681    
2682                    params.put("usersUserGroups", Long.valueOf(userGroupId));
2683    
2684                    return searchCount(userGroup.getCompanyId(), null, status, params);
2685            }
2686    
2687            /**
2688             * Returns the primary key of the user with the email address.
2689             *
2690             * @param  companyId the primary key of the user's company
2691             * @param  emailAddress the user's email address
2692             * @return the primary key of the user with the email address
2693             */
2694            @Override
2695            public long getUserIdByEmailAddress(long companyId, String emailAddress)
2696                    throws PortalException {
2697    
2698                    emailAddress = StringUtil.toLowerCase(emailAddress.trim());
2699    
2700                    User user = userPersistence.findByC_EA(companyId, emailAddress);
2701    
2702                    return user.getUserId();
2703            }
2704    
2705            /**
2706             * Returns the primary key of the user with the screen name.
2707             *
2708             * @param  companyId the primary key of the user's company
2709             * @param  screenName the user's screen name
2710             * @return the primary key of the user with the screen name
2711             */
2712            @Override
2713            public long getUserIdByScreenName(long companyId, String screenName)
2714                    throws PortalException {
2715    
2716                    screenName = getLogin(screenName);
2717    
2718                    User user = userPersistence.findByC_SN(companyId, screenName);
2719    
2720                    return user.getUserId();
2721            }
2722    
2723            /**
2724             * Returns <code>true</code> if the password policy has been assigned to the
2725             * user.
2726             *
2727             * @param  passwordPolicyId the primary key of the password policy
2728             * @param  userId the primary key of the user
2729             * @return <code>true</code> if the password policy is assigned to the user;
2730             *         <code>false</code> otherwise
2731             */
2732            @Override
2733            public boolean hasPasswordPolicyUser(long passwordPolicyId, long userId) {
2734                    return passwordPolicyRelLocalService.hasPasswordPolicyRel(
2735                            passwordPolicyId, User.class.getName(), userId);
2736            }
2737    
2738            /**
2739             * Returns <code>true</code> if the user has the role with the name,
2740             * optionally through inheritance.
2741             *
2742             * @param  companyId the primary key of the role's company
2743             * @param  name the name of the role (must be a regular role, not an
2744             *         organization, site or provider role)
2745             * @param  userId the primary key of the user
2746             * @param  inherited whether to include roles inherited from organizations,
2747             *         sites, etc.
2748             * @return <code>true</code> if the user has the role; <code>false</code>
2749             *         otherwise
2750             */
2751            @Override
2752            public boolean hasRoleUser(
2753                            long companyId, String name, long userId, boolean inherited)
2754                    throws PortalException {
2755    
2756                    return roleLocalService.hasUserRole(userId, companyId, name, inherited);
2757            }
2758    
2759            /**
2760             * Returns <code>true</code> if the user's password is expired.
2761             *
2762             * @param  user the user
2763             * @return <code>true</code> if the user's password is expired;
2764             *         <code>false</code> otherwise
2765             */
2766            @Override
2767            public boolean isPasswordExpired(User user) throws PortalException {
2768                    PasswordPolicy passwordPolicy = user.getPasswordPolicy();
2769    
2770                    if ((passwordPolicy != null) && passwordPolicy.getExpireable()) {
2771                            Date now = new Date();
2772    
2773                            if (user.getPasswordModifiedDate() == null) {
2774                                    user.setPasswordModifiedDate(now);
2775    
2776                                    userLocalService.updateUser(user);
2777                            }
2778    
2779                            long passwordStartTime = user.getPasswordModifiedDate().getTime();
2780                            long elapsedTime = now.getTime() - passwordStartTime;
2781    
2782                            if (elapsedTime > (passwordPolicy.getMaxAge() * 1000)) {
2783                                    return true;
2784                            }
2785                            else {
2786                                    return false;
2787                            }
2788                    }
2789    
2790                    return false;
2791            }
2792    
2793            /**
2794             * Returns <code>true</code> if the password policy is configured to warn
2795             * the user that his password is expiring and the remaining time until
2796             * expiration is equal or less than the configured warning time.
2797             *
2798             * @param  user the user
2799             * @return <code>true</code> if the user's password is expiring soon;
2800             *         <code>false</code> otherwise
2801             */
2802            @Override
2803            public boolean isPasswordExpiringSoon(User user) throws PortalException {
2804                    PasswordPolicy passwordPolicy = user.getPasswordPolicy();
2805    
2806                    if ((passwordPolicy != null) && passwordPolicy.isExpireable() &&
2807                            (passwordPolicy.getWarningTime() > 0)) {
2808    
2809                            Date now = new Date();
2810    
2811                            if (user.getPasswordModifiedDate() == null) {
2812                                    user.setPasswordModifiedDate(now);
2813    
2814                                    userLocalService.updateUser(user);
2815                            }
2816    
2817                            long timeModified = user.getPasswordModifiedDate().getTime();
2818                            long passwordExpiresOn =
2819                                    (passwordPolicy.getMaxAge() * 1000) + timeModified;
2820    
2821                            long timeStartWarning =
2822                                    passwordExpiresOn - (passwordPolicy.getWarningTime() * 1000);
2823    
2824                            if (now.getTime() > timeStartWarning) {
2825                                    return true;
2826                            }
2827                            else {
2828                                    return false;
2829                            }
2830                    }
2831    
2832                    return false;
2833            }
2834    
2835            /**
2836             * Returns the default user for the company.
2837             *
2838             * @param  companyId the primary key of the company
2839             * @return the default user for the company
2840             */
2841            @Override
2842            public User loadGetDefaultUser(long companyId) throws PortalException {
2843                    return userPersistence.findByC_DU(companyId, true);
2844            }
2845    
2846            /**
2847             * Returns an ordered range of all the users who match the keywords and
2848             * status, without using the indexer. It is preferable to use the indexed
2849             * version {@link #search(long, String, int, LinkedHashMap, int, int, Sort)}
2850             * instead of this method wherever possible for performance reasons.
2851             *
2852             * <p>
2853             * Useful when paginating results. Returns a maximum of <code>end -
2854             * start</code> instances. <code>start</code> and <code>end</code> are not
2855             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2856             * refers to the first result in the set. Setting both <code>start</code>
2857             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2858             * result set.
2859             * </p>
2860             *
2861             * @param  companyId the primary key of the user's company
2862             * @param  keywords the keywords (space separated), which may occur in the
2863             *         user's first name, middle name, last name, screen name, or email
2864             *         address
2865             * @param  status the workflow status
2866             * @param  params the finder parameters (optionally <code>null</code>). For
2867             *         more information see {@link
2868             *         com.liferay.portal.service.persistence.UserFinder}.
2869             * @param  start the lower bound of the range of users
2870             * @param  end the upper bound of the range of users (not inclusive)
2871             * @param  obc the comparator to order the users by (optionally
2872             *         <code>null</code>)
2873             * @return the matching users
2874             * @see    com.liferay.portal.service.persistence.UserFinder
2875             */
2876            @Override
2877            public List<User> search(
2878                    long companyId, String keywords, int status,
2879                    LinkedHashMap<String, Object> params, int start, int end,
2880                    OrderByComparator<User> obc) {
2881    
2882                    Indexer<?> indexer = IndexerRegistryUtil.nullSafeGetIndexer(User.class);
2883    
2884                    if (!indexer.isIndexerEnabled() ||
2885                            !PropsValues.USERS_SEARCH_WITH_INDEX || isUseCustomSQL(params)) {
2886    
2887                            return userFinder.findByKeywords(
2888                                    companyId, keywords, status, params, start, end, obc);
2889                    }
2890    
2891                    try {
2892                            return UsersAdminUtil.getUsers(
2893                                    search(
2894                                            companyId, keywords, status, params, start, end,
2895                                            getSorts(obc)));
2896                    }
2897                    catch (Exception e) {
2898                            throw new SystemException(e);
2899                    }
2900            }
2901    
2902            /**
2903             * Returns an ordered range of all the users who match the keywords and
2904             * status, using the indexer. It is preferable to use this method instead of
2905             * the non-indexed version whenever possible for performance reasons.
2906             *
2907             * <p>
2908             * Useful when paginating results. Returns a maximum of <code>end -
2909             * start</code> instances. <code>start</code> and <code>end</code> are not
2910             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2911             * refers to the first result in the set. Setting both <code>start</code>
2912             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2913             * result set.
2914             * </p>
2915             *
2916             * @param  companyId the primary key of the user's company
2917             * @param  keywords the keywords (space separated), which may occur in the
2918             *         user's first name, middle name, last name, screen name, or email
2919             *         address
2920             * @param  status the workflow status
2921             * @param  params the indexer parameters (optionally <code>null</code>). For
2922             *         more information see {@link
2923             *         com.liferay.portlet.usersadmin.util.UserIndexer}.
2924             * @param  start the lower bound of the range of users
2925             * @param  end the upper bound of the range of users (not inclusive)
2926             * @param  sort the field and direction to sort by (optionally
2927             *         <code>null</code>)
2928             * @return the matching users
2929             * @see    com.liferay.portlet.usersadmin.util.UserIndexer
2930             */
2931            @Override
2932            public Hits search(
2933                    long companyId, String keywords, int status,
2934                    LinkedHashMap<String, Object> params, int start, int end, Sort sort) {
2935    
2936                    return search(
2937                            companyId, keywords, status, params, start, end, new Sort[] {sort});
2938            }
2939    
2940            @Override
2941            public Hits search(
2942                    long companyId, String keywords, int status,
2943                    LinkedHashMap<String, Object> params, int start, int end,
2944                    Sort[] sorts) {
2945    
2946                    String firstName = null;
2947                    String middleName = null;
2948                    String lastName = null;
2949                    String fullName = null;
2950                    String screenName = null;
2951                    String emailAddress = null;
2952                    String street = null;
2953                    String city = null;
2954                    String zip = null;
2955                    String region = null;
2956                    String country = null;
2957                    boolean andOperator = false;
2958    
2959                    if (Validator.isNotNull(keywords)) {
2960                            firstName = keywords;
2961                            middleName = keywords;
2962                            lastName = keywords;
2963                            fullName = keywords;
2964                            screenName = keywords;
2965                            emailAddress = keywords;
2966                            street = keywords;
2967                            city = keywords;
2968                            zip = keywords;
2969                            region = keywords;
2970                            country = keywords;
2971                    }
2972                    else {
2973                            andOperator = true;
2974                    }
2975    
2976                    if (params != null) {
2977                            params.put("keywords", keywords);
2978                    }
2979    
2980                    try {
2981                            Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
2982                                    User.class);
2983    
2984                            SearchContext searchContext = buildSearchContext(
2985                                    companyId, firstName, middleName, lastName, fullName,
2986                                    screenName, emailAddress, street, city, zip, region, country,
2987                                    status, params, andOperator, start, end, sorts);
2988    
2989                            return indexer.search(searchContext);
2990                    }
2991                    catch (Exception e) {
2992                            throw new SystemException(e);
2993                    }
2994            }
2995    
2996            /**
2997             * Returns an ordered range of all the users with the status, and whose
2998             * first name, middle name, last name, screen name, and email address match
2999             * the keywords specified for them, without using the indexer. It is
3000             * preferable to use the indexed version {@link #search(long, String,
3001             * String, String, String, String, int, LinkedHashMap, boolean, int, int,
3002             * Sort)} instead of this method wherever possible for performance reasons.
3003             *
3004             * <p>
3005             * Useful when paginating results. Returns a maximum of <code>end -
3006             * start</code> instances. <code>start</code> and <code>end</code> are not
3007             * primary keys, they are indexes in the result set. Thus, <code>0</code>
3008             * refers to the first result in the set. Setting both <code>start</code>
3009             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
3010             * result set.
3011             * </p>
3012             *
3013             * @param  companyId the primary key of the user's company
3014             * @param  firstName the first name keywords (space separated)
3015             * @param  middleName the middle name keywords
3016             * @param  lastName the last name keywords
3017             * @param  screenName the screen name keywords
3018             * @param  emailAddress the email address keywords
3019             * @param  status the workflow status
3020             * @param  params the finder parameters (optionally <code>null</code>). For
3021             *         more information see {@link
3022             *         com.liferay.portal.service.persistence.UserFinder}.
3023             * @param  andSearch whether every field must match its keywords, or just
3024             *         one field. For example, &quot;users with the first name 'bob' and
3025             *         last name 'smith'&quot; vs &quot;users with the first name 'bob'
3026             *         or the last name 'smith'&quot;.
3027             * @param  start the lower bound of the range of users
3028             * @param  end the upper bound of the range of users (not inclusive)
3029             * @param  obc the comparator to order the users by (optionally
3030             *         <code>null</code>)
3031             * @return the matching users
3032             * @see    com.liferay.portal.service.persistence.UserFinder
3033             */
3034            @Override
3035            public List<User> search(
3036                    long companyId, String firstName, String middleName, String lastName,
3037                    String screenName, String emailAddress, int status,
3038                    LinkedHashMap<String, Object> params, boolean andSearch, int start,
3039                    int end, OrderByComparator<User> obc) {
3040    
3041                    Indexer<?> indexer = IndexerRegistryUtil.nullSafeGetIndexer(User.class);
3042    
3043                    if (!indexer.isIndexerEnabled() ||
3044                            !PropsValues.USERS_SEARCH_WITH_INDEX || isUseCustomSQL(params)) {
3045    
3046                            return userFinder.findByC_FN_MN_LN_SN_EA_S(
3047                                    companyId, firstName, middleName, lastName, screenName,
3048                                    emailAddress, status, params, andSearch, start, end, obc);
3049                    }
3050    
3051                    try {
3052                            return UsersAdminUtil.getUsers(
3053                                    search(
3054                                            companyId, firstName, middleName, lastName, screenName,
3055                                            emailAddress, status, params, andSearch, start, end,
3056                                            getSorts(obc)));
3057                    }
3058                    catch (Exception e) {
3059                            throw new SystemException(e);
3060                    }
3061            }
3062    
3063            /**
3064             * Returns an ordered range of all the users with the status, and whose
3065             * first name, middle name, last name, screen name, and email address match
3066             * the keywords specified for them, using the indexer. It is preferable to
3067             * use this method instead of the non-indexed version whenever possible for
3068             * performance reasons.
3069             *
3070             * <p>
3071             * Useful when paginating results. Returns a maximum of <code>end -
3072             * start</code> instances. <code>start</code> and <code>end</code> are not
3073             * primary keys, they are indexes in the result set. Thus, <code>0</code>
3074             * refers to the first result in the set. Setting both <code>start</code>
3075             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
3076             * result set.
3077             * </p>
3078             *
3079             * @param  companyId the primary key of the user's company
3080             * @param  firstName the first name keywords (space separated)
3081             * @param  middleName the middle name keywords
3082             * @param  lastName the last name keywords
3083             * @param  screenName the screen name keywords
3084             * @param  emailAddress the email address keywords
3085             * @param  status the workflow status
3086             * @param  params the indexer parameters (optionally <code>null</code>). For
3087             *         more information see {@link
3088             *         com.liferay.portlet.usersadmin.util.UserIndexer}.
3089             * @param  andSearch whether every field must match its keywords, or just
3090             *         one field. For example, &quot;users with the first name 'bob' and
3091             *         last name 'smith'&quot; vs &quot;users with the first name 'bob'
3092             *         or the last name 'smith'&quot;.
3093             * @param  start the lower bound of the range of users
3094             * @param  end the upper bound of the range of users (not inclusive)
3095             * @param  sort the field and direction to sort by (optionally
3096             *         <code>null</code>)
3097             * @return the matching users
3098             * @see    com.liferay.portlet.usersadmin.util.UserIndexer
3099             */
3100            @Override
3101            public Hits search(
3102                    long companyId, String firstName, String middleName, String lastName,
3103                    String screenName, String emailAddress, int status,
3104                    LinkedHashMap<String, Object> params, boolean andSearch, int start,
3105                    int end, Sort sort) {
3106    
3107                    return search(
3108                            companyId, firstName, middleName, lastName, screenName,
3109                            emailAddress, status, params, andSearch, start, end,
3110                            new Sort[] {sort});
3111            }
3112    
3113            @Override
3114            public Hits search(
3115                    long companyId, String firstName, String middleName, String lastName,
3116                    String screenName, String emailAddress, int status,
3117                    LinkedHashMap<String, Object> params, boolean andSearch, int start,
3118                    int end, Sort[] sorts) {
3119    
3120                    try {
3121                            Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
3122                                    User.class);
3123    
3124                            SearchContext searchContext = buildSearchContext(
3125                                    companyId, firstName, middleName, lastName, null, screenName,
3126                                    emailAddress, null, null, null, null, null, status, params,
3127                                    andSearch, start, end, sorts);
3128    
3129                            return indexer.search(searchContext);
3130                    }
3131                    catch (Exception e) {
3132                            throw new SystemException(e);
3133                    }
3134            }
3135    
3136            /**
3137             * Returns the number of users who match the keywords and status.
3138             *
3139             * @param  companyId the primary key of the user's company
3140             * @param  keywords the keywords (space separated), which may occur in the
3141             *         user's first name, middle name, last name, screen name, or email
3142             *         address
3143             * @param  status the workflow status
3144             * @param  params the finder parameters (optionally <code>null</code>). For
3145             *         more information see {@link
3146             *         com.liferay.portal.service.persistence.UserFinder}.
3147             * @return the number matching users
3148             */
3149            @Override
3150            public int searchCount(
3151                    long companyId, String keywords, int status,
3152                    LinkedHashMap<String, Object> params) {
3153    
3154                    Indexer<?> indexer = IndexerRegistryUtil.nullSafeGetIndexer(User.class);
3155    
3156                    if (!indexer.isIndexerEnabled() ||
3157                            !PropsValues.USERS_SEARCH_WITH_INDEX || isUseCustomSQL(params)) {
3158    
3159                            return userFinder.countByKeywords(
3160                                    companyId, keywords, status, params);
3161                    }
3162    
3163                    try {
3164                            String firstName = null;
3165                            String middleName = null;
3166                            String lastName = null;
3167                            String fullName = null;
3168                            String screenName = null;
3169                            String emailAddress = null;
3170                            String street = null;
3171                            String city = null;
3172                            String zip = null;
3173                            String region = null;
3174                            String country = null;
3175                            boolean andOperator = false;
3176    
3177                            if (Validator.isNotNull(keywords)) {
3178                                    firstName = keywords;
3179                                    middleName = keywords;
3180                                    lastName = keywords;
3181                                    fullName = keywords;
3182                                    screenName = keywords;
3183                                    emailAddress = keywords;
3184                                    street = keywords;
3185                                    city = keywords;
3186                                    zip = keywords;
3187                                    region = keywords;
3188                                    country = keywords;
3189                            }
3190                            else {
3191                                    andOperator = true;
3192                            }
3193    
3194                            if (params != null) {
3195                                    params.put("keywords", keywords);
3196                            }
3197    
3198                            SearchContext searchContext = buildSearchContext(
3199                                    companyId, firstName, middleName, lastName, fullName,
3200                                    screenName, emailAddress, street, city, zip, region, country,
3201                                    status, params, andOperator, QueryUtil.ALL_POS,
3202                                    QueryUtil.ALL_POS, null);
3203    
3204                            return (int)indexer.searchCount(searchContext);
3205                    }
3206                    catch (Exception e) {
3207                            throw new SystemException(e);
3208                    }
3209            }
3210    
3211            /**
3212             * Returns the number of users with the status, and whose first name, middle
3213             * name, last name, screen name, and email address match the keywords
3214             * specified for them.
3215             *
3216             * @param  companyId the primary key of the user's company
3217             * @param  firstName the first name keywords (space separated)
3218             * @param  middleName the middle name keywords
3219             * @param  lastName the last name keywords
3220             * @param  screenName the screen name keywords
3221             * @param  emailAddress the email address keywords
3222             * @param  status the workflow status
3223             * @param  params the finder parameters (optionally <code>null</code>). For
3224             *         more information see {@link
3225             *         com.liferay.portal.service.persistence.UserFinder}.
3226             * @param  andSearch whether every field must match its keywords, or just
3227             *         one field. For example, &quot;users with the first name 'bob' and
3228             *         last name 'smith'&quot; vs &quot;users with the first name 'bob'
3229             *         or the last name 'smith'&quot;.
3230             * @return the number of matching users
3231             */
3232            @Override
3233            public int searchCount(
3234                    long companyId, String firstName, String middleName, String lastName,
3235                    String screenName, String emailAddress, int status,
3236                    LinkedHashMap<String, Object> params, boolean andSearch) {
3237    
3238                    Indexer<?> indexer = IndexerRegistryUtil.nullSafeGetIndexer(User.class);
3239    
3240                    if (!indexer.isIndexerEnabled() ||
3241                            !PropsValues.USERS_SEARCH_WITH_INDEX || isUseCustomSQL(params)) {
3242    
3243                            return userFinder.countByC_FN_MN_LN_SN_EA_S(
3244                                    companyId, firstName, middleName, lastName, screenName,
3245                                    emailAddress, status, params, andSearch);
3246                    }
3247    
3248                    try {
3249                            FullNameGenerator fullNameGenerator =
3250                                    FullNameGeneratorFactory.getInstance();
3251    
3252                            String fullName = fullNameGenerator.getFullName(
3253                                    firstName, middleName, lastName);
3254    
3255                            SearchContext searchContext = buildSearchContext(
3256                                    companyId, firstName, middleName, lastName, fullName,
3257                                    screenName, emailAddress, null, null, null, null, null, status,
3258                                    params, true, QueryUtil.ALL_POS, QueryUtil.ALL_POS, null);
3259    
3260                            return (int)indexer.searchCount(searchContext);
3261                    }
3262                    catch (Exception e) {
3263                            throw new SystemException(e);
3264                    }
3265            }
3266    
3267            @Override
3268            public Map<Long, Integer> searchCounts(
3269                    long companyId, int status, long[] groupIds) {
3270    
3271                    return userFinder.countByGroups(companyId, status, groupIds);
3272            }
3273    
3274            @Override
3275            public List<User> searchSocial(
3276                            long userId, int[] socialRelationTypes, String keywords, int start,
3277                            int end)
3278                    throws PortalException {
3279    
3280                    User user = userPersistence.findByPrimaryKey(userId);
3281    
3282                    LinkedHashMap<String, Object> params = new LinkedHashMap<>();
3283    
3284                    params.put(
3285                            "socialRelationType",
3286                            new Long[][] {
3287                                    new Long[] {userId}, ArrayUtil.toLongArray(socialRelationTypes)
3288                            });
3289                    params.put("wildcardMode", WildcardMode.TRAILING);
3290    
3291                    return userFinder.findByKeywords(
3292                            user.getCompanyId(), keywords, WorkflowConstants.STATUS_APPROVED,
3293                            params, start, end, null);
3294            }
3295    
3296            @Override
3297            public List<User> searchSocial(
3298                    long companyId, long[] groupIds, String keywords, int start, int end) {
3299    
3300                    LinkedHashMap<String, Object> params = new LinkedHashMap<>();
3301    
3302                    params.put("usersGroups", ArrayUtil.toLongArray(groupIds));
3303                    params.put("wildcardMode", WildcardMode.TRAILING);
3304    
3305                    return userFinder.findByKeywords(
3306                            companyId, keywords, WorkflowConstants.STATUS_APPROVED, params,
3307                            start, end, null);
3308            }
3309    
3310            @Override
3311            public List<User> searchSocial(
3312                            long[] groupIds, long userId, int[] socialRelationTypes,
3313                            String keywords, int start, int end)
3314                    throws PortalException {
3315    
3316                    User user = userPersistence.findByPrimaryKey(userId);
3317    
3318                    LinkedHashMap<String, Object> params = new LinkedHashMap<>();
3319    
3320                    params.put(
3321                            "socialRelationType",
3322                            new Long[][] {
3323                                    new Long[] {userId}, ArrayUtil.toLongArray(socialRelationTypes)
3324                            });
3325                    params.put("socialRelationTypeUnionUserGroups", true);
3326                    params.put("usersGroups", ArrayUtil.toLongArray(groupIds));
3327                    params.put("wildcardMode", WildcardMode.TRAILING);
3328    
3329                    return userFinder.findByKeywords(
3330                            user.getCompanyId(), keywords, WorkflowConstants.STATUS_APPROVED,
3331                            params, start, end, null);
3332            }
3333    
3334            @Override
3335            public BaseModelSearchResult<User> searchUsers(
3336                            long companyId, String keywords, int status,
3337                            LinkedHashMap<String, Object> params, int start, int end, Sort sort)
3338                    throws PortalException {
3339    
3340                    return searchUsers(
3341                            companyId, keywords, status, params, start, end, new Sort[] {sort});
3342            }
3343    
3344            @Override
3345            public BaseModelSearchResult<User> searchUsers(
3346                            long companyId, String keywords, int status,
3347                            LinkedHashMap<String, Object> params, int start, int end,
3348                            Sort[] sorts)
3349                    throws PortalException {
3350    
3351                    String firstName = null;
3352                    String middleName = null;
3353                    String lastName = null;
3354                    String fullName = null;
3355                    String screenName = null;
3356                    String emailAddress = null;
3357                    String street = null;
3358                    String city = null;
3359                    String zip = null;
3360                    String region = null;
3361                    String country = null;
3362                    boolean andOperator = false;
3363    
3364                    if (Validator.isNotNull(keywords)) {
3365                            firstName = keywords;
3366                            middleName = keywords;
3367                            lastName = keywords;
3368                            fullName = keywords;
3369                            screenName = keywords;
3370                            emailAddress = keywords;
3371                            street = keywords;
3372                            city = keywords;
3373                            zip = keywords;
3374                            region = keywords;
3375                            country = keywords;
3376                    }
3377                    else {
3378                            andOperator = true;
3379                    }
3380    
3381                    if (params != null) {
3382                            params.put("keywords", keywords);
3383                    }
3384    
3385                    SearchContext searchContext = buildSearchContext(
3386                            companyId, firstName, middleName, lastName, fullName, screenName,
3387                            emailAddress, street, city, zip, region, country, status, params,
3388                            andOperator, start, end, sorts);
3389    
3390                    return searchUsers(searchContext);
3391            }
3392    
3393            @Override
3394            public BaseModelSearchResult<User> searchUsers(
3395                            long companyId, String firstName, String middleName,
3396                            String lastName, String screenName, String emailAddress, int status,
3397                            LinkedHashMap<String, Object> params, boolean andSearch, int start,
3398                            int end, Sort sort)
3399                    throws PortalException {
3400    
3401                    return searchUsers(
3402                            companyId, firstName, middleName, lastName, screenName,
3403                            emailAddress, status, params, andSearch, start, end,
3404                            new Sort[] {sort});
3405            }
3406    
3407            @Override
3408            public BaseModelSearchResult<User> searchUsers(
3409                            long companyId, String firstName, String middleName,
3410                            String lastName, String screenName, String emailAddress, int status,
3411                            LinkedHashMap<String, Object> params, boolean andSearch, int start,
3412                            int end, Sort[] sorts)
3413                    throws PortalException {
3414    
3415                    SearchContext searchContext = buildSearchContext(
3416                            companyId, firstName, middleName, lastName, null, screenName,
3417                            emailAddress, null, null, null, null, null, status, params,
3418                            andSearch, start, end, sorts);
3419    
3420                    return searchUsers(searchContext);
3421            }
3422    
3423            /**
3424             * Sends an email address verification to the user.
3425             *
3426             * @param user the verification email recipient
3427             * @param emailAddress the recipient's email address
3428             * @param serviceContext the service context to be applied. Must set the
3429             *        portal URL, main path, primary key of the layout, remote address,
3430             *        remote host, and agent for the user.
3431             */
3432            @Override
3433            public void sendEmailAddressVerification(
3434                            User user, String emailAddress, ServiceContext serviceContext)
3435                    throws PortalException {
3436    
3437                    if (user.isEmailAddressVerified() &&
3438                            StringUtil.equalsIgnoreCase(emailAddress, user.getEmailAddress())) {
3439    
3440                            return;
3441                    }
3442    
3443                    Ticket ticket = ticketLocalService.addDistinctTicket(
3444                            user.getCompanyId(), User.class.getName(), user.getUserId(),
3445                            TicketConstants.TYPE_EMAIL_ADDRESS, emailAddress, null,
3446                            serviceContext);
3447    
3448                    String verifyEmailAddressURL =
3449                            serviceContext.getPortalURL() + serviceContext.getPathMain() +
3450                                    "/portal/verify_email_address?ticketKey=" + ticket.getKey();
3451    
3452                    long plid = serviceContext.getPlid();
3453    
3454                    if (plid > 0) {
3455                            Layout layout = layoutLocalService.fetchLayout(plid);
3456    
3457                            if (layout != null) {
3458                                    Group group = layout.getGroup();
3459    
3460                                    if (!layout.isPrivateLayout() && !group.isUser()) {
3461                                            verifyEmailAddressURL +=
3462                                                    "&p_l_id=" + serviceContext.getPlid();
3463                                    }
3464                            }
3465                    }
3466    
3467                    String fromName = PrefsPropsUtil.getString(
3468                            user.getCompanyId(), PropsKeys.ADMIN_EMAIL_FROM_NAME);
3469                    String fromAddress = PrefsPropsUtil.getString(
3470                            user.getCompanyId(), PropsKeys.ADMIN_EMAIL_FROM_ADDRESS);
3471    
3472                    String toName = user.getFullName();
3473                    String toAddress = emailAddress;
3474    
3475                    PortletPreferences companyPortletPreferences =
3476                            PrefsPropsUtil.getPreferences(user.getCompanyId(), true);
3477    
3478                    Map<Locale, String> localizedSubjectMap =
3479                            LocalizationUtil.getLocalizationMap(
3480                                    companyPortletPreferences, "adminEmailVerificationSubject",
3481                                    PropsKeys.ADMIN_EMAIL_VERIFICATION_SUBJECT);
3482                    Map<Locale, String> localizedBodyMap =
3483                            LocalizationUtil.getLocalizationMap(
3484                                    companyPortletPreferences, "adminEmailVerificationBody",
3485                                    PropsKeys.ADMIN_EMAIL_VERIFICATION_BODY);
3486    
3487                    SubscriptionSender subscriptionSender = new SubscriptionSender();
3488    
3489                    subscriptionSender.setCompanyId(user.getCompanyId());
3490                    subscriptionSender.setContextAttributes(
3491                            "[$EMAIL_VERIFICATION_CODE$]", ticket.getKey(),
3492                            "[$EMAIL_VERIFICATION_URL$]", verifyEmailAddressURL,
3493                            "[$REMOTE_ADDRESS$]", serviceContext.getRemoteAddr(),
3494                            "[$REMOTE_HOST$]", serviceContext.getRemoteHost(), "[$USER_ID$]",
3495                            user.getUserId(), "[$USER_SCREENNAME$]", user.getScreenName());
3496                    subscriptionSender.setFrom(fromAddress, fromName);
3497                    subscriptionSender.setHtmlFormat(true);
3498                    subscriptionSender.setLocalizedBodyMap(localizedBodyMap);
3499                    subscriptionSender.setLocalizedSubjectMap(localizedSubjectMap);
3500                    subscriptionSender.setMailId("user", user.getUserId());
3501                    subscriptionSender.setServiceContext(serviceContext);
3502    
3503                    subscriptionSender.addRuntimeSubscribers(toAddress, toName);
3504    
3505                    subscriptionSender.flushNotificationsAsync();
3506            }
3507    
3508            /**
3509             * Sends the password email to the user with the email address. The content
3510             * of this email can be specified in <code>portal.properties</code> with the
3511             * <code>admin.email.password</code> keys.
3512             *
3513             * @param companyId the primary key of the user's company
3514             * @param emailAddress the user's email address
3515             * @param fromName the name of the individual that the email should be from
3516             * @param fromAddress the address of the individual that the email should be
3517             *        from
3518             * @param subject the email subject. If <code>null</code>, the subject
3519             *        specified in <code>portal.properties</code> will be used.
3520             * @param body the email body. If <code>null</code>, the body specified in
3521             *        <code>portal.properties</code> will be used.
3522             * @param serviceContext the service context to be applied
3523             */
3524            @Override
3525            public boolean sendPassword(
3526                            long companyId, String emailAddress, String fromName,
3527                            String fromAddress, String subject, String body,
3528                            ServiceContext serviceContext)
3529                    throws PortalException {
3530    
3531                    Company company = companyPersistence.findByPrimaryKey(companyId);
3532    
3533                    if (!company.isSendPassword() && !company.isSendPasswordResetLink()) {
3534                            throw new SendPasswordException.MustBeEnabled(company);
3535                    }
3536    
3537                    emailAddress = StringUtil.toLowerCase(emailAddress.trim());
3538    
3539                    if (Validator.isNull(emailAddress)) {
3540                            throw new UserEmailAddressException.MustNotBeNull();
3541                    }
3542    
3543                    User user = userPersistence.findByC_EA(companyId, emailAddress);
3544    
3545                    PasswordPolicy passwordPolicy = user.getPasswordPolicy();
3546    
3547                    String newPassword = StringPool.BLANK;
3548                    String passwordResetURL = StringPool.BLANK;
3549    
3550                    if (company.isSendPasswordResetLink()) {
3551                            Date expirationDate = null;
3552    
3553                            if ((passwordPolicy != null) &&
3554                                    (passwordPolicy.getResetTicketMaxAge() > 0)) {
3555    
3556                                    expirationDate = new Date(
3557                                            System.currentTimeMillis() +
3558                                                    (passwordPolicy.getResetTicketMaxAge() * 1000));
3559                            }
3560    
3561                            Ticket ticket = ticketLocalService.addDistinctTicket(
3562                                    companyId, User.class.getName(), user.getUserId(),
3563                                    TicketConstants.TYPE_PASSWORD, null, expirationDate,
3564                                    serviceContext);
3565    
3566                            passwordResetURL =
3567                                    serviceContext.getPortalURL() + serviceContext.getPathMain() +
3568                                            "/portal/update_password?p_l_id="+
3569                                                    serviceContext.getPlid() +
3570                                                            "&ticketKey=" + ticket.getKey();
3571                    }
3572                    else {
3573                            if (!Validator.equals(
3574                                            PasswordEncryptorUtil.getDefaultPasswordAlgorithmType(),
3575                                            PasswordEncryptorUtil.TYPE_NONE)) {
3576    
3577                                    if (LDAPSettingsUtil.isPasswordPolicyEnabled(
3578                                                    user.getCompanyId())) {
3579    
3580                                            if (_log.isWarnEnabled()) {
3581                                                    StringBundler sb = new StringBundler(5);
3582    
3583                                                    sb.append("When LDAP password policy is enabled, ");
3584                                                    sb.append("it is possible that portal generated ");
3585                                                    sb.append("passwords will not match the LDAP policy.");
3586                                                    sb.append("Using RegExpToolkit to generate new ");
3587                                                    sb.append("password.");
3588    
3589                                                    _log.warn(sb.toString());
3590                                            }
3591    
3592                                            RegExpToolkit regExpToolkit = new RegExpToolkit();
3593    
3594                                            newPassword = regExpToolkit.generate(null);
3595                                    }
3596                                    else {
3597                                            newPassword = PwdToolkitUtil.generate(passwordPolicy);
3598                                    }
3599    
3600                                    boolean passwordReset = false;
3601    
3602                                    if (passwordPolicy.getChangeable() &&
3603                                            passwordPolicy.getChangeRequired()) {
3604    
3605                                            passwordReset = true;
3606                                    }
3607    
3608                                    user.setPassword(PasswordEncryptorUtil.encrypt(newPassword));
3609                                    user.setPasswordUnencrypted(newPassword);
3610                                    user.setPasswordEncrypted(true);
3611                                    user.setPasswordReset(passwordReset);
3612                                    user.setPasswordModified(true);
3613                                    user.setPasswordModifiedDate(new Date());
3614    
3615                                    userPersistence.update(user);
3616    
3617                                    user.setPasswordModified(false);
3618                            }
3619                            else {
3620                                    newPassword = user.getPassword();
3621                            }
3622                    }
3623    
3624                    sendPasswordNotification(
3625                            user, companyId, newPassword, passwordResetURL, fromName,
3626                            fromAddress, subject, body, serviceContext);
3627    
3628                    return company.isSendPassword();
3629            }
3630    
3631            /**
3632             * Sends a password notification email to the user matching the email
3633             * address. The portal's settings determine whether a password is sent
3634             * explicitly or whether a link for resetting the user's password is sent.
3635             * The method sends the email asynchronously and returns before the email is
3636             * sent.
3637             *
3638             * <p>
3639             * The content of the notification email is specified with the
3640             * <code>admin.email.password</code> portal property keys. They can be
3641             * overridden via a <code>portal-ext.properties</code> file or modified
3642             * through the Portal Settings UI.
3643             * </p>
3644             *
3645             * @param  companyId the primary key of the user's company
3646             * @param  emailAddress the user's email address
3647             * @return <code>true</code> if the notification email includes a new
3648             *         password; <code>false</code> if the notification email only
3649             *         contains a reset link
3650             */
3651            @Override
3652            public boolean sendPasswordByEmailAddress(
3653                            long companyId, String emailAddress)
3654                    throws PortalException {
3655    
3656                    User user = userPersistence.findByC_EA(companyId, emailAddress);
3657    
3658                    return sendPassword(
3659                            user.getCompanyId(), user.getEmailAddress(), null, null, null, null,
3660                            ServiceContextThreadLocal.getServiceContext());
3661            }
3662    
3663            /**
3664             * Sends a password notification email to the user matching the screen name.
3665             * The portal's settings determine whether a password is sent explicitly or
3666             * whether a link for resetting the user's password is sent. The method
3667             * sends the email asynchronously and returns before the email is sent.
3668             *
3669             * <p>
3670             * The content of the notification email is specified with the
3671             * <code>admin.email.password</code> portal property keys. They can be
3672             * overridden via a <code>portal-ext.properties</code> file or modified
3673             * through the Portal Settings UI.
3674             * </p>
3675             *
3676             * @param  companyId the primary key of the user's company
3677             * @param  screenName the user's screen name
3678             * @return <code>true</code> if the notification email includes a new
3679             *         password; <code>false</code> if the notification email only
3680             *         contains a reset link
3681             */
3682            @Override
3683            public boolean sendPasswordByScreenName(long companyId, String screenName)
3684                    throws PortalException {
3685    
3686                    User user = userPersistence.findByC_SN(companyId, screenName);
3687    
3688                    return sendPassword(
3689                            user.getCompanyId(), user.getEmailAddress(), null, null, null, null,
3690                            ServiceContextThreadLocal.getServiceContext());
3691            }
3692    
3693            /**
3694             * Sends a password notification email to the user matching the ID. The
3695             * portal's settings determine whether a password is sent explicitly or
3696             * whether a link for resetting the user's password is sent. The method
3697             * sends the email asynchronously and returns before the email is sent.
3698             *
3699             * <p>
3700             * The content of the notification email is specified with the
3701             * <code>admin.email.password</code> portal property keys. They can be
3702             * overridden via a <code>portal-ext.properties</code> file or modified
3703             * through the Portal Settings UI.
3704             * </p>
3705             *
3706             * @param  userId the user's primary key
3707             * @return <code>true</code> if the notification email includes a new
3708             *         password; <code>false</code> if the notification email only
3709             *         contains a reset link
3710             */
3711            @Override
3712            public boolean sendPasswordByUserId(long userId) throws PortalException {
3713                    User user = userPersistence.findByPrimaryKey(userId);
3714    
3715                    return sendPassword(
3716                            user.getCompanyId(), user.getEmailAddress(), null, null, null, null,
3717                            ServiceContextThreadLocal.getServiceContext());
3718            }
3719    
3720            /**
3721             * Sets the users in the role, removing and adding users to the role as
3722             * necessary.
3723             *
3724             * @param roleId the primary key of the role
3725             * @param userIds the primary keys of the users
3726             */
3727            @Override
3728            public void setRoleUsers(long roleId, long[] userIds)
3729                    throws PortalException {
3730    
3731                    long[] oldUserIds = rolePersistence.getUserPrimaryKeys(roleId);
3732    
3733                    Set<Long> updatedUserIdsSet = SetUtil.symmetricDifference(
3734                            userIds, oldUserIds);
3735    
3736                    long[] updateUserIds = ArrayUtil.toLongArray(updatedUserIdsSet);
3737    
3738                    rolePersistence.setUsers(roleId, userIds);
3739    
3740                    reindex(updateUserIds);
3741    
3742                    PermissionCacheUtil.clearCache(updateUserIds);
3743            }
3744    
3745            /**
3746             * Sets the users in the user group, removing and adding users to the user
3747             * group as necessary.
3748             *
3749             * @param userGroupId the primary key of the user group
3750             * @param userIds the primary keys of the users
3751             */
3752            @Override
3753            @SuppressWarnings("deprecation")
3754            public void setUserGroupUsers(long userGroupId, long[] userIds)
3755                    throws PortalException {
3756    
3757                    if (PropsValues.USER_GROUPS_COPY_LAYOUTS_TO_USER_PERSONAL_SITE) {
3758                            userGroupLocalService.copyUserGroupLayouts(userGroupId, userIds);
3759                    }
3760    
3761                    long[] oldUserIds = userGroupPersistence.getUserPrimaryKeys(
3762                            userGroupId);
3763    
3764                    Set<Long> updatedUserIdsSet = SetUtil.symmetricDifference(
3765                            userIds, oldUserIds);
3766    
3767                    long[] updateUserIds = ArrayUtil.toLongArray(updatedUserIdsSet);
3768    
3769                    userGroupPersistence.setUsers(userGroupId, userIds);
3770    
3771                    reindex(updateUserIds);
3772    
3773                    PermissionCacheUtil.clearCache(updateUserIds);
3774            }
3775    
3776            /**
3777             * Removes the users from the teams of a group.
3778             *
3779             * @param groupId the primary key of the group
3780             * @param userIds the primary keys of the users
3781             */
3782            @Override
3783            public void unsetGroupTeamsUsers(long groupId, long[] userIds)
3784                    throws PortalException {
3785    
3786                    List<Team> teams = teamPersistence.findByGroupId(groupId);
3787    
3788                    for (Team team : teams) {
3789                            unsetTeamUsers(team.getTeamId(), userIds);
3790                    }
3791    
3792                    PermissionCacheUtil.clearCache(userIds);
3793            }
3794    
3795            /**
3796             * Removes the users from the group.
3797             *
3798             * @param groupId the primary key of the group
3799             * @param userIds the primary keys of the users
3800             * @param serviceContext the service context to be applied (optionally
3801             *        <code>null</code>)
3802             */
3803            @Override
3804            public void unsetGroupUsers(
3805                            final long groupId, final long[] userIds,
3806                            ServiceContext serviceContext)
3807                    throws PortalException {
3808    
3809                    userGroupRoleLocalService.deleteUserGroupRoles(
3810                            userIds, groupId, RoleConstants.TYPE_SITE);
3811    
3812                    unsetGroupTeamsUsers(groupId, userIds);
3813    
3814                    groupPersistence.removeUsers(groupId, userIds);
3815    
3816                    reindex(userIds);
3817    
3818                    PermissionCacheUtil.clearCache(userIds);
3819    
3820                    Callable<Void> callable = new Callable<Void>() {
3821    
3822                            @Override
3823                            public Void call() throws Exception {
3824                                    Message message = new Message();
3825    
3826                                    message.put("groupId", groupId);
3827                                    message.put("userIds", userIds);
3828    
3829                                    MessageBusUtil.sendMessage(
3830                                            DestinationNames.SUBSCRIPTION_CLEAN_UP, message);
3831    
3832                                    return null;
3833                            }
3834    
3835                    };
3836    
3837                    TransactionCommitCallbackUtil.registerCallback(callable);
3838            }
3839    
3840            /**
3841             * Removes the users from the organization.
3842             *
3843             * @param organizationId the primary key of the organization
3844             * @param userIds the primary keys of the users
3845             */
3846            @Override
3847            public void unsetOrganizationUsers(
3848                            long organizationId, final long[] userIds)
3849                    throws PortalException {
3850    
3851                    Organization organization = organizationPersistence.findByPrimaryKey(
3852                            organizationId);
3853    
3854                    final Group group = organization.getGroup();
3855    
3856                    userGroupRoleLocalService.deleteUserGroupRoles(
3857                            userIds, group.getGroupId());
3858    
3859                    organizationPersistence.removeUsers(organizationId, userIds);
3860    
3861                    reindex(userIds);
3862    
3863                    PermissionCacheUtil.clearCache(userIds);
3864    
3865                    Callable<Void> callable = new Callable<Void>() {
3866    
3867                            @Override
3868                            public Void call() throws Exception {
3869                                    Message message = new Message();
3870    
3871                                    message.put("groupId", group.getGroupId());
3872                                    message.put("userIds", userIds);
3873    
3874                                    MessageBusUtil.sendMessage(
3875                                            DestinationNames.SUBSCRIPTION_CLEAN_UP, message);
3876    
3877                                    return null;
3878                            }
3879    
3880                    };
3881    
3882                    TransactionCommitCallbackUtil.registerCallback(callable);
3883            }
3884    
3885            /**
3886             * Removes the users from the password policy.
3887             *
3888             * @param passwordPolicyId the primary key of the password policy
3889             * @param userIds the primary keys of the users
3890             */
3891            @Override
3892            public void unsetPasswordPolicyUsers(
3893                    long passwordPolicyId, long[] userIds) {
3894    
3895                    passwordPolicyRelLocalService.deletePasswordPolicyRels(
3896                            passwordPolicyId, User.class.getName(), userIds);
3897            }
3898    
3899            /**
3900             * Removes the users from the role.
3901             *
3902             * @param roleId the primary key of the role
3903             * @param users the users
3904             */
3905            @Override
3906            public void unsetRoleUsers(long roleId, List<User> users)
3907                    throws PortalException {
3908    
3909                    Role role = rolePersistence.findByPrimaryKey(roleId);
3910    
3911                    String roleName = role.getName();
3912    
3913                    if ((roleName.equals(RoleConstants.ADMINISTRATOR) &&
3914                             (getRoleUsersCount(role.getRoleId()) <= 1)) ||
3915                            roleName.equals(RoleConstants.USER)) {
3916    
3917                            return;
3918                    }
3919    
3920                    rolePersistence.removeUsers(roleId, users);
3921    
3922                    Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
3923                            User.class);
3924    
3925                    indexer.reindex(users);
3926    
3927                    long[] userIds = new long[users.size()];
3928    
3929                    for (int i = 0; i < users.size(); i++) {
3930                            User user = users.get(i);
3931    
3932                            userIds[i] = user.getUserId();
3933                    }
3934    
3935                    PermissionCacheUtil.clearCache(userIds);
3936            }
3937    
3938            /**
3939             * Removes the users from the role.
3940             *
3941             * @param roleId the primary key of the role
3942             * @param userIds the primary keys of the users
3943             */
3944            @Override
3945            public void unsetRoleUsers(long roleId, long[] userIds)
3946                    throws PortalException {
3947    
3948                    Role role = rolePersistence.findByPrimaryKey(roleId);
3949    
3950                    String roleName = role.getName();
3951    
3952                    if (roleName.equals(RoleConstants.USER) ||
3953                            (roleName.equals(RoleConstants.ADMINISTRATOR) &&
3954                             getRoleUsersCount(role.getRoleId()) <= 1)) {
3955    
3956                            return;
3957                    }
3958    
3959                    rolePersistence.removeUsers(roleId, userIds);
3960    
3961                    reindex(userIds);
3962    
3963                    PermissionCacheUtil.clearCache(userIds);
3964            }
3965    
3966            /**
3967             * Removes the users from the team.
3968             *
3969             * @param teamId the primary key of the team
3970             * @param userIds the primary keys of the users
3971             */
3972            @Override
3973            public void unsetTeamUsers(long teamId, long[] userIds)
3974                    throws PortalException {
3975    
3976                    teamPersistence.removeUsers(teamId, userIds);
3977    
3978                    reindex(userIds);
3979    
3980                    PermissionCacheUtil.clearCache(userIds);
3981            }
3982    
3983            /**
3984             * Removes the users from the user group.
3985             *
3986             * @param userGroupId the primary key of the user group
3987             * @param userIds the primary keys of the users
3988             */
3989            @Override
3990            public void unsetUserGroupUsers(long userGroupId, long[] userIds)
3991                    throws PortalException {
3992    
3993                    userGroupPersistence.removeUsers(userGroupId, userIds);
3994    
3995                    reindex(userIds);
3996    
3997                    PermissionCacheUtil.clearCache(userIds);
3998            }
3999    
4000            /**
4001             * Updates whether the user has agreed to the terms of use.
4002             *
4003             * @param  userId the primary key of the user
4004             * @param  agreedToTermsOfUse whether the user has agreet to the terms of
4005             *         use
4006             * @return the user
4007             */
4008            @Override
4009            public User updateAgreedToTermsOfUse(
4010                            long userId, boolean agreedToTermsOfUse)
4011                    throws PortalException {
4012    
4013                    User user = userPersistence.findByPrimaryKey(userId);
4014    
4015                    user.setAgreedToTermsOfUse(agreedToTermsOfUse);
4016    
4017                    userPersistence.update(user);
4018    
4019                    return user;
4020            }
4021    
4022            /**
4023             * Updates the user's asset with the new asset categories and tag names,
4024             * removing and adding asset categories and tag names as necessary.
4025             *
4026             * @param userId the primary key of the user
4027             * @param user ID the primary key of the user
4028             * @param assetCategoryIds the primary key's of the new asset categories
4029             * @param assetTagNames the new asset tag names
4030             */
4031            @Override
4032            public void updateAsset(
4033                            long userId, User user, long[] assetCategoryIds,
4034                            String[] assetTagNames)
4035                    throws PortalException {
4036    
4037                    User owner = userPersistence.findByPrimaryKey(userId);
4038    
4039                    Company company = companyPersistence.findByPrimaryKey(
4040                            owner.getCompanyId());
4041    
4042                    Group companyGroup = company.getGroup();
4043    
4044                    assetEntryLocalService.updateEntry(
4045                            userId, companyGroup.getGroupId(), user.getCreateDate(),
4046                            user.getModifiedDate(), User.class.getName(), user.getUserId(),
4047                            user.getUuid(), 0, assetCategoryIds, assetTagNames, false, null,
4048                            null, null, null, user.getFullName(), null, null, null, null, 0, 0,
4049                            null);
4050            }
4051    
4052            /**
4053             * Updates the user's creation date.
4054             *
4055             * @param  userId the primary key of the user
4056             * @param  createDate the new creation date
4057             * @return the user
4058             */
4059            @Override
4060            public User updateCreateDate(long userId, Date createDate)
4061                    throws PortalException {
4062    
4063                    User user = userPersistence.findByPrimaryKey(userId);
4064    
4065                    user.setCreateDate(createDate);
4066    
4067                    userPersistence.update(user);
4068    
4069                    return user;
4070            }
4071    
4072            /**
4073             * Updates the user's email address.
4074             *
4075             * @param  userId the primary key of the user
4076             * @param  password the user's password
4077             * @param  emailAddress1 the user's new email address
4078             * @param  emailAddress2 the user's new email address confirmation
4079             * @return the user
4080             */
4081            @Override
4082            public User updateEmailAddress(
4083                            long userId, String password, String emailAddress1,
4084                            String emailAddress2)
4085                    throws PortalException {
4086    
4087                    emailAddress1 = StringUtil.toLowerCase(emailAddress1.trim());
4088                    emailAddress2 = StringUtil.toLowerCase(emailAddress2.trim());
4089    
4090                    User user = userPersistence.findByPrimaryKey(userId);
4091    
4092                    validateEmailAddress(user, emailAddress1, emailAddress2);
4093    
4094                    setEmailAddress(
4095                            user, password, user.getFirstName(), user.getMiddleName(),
4096                            user.getLastName(), emailAddress1);
4097    
4098                    userPersistence.update(user);
4099    
4100                    Contact contact = user.getContact();
4101    
4102                    contact.setEmailAddress(user.getEmailAddress());
4103    
4104                    contactPersistence.update(contact);
4105    
4106                    return user;
4107            }
4108    
4109            /**
4110             * Updates the user's email address or sends verification email.
4111             *
4112             * @param  userId the primary key of the user
4113             * @param  password the user's password
4114             * @param  emailAddress1 the user's new email address
4115             * @param  emailAddress2 the user's new email address confirmation
4116             * @param  serviceContext the service context to be applied. Must set the
4117             *         portal URL, main path, primary key of the layout, remote address,
4118             *         remote host, and agent for the user.
4119             * @return the user
4120             */
4121            @Override
4122            public User updateEmailAddress(
4123                            long userId, String password, String emailAddress1,
4124                            String emailAddress2, ServiceContext serviceContext)
4125                    throws PortalException {
4126    
4127                    emailAddress1 = StringUtil.toLowerCase(emailAddress1.trim());
4128                    emailAddress2 = StringUtil.toLowerCase(emailAddress2.trim());
4129    
4130                    User user = userPersistence.findByPrimaryKey(userId);
4131    
4132                    validateEmailAddress(user, emailAddress1, emailAddress2);
4133    
4134                    Company company = companyPersistence.findByPrimaryKey(
4135                            user.getCompanyId());
4136    
4137                    if (company.isStrangersVerify() &&
4138                            !StringUtil.equalsIgnoreCase(
4139                                    emailAddress1, user.getEmailAddress())) {
4140    
4141                            sendEmailAddressVerification(user, emailAddress1, serviceContext);
4142                    }
4143                    else {
4144                            setEmailAddress(
4145                                    user, password, user.getFirstName(), user.getMiddleName(),
4146                                    user.getLastName(), emailAddress1);
4147    
4148                            userPersistence.update(user);
4149    
4150                            Contact contact = user.getContact();
4151    
4152                            contact.setEmailAddress(user.getEmailAddress());
4153    
4154                            contactPersistence.update(contact);
4155                    }
4156    
4157                    return user;
4158            }
4159    
4160            /**
4161             * Updates whether the user has verified email address.
4162             *
4163             * @param  userId the primary key of the user
4164             * @param  emailAddressVerified whether the user has verified email address
4165             * @return the user
4166             */
4167            @Override
4168            public User updateEmailAddressVerified(
4169                            long userId, boolean emailAddressVerified)
4170                    throws PortalException {
4171    
4172                    User user = userPersistence.findByPrimaryKey(userId);
4173    
4174                    user.setEmailAddressVerified(emailAddressVerified);
4175    
4176                    userPersistence.update(user);
4177    
4178                    return user;
4179            }
4180    
4181            /**
4182             * Updates the user's Facebook ID.
4183             *
4184             * @param  userId the primary key of the user
4185             * @param  facebookId the user's new Facebook ID
4186             * @return the user
4187             */
4188            @Override
4189            public User updateFacebookId(long userId, long facebookId)
4190                    throws PortalException {
4191    
4192                    User user = userPersistence.findByPrimaryKey(userId);
4193    
4194                    user.setFacebookId(facebookId);
4195    
4196                    userPersistence.update(user);
4197    
4198                    return user;
4199            }
4200    
4201            /**
4202             * Sets the groups the user is in, removing and adding groups as necessary.
4203             *
4204             * @param userId the primary key of the user
4205             * @param newGroupIds the primary keys of the groups
4206             * @param serviceContext the service context to be applied (optionally
4207             *        <code>null</code>)
4208             */
4209            @Override
4210            public void updateGroups(
4211                            long userId, long[] newGroupIds, ServiceContext serviceContext)
4212                    throws PortalException {
4213    
4214                    boolean indexingEnabled = true;
4215    
4216                    if (serviceContext != null) {
4217                            indexingEnabled = serviceContext.isIndexingEnabled();
4218                    }
4219    
4220                    updateGroups(userId, newGroupIds, serviceContext, indexingEnabled);
4221            }
4222    
4223            /**
4224             * Updates a user account that was automatically created when a guest user
4225             * participated in an action (e.g. posting a comment) and only provided his
4226             * name and email address.
4227             *
4228             * @param  creatorUserId the primary key of the creator
4229             * @param  companyId the primary key of the user's company
4230             * @param  autoPassword whether a password should be automatically generated
4231             *         for the user
4232             * @param  password1 the user's password
4233             * @param  password2 the user's password confirmation
4234             * @param  autoScreenName whether a screen name should be automatically
4235             *         generated for the user
4236             * @param  screenName the user's screen name
4237             * @param  emailAddress the user's email address
4238             * @param  facebookId the user's facebook ID
4239             * @param  openId the user's OpenID
4240             * @param  locale the user's locale
4241             * @param  firstName the user's first name
4242             * @param  middleName the user's middle name
4243             * @param  lastName the user's last name
4244             * @param  prefixId the user's name prefix ID
4245             * @param  suffixId the user's name suffix ID
4246             * @param  male whether the user is male
4247             * @param  birthdayMonth the user's birthday month (0-based, meaning 0 for
4248             *         January)
4249             * @param  birthdayDay the user's birthday day
4250             * @param  birthdayYear the user's birthday year
4251             * @param  jobTitle the user's job title
4252             * @param  updateUserInformation whether to update the user's information
4253             * @param  sendEmail whether to send the user an email notification about
4254             *         their new account
4255             * @param  serviceContext the service context to be applied (optionally
4256             *         <code>null</code>). Can set expando bridge attributes for the
4257             *         user.
4258             * @return the user
4259             */
4260            @Override
4261            public User updateIncompleteUser(
4262                            long creatorUserId, long companyId, boolean autoPassword,
4263                            String password1, String password2, boolean autoScreenName,
4264                            String screenName, String emailAddress, long facebookId,
4265                            String openId, Locale locale, String firstName, String middleName,
4266                            String lastName, long prefixId, long suffixId, boolean male,
4267                            int birthdayMonth, int birthdayDay, int birthdayYear,
4268                            String jobTitle, boolean updateUserInformation, boolean sendEmail,
4269                            ServiceContext serviceContext)
4270                    throws PortalException {
4271    
4272                    User user = getUserByEmailAddress(companyId, emailAddress);
4273    
4274                    if (user.getStatus() != WorkflowConstants.STATUS_INCOMPLETE) {
4275                            throw new PortalException("Invalid user status");
4276                    }
4277    
4278                    User defaultUser = getDefaultUser(companyId);
4279    
4280                    if (facebookId > 0) {
4281                            autoPassword = false;
4282    
4283                            if ((password1 == null) || (password2 == null)) {
4284                                    password1 = PwdGenerator.getPassword();
4285                                    password2 = password1;
4286                            }
4287    
4288                            sendEmail = false;
4289                    }
4290    
4291                    if (updateUserInformation) {
4292                            autoScreenName = false;
4293    
4294                            if (PrefsPropsUtil.getBoolean(
4295                                            companyId,
4296                                            PropsKeys.USERS_SCREEN_NAME_ALWAYS_AUTOGENERATE)) {
4297    
4298                                    autoScreenName = true;
4299                            }
4300    
4301                            validate(
4302                                    companyId, user.getUserId(), autoPassword, password1, password2,
4303                                    autoScreenName, screenName, emailAddress, openId, firstName,
4304                                    middleName, lastName, null, locale);
4305    
4306                            if (!autoPassword) {
4307                                    if (Validator.isNull(password1) ||
4308                                            Validator.isNull(password2)) {
4309    
4310                                            throw new UserPasswordException.MustNotBeNull(
4311                                                    user.getUserId());
4312                                    }
4313                            }
4314    
4315                            if (autoScreenName) {
4316                                    ScreenNameGenerator screenNameGenerator =
4317                                            ScreenNameGeneratorFactory.getInstance();
4318    
4319                                    try {
4320                                            screenName = screenNameGenerator.generate(
4321                                                    companyId, user.getUserId(), emailAddress);
4322                                    }
4323                                    catch (Exception e) {
4324                                            throw new SystemException(e);
4325                                    }
4326                            }
4327    
4328                            FullNameGenerator fullNameGenerator =
4329                                    FullNameGeneratorFactory.getInstance();
4330    
4331                            String fullName = fullNameGenerator.getFullName(
4332                                    firstName, middleName, lastName);
4333    
4334                            String greeting = LanguageUtil.format(
4335                                    locale, "welcome-x", fullName, false);
4336    
4337                            if (Validator.isNotNull(password1)) {
4338                                    user.setPassword(PasswordEncryptorUtil.encrypt(password1));
4339                                    user.setPasswordUnencrypted(password1);
4340                            }
4341    
4342                            user.setPasswordEncrypted(true);
4343    
4344                            PasswordPolicy passwordPolicy = defaultUser.getPasswordPolicy();
4345    
4346                            if ((passwordPolicy != null) && passwordPolicy.isChangeable() &&
4347                                    passwordPolicy.isChangeRequired()) {
4348    
4349                                    user.setPasswordReset(true);
4350                            }
4351                            else {
4352                                    user.setPasswordReset(false);
4353                            }
4354    
4355                            user.setScreenName(screenName);
4356                            user.setFacebookId(facebookId);
4357                            user.setOpenId(openId);
4358                            user.setLanguageId(locale.toString());
4359                            user.setTimeZoneId(defaultUser.getTimeZoneId());
4360                            user.setGreeting(greeting);
4361                            user.setFirstName(firstName);
4362                            user.setMiddleName(middleName);
4363                            user.setLastName(lastName);
4364                            user.setJobTitle(jobTitle);
4365                            user.setExpandoBridgeAttributes(serviceContext);
4366    
4367                            Date birthday = getBirthday(
4368                                    birthdayMonth, birthdayDay, birthdayYear);
4369    
4370                            Contact contact = user.getContact();
4371    
4372                            contact.setFirstName(firstName);
4373                            contact.setMiddleName(middleName);
4374                            contact.setLastName(lastName);
4375                            contact.setPrefixId(prefixId);
4376                            contact.setSuffixId(suffixId);
4377                            contact.setMale(male);
4378                            contact.setBirthday(birthday);
4379                            contact.setJobTitle(jobTitle);
4380    
4381                            contactPersistence.update(contact, serviceContext);
4382    
4383                            // Indexer
4384    
4385                            Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
4386                                    User.class);
4387    
4388                            indexer.reindex(user);
4389                    }
4390    
4391                    user.setStatus(WorkflowConstants.STATUS_DRAFT);
4392    
4393                    userPersistence.update(user, serviceContext);
4394    
4395                    // Workflow
4396    
4397                    long workflowUserId = creatorUserId;
4398    
4399                    if (workflowUserId == user.getUserId()) {
4400                            workflowUserId = defaultUser.getUserId();
4401                    }
4402    
4403                    ServiceContext workflowServiceContext = serviceContext;
4404    
4405                    if (workflowServiceContext == null) {
4406                            workflowServiceContext = new ServiceContext();
4407                    }
4408    
4409                    workflowServiceContext.setAttribute("autoPassword", autoPassword);
4410                    workflowServiceContext.setAttribute("passwordUnencrypted", password1);
4411                    workflowServiceContext.setAttribute("sendEmail", sendEmail);
4412    
4413                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
4414                            companyId, workflowUserId, User.class.getName(), user.getUserId(),
4415                            user, workflowServiceContext);
4416    
4417                    return getUserByEmailAddress(companyId, emailAddress);
4418            }
4419    
4420            /**
4421             * Updates the user's job title.
4422             *
4423             * @param  userId the primary key of the user
4424             * @param  jobTitle the user's job title
4425             * @return the user
4426             */
4427            @Override
4428            public User updateJobTitle(long userId, String jobTitle)
4429                    throws PortalException {
4430    
4431                    User user = userPersistence.findByPrimaryKey(userId);
4432    
4433                    user.setJobTitle(jobTitle);
4434    
4435                    userPersistence.update(user);
4436    
4437                    Contact contact = contactPersistence.findByPrimaryKey(
4438                            user.getContactId());
4439    
4440                    contact.setJobTitle(jobTitle);
4441    
4442                    contactPersistence.update(contact);
4443    
4444                    return user;
4445            }
4446    
4447            /**
4448             * Updates the user's last login with the current time and the IP address.
4449             *
4450             * @param  userId the primary key of the user
4451             * @param  loginIP the IP address the user logged in from
4452             * @return the user
4453             */
4454            @Override
4455            public User updateLastLogin(long userId, String loginIP)
4456                    throws PortalException {
4457    
4458                    User user = userPersistence.findByPrimaryKey(userId);
4459    
4460                    Date lastLoginDate = user.getLoginDate();
4461    
4462                    if (lastLoginDate == null) {
4463                            lastLoginDate = new Date();
4464                    }
4465    
4466                    String lastLoginIP = user.getLoginIP();
4467    
4468                    if (lastLoginIP == null) {
4469                            lastLoginIP = loginIP;
4470                    }
4471    
4472                    user.setLoginDate(new Date());
4473                    user.setLoginIP(loginIP);
4474                    user.setLastLoginDate(lastLoginDate);
4475                    user.setLastLoginIP(lastLoginIP);
4476    
4477                    resetFailedLoginAttempts(user, true);
4478    
4479                    return user;
4480            }
4481    
4482            /**
4483             * Updates whether the user is locked out from logging in.
4484             *
4485             * @param  user the user
4486             * @param  lockout whether the user is locked out
4487             * @return the user
4488             */
4489            @Override
4490            public User updateLockout(User user, boolean lockout)
4491                    throws PortalException {
4492    
4493                    PasswordPolicy passwordPolicy = user.getPasswordPolicy();
4494    
4495                    if ((passwordPolicy == null) || !passwordPolicy.isLockout()) {
4496                            return user;
4497                    }
4498    
4499                    Date lockoutDate = null;
4500    
4501                    if (lockout) {
4502                            lockoutDate = new Date();
4503                    }
4504    
4505                    user.setLockout(lockout);
4506                    user.setLockoutDate(lockoutDate);
4507    
4508                    if (!lockout) {
4509                            user.setFailedLoginAttempts(0);
4510                    }
4511    
4512                    userPersistence.update(user);
4513    
4514                    return user;
4515            }
4516    
4517            /**
4518             * Updates whether the user is locked out from logging in.
4519             *
4520             * @param  companyId the primary key of the user's company
4521             * @param  emailAddress the user's email address
4522             * @param  lockout whether the user is locked out
4523             * @return the user
4524             */
4525            @Override
4526            public User updateLockoutByEmailAddress(
4527                            long companyId, String emailAddress, boolean lockout)
4528                    throws PortalException {
4529    
4530                    User user = getUserByEmailAddress(companyId, emailAddress);
4531    
4532                    return updateLockout(user, lockout);
4533            }
4534    
4535            /**
4536             * Updates whether the user is locked out from logging in.
4537             *
4538             * @param  userId the primary key of the user
4539             * @param  lockout whether the user is locked out
4540             * @return the user
4541             */
4542            @Override
4543            public User updateLockoutById(long userId, boolean lockout)
4544                    throws PortalException {
4545    
4546                    User user = userPersistence.findByPrimaryKey(userId);
4547    
4548                    return updateLockout(user, lockout);
4549            }
4550    
4551            /**
4552             * Updates whether the user is locked out from logging in.
4553             *
4554             * @param  companyId the primary key of the user's company
4555             * @param  screenName the user's screen name
4556             * @param  lockout whether the user is locked out
4557             * @return the user
4558             */
4559            @Override
4560            public User updateLockoutByScreenName(
4561                            long companyId, String screenName, boolean lockout)
4562                    throws PortalException {
4563    
4564                    User user = getUserByScreenName(companyId, screenName);
4565    
4566                    return updateLockout(user, lockout);
4567            }
4568    
4569            /**
4570             * Updates the user's modified date.
4571             *
4572             * @param  userId the primary key of the user
4573             * @param  modifiedDate the new modified date
4574             * @return the user
4575             */
4576            @Override
4577            public User updateModifiedDate(long userId, Date modifiedDate)
4578                    throws PortalException {
4579    
4580                    User user = userPersistence.findByPrimaryKey(userId);
4581    
4582                    userPersistence.update(user);
4583    
4584                    return user;
4585            }
4586    
4587            /**
4588             * Updates the user's OpenID.
4589             *
4590             * @param  userId the primary key of the user
4591             * @param  openId the new OpenID
4592             * @return the user
4593             */
4594            @Override
4595            public User updateOpenId(long userId, String openId)
4596                    throws PortalException {
4597    
4598                    openId = openId.trim();
4599    
4600                    User user = userPersistence.findByPrimaryKey(userId);
4601    
4602                    user.setOpenId(openId);
4603    
4604                    userPersistence.update(user);
4605    
4606                    return user;
4607            }
4608    
4609            /**
4610             * Sets the organizations that the user is in, removing and adding
4611             * organizations as necessary.
4612             *
4613             * @param userId the primary key of the user
4614             * @param newOrganizationIds the primary keys of the organizations
4615             * @param serviceContext the service context to be applied. Must set whether
4616             *        user indexing is enabled.
4617             */
4618            @Override
4619            public void updateOrganizations(
4620                            long userId, long[] newOrganizationIds,
4621                            ServiceContext serviceContext)
4622                    throws PortalException {
4623    
4624                    updateOrganizations(
4625                            userId, newOrganizationIds, serviceContext.isIndexingEnabled());
4626            }
4627    
4628            /**
4629             * Updates the user's password without tracking or validation of the change.
4630             *
4631             * @param  userId the primary key of the user
4632             * @param  password1 the user's new password
4633             * @param  password2 the user's new password confirmation
4634             * @param  passwordReset whether the user should be asked to reset their
4635             *         password the next time they log in
4636             * @return the user
4637             */
4638            @Override
4639            public User updatePassword(
4640                            long userId, String password1, String password2,
4641                            boolean passwordReset)
4642                    throws PortalException {
4643    
4644                    return updatePassword(
4645                            userId, password1, password2, passwordReset, false);
4646            }
4647    
4648            /**
4649             * Updates the user's password, optionally with tracking and validation of
4650             * the change.
4651             *
4652             * @param  userId the primary key of the user
4653             * @param  password1 the user's new password
4654             * @param  password2 the user's new password confirmation
4655             * @param  passwordReset whether the user should be asked to reset their
4656             *         password the next time they login
4657             * @param  silentUpdate whether the password should be updated without being
4658             *         tracked, or validated. Primarily used for password imports.
4659             * @return the user
4660             */
4661            @Override
4662            public User updatePassword(
4663                            long userId, String password1, String password2,
4664                            boolean passwordReset, boolean silentUpdate)
4665                    throws PortalException {
4666    
4667                    User user = userPersistence.findByPrimaryKey(userId);
4668    
4669                    if (!silentUpdate) {
4670                            validatePassword(user.getCompanyId(), userId, password1, password2);
4671                    }
4672    
4673                    String oldEncPwd = user.getPassword();
4674    
4675                    if (!user.isPasswordEncrypted()) {
4676                            oldEncPwd = PasswordEncryptorUtil.encrypt(user.getPassword());
4677                    }
4678    
4679                    String newEncPwd = PasswordEncryptorUtil.encrypt(password1);
4680    
4681                    if (user.hasCompanyMx()) {
4682                            mailService.updatePassword(user.getCompanyId(), userId, password1);
4683                    }
4684    
4685                    user.setPassword(newEncPwd);
4686                    user.setPasswordUnencrypted(password1);
4687                    user.setPasswordEncrypted(true);
4688                    user.setPasswordReset(passwordReset);
4689    
4690                    if (!silentUpdate || (user.getPasswordModifiedDate() == null)) {
4691                            user.setPasswordModifiedDate(new Date());
4692                    }
4693    
4694                    user.setDigest(StringPool.BLANK);
4695                    user.setGraceLoginCount(0);
4696    
4697                    if (!silentUpdate) {
4698                            user.setPasswordModified(true);
4699                    }
4700    
4701                    PasswordModificationThreadLocal.setPasswordModified(
4702                            user.getPasswordModified());
4703                    PasswordModificationThreadLocal.setPasswordUnencrypted(
4704                            user.getPasswordUnencrypted());
4705    
4706                    try {
4707                            user = userPersistence.update(user);
4708                    }
4709                    catch (ModelListenerException mle) {
4710                            String msg = GetterUtil.getString(mle.getCause().getMessage());
4711    
4712                            if (LDAPSettingsUtil.isPasswordPolicyEnabled(user.getCompanyId())) {
4713                                    String[] errorPasswordHistoryKeywords =
4714                                            LDAPSettingsUtil.getErrorPasswordHistoryKeywords(
4715                                                    user.getCompanyId());
4716    
4717                                    for (String errorPasswordHistoryKeyword :
4718                                                    errorPasswordHistoryKeywords) {
4719    
4720                                            if (msg.contains(errorPasswordHistoryKeyword)) {
4721                                                    throw new UserPasswordException.MustNotBeRecentlyUsed(
4722                                                            userId);
4723                                            }
4724                                    }
4725                            }
4726    
4727                            throw new UserPasswordException.MustComplyWithModelListeners(
4728                                    userId, mle);
4729                    }
4730    
4731                    if (!silentUpdate) {
4732                            user.setPasswordModified(false);
4733    
4734                            passwordTrackerLocalService.trackPassword(userId, oldEncPwd);
4735                    }
4736    
4737                    if (!silentUpdate && (PrincipalThreadLocal.getUserId() != userId)) {
4738                            sendPasswordNotification(
4739                                    user, user.getCompanyId(), password1, null, null, null, null,
4740                                    null, ServiceContextThreadLocal.getServiceContext());
4741                    }
4742    
4743                    return user;
4744            }
4745    
4746            /**
4747             * Updates the user's password with manually input information. This method
4748             * should only be used when performing maintenance.
4749             *
4750             * @param  userId the primary key of the user
4751             * @param  password the user's new password
4752             * @param  passwordEncrypted the user's new encrypted password
4753             * @param  passwordReset whether the user should be asked to reset their
4754             *         password the next time they login
4755             * @param  passwordModifiedDate the new password modified date
4756             * @return the user
4757             */
4758            @Override
4759            public User updatePasswordManually(
4760                            long userId, String password, boolean passwordEncrypted,
4761                            boolean passwordReset, Date passwordModifiedDate)
4762                    throws PortalException {
4763    
4764                    // This method should only be used to manually massage data
4765    
4766                    User user = userPersistence.findByPrimaryKey(userId);
4767    
4768                    user.setPassword(password);
4769                    user.setPasswordEncrypted(passwordEncrypted);
4770                    user.setPasswordReset(passwordReset);
4771                    user.setPasswordModifiedDate(passwordModifiedDate);
4772                    user.setDigest(StringPool.BLANK);
4773    
4774                    userPersistence.update(user);
4775    
4776                    return user;
4777            }
4778    
4779            /**
4780             * Updates whether the user should be asked to reset their password the next
4781             * time they login.
4782             *
4783             * @param  userId the primary key of the user
4784             * @param  passwordReset whether the user should be asked to reset their
4785             *         password the next time they login
4786             * @return the user
4787             */
4788            @Override
4789            public User updatePasswordReset(long userId, boolean passwordReset)
4790                    throws PortalException {
4791    
4792                    User user = userPersistence.findByPrimaryKey(userId);
4793    
4794                    user.setPasswordReset(passwordReset);
4795    
4796                    userPersistence.update(user);
4797    
4798                    return user;
4799            }
4800    
4801            /**
4802             * Updates the user's portrait image.
4803             *
4804             * @param  userId the primary key of the user
4805             * @param  bytes the new portrait image data
4806             * @return the user
4807             */
4808            @Override
4809            public User updatePortrait(long userId, byte[] bytes)
4810                    throws PortalException {
4811    
4812                    User user = userPersistence.findByPrimaryKey(userId);
4813    
4814                    PortalUtil.updateImageId(
4815                            user, true, bytes, "portraitId",
4816                            PrefsPropsUtil.getLong(PropsKeys.USERS_IMAGE_MAX_SIZE),
4817                            PropsValues.USERS_IMAGE_MAX_HEIGHT,
4818                            PropsValues.USERS_IMAGE_MAX_WIDTH);
4819    
4820                    return userPersistence.update(user);
4821            }
4822    
4823            /**
4824             * Updates the user's password reset question and answer.
4825             *
4826             * @param  userId the primary key of the user
4827             * @param  question the user's new password reset question
4828             * @param  answer the user's new password reset answer
4829             * @return the user
4830             */
4831            @Override
4832            public User updateReminderQuery(long userId, String question, String answer)
4833                    throws PortalException {
4834    
4835                    validateReminderQuery(question, answer);
4836    
4837                    User user = userPersistence.findByPrimaryKey(userId);
4838    
4839                    user.setReminderQueryQuestion(question);
4840                    user.setReminderQueryAnswer(answer);
4841    
4842                    userPersistence.update(user);
4843    
4844                    return user;
4845            }
4846    
4847            /**
4848             * Updates the user's screen name.
4849             *
4850             * @param  userId the primary key of the user
4851             * @param  screenName the user's new screen name
4852             * @return the user
4853             */
4854            @Override
4855            public User updateScreenName(long userId, String screenName)
4856                    throws PortalException {
4857    
4858                    // User
4859    
4860                    User user = userPersistence.findByPrimaryKey(userId);
4861    
4862                    screenName = getLogin(screenName);
4863    
4864                    validateScreenName(user.getCompanyId(), userId, screenName);
4865    
4866                    if (!StringUtil.equalsIgnoreCase(user.getScreenName(), screenName)) {
4867                            user.setDigest(StringPool.BLANK);
4868                    }
4869    
4870                    user.setScreenName(screenName);
4871    
4872                    userPersistence.update(user);
4873    
4874                    // Group
4875    
4876                    Group group = groupLocalService.getUserGroup(
4877                            user.getCompanyId(), userId);
4878    
4879                    group.setFriendlyURL(StringPool.SLASH + screenName);
4880    
4881                    groupPersistence.update(group);
4882    
4883                    return user;
4884            }
4885    
4886            /**
4887             * Updates the user's workflow status.
4888             *
4889             * @param      userId the primary key of the user
4890             * @param      status the user's new workflow status
4891             * @return     the user
4892             * @deprecated As of 7.0.0, replaced by {@link #updateStatus(long, int,
4893             *             ServiceContext)}
4894             */
4895            @Deprecated
4896            @Override
4897            public User updateStatus(long userId, int status) throws PortalException {
4898                    return updateStatus(userId, status, new ServiceContext());
4899            }
4900    
4901            /**
4902             * Updates the user's workflow status.
4903             *
4904             * @param  userId the primary key of the user
4905             * @param  status the user's new workflow status
4906             * @param  serviceContext the service context to be applied. You can specify
4907             *         an unencrypted custom password (used by an LDAP listener) for the
4908             *         user via attribute <code>passwordUnencrypted</code>.
4909             * @return the user
4910             */
4911            @Override
4912            public User updateStatus(
4913                            long userId, int status, ServiceContext serviceContext)
4914                    throws PortalException {
4915    
4916                    User user = userPersistence.findByPrimaryKey(userId);
4917    
4918                    if ((status == WorkflowConstants.STATUS_APPROVED) &&
4919                            (user.getStatus() != WorkflowConstants.STATUS_APPROVED)) {
4920    
4921                            validateCompanyMaxUsers(user.getCompanyId());
4922                    }
4923    
4924                    String passwordUnencrypted = (String)serviceContext.getAttribute(
4925                            "passwordUnencrypted");
4926    
4927                    if (Validator.isNotNull(passwordUnencrypted)) {
4928                            user.setPasswordUnencrypted(passwordUnencrypted);
4929                    }
4930    
4931                    user.setStatus(status);
4932    
4933                    userPersistence.update(user);
4934    
4935                    reindex(user);
4936    
4937                    Group group = user.getGroup();
4938    
4939                    if (status == WorkflowConstants.STATUS_INACTIVE) {
4940                            group.setActive(false);
4941                    }
4942                    else {
4943                            group.setActive(true);
4944                    }
4945    
4946                    groupLocalService.updateGroup(group);
4947    
4948                    return user;
4949            }
4950    
4951            /**
4952             * Updates the user.
4953             *
4954             * @param  userId the primary key of the user
4955             * @param  oldPassword the user's old password
4956             * @param  newPassword1 the user's new password (optionally
4957             *         <code>null</code>)
4958             * @param  newPassword2 the user's new password confirmation (optionally
4959             *         <code>null</code>)
4960             * @param  passwordReset whether the user should be asked to reset their
4961             *         password the next time they login
4962             * @param  reminderQueryQuestion the user's new password reset question
4963             * @param  reminderQueryAnswer the user's new password reset answer
4964             * @param  screenName the user's new screen name
4965             * @param  emailAddress the user's new email address
4966             * @param  facebookId the user's new Facebook ID
4967             * @param  openId the user's new OpenID
4968             * @param  portrait whether to update the user's portrait image
4969             * @param  portraitBytes the new portrait image data
4970             * @param  languageId the user's new language ID
4971             * @param  timeZoneId the user's new time zone ID
4972             * @param  greeting the user's new greeting
4973             * @param  comments the user's new comments
4974             * @param  firstName the user's new first name
4975             * @param  middleName the user's new middle name
4976             * @param  lastName the user's new last name
4977             * @param  prefixId the user's new name prefix ID
4978             * @param  suffixId the user's new name suffix ID
4979             * @param  male whether user is male
4980             * @param  birthdayMonth the user's new birthday month (0-based, meaning 0
4981             *         for January)
4982             * @param  birthdayDay the user's new birthday day
4983             * @param  birthdayYear the user's birthday year
4984             * @param  smsSn the user's new SMS screen name
4985             * @param  facebookSn the user's new Facebook screen name
4986             * @param  jabberSn the user's new Jabber screen name
4987             * @param  skypeSn the user's new Skype screen name
4988             * @param  twitterSn the user's new Twitter screen name
4989             * @param  jobTitle the user's new job title
4990             * @param  groupIds the primary keys of the user's groups
4991             * @param  organizationIds the primary keys of the user's organizations
4992             * @param  roleIds the primary keys of the user's roles
4993             * @param  userGroupRoles the user user's group roles
4994             * @param  userGroupIds the primary keys of the user's user groups
4995             * @param  serviceContext the service context to be applied (optionally
4996             *         <code>null</code>). Can set the UUID (with the <code>uuid</code>
4997             *         attribute), asset category IDs, asset tag names, and expando
4998             *         bridge attributes for the user.
4999             * @return the user
5000             */
5001            @Override
5002            @SuppressWarnings("deprecation")
5003            public User updateUser(
5004                            long userId, String oldPassword, String newPassword1,
5005                            String newPassword2, boolean passwordReset,
5006                            String reminderQueryQuestion, String reminderQueryAnswer,
5007                            String screenName, String emailAddress, long facebookId,
5008                            String openId, boolean portrait, byte[] portraitBytes,
5009                            String languageId, String timeZoneId, String greeting,
5010                            String comments, String firstName, String middleName,
5011                            String lastName, long prefixId, long suffixId, boolean male,
5012                            int birthdayMonth, int birthdayDay, int birthdayYear, String smsSn,
5013                            String facebookSn, String jabberSn, String skypeSn,
5014                            String twitterSn, String jobTitle, long[] groupIds,
5015                            long[] organizationIds, long[] roleIds,
5016                            List<UserGroupRole> userGroupRoles, long[] userGroupIds,
5017                            ServiceContext serviceContext)
5018                    throws PortalException {
5019    
5020                    // User
5021    
5022                    User user = userPersistence.findByPrimaryKey(userId);
5023                    Company company = companyPersistence.findByPrimaryKey(
5024                            user.getCompanyId());
5025                    String password = oldPassword;
5026                    screenName = getLogin(screenName);
5027                    emailAddress = StringUtil.toLowerCase(emailAddress.trim());
5028                    openId = openId.trim();
5029                    String oldFullName = user.getFullName();
5030                    facebookSn = StringUtil.toLowerCase(facebookSn.trim());
5031                    jabberSn = StringUtil.toLowerCase(jabberSn.trim());
5032                    skypeSn = StringUtil.toLowerCase(skypeSn.trim());
5033                    twitterSn = StringUtil.toLowerCase(twitterSn.trim());
5034    
5035                    EmailAddressGenerator emailAddressGenerator =
5036                            EmailAddressGeneratorFactory.getInstance();
5037    
5038                    if (emailAddressGenerator.isGenerated(emailAddress)) {
5039                            emailAddress = StringPool.BLANK;
5040                    }
5041    
5042                    if (!PropsValues.USERS_EMAIL_ADDRESS_REQUIRED &&
5043                            Validator.isNull(emailAddress)) {
5044    
5045                            emailAddress = emailAddressGenerator.generate(
5046                                    user.getCompanyId(), userId);
5047                    }
5048    
5049                    Locale locale = LocaleUtil.fromLanguageId(languageId);
5050    
5051                    validate(
5052                            userId, screenName, emailAddress, openId, firstName, middleName,
5053                            lastName, smsSn, locale);
5054    
5055                    if (Validator.isNotNull(newPassword1) ||
5056                            Validator.isNotNull(newPassword2)) {
5057    
5058                            user = updatePassword(
5059                                    userId, newPassword1, newPassword2, passwordReset);
5060    
5061                            password = newPassword1;
5062    
5063                            user.setDigest(StringPool.BLANK);
5064                    }
5065    
5066                    if (user.getContactId() <= 0) {
5067                            user.setContactId(counterLocalService.increment());
5068                    }
5069    
5070                    user.setPasswordReset(passwordReset);
5071    
5072                    if (Validator.isNotNull(reminderQueryQuestion) &&
5073                            Validator.isNotNull(reminderQueryAnswer)) {
5074    
5075                            user.setReminderQueryQuestion(reminderQueryQuestion);
5076                            user.setReminderQueryAnswer(reminderQueryAnswer);
5077                    }
5078    
5079                    if (!StringUtil.equalsIgnoreCase(user.getScreenName(), screenName)) {
5080                            user.setScreenName(screenName);
5081    
5082                            user.setDigest(StringPool.BLANK);
5083                    }
5084    
5085                    boolean sendEmailAddressVerification = false;
5086    
5087                    if (company.isStrangersVerify() &&
5088                            !StringUtil.equalsIgnoreCase(
5089                                    emailAddress, user.getEmailAddress())) {
5090    
5091                            sendEmailAddressVerification = true;
5092                    }
5093                    else {
5094                            setEmailAddress(
5095                                    user, password, firstName, middleName, lastName, emailAddress);
5096                    }
5097    
5098                    if (serviceContext != null) {
5099                            String uuid = serviceContext.getUuid();
5100    
5101                            if (Validator.isNotNull(uuid)) {
5102                                    user.setUuid(uuid);
5103                            }
5104                    }
5105    
5106                    user.setFacebookId(facebookId);
5107    
5108                    Long ldapServerId = null;
5109    
5110                    if (serviceContext != null) {
5111                            ldapServerId = (Long)serviceContext.getAttribute("ldapServerId");
5112                    }
5113    
5114                    if (ldapServerId != null) {
5115                            user.setLdapServerId(ldapServerId);
5116                    }
5117    
5118                    user.setOpenId(openId);
5119    
5120                    PortalUtil.updateImageId(
5121                            user, portrait, portraitBytes, "portraitId",
5122                            PrefsPropsUtil.getLong(PropsKeys.USERS_IMAGE_MAX_SIZE),
5123                            PropsValues.USERS_IMAGE_MAX_HEIGHT,
5124                            PropsValues.USERS_IMAGE_MAX_WIDTH);
5125    
5126                    user.setLanguageId(languageId);
5127                    user.setTimeZoneId(timeZoneId);
5128                    user.setGreeting(greeting);
5129                    user.setComments(comments);
5130                    user.setFirstName(firstName);
5131                    user.setMiddleName(middleName);
5132                    user.setLastName(lastName);
5133                    user.setJobTitle(jobTitle);
5134                    user.setExpandoBridgeAttributes(serviceContext);
5135    
5136                    userPersistence.update(user, serviceContext);
5137    
5138                    // Contact
5139    
5140                    Date birthday = getBirthday(birthdayMonth, birthdayDay, birthdayYear);
5141    
5142                    long contactId = user.getContactId();
5143    
5144                    Contact contact = contactPersistence.fetchByPrimaryKey(contactId);
5145    
5146                    if (contact == null) {
5147                            contact = contactPersistence.create(contactId);
5148    
5149                            contact.setCompanyId(user.getCompanyId());
5150                            contact.setUserName(StringPool.BLANK);
5151                            contact.setClassName(User.class.getName());
5152                            contact.setClassPK(user.getUserId());
5153                            contact.setAccountId(company.getAccountId());
5154                            contact.setParentContactId(
5155                                    ContactConstants.DEFAULT_PARENT_CONTACT_ID);
5156                    }
5157    
5158                    contact.setEmailAddress(user.getEmailAddress());
5159                    contact.setFirstName(firstName);
5160                    contact.setMiddleName(middleName);
5161                    contact.setLastName(lastName);
5162                    contact.setPrefixId(prefixId);
5163                    contact.setSuffixId(suffixId);
5164                    contact.setMale(male);
5165                    contact.setBirthday(birthday);
5166                    contact.setSmsSn(smsSn);
5167                    contact.setFacebookSn(facebookSn);
5168                    contact.setJabberSn(jabberSn);
5169                    contact.setSkypeSn(skypeSn);
5170                    contact.setTwitterSn(twitterSn);
5171                    contact.setJobTitle(jobTitle);
5172    
5173                    contactPersistence.update(contact, serviceContext);
5174    
5175                    // Group
5176    
5177                    Group group = groupLocalService.getUserGroup(
5178                            user.getCompanyId(), userId);
5179    
5180                    group.setFriendlyURL(StringPool.SLASH + screenName);
5181    
5182                    groupPersistence.update(group);
5183    
5184                    // Groups and organizations
5185    
5186                    // See LPS-33205. Cache the user's list of user group roles because
5187                    // adding or removing groups may add or remove user group roles
5188                    // depending on the site default user associations.
5189    
5190                    List<UserGroupRole> previousUserGroupRoles =
5191                            userGroupRolePersistence.findByUserId(userId);
5192    
5193                    updateGroups(userId, groupIds, serviceContext, false);
5194                    updateOrganizations(userId, organizationIds, false);
5195    
5196                    // Roles
5197    
5198                    if (roleIds != null) {
5199                            roleIds = UsersAdminUtil.addRequiredRoles(user, roleIds);
5200    
5201                            userPersistence.setRoles(userId, roleIds);
5202                    }
5203    
5204                    // User group roles
5205    
5206                    updateUserGroupRoles(
5207                            user, groupIds, organizationIds, userGroupRoles,
5208                            previousUserGroupRoles);
5209    
5210                    // User groups
5211    
5212                    if (userGroupIds != null) {
5213                            if (PropsValues.USER_GROUPS_COPY_LAYOUTS_TO_USER_PERSONAL_SITE) {
5214                                    userGroupLocalService.copyUserGroupLayouts(
5215                                            userGroupIds, userId);
5216                            }
5217    
5218                            userPersistence.setUserGroups(userId, userGroupIds);
5219                    }
5220    
5221                    // Announcements
5222    
5223                    announcementsDeliveryLocalService.getUserDeliveries(user.getUserId());
5224    
5225                    // Asset
5226    
5227                    if (serviceContext != null) {
5228                            updateAsset(
5229                                    userId, user, serviceContext.getAssetCategoryIds(),
5230                                    serviceContext.getAssetTagNames());
5231                    }
5232    
5233                    // Message boards
5234    
5235                    if (GetterUtil.getBoolean(
5236                                    PropsKeys.USERS_UPDATE_USER_NAME + MBMessage.class.getName()) &&
5237                            !oldFullName.equals(user.getFullName())) {
5238    
5239                            mbMessageLocalService.updateUserName(userId, user.getFullName());
5240                    }
5241    
5242                    // Indexer
5243    
5244                    if ((serviceContext == null) || serviceContext.isIndexingEnabled()) {
5245                            Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
5246                                    User.class);
5247    
5248                            indexer.reindex(user);
5249                    }
5250    
5251                    // Email address verification
5252    
5253                    if ((serviceContext != null) && sendEmailAddressVerification) {
5254                            sendEmailAddressVerification(user, emailAddress, serviceContext);
5255                    }
5256    
5257                    // Permission cache
5258    
5259                    PermissionCacheUtil.clearCache(userId);
5260    
5261                    return user;
5262            }
5263    
5264            /**
5265             * Updates the user.
5266             *
5267             * @param      userId the primary key of the user
5268             * @param      oldPassword the user's old password
5269             * @param      newPassword1 the user's new password (optionally
5270             *             <code>null</code>)
5271             * @param      newPassword2 the user's new password confirmation (optionally
5272             *             <code>null</code>)
5273             * @param      passwordReset whether the user should be asked to reset their
5274             *             password the next time they login
5275             * @param      reminderQueryQuestion the user's new password reset question
5276             * @param      reminderQueryAnswer the user's new password reset answer
5277             * @param      screenName the user's new screen name
5278             * @param      emailAddress the user's new email address
5279             * @param      facebookId the user's new Facebook ID
5280             * @param      openId the user's new OpenID
5281             * @param      languageId the user's new language ID
5282             * @param      timeZoneId the user's new time zone ID
5283             * @param      greeting the user's new greeting
5284             * @param      comments the user's new comments
5285             * @param      firstName the user's new first name
5286             * @param      middleName the user's new middle name
5287             * @param      lastName the user's new last name
5288             * @param      prefixId the user's new name prefix ID
5289             * @param      suffixId the user's new name suffix ID
5290             * @param      male whether user is male
5291             * @param      birthdayMonth the user's new birthday month (0-based, meaning
5292             *             0 for January)
5293             * @param      birthdayDay the user's new birthday day
5294             * @param      birthdayYear the user's birthday year
5295             * @param      smsSn the user's new SMS screen name
5296             * @param      facebookSn the user's new Facebook screen name
5297             * @param      jabberSn the user's new Jabber screen name
5298             * @param      skypeSn the user's new Skype screen name
5299             * @param      twitterSn the user's new Twitter screen name
5300             * @param      jobTitle the user's new job title
5301             * @param      groupIds the primary keys of the user's groups
5302             * @param      organizationIds the primary keys of the user's organizations
5303             * @param      roleIds the primary keys of the user's roles
5304             * @param      userGroupRoles the user user's group roles
5305             * @param      userGroupIds the primary keys of the user's user groups
5306             * @param      serviceContext the service context to be applied (optionally
5307             *             <code>null</code>). Can set the UUID (with the
5308             *             <code>uuid</code> attribute), asset category IDs, asset tag
5309             *             names, and expando bridge attributes for the user.
5310             * @return     the user
5311             * @deprecated As of 7.0.0, replaced by {@link #updateUser(long, String,
5312             *             String, String, boolean, String, String, String, String,
5313             *             long, String, boolean, byte[], String, String, String,
5314             *             String, String, String, String, long, long, boolean, int,
5315             *             int, int, String, String, String, String, String, String,
5316             *             long[], long[], long[], List, long[], ServiceContext)}
5317             */
5318            @Deprecated
5319            @Override
5320            public User updateUser(
5321                            long userId, String oldPassword, String newPassword1,
5322                            String newPassword2, boolean passwordReset,
5323                            String reminderQueryQuestion, String reminderQueryAnswer,
5324                            String screenName, String emailAddress, long facebookId,
5325                            String openId, String languageId, String timeZoneId,
5326                            String greeting, String comments, String firstName,
5327                            String middleName, String lastName, long prefixId, long suffixId,
5328                            boolean male, int birthdayMonth, int birthdayDay, int birthdayYear,
5329                            String smsSn, String facebookSn, String jabberSn, String skypeSn,
5330                            String twitterSn, String jobTitle, long[] groupIds,
5331                            long[] organizationIds, long[] roleIds,
5332                            List<UserGroupRole> userGroupRoles, long[] userGroupIds,
5333                            ServiceContext serviceContext)
5334                    throws PortalException {
5335    
5336                    return updateUser(
5337                            userId, oldPassword, newPassword1, newPassword2, passwordReset,
5338                            reminderQueryQuestion, reminderQueryAnswer, screenName,
5339                            emailAddress, facebookId, openId, true, null, languageId,
5340                            timeZoneId, greeting, comments, firstName, middleName, lastName,
5341                            prefixId, suffixId, male, birthdayMonth, birthdayDay, birthdayYear,
5342                            smsSn, facebookSn, jabberSn, skypeSn, twitterSn, jobTitle, groupIds,
5343                            organizationIds, roleIds, userGroupRoles, userGroupIds,
5344                            serviceContext);
5345            }
5346    
5347            /**
5348             * Verifies the email address of the ticket.
5349             *
5350             * @param ticketKey the ticket key
5351             */
5352            @Override
5353            public void verifyEmailAddress(String ticketKey) throws PortalException {
5354                    Ticket ticket = ticketLocalService.getTicket(ticketKey);
5355    
5356                    if (ticket.isExpired() ||
5357                            (ticket.getType() != TicketConstants.TYPE_EMAIL_ADDRESS)) {
5358    
5359                            throw new NoSuchTicketException("{ticketKey=" + ticketKey + "}");
5360                    }
5361    
5362                    User user = userPersistence.findByPrimaryKey(ticket.getClassPK());
5363    
5364                    String emailAddress = ticket.getExtraInfo();
5365    
5366                    emailAddress = StringUtil.toLowerCase(emailAddress).trim();
5367    
5368                    if (!emailAddress.equals(user.getEmailAddress())) {
5369                            if (userPersistence.fetchByC_EA(
5370                                            user.getCompanyId(), emailAddress) != null) {
5371    
5372                                    throw new UserEmailAddressException.MustNotBeDuplicate(
5373                                            user.getUserId(), emailAddress);
5374                            }
5375    
5376                            setEmailAddress(
5377                                    user, StringPool.BLANK, user.getFirstName(),
5378                                    user.getMiddleName(), user.getLastName(), emailAddress);
5379    
5380                            Contact contact = user.getContact();
5381    
5382                            contact.setEmailAddress(user.getEmailAddress());
5383    
5384                            contactPersistence.update(contact);
5385                    }
5386    
5387                    user.setEmailAddressVerified(true);
5388    
5389                    userPersistence.update(user);
5390    
5391                    ticketLocalService.deleteTicket(ticket);
5392            }
5393    
5394            protected void addDefaultRolesAndTeams(long groupId, long[] userIds)
5395                    throws PortalException {
5396    
5397                    List<Role> defaultSiteRoles = new ArrayList<>();
5398    
5399                    Group group = groupLocalService.getGroup(groupId);
5400    
5401                    UnicodeProperties typeSettingsProperties =
5402                            group.getTypeSettingsProperties();
5403    
5404                    long[] defaultSiteRoleIds = StringUtil.split(
5405                            typeSettingsProperties.getProperty("defaultSiteRoleIds"), 0L);
5406    
5407                    for (long defaultSiteRoleId : defaultSiteRoleIds) {
5408                            Role defaultSiteRole = rolePersistence.fetchByPrimaryKey(
5409                                    defaultSiteRoleId);
5410    
5411                            if (defaultSiteRole == null) {
5412                                    if (_log.isWarnEnabled()) {
5413                                            _log.warn("Unable to find role " + defaultSiteRoleId);
5414                                    }
5415    
5416                                    continue;
5417                            }
5418    
5419                            defaultSiteRoles.add(defaultSiteRole);
5420                    }
5421    
5422                    List<Team> defaultTeams = new ArrayList<>();
5423    
5424                    long[] defaultTeamIds = StringUtil.split(
5425                            typeSettingsProperties.getProperty("defaultTeamIds"), 0L);
5426    
5427                    for (long defaultTeamId : defaultTeamIds) {
5428                            Team defaultTeam = teamPersistence.findByPrimaryKey(defaultTeamId);
5429    
5430                            if (defaultTeam == null) {
5431                                    if (_log.isWarnEnabled()) {
5432                                            _log.warn("Unable to find team " + defaultTeamId);
5433                                    }
5434    
5435                                    continue;
5436                            }
5437    
5438                            defaultTeams.add(defaultTeam);
5439                    }
5440    
5441                    for (long userId : userIds) {
5442                            Set<Long> userRoleIdsSet = new HashSet<>();
5443    
5444                            for (Role role : defaultSiteRoles) {
5445                                    if (!userPersistence.containsRole(userId, role.getRoleId())) {
5446                                            userRoleIdsSet.add(role.getRoleId());
5447                                    }
5448                            }
5449    
5450                            long[] userRoleIds = ArrayUtil.toArray(
5451                                    userRoleIdsSet.toArray(new Long[userRoleIdsSet.size()]));
5452    
5453                            userGroupRoleLocalService.addUserGroupRoles(
5454                                    userId, groupId, userRoleIds);
5455    
5456                            Set<Long> userTeamIdsSet = new HashSet<>();
5457    
5458                            for (Team team : defaultTeams) {
5459                                    if (!userPersistence.containsTeam(userId, team.getTeamId())) {
5460                                            userTeamIdsSet.add(team.getTeamId());
5461                                    }
5462                            }
5463    
5464                            long[] userTeamIds = ArrayUtil.toArray(
5465                                    userTeamIdsSet.toArray(new Long[userTeamIdsSet.size()]));
5466    
5467                            userPersistence.addTeams(userId, userTeamIds);
5468                    }
5469            }
5470    
5471            /**
5472             * Attempts to authenticate the user by their login and password, while
5473             * using the AuthPipeline.
5474             *
5475             * <p>
5476             * Authentication type specifies what <code>login</code> contains.The valid
5477             * values are:
5478             * </p>
5479             *
5480             * <ul>
5481             * <li>
5482             * <code>CompanyConstants.AUTH_TYPE_EA</code> - <code>login</code> is the
5483             * user's email address
5484             * </li>
5485             * <li>
5486             * <code>CompanyConstants.AUTH_TYPE_SN</code> - <code>login</code> is the
5487             * user's screen name
5488             * </li>
5489             * <li>
5490             * <code>CompanyConstants.AUTH_TYPE_ID</code> - <code>login</code> is the
5491             * user's primary key
5492             * </li>
5493             * </ul>
5494             *
5495             * @param  companyId the primary key of the user's company
5496             * @param  login either the user's email address, screen name, or primary
5497             *         key depending on the value of <code>authType</code>
5498             * @param  password the user's password
5499             * @param  authType the type of authentication to perform
5500             * @param  headerMap the header map from the authentication request
5501             * @param  parameterMap the parameter map from the authentication request
5502             * @param  resultsMap the map of authentication results (may be nil). After
5503             *         a successful authentication the user's primary key will be placed
5504             *         under the key <code>userId</code>.
5505             * @return the authentication status. This can be {@link
5506             *         Authenticator#FAILURE} indicating that the user's credentials are
5507             *         invalid, {@link Authenticator#SUCCESS} indicating a successful
5508             *         login, or {@link Authenticator#DNE} indicating that a user with
5509             *         that login does not exist.
5510             * @see    AuthPipeline
5511             */
5512            protected int authenticate(
5513                            long companyId, String login, String password, String authType,
5514                            Map<String, String[]> headerMap, Map<String, String[]> parameterMap,
5515                            Map<String, Object> resultsMap)
5516                    throws PortalException {
5517    
5518                    if (PropsValues.AUTH_LOGIN_DISABLED) {
5519                            return Authenticator.FAILURE;
5520                    }
5521    
5522                    login = StringUtil.toLowerCase(login.trim());
5523    
5524                    long userId = GetterUtil.getLong(login);
5525    
5526                    // User input validation
5527    
5528                    if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) {
5529                            if (Validator.isNull(login)) {
5530                                    throw new UserEmailAddressException.MustNotBeNull();
5531                            }
5532                    }
5533                    else if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
5534                            if (Validator.isNull(login)) {
5535                                    throw new UserScreenNameException.MustNotBeNull();
5536                            }
5537                    }
5538                    else if (authType.equals(CompanyConstants.AUTH_TYPE_ID)) {
5539                            if (Validator.isNull(login)) {
5540                                    throw new UserIdException.MustNotBeNull();
5541                            }
5542                    }
5543    
5544                    if (Validator.isNull(password)) {
5545                            throw new UserPasswordException.MustNotBeNull(userId);
5546                    }
5547    
5548                    int authResult = Authenticator.FAILURE;
5549    
5550                    // Pre-authentication pipeline
5551    
5552                    if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) {
5553                            authResult = AuthPipeline.authenticateByEmailAddress(
5554                                    PropsKeys.AUTH_PIPELINE_PRE, companyId, login, password,
5555                                    headerMap, parameterMap);
5556                    }
5557                    else if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
5558                            authResult = AuthPipeline.authenticateByScreenName(
5559                                    PropsKeys.AUTH_PIPELINE_PRE, companyId, login, password,
5560                                    headerMap, parameterMap);
5561                    }
5562                    else if (authType.equals(CompanyConstants.AUTH_TYPE_ID)) {
5563                            authResult = AuthPipeline.authenticateByUserId(
5564                                    PropsKeys.AUTH_PIPELINE_PRE, companyId, userId, password,
5565                                    headerMap, parameterMap);
5566                    }
5567    
5568                    // Get user
5569    
5570                    User user = null;
5571    
5572                    if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) {
5573                            user = fetchUserByEmailAddress(companyId, login);
5574                    }
5575                    else if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
5576                            user = fetchUserByScreenName(companyId, login);
5577                    }
5578                    else if (authType.equals(CompanyConstants.AUTH_TYPE_ID)) {
5579                            user = userPersistence.fetchByPrimaryKey(GetterUtil.getLong(login));
5580                    }
5581    
5582                    if (user == null) {
5583                            return Authenticator.DNE;
5584                    }
5585    
5586                    if (!isUserAllowedToAuthenticate(user)) {
5587                            return Authenticator.FAILURE;
5588                    }
5589    
5590                    if (!user.isPasswordEncrypted()) {
5591                            user.setPassword(PasswordEncryptorUtil.encrypt(user.getPassword()));
5592                            user.setPasswordEncrypted(true);
5593    
5594                            userPersistence.update(user);
5595                    }
5596    
5597                    // Authenticate against the User_ table
5598    
5599                    boolean skipLiferayCheck = false;
5600    
5601                    if (authResult == Authenticator.SKIP_LIFERAY_CHECK) {
5602                            authResult = Authenticator.SUCCESS;
5603    
5604                            skipLiferayCheck = true;
5605                    }
5606                    else if ((authResult == Authenticator.SUCCESS) &&
5607                                     PropsValues.AUTH_PIPELINE_ENABLE_LIFERAY_CHECK) {
5608    
5609                            boolean authenticated = PwdAuthenticator.authenticate(
5610                                    login, password, user.getPassword());
5611    
5612                            if (authenticated) {
5613                                    authResult = Authenticator.SUCCESS;
5614                            }
5615                            else {
5616                                    authResult = Authenticator.FAILURE;
5617                            }
5618                    }
5619    
5620                    // Post-authentication pipeline
5621    
5622                    if (authResult == Authenticator.SUCCESS) {
5623                            if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) {
5624                                    authResult = AuthPipeline.authenticateByEmailAddress(
5625                                            PropsKeys.AUTH_PIPELINE_POST, companyId, login, password,
5626                                            headerMap, parameterMap);
5627                            }
5628                            else if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
5629                                    authResult = AuthPipeline.authenticateByScreenName(
5630                                            PropsKeys.AUTH_PIPELINE_POST, companyId, login, password,
5631                                            headerMap, parameterMap);
5632                            }
5633                            else if (authType.equals(CompanyConstants.AUTH_TYPE_ID)) {
5634                                    authResult = AuthPipeline.authenticateByUserId(
5635                                            PropsKeys.AUTH_PIPELINE_POST, companyId, userId, password,
5636                                            headerMap, parameterMap);
5637                            }
5638                    }
5639    
5640                    if (resultsMap != null) {
5641                            resultsMap.put("userId", user.getUserId());
5642                    }
5643    
5644                    if (authResult == Authenticator.SUCCESS) {
5645    
5646                            // Update digest
5647    
5648                            if (skipLiferayCheck ||
5649                                    !PropsValues.AUTH_PIPELINE_ENABLE_LIFERAY_CHECK ||
5650                                    Validator.isNull(user.getDigest())) {
5651    
5652                                    user = userPersistence.fetchByPrimaryKey(user.getUserId());
5653    
5654                                    String digest = user.getDigest(password);
5655    
5656                                    user.setDigest(digest);
5657    
5658                                    userPersistence.update(user);
5659                            }
5660                    }
5661    
5662                    // Execute code triggered by authentication failure
5663    
5664                    if (authResult == Authenticator.FAILURE) {
5665                            authResult = handleAuthenticationFailure(
5666                                    login, authType, user, headerMap, parameterMap);
5667                    }
5668                    else {
5669                            resetFailedLoginAttempts(user);
5670                    }
5671    
5672                    // PLACEHOLDER 02
5673    
5674                    return authResult;
5675            }
5676    
5677            protected SearchContext buildSearchContext(
5678                    long companyId, String firstName, String middleName, String lastName,
5679                    String fullName, String screenName, String emailAddress, String street,
5680                    String city, String zip, String region, String country, int status,
5681                    LinkedHashMap<String, Object> params, boolean andSearch, int start,
5682                    int end, Sort[] sorts) {
5683    
5684                    SearchContext searchContext = new SearchContext();
5685    
5686                    searchContext.setAndSearch(andSearch);
5687    
5688                    Map<String, Serializable> attributes = new HashMap<>();
5689    
5690                    attributes.put("city", city);
5691                    attributes.put("country", country);
5692                    attributes.put("emailAddress", emailAddress);
5693                    attributes.put("firstName", firstName);
5694                    attributes.put("fullName", fullName);
5695                    attributes.put("lastName", lastName);
5696                    attributes.put("middleName", middleName);
5697                    attributes.put("params", params);
5698                    attributes.put("region", region);
5699                    attributes.put("screenName", screenName);
5700                    attributes.put("street", street);
5701                    attributes.put("status", status);
5702                    attributes.put("zip", zip);
5703    
5704                    searchContext.setAttributes(attributes);
5705    
5706                    searchContext.setCompanyId(companyId);
5707                    searchContext.setEnd(end);
5708    
5709                    if (params != null) {
5710                            String keywords = (String)params.remove("keywords");
5711    
5712                            if (Validator.isNotNull(keywords)) {
5713                                    searchContext.setKeywords(keywords);
5714                            }
5715                    }
5716    
5717                    if (sorts != null) {
5718                            searchContext.setSorts(sorts);
5719                    }
5720    
5721                    searchContext.setStart(start);
5722    
5723                    QueryConfig queryConfig = searchContext.getQueryConfig();
5724    
5725                    queryConfig.setHighlightEnabled(false);
5726                    queryConfig.setScoreEnabled(false);
5727    
5728                    return searchContext;
5729            }
5730    
5731            protected Date getBirthday(
5732                            int birthdayMonth, int birthdayDay, int birthdayYear)
5733                    throws PortalException {
5734    
5735                    Date birthday = PortalUtil.getDate(
5736                            birthdayMonth, birthdayDay, birthdayYear,
5737                            ContactBirthdayException.class);
5738    
5739                    if (birthday.after(new Date())) {
5740                            throw new ContactBirthdayException();
5741                    }
5742    
5743                    return birthday;
5744            }
5745    
5746            protected String getLogin(String login) {
5747                    return StringUtil.lowerCase(StringUtil.trim(login));
5748            }
5749    
5750            protected Sort[] getSorts(OrderByComparator<User> obc) {
5751                    if (obc == null) {
5752                            return new Sort[0];
5753                    }
5754    
5755                    String[] orderByClauses = StringUtil.split(obc.getOrderBy());
5756                    String[] orderByFields = obc.getOrderByFields();
5757    
5758                    Sort[] sorts = new Sort[orderByFields.length];
5759    
5760                    for (int i = 0; i < orderByFields.length; i++) {
5761                            boolean reverse = orderByClauses[i].contains("DESC");
5762    
5763                            sorts[i] = new Sort(orderByFields[i], reverse);
5764                    }
5765    
5766                    return sorts;
5767            }
5768    
5769            protected int handleAuthenticationFailure(
5770                    String login, String authType, User user,
5771                    Map<String, String[]> headerMap, Map<String, String[]> parameterMap) {
5772    
5773                    if (user == null) {
5774                            return Authenticator.DNE;
5775                    }
5776    
5777                    try {
5778                            if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) {
5779                                    AuthPipeline.onFailureByEmailAddress(
5780                                            PropsKeys.AUTH_FAILURE, user.getCompanyId(), login,
5781                                            headerMap, parameterMap);
5782                            }
5783                            else if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
5784                                    AuthPipeline.onFailureByScreenName(
5785                                            PropsKeys.AUTH_FAILURE, user.getCompanyId(), login,
5786                                            headerMap, parameterMap);
5787                            }
5788                            else if (authType.equals(CompanyConstants.AUTH_TYPE_ID)) {
5789                                    AuthPipeline.onFailureByUserId(
5790                                            PropsKeys.AUTH_FAILURE, user.getCompanyId(),
5791                                            user.getUserId(), headerMap, parameterMap);
5792                            }
5793    
5794                            user = userPersistence.fetchByPrimaryKey(user.getUserId());
5795    
5796                            if (user == null) {
5797                                    return Authenticator.DNE;
5798                            }
5799    
5800                            // Let LDAP handle max failure event
5801    
5802                            if (!LDAPSettingsUtil.isPasswordPolicyEnabled(
5803                                            user.getCompanyId())) {
5804    
5805                                    PasswordPolicy passwordPolicy = user.getPasswordPolicy();
5806    
5807                                    user = userPersistence.fetchByPrimaryKey(user.getUserId());
5808    
5809                                    int failedLoginAttempts = user.getFailedLoginAttempts();
5810                                    int maxFailures = passwordPolicy.getMaxFailure();
5811    
5812                                    if ((failedLoginAttempts >= maxFailures) &&
5813                                            (maxFailures != 0)) {
5814    
5815                                            if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) {
5816                                                    AuthPipeline.onMaxFailuresByEmailAddress(
5817                                                            PropsKeys.AUTH_MAX_FAILURES, user.getCompanyId(),
5818                                                            login, headerMap, parameterMap);
5819                                            }
5820                                            else if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
5821                                                    AuthPipeline.onMaxFailuresByScreenName(
5822                                                            PropsKeys.AUTH_MAX_FAILURES, user.getCompanyId(),
5823                                                            login, headerMap, parameterMap);
5824                                            }
5825                                            else if (authType.equals(CompanyConstants.AUTH_TYPE_ID)) {
5826                                                    AuthPipeline.onMaxFailuresByUserId(
5827                                                            PropsKeys.AUTH_MAX_FAILURES, user.getCompanyId(),
5828                                                            user.getUserId(), headerMap, parameterMap);
5829                                            }
5830                                    }
5831                            }
5832                    }
5833                    catch (Exception e) {
5834                            _log.error(e, e);
5835                    }
5836    
5837                    return Authenticator.FAILURE;
5838            }
5839    
5840            protected boolean isUseCustomSQL(LinkedHashMap<String, Object> params) {
5841                    if (MapUtil.isEmpty(params)) {
5842                            return false;
5843                    }
5844    
5845                    for (String key : params.keySet()) {
5846                            if (!key.equals("inherit") && !key.equals("usersGroups") &&
5847                                    !key.equals("usersOrgs") && !key.equals("usersOrgsCount") &&
5848                                    !key.equals("usersRoles") && !key.equals("usersTeams") &&
5849                                    !key.equals("usersUserGroups")) {
5850    
5851                                    return true;
5852                            }
5853                    }
5854    
5855                    Boolean inherit = (Boolean)params.get("inherit");
5856    
5857                    if ((inherit != null) && inherit) {
5858                            return true;
5859                    }
5860    
5861                    return false;
5862            }
5863    
5864            protected boolean isUserAllowedToAuthenticate(User user)
5865                    throws PortalException {
5866    
5867                    if (user.isDefaultUser()) {
5868                            if (_log.isInfoEnabled()) {
5869                                    _log.info("Authentication is disabled for the default user");
5870                            }
5871    
5872                            return false;
5873                    }
5874                    else if (!user.isActive()) {
5875                            if (_log.isInfoEnabled()) {
5876                                    _log.info(
5877                                            "Authentication is disabled for inactive user " +
5878                                                    user.getUserId());
5879                            }
5880    
5881                            return false;
5882                    }
5883    
5884                    // Check password policy to see if the is account locked out or if the
5885                    // password is expired
5886    
5887                    checkLockout(user);
5888    
5889                    checkPasswordExpired(user);
5890    
5891                    return true;
5892            }
5893    
5894            protected void notifyUser(
5895                    User user, String password, ServiceContext serviceContext) {
5896    
5897                    if (!PrefsPropsUtil.getBoolean(
5898                                    user.getCompanyId(),
5899                                    PropsKeys.ADMIN_EMAIL_USER_ADDED_ENABLED)) {
5900    
5901                            return;
5902                    }
5903    
5904                    String fromName = PrefsPropsUtil.getString(
5905                            user.getCompanyId(), PropsKeys.ADMIN_EMAIL_FROM_NAME);
5906                    String fromAddress = PrefsPropsUtil.getString(
5907                            user.getCompanyId(), PropsKeys.ADMIN_EMAIL_FROM_ADDRESS);
5908    
5909                    String toName = user.getFullName();
5910                    String toAddress = user.getEmailAddress();
5911    
5912                    PortletPreferences companyPortletPreferences =
5913                            PrefsPropsUtil.getPreferences(user.getCompanyId(), true);
5914    
5915                    Map<Locale, String> localizedSubjectMap =
5916                            LocalizationUtil.getLocalizationMap(
5917                                    companyPortletPreferences, "adminEmailUserAddedSubject",
5918                                    PropsKeys.ADMIN_EMAIL_USER_ADDED_SUBJECT);
5919    
5920                    Map<Locale, String> localizedBodyMap = null;
5921    
5922                    if (Validator.isNotNull(password)) {
5923                            localizedBodyMap = LocalizationUtil.getLocalizationMap(
5924                                    companyPortletPreferences, "adminEmailUserAddedBody",
5925                                    PropsKeys.ADMIN_EMAIL_USER_ADDED_BODY);
5926                    }
5927                    else {
5928                            localizedBodyMap = LocalizationUtil.getLocalizationMap(
5929                                    companyPortletPreferences, "adminEmailUserAddedNoPasswordBody",
5930                                    PropsKeys.ADMIN_EMAIL_USER_ADDED_NO_PASSWORD_BODY);
5931                    }
5932    
5933                    SubscriptionSender subscriptionSender = new SubscriptionSender();
5934    
5935                    subscriptionSender.setCompanyId(user.getCompanyId());
5936                    subscriptionSender.setContextAttributes(
5937                            "[$USER_ID$]", user.getUserId(), "[$USER_PASSWORD$]", password,
5938                            "[$USER_SCREENNAME$]", user.getScreenName());
5939                    subscriptionSender.setFrom(fromAddress, fromName);
5940                    subscriptionSender.setHtmlFormat(true);
5941                    subscriptionSender.setLocalizedBodyMap(localizedBodyMap);
5942                    subscriptionSender.setLocalizedSubjectMap(localizedSubjectMap);
5943                    subscriptionSender.setMailId("user", user.getUserId());
5944                    subscriptionSender.setServiceContext(serviceContext);
5945    
5946                    subscriptionSender.addRuntimeSubscribers(toAddress, toName);
5947    
5948                    subscriptionSender.flushNotificationsAsync();
5949            }
5950    
5951            protected void reindex(long userId) throws SearchException {
5952                    Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
5953                            User.class);
5954    
5955                    User user = userLocalService.fetchUser(userId);
5956    
5957                    indexer.reindex(user);
5958            }
5959    
5960            protected void reindex(long[] userIds) throws SearchException {
5961                    Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
5962                            User.class);
5963    
5964                    List<User> users = new ArrayList<>(userIds.length);
5965    
5966                    for (Long userId : userIds) {
5967                            User user = userLocalService.fetchUser(userId);
5968    
5969                            users.add(user);
5970                    }
5971    
5972                    indexer.reindex(users);
5973            }
5974    
5975            protected void reindex(final User user) throws SearchException {
5976                    Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
5977                            User.class);
5978    
5979                    indexer.reindex(user);
5980            }
5981    
5982            protected void resetFailedLoginAttempts(User user) {
5983                    resetFailedLoginAttempts(user, false);
5984            }
5985    
5986            protected void resetFailedLoginAttempts(User user, boolean forceUpdate) {
5987                    if (forceUpdate || (user.getFailedLoginAttempts() > 0)) {
5988                            user.setFailedLoginAttempts(0);
5989    
5990                            userPersistence.update(user);
5991                    }
5992            }
5993    
5994            protected BaseModelSearchResult<User> searchUsers(
5995                            SearchContext searchContext)
5996                    throws PortalException {
5997    
5998                    Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
5999                            User.class);
6000    
6001                    for (int i = 0; i < 10; i++) {
6002                            Hits hits = indexer.search(searchContext);
6003    
6004                            List<User> users = UsersAdminUtil.getUsers(hits);
6005    
6006                            if (users != null) {
6007                                    return new BaseModelSearchResult<>(users, hits.getLength());
6008                            }
6009                    }
6010    
6011                    throw new SearchException(
6012                            "Unable to fix the search index after 10 attempts");
6013            }
6014    
6015            protected void sendPasswordNotification(
6016                    User user, long companyId, String newPassword, String passwordResetURL,
6017                    String fromName, String fromAddress, String subject, String body,
6018                    ServiceContext serviceContext) {
6019    
6020                    if (Validator.isNull(fromName)) {
6021                            fromName = PrefsPropsUtil.getString(
6022                                    companyId, PropsKeys.ADMIN_EMAIL_FROM_NAME);
6023                    }
6024    
6025                    if (Validator.isNull(fromAddress)) {
6026                            fromAddress = PrefsPropsUtil.getString(
6027                                    companyId, PropsKeys.ADMIN_EMAIL_FROM_ADDRESS);
6028                    }
6029    
6030                    String toName = user.getFullName();
6031                    String toAddress = user.getEmailAddress();
6032    
6033                    PortletPreferences companyPortletPreferences =
6034                            PrefsPropsUtil.getPreferences(companyId, true);
6035    
6036                    Map<Locale, String> localizedSubjectMap = null;
6037                    Map<Locale, String> localizedBodyMap = null;
6038    
6039                    String bodyProperty = null;
6040                    String prefix = null;
6041                    String subjectProperty = null;
6042    
6043                    if (Validator.isNotNull(passwordResetURL)) {
6044                            bodyProperty = PropsKeys.ADMIN_EMAIL_PASSWORD_RESET_BODY;
6045                            prefix = "adminEmailPasswordReset";
6046                            subjectProperty = PropsKeys.ADMIN_EMAIL_PASSWORD_RESET_SUBJECT;
6047                    }
6048                    else {
6049                            bodyProperty = PropsKeys.ADMIN_EMAIL_PASSWORD_SENT_BODY;
6050                            prefix = "adminEmailPasswordSent";
6051                            subjectProperty = PropsKeys.ADMIN_EMAIL_PASSWORD_SENT_SUBJECT;
6052                    }
6053    
6054                    if (Validator.isNull(body)) {
6055                            localizedBodyMap = LocalizationUtil.getLocalizationMap(
6056                                    companyPortletPreferences, prefix + "Body", bodyProperty);
6057                    }
6058    
6059                    if (Validator.isNull(subject)) {
6060                            localizedSubjectMap = LocalizationUtil.getLocalizationMap(
6061                                    companyPortletPreferences, prefix + "Subject", subjectProperty);
6062                    }
6063    
6064                    SubscriptionSender subscriptionSender = new SubscriptionSender();
6065    
6066                    subscriptionSender.setCompanyId(companyId);
6067                    subscriptionSender.setContextAttributes(
6068                            "[$PASSWORD_RESET_URL$]", passwordResetURL, "[$REMOTE_ADDRESS$]",
6069                            serviceContext.getRemoteAddr(), "[$REMOTE_HOST$]",
6070                            serviceContext.getRemoteHost(), "[$USER_ID$]", user.getUserId(),
6071                            "[$USER_PASSWORD$]", newPassword, "[$USER_SCREENNAME$]",
6072                            user.getScreenName());
6073                    subscriptionSender.setFrom(fromAddress, fromName);
6074                    subscriptionSender.setHtmlFormat(true);
6075                    subscriptionSender.setLocalizedBodyMap(localizedBodyMap);
6076                    subscriptionSender.setLocalizedSubjectMap(localizedSubjectMap);
6077                    subscriptionSender.setMailId("user", user.getUserId());
6078                    subscriptionSender.setServiceContext(serviceContext);
6079    
6080                    subscriptionSender.addRuntimeSubscribers(toAddress, toName);
6081    
6082                    subscriptionSender.flushNotificationsAsync();
6083            }
6084    
6085            protected void setEmailAddress(
6086                            User user, String password, String firstName, String middleName,
6087                            String lastName, String emailAddress)
6088                    throws PortalException {
6089    
6090                    if (StringUtil.equalsIgnoreCase(emailAddress, user.getEmailAddress())) {
6091                            return;
6092                    }
6093    
6094                    long userId = user.getUserId();
6095    
6096                    // test@test.com -> test@liferay.com
6097    
6098                    if (!user.hasCompanyMx() && user.hasCompanyMx(emailAddress) &&
6099                            Validator.isNotNull(password)) {
6100    
6101                            mailService.addUser(
6102                                    user.getCompanyId(), userId, password, firstName, middleName,
6103                                    lastName, emailAddress);
6104                    }
6105    
6106                    // test@liferay.com -> bob@liferay.com
6107    
6108                    else if (user.hasCompanyMx() && user.hasCompanyMx(emailAddress)) {
6109                            mailService.updateEmailAddress(
6110                                    user.getCompanyId(), userId, emailAddress);
6111                    }
6112    
6113                    // test@liferay.com -> test@test.com
6114    
6115                    else if (user.hasCompanyMx() && !user.hasCompanyMx(emailAddress)) {
6116                            mailService.deleteEmailAddress(user.getCompanyId(), userId);
6117                    }
6118    
6119                    user.setEmailAddress(emailAddress);
6120                    user.setDigest(StringPool.BLANK);
6121            }
6122    
6123            protected void updateGroups(
6124                            long userId, long[] newGroupIds, ServiceContext serviceContext,
6125                            boolean indexingEnabled)
6126                    throws PortalException {
6127    
6128                    if (newGroupIds == null) {
6129                            return;
6130                    }
6131    
6132                    long[] oldGroupIds = getGroupPrimaryKeys(userId);
6133    
6134                    for (long oldGroupId : oldGroupIds) {
6135                            if (!ArrayUtil.contains(newGroupIds, oldGroupId)) {
6136                                    unsetGroupUsers(
6137                                            oldGroupId, new long[] {userId}, serviceContext);
6138                            }
6139                    }
6140    
6141                    for (long newGroupId : newGroupIds) {
6142                            if (!ArrayUtil.contains(oldGroupIds, newGroupId)) {
6143                                    addGroupUsers(newGroupId, new long[] {userId});
6144                            }
6145                    }
6146    
6147                    if (indexingEnabled) {
6148                            reindex(userId);
6149                    }
6150    
6151                    PermissionCacheUtil.clearCache(userId);
6152            }
6153    
6154            protected void updateOrganizations(
6155                            long userId, long[] newOrganizationIds, boolean indexingEnabled)
6156                    throws PortalException {
6157    
6158                    if (newOrganizationIds == null) {
6159                            return;
6160                    }
6161    
6162                    long[] oldOrganizationIds = getOrganizationPrimaryKeys(userId);
6163    
6164                    for (long oldOrganizationId : oldOrganizationIds) {
6165                            if (!ArrayUtil.contains(newOrganizationIds, oldOrganizationId)) {
6166                                    unsetOrganizationUsers(oldOrganizationId, new long[] {userId});
6167                            }
6168                    }
6169    
6170                    for (long newOrganizationId : newOrganizationIds) {
6171                            if (!ArrayUtil.contains(oldOrganizationIds, newOrganizationId)) {
6172                                    addOrganizationUsers(newOrganizationId, new long[] {userId});
6173                            }
6174                    }
6175    
6176                    if (indexingEnabled) {
6177                            reindex(userId);
6178                    }
6179    
6180                    PermissionCacheUtil.clearCache(userId);
6181            }
6182    
6183            protected void updateUserGroupRoles(
6184                            User user, long[] groupIds, long[] organizationIds,
6185                            List<UserGroupRole> userGroupRoles,
6186                            List<UserGroupRole> previousUserGroupRoles)
6187                    throws PortalException {
6188    
6189                    if (userGroupRoles == null) {
6190                            return;
6191                    }
6192    
6193                    userGroupRoles = new ArrayList<>(userGroupRoles);
6194    
6195                    for (UserGroupRole userGroupRole : previousUserGroupRoles) {
6196                            if (userGroupRoles.contains(userGroupRole)) {
6197                                    userGroupRoles.remove(userGroupRole);
6198                            }
6199                            else {
6200                                    userGroupRoleLocalService.deleteUserGroupRole(userGroupRole);
6201                            }
6202                    }
6203    
6204                    if (ListUtil.isEmpty(userGroupRoles)) {
6205                            return;
6206                    }
6207    
6208                    long[] validGroupIds = null;
6209    
6210                    if (groupIds != null) {
6211                            validGroupIds = ArrayUtil.clone(groupIds);
6212                    }
6213                    else {
6214                            validGroupIds = user.getGroupIds();
6215                    }
6216    
6217                    if (organizationIds == null) {
6218                            organizationIds = user.getOrganizationIds();
6219                    }
6220    
6221                    for (long organizationId : organizationIds) {
6222                            Organization organization =
6223                                    organizationPersistence.findByPrimaryKey(organizationId);
6224    
6225                            validGroupIds = ArrayUtil.append(
6226                                    validGroupIds, organization.getGroupId());
6227                    }
6228    
6229                    Arrays.sort(validGroupIds);
6230    
6231                    for (UserGroupRole userGroupRole : userGroupRoles) {
6232                            if (Arrays.binarySearch(
6233                                            validGroupIds, userGroupRole.getGroupId()) >= 0) {
6234    
6235                                    userGroupRoleLocalService.addUserGroupRole(userGroupRole);
6236                            }
6237                    }
6238            }
6239    
6240            protected void validate(
6241                            long companyId, long userId, boolean autoPassword, String password1,
6242                            String password2, boolean autoScreenName, String screenName,
6243                            String emailAddress, String openId, String firstName,
6244                            String middleName, String lastName, long[] organizationIds,
6245                            Locale locale)
6246                    throws PortalException {
6247    
6248                    validateCompanyMaxUsers(companyId);
6249    
6250                    if (!autoScreenName) {
6251                            validateScreenName(companyId, userId, screenName);
6252                    }
6253    
6254                    if (!autoPassword) {
6255                            PasswordPolicy passwordPolicy =
6256                                    passwordPolicyLocalService.getDefaultPasswordPolicy(companyId);
6257    
6258                            PwdToolkitUtil.validate(
6259                                    companyId, 0, password1, password2, passwordPolicy);
6260                    }
6261    
6262                    validateEmailAddress(companyId, emailAddress);
6263    
6264                    if (Validator.isNotNull(emailAddress)) {
6265                            User user = userPersistence.fetchByC_EA(companyId, emailAddress);
6266    
6267                            if ((user != null) && (user.getUserId() != userId)) {
6268                                    throw new UserEmailAddressException.MustNotBeDuplicate(
6269                                            userId, emailAddress);
6270                            }
6271                    }
6272    
6273                    validateOpenId(companyId, userId, openId);
6274    
6275                    validateFullName(companyId, firstName, middleName, lastName, locale);
6276    
6277                    if (organizationIds != null) {
6278                            for (long organizationId : organizationIds) {
6279                                    Organization organization =
6280                                            organizationPersistence.fetchByPrimaryKey(organizationId);
6281    
6282                                    if (organization == null) {
6283                                            throw new NoSuchOrganizationException(
6284                                                    "{organizationId=" + organizationId + "}");
6285                                    }
6286                            }
6287                    }
6288            }
6289    
6290            protected void validate(
6291                            long userId, String screenName, String emailAddress, String openId,
6292                            String firstName, String middleName, String lastName, String smsSn,
6293                            Locale locale)
6294                    throws PortalException {
6295    
6296                    User user = userPersistence.findByPrimaryKey(userId);
6297    
6298                    if (!StringUtil.equalsIgnoreCase(user.getScreenName(), screenName)) {
6299                            validateScreenName(user.getCompanyId(), userId, screenName);
6300                    }
6301    
6302                    validateEmailAddress(user.getCompanyId(), emailAddress);
6303    
6304                    validateOpenId(user.getCompanyId(), userId, openId);
6305    
6306                    if (!user.isDefaultUser()) {
6307                            if (Validator.isNotNull(emailAddress) &&
6308                                    !StringUtil.equalsIgnoreCase(
6309                                            user.getEmailAddress(), emailAddress)) {
6310    
6311                                    if (userPersistence.fetchByC_EA(
6312                                                    user.getCompanyId(), emailAddress) != null) {
6313    
6314                                            throw new UserEmailAddressException.MustNotBeDuplicate(
6315                                                    userId, emailAddress);
6316                                    }
6317                            }
6318    
6319                            validateFullName(
6320                                    user.getCompanyId(), firstName, middleName, lastName, locale);
6321                    }
6322    
6323                    if (Validator.isNotNull(smsSn) && !Validator.isEmailAddress(smsSn)) {
6324                            throw new UserSmsException.MustBeEmailAddress(smsSn);
6325                    }
6326            }
6327    
6328            protected void validateCompanyMaxUsers(long companyId)
6329                    throws PortalException {
6330    
6331                    Company company = companyPersistence.findByPrimaryKey(companyId);
6332    
6333                    if (company.isSystem() || (company.getMaxUsers() == 0)) {
6334                            return;
6335                    }
6336    
6337                    int userCount = searchCount(
6338                            companyId, null, WorkflowConstants.STATUS_APPROVED, null);
6339    
6340                    if (userCount >= company.getMaxUsers()) {
6341                            throw new CompanyMaxUsersException();
6342                    }
6343            }
6344    
6345            protected void validateEmailAddress(long companyId, String emailAddress)
6346                    throws PortalException {
6347    
6348                    if (Validator.isNull(emailAddress) &&
6349                            !PropsValues.USERS_EMAIL_ADDRESS_REQUIRED) {
6350    
6351                            return;
6352                    }
6353    
6354                    EmailAddressValidator emailAddressValidator =
6355                            EmailAddressValidatorFactory.getInstance();
6356    
6357                    if (!emailAddressValidator.validate(companyId, emailAddress)) {
6358                            throw new UserEmailAddressException.MustValidate(
6359                                    emailAddress, emailAddressValidator);
6360                    }
6361    
6362                    String pop3User = PrefsPropsUtil.getString(
6363                            PropsKeys.MAIL_SESSION_MAIL_POP3_USER,
6364                            PropsValues.MAIL_SESSION_MAIL_POP3_USER);
6365    
6366                    if (StringUtil.equalsIgnoreCase(emailAddress, pop3User)) {
6367                            throw new UserEmailAddressException.MustNotBePOP3User(emailAddress);
6368                    }
6369    
6370                    String[] reservedEmailAddresses = PrefsPropsUtil.getStringArray(
6371                            companyId, PropsKeys.ADMIN_RESERVED_EMAIL_ADDRESSES,
6372                            StringPool.NEW_LINE, PropsValues.ADMIN_RESERVED_EMAIL_ADDRESSES);
6373    
6374                    for (String reservedEmailAddress : reservedEmailAddresses) {
6375                            if (StringUtil.equalsIgnoreCase(
6376                                            emailAddress, reservedEmailAddress)) {
6377    
6378                                    throw new UserEmailAddressException.MustNotBeReserved(
6379                                            emailAddress, reservedEmailAddresses);
6380                            }
6381                    }
6382            }
6383    
6384            protected void validateEmailAddress(
6385                            User user, String emailAddress1, String emailAddress2)
6386                    throws PortalException {
6387    
6388                    if (!emailAddress1.equals(emailAddress2)) {
6389                            throw new UserEmailAddressException.MustBeEqual(
6390                                    user, emailAddress1, emailAddress2);
6391                    }
6392    
6393                    validateEmailAddress(user.getCompanyId(), emailAddress1);
6394                    validateEmailAddress(user.getCompanyId(), emailAddress2);
6395    
6396                    if (!StringUtil.equalsIgnoreCase(
6397                                    emailAddress1, user.getEmailAddress())) {
6398    
6399                            if (userPersistence.fetchByC_EA(
6400                                            user.getCompanyId(), emailAddress1) != null) {
6401    
6402                                    throw new UserEmailAddressException.MustNotBeDuplicate(
6403                                            user.getUserId(), emailAddress1);
6404                            }
6405                    }
6406            }
6407    
6408            protected void validateFullName(
6409                            long companyId, String firstName, String middleName,
6410                            String lastName, Locale locale)
6411                    throws PortalException {
6412    
6413                    FullNameDefinition fullNameDefinition =
6414                            FullNameDefinitionFactory.getInstance(locale);
6415    
6416                    if (Validator.isNull(firstName)) {
6417                            throw new ContactNameException.MustHaveFirstName();
6418                    }
6419                    else if (Validator.isNull(middleName) &&
6420                                     fullNameDefinition.isFieldRequired("middle-name")) {
6421    
6422                            throw new ContactNameException.MustHaveMiddleName();
6423                    }
6424                    else if (Validator.isNull(lastName) &&
6425                                     fullNameDefinition.isFieldRequired("last-name")) {
6426    
6427                            throw new ContactNameException.MustHaveLastName();
6428                    }
6429    
6430                    FullNameValidator fullNameValidator =
6431                            FullNameValidatorFactory.getInstance();
6432    
6433                    if (!fullNameValidator.validate(
6434                                    companyId, firstName, middleName, lastName)) {
6435    
6436                            throw new ContactNameException.MustHaveValidFullName(
6437                                    fullNameValidator);
6438                    }
6439            }
6440    
6441            protected void validateOpenId(long companyId, long userId, String openId)
6442                    throws PortalException {
6443    
6444                    if (Validator.isNull(openId)) {
6445                            return;
6446                    }
6447    
6448                    User user = userPersistence.fetchByC_O(companyId, openId);
6449    
6450                    if ((user != null) && (user.getUserId() != userId)) {
6451                            throw new DuplicateOpenIdException("{userId=" + userId + "}");
6452                    }
6453            }
6454    
6455            protected void validatePassword(
6456                            long companyId, long userId, String password1, String password2)
6457                    throws PortalException {
6458    
6459                    if (Validator.isNull(password1) || Validator.isNull(password2)) {
6460                            throw new UserPasswordException.MustNotBeNull(userId);
6461                    }
6462    
6463                    if (!password1.equals(password2)) {
6464                            throw new UserPasswordException.MustMatch(userId);
6465                    }
6466    
6467                    PasswordPolicy passwordPolicy =
6468                            passwordPolicyLocalService.getPasswordPolicyByUserId(userId);
6469    
6470                    PwdToolkitUtil.validate(
6471                            companyId, userId, password1, password2, passwordPolicy);
6472            }
6473    
6474            protected void validateReminderQuery(String question, String answer)
6475                    throws PortalException {
6476    
6477                    if (!PropsValues.USERS_REMINDER_QUERIES_ENABLED) {
6478                            return;
6479                    }
6480    
6481                    if (Validator.isNull(question)) {
6482                            throw new UserReminderQueryException("Question is null");
6483                    }
6484    
6485                    if (Validator.isNull(answer)) {
6486                            throw new UserReminderQueryException("Answer is null");
6487                    }
6488            }
6489    
6490            protected void validateScreenName(
6491                            long companyId, long userId, String screenName)
6492                    throws PortalException {
6493    
6494                    if (Validator.isNull(screenName)) {
6495                            throw new UserScreenNameException.MustNotBeNull(userId);
6496                    }
6497    
6498                    ScreenNameValidator screenNameValidator =
6499                            ScreenNameValidatorFactory.getInstance();
6500    
6501                    if (!screenNameValidator.validate(companyId, screenName)) {
6502                            throw new UserScreenNameException.MustValidate(
6503                                    userId, screenName, screenNameValidator);
6504                    }
6505    
6506                    if (Validator.isNumber(screenName)) {
6507                            if (!PropsValues.USERS_SCREEN_NAME_ALLOW_NUMERIC) {
6508                                    throw new UserScreenNameException.MustNotBeNumeric(
6509                                            userId, screenName);
6510                            }
6511    
6512                            if (!screenName.equals(String.valueOf(userId))) {
6513                                    Group group = groupPersistence.fetchByPrimaryKey(
6514                                            GetterUtil.getLong(screenName));
6515    
6516                                    if (group != null) {
6517                                            throw new UserScreenNameException.MustNotBeUsedByGroup(
6518                                                    userId, screenName, group);
6519                                    }
6520                            }
6521                    }
6522    
6523                    String[] anonymousNames = BaseServiceImpl.ANONYMOUS_NAMES;
6524    
6525                    for (String anonymousName : anonymousNames) {
6526                            if (StringUtil.equalsIgnoreCase(screenName, anonymousName)) {
6527                                    throw new UserScreenNameException.MustNotBeReservedForAnonymous(
6528                                            userId, screenName, anonymousNames);
6529                            }
6530                    }
6531    
6532                    User user = userPersistence.fetchByC_SN(companyId, screenName);
6533    
6534                    if ((user != null) && (user.getUserId() != userId)) {
6535                            throw new UserScreenNameException.MustNotBeDuplicate(
6536                                    user.getUserId(), screenName);
6537                    }
6538    
6539                    String friendlyURL = StringPool.SLASH + screenName;
6540    
6541                    Group group = groupPersistence.fetchByC_F(companyId, friendlyURL);
6542    
6543                    if ((group != null) && (group.getClassPK() != userId)) {
6544                            GroupFriendlyURLException gfurle = new GroupFriendlyURLException(
6545                                    GroupFriendlyURLException.DUPLICATE);
6546    
6547                            gfurle.setDuplicateClassPK(group.getGroupId());
6548                            gfurle.setDuplicateClassName(Group.class.getName());
6549    
6550                            throw gfurle;
6551                    }
6552    
6553                    int exceptionType = LayoutImpl.validateFriendlyURL(friendlyURL);
6554    
6555                    if (exceptionType != -1) {
6556                            throw new UserScreenNameException.MustProduceValidFriendlyURL(
6557                                    userId, screenName, exceptionType);
6558                    }
6559    
6560                    String[] reservedScreenNames = PrefsPropsUtil.getStringArray(
6561                            companyId, PropsKeys.ADMIN_RESERVED_SCREEN_NAMES,
6562                            StringPool.NEW_LINE, PropsValues.ADMIN_RESERVED_SCREEN_NAMES);
6563    
6564                    for (String reservedScreenName : reservedScreenNames) {
6565                            if (StringUtil.equalsIgnoreCase(screenName, reservedScreenName)) {
6566                                    throw new UserScreenNameException.MustNotBeReserved(
6567                                            userId, screenName, reservedScreenNames);
6568                            }
6569                    }
6570            }
6571    
6572            @BeanReference(type = MailService.class)
6573            protected MailService mailService;
6574    
6575            private static final Log _log = LogFactoryUtil.getLog(
6576                    UserLocalServiceImpl.class);
6577    
6578            private final Map<Long, User> _defaultUsers = new ConcurrentHashMap<>();
6579    
6580    }