001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: https://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: https://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.ui.apps.user;
029
030import org.opencms.db.CmsUserSettings;
031import org.opencms.file.CmsGroup;
032import org.opencms.file.CmsObject;
033import org.opencms.file.CmsProject;
034import org.opencms.file.CmsResource;
035import org.opencms.file.CmsResourceFilter;
036import org.opencms.file.CmsUser;
037import org.opencms.main.CmsException;
038import org.opencms.main.CmsIllegalArgumentException;
039import org.opencms.main.CmsIllegalStateException;
040import org.opencms.main.CmsLog;
041import org.opencms.main.OpenCms;
042import org.opencms.security.CmsDefaultValidationHandler;
043import org.opencms.security.CmsOrganizationalUnit;
044import org.opencms.security.CmsPasswordInfo;
045import org.opencms.security.CmsRole;
046import org.opencms.security.CmsSecurityException;
047import org.opencms.security.CmsUserLog;
048import org.opencms.security.I_CmsPasswordHandler;
049import org.opencms.security.I_CmsPasswordSecurityEvaluator;
050import org.opencms.security.I_CmsPasswordSecurityEvaluator.SecurityLevel;
051import org.opencms.security.twofactor.CmsTwoFactorAuthenticationHandler;
052import org.opencms.site.CmsSite;
053import org.opencms.ui.A_CmsUI;
054import org.opencms.ui.CmsVaadinUtils;
055import org.opencms.ui.apps.CmsPageEditorConfiguration;
056import org.opencms.ui.apps.CmsSitemapEditorConfiguration;
057import org.opencms.ui.apps.I_CmsWorkplaceAppConfiguration;
058import org.opencms.ui.apps.Messages;
059import org.opencms.ui.components.CmsBasicDialog;
060import org.opencms.ui.components.CmsUserDataFormLayout;
061import org.opencms.ui.components.CmsUserDataFormLayout.EditLevel;
062import org.opencms.ui.components.OpenCmsTheme;
063import org.opencms.ui.components.fileselect.CmsPathSelectField;
064import org.opencms.ui.dialogs.permissions.CmsPrincipalSelect;
065import org.opencms.ui.dialogs.permissions.CmsPrincipalSelect.WidgetType;
066import org.opencms.ui.login.CmsLoginController;
067import org.opencms.ui.login.CmsPasswordForm;
068import org.opencms.util.CmsStringUtil;
069import org.opencms.util.CmsUUID;
070
071import java.util.ArrayList;
072import java.util.Arrays;
073import java.util.Collections;
074import java.util.Iterator;
075import java.util.List;
076import java.util.Locale;
077import java.util.Objects;
078
079import org.apache.commons.logging.Log;
080import org.apache.commons.mail2.core.EmailException;
081
082import com.vaadin.data.provider.DataProvider;
083import com.vaadin.data.provider.ListDataProvider;
084import com.vaadin.server.UserError;
085import com.vaadin.ui.Button;
086import com.vaadin.ui.Button.ClickEvent;
087import com.vaadin.ui.Button.ClickListener;
088import com.vaadin.ui.Component;
089import com.vaadin.ui.FormLayout;
090import com.vaadin.ui.TabSheet;
091import com.vaadin.ui.TabSheet.SelectedTabChangeEvent;
092import com.vaadin.ui.TabSheet.SelectedTabChangeListener;
093import com.vaadin.ui.Window;
094import com.vaadin.v7.data.Item;
095import com.vaadin.v7.data.Property.ValueChangeEvent;
096import com.vaadin.v7.data.Property.ValueChangeListener;
097import com.vaadin.v7.data.Validator;
098import com.vaadin.v7.data.Validator.InvalidValueException;
099import com.vaadin.v7.data.util.IndexedContainer;
100import com.vaadin.v7.ui.CheckBox;
101import com.vaadin.v7.ui.ComboBox;
102import com.vaadin.v7.ui.Label;
103import com.vaadin.v7.ui.TextArea;
104import com.vaadin.v7.ui.TextField;
105
106/**
107 * Class for the dialog to edit user settings.<p>
108 */
109@SuppressWarnings("deprecation")
110public class CmsUserEditDialog extends CmsBasicDialog implements I_CmsPasswordFetcher {
111
112    /**
113     * Validator for the eamil field.<p>
114     */
115    class EmailValidator implements Validator {
116
117        /**vaadin serial id.*/
118        private static final long serialVersionUID = 8943898736907290076L;
119
120        /**
121         * @see com.vaadin.v7.data.Validator#validate(java.lang.Object)
122         */
123        public void validate(Object value) throws InvalidValueException {
124
125            if (value == null) {
126                throw new InvalidValueException(
127                    CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_USER_VALIDATION_EMAIL_EMPTY_0));
128            }
129            try {
130                CmsUser.checkEmail((String)value);
131            } catch (CmsIllegalArgumentException e) {
132                throw new InvalidValueException(
133                    CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_USER_VALIDATION_EMAIL_INVALID_0));
134            }
135        }
136    }
137
138    /**
139     * Validator for the login name field.<p>
140     */
141    class LoginNameValidator implements Validator {
142
143        /**vaadin serial id.*/
144        private static final long serialVersionUID = -6768717591898665618L;
145
146        /**
147         * @see com.vaadin.v7.data.Validator#validate(java.lang.Object)
148         */
149        public void validate(Object value) throws InvalidValueException {
150
151            if (value == null) {
152                throw new InvalidValueException(
153                    CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_USER_VALIDATION_LOGINNAME_EMPTY_0));
154            }
155
156            try {
157                CmsDefaultValidationHandler handler = new CmsDefaultValidationHandler();
158                handler.checkUserName((String)value);
159            } catch (CmsIllegalArgumentException e) {
160                throw new InvalidValueException(
161                    CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_USER_VALIDATION_LOGINNAME_INVALID_0));
162            }
163
164            if (userAlreadyExists((String)value)) {
165                throw new InvalidValueException(
166                    CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_USER_VALIDATION_LOGINNAME_DOUBLE_0));
167            }
168        }
169    }
170
171    /**
172     * Validator for password fields.<p>
173     */
174    class PasswordValidator implements Validator {
175
176        /**vaadin serial id.*/
177        private static final long serialVersionUID = 64216980175982548L;
178
179        /**
180         * @see com.vaadin.v7.data.Validator#validate(java.lang.Object)
181         */
182        public void validate(Object value) throws InvalidValueException {
183
184            if (isPasswordMismatchingConfirm()) {
185                throw new InvalidValueException(
186                    CmsVaadinUtils.getMessageText(
187                        Messages.GUI_USERMANAGEMENT_USER_VALIDATION_PASSWORD_NOT_EQUAL_CONFIRM_0));
188            }
189
190            if (!isNewUser()) {
191                if ((value == null) | CmsStringUtil.isEmptyOrWhitespaceOnly((String)value)) {
192                    return; //ok, password was not changed for existing user
193                }
194            }
195
196            if (!isPasswordValid()) {
197                throw new InvalidValueException(
198                    CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_USER_VALIDATION_PASSWORD_INVALID_0));
199            }
200        }
201    }
202
203    /**
204     * Validator for start view and start site field.<p>
205     */
206    class StartPathValidator implements Validator {
207
208        /**vaadin serial id.*/
209        private static final long serialVersionUID = -4257155941690487831L;
210
211        /**
212         * @see com.vaadin.v7.data.Validator#validate(java.lang.Object)
213         */
214        public void validate(Object value) throws InvalidValueException {
215
216            if (!m_visSites) {
217                return;
218            }
219            if (!isSiteNull()) {
220                if (!isSitePathValid()) {
221                    throw new InvalidValueException(
222                        CmsVaadinUtils.getMessageText(
223                            Messages.GUI_USERMANAGEMENT_USER_VALIDATION_START_PATH_NOT_VALID_0));
224
225                }
226            }
227
228        }
229    }
230
231    /**
232     * Validator for start project.<p>
233     */
234    class StartProjectValidator implements Validator {
235
236        /** Serialization id. */
237        private static final long serialVersionUID = 7117548227591179638L;
238
239        /** The invalid value. */
240        private String m_invalidProject;
241
242        /**
243         * Creates the validator.
244         * @param invalidProject the project to treat as invalid.
245         */
246        public StartProjectValidator(String invalidProject) {
247
248            m_invalidProject = invalidProject;
249        }
250
251        /**
252         * @see com.vaadin.v7.data.Validator#validate(java.lang.Object)
253         */
254        public void validate(Object value) throws InvalidValueException {
255
256            if (Objects.equals(String.valueOf(value), m_invalidProject)) {
257                throw new InvalidValueException(
258                    CmsVaadinUtils.getMessageText(
259                        Messages.GUI_USERMANAGEMENT_USER_VALIDATION_START_PROJECT_NOT_EXISTING_0));
260            }
261        }
262    }
263
264    /**
265     * Validator for start view and start site field.<p>
266     */
267    class StartSiteValidator implements Validator {
268
269        /**vaadin serial id.*/
270        private static final long serialVersionUID = -4257155941690487831L;
271
272        /**
273         * @see com.vaadin.v7.data.Validator#validate(java.lang.Object)
274         */
275        public void validate(Object value) throws InvalidValueException {
276
277            if (!m_visSites) {
278                return;
279            }
280            if (isSiteNull()) {
281                throw new InvalidValueException(
282                    CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_USER_VALIDATION_STARTSITE_EMPTY_0));
283
284            }
285
286        }
287    }
288
289    /**
290     * Validator for start view and start site field.<p>
291     */
292    class StartViewValidator implements Validator {
293
294        /**vaadin serial id.*/
295        private static final long serialVersionUID = -4257155941690487831L;
296
297        /**
298         * @see com.vaadin.v7.data.Validator#validate(java.lang.Object)
299         */
300        public void validate(Object value) throws InvalidValueException {
301
302            if (!isSiteNull()) {
303
304                if (isRootSiteSelected() & !isStartViewAvailableOnRoot()) {
305                    throw new InvalidValueException(
306                        CmsVaadinUtils.getMessageText(
307                            Messages.GUI_USERMANAGEMENT_USER_VALIDATION_STARTVIEW_NOTFORROOT_0));
308                }
309
310            }
311        }
312    }
313
314    /** The log object for this class. */
315    private static final Log LOG = CmsLog.getLog(CmsUserEditDialog.class);
316
317    /**vaadin serial id.*/
318    private static final long serialVersionUID = -5198443053070008413L;
319
320    /**Visible sites? */
321    protected boolean m_visSites = true;
322
323    /**Flag indicates is user is in webou. */
324    boolean m_isWebOU;
325
326    /**Password form. */
327    CmsPasswordForm m_pw;
328
329    /**vaadin component.*/
330    ComboBox m_site;
331
332    /**vaadin component.*/
333    CmsPathSelectField m_startfolder;
334
335    /** The app instance. */
336    private CmsAccountsApp m_app;
337
338    /**vaadin component.*/
339    private Button m_cancel;
340
341    /**CmsObject. */
342    private CmsObject m_cms;
343
344    /**vaadin component.*/
345    private TextArea m_description;
346
347    /** Label containing invisible dummy password fields to dissuade Firefox from saving the password *after* the user edit dialog. */
348    private Label m_dummyPasswordLabel;
349
350    /**User edit parameter. */
351    private CmsUserEditParameters m_editParams = new CmsUserEditParameters();
352
353    /**vaadin component.*/
354    private CheckBox m_enabled;
355
356    /**vaadin component. */
357    private CheckBox m_forceResetPassword;
358
359    /**Vaadin component. */
360    private Button m_generateButton;
361
362    /**Select view for principals.*/
363    private CmsPrincipalSelect m_group;
364
365    /**vaadin component.*/
366    private ComboBox m_language;
367
368    /**vaadin component.*/
369    private TextField m_loginname;
370
371    /**Flag indicates if name was empty. */
372    private boolean m_name_was_empty;
373
374    /**vaadin component. */
375    private Button m_next;
376
377    /**vaadin component.*/
378    private Button m_ok;
379
380    /**vaadin component.*/
381    private Label m_ou;
382
383    private PasswordValidator m_passwordValidator = new PasswordValidator();
384
385    /**vaadin component.*/
386    private ComboBox m_project;
387
388    /** Check box for resetting 2FA information. */
389    private CheckBox m_resetTwoFactorAuthentication;
390
391    /**vaadin component. */
392    private ComboBox m_role;
393
394    /**vaadin component.*/
395    private CheckBox m_selfmanagement;
396
397    /**vaadin component. */
398    private CheckBox m_sendEmail;
399
400    /**vaadin component.*/
401    private ComboBox m_startview;
402
403    /**vaadin component.*/
404    private TabSheet m_tab;
405
406    private com.vaadin.ui.Label m_twoFactorAuthState;
407
408    private FormLayout m_twoFactorBox;
409
410    /**vaadin component.*/
411    private CmsUser m_user;
412
413    /**User data form.<p>*/
414    private CmsUserDataFormLayout m_userdata;
415
416    /**
417     * public constructor.<p>
418     *
419     * @param cms CmsObject
420     * @param userId id of user
421     * @param window to be closed
422     * @param app account app instance
423     */
424    public CmsUserEditDialog(CmsObject cms, CmsUUID userId, final Window window, final CmsAccountsApp app) {
425
426        CmsVaadinUtils.readAndLocalizeDesign(this, CmsVaadinUtils.getWpMessagesForCurrentLocale(), null);
427        setPasswordFields();
428        try {
429            m_cms = OpenCms.initCmsObject(cms);
430            m_app = app;
431            m_startfolder.disableSiteSwitch();
432            m_startfolder.setResourceFilter(CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireFolder());
433            m_user = m_cms.readUser(userId);
434            m_editParams = app.getUserEditParameters(m_user);
435            if (m_user.isWebuser()) {
436                m_sendEmail.setVisible(false);
437                m_sendEmail.setValue(Boolean.FALSE);
438                m_forceResetPassword.setVisible(false);
439                m_forceResetPassword.setValue(Boolean.FALSE);
440                m_selfmanagement.setVisible(false);
441                m_selfmanagement.setValue(Boolean.FALSE);
442                m_isWebOU = true;
443            } else {
444                m_selfmanagement.setValue(Boolean.valueOf(true));
445            }
446
447            displayResourceInfoDirectly(Collections.singletonList(CmsAccountsApp.getPrincipalInfo(m_user)));
448            m_group.setVisible(false);
449            m_role.setVisible(false);
450            m_loginname.setValue(m_user.getSimpleName());
451            m_loginname.setEnabled(false);
452            m_ou.setValue(m_user.getOuFqn().isEmpty() ? "/" : m_user.getOuFqn());
453
454            m_description.setValue(m_user.getDescription());
455            m_selfmanagement.setValue(Boolean.valueOf(!m_user.isManaged()));
456            m_enabled.setValue(Boolean.valueOf(m_user.isEnabled()));
457            CmsUserSettings settings = new CmsUserSettings(m_user);
458            init(window, app, settings, m_editParams.isEditEnabled());
459            m_sendEmail.setEnabled(false);
460            m_forceResetPassword.setValue(
461                m_user.getAdditionalInfo().get(CmsUserSettings.ADDITIONAL_INFO_PASSWORD_RESET) != null);
462            m_next.setVisible(false);
463            setupStartFolder(settings.getStartFolder());
464
465            m_loginname.setEnabled(false);
466
467            if (!m_editParams.isEditEnabled()) {
468                m_description.setEnabled(false);
469            }
470            if (!m_editParams.isPasswordChangeEnabled()) {
471                m_pw.setVisible(false);
472                m_forceResetPassword.setVisible(false);
473                m_sendEmail.setVisible(false);
474                m_generateButton.setVisible(false);
475            }
476
477            CmsTwoFactorAuthenticationHandler twoFactorHandler = OpenCms.getTwoFactorAuthenticationHandler();
478            if (twoFactorHandler.needsTwoFactorAuthentication(m_user)) {
479                m_twoFactorBox.setVisible(true);
480                if (!twoFactorHandler.hasSecondFactor(m_user)) {
481                    m_resetTwoFactorAuthentication.setEnabled(false);
482                    m_twoFactorAuthState.setValue(
483                        CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_2FA_NOT_SET_UP_0));
484                } else {
485                    m_twoFactorAuthState.setValue(
486                        CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_2FA_USED_0));
487                    m_resetTwoFactorAuthentication.setEnabled(true);
488                }
489            } else {
490                m_twoFactorBox.setVisible(false);
491            }
492
493        } catch (CmsException e) {
494            LOG.error("Can't read user", e);
495        }
496    }
497
498    /**
499     * public constructor for new user case.<p>
500     *
501     * @param cms CmsObject
502     * @param window Window
503     * @param ou organizational unit
504     * @param app accounts app instance
505     */
506    public CmsUserEditDialog(CmsObject cms, final Window window, String ou, final CmsAccountsApp app) {
507
508        CmsVaadinUtils.readAndLocalizeDesign(this, CmsVaadinUtils.getWpMessagesForCurrentLocale(), null);
509        CmsOrganizationalUnit myOu = null;
510        try {
511            m_app = app;
512            m_cms = OpenCms.initCmsObject(cms);
513            myOu = OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, ou);
514
515            m_isWebOU = false;
516            m_sendEmail.setValue(Boolean.TRUE);
517            m_forceResetPassword.setValue(Boolean.TRUE);
518            if (myOu.hasFlagWebuser()) {
519                m_role.setVisible(false);
520                m_sendEmail.setVisible(false);
521                m_sendEmail.setValue(Boolean.FALSE);
522                m_forceResetPassword.setVisible(false);
523                m_forceResetPassword.setValue(Boolean.FALSE);
524                m_selfmanagement.setVisible(false);
525                m_selfmanagement.setValue(Boolean.FALSE);
526                m_isWebOU = true;
527            } else {
528                iniRole(m_cms, ou, m_role, LOG, true);
529                m_role.select(CmsRole.EDITOR.forOrgUnit(ou));
530                m_selfmanagement.setValue(Boolean.valueOf(true));
531
532            }
533        } catch (CmsException e) {
534            LOG.error("Unable to read OU", e);
535        }
536        setPasswordFields();
537        m_ou.setValue(ou.isEmpty() ? "/" : ou);
538        m_group.setWidgetType(WidgetType.groupwidget);
539        try {
540            CmsGroup group = m_cms.readGroup(ou + OpenCms.getDefaultUsers().getGroupUsers());
541            m_group.setValue(group.getName());
542        } catch (CmsException e1) {
543            //There is no user group -> ok, keep field empty
544        }
545        m_group.setRealPrincipalsOnly(true);
546        m_group.setOU(m_ou.getValue());
547        try {
548            m_group.setIncludeWebOus(OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, ou).hasFlagWebuser());
549        } catch (CmsException e) {
550            //
551        }
552        m_twoFactorBox.setVisible(false);
553
554        m_enabled.setValue(Boolean.TRUE);
555
556        init(window, app, null, true);
557        setupStartFolder(null);
558
559        m_tab.addSelectedTabChangeListener(new SelectedTabChangeListener() {
560
561            private static final long serialVersionUID = -2579639520410382246L;
562
563            public void selectedTabChange(SelectedTabChangeEvent event) {
564
565                setButtonVisibility();
566
567            }
568        });
569        setButtonVisibility();
570    }
571
572    /**
573     * Initialized the role ComboBox. (Vaadin 8 version)<p>
574     *
575     * @param cms CmsObject
576     * @param ou to load roles for
577     * @param roleComboBox ComboBox
578     * @param log LOG
579     */
580    protected static void iniRole(CmsObject cms, String ou, com.vaadin.ui.ComboBox<CmsRole> roleComboBox, Log log) {
581
582        try {
583            List<CmsRole> roles = OpenCms.getRoleManager().getRoles(cms, ou, false);
584            CmsRole.applySystemRoleOrder(roles);
585
586            DataProvider provider = new ListDataProvider<CmsRole>(roles);
587
588            roleComboBox.setDataProvider(provider);
589            roleComboBox.setItemCaptionGenerator(role -> {
590                try {
591                    return role.getDisplayName(cms, A_CmsUI.get().getLocale());
592                } catch (CmsException e) {
593                    return "";
594                }
595            });
596            roleComboBox.setEmptySelectionAllowed(false);
597
598        } catch (CmsException e) {
599            if (log != null) {
600                log.error("Unable to read roles.", e);
601            }
602        }
603    }
604
605    /**
606     * Initialized the role ComboBox (vaadin-v7-version).<p>
607     *
608     * @param cms CmsObject
609     * @param ou to load roles for
610     * @param roleComboBox ComboBox
611     * @param log LOG
612     */
613    protected static void iniRole(CmsObject cms, String ou, ComboBox roleComboBox, Log log) {
614
615        iniRole(cms, ou, roleComboBox, log, false);
616    }
617
618    /**
619     * Initialized the role ComboBox (vaadin-v7-version).<p>
620     *
621     * @param cms CmsObject
622     * @param ou to load roles for
623     * @param roleComboBox ComboBox
624     * @param log LOG
625     * @param includeNoRoleEntry with noRole entry?
626     */
627    protected static void iniRole(
628        CmsObject cms,
629        String ou,
630        ComboBox roleComboBox,
631        Log log,
632        boolean includeNoRoleEntry) {
633
634        try {
635            List<CmsRole> roles = OpenCms.getRoleManager().getRoles(cms, ou, false);
636            CmsRole.applySystemRoleOrder(roles);
637            IndexedContainer container = new IndexedContainer();
638            container.addContainerProperty("caption", String.class, "");
639            for (CmsRole role : roles) {
640                Item item = container.addItem(role);
641                item.getItemProperty("caption").setValue(role.getDisplayName(cms, A_CmsUI.get().getLocale()));
642            }
643            if (includeNoRoleEntry) {
644                Item item = container.addItem("NoRole");
645                item.getItemProperty("caption").setValue(
646                    CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_USER_NO_ROLE_0));
647            }
648            roleComboBox.setContainerDataSource(container);
649            roleComboBox.setItemCaptionPropertyId("caption");
650            roleComboBox.setNullSelectionAllowed(false);
651            roleComboBox.setNewItemsAllowed(false);
652        } catch (CmsException e) {
653            if (log != null) {
654                log.error("Unable to read roles.", e);
655            }
656        }
657    }
658
659    /**
660     * Sends an email to the user.<p>
661     *
662     * @param cms CmsObject
663     * @param password of the user
664     * @param user user to send mail to
665     * @param newUser flag indicates if user is new
666     * @param changePassword has the user to change password?
667     */
668    protected static void sendMail(
669        CmsObject cms,
670        String password,
671        CmsUser user,
672        boolean newUser,
673        boolean changePassword) {
674
675        sendMail(cms, password, user, user.getOuFqn(), newUser, changePassword);
676    }
677
678    /**
679     * Sends an email to the user.<p>
680     *
681     * @param cms CmsObject
682     * @param password of the user
683     * @param user user to send mail to
684     * @param ou name
685     * @param newUser flag indicates if user is new
686     * @param changePassword has the user to change password?
687     */
688    protected static void sendMail(
689        CmsObject cms,
690        String password,
691        CmsUser user,
692        String ou,
693        boolean newUser,
694        boolean changePassword) {
695
696        sendMail(cms, password, user, ou, newUser, changePassword, false);
697    }
698
699    /**
700     * Sends an email to the user.<p>
701     *
702     * @param cms CmsObject
703     * @param password of the user
704     * @param user user to send mail to
705     * @param ou name
706     * @param newUser flag indicates if user is new
707     * @param changePassword has the user to change password?
708     * @param throwOnError if the mail error should be propagated
709     */
710    protected static void sendMail(
711        CmsObject cms,
712        String password,
713        CmsUser user,
714        String ou,
715        boolean newUser,
716        boolean changePassword,
717        boolean throwOnError) {
718
719        if (CmsStringUtil.isEmptyOrWhitespaceOnly(user.getEmail())) {
720            return;
721        }
722        CmsSendPasswordNotification notification = new CmsSendPasswordNotification(
723            cms,
724            password,
725            user,
726            ou,
727            cms.getRequestContext().getCurrentUser(),
728            newUser,
729            changePassword);
730        try {
731            notification.send();
732        } catch (EmailException e) {
733            LOG.error("Unable to send email with password", e);
734            if (throwOnError) {
735                throw new IllegalStateException("Unable to send email with password.", e);
736            }
737        }
738
739    }
740
741    /**
742     * @see org.opencms.ui.apps.user.I_CmsPasswordFetcher#fetchPassword(java.lang.String)
743     */
744    public void fetchPassword(String password) {
745
746        m_pw.getPassword1Field().setValue(password);
747        m_pw.getPassword2Field().setValue(password);
748        // only check checkboxes if they are visible.
749        if (m_forceResetPassword.isVisible()) {
750            m_forceResetPassword.setValue(Boolean.TRUE);
751        }
752        if (m_sendEmail.isVisible()) {
753            m_sendEmail.setValue(Boolean.TRUE);
754        }
755        m_sendEmail.setEnabled(true);
756
757    }
758
759    /**
760     * Checks if a new user should be created.<p>
761     *
762     * @return true, if create user function
763     */
764    protected boolean isNewUser() {
765
766        return m_user == null;
767    }
768
769    /**m_next
770     * Is password not matching to confirm field?<p>
771     *
772     * @return true, if password not equal to confirm
773     */
774    protected boolean isPasswordMismatchingConfirm() {
775
776        return !m_pw.getPassword1().equals(m_pw.getPassword2());
777
778    }
779
780    /**
781     * Validates the password fields.<p>
782     *
783     * @return true if password is valid (and confirm field matches password field).<p>
784     */
785    protected boolean isPasswordValid() {
786
787        if ((m_pw.getPassword1() == null) | (m_pw.getPassword2() == null)) {
788            return false;
789        }
790        try {
791            CmsPasswordInfo pwdInfo = new CmsPasswordInfo();
792            pwdInfo.setNewPwd(m_pw.getPassword1());
793            pwdInfo.setConfirmation(m_pw.getPassword2());
794
795            pwdInfo.validate();
796            return true;
797        } catch (CmsIllegalArgumentException | CmsIllegalStateException e) {
798            LOG.error("New password is not ok", e);
799            return false;
800        }
801    }
802
803    /**
804     * Checks if currently the root site is chosen as start site.<p>
805     *
806     * @return true if root site was selected
807     */
808    protected boolean isRootSiteSelected() {
809
810        return m_site.getValue().equals("");
811    }
812
813    /**
814     * Checks if the chosen site is valid.<p>
815     *
816     * @return true if site is null
817     */
818    protected boolean isSiteNull() {
819
820        return m_site.getValue() == null;
821    }
822
823    /**
824     * Checks if the given path is valid resource in site.<p>
825     *
826     * @return true if the resource is valid
827     */
828    protected boolean isSitePathValid() {
829
830        try {
831            CmsObject cmsLocal = OpenCms.initCmsObject(m_cms);
832            cmsLocal.getRequestContext().setSiteRoot((String)m_site.getValue());
833            if (m_startfolder.getValue().length() <= ((String)m_site.getValue()).length()) {
834                return false;
835            }
836            return cmsLocal.existsResource(m_startfolder.getValue().substring(((String)m_site.getValue()).length()));
837        } catch (CmsException e) {
838            LOG.error("Unabel to ini CmsObject", e);
839            return false;
840        }
841    }
842
843    /**
844     * Checks if the currently chosen start view is visible for root site.<p>
845     *
846     * @return true if app is available for root site
847     */
848    protected boolean isStartViewAvailableOnRoot() {
849
850        if (!m_startview.isEnabled()) {
851            return false;
852        }
853
854        return !m_startview.getValue().equals(CmsPageEditorConfiguration.APP_ID)
855            & !m_startview.getValue().equals(CmsSitemapEditorConfiguration.APP_ID);
856    }
857
858    /**
859     * Checks if all fields are valid. If not the tab of the first invalid field gets chosen.<p>
860     *
861     * @return true, if everything is ok
862     */
863    protected boolean isValid() {
864
865        boolean[] ret = new boolean[4];
866        ret[0] = m_loginname.isValid();
867        ret[1] = m_isWebOU ? true : m_userdata.isValid() | m_name_was_empty;
868        ret[2] = m_isWebOU
869        ? true
870        : m_site.isValid() & m_startview.isValid() & m_startfolder.isValid() & m_project.isValid();
871        ret[3] = validatePasswordField1(m_pw.getPassword1Field().getValue());
872
873        for (int i = 0; i < ret.length; i++) {
874
875            if (!ret[i]) {
876                m_tab.setSelectedTab(i);
877                break;
878            }
879        }
880        return ret[0] & ret[1] & ret[2] & ret[3];
881    }
882
883    /**
884     * Saves the canged user data.<p>
885     */
886    protected void save() {
887
888        boolean newUser = false;
889        try {
890            if (m_user == null) {
891                createNewUser();
892                newUser = true;
893            } else {
894
895                saveUser();
896            }
897            saveUserSettings();
898            if (m_sendEmail.getValue().booleanValue() & m_sendEmail.isEnabled()) {
899                sendMail(m_cms, m_pw.getPassword1(), m_user, newUser, m_forceResetPassword.getValue().booleanValue());
900            }
901        } catch (CmsException e) {
902            LOG.error("Unable to save user", e);
903        }
904    }
905
906    /**
907     * Sets the visibility of the buttons.<p>
908     */
909    protected void setButtonVisibility() {
910
911        Component tab = m_tab.getSelectedTab();
912        int pos = m_tab.getTabPosition(m_tab.getTab(tab));
913        //TODO: check if necessary (when it was finally known which tabs web ou users should see..
914        int maxPos = m_isWebOU ? 3 : 3; //has to be changed if number of tabs is changed for web OU user
915        m_next.setVisible(pos < maxPos);
916        m_ok.setVisible(pos == maxPos);
917    }
918
919    /**
920     * En/Diables the email box.<p>
921     */
922    protected void setEmailBox() {
923
924        m_sendEmail.setEnabled(
925            !CmsStringUtil.isEmptyOrWhitespaceOnly(m_pw.getPassword1())
926                | !CmsStringUtil.isEmptyOrWhitespaceOnly(m_pw.getPassword2()));
927    }
928
929    /**
930     * Sets the start folder depending on current set site field.<p>
931     *
932     * @param startFolder default value or null
933     */
934    protected void setupStartFolder(String startFolder) {
935
936        try {
937            CmsObject cmsCopy = OpenCms.initCmsObject(m_cms);
938            if (m_site.getValue() != null) {
939                cmsCopy.getRequestContext().setSiteRoot((String)m_site.getValue());
940            } else {
941                cmsCopy.getRequestContext().setSiteRoot("");
942            }
943            m_startfolder.requireFolder();
944            m_startfolder.disableSiteSwitch();
945            String defaultFolder = OpenCms.getWorkplaceManager().getDefaultUserSettings().getStartFolder();
946            if ((startFolder == null)
947                && (CmsStringUtil.isEmptyOrWhitespaceOnly(defaultFolder) || !cmsCopy.existsResource(defaultFolder))) {
948                defaultFolder = "/";
949            }
950            m_startfolder.setValue(
951                cmsCopy.getRequestContext().addSiteRoot(startFolder == null ? defaultFolder : startFolder));
952            m_startfolder.setCmsObject(cmsCopy);
953            m_startfolder.setUseRootPaths(true);
954            if (!m_visSites) {
955                try {
956                    List<CmsResource> ouResources = OpenCms.getOrgUnitManager().getResourcesForOrganizationalUnit(
957                        cmsCopy,
958                        m_ou.getValue());
959                    if (!ouResources.isEmpty()) {
960                        m_startfolder.setValue(ouResources.get(0).getRootPath());
961                    }
962                } catch (CmsException e1) {
963                    LOG.error("unable to read resources for ou", e1);
964                }
965            }
966            m_startfolder.setEnabled(m_visSites);
967        } catch (CmsException e) {
968            LOG.error("Unable to ini CmsObject", e);
969        }
970    }
971
972    /**
973     * Sets up the validators.<p>
974     */
975    protected void setupValidators() {
976
977        if (m_loginname.getValidators().size() == 0) {
978            m_loginname.addValidator(new LoginNameValidator());
979            m_pw.getPassword1Field().addValueChangeListener(event -> {
980                validatePasswordField1(event.getValue());
981            });
982            m_site.addValidator(new StartSiteValidator());
983            m_startview.addValidator(new StartViewValidator());
984            m_startfolder.addValidator(new StartPathValidator());
985        }
986    }
987
988    /**Switches to the next tab.*/
989    protected void switchTab() {
990
991        Component tab = m_tab.getSelectedTab();
992        int pos = m_tab.getTabPosition(m_tab.getTab(tab));
993        if (m_isWebOU) {
994            if (pos == 0) {
995                pos = 1;
996            }
997        }
998        m_tab.setSelectedTab(pos + 1);
999    }
1000
1001    /**
1002     * Checks if given user exists.<p>
1003     *
1004     * @param username to check
1005     * @return boolean
1006     */
1007    protected boolean userAlreadyExists(String username) {
1008
1009        if (m_user != null) {
1010            return false;
1011        }
1012        CmsUser user = null;
1013        try {
1014            user = m_cms.readUser(m_ou.getValue() + username);
1015        } catch (CmsException e) {
1016            return false;
1017        }
1018
1019        return user != null;
1020
1021    }
1022
1023    /**
1024     * Checks whether the passwords match.<p>
1025     *
1026     * @param password2 the password 2 value
1027     */
1028    void checkPasswordMatch(String password2) {
1029
1030        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(password2)) {
1031            showPasswordMatchError(!password2.equals(m_pw.getPassword1()));
1032        }
1033    }
1034
1035    /**
1036     * Checks the security level of the given password.<p>
1037     *
1038     * @param password the password
1039     */
1040    void checkSecurity(String password) {
1041
1042        I_CmsPasswordHandler handler = OpenCms.getPasswordHandler();
1043        try {
1044            handler.validatePassword(password);
1045            if (handler instanceof I_CmsPasswordSecurityEvaluator) {
1046                SecurityLevel level = ((I_CmsPasswordSecurityEvaluator)handler).evaluatePasswordSecurity(password);
1047                m_pw.setErrorPassword1(null, OpenCmsTheme.SECURITY + "-" + level.name());
1048            } else {
1049                m_pw.setErrorPassword1(null, OpenCmsTheme.SECURITY_STRONG);
1050            }
1051        } catch (CmsSecurityException e) {
1052            m_pw.setErrorPassword1(
1053                new UserError(e.getLocalizedMessage(A_CmsUI.get().getLocale())),
1054                OpenCmsTheme.SECURITY_INVALID);
1055        }
1056        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_pw.getPassword2())) {
1057            showPasswordMatchError(!password.equals(m_pw.getPassword2()));
1058        }
1059    }
1060
1061    /**
1062     * Returns a CmsObject with request set to given site.<p>
1063     *
1064     * @param siteRoot to be used
1065     * @return CmsObject
1066     */
1067    CmsObject getCmsObjectWithSite(String siteRoot) {
1068
1069        if (siteRoot == null) {
1070            siteRoot = "/";
1071        }
1072        try {
1073            CmsObject res = OpenCms.initCmsObject(m_cms);
1074            res.getRequestContext().setSiteRoot(siteRoot);
1075            return res;
1076        } catch (CmsException e) {
1077            LOG.error("Unable to initialize CmsObject", e);
1078            return m_cms;
1079        }
1080    }
1081
1082    /**
1083     * Initializes the site combo box.<p>
1084     *
1085     * @param settings user settings
1086     */
1087    void iniSite(CmsUserSettings settings) {
1088
1089        List<CmsSite> sitesList = OpenCms.getSiteManager().getAvailableSites(m_cms, true, false, m_ou.getValue());
1090
1091        IndexedContainer container = new IndexedContainer();
1092        container.addContainerProperty("caption", String.class, "");
1093        CmsSite firstNoRootSite = null;
1094        for (CmsSite site : sitesList) {
1095            if (CmsStringUtil.isEmptyOrWhitespaceOnly(site.getSiteRoot())) {
1096                if (hasRole(CmsRole.VFS_MANAGER)
1097                    | ((m_user == null)
1098                        && Arrays.asList(
1099                            CmsRole.ACCOUNT_MANAGER.forOrgUnit(m_ou.getValue()),
1100                            CmsRole.ADMINISTRATOR.forOrgUnit(m_ou.getValue()),
1101                            CmsRole.WORKPLACE_MANAGER.forOrgUnit(m_ou.getValue()),
1102                            CmsRole.DATABASE_MANAGER.forOrgUnit(m_ou.getValue()),
1103                            CmsRole.PROJECT_MANAGER.forOrgUnit(m_ou.getValue()),
1104                            CmsRole.VFS_MANAGER.forOrgUnit(m_ou.getValue()),
1105                            CmsRole.ROOT_ADMIN.forOrgUnit(m_ou.getValue())).contains(
1106                                m_role.getValue() instanceof CmsRole
1107                                ? ((CmsRole)(m_role.getValue())).forOrgUnit(m_ou.getValue())
1108                                : ""))) {
1109                    Item item = container.addItem(site.getSiteRoot());
1110                    item.getItemProperty("caption").setValue(site.getTitle());
1111                }
1112            } else {
1113                if (firstNoRootSite == null) {
1114                    firstNoRootSite = site;
1115                }
1116                Item item = container.addItem(site.getSiteRoot());
1117                item.getItemProperty("caption").setValue(site.getTitle());
1118            }
1119        }
1120        if (container.size() == 0) {
1121            if (!container.containsId(A_CmsUI.getCmsObject().getRequestContext().getSiteRoot())) {
1122                Item defaultItem = container.addItem(A_CmsUI.getCmsObject().getRequestContext().getSiteRoot());
1123                defaultItem.getItemProperty("caption").setValue(
1124                    A_CmsUI.getCmsObject().getRequestContext().getSiteRoot());
1125            }
1126            m_visSites = false;
1127        }
1128        m_site.setContainerDataSource(container);
1129        m_site.setItemCaptionPropertyId("caption");
1130        m_site.setNewItemsAllowed(false);
1131        m_site.setNullSelectionAllowed(false);
1132        if (settings != null) {
1133            if (settings.getStartSite().length() >= 1) {
1134                m_site.select(settings.getStartSite().substring(0, settings.getStartSite().length() - 1));
1135            } else {
1136                LOG.error("The start site is unvalid configured");
1137            }
1138        } else {
1139            String defaultSite = OpenCms.getWorkplaceManager().getDefaultUserSettings().getStartSite();
1140            if (container.containsId(defaultSite)) {
1141                m_site.select(defaultSite);
1142            } else if (firstNoRootSite != null) {
1143                m_site.select(firstNoRootSite.getSiteRoot());
1144            } else {
1145                m_site.select(container.getItemIds().get(0));
1146            }
1147        }
1148    }
1149
1150    /**
1151     * Initializes the start view.<p>
1152     *
1153     * @param settings user settings
1154     */
1155    void iniStartView(CmsUserSettings settings) {
1156
1157        IndexedContainer container = getStartViewContainer("caption");
1158        if (container.size() > 0) {
1159            m_startview.setEnabled(true);
1160            m_startview.setContainerDataSource(container);
1161            m_startview.setItemCaptionPropertyId("caption");
1162            m_startview.setNullSelectionAllowed(false);
1163            m_startview.setNewItemsAllowed(false);
1164            if (container.getItemIds().size() > 0) {
1165
1166                if ((settings != null) && container.containsId(settings.getStartView())) {
1167                    m_startview.select(settings.getStartView());
1168                } else {
1169                    String defaultView = OpenCms.getWorkplaceManager().getDefaultUserSettings().getStartView();
1170                    if (container.containsId(defaultView)) {
1171                        m_startview.select(defaultView);
1172                    } else {
1173                        if (container.containsId("pageeditor")) {
1174                            m_startview.select("pageeditor");
1175                        } else {
1176                            m_startview.select(container.getItemIds().get(0));
1177                        }
1178                    }
1179                }
1180            }
1181        } else {
1182            m_startview.setValue(null);
1183            m_startview.setEnabled(false);
1184        }
1185    }
1186
1187    /**
1188     * Shows or hides the not matching passwords error.<p>
1189     *
1190     * @param show <code>true</code> to show the error
1191     */
1192    void showPasswordMatchError(boolean show) {
1193
1194        if (show) {
1195
1196            m_pw.setErrorPassword2(
1197                new UserError(CmsVaadinUtils.getMessageText(org.opencms.ui.Messages.GUI_PWCHANGE_PASSWORD_MISMATCH_0)),
1198                OpenCmsTheme.SECURITY_INVALID);
1199        } else {
1200            m_pw.setErrorPassword2(null, OpenCmsTheme.SECURITY_STRONG);
1201        }
1202    }
1203
1204    /**
1205     * Creates new user.<p>
1206     *
1207     * @throws CmsException exception
1208     */
1209    private void createNewUser() throws CmsException {
1210
1211        //Password was checked by validator before
1212        String ou = m_ou.getValue();
1213        if (!ou.endsWith("/")) {
1214            ou += "/";
1215        }
1216        CmsUser user = m_cms.createUser(ou + m_loginname.getValue(), m_pw.getPassword1(), "", null);
1217        updateUser(user);
1218        m_cms.writeUser(user);
1219        if (!CmsStringUtil.isEmptyOrWhitespaceOnly(m_group.getValue())) {
1220            m_cms.addUserToGroup(user.getName(), m_group.getValue());
1221        }
1222        if (m_role.isVisible() && (m_role.getValue() instanceof CmsRole)) {
1223            OpenCms.getRoleManager().addUserToRole(m_cms, (CmsRole)m_role.getValue(), user.getName());
1224        }
1225        m_user = user;
1226
1227    }
1228
1229    /**
1230     * Returns the start view container.<p>
1231     *
1232     * @param caption of the container
1233     * @return indexed container
1234     */
1235    private IndexedContainer getStartViewContainer(String caption) {
1236
1237        List<I_CmsWorkplaceAppConfiguration> apps = OpenCms.getWorkplaceAppManager().getDefaultQuickLaunchConfigurations();
1238
1239        IndexedContainer res = new IndexedContainer();
1240
1241        res.addContainerProperty(caption, String.class, "");
1242
1243        for (I_CmsWorkplaceAppConfiguration app : apps) {
1244            if (hasRoleForApp(app)) {
1245                Item item = res.addItem(app.getId());
1246                item.getItemProperty(caption).setValue(app.getName(A_CmsUI.get().getLocale()));
1247            }
1248        }
1249        return res;
1250    }
1251
1252    /**
1253     * Checks if user, which gets edited, has given role.<p>
1254     *
1255     * @param role to be checked
1256     * @return true if user has role (or a parent role)
1257     */
1258    private boolean hasRole(CmsRole role) {
1259
1260        if (m_user != null) {
1261            return OpenCms.getRoleManager().hasRole(m_cms, m_user.getName(), CmsRole.VFS_MANAGER);
1262        }
1263        return false;
1264    }
1265
1266    /**
1267     * Checks if user, which gets edited, has role for given app.<p>
1268     *
1269     * @param app to be checked
1270     * @return true if user has role
1271     */
1272    private boolean hasRoleForApp(I_CmsWorkplaceAppConfiguration app) {
1273
1274        if (m_user != null) {
1275            return OpenCms.getRoleManager().hasRole(m_cms, m_user.getName(), app.getRequiredRole());
1276        }
1277        if (!(m_role.getValue() instanceof CmsRole)) {
1278            return false;
1279        }
1280        if (!CmsStringUtil.isEmptyOrWhitespaceOnly(m_group.getValue())) {
1281            try {
1282                CmsGroup group = m_cms.readGroup(m_group.getValue());
1283                CmsRole roleFromGroup = CmsRole.valueOf(group);
1284                CmsRole roleFromField = (CmsRole)m_role.getValue();
1285                if ((roleFromGroup == null) || !roleFromGroup.getChildren(true).contains(roleFromField)) {
1286                    roleFromGroup = roleFromField;
1287                }
1288                if (roleFromGroup == null) {
1289                    return false;
1290                }
1291                List<CmsRole> groupRoles = roleFromGroup.getChildren(true);
1292                groupRoles.add(roleFromGroup);
1293                List<String> roleNames = new ArrayList<String>();
1294                for (CmsRole gr : groupRoles) {
1295                    roleNames.add(gr.getRoleName());
1296                }
1297                return roleNames.contains(app.getRequiredRole().getRoleName());
1298            } catch (CmsException e) {
1299                LOG.error("Unable to read group", e);
1300            }
1301        }
1302        return true;
1303    }
1304
1305    /**
1306     * Initializes the language combo box.<p>
1307     *
1308     * @param settings user settings
1309     */
1310    private void iniLanguage(CmsUserSettings settings) {
1311
1312        IndexedContainer container = CmsVaadinUtils.getWorkplaceLanguageContainer("caption");
1313        m_language.setContainerDataSource(container);
1314        m_language.setItemCaptionPropertyId("caption");
1315        m_language.setNewItemsAllowed(false);
1316        m_language.setNullSelectionAllowed(false);
1317
1318        if (settings != null) {
1319            m_language.select(settings.getLocale());
1320        } else {
1321            if (container.containsId(OpenCms.getWorkplaceManager().getDefaultUserSettings().getLocale())) {
1322                m_language.select(OpenCms.getWorkplaceManager().getDefaultUserSettings().getLocale());
1323            } else {
1324                m_language.select(m_language.getItemIds().iterator().next());
1325            }
1326        }
1327    }
1328
1329    /**
1330     * Initializes the project combo box.<p>
1331     *
1332     * @param settings of user
1333     */
1334    private void iniProject(CmsUserSettings settings) {
1335
1336        try {
1337            List<CmsProject> projects = OpenCms.getOrgUnitManager().getAllAccessibleProjects(
1338                m_cms,
1339                m_ou.getValue(),
1340                false);
1341            for (CmsProject project : projects) {
1342                m_project.addItem(project.getName());
1343            }
1344            m_project.setNewItemsAllowed(false);
1345            m_project.setNullSelectionAllowed(false);
1346            if (settings != null) {
1347                // Project names may start with "/" when stored via the old workplace, this slash has to be removed, to match the name.
1348                String projString = settings.getStartProject();
1349                if (projString.startsWith("/")) {
1350                    projString = projString.substring(1);
1351                }
1352                if (!m_project.containsId(projString)) {
1353                    m_project.addItem(projString);
1354                    m_project.addValidator(new StartProjectValidator(projString));
1355                }
1356                m_project.select(projString);
1357            } else {
1358                String defaultProject = OpenCms.getWorkplaceManager().getDefaultUserSettings().getStartProject();
1359                if (m_project.containsId(defaultProject)) {
1360                    m_project.select(defaultProject);
1361                } else if (m_project.containsId("Offline")) {
1362                    m_project.select("Offline");
1363                } else {
1364                    Iterator<?> it = m_project.getItemIds().iterator();
1365                    String p = (String)it.next();
1366                    while (p.equals(CmsProject.ONLINE_PROJECT_NAME) & it.hasNext()) {
1367                        p = (String)it.next();
1368                    }
1369                    m_project.select(p);
1370                }
1371            }
1372        } catch (CmsException e) {
1373            LOG.error("Unable to read projects", e);
1374        }
1375    }
1376
1377    /**
1378     * A initialization method.<p>
1379     *
1380     * @param window to be closed
1381     * @param app opening this dialog
1382     * @param settings user settings, null if new user
1383     * @param enabled enable edit
1384     */
1385    private void init(final Window window, final CmsAccountsApp app, final CmsUserSettings settings, boolean enabled) {
1386
1387        m_userdata.initFields(m_user, enabled ? EditLevel.all : EditLevel.none);
1388        if (m_user != null) {
1389            if (CmsStringUtil.isEmptyOrWhitespaceOnly(m_user.getFirstname())
1390                | CmsStringUtil.isEmptyOrWhitespaceOnly(m_user.getLastname())
1391                | CmsStringUtil.isEmptyOrWhitespaceOnly(m_user.getEmail())) {
1392                m_name_was_empty = true;
1393            }
1394        }
1395        iniLanguage(settings);
1396        iniProject(settings);
1397        iniSite(settings);
1398        iniStartView(settings);
1399
1400        m_site.addValueChangeListener(new ValueChangeListener() {
1401
1402            private static final long serialVersionUID = 5111762655156037899L;
1403
1404            public void valueChange(ValueChangeEvent event) {
1405
1406                setupStartFolder(null);
1407
1408            }
1409
1410        });
1411
1412        m_ok.addClickListener(new ClickListener() {
1413
1414            private static final long serialVersionUID = -2579639520410382246L;
1415
1416            public void buttonClick(ClickEvent event) {
1417
1418                setupValidators();
1419                if (isValid()) {
1420                    save();
1421                    window.close();
1422                    app.reload();
1423                }
1424            }
1425        });
1426
1427        m_next.addClickListener(new ClickListener() {
1428
1429            private static final long serialVersionUID = -8584899970290349959L;
1430
1431            public void buttonClick(ClickEvent event) {
1432
1433                setupValidators();
1434                switchTab();
1435
1436            }
1437        });
1438
1439        m_cancel.addClickListener(new ClickListener() {
1440
1441            private static final long serialVersionUID = 5803825104722705175L;
1442
1443            public void buttonClick(ClickEvent event) {
1444
1445                window.close();
1446            }
1447        });
1448
1449        if (m_user == null) {
1450            m_role.addValueChangeListener(new ValueChangeListener() {
1451
1452                private static final long serialVersionUID = 5697126133686172725L;
1453
1454                public void valueChange(ValueChangeEvent event) {
1455
1456                    iniSite(settings);
1457                    iniStartView(settings);
1458                }
1459            });
1460            m_group.addValueChangeListener(new ValueChangeListener() {
1461
1462                private static final long serialVersionUID = 1512940002751242094L;
1463
1464                public void valueChange(ValueChangeEvent event) {
1465
1466                    iniStartView(settings);
1467                    iniSite(settings);
1468                }
1469
1470            });
1471        }
1472
1473        m_site.addValueChangeListener(new ValueChangeListener() {
1474
1475            private static final long serialVersionUID = -169973382455098800L;
1476
1477            public void valueChange(ValueChangeEvent event) {
1478
1479                m_startfolder.setCmsObject(getCmsObjectWithSite((String)m_site.getValue()));
1480
1481            }
1482
1483        });
1484
1485        m_generateButton.addClickListener(new Button.ClickListener() {
1486
1487            private static final long serialVersionUID = 4128513094772586752L;
1488
1489            public void buttonClick(ClickEvent event) {
1490
1491                final Window windowDialog = CmsBasicDialog.prepareWindow(CmsBasicDialog.DialogWidth.content);
1492                windowDialog.setCaption(
1493                    CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_GEN_PASSWORD_CAPTION_0));
1494                CmsGeneratePasswordDialog dialog = new CmsGeneratePasswordDialog(
1495                    CmsUserEditDialog.this,
1496                    new Runnable() {
1497
1498                        public void run() {
1499
1500                            windowDialog.close();
1501
1502                        }
1503                    });
1504                windowDialog.setContent(dialog);
1505                A_CmsUI.get().addWindow(windowDialog);
1506            }
1507        });
1508    }
1509
1510    private boolean isPasswordField1Valid() {
1511
1512        String value = m_pw.getPassword1Field().getValue();
1513        try {
1514            m_passwordValidator.validate(value);
1515            return true;
1516        } catch (InvalidValueException e) {
1517            return false;
1518        }
1519    }
1520
1521    /**
1522     * Saves changes to an existing user.<p>
1523     *
1524     * @throws CmsException exception
1525     */
1526    private void saveUser() throws CmsException {
1527
1528        updateUser(m_user);
1529
1530        if (!CmsStringUtil.isEmptyOrWhitespaceOnly(m_pw.getPassword1())) {
1531            if (isPasswordValid()) {
1532                m_cms.setPassword(m_user.getName(), m_pw.getPassword1());
1533                CmsUserLog.logPasswordChange(m_cms, m_user.getName());
1534            }
1535        }
1536
1537        m_cms.writeUser(m_user);
1538
1539    }
1540
1541    /**
1542     * Saves the user settings.<p>
1543     *
1544     * @throws CmsException exception
1545     */
1546    private void saveUserSettings() throws CmsException {
1547
1548        CmsUserSettings settings = new CmsUserSettings(m_user);
1549        settings.setLocale((Locale)m_language.getValue());
1550        settings.setStartSite((String)m_site.getValue() + "/");
1551        settings.setStartProject((String)m_project.getValue());
1552        if (m_visSites) {
1553            settings.setStartFolder(m_startfolder.getValue().substring(((String)m_site.getValue()).length()));
1554            if (!CmsStringUtil.isEmptyOrWhitespaceOnly((String)m_startview.getValue())) {
1555                settings.setStartView((String)m_startview.getValue());
1556            }
1557        }
1558        settings.save(m_cms);
1559    }
1560
1561    /**
1562     * Sets the password fields.<p>
1563     */
1564    private void setPasswordFields() {
1565
1566        m_dummyPasswordLabel.setContentMode(com.vaadin.v7.shared.ui.label.ContentMode.HTML);
1567
1568        // ugly hack to prevent Firefox from asking user to save password on every click which causes the history token to change after editing a user
1569        String pwd = "<input type=\"password\" value=\"password\">";
1570        m_dummyPasswordLabel.setValue("<div style=\"display: none;\">" + pwd + pwd + "</div>");
1571
1572        m_pw.hideOldPassword();
1573        m_pw.setHeaderVisible(false);
1574        if (OpenCms.getPasswordHandler() instanceof I_CmsPasswordSecurityEvaluator) {
1575            m_pw.setSecurityHint(
1576                ((I_CmsPasswordSecurityEvaluator)OpenCms.getPasswordHandler()).getPasswordSecurityHint(
1577                    A_CmsUI.get().getLocale()));
1578        }
1579        m_pw.getOldPasswordField().setImmediate(true);
1580
1581        m_pw.getPassword1Field().addValueChangeListener(event -> {
1582            checkSecurity(event.getValue());
1583            setEmailBox();
1584        });
1585        m_pw.getPassword2Field().addValueChangeListener(event -> {
1586
1587            checkSecurity(m_pw.getPassword1());
1588            checkPasswordMatch(event.getValue());
1589            setEmailBox();
1590
1591        });
1592
1593    }
1594
1595    /**
1596     * Sets the password status for the user.<p>
1597     *
1598     * @param user CmsUser
1599     * @param reset true or false
1600     */
1601    private void setUserPasswordStatus(CmsUser user, boolean reset) {
1602
1603        if (reset) {
1604            user.setAdditionalInfo(CmsUserSettings.ADDITIONAL_INFO_PASSWORD_RESET, "true");
1605        } else {
1606            user.deleteAdditionalInfo(CmsUserSettings.ADDITIONAL_INFO_PASSWORD_RESET);
1607        }
1608        m_app.getPasswordResetStateCache().put(user.getId(), Boolean.valueOf(reset));
1609    }
1610
1611    /**
1612     *  Read form and updates a given user according to form.<p>
1613     *
1614     * @param user to be updated
1615     */
1616    private void updateUser(CmsUser user) {
1617
1618        setUserPasswordStatus(user, m_forceResetPassword.getValue().booleanValue());
1619        CmsUserLog.logSetForceResetPassword(A_CmsUI.getCmsObject(), user.getName());
1620        user.setDescription(m_description.getValue());
1621        user.setManaged(!m_selfmanagement.getValue().booleanValue());
1622        if (m_resetTwoFactorAuthentication.getValue().booleanValue()) {
1623            OpenCms.getTwoFactorAuthenticationHandler().resetTwoFactorAuthentication(user);
1624        }
1625        boolean enabled = m_enabled.getValue().booleanValue();
1626        user.setEnabled(enabled);
1627        if (enabled) {
1628            user.getAdditionalInfo().remove(CmsLoginController.KEY_ACCOUNT_LOCKED);
1629        }
1630        m_userdata.submit(user, m_cms, new Runnable() {
1631
1632            public void run() {
1633
1634                //
1635            }
1636        }, true);
1637    }
1638
1639    private boolean validatePasswordField1(String value) {
1640
1641        try {
1642            m_passwordValidator.validate(value);
1643            m_pw.getPassword1Field().setComponentError(null);
1644            return true;
1645        } catch (InvalidValueException e) {
1646            m_pw.getPassword1Field().setComponentError(e.getErrorMessage());
1647            return false;
1648        }
1649
1650    }
1651}