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