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