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