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