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