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