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.file.CmsGroup;
031import org.opencms.file.CmsObject;
032import org.opencms.file.CmsUser;
033import org.opencms.main.CmsException;
034import org.opencms.main.CmsIllegalArgumentException;
035import org.opencms.main.CmsLog;
036import org.opencms.main.OpenCms;
037import org.opencms.security.CmsRole;
038import org.opencms.ui.CmsVaadinUtils;
039import org.opencms.ui.apps.Messages;
040import org.opencms.ui.components.CmsBasicDialog;
041import org.opencms.util.CmsUUID;
042
043import java.util.ArrayList;
044import java.util.Collections;
045import java.util.List;
046
047import org.apache.commons.logging.Log;
048
049import com.vaadin.ui.Button;
050import com.vaadin.ui.Window;
051import com.vaadin.v7.data.Property.ValueChangeEvent;
052import com.vaadin.v7.data.Property.ValueChangeListener;
053import com.vaadin.v7.data.Validator;
054import com.vaadin.v7.shared.ui.combobox.FilteringMode;
055import com.vaadin.v7.ui.CheckBox;
056import com.vaadin.v7.ui.ComboBox;
057import com.vaadin.v7.ui.VerticalLayout;
058
059/**
060 * Dialog to change OU of given user.<p>
061 */
062public class CmsMoveUserToOU extends CmsBasicDialog {
063
064    /**
065     * OU ComboBox validator.<p>
066     */
067    class OUValidator implements Validator {
068
069        private static final long serialVersionUID = 1L;
070
071        /**
072         * @see com.vaadin.v7.data.Validator#validate(java.lang.Object)
073         */
074        public void validate(Object value) throws InvalidValueException {
075
076            String ou = (String)value;
077
078            if (m_user.getOuFqn().equals(ou)) {
079                throw new InvalidValueException(
080                    CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_USER_MOVE_OU_SAME_OU_0));
081            }
082            try {
083                m_cms.readUser(ou + m_user.getSimpleName());
084                throw new InvalidValueException(
085                    CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_USER_MOVE_OU_USERNAME_COLLISION_0));
086            } catch (CmsException e) {
087                //Ok, no user found
088            }
089
090        }
091
092    }
093
094    /** The logger for this class. */
095    static Log LOG = CmsLog.getLog(CmsMoveUserToOU.class.getName());
096
097    /**vaadin serial id.*/
098    private static final long serialVersionUID = 1L;
099
100    /**CmsObject. */
101    protected CmsObject m_cms;
102
103    /**User. */
104    CmsUser m_user;
105
106    /**Vaadin component. */
107    private Button m_cancel;
108
109    /**Vaadin component. */
110    private VerticalLayout m_error;
111
112    /**Vaadin component. */
113    private CmsGroupsOfUserTable m_groupTable;
114
115    /**Vaadin component. */
116    private Button m_ok;
117
118    /**Vaadin component. */
119    private ComboBox m_ou;
120
121    /**Vaadin component. */
122    private CheckBox m_removeAll;
123
124    /**
125     * Public constructor.<p>
126     *
127     * @param cms CmsObject
128     * @param userID ID of user
129     * @param window Window holding the dialog
130     * @param app to be updated
131     */
132    public CmsMoveUserToOU(CmsObject cms, CmsUUID userID, final Window window, final CmsAccountsApp app) {
133
134        CmsVaadinUtils.readAndLocalizeDesign(this, CmsVaadinUtils.getWpMessagesForCurrentLocale(), null);
135        m_cms = cms;
136        try {
137            m_user = cms.readUser(userID);
138            displayResourceInfoDirectly(Collections.singletonList(CmsAccountsApp.getPrincipalInfo(m_user)));
139            List<CmsGroup> groups = cms.getGroupsOfUser(m_user.getName(), true);
140            if (!groups.isEmpty()) {
141                m_error.setVisible(true);
142                m_groupTable.init(app, m_cms, m_user, groups);
143                m_ok.setEnabled(false);
144                m_removeAll.addValueChangeListener(new ValueChangeListener() {
145
146                    private static final long serialVersionUID = 1L;
147
148                    public void valueChange(ValueChangeEvent event) {
149
150                        setOkState();
151                    }
152                });
153            }
154            m_ou.setContainerDataSource(CmsVaadinUtils.getOUComboBox(m_cms, "", LOG, false).getContainerDataSource());
155            m_ou.setItemCaptionPropertyId("desc");
156            m_ou.setNewItemsAllowed(false);
157            m_ou.setFilteringMode(FilteringMode.CONTAINS);
158            m_ou.select("");
159            m_ou.setNullSelectionAllowed(false);
160        } catch (CmsException e) {
161            LOG.error("Cannot read user with id " + userID, e);
162        }
163
164        m_ou.addValidator(new OUValidator());
165        m_ok.addClickListener(e -> submit(window, app));
166        m_cancel.addClickListener(e -> window.close());
167    }
168
169    /**
170     * En/disables the ok button.<p>
171     */
172    protected void setOkState() {
173
174        m_ok.setEnabled(m_removeAll.getValue().booleanValue());
175    }
176
177    /**
178     * Perform ok action.<p>
179     *
180     * @param window Window
181     * @param app app
182     */
183    protected void submit(Window window, CmsAccountsApp app) {
184
185        if (m_ou.isValid()) {
186            try {
187                //First read out groups without removing them. Remove may change roles..
188                List<CmsGroup> userGroups = new ArrayList<CmsGroup>();
189                for (CmsGroup group : m_cms.getGroupsOfUser(m_user.getName(), true)) {
190                    userGroups.add(group);
191                }
192                List<CmsRole> directOURoles = new ArrayList<CmsRole>();
193                List<CmsRole> otherRoles = new ArrayList<CmsRole>();
194                for (CmsRole role : OpenCms.getRoleManager().getRolesOfUser(
195                    m_cms,
196                    m_user.getName(),
197                    m_user.getOuFqn(),
198                    true,
199                    true,
200                    false)) {
201                    //OU specific roles: save them to add them to new ou later
202                    if ((m_user.getOuFqn()).equals(role.getOuFqn())) {
203                        directOURoles.add(role);
204                        OpenCms.getRoleManager().removeUserFromRole(m_cms, role, m_user.getName());
205                        continue;
206                    }
207                    //Sub OUs: just delete
208                    if (role.getOuFqn().startsWith(m_user.getOuFqn())) {
209                        OpenCms.getRoleManager().removeUserFromRole(m_cms, role, m_user.getName());
210                        continue;
211                    }
212                    //Other role from complete different OU: preserve
213                    otherRoles.add(role);
214                }
215                for (CmsGroup group : userGroups) {
216                    try {
217                        m_cms.removeUserFromGroup(m_user.getName(), group.getName());
218                    } catch (CmsIllegalArgumentException e) {
219                        //Group not there.. happens if the Admin group gets removed
220                        LOG.error("User cannot be removed from group", e);
221                    }
222                }
223                OpenCms.getOrgUnitManager().setUsersOrganizationalUnit(
224                    m_cms,
225                    (String)m_ou.getValue(),
226                    m_user.getName());
227                //Reload moved user
228                m_user = m_cms.readUser(m_user.getId());
229                for (CmsRole role : directOURoles) {
230                    OpenCms.getRoleManager().addUserToRole(
231                        m_cms,
232                        role.forOrgUnit((String)m_ou.getValue()),
233                        m_user.getName());
234                }
235                for (CmsRole role : otherRoles) {
236                    OpenCms.getRoleManager().addUserToRole(m_cms, role, m_user.getName());
237                }
238            } catch (CmsException e) {
239                LOG.error("Unable to move the user to anouther OU", e);
240            }
241            window.close();
242            app.reload();
243        }
244    }
245}