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}