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.CmsLog;
035import org.opencms.main.OpenCms;
036import org.opencms.security.CmsAccessControlEntry;
037import org.opencms.security.CmsOrganizationalUnit;
038import org.opencms.security.CmsPrincipal;
039import org.opencms.security.CmsRole;
040import org.opencms.security.CmsRoleViolationException;
041import org.opencms.security.I_CmsPrincipal;
042import org.opencms.ui.A_CmsUI;
043import org.opencms.ui.CmsCssIcon;
044import org.opencms.ui.CmsUserIconHelper;
045import org.opencms.ui.CmsVaadinUtils;
046import org.opencms.ui.FontOpenCms;
047import org.opencms.ui.apps.A_CmsWorkplaceApp;
048import org.opencms.ui.apps.CmsAppWorkplaceUi;
049import org.opencms.ui.apps.CmsFileExplorer;
050import org.opencms.ui.apps.I_CmsAppUIContext;
051import org.opencms.ui.apps.Messages;
052import org.opencms.ui.apps.user.CmsGroupTable.TableProperty;
053import org.opencms.ui.components.CmsBasicDialog;
054import org.opencms.ui.components.CmsBasicDialog.DialogWidth;
055import org.opencms.ui.components.CmsInfoButton;
056import org.opencms.ui.components.CmsResourceInfo;
057import org.opencms.ui.components.CmsToolBar;
058import org.opencms.ui.components.OpenCmsTheme;
059import org.opencms.ui.dialogs.permissions.CmsPrincipalSelect;
060import org.opencms.ui.dialogs.permissions.CmsPrincipalSelect.WidgetType;
061import org.opencms.ui.dialogs.permissions.CmsPrincipalSelectDialog;
062import org.opencms.ui.dialogs.permissions.I_CmsPrincipalSelect;
063import org.opencms.util.CmsStringUtil;
064import org.opencms.util.CmsUUID;
065
066import java.util.ArrayList;
067import java.util.Collections;
068import java.util.LinkedHashMap;
069import java.util.List;
070import java.util.Map;
071import java.util.Set;
072import java.util.concurrent.ConcurrentHashMap;
073import java.util.function.Function;
074
075import org.apache.commons.logging.Log;
076
077import com.vaadin.server.ExternalResource;
078import com.vaadin.server.FontAwesome;
079import com.vaadin.server.Sizeable.Unit;
080import com.vaadin.ui.Button;
081import com.vaadin.ui.Button.ClickEvent;
082import com.vaadin.ui.Button.ClickListener;
083import com.vaadin.ui.Component;
084import com.vaadin.ui.HorizontalSplitPanel;
085import com.vaadin.ui.UI;
086import com.vaadin.ui.Window;
087import com.vaadin.ui.themes.ValoTheme;
088import com.vaadin.v7.data.Item;
089import com.vaadin.v7.data.Property.ValueChangeEvent;
090import com.vaadin.v7.data.Property.ValueChangeListener;
091import com.vaadin.v7.data.util.IndexedContainer;
092import com.vaadin.v7.event.FieldEvents.TextChangeEvent;
093import com.vaadin.v7.event.FieldEvents.TextChangeListener;
094import com.vaadin.v7.ui.ComboBox;
095import com.vaadin.v7.ui.Label;
096import com.vaadin.v7.ui.Table;
097import com.vaadin.v7.ui.TextField;
098import com.vaadin.v7.ui.VerticalLayout;
099
100/**
101 * App for the OU Management.<p>
102 */
103public class CmsAccountsApp extends A_CmsWorkplaceApp implements I_CmsPrincipalSelect {
104
105    /**
106     * Bean for the state of the app.<p>
107     */
108    class CmsStateBean {
109
110        /**the filter for tables. */
111        private String m_filter;
112
113        /**Group id to be opended (or null). */
114        private CmsUUID m_groupID;
115
116        /**ou path. */
117        private String m_path = "";
118
119        /**type of element to be openend. */
120        private I_CmsOuTreeType m_type;
121
122        /**
123         * public constructor.<p>
124         *
125         * @param path ou path
126         * @param type type to be opened
127         * @param groupID groupid
128         * @param filter filter string
129         */
130        public CmsStateBean(String path, I_CmsOuTreeType type, CmsUUID groupID, String filter) {
131
132            m_path = path.equals("/") ? "" : path;
133            m_type = type;
134            m_groupID = groupID;
135            m_filter = filter;
136        }
137
138        /**
139         * Gets group id.<p>
140         *
141         * @return group id
142         */
143        public CmsUUID getGroupID() {
144
145            return m_groupID;
146        }
147
148        /**
149         * Gets the ou path.<p>
150         *
151         * @return ou path
152         */
153        public String getPath() {
154
155            return m_path;
156        }
157
158        /**
159         * Gets the state string of the current bean.<p>
160         *
161         * @return state string
162         */
163        public String getState() {
164
165            String typeString = m_type.getId();
166            String groupString = "";
167            if (m_groupID != null) {
168                groupString = m_groupID.getStringValue();
169            }
170            return typeString + STATE_SEPERATOR + m_path + STATE_SEPERATOR + groupString + STATE_SEPERATOR + m_filter;
171
172        }
173
174        /**
175         * Gets the filter string for the table.<p>
176         *
177         * @return the table filter
178         */
179        public String getTableFilter() {
180
181            return m_filter;
182        }
183
184        /**
185         * Gets type of element to open.<p>
186         *
187         * @return type of element
188         */
189        public I_CmsOuTreeType getType() {
190
191            return m_type;
192        }
193    }
194
195    /**State seperator. */
196    public static String STATE_SEPERATOR = A_CmsWorkplaceApp.PARAM_SEPARATOR;
197
198    /** Default tree type provider. */
199    private static final CmsDefaultTreeTypeProvider DEFAULT_TREETYPES = new CmsDefaultTreeTypeProvider();
200
201    /** The log object for this class. */
202    private static final Log LOG = CmsLog.getLog(CmsAccountsApp.class);
203
204    /**Button to add an element. */
205    protected Button m_addElementButton;
206
207    /**CmsObject. */
208    protected CmsObject m_cms;
209
210    /**vaadin component. */
211    protected CmsInfoButton m_infoButton;
212
213    /**vaadin component.*/
214    protected Button m_newButton;
215
216    /**vaadin component.*/
217    protected Button m_toggleButtonGroups;
218
219    /**vaadin component.*/
220    protected Button m_toggleButtonRole;
221
222    /**vaadin component.*/
223    protected Button m_toggleButtonUser;
224
225    /**Don't handle change event flag.*/
226    boolean m_doNotChange;
227
228    /**State bean. */
229    CmsStateBean m_stateBean;
230
231    /**Base ou. */
232    private String m_baseOU = "";
233
234    /**vaadin component.*/
235    private ComboBox m_filter;
236
237    /** The file table filter input. */
238    private TextField m_filterTable;
239
240    /**Class to handle visible and managable ous. */
241    private CmsOUHandler m_ouHandler;
242
243    /** The folder tree. */
244    private CmsOuTree m_ouTree;
245
246    /** Map for the cached password reset states. */ 
247    private Map<CmsUUID, Boolean> m_passwordResetStateCache = new ConcurrentHashMap<>();
248
249    /**vaadin component.*/
250    private HorizontalSplitPanel m_splitScreen;
251
252    /**vaadin component.*/
253    private I_CmsFilterableTable m_table;
254
255    /**
256     * constructor.<p>
257     */
258    public CmsAccountsApp() {
259
260        super();
261        try {
262            m_cms = OpenCms.initCmsObject(A_CmsUI.getCmsObject());
263            m_cms.getRequestContext().setSiteRoot("");
264            m_ouHandler = new CmsOUHandler(m_cms);
265            m_baseOU = m_ouHandler.getBaseOU();
266
267        } catch (
268
269        CmsException e) {
270            //}
271        }
272        m_rootLayout.setMainHeightFull(true);
273        m_splitScreen = new HorizontalSplitPanel();
274        m_splitScreen.setSizeFull();
275        m_splitScreen.setSplitPosition(CmsFileExplorer.LAYOUT_SPLIT_POSITION, Unit.PIXELS);
276        m_rootLayout.setMainContent(m_splitScreen);
277        m_ouTree = new CmsOuTree(m_cms, this, m_baseOU);
278        m_splitScreen.setFirstComponent(m_ouTree);
279
280    }
281
282    /**
283     * Creates info panel for OUs.<p>
284     *
285     *
286     * @param ou to get panel for
287     * @return CmsResourceInfo
288     */
289    public static CmsResourceInfo getOUInfo(CmsOrganizationalUnit ou) {
290
291        String style = OpenCmsTheme.ICON_OU;
292        if (ou.hasFlagWebuser()) {
293            style = OpenCmsTheme.ICON_OU_WEB;
294        }
295        CmsCssIcon image = new CmsCssIcon(style);
296        return new CmsResourceInfo(
297            ou.getDisplayName(A_CmsUI.get().getLocale()),
298            ou.getDescription(A_CmsUI.get().getLocale()),
299            image);
300    }
301
302    /**
303     * Creates info panel for principals.<p>
304     *
305     * @param principal to get info panel for
306     * @return CmsResourceInfo
307     */
308    public static CmsResourceInfo getPrincipalInfo(I_CmsPrincipal principal) {
309
310        if (principal == null) {
311            return null;
312        }
313        if (principal instanceof CmsUser) {
314            CmsUser user = (CmsUser)principal;
315            CmsUserIconHelper helper = OpenCms.getWorkplaceAppManager().getUserIconHelper();
316            return new CmsResourceInfo(
317                user.getName(),
318                user.getEmail(),
319                new ExternalResource(helper.getTinyIconPath(A_CmsUI.getCmsObject(), user)));
320        }
321        if (principal.getId().equals(CmsAccessControlEntry.PRINCIPAL_ALL_OTHERS_ID)) {
322            return new CmsResourceInfo(
323                CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_LABEL_ALLOTHERS_0),
324                CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_DESCRIPTION_ALLOTHERS_0),
325                new CmsCssIcon(OpenCmsTheme.ICON_PRINCIPAL_ALL));
326        }
327        if (principal.getId().equals(CmsAccessControlEntry.PRINCIPAL_OVERWRITE_ALL_ID)) {
328            return new CmsResourceInfo(
329                CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_LABEL_OVERWRITEALL_0),
330                CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_DESCRIPTION_OVERWRITEALL_0),
331                new CmsCssIcon(OpenCmsTheme.ICON_PRINCIPAL_OVERWRITE));
332        }
333        CmsRole role = CmsRole.valueOfId(principal.getId());
334        if (role != null) {
335            return new CmsResourceInfo(
336                role.getName(A_CmsUI.get().getLocale()),
337                role.getDescription(A_CmsUI.get().getLocale()),
338                new CmsCssIcon(OpenCmsTheme.ICON_ROLE));
339        }
340        return new CmsResourceInfo(
341            principal.getName(),
342            principal.getDescription(A_CmsUI.get().getLocale()),
343            new CmsCssIcon(OpenCmsTheme.ICON_GROUP));
344    }
345
346    /**
347     * Adds additional properties for groups to a container.
348     *
349     * @param container the container to update
350     */
351    public void addGroupContainerProperties(IndexedContainer container) {
352
353        // do nothing
354
355    }
356
357    /**
358     * Adds additional properties for users to a container.
359     *
360     * @param container the container to update
361     */
362    public void addUserContainerProperties(IndexedContainer container) {
363
364        // do nothing
365
366    }
367
368    /**
369     * Checks if the given user is editable.<p>
370     *
371     * @param id the id of the user
372     * @return true if the user is editable
373     */
374    public boolean canEditUser(CmsUUID id) {
375
376        return true;
377    }
378
379    /**
380     * Checks if group members can be removed from the given OU.<p>
381     *
382     * @param group the group name
383     * @return true if group members can be removed from the given OU
384     */
385    public boolean canRemoveGroupMemebers(String group) {
386
387        return true;
388    }
389
390    /**
391     * Checks if a set of groups can be added to a user.<p>
392     *
393     * @param principal the user
394     * @param data the set of names of groups to check
395     *
396     * @return true if the groups can be added to the user
397     */
398    public boolean checkAddGroup(CmsUser principal, Set<String> data) {
399
400        return true;
401    }
402
403    /**
404     * Checks if a user can be removed from a set of groups.<p>
405     *
406     * @param principal the user
407     * @param items the names of groups to check
408     *
409     * @return true if the user can be removed from  the group
410     */
411    public boolean checkRemoveGroups(CmsUser principal, Set<String> items) {
412
413        return true;
414    }
415
416    /**
417     * Fills the container item representing a group.<p>
418     *
419     * @param item the item
420     * @param group the group
421     * @param indirects the indirect groups
422     */
423    public void fillGroupItem(Item item, CmsGroup group, List<CmsGroup> indirects) {
424
425        item.getItemProperty(TableProperty.Name).setValue(group.getName());
426        item.getItemProperty(TableProperty.Description).setValue(group.getDescription(A_CmsUI.get().getLocale()));
427        item.getItemProperty(TableProperty.OU).setValue(group.getOuFqn());
428        if (indirects.contains(group)) {
429            item.getItemProperty(TableProperty.INDIRECT).setValue(Boolean.TRUE);
430        }
431    }
432
433    /**
434    * Gets the app id.<p>
435    *
436    * @return the app id
437    */
438    public String getAppId() {
439
440        return CmsAccountsAppConfiguration.APP_ID;
441    }
442
443    /**
444     * Gets a data container for the groups available to be added to a user, excluding some groups.<p>
445     *
446     * @param cms the current CMS context
447     * @param ouFqn the OU for which to get the groups
448     * @param propCaption the property for the caption
449     * @param propIcon the property for the icon
450     * @param propOu the property for the OU
451     * @param groupsOfUser the groups to exclude
452     * @param iconProvider the icon provider
453     *
454     * @return the container with the group data
455     */
456    public IndexedContainer getAvailableGroupsContainerWithout(
457        CmsObject cms,
458        String ouFqn,
459        String propCaption,
460        String propIcon,
461        String propOu,
462        List<CmsGroup> groupsOfUser,
463        Function<CmsGroup, CmsCssIcon> iconProvider) {
464
465        // TODO Auto-generated method stub
466        return CmsVaadinUtils.getAvailableGroupsContainerWithout(
467            cms,
468            ouFqn,
469            propCaption,
470            propIcon,
471            propOu,
472            groupsOfUser,
473            iconProvider);
474    }
475
476    /**
477     * Gets the group edit parameters for a given group.<p>
478     *
479     * @param group a group
480     *
481     * @return the group edit parameters for the group
482     */
483    public CmsGroupEditParameters getGroupEditParameters(CmsGroup group) {
484
485        CmsGroupEditParameters params = new CmsGroupEditParameters();
486        return params;
487    }
488
489    /**
490     * Gets the icon for a group.<p>
491     *
492     * @param group the group
493     * @return the icon for the group
494     */
495    public CmsCssIcon getGroupIcon(CmsGroup group) {
496
497        return new CmsCssIcon("oc-icon-24-group");
498    }
499
500    /** 
501     * Gets the cache for the password reset states.
502     * <p>The cache keys are user ids.
503     * 
504     * @return the cache for the password reset states 
505     */
506    public Map<CmsUUID, Boolean> getPasswordResetStateCache() {
507
508        return m_passwordResetStateCache;
509    }
510
511    /**
512     * Gets the user edit parameters.<p>
513     *
514     * @param user the user
515     * @return the user edit parameters
516     */
517    public CmsUserEditParameters getUserEditParameters(CmsUser user) {
518
519        CmsUserEditParameters params = new CmsUserEditParameters();
520        params.setEditEnabled(true);
521        params.setPasswordChangeEnabled(true);
522        return params;
523    }
524
525    /**
526     * Gets the container for the groups of an user for the purpose of editing them.<p>
527     *
528     * @param user the user
529     * @param propName the property for the name
530     * @param propIcon the property for the icon
531     * @param propStatus the property for the status
532     *
533     * @return the container with the user groups
534     */
535    public IndexedContainer getUserGroupsEditorContainer(
536        CmsUser user,
537        String propName,
538        String propIcon,
539        String propStatus) {
540
541        IndexedContainer container = new IndexedContainer();
542        container.addContainerProperty(propName, String.class, "");
543        container.addContainerProperty(CmsUserEditGroupsDialog.ID_OU, String.class, "");
544        container.addContainerProperty(propStatus, Boolean.class, Boolean.valueOf(true));
545        container.addContainerProperty(propIcon, CmsCssIcon.class, new CmsCssIcon("oc-icon-group-24"));
546        try {
547            for (CmsGroup group : m_cms.getGroupsOfUser(user.getName(), true)) {
548                Item item = container.addItem(group);
549                item.getItemProperty(propName).setValue(group.getSimpleName());
550                item.getItemProperty(CmsUserEditGroupsDialog.ID_OU).setValue(group.getOuFqn());
551                item.getItemProperty(propIcon).setValue(getGroupIcon(group));
552            }
553        } catch (CmsException e) {
554            LOG.error("Unable to read groups from user", e);
555        }
556        return container;
557    }
558
559    /**
560     * Gets list of users for organizational unit.<p>
561     *
562     * @param cms the CMS context
563     * @param ou the OU path
564     * @param recursive true if users from other OUs should be retrieved
565     *
566     * @return the list of users, without their additional info
567     *
568     * @throws CmsException if something goes wrong
569     */
570    public List<CmsUser> getUsersWithoutAdditionalInfo(
571        CmsObject cms,
572        I_CmsOuTreeType type,
573        String ou,
574        boolean recursive)
575    throws CmsException {
576
577        return CmsPrincipal.filterCoreUsers(
578            OpenCms.getOrgUnitManager().getUsersWithoutAdditionalInfo(cms, ou, recursive));
579    }
580
581    /**
582     * @see org.opencms.ui.dialogs.permissions.I_CmsPrincipalSelect#handlePrincipal(org.opencms.security.I_CmsPrincipal)
583     */
584    public void handlePrincipal(I_CmsPrincipal principal) {
585
586        if (m_stateBean.getType().isGroup()) {
587            try {
588                CmsGroup group = m_cms.readGroup(m_stateBean.getGroupID());
589                m_cms.addUserToGroup(principal.getName(), group.getName());
590
591            } catch (CmsException e) {
592                return;
593            }
594        }
595        if (m_stateBean.getType().isRole()) {
596            try {
597                OpenCms.getRoleManager().addUserToRole(
598                    m_cms,
599                    CmsRole.valueOfId(m_stateBean.getGroupID()).forOrgUnit(m_stateBean.getPath()),
600                    principal.getName());
601            } catch (CmsException e) {
602                return;
603            }
604        }
605        A_CmsUI.get().reload();
606    }
607
608    /**
609     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#initUI(org.opencms.ui.apps.I_CmsAppUIContext)
610     */
611    @Override
612    public void initUI(I_CmsAppUIContext context) {
613
614        context.addPublishButton(changed -> {/* do nothing*/});
615        super.initUI(context);
616    }
617
618    /**
619     * Checks if the given OU is manageable.<p>
620     *
621     * @param ou to check
622     * @return true if user is allowed to manage ou
623     */
624    public boolean isOUManagable(String ou) {
625
626        return m_ouHandler.isOUManagable(ou);
627    }
628
629    /**
630     * Checks if given ou is parent of a managable ou.<p>
631     *
632     * @param name to check
633     * @return boolean
634     */
635    public boolean isParentOfManagableOU(String name) {
636
637        return m_ouHandler.isParentOfManagableOU(name);
638    }
639
640    /**
641     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#openSubView(java.lang.String, boolean)
642     */
643    @Override
644    public void openSubView(String state, boolean updateState) {
645
646        if (updateState) {
647            CmsAppWorkplaceUi.get().changeCurrentAppState(state);
648        }
649
650        Component comp = getComponentForState(state);
651
652        updateInfoButton();
653        if (comp != null) {
654            VerticalLayout layout = new VerticalLayout();
655            layout.setSizeFull();
656            comp.setSizeFull();
657            layout.addComponent(m_table.getEmptyLayout());
658            layout.addComponent(m_table);
659            handleSetTable(m_table);
660            m_splitScreen.setSecondComponent(layout);
661        } else {
662            m_splitScreen.setSecondComponent(new Label("Malformed path, tool not available for path: " + state));
663            handleSetTable(null);
664        }
665        m_splitScreen.setSizeFull();
666        updateSubNav(getSubNavEntries(state));
667        updateBreadCrumb(getBreadCrumbForState(state));
668    }
669
670    /**
671     * Parses a given state string to state bean.<p>
672     *
673     * @param state to be read
674     * @param baseOU baseOu
675     * @return CmsStateBean
676     */
677    public CmsStateBean parseState(String state, String baseOU) {
678
679        String path = baseOU;
680        String filter = "";
681        I_CmsOuTreeType type = CmsOuTreeType.OU;
682        CmsUUID groupId = null;
683        List<String> fields = CmsStringUtil.splitAsList(state, STATE_SEPERATOR);
684        if (!fields.isEmpty()) {
685            if (fields.size() > 1) {
686                path = fields.get(1);
687                //Make sure to only show OUs which are under baseOU
688                if (path.equals("") | !path.startsWith(baseOU)) {
689                    path = baseOU;
690                }
691            }
692            for (I_CmsOuTreeType ty : getTreeTypeProvider().getTreeTypes()) {
693                if (fields.get(0).equals(ty.getId())) {
694                    type = ty;
695                }
696            }
697            if (fields.size() > 2) {
698                if (!CmsStringUtil.isEmptyOrWhitespaceOnly(fields.get(2))) {
699                    groupId = new CmsUUID(fields.get(2));
700                }
701            }
702            if (fields.size() > 3) {
703                filter = fields.get(3);
704            }
705        }
706        return new CmsStateBean(path, type, groupId, filter);
707    }
708
709    /**
710     * Reads the list of groups for an organizational unit.<p>
711     *
712     * @param cms the CMS context
713     * @param ou the OU path
714     * @param type the tree type
715     * @param subOus true if groups for sub-OUs should be read
716     * @return the list of groups for the OU
717     *
718     * @throws CmsException if something goes wrong
719     */
720    public List<CmsGroup> readGroupsForOu(CmsObject cms, String ou, I_CmsOuTreeType type, boolean subOus)
721    throws CmsException {
722
723        return CmsPrincipal.filterCoreGroups(OpenCms.getOrgUnitManager().getGroups(m_cms, ou, subOus));
724    }
725
726    /**
727     * Reloads the app with current state.<p>
728     */
729    public void reload() {
730
731        update(m_stateBean.getPath(), m_stateBean.getType(), m_stateBean.getGroupID());
732    }
733
734    /**
735     * Updates the app state.<p>
736     *
737     * @param ou to be opened
738     * @param type to be opened
739     * @param groupID to be openend(may be null)
740     */
741    public void update(String ou, I_CmsOuTreeType type, CmsUUID groupID) {
742
743        update(ou, type, groupID, m_filterTable.getValue());
744
745    }
746
747    /**
748     * Updates the app state.<p>
749     *
750     * @param ou to be opened
751     * @param type to be opened
752     * @param roleOrGroupID to be openend(may be null)
753     * @param filter filter string
754     */
755    public void update(String ou, I_CmsOuTreeType type, CmsUUID roleOrGroupID, String filter) {
756
757        CmsStateBean stateBean = new CmsStateBean(ou, type, roleOrGroupID, filter);
758
759        try {
760            m_ouTree.updateOU(OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, ou));
761        } catch (CmsException e) {
762            LOG.error("Unable to read ou: " + ou);
763        }
764        openSubView(stateBean.getState(), true);
765
766    }
767
768    /**
769     * Creates a table for displaying groups.<p>
770     *
771     * @param path the path
772     * @param cmsAccountsApp the app instance
773     * @param type the tree type
774     * @param toggle the value of the 'sub-OU' toggle
775     *
776     * @return the table
777     */
778    protected I_CmsFilterableTable createGroupTable(
779        String path,
780        CmsAccountsApp cmsAccountsApp,
781        I_CmsOuTreeType type,
782        boolean toggle) {
783
784        return new CmsGroupTable(path, cmsAccountsApp, type, toggle);
785    }
786
787    /**
788     * Creates the overview table for the given OU.<p>
789     *
790     * @param ou the OU path
791     * @return the overview table for the given OU
792     */
793    protected I_CmsFilterableTable createOUTable(String ou) {
794
795        return new CmsOUTable(ou, this);
796    }
797
798    /**
799     * Creates the role table for  the given OU.<p>
800     *
801     * @param ou the OU path
802     * @return the role table for the given OU
803     */
804    protected I_CmsFilterableTable createRoleTable(String ou) {
805
806        return new CmsRoleTable(this, ou);
807    }
808
809    /**
810     * Creates user table for a specific group or role.<p>
811     *
812     * @param ou the OU path
813     * @param groupID the group id
814     * @param type the tree type
815     * @param showAll true if all users should be shown
816     * @param cmsAccountsApp the app instance
817     *
818     * @return the user table
819     */
820    protected I_CmsFilterableTable createUserTable(
821        String ou,
822        CmsUUID groupID,
823        I_CmsOuTreeType type,
824        boolean showAll,
825        CmsAccountsApp cmsAccountsApp) {
826
827        return new CmsUserTable(ou, groupID, type, showAll, cmsAccountsApp);
828    }
829
830    /**
831     * Creates the user table for an OU.<p>
832     *
833     * @param ou the OU path
834     * @param type the tree type
835     * @param cmsAccountsApp the app instance
836     * @param buttonPressed true if toggle button for users is active
837
838     * @return the user table
839     */
840    protected I_CmsFilterableTable createUserTable(
841        String ou,
842        I_CmsOuTreeType type,
843        CmsAccountsApp cmsAccountsApp,
844        boolean buttonPressed) {
845
846        return new CmsUserTable(ou, type, cmsAccountsApp, buttonPressed);
847    }
848
849    /**
850     * Filters table.<p>
851     *"
852     * @param text for filter
853     */
854    protected void filterTable(String text) {
855
856        if (m_table != null) {
857            m_table.filter(text);
858        }
859    }
860
861    /**
862     * Gets the additional buttons to display.<p>
863     *
864     * @return the additional buttons to display
865     */
866    protected List<Button> getAdditionalButtons() {
867
868        return new ArrayList<>();
869    }
870
871    /**
872     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#getBreadCrumbForState(java.lang.String)
873     */
874    @Override
875    protected LinkedHashMap<String, String> getBreadCrumbForState(String state) {
876
877        try {
878            CmsStateBean bean = parseState(state, m_baseOU);
879            String[] ouPath = bean.getPath().split("/");
880            LinkedHashMap<String, String> crumbs = new LinkedHashMap<String, String>();
881
882            if ((bean.getPath().equals(m_baseOU))
883                && (CmsOuTreeType.OU.equals(bean.getType()) | (bean.getType() == null))) {
884                crumbs.put(
885                    "",
886                    CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_TOOL_NAME_0)
887                        + " ("
888                        + OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, m_baseOU).getDisplayName(
889                            A_CmsUI.get().getLocale())
890                        + ")");
891                return crumbs;
892            }
893            CmsStateBean beanCr = new CmsStateBean(m_baseOU, CmsOuTreeType.OU, null, "");
894            crumbs.put(
895                getAppId() + "/" + beanCr.getState(),
896                CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_TOOL_NAME_0)
897                    + " ("
898                    + OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, m_baseOU).getDisplayName(
899                        A_CmsUI.get().getLocale())
900                    + ")");
901            String base = "";
902            String pathOfLastElement = "";
903            for (String oP : ouPath) {
904                if (!oP.isEmpty()) {
905                    if ((oP + base).length() > m_baseOU.length()) {
906                        if (oP.equals(ouPath[ouPath.length - 1])) {
907                            CmsStateBean beanCrumb = new CmsStateBean(base + oP, CmsOuTreeType.OU, null, "");
908                            pathOfLastElement = getAppId() + "/" + beanCrumb.getState();
909                            crumbs.put("", oP);
910                        } else {
911                            CmsStateBean beanCrumb = new CmsStateBean(base + oP, CmsOuTreeType.OU, null, "");
912                            crumbs.put(getAppId() + "/" + beanCrumb.getState(), oP);
913                        }
914                    }
915                    base += oP + "/";
916                }
917            }
918            if (bean.getType() != null) {
919                if (!bean.getType().equals(CmsOuTreeType.OU)) {
920                    if (!pathOfLastElement.isEmpty()) {
921                        crumbs.put(pathOfLastElement, crumbs.get(""));
922                        crumbs.remove("");
923                    }
924                    if (bean.getGroupID() == null) {
925                        crumbs.put("", bean.getType().getName());
926                    } else {
927                        CmsStateBean beanCrumb = new CmsStateBean(bean.getPath(), bean.getType(), null, "");
928                        crumbs.put(getAppId() + "/" + beanCrumb.getState(), beanCrumb.getType().getName());
929                        if (bean.getType().equals(CmsOuTreeType.ROLE)) {
930                            crumbs.put("", CmsRole.valueOfId(bean.getGroupID()).getName(A_CmsUI.get().getLocale()));
931                        } else {
932                            crumbs.put("", m_cms.readGroup(bean.getGroupID()).getSimpleName());
933                        }
934                    }
935                }
936            }
937            return crumbs;
938        } catch (CmsException e) {
939            return null;
940        }
941    }
942
943    /**
944     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#getComponentForState(java.lang.String)
945     */
946    @Override
947    protected Component getComponentForState(String state) {
948
949        m_stateBean = parseState(state, m_baseOU);
950
951        if (m_filter == null) {
952            iniButtons();
953        }
954
955        m_doNotChange = true;
956
957        m_filter.setValue(m_stateBean.getPath());
958        if (!CmsStringUtil.isEmptyOrWhitespaceOnly(m_stateBean.getTableFilter())) {
959            m_filterTable.setValue(m_stateBean.getTableFilter());
960        } else {
961            m_filterTable.setValue("");
962        }
963
964        m_newButton.setVisible((m_stateBean.getGroupID() == null) & isOUManagable(m_stateBean.getPath()));
965        m_toggleButtonRole.setVisible(m_stateBean.getType().isRole() && (m_stateBean.getGroupID() != null));
966        m_toggleButtonUser.setVisible(m_stateBean.getType().isUser());
967
968        m_toggleButtonGroups.setVisible(m_stateBean.getType().isGroup() && (m_stateBean.getGroupID() == null));
969        m_infoButton.setVisible(
970            m_stateBean.getType().isUser()
971                || (m_stateBean.getType().isRole() && (m_stateBean.getGroupID() != null))
972                || (m_stateBean.getType().isGroup() && (m_stateBean.getGroupID() != null)));
973        m_addElementButton.setVisible(
974            (m_stateBean.getType().isGroup() || m_stateBean.getType().isRole()) & (m_stateBean.getGroupID() != null));
975        m_ouTree.openPath(m_stateBean.getPath(), m_stateBean.getType(), m_stateBean.getGroupID());
976
977        m_doNotChange = false;
978        I_CmsFilterableTable table = null;
979        if (m_stateBean.getType().equals(CmsOuTreeType.OU)) {
980            m_table = createOUTable(m_stateBean.getPath());
981            table = m_table;
982        }
983        if (m_stateBean.getType().isUser()) {
984            m_table = createUserTable(
985                m_stateBean.getPath(),
986                m_stateBean.getType(),
987                this,
988                CmsVaadinUtils.isButtonPressed(m_toggleButtonUser));
989            table = m_table;
990        }
991        if (m_stateBean.getType().isGroup()) {
992            if (m_stateBean.getGroupID() == null) {
993                m_table = createGroupTable(
994                    m_stateBean.getPath(),
995                    this,
996                    m_stateBean.getType(),
997                    CmsVaadinUtils.isButtonPressed(m_toggleButtonGroups));
998                table = m_table;
999            } else {
1000                m_table = createUserTable(
1001                    m_stateBean.getPath(),
1002                    m_stateBean.getGroupID(),
1003                    m_stateBean.getType(),
1004                    false,
1005                    this);
1006                table = m_table;
1007            }
1008        }
1009        if (m_stateBean.getType().isRole()) {
1010            if (m_stateBean.getGroupID() == null) {
1011                m_table = createRoleTable(m_stateBean.getPath());
1012                table = m_table;
1013            } else {
1014                m_table = createUserTable(
1015                    m_stateBean.getPath(),
1016                    m_stateBean.getGroupID(),
1017                    m_stateBean.getType(),
1018                    CmsVaadinUtils.isButtonPressed(m_toggleButtonRole),
1019                    this);
1020                table = m_table;
1021            }
1022        }
1023        if ((table != null) && !CmsStringUtil.isEmptyOrWhitespaceOnly(m_filterTable.getValue())) {
1024            table.filter(m_filterTable.getValue());
1025        }
1026        return table;
1027    }
1028
1029    /**
1030     * Gets the group-, role-, or ou name.<p>
1031     *
1032     * @param stateBean to be read out
1033     * @return Name
1034     */
1035    protected String getElementName(CmsStateBean stateBean) {
1036
1037        if (stateBean.getType().equals(CmsOuTreeType.USER)) {
1038            try {
1039                return OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, stateBean.getPath()).getDisplayName(
1040                    A_CmsUI.get().getLocale());
1041            } catch (CmsException e) {
1042                LOG.error("Unable to read OU", e);
1043            }
1044        }
1045        if (stateBean.getType().equals(CmsOuTreeType.ROLE)) {
1046            return CmsRole.valueOfId(stateBean.getGroupID()).getName(A_CmsUI.get().getLocale());
1047        } else {
1048            try {
1049                return m_cms.readGroup(stateBean.getGroupID()).getSimpleName();
1050            } catch (CmsException e) {
1051                LOG.error("Unable to read group", e);
1052            }
1053        }
1054        return "";
1055    }
1056
1057    /**
1058     * Gets the full user List including additionInfos.<p>
1059     *
1060     * @param users user list
1061     * @return List of user
1062     */
1063    protected List<CmsUser> getFullUser(List<CmsUser> users) {
1064
1065        List<CmsUser> res = new ArrayList<CmsUser>();
1066        for (CmsUser user : users) {
1067            try {
1068                res.add(m_cms.readUser(user.getId()));
1069            } catch (CmsException e) {
1070                LOG.error("Unable to read user", e);
1071            }
1072        }
1073        return res;
1074    }
1075
1076    /**
1077     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#getSubNavEntries(java.lang.String)
1078     */
1079    @Override
1080    protected List<NavEntry> getSubNavEntries(String state) {
1081
1082        return null;
1083    }
1084
1085    /**
1086     * Get the current toggle button.<p>
1087     *
1088     * @param stateBean to be read out
1089     * @return Button
1090     */
1091    protected Button getToggleButton(CmsStateBean stateBean) {
1092
1093        if (stateBean.getType().equals(CmsOuTreeType.USER)) {
1094            return m_toggleButtonUser;
1095        }
1096        if (stateBean.getType().equals(CmsOuTreeType.ROLE)) {
1097            return m_toggleButtonRole;
1098        } else {
1099            return m_toggleButtonGroups;
1100        }
1101    }
1102
1103    /**
1104     * Gets the tree type provider.<p>
1105     *
1106     * @return the tree type provider
1107     */
1108    protected I_CmsTreeTypeProvider getTreeTypeProvider() {
1109
1110        return DEFAULT_TREETYPES;
1111    }
1112
1113    /**
1114     * Gets all currently visible user.<p>
1115     *
1116     * @return List of CmsUser
1117     */
1118    protected List<CmsUser> getVisibleUser() {
1119
1120        if (m_table instanceof CmsUserTable) {
1121            return ((CmsUserTable)m_table).getVisibleUser();
1122        }
1123        return null;
1124    }
1125
1126    /**
1127     * Called when new table is shown.<p>
1128     *
1129     * @param component the table that is displayed
1130     */
1131    protected void handleSetTable(Component component) {
1132
1133        // do nothing
1134    }
1135
1136    /**
1137     * Opens a dialog for a new item (ou, group or user).<p>
1138     */
1139    protected void openNewDialog() {
1140
1141        final Window window = CmsBasicDialog.prepareWindow(DialogWidth.wide);
1142        CmsBasicDialog dialog = new CmsNewElementDialog(m_cms, m_stateBean.getPath(), window, this);
1143        window.setContent(dialog);
1144        window.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_ADD_ELEMENT_0));
1145        A_CmsUI.get().addWindow(window);
1146    }
1147
1148    /**
1149     * opens a principle select dialog.<p>
1150     */
1151    void openAddUserDialog() {
1152
1153        CmsPrincipalSelectDialog dialog;
1154
1155        final Window window = CmsBasicDialog.prepareWindow(DialogWidth.max);
1156
1157        dialog = new CmsPrincipalSelectDialog(
1158            this,
1159            m_stateBean.getPath(),
1160            window,
1161            WidgetType.userwidget,
1162            true,
1163            CmsPrincipalSelect.PrincipalType.user);
1164
1165        try {
1166            dialog.setOuComboBoxEnabled(
1167                !OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, m_stateBean.getPath()).hasFlagWebuser()
1168                    | m_stateBean.getType().equals(CmsOuTreeType.ROLE));
1169        } catch (CmsException e) {
1170            LOG.error("Can not read OU.", e);
1171        }
1172        window.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_ADD_USER_TO_GROUP_0));
1173        window.setContent(dialog);
1174        A_CmsUI.get().addWindow(window);
1175
1176    }
1177
1178    /**
1179     * Toggles the table.<p>
1180     *
1181     * @param toggleButton the toggle button state
1182     */
1183    void toggleTable(Button toggleButton) {
1184
1185        I_CmsToggleTable table = (I_CmsToggleTable)m_table;
1186        table.toggle(!CmsVaadinUtils.isButtonPressed(toggleButton));
1187        CmsVaadinUtils.toggleButton(toggleButton);
1188        if (!CmsStringUtil.isEmptyOrWhitespaceOnly(m_filterTable.getValue())) {
1189            filterTable(m_filterTable.getValue());
1190        }
1191        updateInfoButton();
1192    }
1193
1194    /**
1195     * Initializes the toolbar buttons.<p>
1196     */
1197    private void iniButtons() {
1198
1199        m_newButton = CmsToolBar.createButton(
1200            FontOpenCms.WAND,
1201            CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_ADD_ELEMENT_0));
1202        m_newButton.addClickListener(new ClickListener() {
1203
1204            private static final long serialVersionUID = 1L;
1205
1206            public void buttonClick(ClickEvent event) {
1207
1208                openNewDialog();
1209            }
1210        });
1211        m_infoButton = new CmsInfoButton();
1212        Button csvButton = new Button(CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_EXPORT_ONLY_USER_0));
1213        csvButton.addClickListener(new ClickListener() {
1214
1215            private static final long serialVersionUID = 5472430305539438757L;
1216
1217            public void buttonClick(ClickEvent event) {
1218
1219                boolean includeTechnicalFields = false;
1220                try {
1221                    OpenCms.getRoleManager().checkRole(m_cms, CmsRole.ADMINISTRATOR);
1222                    includeTechnicalFields = true;
1223                } catch (CmsRoleViolationException e) {
1224                    // ok
1225                }
1226                Window window = CmsBasicDialog.prepareWindow(DialogWidth.wide);
1227                CmsUserCsvExportDialog dialog = new CmsUserCsvExportDialog(
1228                    getFullUser(getVisibleUser()),
1229                    m_stateBean.getPath(),
1230                    m_stateBean.getType(),
1231                    getElementName(m_stateBean),
1232                    CmsVaadinUtils.isButtonPressed(getToggleButton(m_stateBean)),
1233                    window,
1234                    includeTechnicalFields);
1235                window.setContent(dialog);
1236                A_CmsUI.get().addWindow(window);
1237
1238            }
1239
1240        });
1241        m_infoButton.setAdditionalButton(csvButton);
1242
1243        m_addElementButton = CmsToolBar.createButton(
1244            FontAwesome.PLUS,
1245            CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_ADD_USER_TO_GROUP_0));
1246        m_addElementButton.addClickListener(new ClickListener() {
1247
1248            private static final long serialVersionUID = 1859694635385726953L;
1249
1250            public void buttonClick(ClickEvent event) {
1251
1252                openAddUserDialog();
1253
1254            }
1255        });
1256
1257        m_toggleButtonRole = CmsToolBar.createButton(
1258            FontOpenCms.USERS,
1259            CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_ROLES_TOGGLE_0));
1260        m_toggleButtonRole.addClickListener(new ClickListener() {
1261
1262            private static final long serialVersionUID = 8265075332953321274L;
1263
1264            public void buttonClick(ClickEvent event) {
1265
1266                toggleTable(m_toggleButtonRole);
1267
1268            }
1269
1270        });
1271
1272        m_toggleButtonUser = CmsToolBar.createButton(
1273            FontOpenCms.USERS,
1274            CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_USER_TOGGLE_0));
1275        m_toggleButtonUser.addClickListener(new ClickListener() {
1276
1277            private static final long serialVersionUID = 8265075332953321274L;
1278
1279            public void buttonClick(ClickEvent event) {
1280
1281                toggleTable(m_toggleButtonUser);
1282
1283            }
1284
1285        });
1286
1287        m_toggleButtonGroups = CmsToolBar.createButton(
1288            FontOpenCms.USERS,
1289            CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_GROUPS_TOGGLE_0));
1290        m_toggleButtonGroups.addClickListener(new ClickListener() {
1291
1292            private static final long serialVersionUID = 8265075332953321274L;
1293
1294            public void buttonClick(ClickEvent event) {
1295
1296                toggleTable(m_toggleButtonGroups);
1297
1298            }
1299
1300        });
1301
1302        m_uiContext.addToolbarButton(m_newButton);
1303
1304        m_uiContext.addToolbarButton(m_addElementButton);
1305        m_uiContext.addToolbarButton(m_infoButton);
1306        m_uiContext.addToolbarButton(m_toggleButtonRole);
1307        m_uiContext.addToolbarButton(m_toggleButtonUser);
1308        m_uiContext.addToolbarButton(m_toggleButtonGroups);
1309
1310        for (Button button : getAdditionalButtons()) {
1311            m_uiContext.addToolbarButton(button);
1312        }
1313        m_filter = CmsVaadinUtils.getOUComboBox(m_cms, m_baseOU, LOG);
1314        m_filter.setWidth("379px");
1315        m_infoLayout.addComponent(m_filter, 0);
1316
1317        m_filterTable = new TextField();
1318        m_filterTable.setIcon(FontOpenCms.FILTER);
1319        m_filterTable.setInputPrompt(
1320            Messages.get().getBundle(UI.getCurrent().getLocale()).key(Messages.GUI_EXPLORER_FILTER_0));
1321        m_filterTable.addStyleName(ValoTheme.TEXTFIELD_INLINE_ICON);
1322        //            m_filterTable.setWidth("200px");
1323        m_filterTable.addTextChangeListener(new TextChangeListener() {
1324
1325            private static final long serialVersionUID = 1L;
1326
1327            public void textChange(TextChangeEvent event) {
1328
1329                filterTable(event.getText());
1330            }
1331        });
1332        m_filterTable.setWidth("200px");
1333        m_infoLayout.addComponent(m_filterTable);
1334        m_infoLayout.addStyleName("o-many-elements");
1335        m_filter.addValueChangeListener(new ValueChangeListener() {
1336
1337            private static final long serialVersionUID = 1L;
1338
1339            public void valueChange(ValueChangeEvent event) {
1340
1341                if ((m_stateBean.getType() != null) & !m_doNotChange) {
1342                    update((String)event.getProperty().getValue(), CmsOuTreeType.OU, null);
1343                } else {
1344                    //
1345                }
1346            }
1347        });
1348        if (!m_ouHandler.isOUManagable(m_stateBean.getPath())) {
1349            boolean change = m_doNotChange;
1350            m_doNotChange = false;
1351            m_filter.select(m_filter.getItemIds().iterator().next());
1352            m_doNotChange = change;
1353        }
1354    }
1355
1356    /**
1357     * Updates the info button.<p>
1358     */
1359    private void updateInfoButton() {
1360
1361        if (m_stateBean.getType().isUser()) {
1362            Map<String, String> dataMap = new LinkedHashMap<String, String>();
1363            dataMap.put(
1364                CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_COUNT_0),
1365                String.valueOf(((Table)m_table).size()));
1366            try {
1367                int count = getUsersWithoutAdditionalInfo(
1368                    m_cms,
1369                    m_stateBean.getType(),
1370                    m_stateBean.getPath(),
1371                    true).size();
1372                if (count > ((Table)m_table).size()) {
1373                    dataMap.put(
1374                        CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_TOT_COUNT_0),
1375                        String.valueOf(count));
1376                }
1377            } catch (CmsException e) {
1378                //;
1379            }
1380            m_infoButton.replaceData(dataMap);
1381        } else {
1382            int size = ((Table)m_table).size();
1383            if (m_table instanceof CmsUserTable) {
1384                size = ((CmsUserTable)m_table).getVisibleUser().size();
1385            }
1386            m_infoButton.replaceData(
1387                Collections.singletonMap(
1388                    CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_COUNT_0),
1389                    String.valueOf(size)));
1390        }
1391    }
1392
1393}