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