001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.service.impl;
016    
017    import com.liferay.mail.service.MailService;
018    import com.liferay.portal.exception.CompanyMaxUsersException;
019    import com.liferay.portal.exception.ContactBirthdayException;
020    import com.liferay.portal.exception.ContactNameException;
021    import com.liferay.portal.exception.DuplicateOpenIdException;
022    import com.liferay.portal.exception.GroupFriendlyURLException;
023    import com.liferay.portal.exception.ModelListenerException;
024    import com.liferay.portal.exception.NoSuchImageException;
025    import com.liferay.portal.exception.NoSuchOrganizationException;
026    import com.liferay.portal.exception.NoSuchTicketException;
027    import com.liferay.portal.exception.NoSuchUserException;
028    import com.liferay.portal.exception.PasswordExpiredException;
029    import com.liferay.portal.exception.RequiredUserException;
030    import com.liferay.portal.exception.SendPasswordException;
031    import com.liferay.portal.exception.UserEmailAddressException;
032    import com.liferay.portal.exception.UserIdException;
033    import com.liferay.portal.exception.UserLockoutException;
034    import com.liferay.portal.exception.UserPasswordException;
035    import com.liferay.portal.exception.UserReminderQueryException;
036    import com.liferay.portal.exception.UserScreenNameException;
037    import com.liferay.portal.exception.UserSmsException;
038    import com.liferay.portal.kernel.bean.BeanReference;
039    import com.liferay.portal.kernel.cache.PortalCache;
040    import com.liferay.portal.kernel.cache.PortalCacheMapSynchronizeUtil;
041    import com.liferay.portal.kernel.cache.PortalCacheMapSynchronizeUtil.Synchronizer;
042    import com.liferay.portal.kernel.dao.orm.EntityCacheUtil;
043    import com.liferay.portal.kernel.dao.orm.QueryUtil;
044    import com.liferay.portal.kernel.dao.orm.WildcardMode;
045    import com.liferay.portal.kernel.exception.PortalException;
046    import com.liferay.portal.kernel.exception.SystemException;
047    import com.liferay.portal.kernel.language.LanguageUtil;
048    import com.liferay.portal.kernel.log.Log;
049    import com.liferay.portal.kernel.log.LogFactoryUtil;
050    import com.liferay.portal.kernel.messaging.DestinationNames;
051    import com.liferay.portal.kernel.messaging.Message;
052    import com.liferay.portal.kernel.messaging.MessageBusUtil;
053    import com.liferay.portal.kernel.search.BaseModelSearchResult;
054    import com.liferay.portal.kernel.search.Hits;
055    import com.liferay.portal.kernel.search.Indexer;
056    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
057    import com.liferay.portal.kernel.search.QueryConfig;
058    import com.liferay.portal.kernel.search.SearchContext;
059    import com.liferay.portal.kernel.search.SearchException;
060    import com.liferay.portal.kernel.search.Sort;
061    import com.liferay.portal.kernel.security.auth.Authenticator;
062    import com.liferay.portal.kernel.security.auth.EmailAddressGenerator;
063    import com.liferay.portal.kernel.security.auth.EmailAddressValidator;
064    import com.liferay.portal.kernel.security.auth.FullNameDefinition;
065    import com.liferay.portal.kernel.security.auth.FullNameDefinitionFactory;
066    import com.liferay.portal.kernel.security.auth.FullNameGenerator;
067    import com.liferay.portal.kernel.security.auth.FullNameGeneratorFactory;
068    import com.liferay.portal.kernel.security.auth.FullNameValidator;
069    import com.liferay.portal.kernel.security.auth.PrincipalException;
070    import com.liferay.portal.kernel.security.auth.PrincipalThreadLocal;
071    import com.liferay.portal.kernel.security.auth.ScreenNameGenerator;
072    import com.liferay.portal.kernel.security.auth.ScreenNameValidator;
073    import com.liferay.portal.kernel.security.ldap.LDAPSettingsUtil;
074    import com.liferay.portal.kernel.security.pwd.PasswordEncryptorUtil;
075    import com.liferay.portal.kernel.spring.aop.Skip;
076    import com.liferay.portal.kernel.transaction.Propagation;
077    import com.liferay.portal.kernel.transaction.TransactionCommitCallbackUtil;
078    import com.liferay.portal.kernel.transaction.Transactional;
079    import com.liferay.portal.kernel.util.ArrayUtil;
080    import com.liferay.portal.kernel.util.Digester;
081    import com.liferay.portal.kernel.util.DigesterUtil;
082    import com.liferay.portal.kernel.util.GetterUtil;
083    import com.liferay.portal.kernel.util.KeyValuePair;
084    import com.liferay.portal.kernel.util.ListUtil;
085    import com.liferay.portal.kernel.util.LocaleUtil;
086    import com.liferay.portal.kernel.util.LocalizationUtil;
087    import com.liferay.portal.kernel.util.MapUtil;
088    import com.liferay.portal.kernel.util.OrderByComparator;
089    import com.liferay.portal.kernel.util.ParamUtil;
090    import com.liferay.portal.kernel.util.PropsKeys;
091    import com.liferay.portal.kernel.util.PwdGenerator;
092    import com.liferay.portal.kernel.util.SetUtil;
093    import com.liferay.portal.kernel.util.StringBundler;
094    import com.liferay.portal.kernel.util.StringPool;
095    import com.liferay.portal.kernel.util.StringUtil;
096    import com.liferay.portal.kernel.util.UnicodeProperties;
097    import com.liferay.portal.kernel.util.Validator;
098    import com.liferay.portal.kernel.workflow.WorkflowConstants;
099    import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
100    import com.liferay.portal.kernel.workflow.WorkflowThreadLocal;
101    import com.liferay.portal.model.Account;
102    import com.liferay.portal.model.Company;
103    import com.liferay.portal.model.CompanyConstants;
104    import com.liferay.portal.model.Contact;
105    import com.liferay.portal.model.ContactConstants;
106    import com.liferay.portal.model.Group;
107    import com.liferay.portal.model.GroupConstants;
108    import com.liferay.portal.model.Layout;
109    import com.liferay.portal.model.Organization;
110    import com.liferay.portal.model.PasswordPolicy;
111    import com.liferay.portal.model.ResourceConstants;
112    import com.liferay.portal.model.Role;
113    import com.liferay.portal.model.RoleConstants;
114    import com.liferay.portal.model.Team;
115    import com.liferay.portal.model.Ticket;
116    import com.liferay.portal.model.TicketConstants;
117    import com.liferay.portal.model.User;
118    import com.liferay.portal.model.UserGroup;
119    import com.liferay.portal.model.UserGroupRole;
120    import com.liferay.portal.model.impl.LayoutImpl;
121    import com.liferay.portal.model.impl.UserCacheModel;
122    import com.liferay.portal.model.impl.UserImpl;
123    import com.liferay.portal.security.auth.AuthPipeline;
124    import com.liferay.portal.security.auth.EmailAddressGeneratorFactory;
125    import com.liferay.portal.security.auth.EmailAddressValidatorFactory;
126    import com.liferay.portal.security.auth.FullNameValidatorFactory;
127    import com.liferay.portal.security.auth.ScreenNameGeneratorFactory;
128    import com.liferay.portal.security.auth.ScreenNameValidatorFactory;
129    import com.liferay.portal.security.permission.PermissionCacheUtil;
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             * @param  companyId the primary key of the user's company
2680             * @return the user with the UUID
2681             */
2682            @Override
2683            public User getUserByUuidAndCompanyId(String uuid, long companyId)
2684                    throws PortalException {
2685    
2686                    List<User> users = userPersistence.findByUuid_C(uuid, companyId);
2687    
2688                    if (users.isEmpty()) {
2689                            StringBundler sb = new StringBundler(5);
2690    
2691                            sb.append("{uuid=");
2692                            sb.append(uuid);
2693                            sb.append(", companyId=");
2694                            sb.append(companyId);
2695                            sb.append("}");
2696    
2697                            throw new NoSuchUserException(sb.toString());
2698                    }
2699                    else {
2700                            return users.get(0);
2701                    }
2702            }
2703    
2704            /**
2705             * Returns the number of users with the status belonging to the user group.
2706             *
2707             * @param  userGroupId the primary key of the user group
2708             * @param  status the workflow status
2709             * @return the number of users with the status belonging to the user group
2710             */
2711            @Override
2712            public int getUserGroupUsersCount(long userGroupId, int status)
2713                    throws PortalException {
2714    
2715                    UserGroup userGroup = userGroupPersistence.findByPrimaryKey(
2716                            userGroupId);
2717    
2718                    LinkedHashMap<String, Object> params = new LinkedHashMap<>();
2719    
2720                    params.put("usersUserGroups", Long.valueOf(userGroupId));
2721    
2722                    return searchCount(userGroup.getCompanyId(), null, status, params);
2723            }
2724    
2725            /**
2726             * Returns the primary key of the user with the email address.
2727             *
2728             * @param  companyId the primary key of the user's company
2729             * @param  emailAddress the user's email address
2730             * @return the primary key of the user with the email address
2731             */
2732            @Override
2733            public long getUserIdByEmailAddress(long companyId, String emailAddress)
2734                    throws PortalException {
2735    
2736                    emailAddress = StringUtil.toLowerCase(emailAddress.trim());
2737    
2738                    User user = userPersistence.findByC_EA(companyId, emailAddress);
2739    
2740                    return user.getUserId();
2741            }
2742    
2743            /**
2744             * Returns the primary key of the user with the screen name.
2745             *
2746             * @param  companyId the primary key of the user's company
2747             * @param  screenName the user's screen name
2748             * @return the primary key of the user with the screen name
2749             */
2750            @Override
2751            public long getUserIdByScreenName(long companyId, String screenName)
2752                    throws PortalException {
2753    
2754                    screenName = getLogin(screenName);
2755    
2756                    User user = userPersistence.findByC_SN(companyId, screenName);
2757    
2758                    return user.getUserId();
2759            }
2760    
2761            /**
2762             * Returns <code>true</code> if the password policy has been assigned to the
2763             * user.
2764             *
2765             * @param  passwordPolicyId the primary key of the password policy
2766             * @param  userId the primary key of the user
2767             * @return <code>true</code> if the password policy is assigned to the user;
2768             *         <code>false</code> otherwise
2769             */
2770            @Override
2771            public boolean hasPasswordPolicyUser(long passwordPolicyId, long userId) {
2772                    return passwordPolicyRelLocalService.hasPasswordPolicyRel(
2773                            passwordPolicyId, User.class.getName(), userId);
2774            }
2775    
2776            /**
2777             * Returns <code>true</code> if the user has the role with the name,
2778             * optionally through inheritance.
2779             *
2780             * @param  companyId the primary key of the role's company
2781             * @param  name the name of the role (must be a regular role, not an
2782             *         organization, site or provider role)
2783             * @param  userId the primary key of the user
2784             * @param  inherited whether to include roles inherited from organizations,
2785             *         sites, etc.
2786             * @return <code>true</code> if the user has the role; <code>false</code>
2787             *         otherwise
2788             */
2789            @Override
2790            public boolean hasRoleUser(
2791                            long companyId, String name, long userId, boolean inherited)
2792                    throws PortalException {
2793    
2794                    return roleLocalService.hasUserRole(userId, companyId, name, inherited);
2795            }
2796    
2797            /**
2798             * Returns <code>true</code> if the user's password is expired.
2799             *
2800             * @param  user the user
2801             * @return <code>true</code> if the user's password is expired;
2802             *         <code>false</code> otherwise
2803             */
2804            @Override
2805            public boolean isPasswordExpired(User user) throws PortalException {
2806                    PasswordPolicy passwordPolicy = user.getPasswordPolicy();
2807    
2808                    if ((passwordPolicy != null) && passwordPolicy.getExpireable()) {
2809                            Date now = new Date();
2810    
2811                            if (user.getPasswordModifiedDate() == null) {
2812                                    user.setPasswordModifiedDate(now);
2813    
2814                                    userLocalService.updateUser(user);
2815                            }
2816    
2817                            long passwordStartTime = user.getPasswordModifiedDate().getTime();
2818                            long elapsedTime = now.getTime() - passwordStartTime;
2819    
2820                            if (elapsedTime > (passwordPolicy.getMaxAge() * 1000)) {
2821                                    return true;
2822                            }
2823                            else {
2824                                    return false;
2825                            }
2826                    }
2827    
2828                    return false;
2829            }
2830    
2831            /**
2832             * Returns <code>true</code> if the password policy is configured to warn
2833             * the user that his password is expiring and the remaining time until
2834             * expiration is equal or less than the configured warning time.
2835             *
2836             * @param  user the user
2837             * @return <code>true</code> if the user's password is expiring soon;
2838             *         <code>false</code> otherwise
2839             */
2840            @Override
2841            public boolean isPasswordExpiringSoon(User user) throws PortalException {
2842                    PasswordPolicy passwordPolicy = user.getPasswordPolicy();
2843    
2844                    if ((passwordPolicy != null) && passwordPolicy.isExpireable() &&
2845                            (passwordPolicy.getWarningTime() > 0)) {
2846    
2847                            Date now = new Date();
2848    
2849                            if (user.getPasswordModifiedDate() == null) {
2850                                    user.setPasswordModifiedDate(now);
2851    
2852                                    userLocalService.updateUser(user);
2853                            }
2854    
2855                            long timeModified = user.getPasswordModifiedDate().getTime();
2856                            long passwordExpiresOn =
2857                                    (passwordPolicy.getMaxAge() * 1000) + timeModified;
2858    
2859                            long timeStartWarning =
2860                                    passwordExpiresOn - (passwordPolicy.getWarningTime() * 1000);
2861    
2862                            if (now.getTime() > timeStartWarning) {
2863                                    return true;
2864                            }
2865                            else {
2866                                    return false;
2867                            }
2868                    }
2869    
2870                    return false;
2871            }
2872    
2873            /**
2874             * Returns the default user for the company.
2875             *
2876             * @param  companyId the primary key of the company
2877             * @return the default user for the company
2878             */
2879            @Override
2880            public User loadGetDefaultUser(long companyId) throws PortalException {
2881                    return userPersistence.findByC_DU(companyId, true);
2882            }
2883    
2884            /**
2885             * Returns an ordered range of all the users who match the keywords and
2886             * status, without using the indexer. It is preferable to use the indexed
2887             * version {@link #search(long, String, int, LinkedHashMap, int, int, Sort)}
2888             * instead of this method wherever possible for performance reasons.
2889             *
2890             * <p>
2891             * Useful when paginating results. Returns a maximum of <code>end -
2892             * start</code> instances. <code>start</code> and <code>end</code> are not
2893             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2894             * refers to the first result in the set. Setting both <code>start</code>
2895             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2896             * result set.
2897             * </p>
2898             *
2899             * @param  companyId the primary key of the user's company
2900             * @param  keywords the keywords (space separated), which may occur in the
2901             *         user's first name, middle name, last name, screen name, or email
2902             *         address
2903             * @param  status the workflow status
2904             * @param  params the finder parameters (optionally <code>null</code>). For
2905             *         more information see {@link
2906             *         com.liferay.portal.service.persistence.UserFinder}.
2907             * @param  start the lower bound of the range of users
2908             * @param  end the upper bound of the range of users (not inclusive)
2909             * @param  obc the comparator to order the users by (optionally
2910             *         <code>null</code>)
2911             * @return the matching users
2912             * @see    com.liferay.portal.service.persistence.UserFinder
2913             */
2914            @Override
2915            public List<User> search(
2916                    long companyId, String keywords, int status,
2917                    LinkedHashMap<String, Object> params, int start, int end,
2918                    OrderByComparator<User> obc) {
2919    
2920                    Indexer<?> indexer = IndexerRegistryUtil.nullSafeGetIndexer(User.class);
2921    
2922                    if (!indexer.isIndexerEnabled() ||
2923                            !PropsValues.USERS_SEARCH_WITH_INDEX || isUseCustomSQL(params)) {
2924    
2925                            return userFinder.findByKeywords(
2926                                    companyId, keywords, status, params, start, end, obc);
2927                    }
2928    
2929                    try {
2930                            return UsersAdminUtil.getUsers(
2931                                    search(
2932                                            companyId, keywords, status, params, start, end,
2933                                            getSorts(obc)));
2934                    }
2935                    catch (Exception e) {
2936                            throw new SystemException(e);
2937                    }
2938            }
2939    
2940            /**
2941             * Returns an ordered range of all the users who match the keywords and
2942             * status, using the indexer. It is preferable to use this method instead of
2943             * the non-indexed version whenever possible for performance reasons.
2944             *
2945             * <p>
2946             * Useful when paginating results. Returns a maximum of <code>end -
2947             * start</code> instances. <code>start</code> and <code>end</code> are not
2948             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2949             * refers to the first result in the set. Setting both <code>start</code>
2950             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2951             * result set.
2952             * </p>
2953             *
2954             * @param  companyId the primary key of the user's company
2955             * @param  keywords the keywords (space separated), which may occur in the
2956             *         user's first name, middle name, last name, screen name, or email
2957             *         address
2958             * @param  status the workflow status
2959             * @param  params the indexer parameters (optionally <code>null</code>). For
2960             *         more information see {@link
2961             *         com.liferay.portlet.usersadmin.util.UserIndexer}.
2962             * @param  start the lower bound of the range of users
2963             * @param  end the upper bound of the range of users (not inclusive)
2964             * @param  sort the field and direction to sort by (optionally
2965             *         <code>null</code>)
2966             * @return the matching users
2967             * @see    com.liferay.portlet.usersadmin.util.UserIndexer
2968             */
2969            @Override
2970            public Hits search(
2971                    long companyId, String keywords, int status,
2972                    LinkedHashMap<String, Object> params, int start, int end, Sort sort) {
2973    
2974                    return search(
2975                            companyId, keywords, status, params, start, end, new Sort[] {sort});
2976            }
2977    
2978            @Override
2979            public Hits search(
2980                    long companyId, String keywords, int status,
2981                    LinkedHashMap<String, Object> params, int start, int end,
2982                    Sort[] sorts) {
2983    
2984                    String firstName = null;
2985                    String middleName = null;
2986                    String lastName = null;
2987                    String fullName = null;
2988                    String screenName = null;
2989                    String emailAddress = null;
2990                    String street = null;
2991                    String city = null;
2992                    String zip = null;
2993                    String region = null;
2994                    String country = null;
2995                    boolean andOperator = false;
2996    
2997                    if (Validator.isNotNull(keywords)) {
2998                            firstName = keywords;
2999                            middleName = keywords;
3000                            lastName = keywords;
3001                            fullName = keywords;
3002                            screenName = keywords;
3003                            emailAddress = keywords;
3004                            street = keywords;
3005                            city = keywords;
3006                            zip = keywords;
3007                            region = keywords;
3008                            country = keywords;
3009                    }
3010                    else {
3011                            andOperator = true;
3012                    }
3013    
3014                    if (params != null) {
3015                            params.put("keywords", keywords);
3016                    }
3017    
3018                    try {
3019                            Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
3020                                    User.class);
3021    
3022                            SearchContext searchContext = buildSearchContext(
3023                                    companyId, firstName, middleName, lastName, fullName,
3024                                    screenName, emailAddress, street, city, zip, region, country,
3025                                    status, params, andOperator, start, end, sorts);
3026    
3027                            return indexer.search(searchContext);
3028                    }
3029                    catch (Exception e) {
3030                            throw new SystemException(e);
3031                    }
3032            }
3033    
3034            /**
3035             * Returns an ordered range of all the users with the status, and whose
3036             * first name, middle name, last name, screen name, and email address match
3037             * the keywords specified for them, without using the indexer. It is
3038             * preferable to use the indexed version {@link #search(long, String,
3039             * String, String, String, String, int, LinkedHashMap, boolean, int, int,
3040             * Sort)} instead of this method wherever possible for performance reasons.
3041             *
3042             * <p>
3043             * Useful when paginating results. Returns a maximum of <code>end -
3044             * start</code> instances. <code>start</code> and <code>end</code> are not
3045             * primary keys, they are indexes in the result set. Thus, <code>0</code>
3046             * refers to the first result in the set. Setting both <code>start</code>
3047             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
3048             * result set.
3049             * </p>
3050             *
3051             * @param  companyId the primary key of the user's company
3052             * @param  firstName the first name keywords (space separated)
3053             * @param  middleName the middle name keywords
3054             * @param  lastName the last name keywords
3055             * @param  screenName the screen name keywords
3056             * @param  emailAddress the email address keywords
3057             * @param  status the workflow status
3058             * @param  params the finder parameters (optionally <code>null</code>). For
3059             *         more information see {@link
3060             *         com.liferay.portal.service.persistence.UserFinder}.
3061             * @param  andSearch whether every field must match its keywords, or just
3062             *         one field. For example, &quot;users with the first name 'bob' and
3063             *         last name 'smith'&quot; vs &quot;users with the first name 'bob'
3064             *         or the last name 'smith'&quot;.
3065             * @param  start the lower bound of the range of users
3066             * @param  end the upper bound of the range of users (not inclusive)
3067             * @param  obc the comparator to order the users by (optionally
3068             *         <code>null</code>)
3069             * @return the matching users
3070             * @see    com.liferay.portal.service.persistence.UserFinder
3071             */
3072            @Override
3073            public List<User> search(
3074                    long companyId, String firstName, String middleName, String lastName,
3075                    String screenName, String emailAddress, int status,
3076                    LinkedHashMap<String, Object> params, boolean andSearch, int start,
3077                    int end, OrderByComparator<User> obc) {
3078    
3079                    Indexer<?> indexer = IndexerRegistryUtil.nullSafeGetIndexer(User.class);
3080    
3081                    if (!indexer.isIndexerEnabled() ||
3082                            !PropsValues.USERS_SEARCH_WITH_INDEX || isUseCustomSQL(params)) {
3083    
3084                            return userFinder.findByC_FN_MN_LN_SN_EA_S(
3085                                    companyId, firstName, middleName, lastName, screenName,
3086                                    emailAddress, status, params, andSearch, start, end, obc);
3087                    }
3088    
3089                    try {
3090                            return UsersAdminUtil.getUsers(
3091                                    search(
3092                                            companyId, firstName, middleName, lastName, screenName,
3093                                            emailAddress, status, params, andSearch, start, end,
3094                                            getSorts(obc)));
3095                    }
3096                    catch (Exception e) {
3097                            throw new SystemException(e);
3098                    }
3099            }
3100    
3101            /**
3102             * Returns an ordered range of all the users with the status, and whose
3103             * first name, middle name, last name, screen name, and email address match
3104             * the keywords specified for them, using the indexer. It is preferable to
3105             * use this method instead of the non-indexed version whenever possible for
3106             * performance reasons.
3107             *
3108             * <p>
3109             * Useful when paginating results. Returns a maximum of <code>end -
3110             * start</code> instances. <code>start</code> and <code>end</code> are not
3111             * primary keys, they are indexes in the result set. Thus, <code>0</code>
3112             * refers to the first result in the set. Setting both <code>start</code>
3113             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
3114             * result set.
3115             * </p>
3116             *
3117             * @param  companyId the primary key of the user's company
3118             * @param  firstName the first name keywords (space separated)
3119             * @param  middleName the middle name keywords
3120             * @param  lastName the last name keywords
3121             * @param  screenName the screen name keywords
3122             * @param  emailAddress the email address keywords
3123             * @param  status the workflow status
3124             * @param  params the indexer parameters (optionally <code>null</code>). For
3125             *         more information see {@link
3126             *         com.liferay.portlet.usersadmin.util.UserIndexer}.
3127             * @param  andSearch whether every field must match its keywords, or just
3128             *         one field. For example, &quot;users with the first name 'bob' and
3129             *         last name 'smith'&quot; vs &quot;users with the first name 'bob'
3130             *         or the last name 'smith'&quot;.
3131             * @param  start the lower bound of the range of users
3132             * @param  end the upper bound of the range of users (not inclusive)
3133             * @param  sort the field and direction to sort by (optionally
3134             *         <code>null</code>)
3135             * @return the matching users
3136             * @see    com.liferay.portlet.usersadmin.util.UserIndexer
3137             */
3138            @Override
3139            public Hits search(
3140                    long companyId, String firstName, String middleName, String lastName,
3141                    String screenName, String emailAddress, int status,
3142                    LinkedHashMap<String, Object> params, boolean andSearch, int start,
3143                    int end, Sort sort) {
3144    
3145                    return search(
3146                            companyId, firstName, middleName, lastName, screenName,
3147                            emailAddress, status, params, andSearch, start, end,
3148                            new Sort[] {sort});
3149            }
3150    
3151            @Override
3152            public Hits search(
3153                    long companyId, String firstName, String middleName, String lastName,
3154                    String screenName, String emailAddress, int status,
3155                    LinkedHashMap<String, Object> params, boolean andSearch, int start,
3156                    int end, Sort[] sorts) {
3157    
3158                    try {
3159                            Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
3160                                    User.class);
3161    
3162                            SearchContext searchContext = buildSearchContext(
3163                                    companyId, firstName, middleName, lastName, null, screenName,
3164                                    emailAddress, null, null, null, null, null, status, params,
3165                                    andSearch, start, end, sorts);
3166    
3167                            return indexer.search(searchContext);
3168                    }
3169                    catch (Exception e) {
3170                            throw new SystemException(e);
3171                    }
3172            }
3173    
3174            /**
3175             * Returns the number of users who match the keywords and status.
3176             *
3177             * @param  companyId the primary key of the user's company
3178             * @param  keywords the keywords (space separated), which may occur in the
3179             *         user's first name, middle name, last name, screen name, or email
3180             *         address
3181             * @param  status the workflow status
3182             * @param  params the finder parameters (optionally <code>null</code>). For
3183             *         more information see {@link
3184             *         com.liferay.portal.service.persistence.UserFinder}.
3185             * @return the number matching users
3186             */
3187            @Override
3188            public int searchCount(
3189                    long companyId, String keywords, int status,
3190                    LinkedHashMap<String, Object> params) {
3191    
3192                    Indexer<?> indexer = IndexerRegistryUtil.nullSafeGetIndexer(User.class);
3193    
3194                    if (!indexer.isIndexerEnabled() ||
3195                            !PropsValues.USERS_SEARCH_WITH_INDEX || isUseCustomSQL(params)) {
3196    
3197                            return userFinder.countByKeywords(
3198                                    companyId, keywords, status, params);
3199                    }
3200    
3201                    try {
3202                            String firstName = null;
3203                            String middleName = null;
3204                            String lastName = null;
3205                            String fullName = null;
3206                            String screenName = null;
3207                            String emailAddress = null;
3208                            String street = null;
3209                            String city = null;
3210                            String zip = null;
3211                            String region = null;
3212                            String country = null;
3213                            boolean andOperator = false;
3214    
3215                            if (Validator.isNotNull(keywords)) {
3216                                    firstName = keywords;
3217                                    middleName = keywords;
3218                                    lastName = keywords;
3219                                    fullName = keywords;
3220                                    screenName = keywords;
3221                                    emailAddress = keywords;
3222                                    street = keywords;
3223                                    city = keywords;
3224                                    zip = keywords;
3225                                    region = keywords;
3226                                    country = keywords;
3227                            }
3228                            else {
3229                                    andOperator = true;
3230                            }
3231    
3232                            if (params != null) {
3233                                    params.put("keywords", keywords);
3234                            }
3235    
3236                            SearchContext searchContext = buildSearchContext(
3237                                    companyId, firstName, middleName, lastName, fullName,
3238                                    screenName, emailAddress, street, city, zip, region, country,
3239                                    status, params, andOperator, QueryUtil.ALL_POS,
3240                                    QueryUtil.ALL_POS, null);
3241    
3242                            return (int)indexer.searchCount(searchContext);
3243                    }
3244                    catch (Exception e) {
3245                            throw new SystemException(e);
3246                    }
3247            }
3248    
3249            /**
3250             * Returns the number of users with the status, and whose first name, middle
3251             * name, last name, screen name, and email address match the keywords
3252             * specified for them.
3253             *
3254             * @param  companyId the primary key of the user's company
3255             * @param  firstName the first name keywords (space separated)
3256             * @param  middleName the middle name keywords
3257             * @param  lastName the last name keywords
3258             * @param  screenName the screen name keywords
3259             * @param  emailAddress the email address keywords
3260             * @param  status the workflow status
3261             * @param  params the finder parameters (optionally <code>null</code>). For
3262             *         more information see {@link
3263             *         com.liferay.portal.service.persistence.UserFinder}.
3264             * @param  andSearch whether every field must match its keywords, or just
3265             *         one field. For example, &quot;users with the first name 'bob' and
3266             *         last name 'smith'&quot; vs &quot;users with the first name 'bob'
3267             *         or the last name 'smith'&quot;.
3268             * @return the number of matching users
3269             */
3270            @Override
3271            public int searchCount(
3272                    long companyId, String firstName, String middleName, String lastName,
3273                    String screenName, String emailAddress, int status,
3274                    LinkedHashMap<String, Object> params, boolean andSearch) {
3275    
3276                    Indexer<?> indexer = IndexerRegistryUtil.nullSafeGetIndexer(User.class);
3277    
3278                    if (!indexer.isIndexerEnabled() ||
3279                            !PropsValues.USERS_SEARCH_WITH_INDEX || isUseCustomSQL(params)) {
3280    
3281                            return userFinder.countByC_FN_MN_LN_SN_EA_S(
3282                                    companyId, firstName, middleName, lastName, screenName,
3283                                    emailAddress, status, params, andSearch);
3284                    }
3285    
3286                    try {
3287                            FullNameGenerator fullNameGenerator =
3288                                    FullNameGeneratorFactory.getInstance();
3289    
3290                            String fullName = fullNameGenerator.getFullName(
3291                                    firstName, middleName, lastName);
3292    
3293                            SearchContext searchContext = buildSearchContext(
3294                                    companyId, firstName, middleName, lastName, fullName,
3295                                    screenName, emailAddress, null, null, null, null, null, status,
3296                                    params, true, QueryUtil.ALL_POS, QueryUtil.ALL_POS, null);
3297    
3298                            return (int)indexer.searchCount(searchContext);
3299                    }
3300                    catch (Exception e) {
3301                            throw new SystemException(e);
3302                    }
3303            }
3304    
3305            @Override
3306            public Map<Long, Integer> searchCounts(
3307                    long companyId, int status, long[] groupIds) {
3308    
3309                    return userFinder.countByGroups(companyId, status, groupIds);
3310            }
3311    
3312            @Override
3313            public List<User> searchSocial(
3314                            long userId, int[] socialRelationTypes, String keywords, int start,
3315                            int end)
3316                    throws PortalException {
3317    
3318                    User user = userPersistence.findByPrimaryKey(userId);
3319    
3320                    LinkedHashMap<String, Object> params = new LinkedHashMap<>();
3321    
3322                    params.put(
3323                            "socialRelationType",
3324                            new Long[][] {
3325                                    new Long[] {userId}, ArrayUtil.toLongArray(socialRelationTypes)
3326                            });
3327                    params.put("wildcardMode", WildcardMode.TRAILING);
3328    
3329                    return userFinder.findByKeywords(
3330                            user.getCompanyId(), keywords, WorkflowConstants.STATUS_APPROVED,
3331                            params, start, end, null);
3332            }
3333    
3334            @Override
3335            public List<User> searchSocial(
3336                    long companyId, long[] groupIds, String keywords, int start, int end) {
3337    
3338                    LinkedHashMap<String, Object> params = new LinkedHashMap<>();
3339    
3340                    params.put("usersGroups", ArrayUtil.toLongArray(groupIds));
3341                    params.put("wildcardMode", WildcardMode.TRAILING);
3342    
3343                    return userFinder.findByKeywords(
3344                            companyId, keywords, WorkflowConstants.STATUS_APPROVED, params,
3345                            start, end, null);
3346            }
3347    
3348            @Override
3349            public List<User> searchSocial(
3350                            long[] groupIds, long userId, int[] socialRelationTypes,
3351                            String keywords, int start, int end)
3352                    throws PortalException {
3353    
3354                    User user = userPersistence.findByPrimaryKey(userId);
3355    
3356                    LinkedHashMap<String, Object> params = new LinkedHashMap<>();
3357    
3358                    params.put(
3359                            "socialRelationType",
3360                            new Long[][] {
3361                                    new Long[] {userId}, ArrayUtil.toLongArray(socialRelationTypes)
3362                            });
3363                    params.put("socialRelationTypeUnionUserGroups", true);
3364                    params.put("usersGroups", ArrayUtil.toLongArray(groupIds));
3365                    params.put("wildcardMode", WildcardMode.TRAILING);
3366    
3367                    return userFinder.findByKeywords(
3368                            user.getCompanyId(), keywords, WorkflowConstants.STATUS_APPROVED,
3369                            params, start, end, null);
3370            }
3371    
3372            @Override
3373            public BaseModelSearchResult<User> searchUsers(
3374                            long companyId, String keywords, int status,
3375                            LinkedHashMap<String, Object> params, int start, int end, Sort sort)
3376                    throws PortalException {
3377    
3378                    return searchUsers(
3379                            companyId, keywords, status, params, start, end, new Sort[] {sort});
3380            }
3381    
3382            @Override
3383            public BaseModelSearchResult<User> searchUsers(
3384                            long companyId, String keywords, int status,
3385                            LinkedHashMap<String, Object> params, int start, int end,
3386                            Sort[] sorts)
3387                    throws PortalException {
3388    
3389                    String firstName = null;
3390                    String middleName = null;
3391                    String lastName = null;
3392                    String fullName = null;
3393                    String screenName = null;
3394                    String emailAddress = null;
3395                    String street = null;
3396                    String city = null;
3397                    String zip = null;
3398                    String region = null;
3399                    String country = null;
3400                    boolean andOperator = false;
3401    
3402                    if (Validator.isNotNull(keywords)) {
3403                            firstName = keywords;
3404                            middleName = keywords;
3405                            lastName = keywords;
3406                            fullName = keywords;
3407                            screenName = keywords;
3408                            emailAddress = keywords;
3409                            street = keywords;
3410                            city = keywords;
3411                            zip = keywords;
3412                            region = keywords;
3413                            country = keywords;
3414                    }
3415                    else {
3416                            andOperator = true;
3417                    }
3418    
3419                    if (params != null) {
3420                            params.put("keywords", keywords);
3421                    }
3422    
3423                    SearchContext searchContext = buildSearchContext(
3424                            companyId, firstName, middleName, lastName, fullName, screenName,
3425                            emailAddress, street, city, zip, region, country, status, params,
3426                            andOperator, start, end, sorts);
3427    
3428                    return searchUsers(searchContext);
3429            }
3430    
3431            @Override
3432            public BaseModelSearchResult<User> searchUsers(
3433                            long companyId, String firstName, String middleName,
3434                            String lastName, String screenName, String emailAddress, int status,
3435                            LinkedHashMap<String, Object> params, boolean andSearch, int start,
3436                            int end, Sort sort)
3437                    throws PortalException {
3438    
3439                    return searchUsers(
3440                            companyId, firstName, middleName, lastName, screenName,
3441                            emailAddress, status, params, andSearch, start, end,
3442                            new Sort[] {sort});
3443            }
3444    
3445            @Override
3446            public BaseModelSearchResult<User> searchUsers(
3447                            long companyId, String firstName, String middleName,
3448                            String lastName, String screenName, String emailAddress, int status,
3449                            LinkedHashMap<String, Object> params, boolean andSearch, int start,
3450                            int end, Sort[] sorts)
3451                    throws PortalException {
3452    
3453                    SearchContext searchContext = buildSearchContext(
3454                            companyId, firstName, middleName, lastName, null, screenName,
3455                            emailAddress, null, null, null, null, null, status, params,
3456                            andSearch, start, end, sorts);
3457    
3458                    return searchUsers(searchContext);
3459            }
3460    
3461            /**
3462             * Sends an email address verification to the user.
3463             *
3464             * @param user the verification email recipient
3465             * @param emailAddress the recipient's email address
3466             * @param serviceContext the service context to be applied. Must set the
3467             *        portal URL, main path, primary key of the layout, remote address,
3468             *        remote host, and agent for the user.
3469             */
3470            @Override
3471            public void sendEmailAddressVerification(
3472                            User user, String emailAddress, ServiceContext serviceContext)
3473                    throws PortalException {
3474    
3475                    if (user.isEmailAddressVerified() &&
3476                            StringUtil.equalsIgnoreCase(emailAddress, user.getEmailAddress())) {
3477    
3478                            return;
3479                    }
3480    
3481                    Ticket ticket = ticketLocalService.addDistinctTicket(
3482                            user.getCompanyId(), User.class.getName(), user.getUserId(),
3483                            TicketConstants.TYPE_EMAIL_ADDRESS, emailAddress, null,
3484                            serviceContext);
3485    
3486                    String verifyEmailAddressURL =
3487                            serviceContext.getPortalURL() + serviceContext.getPathMain() +
3488                                    "/portal/verify_email_address?ticketKey=" + ticket.getKey();
3489    
3490                    long plid = serviceContext.getPlid();
3491    
3492                    if (plid > 0) {
3493                            Layout layout = layoutLocalService.fetchLayout(plid);
3494    
3495                            if (layout != null) {
3496                                    Group group = layout.getGroup();
3497    
3498                                    if (!layout.isPrivateLayout() && !group.isUser()) {
3499                                            verifyEmailAddressURL +=
3500                                                    "&p_l_id=" + serviceContext.getPlid();
3501                                    }
3502                            }
3503                    }
3504    
3505                    String fromName = PrefsPropsUtil.getString(
3506                            user.getCompanyId(), PropsKeys.ADMIN_EMAIL_FROM_NAME);
3507                    String fromAddress = PrefsPropsUtil.getString(
3508                            user.getCompanyId(), PropsKeys.ADMIN_EMAIL_FROM_ADDRESS);
3509    
3510                    String toName = user.getFullName();
3511                    String toAddress = emailAddress;
3512    
3513                    PortletPreferences companyPortletPreferences =
3514                            PrefsPropsUtil.getPreferences(user.getCompanyId(), true);
3515    
3516                    Map<Locale, String> localizedSubjectMap =
3517                            LocalizationUtil.getLocalizationMap(
3518                                    companyPortletPreferences, "adminEmailVerificationSubject",
3519                                    PropsKeys.ADMIN_EMAIL_VERIFICATION_SUBJECT);
3520                    Map<Locale, String> localizedBodyMap =
3521                            LocalizationUtil.getLocalizationMap(
3522                                    companyPortletPreferences, "adminEmailVerificationBody",
3523                                    PropsKeys.ADMIN_EMAIL_VERIFICATION_BODY);
3524    
3525                    SubscriptionSender subscriptionSender = new SubscriptionSender();
3526    
3527                    subscriptionSender.setCompanyId(user.getCompanyId());
3528                    subscriptionSender.setContextAttributes(
3529                            "[$EMAIL_VERIFICATION_CODE$]", ticket.getKey(),
3530                            "[$EMAIL_VERIFICATION_URL$]", verifyEmailAddressURL,
3531                            "[$REMOTE_ADDRESS$]", serviceContext.getRemoteAddr(),
3532                            "[$REMOTE_HOST$]", serviceContext.getRemoteHost(), "[$USER_ID$]",
3533                            user.getUserId(), "[$USER_SCREENNAME$]", user.getScreenName());
3534                    subscriptionSender.setFrom(fromAddress, fromName);
3535                    subscriptionSender.setHtmlFormat(true);
3536                    subscriptionSender.setLocalizedBodyMap(localizedBodyMap);
3537                    subscriptionSender.setLocalizedSubjectMap(localizedSubjectMap);
3538                    subscriptionSender.setMailId("user", user.getUserId());
3539                    subscriptionSender.setServiceContext(serviceContext);
3540    
3541                    subscriptionSender.addRuntimeSubscribers(toAddress, toName);
3542    
3543                    subscriptionSender.flushNotificationsAsync();
3544            }
3545    
3546            /**
3547             * Sends the password email to the user with the email address. The content
3548             * of this email can be specified in <code>portal.properties</code> with the
3549             * <code>admin.email.password</code> keys.
3550             *
3551             * @param companyId the primary key of the user's company
3552             * @param emailAddress the user's email address
3553             * @param fromName the name of the individual that the email should be from
3554             * @param fromAddress the address of the individual that the email should be
3555             *        from
3556             * @param subject the email subject. If <code>null</code>, the subject
3557             *        specified in <code>portal.properties</code> will be used.
3558             * @param body the email body. If <code>null</code>, the body specified in
3559             *        <code>portal.properties</code> will be used.
3560             * @param serviceContext the service context to be applied
3561             */
3562            @Override
3563            public boolean sendPassword(
3564                            long companyId, String emailAddress, String fromName,
3565                            String fromAddress, String subject, String body,
3566                            ServiceContext serviceContext)
3567                    throws PortalException {
3568    
3569                    Company company = companyPersistence.findByPrimaryKey(companyId);
3570    
3571                    if (!company.isSendPassword() && !company.isSendPasswordResetLink()) {
3572                            throw new SendPasswordException.MustBeEnabled(company);
3573                    }
3574    
3575                    emailAddress = StringUtil.toLowerCase(emailAddress.trim());
3576    
3577                    if (Validator.isNull(emailAddress)) {
3578                            throw new UserEmailAddressException.MustNotBeNull();
3579                    }
3580    
3581                    User user = userPersistence.findByC_EA(companyId, emailAddress);
3582    
3583                    PasswordPolicy passwordPolicy = user.getPasswordPolicy();
3584    
3585                    String newPassword = StringPool.BLANK;
3586                    String passwordResetURL = StringPool.BLANK;
3587    
3588                    if (company.isSendPasswordResetLink()) {
3589                            Date expirationDate = null;
3590    
3591                            if ((passwordPolicy != null) &&
3592                                    (passwordPolicy.getResetTicketMaxAge() > 0)) {
3593    
3594                                    expirationDate = new Date(
3595                                            System.currentTimeMillis() +
3596                                                    (passwordPolicy.getResetTicketMaxAge() * 1000));
3597                            }
3598    
3599                            Ticket ticket = ticketLocalService.addDistinctTicket(
3600                                    companyId, User.class.getName(), user.getUserId(),
3601                                    TicketConstants.TYPE_PASSWORD, null, expirationDate,
3602                                    serviceContext);
3603    
3604                            passwordResetURL =
3605                                    serviceContext.getPortalURL() + serviceContext.getPathMain() +
3606                                            "/portal/update_password?p_l_id="+
3607                                                    serviceContext.getPlid() +
3608                                                            "&ticketKey=" + ticket.getKey();
3609                    }
3610                    else {
3611                            if (!Validator.equals(
3612                                            PasswordEncryptorUtil.getDefaultPasswordAlgorithmType(),
3613                                            PasswordEncryptorUtil.TYPE_NONE)) {
3614    
3615                                    if (LDAPSettingsUtil.isPasswordPolicyEnabled(
3616                                                    user.getCompanyId())) {
3617    
3618                                            if (_log.isWarnEnabled()) {
3619                                                    StringBundler sb = new StringBundler(5);
3620    
3621                                                    sb.append("When LDAP password policy is enabled, ");
3622                                                    sb.append("it is possible that portal generated ");
3623                                                    sb.append("passwords will not match the LDAP policy.");
3624                                                    sb.append("Using RegExpToolkit to generate new ");
3625                                                    sb.append("password.");
3626    
3627                                                    _log.warn(sb.toString());
3628                                            }
3629    
3630                                            RegExpToolkit regExpToolkit = new RegExpToolkit();
3631    
3632                                            newPassword = regExpToolkit.generate(null);
3633                                    }
3634                                    else {
3635                                            newPassword = PwdToolkitUtil.generate(passwordPolicy);
3636                                    }
3637    
3638                                    boolean passwordReset = false;
3639    
3640                                    if (passwordPolicy.getChangeable() &&
3641                                            passwordPolicy.getChangeRequired()) {
3642    
3643                                            passwordReset = true;
3644                                    }
3645    
3646                                    user.setPassword(PasswordEncryptorUtil.encrypt(newPassword));
3647                                    user.setPasswordUnencrypted(newPassword);
3648                                    user.setPasswordEncrypted(true);
3649                                    user.setPasswordReset(passwordReset);
3650                                    user.setPasswordModified(true);
3651                                    user.setPasswordModifiedDate(new Date());
3652    
3653                                    userPersistence.update(user);
3654    
3655                                    user.setPasswordModified(false);
3656                            }
3657                            else {
3658                                    newPassword = user.getPassword();
3659                            }
3660                    }
3661    
3662                    sendPasswordNotification(
3663                            user, companyId, newPassword, passwordResetURL, fromName,
3664                            fromAddress, subject, body, serviceContext);
3665    
3666                    return company.isSendPassword();
3667            }
3668    
3669            /**
3670             * Sends a password notification email to the user matching the email
3671             * address. The portal's settings determine whether a password is sent
3672             * explicitly or whether a link for resetting the user's password is sent.
3673             * The method sends the email asynchronously and returns before the email is
3674             * sent.
3675             *
3676             * <p>
3677             * The content of the notification email is specified with the
3678             * <code>admin.email.password</code> portal property keys. They can be
3679             * overridden via a <code>portal-ext.properties</code> file or modified
3680             * through the Portal Settings UI.
3681             * </p>
3682             *
3683             * @param  companyId the primary key of the user's company
3684             * @param  emailAddress the user's email address
3685             * @return <code>true</code> if the notification email includes a new
3686             *         password; <code>false</code> if the notification email only
3687             *         contains a reset link
3688             */
3689            @Override
3690            public boolean sendPasswordByEmailAddress(
3691                            long companyId, String emailAddress)
3692                    throws PortalException {
3693    
3694                    User user = userPersistence.findByC_EA(companyId, emailAddress);
3695    
3696                    return sendPassword(
3697                            user.getCompanyId(), user.getEmailAddress(), null, null, null, null,
3698                            ServiceContextThreadLocal.getServiceContext());
3699            }
3700    
3701            /**
3702             * Sends a password notification email to the user matching the screen name.
3703             * The portal's settings determine whether a password is sent explicitly or
3704             * whether a link for resetting the user's password is sent. The method
3705             * sends the email asynchronously and returns before the email is sent.
3706             *
3707             * <p>
3708             * The content of the notification email is specified with the
3709             * <code>admin.email.password</code> portal property keys. They can be
3710             * overridden via a <code>portal-ext.properties</code> file or modified
3711             * through the Portal Settings UI.
3712             * </p>
3713             *
3714             * @param  companyId the primary key of the user's company
3715             * @param  screenName the user's screen name
3716             * @return <code>true</code> if the notification email includes a new
3717             *         password; <code>false</code> if the notification email only
3718             *         contains a reset link
3719             */
3720            @Override
3721            public boolean sendPasswordByScreenName(long companyId, String screenName)
3722                    throws PortalException {
3723    
3724                    User user = userPersistence.findByC_SN(companyId, screenName);
3725    
3726                    return sendPassword(
3727                            user.getCompanyId(), user.getEmailAddress(), null, null, null, null,
3728                            ServiceContextThreadLocal.getServiceContext());
3729            }
3730    
3731            /**
3732             * Sends a password notification email to the user matching the ID. The
3733             * portal's settings determine whether a password is sent explicitly or
3734             * whether a link for resetting the user's password is sent. The method
3735             * sends the email asynchronously and returns before the email is sent.
3736             *
3737             * <p>
3738             * The content of the notification email is specified with the
3739             * <code>admin.email.password</code> portal property keys. They can be
3740             * overridden via a <code>portal-ext.properties</code> file or modified
3741             * through the Portal Settings UI.
3742             * </p>
3743             *
3744             * @param  userId the user's primary key
3745             * @return <code>true</code> if the notification email includes a new
3746             *         password; <code>false</code> if the notification email only
3747             *         contains a reset link
3748             */
3749            @Override
3750            public boolean sendPasswordByUserId(long userId) throws PortalException {
3751                    User user = userPersistence.findByPrimaryKey(userId);
3752    
3753                    return sendPassword(
3754                            user.getCompanyId(), user.getEmailAddress(), null, null, null, null,
3755                            ServiceContextThreadLocal.getServiceContext());
3756            }
3757    
3758            /**
3759             * Sets the users in the role, removing and adding users to the role as
3760             * necessary.
3761             *
3762             * @param roleId the primary key of the role
3763             * @param userIds the primary keys of the users
3764             */
3765            @Override
3766            public void setRoleUsers(long roleId, long[] userIds)
3767                    throws PortalException {
3768    
3769                    long[] oldUserIds = rolePersistence.getUserPrimaryKeys(roleId);
3770    
3771                    Set<Long> updatedUserIdsSet = SetUtil.symmetricDifference(
3772                            userIds, oldUserIds);
3773    
3774                    long[] updateUserIds = ArrayUtil.toLongArray(updatedUserIdsSet);
3775    
3776                    rolePersistence.setUsers(roleId, userIds);
3777    
3778                    reindex(updateUserIds);
3779    
3780                    PermissionCacheUtil.clearCache(updateUserIds);
3781            }
3782    
3783            /**
3784             * Sets the users in the user group, removing and adding users to the user
3785             * group as necessary.
3786             *
3787             * @param userGroupId the primary key of the user group
3788             * @param userIds the primary keys of the users
3789             */
3790            @Override
3791            @SuppressWarnings("deprecation")
3792            public void setUserGroupUsers(long userGroupId, long[] userIds)
3793                    throws PortalException {
3794    
3795                    if (PropsValues.USER_GROUPS_COPY_LAYOUTS_TO_USER_PERSONAL_SITE) {
3796                            userGroupLocalService.copyUserGroupLayouts(userGroupId, userIds);
3797                    }
3798    
3799                    long[] oldUserIds = userGroupPersistence.getUserPrimaryKeys(
3800                            userGroupId);
3801    
3802                    Set<Long> updatedUserIdsSet = SetUtil.symmetricDifference(
3803                            userIds, oldUserIds);
3804    
3805                    long[] updateUserIds = ArrayUtil.toLongArray(updatedUserIdsSet);
3806    
3807                    userGroupPersistence.setUsers(userGroupId, userIds);
3808    
3809                    reindex(updateUserIds);
3810    
3811                    PermissionCacheUtil.clearCache(updateUserIds);
3812            }
3813    
3814            /**
3815             * Removes the users from the teams of a group.
3816             *
3817             * @param groupId the primary key of the group
3818             * @param userIds the primary keys of the users
3819             */
3820            @Override
3821            public void unsetGroupTeamsUsers(long groupId, long[] userIds)
3822                    throws PortalException {
3823    
3824                    List<Team> teams = teamPersistence.findByGroupId(groupId);
3825    
3826                    for (Team team : teams) {
3827                            unsetTeamUsers(team.getTeamId(), userIds);
3828                    }
3829    
3830                    PermissionCacheUtil.clearCache(userIds);
3831            }
3832    
3833            /**
3834             * Removes the users from the group.
3835             *
3836             * @param groupId the primary key of the group
3837             * @param userIds the primary keys of the users
3838             * @param serviceContext the service context to be applied (optionally
3839             *        <code>null</code>)
3840             */
3841            @Override
3842            public void unsetGroupUsers(
3843                            final long groupId, final long[] userIds,
3844                            ServiceContext serviceContext)
3845                    throws PortalException {
3846    
3847                    userGroupRoleLocalService.deleteUserGroupRoles(
3848                            userIds, groupId, RoleConstants.TYPE_SITE);
3849    
3850                    unsetGroupTeamsUsers(groupId, userIds);
3851    
3852                    groupPersistence.removeUsers(groupId, userIds);
3853    
3854                    reindex(userIds);
3855    
3856                    PermissionCacheUtil.clearCache(userIds);
3857    
3858                    Callable<Void> callable = new Callable<Void>() {
3859    
3860                            @Override
3861                            public Void call() throws Exception {
3862                                    Message message = new Message();
3863    
3864                                    message.put("groupId", groupId);
3865                                    message.put("userIds", userIds);
3866    
3867                                    MessageBusUtil.sendMessage(
3868                                            DestinationNames.SUBSCRIPTION_CLEAN_UP, message);
3869    
3870                                    return null;
3871                            }
3872    
3873                    };
3874    
3875                    TransactionCommitCallbackUtil.registerCallback(callable);
3876            }
3877    
3878            /**
3879             * Removes the users from the organization.
3880             *
3881             * @param organizationId the primary key of the organization
3882             * @param userIds the primary keys of the users
3883             */
3884            @Override
3885            public void unsetOrganizationUsers(
3886                            long organizationId, final long[] userIds)
3887                    throws PortalException {
3888    
3889                    Organization organization = organizationPersistence.findByPrimaryKey(
3890                            organizationId);
3891    
3892                    final Group group = organization.getGroup();
3893    
3894                    userGroupRoleLocalService.deleteUserGroupRoles(
3895                            userIds, group.getGroupId());
3896    
3897                    organizationPersistence.removeUsers(organizationId, userIds);
3898    
3899                    reindex(userIds);
3900    
3901                    PermissionCacheUtil.clearCache(userIds);
3902    
3903                    Callable<Void> callable = new Callable<Void>() {
3904    
3905                            @Override
3906                            public Void call() throws Exception {
3907                                    Message message = new Message();
3908    
3909                                    message.put("groupId", group.getGroupId());
3910                                    message.put("userIds", userIds);
3911    
3912                                    MessageBusUtil.sendMessage(
3913                                            DestinationNames.SUBSCRIPTION_CLEAN_UP, message);
3914    
3915                                    return null;
3916                            }
3917    
3918                    };
3919    
3920                    TransactionCommitCallbackUtil.registerCallback(callable);
3921            }
3922    
3923            /**
3924             * Removes the users from the password policy.
3925             *
3926             * @param passwordPolicyId the primary key of the password policy
3927             * @param userIds the primary keys of the users
3928             */
3929            @Override
3930            public void unsetPasswordPolicyUsers(
3931                    long passwordPolicyId, long[] userIds) {
3932    
3933                    passwordPolicyRelLocalService.deletePasswordPolicyRels(
3934                            passwordPolicyId, User.class.getName(), userIds);
3935            }
3936    
3937            /**
3938             * Removes the users from the role.
3939             *
3940             * @param roleId the primary key of the role
3941             * @param users the users
3942             */
3943            @Override
3944            public void unsetRoleUsers(long roleId, List<User> users)
3945                    throws PortalException {
3946    
3947                    Role role = rolePersistence.findByPrimaryKey(roleId);
3948    
3949                    String roleName = role.getName();
3950    
3951                    if ((roleName.equals(RoleConstants.ADMINISTRATOR) &&
3952                             (getRoleUsersCount(role.getRoleId()) <= 1)) ||
3953                            roleName.equals(RoleConstants.USER)) {
3954    
3955                            return;
3956                    }
3957    
3958                    rolePersistence.removeUsers(roleId, users);
3959    
3960                    Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
3961                            User.class);
3962    
3963                    indexer.reindex(users);
3964    
3965                    long[] userIds = new long[users.size()];
3966    
3967                    for (int i = 0; i < users.size(); i++) {
3968                            User user = users.get(i);
3969    
3970                            userIds[i] = user.getUserId();
3971                    }
3972    
3973                    PermissionCacheUtil.clearCache(userIds);
3974            }
3975    
3976            /**
3977             * Removes the users from the role.
3978             *
3979             * @param roleId the primary key of the role
3980             * @param userIds the primary keys of the users
3981             */
3982            @Override
3983            public void unsetRoleUsers(long roleId, long[] userIds)
3984                    throws PortalException {
3985    
3986                    Role role = rolePersistence.findByPrimaryKey(roleId);
3987    
3988                    String roleName = role.getName();
3989    
3990                    if (roleName.equals(RoleConstants.USER) ||
3991                            (roleName.equals(RoleConstants.ADMINISTRATOR) &&
3992                             getRoleUsersCount(role.getRoleId()) <= 1)) {
3993    
3994                            return;
3995                    }
3996    
3997                    rolePersistence.removeUsers(roleId, userIds);
3998    
3999                    reindex(userIds);
4000    
4001                    PermissionCacheUtil.clearCache(userIds);
4002            }
4003    
4004            /**
4005             * Removes the users from the team.
4006             *
4007             * @param teamId the primary key of the team
4008             * @param userIds the primary keys of the users
4009             */
4010            @Override
4011            public void unsetTeamUsers(long teamId, long[] userIds)
4012                    throws PortalException {
4013    
4014                    teamPersistence.removeUsers(teamId, userIds);
4015    
4016                    reindex(userIds);
4017    
4018                    PermissionCacheUtil.clearCache(userIds);
4019            }
4020    
4021            /**
4022             * Removes the users from the user group.
4023             *
4024             * @param userGroupId the primary key of the user group
4025             * @param userIds the primary keys of the users
4026             */
4027            @Override
4028            public void unsetUserGroupUsers(long userGroupId, long[] userIds)
4029                    throws PortalException {
4030    
4031                    userGroupPersistence.removeUsers(userGroupId, userIds);
4032    
4033                    reindex(userIds);
4034    
4035                    PermissionCacheUtil.clearCache(userIds);
4036            }
4037    
4038            /**
4039             * Updates whether the user has agreed to the terms of use.
4040             *
4041             * @param  userId the primary key of the user
4042             * @param  agreedToTermsOfUse whether the user has agreet to the terms of
4043             *         use
4044             * @return the user
4045             */
4046            @Override
4047            public User updateAgreedToTermsOfUse(
4048                            long userId, boolean agreedToTermsOfUse)
4049                    throws PortalException {
4050    
4051                    User user = userPersistence.findByPrimaryKey(userId);
4052    
4053                    user.setAgreedToTermsOfUse(agreedToTermsOfUse);
4054    
4055                    userPersistence.update(user);
4056    
4057                    return user;
4058            }
4059    
4060            /**
4061             * Updates the user's asset with the new asset categories and tag names,
4062             * removing and adding asset categories and tag names as necessary.
4063             *
4064             * @param userId the primary key of the user
4065             * @param user ID the primary key of the user
4066             * @param assetCategoryIds the primary key's of the new asset categories
4067             * @param assetTagNames the new asset tag names
4068             */
4069            @Override
4070            public void updateAsset(
4071                            long userId, User user, long[] assetCategoryIds,
4072                            String[] assetTagNames)
4073                    throws PortalException {
4074    
4075                    User owner = userPersistence.findByPrimaryKey(userId);
4076    
4077                    Company company = companyPersistence.findByPrimaryKey(
4078                            owner.getCompanyId());
4079    
4080                    Group companyGroup = company.getGroup();
4081    
4082                    assetEntryLocalService.updateEntry(
4083                            userId, companyGroup.getGroupId(), user.getCreateDate(),
4084                            user.getModifiedDate(), User.class.getName(), user.getUserId(),
4085                            user.getUuid(), 0, assetCategoryIds, assetTagNames, false, null,
4086                            null, null, null, user.getFullName(), null, null, null, null, 0, 0,
4087                            null);
4088            }
4089    
4090            /**
4091             * Updates the user's creation date.
4092             *
4093             * @param  userId the primary key of the user
4094             * @param  createDate the new creation date
4095             * @return the user
4096             */
4097            @Override
4098            public User updateCreateDate(long userId, Date createDate)
4099                    throws PortalException {
4100    
4101                    User user = userPersistence.findByPrimaryKey(userId);
4102    
4103                    user.setCreateDate(createDate);
4104    
4105                    userPersistence.update(user);
4106    
4107                    return user;
4108            }
4109    
4110            /**
4111             * Updates the user's email address.
4112             *
4113             * @param  userId the primary key of the user
4114             * @param  password the user's password
4115             * @param  emailAddress1 the user's new email address
4116             * @param  emailAddress2 the user's new email address confirmation
4117             * @return the user
4118             */
4119            @Override
4120            public User updateEmailAddress(
4121                            long userId, String password, String emailAddress1,
4122                            String emailAddress2)
4123                    throws PortalException {
4124    
4125                    emailAddress1 = StringUtil.toLowerCase(emailAddress1.trim());
4126                    emailAddress2 = StringUtil.toLowerCase(emailAddress2.trim());
4127    
4128                    User user = userPersistence.findByPrimaryKey(userId);
4129    
4130                    validateEmailAddress(user, emailAddress1, emailAddress2);
4131    
4132                    setEmailAddress(
4133                            user, password, user.getFirstName(), user.getMiddleName(),
4134                            user.getLastName(), emailAddress1);
4135    
4136                    userPersistence.update(user);
4137    
4138                    Contact contact = user.getContact();
4139    
4140                    contact.setEmailAddress(user.getEmailAddress());
4141    
4142                    contactPersistence.update(contact);
4143    
4144                    return user;
4145            }
4146    
4147            /**
4148             * Updates the user's email address or sends verification email.
4149             *
4150             * @param  userId the primary key of the user
4151             * @param  password the user's password
4152             * @param  emailAddress1 the user's new email address
4153             * @param  emailAddress2 the user's new email address confirmation
4154             * @param  serviceContext the service context to be applied. Must set the
4155             *         portal URL, main path, primary key of the layout, remote address,
4156             *         remote host, and agent for the user.
4157             * @return the user
4158             */
4159            @Override
4160            public User updateEmailAddress(
4161                            long userId, String password, String emailAddress1,
4162                            String emailAddress2, ServiceContext serviceContext)
4163                    throws PortalException {
4164    
4165                    emailAddress1 = StringUtil.toLowerCase(emailAddress1.trim());
4166                    emailAddress2 = StringUtil.toLowerCase(emailAddress2.trim());
4167    
4168                    User user = userPersistence.findByPrimaryKey(userId);
4169    
4170                    validateEmailAddress(user, emailAddress1, emailAddress2);
4171    
4172                    Company company = companyPersistence.findByPrimaryKey(
4173                            user.getCompanyId());
4174    
4175                    if (company.isStrangersVerify() &&
4176                            !StringUtil.equalsIgnoreCase(
4177                                    emailAddress1, user.getEmailAddress())) {
4178    
4179                            sendEmailAddressVerification(user, emailAddress1, serviceContext);
4180                    }
4181                    else {
4182                            setEmailAddress(
4183                                    user, password, user.getFirstName(), user.getMiddleName(),
4184                                    user.getLastName(), emailAddress1);
4185    
4186                            userPersistence.update(user);
4187    
4188                            Contact contact = user.getContact();
4189    
4190                            contact.setEmailAddress(user.getEmailAddress());
4191    
4192                            contactPersistence.update(contact);
4193                    }
4194    
4195                    return user;
4196            }
4197    
4198            /**
4199             * Updates whether the user has verified email address.
4200             *
4201             * @param  userId the primary key of the user
4202             * @param  emailAddressVerified whether the user has verified email address
4203             * @return the user
4204             */
4205            @Override
4206            public User updateEmailAddressVerified(
4207                            long userId, boolean emailAddressVerified)
4208                    throws PortalException {
4209    
4210                    User user = userPersistence.findByPrimaryKey(userId);
4211    
4212                    user.setEmailAddressVerified(emailAddressVerified);
4213    
4214                    userPersistence.update(user);
4215    
4216                    return user;
4217            }
4218    
4219            /**
4220             * Updates the user's Facebook ID.
4221             *
4222             * @param  userId the primary key of the user
4223             * @param  facebookId the user's new Facebook ID
4224             * @return the user
4225             */
4226            @Override
4227            public User updateFacebookId(long userId, long facebookId)
4228                    throws PortalException {
4229    
4230                    User user = userPersistence.findByPrimaryKey(userId);
4231    
4232                    user.setFacebookId(facebookId);
4233    
4234                    userPersistence.update(user);
4235    
4236                    return user;
4237            }
4238    
4239            /**
4240             * Sets the groups the user is in, removing and adding groups as necessary.
4241             *
4242             * @param userId the primary key of the user
4243             * @param newGroupIds the primary keys of the groups
4244             * @param serviceContext the service context to be applied (optionally
4245             *        <code>null</code>)
4246             */
4247            @Override
4248            public void updateGroups(
4249                            long userId, long[] newGroupIds, ServiceContext serviceContext)
4250                    throws PortalException {
4251    
4252                    boolean indexingEnabled = true;
4253    
4254                    if (serviceContext != null) {
4255                            indexingEnabled = serviceContext.isIndexingEnabled();
4256                    }
4257    
4258                    updateGroups(userId, newGroupIds, serviceContext, indexingEnabled);
4259            }
4260    
4261            /**
4262             * Updates a user account that was automatically created when a guest user
4263             * participated in an action (e.g. posting a comment) and only provided his
4264             * name and email address.
4265             *
4266             * @param  creatorUserId the primary key of the creator
4267             * @param  companyId the primary key of the user's company
4268             * @param  autoPassword whether a password should be automatically generated
4269             *         for the user
4270             * @param  password1 the user's password
4271             * @param  password2 the user's password confirmation
4272             * @param  autoScreenName whether a screen name should be automatically
4273             *         generated for the user
4274             * @param  screenName the user's screen name
4275             * @param  emailAddress the user's email address
4276             * @param  facebookId the user's facebook ID
4277             * @param  openId the user's OpenID
4278             * @param  locale the user's locale
4279             * @param  firstName the user's first name
4280             * @param  middleName the user's middle name
4281             * @param  lastName the user's last name
4282             * @param  prefixId the user's name prefix ID
4283             * @param  suffixId the user's name suffix ID
4284             * @param  male whether the user is male
4285             * @param  birthdayMonth the user's birthday month (0-based, meaning 0 for
4286             *         January)
4287             * @param  birthdayDay the user's birthday day
4288             * @param  birthdayYear the user's birthday year
4289             * @param  jobTitle the user's job title
4290             * @param  updateUserInformation whether to update the user's information
4291             * @param  sendEmail whether to send the user an email notification about
4292             *         their new account
4293             * @param  serviceContext the service context to be applied (optionally
4294             *         <code>null</code>). Can set expando bridge attributes for the
4295             *         user.
4296             * @return the user
4297             */
4298            @Override
4299            public User updateIncompleteUser(
4300                            long creatorUserId, long companyId, boolean autoPassword,
4301                            String password1, String password2, boolean autoScreenName,
4302                            String screenName, String emailAddress, long facebookId,
4303                            String openId, Locale locale, String firstName, String middleName,
4304                            String lastName, long prefixId, long suffixId, boolean male,
4305                            int birthdayMonth, int birthdayDay, int birthdayYear,
4306                            String jobTitle, boolean updateUserInformation, boolean sendEmail,
4307                            ServiceContext serviceContext)
4308                    throws PortalException {
4309    
4310                    User user = getUserByEmailAddress(companyId, emailAddress);
4311    
4312                    if (user.getStatus() != WorkflowConstants.STATUS_INCOMPLETE) {
4313                            throw new PortalException("Invalid user status");
4314                    }
4315    
4316                    User defaultUser = getDefaultUser(companyId);
4317    
4318                    if (facebookId > 0) {
4319                            autoPassword = false;
4320    
4321                            if ((password1 == null) || (password2 == null)) {
4322                                    password1 = PwdGenerator.getPassword();
4323                                    password2 = password1;
4324                            }
4325    
4326                            sendEmail = false;
4327                    }
4328    
4329                    if (updateUserInformation) {
4330                            autoScreenName = false;
4331    
4332                            if (PrefsPropsUtil.getBoolean(
4333                                            companyId,
4334                                            PropsKeys.USERS_SCREEN_NAME_ALWAYS_AUTOGENERATE)) {
4335    
4336                                    autoScreenName = true;
4337                            }
4338    
4339                            validate(
4340                                    companyId, user.getUserId(), autoPassword, password1, password2,
4341                                    autoScreenName, screenName, emailAddress, openId, firstName,
4342                                    middleName, lastName, null, locale);
4343    
4344                            if (!autoPassword) {
4345                                    if (Validator.isNull(password1) ||
4346                                            Validator.isNull(password2)) {
4347    
4348                                            throw new UserPasswordException.MustNotBeNull(
4349                                                    user.getUserId());
4350                                    }
4351                            }
4352    
4353                            if (autoScreenName) {
4354                                    ScreenNameGenerator screenNameGenerator =
4355                                            ScreenNameGeneratorFactory.getInstance();
4356    
4357                                    try {
4358                                            screenName = screenNameGenerator.generate(
4359                                                    companyId, user.getUserId(), emailAddress);
4360                                    }
4361                                    catch (Exception e) {
4362                                            throw new SystemException(e);
4363                                    }
4364                            }
4365    
4366                            FullNameGenerator fullNameGenerator =
4367                                    FullNameGeneratorFactory.getInstance();
4368    
4369                            String fullName = fullNameGenerator.getFullName(
4370                                    firstName, middleName, lastName);
4371    
4372                            String greeting = LanguageUtil.format(
4373                                    locale, "welcome-x", fullName, false);
4374    
4375                            if (Validator.isNotNull(password1)) {
4376                                    user.setPassword(PasswordEncryptorUtil.encrypt(password1));
4377                                    user.setPasswordUnencrypted(password1);
4378                            }
4379    
4380                            user.setPasswordEncrypted(true);
4381    
4382                            PasswordPolicy passwordPolicy = defaultUser.getPasswordPolicy();
4383    
4384                            if ((passwordPolicy != null) && passwordPolicy.isChangeable() &&
4385                                    passwordPolicy.isChangeRequired()) {
4386    
4387                                    user.setPasswordReset(true);
4388                            }
4389                            else {
4390                                    user.setPasswordReset(false);
4391                            }
4392    
4393                            user.setScreenName(screenName);
4394                            user.setFacebookId(facebookId);
4395                            user.setOpenId(openId);
4396                            user.setLanguageId(locale.toString());
4397                            user.setTimeZoneId(defaultUser.getTimeZoneId());
4398                            user.setGreeting(greeting);
4399                            user.setFirstName(firstName);
4400                            user.setMiddleName(middleName);
4401                            user.setLastName(lastName);
4402                            user.setJobTitle(jobTitle);
4403                            user.setExpandoBridgeAttributes(serviceContext);
4404    
4405                            Date birthday = getBirthday(
4406                                    birthdayMonth, birthdayDay, birthdayYear);
4407    
4408                            Contact contact = user.getContact();
4409    
4410                            contact.setFirstName(firstName);
4411                            contact.setMiddleName(middleName);
4412                            contact.setLastName(lastName);
4413                            contact.setPrefixId(prefixId);
4414                            contact.setSuffixId(suffixId);
4415                            contact.setMale(male);
4416                            contact.setBirthday(birthday);
4417                            contact.setJobTitle(jobTitle);
4418    
4419                            contactPersistence.update(contact, serviceContext);
4420    
4421                            // Indexer
4422    
4423                            Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
4424                                    User.class);
4425    
4426                            indexer.reindex(user);
4427                    }
4428    
4429                    user.setStatus(WorkflowConstants.STATUS_DRAFT);
4430    
4431                    userPersistence.update(user, serviceContext);
4432    
4433                    // Workflow
4434    
4435                    long workflowUserId = creatorUserId;
4436    
4437                    if (workflowUserId == user.getUserId()) {
4438                            workflowUserId = defaultUser.getUserId();
4439                    }
4440    
4441                    ServiceContext workflowServiceContext = serviceContext;
4442    
4443                    if (workflowServiceContext == null) {
4444                            workflowServiceContext = new ServiceContext();
4445                    }
4446    
4447                    workflowServiceContext.setAttribute("autoPassword", autoPassword);
4448                    workflowServiceContext.setAttribute("passwordUnencrypted", password1);
4449                    workflowServiceContext.setAttribute("sendEmail", sendEmail);
4450    
4451                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
4452                            companyId, workflowUserId, User.class.getName(), user.getUserId(),
4453                            user, workflowServiceContext);
4454    
4455                    return getUserByEmailAddress(companyId, emailAddress);
4456            }
4457    
4458            /**
4459             * Updates the user's job title.
4460             *
4461             * @param  userId the primary key of the user
4462             * @param  jobTitle the user's job title
4463             * @return the user
4464             */
4465            @Override
4466            public User updateJobTitle(long userId, String jobTitle)
4467                    throws PortalException {
4468    
4469                    User user = userPersistence.findByPrimaryKey(userId);
4470    
4471                    user.setJobTitle(jobTitle);
4472    
4473                    userPersistence.update(user);
4474    
4475                    Contact contact = contactPersistence.findByPrimaryKey(
4476                            user.getContactId());
4477    
4478                    contact.setJobTitle(jobTitle);
4479    
4480                    contactPersistence.update(contact);
4481    
4482                    return user;
4483            }
4484    
4485            /**
4486             * Updates the user's last login with the current time and the IP address.
4487             *
4488             * @param  userId the primary key of the user
4489             * @param  loginIP the IP address the user logged in from
4490             * @return the user
4491             */
4492            @Override
4493            public User updateLastLogin(long userId, String loginIP)
4494                    throws PortalException {
4495    
4496                    User user = userPersistence.findByPrimaryKey(userId);
4497    
4498                    Date lastLoginDate = user.getLoginDate();
4499    
4500                    if (lastLoginDate == null) {
4501                            lastLoginDate = new Date();
4502                    }
4503    
4504                    String lastLoginIP = user.getLoginIP();
4505    
4506                    if (lastLoginIP == null) {
4507                            lastLoginIP = loginIP;
4508                    }
4509    
4510                    user.setLoginDate(new Date());
4511                    user.setLoginIP(loginIP);
4512                    user.setLastLoginDate(lastLoginDate);
4513                    user.setLastLoginIP(lastLoginIP);
4514    
4515                    resetFailedLoginAttempts(user, true);
4516    
4517                    return user;
4518            }
4519    
4520            /**
4521             * Updates whether the user is locked out from logging in.
4522             *
4523             * @param  user the user
4524             * @param  lockout whether the user is locked out
4525             * @return the user
4526             */
4527            @Override
4528            public User updateLockout(User user, boolean lockout)
4529                    throws PortalException {
4530    
4531                    PasswordPolicy passwordPolicy = user.getPasswordPolicy();
4532    
4533                    if ((passwordPolicy == null) || !passwordPolicy.isLockout()) {
4534                            return user;
4535                    }
4536    
4537                    Date lockoutDate = null;
4538    
4539                    if (lockout) {
4540                            lockoutDate = new Date();
4541                    }
4542    
4543                    user.setLockout(lockout);
4544                    user.setLockoutDate(lockoutDate);
4545    
4546                    if (!lockout) {
4547                            user.setFailedLoginAttempts(0);
4548                    }
4549    
4550                    userPersistence.update(user);
4551    
4552                    return user;
4553            }
4554    
4555            /**
4556             * Updates whether the user is locked out from logging in.
4557             *
4558             * @param  companyId the primary key of the user's company
4559             * @param  emailAddress the user's email address
4560             * @param  lockout whether the user is locked out
4561             * @return the user
4562             */
4563            @Override
4564            public User updateLockoutByEmailAddress(
4565                            long companyId, String emailAddress, boolean lockout)
4566                    throws PortalException {
4567    
4568                    User user = getUserByEmailAddress(companyId, emailAddress);
4569    
4570                    return updateLockout(user, lockout);
4571            }
4572    
4573            /**
4574             * Updates whether the user is locked out from logging in.
4575             *
4576             * @param  userId the primary key of the user
4577             * @param  lockout whether the user is locked out
4578             * @return the user
4579             */
4580            @Override
4581            public User updateLockoutById(long userId, boolean lockout)
4582                    throws PortalException {
4583    
4584                    User user = userPersistence.findByPrimaryKey(userId);
4585    
4586                    return updateLockout(user, lockout);
4587            }
4588    
4589            /**
4590             * Updates whether the user is locked out from logging in.
4591             *
4592             * @param  companyId the primary key of the user's company
4593             * @param  screenName the user's screen name
4594             * @param  lockout whether the user is locked out
4595             * @return the user
4596             */
4597            @Override
4598            public User updateLockoutByScreenName(
4599                            long companyId, String screenName, boolean lockout)
4600                    throws PortalException {
4601    
4602                    User user = getUserByScreenName(companyId, screenName);
4603    
4604                    return updateLockout(user, lockout);
4605            }
4606    
4607            /**
4608             * Updates the user's modified date.
4609             *
4610             * @param  userId the primary key of the user
4611             * @param  modifiedDate the new modified date
4612             * @return the user
4613             */
4614            @Override
4615            public User updateModifiedDate(long userId, Date modifiedDate)
4616                    throws PortalException {
4617    
4618                    User user = userPersistence.findByPrimaryKey(userId);
4619    
4620                    userPersistence.update(user);
4621    
4622                    return user;
4623            }
4624    
4625            /**
4626             * Updates the user's OpenID.
4627             *
4628             * @param  userId the primary key of the user
4629             * @param  openId the new OpenID
4630             * @return the user
4631             */
4632            @Override
4633            public User updateOpenId(long userId, String openId)
4634                    throws PortalException {
4635    
4636                    openId = openId.trim();
4637    
4638                    User user = userPersistence.findByPrimaryKey(userId);
4639    
4640                    user.setOpenId(openId);
4641    
4642                    userPersistence.update(user);
4643    
4644                    return user;
4645            }
4646    
4647            /**
4648             * Sets the organizations that the user is in, removing and adding
4649             * organizations as necessary.
4650             *
4651             * @param userId the primary key of the user
4652             * @param newOrganizationIds the primary keys of the organizations
4653             * @param serviceContext the service context to be applied. Must set whether
4654             *        user indexing is enabled.
4655             */
4656            @Override
4657            public void updateOrganizations(
4658                            long userId, long[] newOrganizationIds,
4659                            ServiceContext serviceContext)
4660                    throws PortalException {
4661    
4662                    updateOrganizations(
4663                            userId, newOrganizationIds, serviceContext.isIndexingEnabled());
4664            }
4665    
4666            /**
4667             * Updates the user's password without tracking or validation of the change.
4668             *
4669             * @param  userId the primary key of the user
4670             * @param  password1 the user's new password
4671             * @param  password2 the user's new password confirmation
4672             * @param  passwordReset whether the user should be asked to reset their
4673             *         password the next time they log in
4674             * @return the user
4675             */
4676            @Override
4677            public User updatePassword(
4678                            long userId, String password1, String password2,
4679                            boolean passwordReset)
4680                    throws PortalException {
4681    
4682                    return updatePassword(
4683                            userId, password1, password2, passwordReset, false);
4684            }
4685    
4686            /**
4687             * Updates the user's password, optionally with tracking and validation of
4688             * 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 login
4695             * @param  silentUpdate whether the password should be updated without being
4696             *         tracked, or validated. Primarily used for password imports.
4697             * @return the user
4698             */
4699            @Override
4700            public User updatePassword(
4701                            long userId, String password1, String password2,
4702                            boolean passwordReset, boolean silentUpdate)
4703                    throws PortalException {
4704    
4705                    User user = userPersistence.findByPrimaryKey(userId);
4706    
4707                    if (!silentUpdate) {
4708                            validatePassword(user.getCompanyId(), userId, password1, password2);
4709                    }
4710    
4711                    String oldEncPwd = user.getPassword();
4712    
4713                    if (!user.isPasswordEncrypted()) {
4714                            oldEncPwd = PasswordEncryptorUtil.encrypt(user.getPassword());
4715                    }
4716    
4717                    String newEncPwd = PasswordEncryptorUtil.encrypt(password1);
4718    
4719                    if (user.hasCompanyMx()) {
4720                            mailService.updatePassword(user.getCompanyId(), userId, password1);
4721                    }
4722    
4723                    user.setPassword(newEncPwd);
4724                    user.setPasswordUnencrypted(password1);
4725                    user.setPasswordEncrypted(true);
4726                    user.setPasswordReset(passwordReset);
4727    
4728                    if (!silentUpdate || (user.getPasswordModifiedDate() == null)) {
4729                            user.setPasswordModifiedDate(new Date());
4730                    }
4731    
4732                    user.setDigest(StringPool.BLANK);
4733                    user.setGraceLoginCount(0);
4734    
4735                    if (!silentUpdate) {
4736                            user.setPasswordModified(true);
4737                    }
4738    
4739                    try {
4740                            user = userPersistence.update(user);
4741                    }
4742                    catch (ModelListenerException mle) {
4743                            String msg = GetterUtil.getString(mle.getCause().getMessage());
4744    
4745                            if (LDAPSettingsUtil.isPasswordPolicyEnabled(user.getCompanyId())) {
4746                                    String[] errorPasswordHistoryKeywords =
4747                                            LDAPSettingsUtil.getErrorPasswordHistoryKeywords(
4748                                                    user.getCompanyId());
4749    
4750                                    for (String errorPasswordHistoryKeyword :
4751                                                    errorPasswordHistoryKeywords) {
4752    
4753                                            if (msg.contains(errorPasswordHistoryKeyword)) {
4754                                                    throw new UserPasswordException.MustNotBeRecentlyUsed(
4755                                                            userId);
4756                                            }
4757                                    }
4758                            }
4759    
4760                            throw new UserPasswordException.MustComplyWithModelListeners(
4761                                    userId, mle);
4762                    }
4763    
4764                    if (!silentUpdate) {
4765                            user.setPasswordModified(false);
4766    
4767                            passwordTrackerLocalService.trackPassword(userId, oldEncPwd);
4768                    }
4769    
4770                    if (!silentUpdate && (PrincipalThreadLocal.getUserId() != userId)) {
4771                            sendPasswordNotification(
4772                                    user, user.getCompanyId(), password1, null, null, null, null,
4773                                    null, ServiceContextThreadLocal.getServiceContext());
4774                    }
4775    
4776                    return user;
4777            }
4778    
4779            /**
4780             * Updates the user's password with manually input information. This method
4781             * should only be used when performing maintenance.
4782             *
4783             * @param  userId the primary key of the user
4784             * @param  password the user's new password
4785             * @param  passwordEncrypted the user's new encrypted password
4786             * @param  passwordReset whether the user should be asked to reset their
4787             *         password the next time they login
4788             * @param  passwordModifiedDate the new password modified date
4789             * @return the user
4790             */
4791            @Override
4792            public User updatePasswordManually(
4793                            long userId, String password, boolean passwordEncrypted,
4794                            boolean passwordReset, Date passwordModifiedDate)
4795                    throws PortalException {
4796    
4797                    // This method should only be used to manually massage data
4798    
4799                    User user = userPersistence.findByPrimaryKey(userId);
4800    
4801                    user.setPassword(password);
4802                    user.setPasswordEncrypted(passwordEncrypted);
4803                    user.setPasswordReset(passwordReset);
4804                    user.setPasswordModifiedDate(passwordModifiedDate);
4805                    user.setDigest(StringPool.BLANK);
4806    
4807                    userPersistence.update(user);
4808    
4809                    return user;
4810            }
4811    
4812            /**
4813             * Updates whether the user should be asked to reset their password the next
4814             * time they login.
4815             *
4816             * @param  userId the primary key of the user
4817             * @param  passwordReset whether the user should be asked to reset their
4818             *         password the next time they login
4819             * @return the user
4820             */
4821            @Override
4822            public User updatePasswordReset(long userId, boolean passwordReset)
4823                    throws PortalException {
4824    
4825                    User user = userPersistence.findByPrimaryKey(userId);
4826    
4827                    user.setPasswordReset(passwordReset);
4828    
4829                    userPersistence.update(user);
4830    
4831                    return user;
4832            }
4833    
4834            /**
4835             * Updates the user's portrait image.
4836             *
4837             * @param  userId the primary key of the user
4838             * @param  bytes the new portrait image data
4839             * @return the user
4840             */
4841            @Override
4842            public User updatePortrait(long userId, byte[] bytes)
4843                    throws PortalException {
4844    
4845                    User user = userPersistence.findByPrimaryKey(userId);
4846    
4847                    PortalUtil.updateImageId(
4848                            user, true, bytes, "portraitId",
4849                            PrefsPropsUtil.getLong(PropsKeys.USERS_IMAGE_MAX_SIZE),
4850                            PropsValues.USERS_IMAGE_MAX_HEIGHT,
4851                            PropsValues.USERS_IMAGE_MAX_WIDTH);
4852    
4853                    return userPersistence.update(user);
4854            }
4855    
4856            /**
4857             * Updates the user's password reset question and answer.
4858             *
4859             * @param  userId the primary key of the user
4860             * @param  question the user's new password reset question
4861             * @param  answer the user's new password reset answer
4862             * @return the user
4863             */
4864            @Override
4865            public User updateReminderQuery(long userId, String question, String answer)
4866                    throws PortalException {
4867    
4868                    validateReminderQuery(question, answer);
4869    
4870                    User user = userPersistence.findByPrimaryKey(userId);
4871    
4872                    user.setReminderQueryQuestion(question);
4873                    user.setReminderQueryAnswer(answer);
4874    
4875                    userPersistence.update(user);
4876    
4877                    return user;
4878            }
4879    
4880            /**
4881             * Updates the user's screen name.
4882             *
4883             * @param  userId the primary key of the user
4884             * @param  screenName the user's new screen name
4885             * @return the user
4886             */
4887            @Override
4888            public User updateScreenName(long userId, String screenName)
4889                    throws PortalException {
4890    
4891                    // User
4892    
4893                    User user = userPersistence.findByPrimaryKey(userId);
4894    
4895                    screenName = getLogin(screenName);
4896    
4897                    validateScreenName(user.getCompanyId(), userId, screenName);
4898    
4899                    if (!StringUtil.equalsIgnoreCase(user.getScreenName(), screenName)) {
4900                            user.setDigest(StringPool.BLANK);
4901                    }
4902    
4903                    user.setScreenName(screenName);
4904    
4905                    userPersistence.update(user);
4906    
4907                    // Group
4908    
4909                    Group group = groupLocalService.getUserGroup(
4910                            user.getCompanyId(), userId);
4911    
4912                    group.setFriendlyURL(StringPool.SLASH + screenName);
4913    
4914                    groupPersistence.update(group);
4915    
4916                    return user;
4917            }
4918    
4919            /**
4920             * Updates the user's workflow status.
4921             *
4922             * @param      userId the primary key of the user
4923             * @param      status the user's new workflow status
4924             * @return     the user
4925             * @deprecated As of 7.0.0, replaced by {@link #updateStatus(long, int,
4926             *             ServiceContext)}
4927             */
4928            @Deprecated
4929            @Override
4930            public User updateStatus(long userId, int status) throws PortalException {
4931                    return updateStatus(userId, status, new ServiceContext());
4932            }
4933    
4934            /**
4935             * Updates the user's workflow status.
4936             *
4937             * @param  userId the primary key of the user
4938             * @param  status the user's new workflow status
4939             * @param  serviceContext the service context to be applied. You can specify
4940             *         an unencrypted custom password (used by an LDAP listener) for the
4941             *         user via attribute <code>passwordUnencrypted</code>.
4942             * @return the user
4943             */
4944            @Override
4945            public User updateStatus(
4946                            long userId, int status, ServiceContext serviceContext)
4947                    throws PortalException {
4948    
4949                    User user = userPersistence.findByPrimaryKey(userId);
4950    
4951                    if ((status == WorkflowConstants.STATUS_APPROVED) &&
4952                            (user.getStatus() != WorkflowConstants.STATUS_APPROVED)) {
4953    
4954                            validateCompanyMaxUsers(user.getCompanyId());
4955                    }
4956    
4957                    String passwordUnencrypted = (String)serviceContext.getAttribute(
4958                            "passwordUnencrypted");
4959    
4960                    if (Validator.isNotNull(passwordUnencrypted)) {
4961                            user.setPasswordUnencrypted(passwordUnencrypted);
4962                    }
4963    
4964                    user.setStatus(status);
4965    
4966                    userPersistence.update(user);
4967    
4968                    reindex(user);
4969    
4970                    Group group = user.getGroup();
4971    
4972                    if (status == WorkflowConstants.STATUS_INACTIVE) {
4973                            group.setActive(false);
4974                    }
4975                    else {
4976                            group.setActive(true);
4977                    }
4978    
4979                    groupLocalService.updateGroup(group);
4980    
4981                    return user;
4982            }
4983    
4984            /**
4985             * Updates the user.
4986             *
4987             * @param  userId the primary key of the user
4988             * @param  oldPassword the user's old password
4989             * @param  newPassword1 the user's new password (optionally
4990             *         <code>null</code>)
4991             * @param  newPassword2 the user's new password confirmation (optionally
4992             *         <code>null</code>)
4993             * @param  passwordReset whether the user should be asked to reset their
4994             *         password the next time they login
4995             * @param  reminderQueryQuestion the user's new password reset question
4996             * @param  reminderQueryAnswer the user's new password reset answer
4997             * @param  screenName the user's new screen name
4998             * @param  emailAddress the user's new email address
4999             * @param  facebookId the user's new Facebook ID
5000             * @param  openId the user's new OpenID
5001             * @param  portrait whether to update the user's portrait image
5002             * @param  portraitBytes the new portrait image data
5003             * @param  languageId the user's new language ID
5004             * @param  timeZoneId the user's new time zone ID
5005             * @param  greeting the user's new greeting
5006             * @param  comments the user's new comments
5007             * @param  firstName the user's new first name
5008             * @param  middleName the user's new middle name
5009             * @param  lastName the user's new last name
5010             * @param  prefixId the user's new name prefix ID
5011             * @param  suffixId the user's new name suffix ID
5012             * @param  male whether user is male
5013             * @param  birthdayMonth the user's new birthday month (0-based, meaning 0
5014             *         for January)
5015             * @param  birthdayDay the user's new birthday day
5016             * @param  birthdayYear the user's birthday year
5017             * @param  smsSn the user's new SMS screen name
5018             * @param  facebookSn the user's new Facebook screen name
5019             * @param  jabberSn the user's new Jabber screen name
5020             * @param  skypeSn the user's new Skype screen name
5021             * @param  twitterSn the user's new Twitter screen name
5022             * @param  jobTitle the user's new job title
5023             * @param  groupIds the primary keys of the user's groups
5024             * @param  organizationIds the primary keys of the user's organizations
5025             * @param  roleIds the primary keys of the user's roles
5026             * @param  userGroupRoles the user user's group roles
5027             * @param  userGroupIds the primary keys of the user's user groups
5028             * @param  serviceContext the service context to be applied (optionally
5029             *         <code>null</code>). Can set the UUID (with the <code>uuid</code>
5030             *         attribute), asset category IDs, asset tag names, and expando
5031             *         bridge attributes for the user.
5032             * @return the user
5033             */
5034            @Override
5035            @SuppressWarnings("deprecation")
5036            public User updateUser(
5037                            long userId, String oldPassword, String newPassword1,
5038                            String newPassword2, boolean passwordReset,
5039                            String reminderQueryQuestion, String reminderQueryAnswer,
5040                            String screenName, String emailAddress, long facebookId,
5041                            String openId, boolean portrait, byte[] portraitBytes,
5042                            String languageId, String timeZoneId, String greeting,
5043                            String comments, String firstName, String middleName,
5044                            String lastName, long prefixId, long suffixId, boolean male,
5045                            int birthdayMonth, int birthdayDay, int birthdayYear, String smsSn,
5046                            String facebookSn, String jabberSn, String skypeSn,
5047                            String twitterSn, String jobTitle, long[] groupIds,
5048                            long[] organizationIds, long[] roleIds,
5049                            List<UserGroupRole> userGroupRoles, long[] userGroupIds,
5050                            ServiceContext serviceContext)
5051                    throws PortalException {
5052    
5053                    // User
5054    
5055                    User user = userPersistence.findByPrimaryKey(userId);
5056                    Company company = companyPersistence.findByPrimaryKey(
5057                            user.getCompanyId());
5058                    String password = oldPassword;
5059                    screenName = getLogin(screenName);
5060                    emailAddress = StringUtil.toLowerCase(emailAddress.trim());
5061                    openId = openId.trim();
5062                    String oldFullName = user.getFullName();
5063                    facebookSn = StringUtil.toLowerCase(facebookSn.trim());
5064                    jabberSn = StringUtil.toLowerCase(jabberSn.trim());
5065                    skypeSn = StringUtil.toLowerCase(skypeSn.trim());
5066                    twitterSn = StringUtil.toLowerCase(twitterSn.trim());
5067    
5068                    EmailAddressGenerator emailAddressGenerator =
5069                            EmailAddressGeneratorFactory.getInstance();
5070    
5071                    if (emailAddressGenerator.isGenerated(emailAddress)) {
5072                            emailAddress = StringPool.BLANK;
5073                    }
5074    
5075                    if (!PropsValues.USERS_EMAIL_ADDRESS_REQUIRED &&
5076                            Validator.isNull(emailAddress)) {
5077    
5078                            emailAddress = emailAddressGenerator.generate(
5079                                    user.getCompanyId(), userId);
5080                    }
5081    
5082                    Locale locale = LocaleUtil.fromLanguageId(languageId);
5083    
5084                    validate(
5085                            userId, screenName, emailAddress, openId, firstName, middleName,
5086                            lastName, smsSn, locale);
5087    
5088                    if (Validator.isNotNull(newPassword1) ||
5089                            Validator.isNotNull(newPassword2)) {
5090    
5091                            user = updatePassword(
5092                                    userId, newPassword1, newPassword2, passwordReset);
5093    
5094                            password = newPassword1;
5095    
5096                            user.setDigest(StringPool.BLANK);
5097                    }
5098    
5099                    if (user.getContactId() <= 0) {
5100                            user.setContactId(counterLocalService.increment());
5101                    }
5102    
5103                    user.setPasswordReset(passwordReset);
5104    
5105                    if (Validator.isNotNull(reminderQueryQuestion) &&
5106                            Validator.isNotNull(reminderQueryAnswer)) {
5107    
5108                            user.setReminderQueryQuestion(reminderQueryQuestion);
5109                            user.setReminderQueryAnswer(reminderQueryAnswer);
5110                    }
5111    
5112                    if (!StringUtil.equalsIgnoreCase(user.getScreenName(), screenName)) {
5113                            user.setScreenName(screenName);
5114    
5115                            user.setDigest(StringPool.BLANK);
5116                    }
5117    
5118                    boolean sendEmailAddressVerification = false;
5119    
5120                    if (company.isStrangersVerify() &&
5121                            !StringUtil.equalsIgnoreCase(
5122                                    emailAddress, user.getEmailAddress())) {
5123    
5124                            sendEmailAddressVerification = true;
5125                    }
5126                    else {
5127                            setEmailAddress(
5128                                    user, password, firstName, middleName, lastName, emailAddress);
5129                    }
5130    
5131                    if (serviceContext != null) {
5132                            String uuid = serviceContext.getUuid();
5133    
5134                            if (Validator.isNotNull(uuid)) {
5135                                    user.setUuid(uuid);
5136                            }
5137                    }
5138    
5139                    user.setFacebookId(facebookId);
5140    
5141                    Long ldapServerId = null;
5142    
5143                    if (serviceContext != null) {
5144                            ldapServerId = (Long)serviceContext.getAttribute("ldapServerId");
5145                    }
5146    
5147                    if (ldapServerId != null) {
5148                            user.setLdapServerId(ldapServerId);
5149                    }
5150    
5151                    user.setOpenId(openId);
5152    
5153                    PortalUtil.updateImageId(
5154                            user, portrait, portraitBytes, "portraitId",
5155                            PrefsPropsUtil.getLong(PropsKeys.USERS_IMAGE_MAX_SIZE),
5156                            PropsValues.USERS_IMAGE_MAX_HEIGHT,
5157                            PropsValues.USERS_IMAGE_MAX_WIDTH);
5158    
5159                    user.setLanguageId(languageId);
5160                    user.setTimeZoneId(timeZoneId);
5161                    user.setGreeting(greeting);
5162                    user.setComments(comments);
5163                    user.setFirstName(firstName);
5164                    user.setMiddleName(middleName);
5165                    user.setLastName(lastName);
5166                    user.setJobTitle(jobTitle);
5167                    user.setExpandoBridgeAttributes(serviceContext);
5168    
5169                    userPersistence.update(user, serviceContext);
5170    
5171                    // Contact
5172    
5173                    Date birthday = getBirthday(birthdayMonth, birthdayDay, birthdayYear);
5174    
5175                    long contactId = user.getContactId();
5176    
5177                    Contact contact = contactPersistence.fetchByPrimaryKey(contactId);
5178    
5179                    if (contact == null) {
5180                            contact = contactPersistence.create(contactId);
5181    
5182                            contact.setCompanyId(user.getCompanyId());
5183                            contact.setUserName(StringPool.BLANK);
5184                            contact.setClassName(User.class.getName());
5185                            contact.setClassPK(user.getUserId());
5186                            contact.setAccountId(company.getAccountId());
5187                            contact.setParentContactId(
5188                                    ContactConstants.DEFAULT_PARENT_CONTACT_ID);
5189                    }
5190    
5191                    contact.setEmailAddress(user.getEmailAddress());
5192                    contact.setFirstName(firstName);
5193                    contact.setMiddleName(middleName);
5194                    contact.setLastName(lastName);
5195                    contact.setPrefixId(prefixId);
5196                    contact.setSuffixId(suffixId);
5197                    contact.setMale(male);
5198                    contact.setBirthday(birthday);
5199                    contact.setSmsSn(smsSn);
5200                    contact.setFacebookSn(facebookSn);
5201                    contact.setJabberSn(jabberSn);
5202                    contact.setSkypeSn(skypeSn);
5203                    contact.setTwitterSn(twitterSn);
5204                    contact.setJobTitle(jobTitle);
5205    
5206                    contactPersistence.update(contact, serviceContext);
5207    
5208                    // Group
5209    
5210                    Group group = groupLocalService.getUserGroup(
5211                            user.getCompanyId(), userId);
5212    
5213                    group.setFriendlyURL(StringPool.SLASH + screenName);
5214    
5215                    groupPersistence.update(group);
5216    
5217                    // Groups and organizations
5218    
5219                    // See LPS-33205. Cache the user's list of user group roles because
5220                    // adding or removing groups may add or remove user group roles
5221                    // depending on the site default user associations.
5222    
5223                    List<UserGroupRole> previousUserGroupRoles =
5224                            userGroupRolePersistence.findByUserId(userId);
5225    
5226                    updateGroups(userId, groupIds, serviceContext, false);
5227                    updateOrganizations(userId, organizationIds, false);
5228    
5229                    // Roles
5230    
5231                    if (roleIds != null) {
5232                            roleIds = UsersAdminUtil.addRequiredRoles(user, roleIds);
5233    
5234                            userPersistence.setRoles(userId, roleIds);
5235                    }
5236    
5237                    // User group roles
5238    
5239                    updateUserGroupRoles(
5240                            user, groupIds, organizationIds, userGroupRoles,
5241                            previousUserGroupRoles);
5242    
5243                    // User groups
5244    
5245                    if (userGroupIds != null) {
5246                            if (PropsValues.USER_GROUPS_COPY_LAYOUTS_TO_USER_PERSONAL_SITE) {
5247                                    userGroupLocalService.copyUserGroupLayouts(
5248                                            userGroupIds, userId);
5249                            }
5250    
5251                            userPersistence.setUserGroups(userId, userGroupIds);
5252                    }
5253    
5254                    // Announcements
5255    
5256                    announcementsDeliveryLocalService.getUserDeliveries(user.getUserId());
5257    
5258                    // Asset
5259    
5260                    if (serviceContext != null) {
5261                            updateAsset(
5262                                    userId, user, serviceContext.getAssetCategoryIds(),
5263                                    serviceContext.getAssetTagNames());
5264                    }
5265    
5266                    // Message boards
5267    
5268                    if (GetterUtil.getBoolean(
5269                                    PropsKeys.USERS_UPDATE_USER_NAME + MBMessage.class.getName()) &&
5270                            !oldFullName.equals(user.getFullName())) {
5271    
5272                            mbMessageLocalService.updateUserName(userId, user.getFullName());
5273                    }
5274    
5275                    // Indexer
5276    
5277                    if ((serviceContext == null) || serviceContext.isIndexingEnabled()) {
5278                            Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
5279                                    User.class);
5280    
5281                            indexer.reindex(user);
5282                    }
5283    
5284                    // Email address verification
5285    
5286                    if ((serviceContext != null) && sendEmailAddressVerification) {
5287                            sendEmailAddressVerification(user, emailAddress, serviceContext);
5288                    }
5289    
5290                    // Permission cache
5291    
5292                    PermissionCacheUtil.clearCache(userId);
5293    
5294                    return user;
5295            }
5296    
5297            /**
5298             * Updates the user.
5299             *
5300             * @param      userId the primary key of the user
5301             * @param      oldPassword the user's old password
5302             * @param      newPassword1 the user's new password (optionally
5303             *             <code>null</code>)
5304             * @param      newPassword2 the user's new password confirmation (optionally
5305             *             <code>null</code>)
5306             * @param      passwordReset whether the user should be asked to reset their
5307             *             password the next time they login
5308             * @param      reminderQueryQuestion the user's new password reset question
5309             * @param      reminderQueryAnswer the user's new password reset answer
5310             * @param      screenName the user's new screen name
5311             * @param      emailAddress the user's new email address
5312             * @param      facebookId the user's new Facebook ID
5313             * @param      openId the user's new OpenID
5314             * @param      languageId the user's new language ID
5315             * @param      timeZoneId the user's new time zone ID
5316             * @param      greeting the user's new greeting
5317             * @param      comments the user's new comments
5318             * @param      firstName the user's new first name
5319             * @param      middleName the user's new middle name
5320             * @param      lastName the user's new last name
5321             * @param      prefixId the user's new name prefix ID
5322             * @param      suffixId the user's new name suffix ID
5323             * @param      male whether user is male
5324             * @param      birthdayMonth the user's new birthday month (0-based, meaning
5325             *             0 for January)
5326             * @param      birthdayDay the user's new birthday day
5327             * @param      birthdayYear the user's birthday year
5328             * @param      smsSn the user's new SMS screen name
5329             * @param      facebookSn the user's new Facebook screen name
5330             * @param      jabberSn the user's new Jabber screen name
5331             * @param      skypeSn the user's new Skype screen name
5332             * @param      twitterSn the user's new Twitter screen name
5333             * @param      jobTitle the user's new job title
5334             * @param      groupIds the primary keys of the user's groups
5335             * @param      organizationIds the primary keys of the user's organizations
5336             * @param      roleIds the primary keys of the user's roles
5337             * @param      userGroupRoles the user user's group roles
5338             * @param      userGroupIds the primary keys of the user's user groups
5339             * @param      serviceContext the service context to be applied (optionally
5340             *             <code>null</code>). Can set the UUID (with the
5341             *             <code>uuid</code> attribute), asset category IDs, asset tag
5342             *             names, and expando bridge attributes for the user.
5343             * @return     the user
5344             * @deprecated As of 7.0.0, replaced by {@link #updateUser(long, String,
5345             *             String, String, boolean, String, String, String, String,
5346             *             long, String, boolean, byte[], String, String, String,
5347             *             String, String, String, String, long, long, boolean, int,
5348             *             int, int, String, String, String, String, String, String,
5349             *             long[], long[], long[], List, long[], ServiceContext)}
5350             */
5351            @Deprecated
5352            @Override
5353            public User updateUser(
5354                            long userId, String oldPassword, String newPassword1,
5355                            String newPassword2, boolean passwordReset,
5356                            String reminderQueryQuestion, String reminderQueryAnswer,
5357                            String screenName, String emailAddress, long facebookId,
5358                            String openId, String languageId, String timeZoneId,
5359                            String greeting, String comments, String firstName,
5360                            String middleName, String lastName, long prefixId, long suffixId,
5361                            boolean male, int birthdayMonth, int birthdayDay, int birthdayYear,
5362                            String smsSn, String facebookSn, String jabberSn, String skypeSn,
5363                            String twitterSn, String jobTitle, long[] groupIds,
5364                            long[] organizationIds, long[] roleIds,
5365                            List<UserGroupRole> userGroupRoles, long[] userGroupIds,
5366                            ServiceContext serviceContext)
5367                    throws PortalException {
5368    
5369                    return updateUser(
5370                            userId, oldPassword, newPassword1, newPassword2, passwordReset,
5371                            reminderQueryQuestion, reminderQueryAnswer, screenName,
5372                            emailAddress, facebookId, openId, true, null, languageId,
5373                            timeZoneId, greeting, comments, firstName, middleName, lastName,
5374                            prefixId, suffixId, male, birthdayMonth, birthdayDay, birthdayYear,
5375                            smsSn, facebookSn, jabberSn, skypeSn, twitterSn, jobTitle, groupIds,
5376                            organizationIds, roleIds, userGroupRoles, userGroupIds,
5377                            serviceContext);
5378            }
5379    
5380            /**
5381             * Verifies the email address of the ticket.
5382             *
5383             * @param ticketKey the ticket key
5384             */
5385            @Override
5386            public void verifyEmailAddress(String ticketKey) throws PortalException {
5387                    Ticket ticket = ticketLocalService.getTicket(ticketKey);
5388    
5389                    if (ticket.isExpired() ||
5390                            (ticket.getType() != TicketConstants.TYPE_EMAIL_ADDRESS)) {
5391    
5392                            throw new NoSuchTicketException("{ticketKey=" + ticketKey + "}");
5393                    }
5394    
5395                    User user = userPersistence.findByPrimaryKey(ticket.getClassPK());
5396    
5397                    String emailAddress = ticket.getExtraInfo();
5398    
5399                    emailAddress = StringUtil.toLowerCase(emailAddress).trim();
5400    
5401                    if (!emailAddress.equals(user.getEmailAddress())) {
5402                            if (userPersistence.fetchByC_EA(
5403                                            user.getCompanyId(), emailAddress) != null) {
5404    
5405                                    throw new UserEmailAddressException.MustNotBeDuplicate(
5406                                            user.getUserId(), emailAddress);
5407                            }
5408    
5409                            setEmailAddress(
5410                                    user, StringPool.BLANK, user.getFirstName(),
5411                                    user.getMiddleName(), user.getLastName(), emailAddress);
5412    
5413                            Contact contact = user.getContact();
5414    
5415                            contact.setEmailAddress(user.getEmailAddress());
5416    
5417                            contactPersistence.update(contact);
5418                    }
5419    
5420                    user.setEmailAddressVerified(true);
5421    
5422                    userPersistence.update(user);
5423    
5424                    ticketLocalService.deleteTicket(ticket);
5425            }
5426    
5427            protected void addDefaultRolesAndTeams(long groupId, long[] userIds)
5428                    throws PortalException {
5429    
5430                    List<Role> defaultSiteRoles = new ArrayList<>();
5431    
5432                    Group group = groupLocalService.getGroup(groupId);
5433    
5434                    UnicodeProperties typeSettingsProperties =
5435                            group.getTypeSettingsProperties();
5436    
5437                    long[] defaultSiteRoleIds = StringUtil.split(
5438                            typeSettingsProperties.getProperty("defaultSiteRoleIds"), 0L);
5439    
5440                    for (long defaultSiteRoleId : defaultSiteRoleIds) {
5441                            Role defaultSiteRole = rolePersistence.fetchByPrimaryKey(
5442                                    defaultSiteRoleId);
5443    
5444                            if (defaultSiteRole == null) {
5445                                    if (_log.isWarnEnabled()) {
5446                                            _log.warn("Unable to find role " + defaultSiteRoleId);
5447                                    }
5448    
5449                                    continue;
5450                            }
5451    
5452                            defaultSiteRoles.add(defaultSiteRole);
5453                    }
5454    
5455                    List<Team> defaultTeams = new ArrayList<>();
5456    
5457                    long[] defaultTeamIds = StringUtil.split(
5458                            typeSettingsProperties.getProperty("defaultTeamIds"), 0L);
5459    
5460                    for (long defaultTeamId : defaultTeamIds) {
5461                            Team defaultTeam = teamPersistence.findByPrimaryKey(defaultTeamId);
5462    
5463                            if (defaultTeam == null) {
5464                                    if (_log.isWarnEnabled()) {
5465                                            _log.warn("Unable to find team " + defaultTeamId);
5466                                    }
5467    
5468                                    continue;
5469                            }
5470    
5471                            defaultTeams.add(defaultTeam);
5472                    }
5473    
5474                    for (long userId : userIds) {
5475                            Set<Long> userRoleIdsSet = new HashSet<>();
5476    
5477                            for (Role role : defaultSiteRoles) {
5478                                    if (!userPersistence.containsRole(userId, role.getRoleId())) {
5479                                            userRoleIdsSet.add(role.getRoleId());
5480                                    }
5481                            }
5482    
5483                            long[] userRoleIds = ArrayUtil.toArray(
5484                                    userRoleIdsSet.toArray(new Long[userRoleIdsSet.size()]));
5485    
5486                            userGroupRoleLocalService.addUserGroupRoles(
5487                                    userId, groupId, userRoleIds);
5488    
5489                            Set<Long> userTeamIdsSet = new HashSet<>();
5490    
5491                            for (Team team : defaultTeams) {
5492                                    if (!userPersistence.containsTeam(userId, team.getTeamId())) {
5493                                            userTeamIdsSet.add(team.getTeamId());
5494                                    }
5495                            }
5496    
5497                            long[] userTeamIds = ArrayUtil.toArray(
5498                                    userTeamIdsSet.toArray(new Long[userTeamIdsSet.size()]));
5499    
5500                            userPersistence.addTeams(userId, userTeamIds);
5501                    }
5502            }
5503    
5504            /**
5505             * Attempts to authenticate the user by their login and password, while
5506             * using the AuthPipeline.
5507             *
5508             * <p>
5509             * Authentication type specifies what <code>login</code> contains.The valid
5510             * values are:
5511             * </p>
5512             *
5513             * <ul>
5514             * <li>
5515             * <code>CompanyConstants.AUTH_TYPE_EA</code> - <code>login</code> is the
5516             * user's email address
5517             * </li>
5518             * <li>
5519             * <code>CompanyConstants.AUTH_TYPE_SN</code> - <code>login</code> is the
5520             * user's screen name
5521             * </li>
5522             * <li>
5523             * <code>CompanyConstants.AUTH_TYPE_ID</code> - <code>login</code> is the
5524             * user's primary key
5525             * </li>
5526             * </ul>
5527             *
5528             * @param  companyId the primary key of the user's company
5529             * @param  login either the user's email address, screen name, or primary
5530             *         key depending on the value of <code>authType</code>
5531             * @param  password the user's password
5532             * @param  authType the type of authentication to perform
5533             * @param  headerMap the header map from the authentication request
5534             * @param  parameterMap the parameter map from the authentication request
5535             * @param  resultsMap the map of authentication results (may be nil). After
5536             *         a successful authentication the user's primary key will be placed
5537             *         under the key <code>userId</code>.
5538             * @return the authentication status. This can be {@link
5539             *         Authenticator#FAILURE} indicating that the user's credentials are
5540             *         invalid, {@link Authenticator#SUCCESS} indicating a successful
5541             *         login, or {@link Authenticator#DNE} indicating that a user with
5542             *         that login does not exist.
5543             * @see    AuthPipeline
5544             */
5545            protected int authenticate(
5546                            long companyId, String login, String password, String authType,
5547                            Map<String, String[]> headerMap, Map<String, String[]> parameterMap,
5548                            Map<String, Object> resultsMap)
5549                    throws PortalException {
5550    
5551                    if (PropsValues.AUTH_LOGIN_DISABLED) {
5552                            return Authenticator.FAILURE;
5553                    }
5554    
5555                    login = StringUtil.toLowerCase(login.trim());
5556    
5557                    long userId = GetterUtil.getLong(login);
5558    
5559                    // User input validation
5560    
5561                    if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) {
5562                            if (Validator.isNull(login)) {
5563                                    throw new UserEmailAddressException.MustNotBeNull();
5564                            }
5565                    }
5566                    else if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
5567                            if (Validator.isNull(login)) {
5568                                    throw new UserScreenNameException.MustNotBeNull();
5569                            }
5570                    }
5571                    else if (authType.equals(CompanyConstants.AUTH_TYPE_ID)) {
5572                            if (Validator.isNull(login)) {
5573                                    throw new UserIdException.MustNotBeNull();
5574                            }
5575                    }
5576    
5577                    if (Validator.isNull(password)) {
5578                            throw new UserPasswordException.MustNotBeNull(userId);
5579                    }
5580    
5581                    int authResult = Authenticator.FAILURE;
5582    
5583                    // Pre-authentication pipeline
5584    
5585                    if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) {
5586                            authResult = AuthPipeline.authenticateByEmailAddress(
5587                                    PropsKeys.AUTH_PIPELINE_PRE, companyId, login, password,
5588                                    headerMap, parameterMap);
5589                    }
5590                    else if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
5591                            authResult = AuthPipeline.authenticateByScreenName(
5592                                    PropsKeys.AUTH_PIPELINE_PRE, companyId, login, password,
5593                                    headerMap, parameterMap);
5594                    }
5595                    else if (authType.equals(CompanyConstants.AUTH_TYPE_ID)) {
5596                            authResult = AuthPipeline.authenticateByUserId(
5597                                    PropsKeys.AUTH_PIPELINE_PRE, companyId, userId, password,
5598                                    headerMap, parameterMap);
5599                    }
5600    
5601                    // Get user
5602    
5603                    User user = null;
5604    
5605                    if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) {
5606                            user = fetchUserByEmailAddress(companyId, login);
5607                    }
5608                    else if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
5609                            user = fetchUserByScreenName(companyId, login);
5610                    }
5611                    else if (authType.equals(CompanyConstants.AUTH_TYPE_ID)) {
5612                            user = userPersistence.fetchByPrimaryKey(GetterUtil.getLong(login));
5613                    }
5614    
5615                    if (user == null) {
5616                            return Authenticator.DNE;
5617                    }
5618    
5619                    if (!isUserAllowedToAuthenticate(user)) {
5620                            return Authenticator.FAILURE;
5621                    }
5622    
5623                    if (!user.isPasswordEncrypted()) {
5624                            user.setPassword(PasswordEncryptorUtil.encrypt(user.getPassword()));
5625                            user.setPasswordEncrypted(true);
5626    
5627                            userPersistence.update(user);
5628                    }
5629    
5630                    // Authenticate against the User_ table
5631    
5632                    boolean skipLiferayCheck = false;
5633    
5634                    if (authResult == Authenticator.SKIP_LIFERAY_CHECK) {
5635                            authResult = Authenticator.SUCCESS;
5636    
5637                            skipLiferayCheck = true;
5638                    }
5639                    else if ((authResult == Authenticator.SUCCESS) &&
5640                                     PropsValues.AUTH_PIPELINE_ENABLE_LIFERAY_CHECK) {
5641    
5642                            boolean authenticated = PwdAuthenticator.authenticate(
5643                                    login, password, user.getPassword());
5644    
5645                            if (authenticated) {
5646                                    authResult = Authenticator.SUCCESS;
5647                            }
5648                            else {
5649                                    authResult = Authenticator.FAILURE;
5650                            }
5651                    }
5652    
5653                    // Post-authentication pipeline
5654    
5655                    if (authResult == Authenticator.SUCCESS) {
5656                            if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) {
5657                                    authResult = AuthPipeline.authenticateByEmailAddress(
5658                                            PropsKeys.AUTH_PIPELINE_POST, companyId, login, password,
5659                                            headerMap, parameterMap);
5660                            }
5661                            else if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
5662                                    authResult = AuthPipeline.authenticateByScreenName(
5663                                            PropsKeys.AUTH_PIPELINE_POST, companyId, login, password,
5664                                            headerMap, parameterMap);
5665                            }
5666                            else if (authType.equals(CompanyConstants.AUTH_TYPE_ID)) {
5667                                    authResult = AuthPipeline.authenticateByUserId(
5668                                            PropsKeys.AUTH_PIPELINE_POST, companyId, userId, password,
5669                                            headerMap, parameterMap);
5670                            }
5671                    }
5672    
5673                    if (resultsMap != null) {
5674                            resultsMap.put("userId", user.getUserId());
5675                    }
5676    
5677                    if (authResult == Authenticator.SUCCESS) {
5678    
5679                            // Update digest
5680    
5681                            if (skipLiferayCheck ||
5682                                    !PropsValues.AUTH_PIPELINE_ENABLE_LIFERAY_CHECK ||
5683                                    Validator.isNull(user.getDigest())) {
5684    
5685                                    user = userPersistence.fetchByPrimaryKey(user.getUserId());
5686    
5687                                    String digest = user.getDigest(password);
5688    
5689                                    user.setDigest(digest);
5690    
5691                                    userPersistence.update(user);
5692                            }
5693                    }
5694    
5695                    // Execute code triggered by authentication failure
5696    
5697                    if (authResult == Authenticator.FAILURE) {
5698                            authResult = handleAuthenticationFailure(
5699                                    login, authType, user, headerMap, parameterMap);
5700                    }
5701                    else {
5702                            resetFailedLoginAttempts(user);
5703                    }
5704    
5705                    // PLACEHOLDER 02
5706    
5707                    return authResult;
5708            }
5709    
5710            protected SearchContext buildSearchContext(
5711                    long companyId, String firstName, String middleName, String lastName,
5712                    String fullName, String screenName, String emailAddress, String street,
5713                    String city, String zip, String region, String country, int status,
5714                    LinkedHashMap<String, Object> params, boolean andSearch, int start,
5715                    int end, Sort[] sorts) {
5716    
5717                    SearchContext searchContext = new SearchContext();
5718    
5719                    searchContext.setAndSearch(andSearch);
5720    
5721                    Map<String, Serializable> attributes = new HashMap<>();
5722    
5723                    attributes.put("city", city);
5724                    attributes.put("country", country);
5725                    attributes.put("emailAddress", emailAddress);
5726                    attributes.put("firstName", firstName);
5727                    attributes.put("fullName", fullName);
5728                    attributes.put("lastName", lastName);
5729                    attributes.put("middleName", middleName);
5730                    attributes.put("params", params);
5731                    attributes.put("region", region);
5732                    attributes.put("screenName", screenName);
5733                    attributes.put("street", street);
5734                    attributes.put("status", status);
5735                    attributes.put("zip", zip);
5736    
5737                    searchContext.setAttributes(attributes);
5738    
5739                    searchContext.setCompanyId(companyId);
5740                    searchContext.setEnd(end);
5741    
5742                    if (params != null) {
5743                            String keywords = (String)params.remove("keywords");
5744    
5745                            if (Validator.isNotNull(keywords)) {
5746                                    searchContext.setKeywords(keywords);
5747                            }
5748                    }
5749    
5750                    if (sorts != null) {
5751                            searchContext.setSorts(sorts);
5752                    }
5753    
5754                    searchContext.setStart(start);
5755    
5756                    QueryConfig queryConfig = searchContext.getQueryConfig();
5757    
5758                    queryConfig.setHighlightEnabled(false);
5759                    queryConfig.setScoreEnabled(false);
5760    
5761                    return searchContext;
5762            }
5763    
5764            protected Date getBirthday(
5765                            int birthdayMonth, int birthdayDay, int birthdayYear)
5766                    throws PortalException {
5767    
5768                    Date birthday = PortalUtil.getDate(
5769                            birthdayMonth, birthdayDay, birthdayYear,
5770                            ContactBirthdayException.class);
5771    
5772                    if (birthday.after(new Date())) {
5773                            throw new ContactBirthdayException();
5774                    }
5775    
5776                    return birthday;
5777            }
5778    
5779            protected String getLogin(String login) {
5780                    return StringUtil.lowerCase(StringUtil.trim(login));
5781            }
5782    
5783            protected Sort[] getSorts(OrderByComparator<User> obc) {
5784                    if (obc == null) {
5785                            return new Sort[0];
5786                    }
5787    
5788                    String[] orderByClauses = StringUtil.split(obc.getOrderBy());
5789                    String[] orderByFields = obc.getOrderByFields();
5790    
5791                    Sort[] sorts = new Sort[orderByFields.length];
5792    
5793                    for (int i = 0; i < orderByFields.length; i++) {
5794                            boolean reverse = orderByClauses[i].contains("DESC");
5795    
5796                            sorts[i] = new Sort(orderByFields[i], reverse);
5797                    }
5798    
5799                    return sorts;
5800            }
5801    
5802            protected int handleAuthenticationFailure(
5803                    String login, String authType, User user,
5804                    Map<String, String[]> headerMap, Map<String, String[]> parameterMap) {
5805    
5806                    if (user == null) {
5807                            return Authenticator.DNE;
5808                    }
5809    
5810                    try {
5811                            if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) {
5812                                    AuthPipeline.onFailureByEmailAddress(
5813                                            PropsKeys.AUTH_FAILURE, user.getCompanyId(), login,
5814                                            headerMap, parameterMap);
5815                            }
5816                            else if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
5817                                    AuthPipeline.onFailureByScreenName(
5818                                            PropsKeys.AUTH_FAILURE, user.getCompanyId(), login,
5819                                            headerMap, parameterMap);
5820                            }
5821                            else if (authType.equals(CompanyConstants.AUTH_TYPE_ID)) {
5822                                    AuthPipeline.onFailureByUserId(
5823                                            PropsKeys.AUTH_FAILURE, user.getCompanyId(),
5824                                            user.getUserId(), headerMap, parameterMap);
5825                            }
5826    
5827                            user = userPersistence.fetchByPrimaryKey(user.getUserId());
5828    
5829                            if (user == null) {
5830                                    return Authenticator.DNE;
5831                            }
5832    
5833                            // Let LDAP handle max failure event
5834    
5835                            if (!LDAPSettingsUtil.isPasswordPolicyEnabled(
5836                                            user.getCompanyId())) {
5837    
5838                                    PasswordPolicy passwordPolicy = user.getPasswordPolicy();
5839    
5840                                    user = userPersistence.fetchByPrimaryKey(user.getUserId());
5841    
5842                                    int failedLoginAttempts = user.getFailedLoginAttempts();
5843                                    int maxFailures = passwordPolicy.getMaxFailure();
5844    
5845                                    if ((failedLoginAttempts >= maxFailures) &&
5846                                            (maxFailures != 0)) {
5847    
5848                                            if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) {
5849                                                    AuthPipeline.onMaxFailuresByEmailAddress(
5850                                                            PropsKeys.AUTH_MAX_FAILURES, user.getCompanyId(),
5851                                                            login, headerMap, parameterMap);
5852                                            }
5853                                            else if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
5854                                                    AuthPipeline.onMaxFailuresByScreenName(
5855                                                            PropsKeys.AUTH_MAX_FAILURES, user.getCompanyId(),
5856                                                            login, headerMap, parameterMap);
5857                                            }
5858                                            else if (authType.equals(CompanyConstants.AUTH_TYPE_ID)) {
5859                                                    AuthPipeline.onMaxFailuresByUserId(
5860                                                            PropsKeys.AUTH_MAX_FAILURES, user.getCompanyId(),
5861                                                            user.getUserId(), headerMap, parameterMap);
5862                                            }
5863                                    }
5864                            }
5865                    }
5866                    catch (Exception e) {
5867                            _log.error(e, e);
5868                    }
5869    
5870                    return Authenticator.FAILURE;
5871            }
5872    
5873            protected boolean isUseCustomSQL(LinkedHashMap<String, Object> params) {
5874                    if (MapUtil.isEmpty(params)) {
5875                            return false;
5876                    }
5877    
5878                    for (String key : params.keySet()) {
5879                            if (!key.equals("inherit") && !key.equals("usersGroups") &&
5880                                    !key.equals("usersOrgs") && !key.equals("usersOrgsCount") &&
5881                                    !key.equals("usersRoles") && !key.equals("usersTeams") &&
5882                                    !key.equals("usersUserGroups")) {
5883    
5884                                    return true;
5885                            }
5886                    }
5887    
5888                    Boolean inherit = (Boolean)params.get("inherit");
5889    
5890                    if ((inherit != null) && inherit) {
5891                            return true;
5892                    }
5893    
5894                    return false;
5895            }
5896    
5897            protected boolean isUserAllowedToAuthenticate(User user)
5898                    throws PortalException {
5899    
5900                    if (user.isDefaultUser()) {
5901                            if (_log.isInfoEnabled()) {
5902                                    _log.info("Authentication is disabled for the default user");
5903                            }
5904    
5905                            return false;
5906                    }
5907                    else if (!user.isActive()) {
5908                            if (_log.isInfoEnabled()) {
5909                                    _log.info(
5910                                            "Authentication is disabled for inactive user " +
5911                                                    user.getUserId());
5912                            }
5913    
5914                            return false;
5915                    }
5916    
5917                    // Check password policy to see if the is account locked out or if the
5918                    // password is expired
5919    
5920                    checkLockout(user);
5921    
5922                    checkPasswordExpired(user);
5923    
5924                    return true;
5925            }
5926    
5927            protected void notifyUser(
5928                    User user, String password, ServiceContext serviceContext) {
5929    
5930                    if (!PrefsPropsUtil.getBoolean(
5931                                    user.getCompanyId(),
5932                                    PropsKeys.ADMIN_EMAIL_USER_ADDED_ENABLED)) {
5933    
5934                            return;
5935                    }
5936    
5937                    String fromName = PrefsPropsUtil.getString(
5938                            user.getCompanyId(), PropsKeys.ADMIN_EMAIL_FROM_NAME);
5939                    String fromAddress = PrefsPropsUtil.getString(
5940                            user.getCompanyId(), PropsKeys.ADMIN_EMAIL_FROM_ADDRESS);
5941    
5942                    String toName = user.getFullName();
5943                    String toAddress = user.getEmailAddress();
5944    
5945                    PortletPreferences companyPortletPreferences =
5946                            PrefsPropsUtil.getPreferences(user.getCompanyId(), true);
5947    
5948                    Map<Locale, String> localizedSubjectMap =
5949                            LocalizationUtil.getLocalizationMap(
5950                                    companyPortletPreferences, "adminEmailUserAddedSubject",
5951                                    PropsKeys.ADMIN_EMAIL_USER_ADDED_SUBJECT);
5952    
5953                    Map<Locale, String> localizedBodyMap = null;
5954    
5955                    if (Validator.isNotNull(password)) {
5956                            localizedBodyMap = LocalizationUtil.getLocalizationMap(
5957                                    companyPortletPreferences, "adminEmailUserAddedBody",
5958                                    PropsKeys.ADMIN_EMAIL_USER_ADDED_BODY);
5959                    }
5960                    else {
5961                            localizedBodyMap = LocalizationUtil.getLocalizationMap(
5962                                    companyPortletPreferences, "adminEmailUserAddedNoPasswordBody",
5963                                    PropsKeys.ADMIN_EMAIL_USER_ADDED_NO_PASSWORD_BODY);
5964                    }
5965    
5966                    SubscriptionSender subscriptionSender = new SubscriptionSender();
5967    
5968                    subscriptionSender.setCompanyId(user.getCompanyId());
5969                    subscriptionSender.setContextAttributes(
5970                            "[$USER_ID$]", user.getUserId(), "[$USER_PASSWORD$]", password,
5971                            "[$USER_SCREENNAME$]", user.getScreenName());
5972                    subscriptionSender.setFrom(fromAddress, fromName);
5973                    subscriptionSender.setHtmlFormat(true);
5974                    subscriptionSender.setLocalizedBodyMap(localizedBodyMap);
5975                    subscriptionSender.setLocalizedSubjectMap(localizedSubjectMap);
5976                    subscriptionSender.setMailId("user", user.getUserId());
5977                    subscriptionSender.setServiceContext(serviceContext);
5978    
5979                    subscriptionSender.addRuntimeSubscribers(toAddress, toName);
5980    
5981                    subscriptionSender.flushNotificationsAsync();
5982            }
5983    
5984            protected void reindex(long userId) throws SearchException {
5985                    Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
5986                            User.class);
5987    
5988                    User user = userLocalService.fetchUser(userId);
5989    
5990                    indexer.reindex(user);
5991            }
5992    
5993            protected void reindex(long[] userIds) throws SearchException {
5994                    Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
5995                            User.class);
5996    
5997                    List<User> users = new ArrayList<>(userIds.length);
5998    
5999                    for (Long userId : userIds) {
6000                            User user = userLocalService.fetchUser(userId);
6001    
6002                            users.add(user);
6003                    }
6004    
6005                    indexer.reindex(users);
6006            }
6007    
6008            protected void reindex(final User user) throws SearchException {
6009                    Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
6010                            User.class);
6011    
6012                    indexer.reindex(user);
6013            }
6014    
6015            protected void resetFailedLoginAttempts(User user) {
6016                    resetFailedLoginAttempts(user, false);
6017            }
6018    
6019            protected void resetFailedLoginAttempts(User user, boolean forceUpdate) {
6020                    if (forceUpdate || (user.getFailedLoginAttempts() > 0)) {
6021                            user.setFailedLoginAttempts(0);
6022    
6023                            userPersistence.update(user);
6024                    }
6025            }
6026    
6027            protected BaseModelSearchResult<User> searchUsers(
6028                            SearchContext searchContext)
6029                    throws PortalException {
6030    
6031                    Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
6032                            User.class);
6033    
6034                    for (int i = 0; i < 10; i++) {
6035                            Hits hits = indexer.search(searchContext);
6036    
6037                            List<User> users = UsersAdminUtil.getUsers(hits);
6038    
6039                            if (users != null) {
6040                                    return new BaseModelSearchResult<>(users, hits.getLength());
6041                            }
6042                    }
6043    
6044                    throw new SearchException(
6045                            "Unable to fix the search index after 10 attempts");
6046            }
6047    
6048            protected void sendPasswordNotification(
6049                    User user, long companyId, String newPassword, String passwordResetURL,
6050                    String fromName, String fromAddress, String subject, String body,
6051                    ServiceContext serviceContext) {
6052    
6053                    if (Validator.isNull(fromName)) {
6054                            fromName = PrefsPropsUtil.getString(
6055                                    companyId, PropsKeys.ADMIN_EMAIL_FROM_NAME);
6056                    }
6057    
6058                    if (Validator.isNull(fromAddress)) {
6059                            fromAddress = PrefsPropsUtil.getString(
6060                                    companyId, PropsKeys.ADMIN_EMAIL_FROM_ADDRESS);
6061                    }
6062    
6063                    String toName = user.getFullName();
6064                    String toAddress = user.getEmailAddress();
6065    
6066                    PortletPreferences companyPortletPreferences =
6067                            PrefsPropsUtil.getPreferences(companyId, true);
6068    
6069                    Map<Locale, String> localizedSubjectMap = null;
6070                    Map<Locale, String> localizedBodyMap = null;
6071    
6072                    String bodyProperty = null;
6073                    String prefix = null;
6074                    String subjectProperty = null;
6075    
6076                    if (Validator.isNotNull(passwordResetURL)) {
6077                            bodyProperty = PropsKeys.ADMIN_EMAIL_PASSWORD_RESET_BODY;
6078                            prefix = "adminEmailPasswordReset";
6079                            subjectProperty = PropsKeys.ADMIN_EMAIL_PASSWORD_RESET_SUBJECT;
6080                    }
6081                    else {
6082                            bodyProperty = PropsKeys.ADMIN_EMAIL_PASSWORD_SENT_BODY;
6083                            prefix = "adminEmailPasswordSent";
6084                            subjectProperty = PropsKeys.ADMIN_EMAIL_PASSWORD_SENT_SUBJECT;
6085                    }
6086    
6087                    if (Validator.isNull(body)) {
6088                            localizedBodyMap = LocalizationUtil.getLocalizationMap(
6089                                    companyPortletPreferences, prefix + "Body", bodyProperty);
6090                    }
6091    
6092                    if (Validator.isNull(subject)) {
6093                            localizedSubjectMap = LocalizationUtil.getLocalizationMap(
6094                                    companyPortletPreferences, prefix + "Subject", subjectProperty);
6095                    }
6096    
6097                    SubscriptionSender subscriptionSender = new SubscriptionSender();
6098    
6099                    subscriptionSender.setCompanyId(companyId);
6100                    subscriptionSender.setContextAttributes(
6101                            "[$PASSWORD_RESET_URL$]", passwordResetURL, "[$REMOTE_ADDRESS$]",
6102                            serviceContext.getRemoteAddr(), "[$REMOTE_HOST$]",
6103                            serviceContext.getRemoteHost(), "[$USER_ID$]", user.getUserId(),
6104                            "[$USER_PASSWORD$]", newPassword, "[$USER_SCREENNAME$]",
6105                            user.getScreenName());
6106                    subscriptionSender.setFrom(fromAddress, fromName);
6107                    subscriptionSender.setHtmlFormat(true);
6108                    subscriptionSender.setLocalizedBodyMap(localizedBodyMap);
6109                    subscriptionSender.setLocalizedSubjectMap(localizedSubjectMap);
6110                    subscriptionSender.setMailId("user", user.getUserId());
6111                    subscriptionSender.setServiceContext(serviceContext);
6112    
6113                    subscriptionSender.addRuntimeSubscribers(toAddress, toName);
6114    
6115                    subscriptionSender.flushNotificationsAsync();
6116            }
6117    
6118            protected void setEmailAddress(
6119                            User user, String password, String firstName, String middleName,
6120                            String lastName, String emailAddress)
6121                    throws PortalException {
6122    
6123                    if (StringUtil.equalsIgnoreCase(emailAddress, user.getEmailAddress())) {
6124                            return;
6125                    }
6126    
6127                    long userId = user.getUserId();
6128    
6129                    // test@test.com -> test@liferay.com
6130    
6131                    if (!user.hasCompanyMx() && user.hasCompanyMx(emailAddress) &&
6132                            Validator.isNotNull(password)) {
6133    
6134                            mailService.addUser(
6135                                    user.getCompanyId(), userId, password, firstName, middleName,
6136                                    lastName, emailAddress);
6137                    }
6138    
6139                    // test@liferay.com -> bob@liferay.com
6140    
6141                    else if (user.hasCompanyMx() && user.hasCompanyMx(emailAddress)) {
6142                            mailService.updateEmailAddress(
6143                                    user.getCompanyId(), userId, emailAddress);
6144                    }
6145    
6146                    // test@liferay.com -> test@test.com
6147    
6148                    else if (user.hasCompanyMx() && !user.hasCompanyMx(emailAddress)) {
6149                            mailService.deleteEmailAddress(user.getCompanyId(), userId);
6150                    }
6151    
6152                    user.setEmailAddress(emailAddress);
6153                    user.setDigest(StringPool.BLANK);
6154            }
6155    
6156            protected void updateGroups(
6157                            long userId, long[] newGroupIds, ServiceContext serviceContext,
6158                            boolean indexingEnabled)
6159                    throws PortalException {
6160    
6161                    if (newGroupIds == null) {
6162                            return;
6163                    }
6164    
6165                    long[] oldGroupIds = getGroupPrimaryKeys(userId);
6166    
6167                    for (long oldGroupId : oldGroupIds) {
6168                            if (!ArrayUtil.contains(newGroupIds, oldGroupId)) {
6169                                    unsetGroupUsers(
6170                                            oldGroupId, new long[] {userId}, serviceContext);
6171                            }
6172                    }
6173    
6174                    for (long newGroupId : newGroupIds) {
6175                            if (!ArrayUtil.contains(oldGroupIds, newGroupId)) {
6176                                    addGroupUsers(newGroupId, new long[] {userId});
6177                            }
6178                    }
6179    
6180                    if (indexingEnabled) {
6181                            reindex(userId);
6182                    }
6183    
6184                    PermissionCacheUtil.clearCache(userId);
6185            }
6186    
6187            protected void updateOrganizations(
6188                            long userId, long[] newOrganizationIds, boolean indexingEnabled)
6189                    throws PortalException {
6190    
6191                    if (newOrganizationIds == null) {
6192                            return;
6193                    }
6194    
6195                    long[] oldOrganizationIds = getOrganizationPrimaryKeys(userId);
6196    
6197                    for (long oldOrganizationId : oldOrganizationIds) {
6198                            if (!ArrayUtil.contains(newOrganizationIds, oldOrganizationId)) {
6199                                    unsetOrganizationUsers(oldOrganizationId, new long[] {userId});
6200                            }
6201                    }
6202    
6203                    for (long newOrganizationId : newOrganizationIds) {
6204                            if (!ArrayUtil.contains(oldOrganizationIds, newOrganizationId)) {
6205                                    addOrganizationUsers(newOrganizationId, new long[] {userId});
6206                            }
6207                    }
6208    
6209                    if (indexingEnabled) {
6210                            reindex(userId);
6211                    }
6212    
6213                    PermissionCacheUtil.clearCache(userId);
6214            }
6215    
6216            protected void updateUserGroupRoles(
6217                            User user, long[] groupIds, long[] organizationIds,
6218                            List<UserGroupRole> userGroupRoles,
6219                            List<UserGroupRole> previousUserGroupRoles)
6220                    throws PortalException {
6221    
6222                    if (userGroupRoles == null) {
6223                            return;
6224                    }
6225    
6226                    userGroupRoles = new ArrayList<>(userGroupRoles);
6227    
6228                    for (UserGroupRole userGroupRole : previousUserGroupRoles) {
6229                            if (userGroupRoles.contains(userGroupRole)) {
6230                                    userGroupRoles.remove(userGroupRole);
6231                            }
6232                            else {
6233                                    userGroupRoleLocalService.deleteUserGroupRole(userGroupRole);
6234                            }
6235                    }
6236    
6237                    if (ListUtil.isEmpty(userGroupRoles)) {
6238                            return;
6239                    }
6240    
6241                    long[] validGroupIds = null;
6242    
6243                    if (groupIds != null) {
6244                            validGroupIds = ArrayUtil.clone(groupIds);
6245                    }
6246                    else {
6247                            validGroupIds = user.getGroupIds();
6248                    }
6249    
6250                    if (organizationIds == null) {
6251                            organizationIds = user.getOrganizationIds();
6252                    }
6253    
6254                    for (long organizationId : organizationIds) {
6255                            Organization organization =
6256                                    organizationPersistence.findByPrimaryKey(organizationId);
6257    
6258                            validGroupIds = ArrayUtil.append(
6259                                    validGroupIds, organization.getGroupId());
6260                    }
6261    
6262                    Arrays.sort(validGroupIds);
6263    
6264                    for (UserGroupRole userGroupRole : userGroupRoles) {
6265                            if (Arrays.binarySearch(
6266                                            validGroupIds, userGroupRole.getGroupId()) >= 0) {
6267    
6268                                    userGroupRoleLocalService.addUserGroupRole(userGroupRole);
6269                            }
6270                    }
6271            }
6272    
6273            protected void validate(
6274                            long companyId, long userId, boolean autoPassword, String password1,
6275                            String password2, boolean autoScreenName, String screenName,
6276                            String emailAddress, String openId, String firstName,
6277                            String middleName, String lastName, long[] organizationIds,
6278                            Locale locale)
6279                    throws PortalException {
6280    
6281                    validateCompanyMaxUsers(companyId);
6282    
6283                    if (!autoScreenName) {
6284                            validateScreenName(companyId, userId, screenName);
6285                    }
6286    
6287                    if (!autoPassword) {
6288                            PasswordPolicy passwordPolicy =
6289                                    passwordPolicyLocalService.getDefaultPasswordPolicy(companyId);
6290    
6291                            PwdToolkitUtil.validate(
6292                                    companyId, 0, password1, password2, passwordPolicy);
6293                    }
6294    
6295                    validateEmailAddress(companyId, emailAddress);
6296    
6297                    if (Validator.isNotNull(emailAddress)) {
6298                            User user = userPersistence.fetchByC_EA(companyId, emailAddress);
6299    
6300                            if ((user != null) && (user.getUserId() != userId)) {
6301                                    throw new UserEmailAddressException.MustNotBeDuplicate(
6302                                            userId, emailAddress);
6303                            }
6304                    }
6305    
6306                    validateOpenId(companyId, userId, openId);
6307    
6308                    validateFullName(companyId, firstName, middleName, lastName, locale);
6309    
6310                    if (organizationIds != null) {
6311                            for (long organizationId : organizationIds) {
6312                                    Organization organization =
6313                                            organizationPersistence.fetchByPrimaryKey(organizationId);
6314    
6315                                    if (organization == null) {
6316                                            throw new NoSuchOrganizationException(
6317                                                    "{organizationId=" + organizationId + "}");
6318                                    }
6319                            }
6320                    }
6321            }
6322    
6323            protected void validate(
6324                            long userId, String screenName, String emailAddress, String openId,
6325                            String firstName, String middleName, String lastName, String smsSn,
6326                            Locale locale)
6327                    throws PortalException {
6328    
6329                    User user = userPersistence.findByPrimaryKey(userId);
6330    
6331                    if (!StringUtil.equalsIgnoreCase(user.getScreenName(), screenName)) {
6332                            validateScreenName(user.getCompanyId(), userId, screenName);
6333                    }
6334    
6335                    validateEmailAddress(user.getCompanyId(), emailAddress);
6336    
6337                    validateOpenId(user.getCompanyId(), userId, openId);
6338    
6339                    if (!user.isDefaultUser()) {
6340                            if (Validator.isNotNull(emailAddress) &&
6341                                    !StringUtil.equalsIgnoreCase(
6342                                            user.getEmailAddress(), emailAddress)) {
6343    
6344                                    if (userPersistence.fetchByC_EA(
6345                                                    user.getCompanyId(), emailAddress) != null) {
6346    
6347                                            throw new UserEmailAddressException.MustNotBeDuplicate(
6348                                                    userId, emailAddress);
6349                                    }
6350                            }
6351    
6352                            validateFullName(
6353                                    user.getCompanyId(), firstName, middleName, lastName, locale);
6354                    }
6355    
6356                    if (Validator.isNotNull(smsSn) && !Validator.isEmailAddress(smsSn)) {
6357                            throw new UserSmsException.MustBeEmailAddress(smsSn);
6358                    }
6359            }
6360    
6361            protected void validateCompanyMaxUsers(long companyId)
6362                    throws PortalException {
6363    
6364                    Company company = companyPersistence.findByPrimaryKey(companyId);
6365    
6366                    if (company.isSystem() || (company.getMaxUsers() == 0)) {
6367                            return;
6368                    }
6369    
6370                    int userCount = searchCount(
6371                            companyId, null, WorkflowConstants.STATUS_APPROVED, null);
6372    
6373                    if (userCount >= company.getMaxUsers()) {
6374                            throw new CompanyMaxUsersException();
6375                    }
6376            }
6377    
6378            protected void validateEmailAddress(long companyId, String emailAddress)
6379                    throws PortalException {
6380    
6381                    if (Validator.isNull(emailAddress) &&
6382                            !PropsValues.USERS_EMAIL_ADDRESS_REQUIRED) {
6383    
6384                            return;
6385                    }
6386    
6387                    EmailAddressValidator emailAddressValidator =
6388                            EmailAddressValidatorFactory.getInstance();
6389    
6390                    if (!emailAddressValidator.validate(companyId, emailAddress)) {
6391                            throw new UserEmailAddressException.MustValidate(
6392                                    emailAddress, emailAddressValidator);
6393                    }
6394    
6395                    String pop3User = PrefsPropsUtil.getString(
6396                            PropsKeys.MAIL_SESSION_MAIL_POP3_USER,
6397                            PropsValues.MAIL_SESSION_MAIL_POP3_USER);
6398    
6399                    if (StringUtil.equalsIgnoreCase(emailAddress, pop3User)) {
6400                            throw new UserEmailAddressException.MustNotBePOP3User(emailAddress);
6401                    }
6402    
6403                    String[] reservedEmailAddresses = PrefsPropsUtil.getStringArray(
6404                            companyId, PropsKeys.ADMIN_RESERVED_EMAIL_ADDRESSES,
6405                            StringPool.NEW_LINE, PropsValues.ADMIN_RESERVED_EMAIL_ADDRESSES);
6406    
6407                    for (String reservedEmailAddress : reservedEmailAddresses) {
6408                            if (StringUtil.equalsIgnoreCase(
6409                                            emailAddress, reservedEmailAddress)) {
6410    
6411                                    throw new UserEmailAddressException.MustNotBeReserved(
6412                                            emailAddress, reservedEmailAddresses);
6413                            }
6414                    }
6415            }
6416    
6417            protected void validateEmailAddress(
6418                            User user, String emailAddress1, String emailAddress2)
6419                    throws PortalException {
6420    
6421                    if (!emailAddress1.equals(emailAddress2)) {
6422                            throw new UserEmailAddressException.MustBeEqual(
6423                                    user, emailAddress1, emailAddress2);
6424                    }
6425    
6426                    validateEmailAddress(user.getCompanyId(), emailAddress1);
6427                    validateEmailAddress(user.getCompanyId(), emailAddress2);
6428    
6429                    if (!StringUtil.equalsIgnoreCase(
6430                                    emailAddress1, user.getEmailAddress())) {
6431    
6432                            if (userPersistence.fetchByC_EA(
6433                                            user.getCompanyId(), emailAddress1) != null) {
6434    
6435                                    throw new UserEmailAddressException.MustNotBeDuplicate(
6436                                            user.getUserId(), emailAddress1);
6437                            }
6438                    }
6439            }
6440    
6441            protected void validateFullName(
6442                            long companyId, String firstName, String middleName,
6443                            String lastName, Locale locale)
6444                    throws PortalException {
6445    
6446                    FullNameDefinition fullNameDefinition =
6447                            FullNameDefinitionFactory.getInstance(locale);
6448    
6449                    if (Validator.isNull(firstName)) {
6450                            throw new ContactNameException.MustHaveFirstName();
6451                    }
6452                    else if (Validator.isNull(middleName) &&
6453                                     fullNameDefinition.isFieldRequired("middle-name")) {
6454    
6455                            throw new ContactNameException.MustHaveMiddleName();
6456                    }
6457                    else if (Validator.isNull(lastName) &&
6458                                     fullNameDefinition.isFieldRequired("last-name")) {
6459    
6460                            throw new ContactNameException.MustHaveLastName();
6461                    }
6462    
6463                    FullNameValidator fullNameValidator =
6464                            FullNameValidatorFactory.getInstance();
6465    
6466                    if (!fullNameValidator.validate(
6467                                    companyId, firstName, middleName, lastName)) {
6468    
6469                            throw new ContactNameException.MustHaveValidFullName(
6470                                    fullNameValidator);
6471                    }
6472            }
6473    
6474            protected void validateOpenId(long companyId, long userId, String openId)
6475                    throws PortalException {
6476    
6477                    if (Validator.isNull(openId)) {
6478                            return;
6479                    }
6480    
6481                    User user = userPersistence.fetchByC_O(companyId, openId);
6482    
6483                    if ((user != null) && (user.getUserId() != userId)) {
6484                            throw new DuplicateOpenIdException("{userId=" + userId + "}");
6485                    }
6486            }
6487    
6488            protected void validatePassword(
6489                            long companyId, long userId, String password1, String password2)
6490                    throws PortalException {
6491    
6492                    if (Validator.isNull(password1) || Validator.isNull(password2)) {
6493                            throw new UserPasswordException.MustNotBeNull(userId);
6494                    }
6495    
6496                    if (!password1.equals(password2)) {
6497                            throw new UserPasswordException.MustMatch(userId);
6498                    }
6499    
6500                    PasswordPolicy passwordPolicy =
6501                            passwordPolicyLocalService.getPasswordPolicyByUserId(userId);
6502    
6503                    PwdToolkitUtil.validate(
6504                            companyId, userId, password1, password2, passwordPolicy);
6505            }
6506    
6507            protected void validateReminderQuery(String question, String answer)
6508                    throws PortalException {
6509    
6510                    if (!PropsValues.USERS_REMINDER_QUERIES_ENABLED) {
6511                            return;
6512                    }
6513    
6514                    if (Validator.isNull(question)) {
6515                            throw new UserReminderQueryException("Question is null");
6516                    }
6517    
6518                    if (Validator.isNull(answer)) {
6519                            throw new UserReminderQueryException("Answer is null");
6520                    }
6521            }
6522    
6523            protected void validateScreenName(
6524                            long companyId, long userId, String screenName)
6525                    throws PortalException {
6526    
6527                    if (Validator.isNull(screenName)) {
6528                            throw new UserScreenNameException.MustNotBeNull(userId);
6529                    }
6530    
6531                    ScreenNameValidator screenNameValidator =
6532                            ScreenNameValidatorFactory.getInstance();
6533    
6534                    if (!screenNameValidator.validate(companyId, screenName)) {
6535                            throw new UserScreenNameException.MustValidate(
6536                                    userId, screenName, screenNameValidator);
6537                    }
6538    
6539                    if (Validator.isNumber(screenName)) {
6540                            if (!PropsValues.USERS_SCREEN_NAME_ALLOW_NUMERIC) {
6541                                    throw new UserScreenNameException.MustNotBeNumeric(
6542                                            userId, screenName);
6543                            }
6544    
6545                            if (!screenName.equals(String.valueOf(userId))) {
6546                                    Group group = groupPersistence.fetchByPrimaryKey(
6547                                            GetterUtil.getLong(screenName));
6548    
6549                                    if (group != null) {
6550                                            throw new UserScreenNameException.MustNotBeUsedByGroup(
6551                                                    userId, screenName, group);
6552                                    }
6553                            }
6554                    }
6555    
6556                    String[] anonymousNames = BaseServiceImpl.ANONYMOUS_NAMES;
6557    
6558                    for (String anonymousName : anonymousNames) {
6559                            if (StringUtil.equalsIgnoreCase(screenName, anonymousName)) {
6560                                    throw new UserScreenNameException.MustNotBeReservedForAnonymous(
6561                                            userId, screenName, anonymousNames);
6562                            }
6563                    }
6564    
6565                    User user = userPersistence.fetchByC_SN(companyId, screenName);
6566    
6567                    if ((user != null) && (user.getUserId() != userId)) {
6568                            throw new UserScreenNameException.MustNotBeDuplicate(
6569                                    user.getUserId(), screenName);
6570                    }
6571    
6572                    String friendlyURL = StringPool.SLASH + screenName;
6573    
6574                    Group group = groupPersistence.fetchByC_F(companyId, friendlyURL);
6575    
6576                    if ((group != null) && (group.getClassPK() != userId)) {
6577                            GroupFriendlyURLException gfurle = new GroupFriendlyURLException(
6578                                    GroupFriendlyURLException.DUPLICATE);
6579    
6580                            gfurle.setDuplicateClassPK(group.getGroupId());
6581                            gfurle.setDuplicateClassName(Group.class.getName());
6582    
6583                            throw gfurle;
6584                    }
6585    
6586                    int exceptionType = LayoutImpl.validateFriendlyURL(friendlyURL);
6587    
6588                    if (exceptionType != -1) {
6589                            throw new UserScreenNameException.MustProduceValidFriendlyURL(
6590                                    userId, screenName, exceptionType);
6591                    }
6592    
6593                    String[] reservedScreenNames = PrefsPropsUtil.getStringArray(
6594                            companyId, PropsKeys.ADMIN_RESERVED_SCREEN_NAMES,
6595                            StringPool.NEW_LINE, PropsValues.ADMIN_RESERVED_SCREEN_NAMES);
6596    
6597                    for (String reservedScreenName : reservedScreenNames) {
6598                            if (StringUtil.equalsIgnoreCase(screenName, reservedScreenName)) {
6599                                    throw new UserScreenNameException.MustNotBeReserved(
6600                                            userId, screenName, reservedScreenNames);
6601                            }
6602                    }
6603            }
6604    
6605            @BeanReference(type = MailService.class)
6606            protected MailService mailService;
6607    
6608            private static final Log _log = LogFactoryUtil.getLog(
6609                    UserLocalServiceImpl.class);
6610    
6611            private final Map<Long, User> _defaultUsers = new ConcurrentHashMap<>();
6612    
6613    }