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