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.dialogs.permissions;
029
030import org.opencms.security.CmsPrincipal;
031import org.opencms.security.CmsRole;
032import org.opencms.security.I_CmsPrincipal;
033import org.opencms.ui.A_CmsUI;
034import org.opencms.ui.CmsVaadinUtils;
035import org.opencms.ui.components.CmsBasicDialog;
036import org.opencms.ui.components.CmsBasicDialog.DialogWidth;
037import org.opencms.ui.components.OpenCmsTheme;
038
039import java.util.Arrays;
040import java.util.Collection;
041import java.util.Collections;
042import java.util.HashSet;
043import java.util.LinkedHashMap;
044import java.util.Map;
045import java.util.Objects;
046import java.util.Set;
047
048import com.vaadin.server.FontAwesome;
049import com.vaadin.ui.Button;
050import com.vaadin.ui.Button.ClickEvent;
051import com.vaadin.ui.Button.ClickListener;
052import com.vaadin.ui.CustomComponent;
053import com.vaadin.ui.Window;
054import com.vaadin.v7.data.Item;
055import com.vaadin.v7.data.Property;
056import com.vaadin.v7.data.Validator;
057import com.vaadin.v7.data.Validator.InvalidValueException;
058import com.vaadin.v7.ui.ComboBox;
059import com.vaadin.v7.ui.Field;
060import com.vaadin.v7.ui.HorizontalLayout;
061import com.vaadin.v7.ui.TextField;
062
063/**
064 * The principal select widget.<p>
065 */
066public class CmsPrincipalSelect extends CustomComponent implements Field<String>, I_CmsPrincipalSelect {
067
068    /**
069     * Handles the principal selection.<p>
070     */
071    public interface I_PrincipalSelectHandler {
072
073        /**
074         * Called to select a principal.<p>
075         *
076         * @param principalType the principal type
077         * @param principalName the principal name
078         */
079        void onPrincipalSelect(String principalType, String principalName);
080    }
081
082    /** Type of principal. */
083    public static enum PrincipalType {
084        /** Groups. */
085        group,
086
087        /** Users. */
088        user,
089
090        /** Roles. */
091        role;
092    }
093
094    /** The widget types. */
095    public static enum WidgetType {
096
097        /** Select groups only. */
098        groupwidget(PrincipalType.group),
099        /** Select any principal. */
100        principalwidget(PrincipalType.group, PrincipalType.user, PrincipalType.role),
101        /** Select users only. */
102        userwidget(PrincipalType.user);
103
104        private Set<PrincipalType> m_principalTypes;
105
106        private WidgetType(PrincipalType... principalTypes) {
107
108            m_principalTypes = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(principalTypes)));
109        }
110
111        public Set<PrincipalType> getPrincipalTypes() {
112
113            return m_principalTypes;
114        }
115
116    }
117
118    /** The serial version id. */
119    private static final long serialVersionUID = 6944968889428174262L;
120
121    /** The add button. */
122    private Button m_addPermissionSetButton;
123
124    /** The principal name text field. */
125    private TextField m_principalName;
126
127    /** The type select box. */
128    private ComboBox m_principalTypeSelect;
129
130    /** The principal select handler. */
131    private I_PrincipalSelectHandler m_selectHandler;
132
133    /** The open principal select dialog button. */
134    private Button m_selectPrincipalButton;
135
136    /** The widget type. */
137    private WidgetType m_widgetType;
138
139    /** The principal select dialog window. */
140    private Window m_window;
141
142    /** The main layout. */
143    private HorizontalLayout m_main;
144
145    /**Indicates if web ous should be included. */
146    private boolean m_includeWebOus = true;
147
148    /** Controls whether only real users/groups or also pseudo-principals like ALL_OTHERS should be shown. */
149    private boolean m_realOnly;
150
151    /**Ou. */
152    private String m_ou;
153
154    /** Is ou change enabled?*/
155    private boolean m_ouChangeEnabled = true;
156
157    /** True if role selection should be allowed. */
158    private boolean m_roleSelectionAllowed;
159
160    /**
161     * Constructor.<p>
162     */
163    public CmsPrincipalSelect() {
164
165        m_main = new HorizontalLayout();
166        m_main.setSpacing(true);
167        m_main.setWidth("100%");
168        setCompositionRoot(m_main);
169
170        m_widgetType = WidgetType.principalwidget;
171
172        ComboBox principalTypeSelect = new ComboBox();
173        principalTypeSelect.setWidth("150px");
174        Map<String, String> principalTypes = new LinkedHashMap<String, String>();
175        principalTypes.put(
176            I_CmsPrincipal.PRINCIPAL_USER,
177            CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_LABEL_USER_0));
178        principalTypes.put(
179            I_CmsPrincipal.PRINCIPAL_GROUP,
180            CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_LABEL_GROUP_0));
181        CmsVaadinUtils.prepareComboBox(principalTypeSelect, principalTypes);
182
183        principalTypeSelect.setNewItemsAllowed(false);
184        principalTypeSelect.setNullSelectionAllowed(false);
185        principalTypeSelect.select(I_CmsPrincipal.PRINCIPAL_USER);
186        m_main.addComponent(principalTypeSelect);
187        m_principalTypeSelect = principalTypeSelect;
188
189        m_principalName = new TextField();
190        m_principalName.setWidth("100%");
191        m_main.addComponent(m_principalName);
192        m_main.setExpandRatio(m_principalName, 2);
193
194        m_selectPrincipalButton = new Button(FontAwesome.USER);
195        m_selectPrincipalButton.addStyleName(OpenCmsTheme.BUTTON_ICON);
196        m_selectPrincipalButton.addClickListener(new ClickListener() {
197
198            private static final long serialVersionUID = 1L;
199
200            public void buttonClick(ClickEvent event) {
201
202                openPrincipalSelect();
203            }
204        });
205        m_main.addComponent(m_selectPrincipalButton);
206    }
207
208    /**
209     * @see com.vaadin.v7.data.Property.ValueChangeNotifier#addListener(com.vaadin.v7.data.Property.ValueChangeListener)
210     */
211    @SuppressWarnings({"deprecation", "javadoc"})
212    public void addListener(com.vaadin.v7.data.Property.ValueChangeListener listener) {
213
214        m_principalName.addListener(listener);
215    }
216
217    /**
218     * @see com.vaadin.data.Validatable#addValidator(com.vaadin.data.Validator)
219     */
220    public void addValidator(Validator validator) {
221
222        m_principalName.addValidator(validator);
223    }
224
225    /**
226     * @see com.vaadin.v7.data.Property.ValueChangeNotifier#addValueChangeListener(com.vaadin.v7.data.Property.ValueChangeListener)
227     */
228    public void addValueChangeListener(com.vaadin.v7.data.Property.ValueChangeListener listener) {
229
230        m_principalName.addValueChangeListener(listener);
231    }
232
233    /**
234     * @see com.vaadin.v7.ui.Field#clear()
235     */
236    public void clear() {
237
238        m_principalName.clear();
239    }
240
241    /**
242     * @see com.vaadin.v7.data.Buffered#commit()
243     */
244    public void commit() throws SourceException, InvalidValueException {
245
246        m_principalName.commit();
247    }
248
249    /**
250     * @see com.vaadin.v7.data.Buffered#discard()
251     */
252    public void discard() throws SourceException {
253
254        m_principalName.discard();
255    }
256
257    /**
258     * @see com.vaadin.ui.AbstractComponent#focus()
259     */
260    @Override
261    public void focus() {
262
263        m_principalName.focus();
264    }
265
266    /**
267     * @see com.vaadin.v7.data.Property.Viewer#getPropertyDataSource()
268     */
269    public Property getPropertyDataSource() {
270
271        return m_principalName.getPropertyDataSource();
272    }
273
274    /**
275     * @see com.vaadin.v7.ui.Field#getRequiredError()
276     */
277    public String getRequiredError() {
278
279        return m_principalName.getRequiredError();
280    }
281
282    /**
283     * @see com.vaadin.ui.Component.Focusable#getTabIndex()
284     */
285    public int getTabIndex() {
286
287        return m_principalName.getTabIndex();
288    }
289
290    /**
291     * @see com.vaadin.v7.data.Property#getType()
292     */
293    public Class<? extends String> getType() {
294
295        return m_principalName.getType();
296    }
297
298    /**
299     * @see com.vaadin.data.Validatable#getValidators()
300     */
301    public Collection<Validator> getValidators() {
302
303        return m_principalName.getValidators();
304    }
305
306    /**
307     * @see com.vaadin.v7.data.Property#getValue()
308     */
309    public String getValue() {
310
311        return m_principalName.getValue();
312    }
313
314    /**
315     * @see org.opencms.ui.dialogs.permissions.I_CmsPrincipalSelect#handlePrincipal(org.opencms.security.I_CmsPrincipal)
316     */
317    public void handlePrincipal(I_CmsPrincipal principal) {
318
319        if ((principal != null) && !Objects.equals(CmsPrincipal.getType(principal), m_principalTypeSelect.getValue())) {
320            m_principalTypeSelect.setValue(CmsPrincipal.getType(principal));
321        }
322        setValue(principal.getName());
323
324    }
325
326    /**
327     * @see com.vaadin.v7.data.Buffered#isBuffered()
328     */
329    public boolean isBuffered() {
330
331        return m_principalName.isBuffered();
332    }
333
334    /**
335     * @see com.vaadin.v7.ui.Field#isEmpty()
336     */
337    public boolean isEmpty() {
338
339        return m_principalName.isEmpty();
340    }
341
342    /**
343     * @see com.vaadin.data.Validatable#isInvalidAllowed()
344     */
345    public boolean isInvalidAllowed() {
346
347        return m_principalName.isInvalidAllowed();
348    }
349
350    /**
351     * @see com.vaadin.v7.data.BufferedValidatable#isInvalidCommitted()
352     */
353    public boolean isInvalidCommitted() {
354
355        return m_principalName.isInvalidCommitted();
356    }
357
358    /**
359     * @see com.vaadin.v7.data.Buffered#isModified()
360     */
361    public boolean isModified() {
362
363        return m_principalName.isModified();
364    }
365
366    public boolean isReadOnly() {
367
368        return super.isReadOnly();
369    }
370
371    /**
372     * @see com.vaadin.v7.ui.Field#isRequired()
373     */
374    public boolean isRequired() {
375
376        return m_principalName.isRequired();
377    }
378
379    /**
380     * @see com.vaadin.data.Validatable#isValid()
381     */
382    public boolean isValid() {
383
384        return m_principalName.isValid();
385    }
386
387    /**
388     * @see com.vaadin.data.Validatable#removeAllValidators()
389     */
390    public void removeAllValidators() {
391
392        m_principalName.removeAllValidators();
393    }
394
395    /**
396     * @see com.vaadin.v7.data.Property.ValueChangeNotifier#removeListener(com.vaadin.v7.data.Property.ValueChangeListener)
397     */
398    @SuppressWarnings({"deprecation", "javadoc"})
399    public void removeListener(com.vaadin.v7.data.Property.ValueChangeListener listener) {
400
401        m_principalName.removeListener(listener);
402    }
403
404    /**
405     * @see com.vaadin.data.Validatable#removeValidator(com.vaadin.data.Validator)
406     */
407    public void removeValidator(Validator validator) {
408
409        m_principalName.removeValidator(validator);
410    }
411
412    /**
413     * @see com.vaadin.v7.data.Property.ValueChangeNotifier#removeValueChangeListener(com.vaadin.v7.data.Property.ValueChangeListener)
414     */
415    public void removeValueChangeListener(com.vaadin.v7.data.Property.ValueChangeListener listener) {
416
417        m_principalName.removeValueChangeListener(listener);
418    }
419
420    /**
421     * @see com.vaadin.v7.data.Buffered#setBuffered(boolean)
422     */
423    public void setBuffered(boolean buffered) {
424
425        m_principalName.setBuffered(buffered);
426    }
427
428    /**
429     * Set if web Ous should be included. Default behavior is true.<p>
430     *
431     * @param include boolean
432     */
433    public void setIncludeWebOus(boolean include) {
434
435        m_includeWebOus = include;
436    }
437
438    /**
439     * @see com.vaadin.data.Validatable#setInvalidAllowed(boolean)
440     */
441    public void setInvalidAllowed(boolean invalidValueAllowed) throws UnsupportedOperationException {
442
443        m_principalName.setInvalidAllowed(invalidValueAllowed);
444    }
445
446    /**
447     * @see com.vaadin.data.BufferedValidatable#setInvalidCommitted(boolean)
448     */
449    public void setInvalidCommitted(boolean isCommitted) {
450
451        m_principalName.setInvalidCommitted(isCommitted);
452    }
453
454    /**
455     * Enable layout margins. Affects all four sides of the layout.
456     * This will tell the client-side implementation to leave extra space around the layout.
457     * The client-side implementation decides the actual amount, and it can vary between themes.<p>
458     *
459     * @param enabled <code>true</code> if margins should be enabled on all sides, false to disable all margins
460     */
461    public void setMargin(boolean enabled) {
462
463        ((HorizontalLayout)getCompositionRoot()).setMargin(enabled);
464    }
465
466    /**
467     * Set the ou.
468     *
469     * @param ou to choose principals for
470     */
471    public void setOU(String ou) {
472
473        m_ou = ou;
474    }
475
476    public void setOuChangeEnabled(boolean enabled) {
477
478        m_ouChangeEnabled = enabled;
479    }
480
481    /**
482     * Sets the principal type and clears the name.<p>
483     *
484     * @param type the principal type
485     */
486    public void setPrincipalType(String type) {
487
488        m_principalTypeSelect.setValue(type);
489    }
490
491    /**
492     * @see com.vaadin.v7.data.Property.Viewer#setPropertyDataSource(com.vaadin.v7.data.Property)
493     */
494    public void setPropertyDataSource(Property newDataSource) {
495
496        m_principalName.setPropertyDataSource(newDataSource);
497    }
498
499    public void setReadOnly(boolean readOnly) {
500
501        super.setReadOnly(readOnly);
502    }
503
504    /**
505     * Controls whether only real users/groups or also pseudo-principals like ALL_OTHERS should be shown.
506     *
507     *  @param realOnly if true, only real users / groups will be shown
508     */
509    public void setRealPrincipalsOnly(boolean realOnly) {
510
511        m_realOnly = realOnly;
512    }
513
514    /**
515     * @see com.vaadin.v7.ui.Field#setRequired(boolean)
516     */
517    public void setRequired(boolean required) {
518
519        m_principalName.setRequired(required);
520    }
521
522    /**
523     * @see com.vaadin.v7.ui.Field#setRequiredError(java.lang.String)
524     */
525    public void setRequiredError(String requiredMessage) {
526
527        m_principalName.setRequiredError(requiredMessage);
528    }
529
530    /**
531     * Enables/disables selection of the 'Roles' prinipal type.<p>
532     *
533     * @param editRoles true if the user should be allowed to select roles
534     */
535    public void setRoleSelectionAllowed(boolean editRoles) {
536
537        m_principalTypeSelect.removeItem(CmsRole.PRINCIPAL_ROLE);
538        if (editRoles) {
539            Item item = m_principalTypeSelect.addItem(CmsRole.PRINCIPAL_ROLE);
540            String roleText = CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_LABEL_ROLE_0);
541            item.getItemProperty(CmsVaadinUtils.PROPERTY_LABEL).setValue(roleText);
542        }
543        m_roleSelectionAllowed = editRoles;
544        m_principalTypeSelect.setNewItemsAllowed(!editRoles);
545
546    }
547
548    /**
549     * Sets the principal select handler.<p>
550     *
551     * @param selectHandler the principal select handler
552     */
553    public void setSelectHandler(I_PrincipalSelectHandler selectHandler) {
554
555        m_selectHandler = selectHandler;
556        enableSetButton(m_selectHandler != null);
557    }
558
559    /**
560     * @see com.vaadin.ui.Component.Focusable#setTabIndex(int)
561     */
562    public void setTabIndex(int tabIndex) {
563
564        m_principalName.setTabIndex(tabIndex);
565    }
566
567    /**
568     * @see com.vaadin.v7.data.Property#setValue(java.lang.Object)
569     */
570    public void setValue(String newValue) throws com.vaadin.v7.data.Property.ReadOnlyException {
571
572        m_principalName.setValue(newValue);
573    }
574
575    /**
576     * Sets the widget type.<p>
577     *
578     * @param type the widget type
579     */
580    public void setWidgetType(WidgetType type) {
581
582        m_widgetType = type;
583        m_principalTypeSelect.setVisible(m_widgetType.equals(WidgetType.principalwidget));
584        m_principalTypeSelect.setValue(
585            m_widgetType.equals(WidgetType.groupwidget)
586            ? I_CmsPrincipal.PRINCIPAL_GROUP
587            : I_CmsPrincipal.PRINCIPAL_USER);
588    }
589
590    /**
591     * @see com.vaadin.data.Validatable#validate()
592     */
593    public void validate() throws InvalidValueException {
594
595        m_principalName.validate();
596    }
597
598    /**
599     * @see com.vaadin.v7.data.Property.ValueChangeListener#valueChange(com.vaadin.v7.data.Property.ValueChangeEvent)
600     */
601    public void valueChange(com.vaadin.v7.data.Property.ValueChangeEvent event) {
602
603        m_principalName.valueChange(event);
604    }
605
606    /**
607     * Closes the principal select dialog window if present.<p>
608     */
609    protected void closeWindow() {
610
611        if (m_window != null) {
612            m_window.close();
613            m_window = null;
614        }
615    }
616
617    /**
618     * Sets the principal type and name.<p>
619     *
620     * @param type the principal type
621     * @param principalName the principal name
622     */
623    protected void setPrincipal(int type, String principalName) {
624
625        m_principalName.setValue(principalName);
626
627        String typeName = null;
628        switch (type) {
629            case 0:
630                typeName = I_CmsPrincipal.PRINCIPAL_GROUP;
631                break;
632            case 1:
633            default:
634                typeName = I_CmsPrincipal.PRINCIPAL_USER;
635                break;
636        }
637        if (typeName != null) {
638            m_principalTypeSelect.setValue(typeName);
639        }
640    }
641
642    /**
643     * Calls the principal select handler.<p>
644     */
645    void onSelect() {
646
647        if (m_selectHandler != null) {
648            String principalType = (String)m_principalTypeSelect.getValue();
649            if (CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_LABEL_ROLE_0).equals(
650                principalType)) {
651                principalType = CmsRole.PRINCIPAL_ROLE;
652            }
653            m_selectHandler.onPrincipalSelect(principalType, m_principalName.getValue());
654        }
655    }
656
657    /**
658     * Opens the principal select dialog window.<p>
659     */
660    void openPrincipalSelect() {
661
662        CmsPrincipalSelectDialog dialog;
663
664        m_window = CmsBasicDialog.prepareWindow(DialogWidth.max);
665        CmsPrincipalSelect.PrincipalType defaultType = CmsPrincipalSelect.PrincipalType.group;
666        if (m_principalTypeSelect.getValue().equals(I_CmsPrincipal.PRINCIPAL_USER)) {
667            defaultType = CmsPrincipalSelect.PrincipalType.user;
668        } else if (m_principalTypeSelect.getValue().equals(CmsRole.PRINCIPAL_ROLE)) {
669            defaultType = CmsPrincipalSelect.PrincipalType.role;
670        }
671
672        dialog = new CmsPrincipalSelectDialog(
673            this,
674            m_ou == null ? A_CmsUI.getCmsObject().getRequestContext().getOuFqn() : m_ou,
675            m_window,
676            m_widgetType,
677            m_realOnly,
678            defaultType,
679            m_includeWebOus,
680            m_roleSelectionAllowed);
681
682        dialog.setOuComboBoxEnabled(m_ouChangeEnabled);
683
684        m_window.setCaption(
685            CmsVaadinUtils.getMessageText(
686                org.opencms.workplace.commons.Messages.GUI_PRINCIPALSELECTION_LIST_ACTION_SELECT_NAME_0));
687        m_window.setContent(dialog);
688        A_CmsUI.get().addWindow(m_window);
689    }
690
691    /**
692     * Sets the add permission button enabled.<p>
693     *
694     * @param enabled <code>true</code> to enable the button
695     */
696    private void enableSetButton(boolean enabled) {
697
698        if (enabled) {
699            if (m_addPermissionSetButton == null) {
700                m_addPermissionSetButton = new Button(FontAwesome.PLUS);
701                m_addPermissionSetButton.addStyleName(OpenCmsTheme.BUTTON_ICON);
702                m_addPermissionSetButton.addClickListener(new ClickListener() {
703
704                    private static final long serialVersionUID = 1L;
705
706                    public void buttonClick(ClickEvent event) {
707
708                        onSelect();
709                    }
710                });
711                m_main.addComponent(m_addPermissionSetButton);
712            }
713        } else if (m_addPermissionSetButton != null) {
714            m_main.removeComponent(m_addPermissionSetButton);
715            m_addPermissionSetButton = null;
716        }
717    }
718}