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.mail.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        if (CmsStringUtil.isEmptyOrWhitespaceOnly(user.getEmail())) {
697            return;
698        }
699        CmsSendPasswordNotification notification = new CmsSendPasswordNotification(
700            cms,
701            password,
702            user,
703            ou,
704            cms.getRequestContext().getCurrentUser(),
705            newUser,
706            changePassword);
707        try {
708            notification.send();
709        } catch (EmailException e) {
710            LOG.error("Unable to send email with password", e);
711        }
712
713    }
714
715    /**
716     * @see org.opencms.ui.apps.user.I_CmsPasswordFetcher#fetchPassword(java.lang.String)
717     */
718    public void fetchPassword(String password) {
719
720        m_pw.getPassword1Field().setValue(password);
721        m_pw.getPassword2Field().setValue(password);
722        // only check checkboxes if they are visible.
723        if (m_forceResetPassword.isVisible()) {
724            m_forceResetPassword.setValue(Boolean.TRUE);
725        }
726        if (m_sendEmail.isVisible()) {
727            m_sendEmail.setValue(Boolean.TRUE);
728        }
729        m_sendEmail.setEnabled(true);
730
731    }
732
733    /**
734     * Checks if a new user should be created.<p>
735     *
736     * @return true, if create user function
737     */
738    protected boolean isNewUser() {
739
740        return m_user == null;
741    }
742
743    /**m_next
744     * Is password not matching to confirm field?<p>
745     *
746     * @return true, if password not equal to confirm
747     */
748    protected boolean isPasswordMismatchingConfirm() {
749
750        return !m_pw.getPassword1().equals(m_pw.getPassword2());
751
752    }
753
754    /**
755     * Validates the password fields.<p>
756     *
757     * @return true if password is valid (and confirm field matches password field).<p>
758     */
759    protected boolean isPasswordValid() {
760
761        if ((m_pw.getPassword1() == null) | (m_pw.getPassword2() == null)) {
762            return false;
763        }
764        try {
765            CmsPasswordInfo pwdInfo = new CmsPasswordInfo();
766            pwdInfo.setNewPwd(m_pw.getPassword1());
767            pwdInfo.setConfirmation(m_pw.getPassword2());
768
769            pwdInfo.validate();
770            return true;
771        } catch (CmsIllegalArgumentException | CmsIllegalStateException e) {
772            LOG.error("New password is not ok", e);
773            return false;
774        }
775    }
776
777    /**
778     * Checks if currently the root site is chosen as start site.<p>
779     *
780     * @return true if root site was selected
781     */
782    protected boolean isRootSiteSelected() {
783
784        return m_site.getValue().equals("");
785    }
786
787    /**
788     * Checks if the chosen site is valid.<p>
789     *
790     * @return true if site is null
791     */
792    protected boolean isSiteNull() {
793
794        return m_site.getValue() == null;
795    }
796
797    /**
798     * Checks if the given path is valid resource in site.<p>
799     *
800     * @return true if the resource is valid
801     */
802    protected boolean isSitePathValid() {
803
804        try {
805            CmsObject cmsLocal = OpenCms.initCmsObject(m_cms);
806            cmsLocal.getRequestContext().setSiteRoot((String)m_site.getValue());
807            if (m_startfolder.getValue().length() <= ((String)m_site.getValue()).length()) {
808                return false;
809            }
810            return cmsLocal.existsResource(m_startfolder.getValue().substring(((String)m_site.getValue()).length()));
811        } catch (CmsException e) {
812            LOG.error("Unabel to ini CmsObject", e);
813            return false;
814        }
815    }
816
817    /**
818     * Checks if the currently chosen start view is visible for root site.<p>
819     *
820     * @return true if app is available for root site
821     */
822    protected boolean isStartViewAvailableOnRoot() {
823
824        if (!m_startview.isEnabled()) {
825            return false;
826        }
827
828        return !m_startview.getValue().equals(CmsPageEditorConfiguration.APP_ID)
829            & !m_startview.getValue().equals(CmsSitemapEditorConfiguration.APP_ID);
830    }
831
832    /**
833     * Checks if all fields are valid. If not the tab of the first invalid field gets chosen.<p>
834     *
835     * @return true, if everything is ok
836     */
837    protected boolean isValid() {
838
839        boolean[] ret = new boolean[4];
840        ret[0] = m_loginname.isValid();
841        ret[1] = m_isWebOU ? true : m_userdata.isValid() | m_name_was_empty;
842        ret[2] = m_isWebOU
843        ? true
844        : m_site.isValid() & m_startview.isValid() & m_startfolder.isValid() & m_project.isValid();
845        ret[3] = validatePasswordField1(m_pw.getPassword1Field().getValue());
846
847        for (int i = 0; i < ret.length; i++) {
848
849            if (!ret[i]) {
850                m_tab.setSelectedTab(i);
851                break;
852            }
853        }
854        return ret[0] & ret[1] & ret[2] & ret[3];
855    }
856
857    /**
858     * Saves the canged user data.<p>
859     */
860    protected void save() {
861
862        boolean newUser = false;
863        try {
864            if (m_user == null) {
865                createNewUser();
866                newUser = true;
867            } else {
868
869                saveUser();
870            }
871            saveUserSettings();
872            if (m_sendEmail.getValue().booleanValue() & m_sendEmail.isEnabled()) {
873                sendMail(m_cms, m_pw.getPassword1(), m_user, newUser, m_forceResetPassword.getValue().booleanValue());
874            }
875        } catch (CmsException e) {
876            LOG.error("Unable to save user", e);
877        }
878    }
879
880    /**
881     * Sets the visibility of the buttons.<p>
882     */
883    protected void setButtonVisibility() {
884
885        Component tab = m_tab.getSelectedTab();
886        int pos = m_tab.getTabPosition(m_tab.getTab(tab));
887        //TODO: check if necessary (when it was finally known which tabs web ou users should see..
888        int maxPos = m_isWebOU ? 3 : 3; //has to be changed if number of tabs is changed for web OU user
889        m_next.setVisible(pos < maxPos);
890        m_ok.setVisible(pos == maxPos);
891    }
892
893    /**
894     * En/Diables the email box.<p>
895     */
896    protected void setEmailBox() {
897
898        m_sendEmail.setEnabled(
899            !CmsStringUtil.isEmptyOrWhitespaceOnly(m_pw.getPassword1())
900                | !CmsStringUtil.isEmptyOrWhitespaceOnly(m_pw.getPassword2()));
901    }
902
903    /**
904     * Sets the start folder depending on current set site field.<p>
905     *
906     * @param startFolder default value or null
907     */
908    protected void setupStartFolder(String startFolder) {
909
910        try {
911            CmsObject cmsCopy = OpenCms.initCmsObject(m_cms);
912            if (m_site.getValue() != null) {
913                cmsCopy.getRequestContext().setSiteRoot((String)m_site.getValue());
914            } else {
915                cmsCopy.getRequestContext().setSiteRoot("");
916            }
917            m_startfolder.requireFolder();
918            m_startfolder.disableSiteSwitch();
919            String defaultFolder = OpenCms.getWorkplaceManager().getDefaultUserSettings().getStartFolder();
920            if ((startFolder == null)
921                && (CmsStringUtil.isEmptyOrWhitespaceOnly(defaultFolder) || !cmsCopy.existsResource(defaultFolder))) {
922                defaultFolder = "/";
923            }
924            m_startfolder.setValue(
925                cmsCopy.getRequestContext().addSiteRoot(startFolder == null ? defaultFolder : startFolder));
926            m_startfolder.setCmsObject(cmsCopy);
927            m_startfolder.setUseRootPaths(true);
928            if (!m_visSites) {
929                try {
930                    List<CmsResource> ouResources = OpenCms.getOrgUnitManager().getResourcesForOrganizationalUnit(
931                        cmsCopy,
932                        m_ou.getValue());
933                    if (!ouResources.isEmpty()) {
934                        m_startfolder.setValue(ouResources.get(0).getRootPath());
935                    }
936                } catch (CmsException e1) {
937                    LOG.error("unable to read resources for ou", e1);
938                }
939            }
940            m_startfolder.setEnabled(m_visSites);
941        } catch (CmsException e) {
942            LOG.error("Unable to ini CmsObject", e);
943        }
944    }
945
946    /**
947     * Sets up the validators.<p>
948     */
949    protected void setupValidators() {
950
951        if (m_loginname.getValidators().size() == 0) {
952            m_loginname.addValidator(new LoginNameValidator());
953            m_pw.getPassword1Field().addValueChangeListener(event -> {
954                validatePasswordField1(event.getValue());
955            });
956            m_site.addValidator(new StartSiteValidator());
957            m_startview.addValidator(new StartViewValidator());
958            m_startfolder.addValidator(new StartPathValidator());
959        }
960    }
961
962    /**Switches to the next tab.*/
963    protected void switchTab() {
964
965        Component tab = m_tab.getSelectedTab();
966        int pos = m_tab.getTabPosition(m_tab.getTab(tab));
967        if (m_isWebOU) {
968            if (pos == 0) {
969                pos = 1;
970            }
971        }
972        m_tab.setSelectedTab(pos + 1);
973    }
974
975    /**
976     * Checks if given user exists.<p>
977     *
978     * @param username to check
979     * @return boolean
980     */
981    protected boolean userAlreadyExists(String username) {
982
983        if (m_user != null) {
984            return false;
985        }
986        CmsUser user = null;
987        try {
988            user = m_cms.readUser(m_ou.getValue() + username);
989        } catch (CmsException e) {
990            return false;
991        }
992
993        return user != null;
994
995    }
996
997    /**
998     * Checks whether the passwords match.<p>
999     *
1000     * @param password2 the password 2 value
1001     */
1002    void checkPasswordMatch(String password2) {
1003
1004        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(password2)) {
1005            showPasswordMatchError(!password2.equals(m_pw.getPassword1()));
1006        }
1007    }
1008
1009    /**
1010     * Checks the security level of the given password.<p>
1011     *
1012     * @param password the password
1013     */
1014    void checkSecurity(String password) {
1015
1016        I_CmsPasswordHandler handler = OpenCms.getPasswordHandler();
1017        try {
1018            handler.validatePassword(password);
1019            if (handler instanceof I_CmsPasswordSecurityEvaluator) {
1020                SecurityLevel level = ((I_CmsPasswordSecurityEvaluator)handler).evaluatePasswordSecurity(password);
1021                m_pw.setErrorPassword1(null, OpenCmsTheme.SECURITY + "-" + level.name());
1022            } else {
1023                m_pw.setErrorPassword1(null, OpenCmsTheme.SECURITY_STRONG);
1024            }
1025        } catch (CmsSecurityException e) {
1026            m_pw.setErrorPassword1(
1027                new UserError(e.getLocalizedMessage(A_CmsUI.get().getLocale())),
1028                OpenCmsTheme.SECURITY_INVALID);
1029        }
1030        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_pw.getPassword2())) {
1031            showPasswordMatchError(!password.equals(m_pw.getPassword2()));
1032        }
1033    }
1034
1035    /**
1036     * Returns a CmsObject with request set to given site.<p>
1037     *
1038     * @param siteRoot to be used
1039     * @return CmsObject
1040     */
1041    CmsObject getCmsObjectWithSite(String siteRoot) {
1042
1043        if (siteRoot == null) {
1044            siteRoot = "/";
1045        }
1046        try {
1047            CmsObject res = OpenCms.initCmsObject(m_cms);
1048            res.getRequestContext().setSiteRoot(siteRoot);
1049            return res;
1050        } catch (CmsException e) {
1051            LOG.error("Unable to initialize CmsObject", e);
1052            return m_cms;
1053        }
1054    }
1055
1056    /**
1057     * Initializes the site combo box.<p>
1058     *
1059     * @param settings user settings
1060     */
1061    void iniSite(CmsUserSettings settings) {
1062
1063        List<CmsSite> sitesList = OpenCms.getSiteManager().getAvailableSites(m_cms, true, false, m_ou.getValue());
1064
1065        IndexedContainer container = new IndexedContainer();
1066        container.addContainerProperty("caption", String.class, "");
1067        CmsSite firstNoRootSite = null;
1068        for (CmsSite site : sitesList) {
1069            if (CmsStringUtil.isEmptyOrWhitespaceOnly(site.getSiteRoot())) {
1070                if (hasRole(CmsRole.VFS_MANAGER)
1071                    | ((m_user == null)
1072                        && Arrays.asList(
1073                            CmsRole.ACCOUNT_MANAGER.forOrgUnit(m_ou.getValue()),
1074                            CmsRole.ADMINISTRATOR.forOrgUnit(m_ou.getValue()),
1075                            CmsRole.WORKPLACE_MANAGER.forOrgUnit(m_ou.getValue()),
1076                            CmsRole.DATABASE_MANAGER.forOrgUnit(m_ou.getValue()),
1077                            CmsRole.PROJECT_MANAGER.forOrgUnit(m_ou.getValue()),
1078                            CmsRole.VFS_MANAGER.forOrgUnit(m_ou.getValue()),
1079                            CmsRole.ROOT_ADMIN.forOrgUnit(m_ou.getValue())).contains(
1080                                m_role.getValue() instanceof CmsRole
1081                                ? ((CmsRole)(m_role.getValue())).forOrgUnit(m_ou.getValue())
1082                                : ""))) {
1083                    Item item = container.addItem(site.getSiteRoot());
1084                    item.getItemProperty("caption").setValue(site.getTitle());
1085                }
1086            } else {
1087                if (firstNoRootSite == null) {
1088                    firstNoRootSite = site;
1089                }
1090                Item item = container.addItem(site.getSiteRoot());
1091                item.getItemProperty("caption").setValue(site.getTitle());
1092            }
1093        }
1094        if (container.size() == 0) {
1095            if (!container.containsId(A_CmsUI.getCmsObject().getRequestContext().getSiteRoot())) {
1096                Item defaultItem = container.addItem(A_CmsUI.getCmsObject().getRequestContext().getSiteRoot());
1097                defaultItem.getItemProperty("caption").setValue(
1098                    A_CmsUI.getCmsObject().getRequestContext().getSiteRoot());
1099            }
1100            m_visSites = false;
1101        }
1102        m_site.setContainerDataSource(container);
1103        m_site.setItemCaptionPropertyId("caption");
1104        m_site.setNewItemsAllowed(false);
1105        m_site.setNullSelectionAllowed(false);
1106        if (settings != null) {
1107            if (settings.getStartSite().length() >= 1) {
1108                m_site.select(settings.getStartSite().substring(0, settings.getStartSite().length() - 1));
1109            } else {
1110                LOG.error("The start site is unvalid configured");
1111            }
1112        } else {
1113            String defaultSite = OpenCms.getWorkplaceManager().getDefaultUserSettings().getStartSite();
1114            if (container.containsId(defaultSite)) {
1115                m_site.select(defaultSite);
1116            } else if (firstNoRootSite != null) {
1117                m_site.select(firstNoRootSite.getSiteRoot());
1118            } else {
1119                m_site.select(container.getItemIds().get(0));
1120            }
1121        }
1122    }
1123
1124    /**
1125     * Initializes the start view.<p>
1126     *
1127     * @param settings user settings
1128     */
1129    void iniStartView(CmsUserSettings settings) {
1130
1131        IndexedContainer container = getStartViewContainer("caption");
1132        if (container.size() > 0) {
1133            m_startview.setEnabled(true);
1134            m_startview.setContainerDataSource(container);
1135            m_startview.setItemCaptionPropertyId("caption");
1136            m_startview.setNullSelectionAllowed(false);
1137            m_startview.setNewItemsAllowed(false);
1138            if (container.getItemIds().size() > 0) {
1139
1140                if ((settings != null) && container.containsId(settings.getStartView())) {
1141                    m_startview.select(settings.getStartView());
1142                } else {
1143                    String defaultView = OpenCms.getWorkplaceManager().getDefaultUserSettings().getStartView();
1144                    if (container.containsId(defaultView)) {
1145                        m_startview.select(defaultView);
1146                    } else {
1147                        if (container.containsId("pageeditor")) {
1148                            m_startview.select("pageeditor");
1149                        } else {
1150                            m_startview.select(container.getItemIds().get(0));
1151                        }
1152                    }
1153                }
1154            }
1155        } else {
1156            m_startview.setValue(null);
1157            m_startview.setEnabled(false);
1158        }
1159    }
1160
1161    /**
1162     * Shows or hides the not matching passwords error.<p>
1163     *
1164     * @param show <code>true</code> to show the error
1165     */
1166    void showPasswordMatchError(boolean show) {
1167
1168        if (show) {
1169
1170            m_pw.setErrorPassword2(
1171                new UserError(CmsVaadinUtils.getMessageText(org.opencms.ui.Messages.GUI_PWCHANGE_PASSWORD_MISMATCH_0)),
1172                OpenCmsTheme.SECURITY_INVALID);
1173        } else {
1174            m_pw.setErrorPassword2(null, OpenCmsTheme.SECURITY_STRONG);
1175        }
1176    }
1177
1178    /**
1179     * Creates new user.<p>
1180     *
1181     * @throws CmsException exception
1182     */
1183    private void createNewUser() throws CmsException {
1184
1185        //Password was checked by validator before
1186        String ou = m_ou.getValue();
1187        if (!ou.endsWith("/")) {
1188            ou += "/";
1189        }
1190        CmsUser user = m_cms.createUser(ou + m_loginname.getValue(), m_pw.getPassword1(), "", null);
1191        updateUser(user);
1192        m_cms.writeUser(user);
1193        if (!CmsStringUtil.isEmptyOrWhitespaceOnly(m_group.getValue())) {
1194            m_cms.addUserToGroup(user.getName(), m_group.getValue());
1195        }
1196        if (m_role.isVisible() && (m_role.getValue() instanceof CmsRole)) {
1197            OpenCms.getRoleManager().addUserToRole(m_cms, (CmsRole)m_role.getValue(), user.getName());
1198        }
1199        m_user = user;
1200
1201    }
1202
1203    /**
1204     * Returns the start view container.<p>
1205     *
1206     * @param caption of the container
1207     * @return indexed container
1208     */
1209    private IndexedContainer getStartViewContainer(String caption) {
1210
1211        List<I_CmsWorkplaceAppConfiguration> apps = OpenCms.getWorkplaceAppManager().getDefaultQuickLaunchConfigurations();
1212
1213        IndexedContainer res = new IndexedContainer();
1214
1215        res.addContainerProperty(caption, String.class, "");
1216
1217        for (I_CmsWorkplaceAppConfiguration app : apps) {
1218            if (hasRoleForApp(app)) {
1219                Item item = res.addItem(app.getId());
1220                item.getItemProperty(caption).setValue(app.getName(A_CmsUI.get().getLocale()));
1221            }
1222        }
1223        return res;
1224    }
1225
1226    /**
1227     * Checks if user, which gets edited, has given role.<p>
1228     *
1229     * @param role to be checked
1230     * @return true if user has role (or a parent role)
1231     */
1232    private boolean hasRole(CmsRole role) {
1233
1234        if (m_user != null) {
1235            return OpenCms.getRoleManager().hasRole(m_cms, m_user.getName(), CmsRole.VFS_MANAGER);
1236        }
1237        return false;
1238    }
1239
1240    /**
1241     * Checks if user, which gets edited, has role for given app.<p>
1242     *
1243     * @param app to be checked
1244     * @return true if user has role
1245     */
1246    private boolean hasRoleForApp(I_CmsWorkplaceAppConfiguration app) {
1247
1248        if (m_user != null) {
1249            return OpenCms.getRoleManager().hasRole(m_cms, m_user.getName(), app.getRequiredRole());
1250        }
1251        if (!(m_role.getValue() instanceof CmsRole)) {
1252            return false;
1253        }
1254        if (!CmsStringUtil.isEmptyOrWhitespaceOnly(m_group.getValue())) {
1255            try {
1256                CmsGroup group = m_cms.readGroup(m_group.getValue());
1257                CmsRole roleFromGroup = CmsRole.valueOf(group);
1258                CmsRole roleFromField = (CmsRole)m_role.getValue();
1259                if ((roleFromGroup == null) || !roleFromGroup.getChildren(true).contains(roleFromField)) {
1260                    roleFromGroup = roleFromField;
1261                }
1262                if (roleFromGroup == null) {
1263                    return false;
1264                }
1265                List<CmsRole> groupRoles = roleFromGroup.getChildren(true);
1266                groupRoles.add(roleFromGroup);
1267                List<String> roleNames = new ArrayList<String>();
1268                for (CmsRole gr : groupRoles) {
1269                    roleNames.add(gr.getRoleName());
1270                }
1271                return roleNames.contains(app.getRequiredRole().getRoleName());
1272            } catch (CmsException e) {
1273                LOG.error("Unable to read group", e);
1274            }
1275        }
1276        return true;
1277    }
1278
1279    /**
1280     * Initializes the language combo box.<p>
1281     *
1282     * @param settings user settings
1283     */
1284    private void iniLanguage(CmsUserSettings settings) {
1285
1286        IndexedContainer container = CmsVaadinUtils.getWorkplaceLanguageContainer("caption");
1287        m_language.setContainerDataSource(container);
1288        m_language.setItemCaptionPropertyId("caption");
1289        m_language.setNewItemsAllowed(false);
1290        m_language.setNullSelectionAllowed(false);
1291
1292        if (settings != null) {
1293            m_language.select(settings.getLocale());
1294        } else {
1295            if (container.containsId(OpenCms.getWorkplaceManager().getDefaultUserSettings().getLocale())) {
1296                m_language.select(OpenCms.getWorkplaceManager().getDefaultUserSettings().getLocale());
1297            } else {
1298                m_language.select(m_language.getItemIds().iterator().next());
1299            }
1300        }
1301    }
1302
1303    /**
1304     * Initializes the project combo box.<p>
1305     *
1306     * @param settings of user
1307     */
1308    private void iniProject(CmsUserSettings settings) {
1309
1310        try {
1311            List<CmsProject> projects = OpenCms.getOrgUnitManager().getAllAccessibleProjects(
1312                m_cms,
1313                m_ou.getValue(),
1314                false);
1315            for (CmsProject project : projects) {
1316                m_project.addItem(project.getName());
1317            }
1318            m_project.setNewItemsAllowed(false);
1319            m_project.setNullSelectionAllowed(false);
1320            if (settings != null) {
1321                // Project names may start with "/" when stored via the old workplace, this slash has to be removed, to match the name.
1322                String projString = settings.getStartProject();
1323                if (projString.startsWith("/")) {
1324                    projString = projString.substring(1);
1325                }
1326                if (!m_project.containsId(projString)) {
1327                    m_project.addItem(projString);
1328                    m_project.addValidator(new StartProjectValidator(projString));
1329                }
1330                m_project.select(projString);
1331            } else {
1332                String defaultProject = OpenCms.getWorkplaceManager().getDefaultUserSettings().getStartProject();
1333                if (m_project.containsId(defaultProject)) {
1334                    m_project.select(defaultProject);
1335                } else if (m_project.containsId("Offline")) {
1336                    m_project.select("Offline");
1337                } else {
1338                    Iterator<?> it = m_project.getItemIds().iterator();
1339                    String p = (String)it.next();
1340                    while (p.equals(CmsProject.ONLINE_PROJECT_NAME) & it.hasNext()) {
1341                        p = (String)it.next();
1342                    }
1343                    m_project.select(p);
1344                }
1345            }
1346        } catch (CmsException e) {
1347            LOG.error("Unable to read projects", e);
1348        }
1349    }
1350
1351    /**
1352     * A initialization method.<p>
1353     *
1354     * @param window to be closed
1355     * @param app opening this dialog
1356     * @param settings user settings, null if new user
1357     * @param enabled enable edit
1358     */
1359    private void init(final Window window, final CmsAccountsApp app, final CmsUserSettings settings, boolean enabled) {
1360
1361        m_userdata.initFields(m_user, enabled ? EditLevel.all : EditLevel.none);
1362        if (m_user != null) {
1363            if (CmsStringUtil.isEmptyOrWhitespaceOnly(m_user.getFirstname())
1364                | CmsStringUtil.isEmptyOrWhitespaceOnly(m_user.getLastname())
1365                | CmsStringUtil.isEmptyOrWhitespaceOnly(m_user.getEmail())) {
1366                m_name_was_empty = true;
1367            }
1368        }
1369        iniLanguage(settings);
1370        iniProject(settings);
1371        iniSite(settings);
1372        iniStartView(settings);
1373
1374        m_site.addValueChangeListener(new ValueChangeListener() {
1375
1376            private static final long serialVersionUID = 5111762655156037899L;
1377
1378            public void valueChange(ValueChangeEvent event) {
1379
1380                setupStartFolder(null);
1381
1382            }
1383
1384        });
1385
1386        m_ok.addClickListener(new ClickListener() {
1387
1388            private static final long serialVersionUID = -2579639520410382246L;
1389
1390            public void buttonClick(ClickEvent event) {
1391
1392                setupValidators();
1393                if (isValid()) {
1394                    save();
1395                    window.close();
1396                    app.reload();
1397                }
1398            }
1399        });
1400
1401        m_next.addClickListener(new ClickListener() {
1402
1403            private static final long serialVersionUID = -8584899970290349959L;
1404
1405            public void buttonClick(ClickEvent event) {
1406
1407                setupValidators();
1408                switchTab();
1409
1410            }
1411        });
1412
1413        m_cancel.addClickListener(new ClickListener() {
1414
1415            private static final long serialVersionUID = 5803825104722705175L;
1416
1417            public void buttonClick(ClickEvent event) {
1418
1419                window.close();
1420            }
1421        });
1422
1423        if (m_user == null) {
1424            m_role.addValueChangeListener(new ValueChangeListener() {
1425
1426                private static final long serialVersionUID = 5697126133686172725L;
1427
1428                public void valueChange(ValueChangeEvent event) {
1429
1430                    iniSite(settings);
1431                    iniStartView(settings);
1432                }
1433            });
1434            m_group.addValueChangeListener(new ValueChangeListener() {
1435
1436                private static final long serialVersionUID = 1512940002751242094L;
1437
1438                public void valueChange(ValueChangeEvent event) {
1439
1440                    iniStartView(settings);
1441                    iniSite(settings);
1442                }
1443
1444            });
1445        }
1446
1447        m_site.addValueChangeListener(new ValueChangeListener() {
1448
1449            private static final long serialVersionUID = -169973382455098800L;
1450
1451            public void valueChange(ValueChangeEvent event) {
1452
1453                m_startfolder.setCmsObject(getCmsObjectWithSite((String)m_site.getValue()));
1454
1455            }
1456
1457        });
1458
1459        m_generateButton.addClickListener(new Button.ClickListener() {
1460
1461            private static final long serialVersionUID = 4128513094772586752L;
1462
1463            public void buttonClick(ClickEvent event) {
1464
1465                final Window windowDialog = CmsBasicDialog.prepareWindow(CmsBasicDialog.DialogWidth.content);
1466                windowDialog.setCaption(
1467                    CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_GEN_PASSWORD_CAPTION_0));
1468                CmsGeneratePasswordDialog dialog = new CmsGeneratePasswordDialog(
1469                    CmsUserEditDialog.this,
1470                    new Runnable() {
1471
1472                        public void run() {
1473
1474                            windowDialog.close();
1475
1476                        }
1477                    });
1478                windowDialog.setContent(dialog);
1479                A_CmsUI.get().addWindow(windowDialog);
1480            }
1481        });
1482    }
1483
1484    private boolean isPasswordField1Valid() {
1485
1486        String value = m_pw.getPassword1Field().getValue();
1487        try {
1488            m_passwordValidator.validate(value);
1489            return true;
1490        } catch (InvalidValueException e) {
1491            return false;
1492        }
1493    }
1494
1495    /**
1496     * Saves changes to an existing user.<p>
1497     *
1498     * @throws CmsException exception
1499     */
1500    private void saveUser() throws CmsException {
1501
1502        updateUser(m_user);
1503
1504        if (!CmsStringUtil.isEmptyOrWhitespaceOnly(m_pw.getPassword1())) {
1505            if (isPasswordValid()) {
1506                m_cms.setPassword(m_user.getName(), m_pw.getPassword1());
1507                CmsUserLog.logPasswordChange(m_cms, m_user.getName());
1508            }
1509        }
1510
1511        m_cms.writeUser(m_user);
1512
1513    }
1514
1515    /**
1516     * Saves the user settings.<p>
1517     *
1518     * @throws CmsException exception
1519     */
1520    private void saveUserSettings() throws CmsException {
1521
1522        CmsUserSettings settings = new CmsUserSettings(m_user);
1523        settings.setLocale((Locale)m_language.getValue());
1524        settings.setStartSite((String)m_site.getValue() + "/");
1525        settings.setStartProject((String)m_project.getValue());
1526        if (m_visSites) {
1527            settings.setStartFolder(m_startfolder.getValue().substring(((String)m_site.getValue()).length()));
1528            if (!CmsStringUtil.isEmptyOrWhitespaceOnly((String)m_startview.getValue())) {
1529                settings.setStartView((String)m_startview.getValue());
1530            }
1531        }
1532        settings.save(m_cms);
1533    }
1534
1535    /**
1536     * Sets the password fields.<p>
1537     */
1538    private void setPasswordFields() {
1539
1540        m_dummyPasswordLabel.setContentMode(com.vaadin.v7.shared.ui.label.ContentMode.HTML);
1541
1542        // 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
1543        String pwd = "<input type=\"password\" value=\"password\">";
1544        m_dummyPasswordLabel.setValue("<div style=\"display: none;\">" + pwd + pwd + "</div>");
1545
1546        m_pw.hideOldPassword();
1547        m_pw.setHeaderVisible(false);
1548        if (OpenCms.getPasswordHandler() instanceof I_CmsPasswordSecurityEvaluator) {
1549            m_pw.setSecurityHint(
1550                ((I_CmsPasswordSecurityEvaluator)OpenCms.getPasswordHandler()).getPasswordSecurityHint(
1551                    A_CmsUI.get().getLocale()));
1552        }
1553        m_pw.getOldPasswordField().setImmediate(true);
1554
1555        m_pw.getPassword1Field().addValueChangeListener(event -> {
1556            checkSecurity(event.getValue());
1557            setEmailBox();
1558        });
1559        m_pw.getPassword2Field().addValueChangeListener(event -> {
1560
1561            checkSecurity(m_pw.getPassword1());
1562            checkPasswordMatch(event.getValue());
1563            setEmailBox();
1564
1565        });
1566
1567    }
1568
1569    /**
1570     * Sets the password status for the user.<p>
1571     *
1572     * @param user CmsUser
1573     * @param reset true or false
1574     */
1575    private void setUserPasswordStatus(CmsUser user, boolean reset) {
1576
1577        if (reset) {
1578            user.setAdditionalInfo(CmsUserSettings.ADDITIONAL_INFO_PASSWORD_RESET, "true");
1579        } else {
1580            user.deleteAdditionalInfo(CmsUserSettings.ADDITIONAL_INFO_PASSWORD_RESET);
1581        }
1582        m_app.getPasswordResetStateCache().put(user.getId(), Boolean.valueOf(reset));
1583    }
1584
1585    /**
1586     *  Read form and updates a given user according to form.<p>
1587     *
1588     * @param user to be updated
1589     */
1590    private void updateUser(CmsUser user) {
1591
1592        setUserPasswordStatus(user, m_forceResetPassword.getValue().booleanValue());
1593        CmsUserLog.logSetForceResetPassword(A_CmsUI.getCmsObject(), user.getName());
1594        user.setDescription(m_description.getValue());
1595        user.setManaged(!m_selfmanagement.getValue().booleanValue());
1596        if (m_resetTwoFactorAuthentication.getValue().booleanValue()) {
1597            OpenCms.getTwoFactorAuthenticationHandler().resetTwoFactorAuthentication(user);
1598        }
1599        boolean enabled = m_enabled.getValue().booleanValue();
1600        user.setEnabled(enabled);
1601        if (enabled) {
1602            user.getAdditionalInfo().remove(CmsLoginController.KEY_ACCOUNT_LOCKED);
1603        }
1604        m_userdata.submit(user, m_cms, new Runnable() {
1605
1606            public void run() {
1607
1608                //
1609            }
1610        }, true);
1611    }
1612
1613    private boolean validatePasswordField1(String value) {
1614
1615        try {
1616            m_passwordValidator.validate(value);
1617            m_pw.getPassword1Field().setComponentError(null);
1618            return true;
1619        } catch (InvalidValueException e) {
1620            m_pw.getPassword1Field().setComponentError(e.getErrorMessage());
1621            return false;
1622        }
1623
1624    }
1625}