001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.ui.dialogs.permissions; 029 030import org.opencms.file.CmsObject; 031import org.opencms.file.history.CmsHistoryPrincipal; 032import org.opencms.main.CmsException; 033import org.opencms.main.CmsLog; 034import org.opencms.security.CmsAccessControlEntry; 035import org.opencms.security.CmsPermissionSet; 036import org.opencms.security.CmsPrincipal; 037import org.opencms.security.CmsRole; 038import org.opencms.security.I_CmsPrincipal; 039import org.opencms.ui.A_CmsUI; 040import org.opencms.ui.CmsVaadinUtils; 041import org.opencms.workplace.commons.Messages; 042 043import java.util.Arrays; 044 045import org.apache.commons.logging.Log; 046 047import com.vaadin.ui.Component; 048import com.vaadin.ui.CssLayout; 049import com.vaadin.v7.data.Container; 050import com.vaadin.v7.data.Item; 051import com.vaadin.v7.data.Property.ValueChangeEvent; 052import com.vaadin.v7.data.Property.ValueChangeListener; 053import com.vaadin.v7.data.util.IndexedContainer; 054import com.vaadin.v7.shared.ui.label.ContentMode; 055import com.vaadin.v7.ui.CheckBox; 056import com.vaadin.v7.ui.DefaultFieldFactory; 057import com.vaadin.v7.ui.Field; 058import com.vaadin.v7.ui.Label; 059import com.vaadin.v7.ui.Table; 060import com.vaadin.v7.ui.TableFieldFactory; 061import com.vaadin.v7.ui.VerticalLayout; 062 063/** 064 * Displays the permission settings for a single principal.<p> 065 */ 066public class CmsPermissionView extends CssLayout { 067 068 /** 069 * Permission change handler.<p> 070 */ 071 public interface PermissionChangeHandler { 072 073 /** 074 * Called to delete a permission set.<p> 075 * 076 * @param principalType the principal type 077 * @param principalName the principal name 078 */ 079 void deletePermissionSet(String principalType, String principalName); 080 081 /** 082 * Called on view changes, allowing for resizing or centering.<p> 083 */ 084 void onViewChange(); 085 086 /** 087 * Sets a changed permission set.<p> 088 * 089 * @param permissionBean bean for permission 090 */ 091 void setPermissions(CmsPermissionBean permissionBean); 092 } 093 094 /** The logger instance for this class. */ 095 private static final Log LOG = CmsLog.getLog(CmsPermissionView.class); 096 097 /** The allowed table property id. */ 098 private static final String PROPERTY_ALLOWED = "allowed"; 099 100 /** The denied table property id. */ 101 private static final String PROPERTY_DENIED = "denied"; 102 103 /** The display allowed table property id. */ 104 private static final String PROPERTY_DISPLAY_ALLOWED = "display_allowed"; 105 106 /** The display denied table property id. */ 107 private static final String PROPERTY_DISPLAY_DENIED = "display_denied"; 108 109 /** The label table property id. */ 110 private static final String PROPERTY_LABEL = "label"; 111 112 /** The value table property id. */ 113 private static final String PROPERTY_VALUE = "value"; 114 115 /** The serial version id. */ 116 private static final long serialVersionUID = 3440901877277200393L; 117 118 /** Constant for unknown type. */ 119 private static final String UNKNOWN_TYPE = "Unknown"; 120 121 /** The value change listener for all fields of this view. */ 122 final ValueChangeListener m_valueChangeListener = new ValueChangeListener() { 123 124 private static final long serialVersionUID = 3923093753370151014L; 125 126 public void valueChange(ValueChangeEvent event) { 127 128 setPermissions(); 129 130 } 131 }; 132 133 /** The button bar. */ 134 private VerticalLayout m_buttonBar; 135 136 /** The permission change handler. */ 137 private PermissionChangeHandler m_changeHandler; 138 139 /** The editable flag. */ 140 private boolean m_editable; 141 142 /** The access control entry to display. */ 143 private CmsAccessControlEntry m_entry; 144 145 /** The table field factory. */ 146 private final TableFieldFactory m_fieldFactory = new DefaultFieldFactory() { 147 148 private static final long serialVersionUID = 1L; 149 150 /** 151 * @see com.vaadin.ui.DefaultFieldFactory#createField(com.vaadin.v7.data.Container, java.lang.Object, java.lang.Object, com.vaadin.ui.Component) 152 */ 153 @Override 154 public Field<?> createField(Container container, Object itemId, Object propertyId, Component uiContext) { 155 156 Field<?> result = null; 157 if (PROPERTY_ALLOWED.equals(propertyId) || PROPERTY_DENIED.equals(propertyId)) { 158 result = super.createField(container, itemId, propertyId, uiContext); 159 result.addValueChangeListener(m_valueChangeListener); 160 result.setCaption(""); 161 } 162 return result; 163 } 164 }; 165 166 /** The inherit check box. */ 167 private CheckBox m_inheritCheckbox; 168 169 /** The overwrite check box. */ 170 private CheckBox m_overwriteCheckbox; 171 172 /** The permissions table. */ 173 private Table m_permissions; 174 175 /** The principal name. */ 176 private String m_principalName; 177 178 /** The principal type. */ 179 private String m_principalType; 180 181 /** The responsible check box. */ 182 private CheckBox m_responsibleCheckbox; 183 184 /** 185 * Constructor.<p> 186 * 187 * @param entry the access control entry 188 * @param editable the editable flag 189 * @param isFolder the is folder flag 190 * @param inheritedFrom the inherited from path 191 * @param changeHandler the change handler 192 */ 193 public CmsPermissionView( 194 CmsAccessControlEntry entry, 195 boolean editable, 196 boolean isFolder, 197 String inheritedFrom, 198 PermissionChangeHandler changeHandler) { 199 200 m_changeHandler = changeHandler; 201 m_editable = editable; 202 m_entry = entry; 203 CmsVaadinUtils.readAndLocalizeDesign(this, CmsVaadinUtils.getWpMessagesForCurrentLocale(), null); 204 CmsObject cms = A_CmsUI.getCmsObject(); 205 m_responsibleCheckbox.addValueChangeListener(m_valueChangeListener); 206 m_overwriteCheckbox.addValueChangeListener(m_valueChangeListener); 207 m_inheritCheckbox.addValueChangeListener(m_valueChangeListener); 208 209 // get name and type of the current entry 210 I_CmsPrincipal principal; 211 try { 212 principal = CmsPrincipal.readPrincipalIncludingHistory(cms, entry.getPrincipal()); 213 } catch (CmsException e) { 214 principal = null; 215 LOG.debug(e.getLocalizedMessage(), e); 216 } 217 m_principalName = (principal != null) ? principal.getName() : entry.getPrincipal().toString(); 218 219 int flags = 0; 220 if ((principal != null) && (principal instanceof CmsHistoryPrincipal)) { 221 // there is a history principal entry, handle it 222 if (principal.isGroup()) { 223 flags = CmsAccessControlEntry.ACCESS_FLAGS_GROUP; 224 } else { 225 flags = CmsAccessControlEntry.ACCESS_FLAGS_USER; 226 } 227 } else if ((principal != null) && principal.isGroup()) { 228 flags = CmsAccessControlEntry.ACCESS_FLAGS_GROUP; 229 } else if ((principal != null) && principal.isUser()) { 230 flags = CmsAccessControlEntry.ACCESS_FLAGS_USER; 231 } else if ((m_principalName != null) 232 && m_principalName.equals(CmsAccessControlEntry.PRINCIPAL_ALL_OTHERS_ID.toString())) { 233 m_principalName = CmsAccessControlEntry.PRINCIPAL_ALL_OTHERS_NAME; 234 m_responsibleCheckbox.setVisible(false); 235 flags = CmsAccessControlEntry.ACCESS_FLAGS_ALLOTHERS; 236 } else if ((m_principalName != null) 237 && m_principalName.equals(CmsAccessControlEntry.PRINCIPAL_OVERWRITE_ALL_ID.toString())) { 238 m_principalName = CmsAccessControlEntry.PRINCIPAL_OVERWRITE_ALL_NAME; 239 flags = CmsAccessControlEntry.ACCESS_FLAGS_OVERWRITE_ALL; 240 } else { 241 // check if it is the case of a role 242 CmsRole role = CmsRole.valueOfId(entry.getPrincipal()); 243 if (role != null) { 244 m_principalName = role.getRoleName(); 245 flags = CmsAccessControlEntry.ACCESS_FLAGS_ROLE; 246 } 247 } 248 249 if ((flags > 0) && ((entry.getFlags() & flags) == 0)) { 250 // the flag is set to the wrong principal type 251 if (LOG.isErrorEnabled()) { 252 LOG.error( 253 Messages.get().getBundle(A_CmsUI.get().getLocale()).key( 254 Messages.ERR_INVALID_ACE_1, 255 entry.toString())); 256 } 257 entry = new CmsAccessControlEntry( 258 entry.getResource(), 259 entry.getPrincipal(), 260 entry.getAllowedPermissions(), 261 entry.getDeniedPermissions(), 262 (entry.getFlags() | flags)); 263 } else if (entry.getFlags() < CmsAccessControlEntry.ACCESS_FLAGS_USER) { 264 // the flag is set to NO principal type 265 if (LOG.isErrorEnabled()) { 266 LOG.error( 267 Messages.get().getBundle(A_CmsUI.get().getLocale()).key( 268 Messages.ERR_INVALID_ACE_1, 269 entry.toString())); 270 } 271 entry = new CmsAccessControlEntry( 272 entry.getResource(), 273 entry.getPrincipal(), 274 entry.getAllowedPermissions(), 275 entry.getDeniedPermissions(), 276 (entry.getFlags() | CmsAccessControlEntry.ACCESS_FLAGS_GROUP)); 277 } 278 279 m_principalType = getEntryType(entry.getFlags(), false); 280 281 if (m_principalName == null) { 282 m_principalName = ""; 283 } 284 285 boolean isOverwriteAll = false; 286 if (flags == CmsAccessControlEntry.ACCESS_FLAGS_OVERWRITE_ALL) { 287 isOverwriteAll = true; 288 } 289 290 if (!isOverwriteAll) { 291 292 // get all permissions of the current entry 293 CmsPermissionSet permissions = entry.getPermissions(); 294 IndexedContainer container = getPermissionContainer(permissions); 295 m_permissions.setContainerDataSource(container); 296 m_permissions.setColumnReorderingAllowed(false); 297 m_permissions.setColumnHeader(PROPERTY_LABEL, CmsVaadinUtils.getMessageText(Messages.GUI_PERMISSION_0)); 298 m_permissions.setColumnHeader( 299 PROPERTY_ALLOWED, 300 CmsVaadinUtils.getMessageText(Messages.GUI_PERMISSION_ALLOWED_0)); 301 m_permissions.setColumnHeader( 302 PROPERTY_DISPLAY_ALLOWED, 303 CmsVaadinUtils.getMessageText(Messages.GUI_PERMISSION_ALLOWED_0)); 304 m_permissions.setColumnHeader( 305 PROPERTY_DENIED, 306 CmsVaadinUtils.getMessageText(Messages.GUI_PERMISSION_DENIED_0)); 307 m_permissions.setColumnHeader( 308 PROPERTY_DISPLAY_DENIED, 309 CmsVaadinUtils.getMessageText(Messages.GUI_PERMISSION_DENIED_0)); 310 311 m_permissions.setPageLength(5); 312 m_permissions.setSortEnabled(false); 313 m_permissions.setVisible(true); 314 if (m_editable) { 315 316 m_permissions.setVisibleColumns(PROPERTY_LABEL, PROPERTY_ALLOWED, PROPERTY_DENIED); 317 m_permissions.setTableFieldFactory(m_fieldFactory); 318 m_permissions.setEditable(m_editable); 319 m_responsibleCheckbox.setValue(isResponsible(entry.getFlags())); 320 m_overwriteCheckbox.setValue(isOverWritingInherited(entry.getFlags())); 321 m_inheritCheckbox.setVisible(isFolder); 322 m_inheritCheckbox.setValue(Boolean.valueOf(m_entry.isInheriting())); 323 324 m_buttonBar.setVisible(true); 325 } else { 326 m_permissions.setVisibleColumns(PROPERTY_LABEL, PROPERTY_DISPLAY_ALLOWED, PROPERTY_DISPLAY_DENIED); 327 } 328 } 329 } 330 331 /** 332 * Gets the name of the principal.<p> 333 * 334 * @return String 335 */ 336 public String getPrincipalName() { 337 338 return m_principalName; 339 } 340 341 /** 342 * Hides the denied permissions column.<p> 343 */ 344 public void hideDeniedColumn() { 345 346 if (m_editable) { 347 m_permissions.setVisibleColumns(PROPERTY_LABEL, PROPERTY_ALLOWED); 348 } else { 349 m_permissions.setVisibleColumns(PROPERTY_LABEL, PROPERTY_DISPLAY_ALLOWED); 350 } 351 } 352 353 /** 354 * Checks if view is editable.<p> 355 * 356 * @return true if view is editable 357 */ 358 public boolean isEditable() { 359 360 return m_editable; 361 } 362 363 /** 364 * Determines the type of the current access control entry.<p> 365 * 366 * @param flags the value of the current flags 367 * @param all to include all types, or just user and groups 368 * 369 * @return String representation of the ace type 370 */ 371 protected String getEntryType(int flags, boolean all) { 372 373 for (int i = 0; i < getTypes(all).length; i++) { 374 if ((flags & getTypesInt()[i]) > 0) { 375 return getTypes(all)[i]; 376 } 377 } 378 return UNKNOWN_TYPE; 379 } 380 381 /** 382 * Returns a String array with the possible entry types.<p> 383 * 384 * @param all to include all types, or just user, groups and roles 385 * 386 * @return the possible types 387 */ 388 protected String[] getTypes(boolean all) { 389 390 if (!all) { 391 String[] array = new String[3]; 392 return Arrays.asList(CmsPermissionDialog.PRINCIPAL_TYPES).subList(0, 3).toArray(array); 393 } 394 return CmsPermissionDialog.PRINCIPAL_TYPES; 395 } 396 397 /** 398 * Returns an int array with possible entry types.<p> 399 * 400 * @return the possible types as int array 401 */ 402 protected int[] getTypesInt() { 403 404 return CmsPermissionDialog.PRINCIPAL_TYPES_INT; 405 } 406 407 /** 408 * Checks if a certain permission of a permission set is allowed.<p> 409 * 410 * @param p the current CmsPermissionSet 411 * @param value the int value of the permission to check 412 * @return true if the permission is allowed, otherwise false 413 */ 414 protected Boolean isAllowed(CmsPermissionSet p, int value) { 415 416 if ((p.getAllowedPermissions() & value) > 0) { 417 return Boolean.TRUE; 418 } 419 return Boolean.FALSE; 420 } 421 422 /** 423 * Checks if a certain permission of a permission set is denied.<p> 424 * 425 * @param p the current CmsPermissionSet 426 * @param value the int value of the permission to check 427 * @return true if the permission is denied, otherwise false 428 */ 429 protected Boolean isDenied(CmsPermissionSet p, int value) { 430 431 if ((p.getDeniedPermissions() & value) > 0) { 432 return Boolean.TRUE; 433 } 434 return Boolean.FALSE; 435 } 436 437 /** 438 * Check if the current permissions are overwriting the inherited ones.<p> 439 * 440 * @param flags value of all flags of the current entry 441 * @return true if permissions are overwriting the inherited ones, otherwise false 442 */ 443 protected Boolean isOverWritingInherited(int flags) { 444 445 if ((flags & CmsAccessControlEntry.ACCESS_FLAGS_OVERWRITE) > 0) { 446 return Boolean.TRUE; 447 } 448 return Boolean.FALSE; 449 } 450 451 /** 452 * Check if the user is a responsible for the resource.<p> 453 * 454 * @param flags value of all flags of the current entry 455 * @return true if user is responsible for the resource, otherwise false 456 */ 457 protected Boolean isResponsible(int flags) { 458 459 if ((flags & CmsAccessControlEntry.ACCESS_FLAGS_RESPONSIBLE) > 0) { 460 return Boolean.TRUE; 461 } 462 return Boolean.FALSE; 463 } 464 465 /** 466 * Deletes the current permission set.<p> 467 */ 468 void deletePermissionSet() { 469 470 m_changeHandler.deletePermissionSet(m_principalType, m_principalName); 471 } 472 473 /** 474 * Generates the permissions data container.<p> 475 * 476 * @param permissions the permission set 477 * 478 * @return the container 479 */ 480 IndexedContainer getPermissionContainer(CmsPermissionSet permissions) { 481 482 IndexedContainer result = new IndexedContainer(); 483 result.addContainerProperty(PROPERTY_LABEL, String.class, ""); 484 result.addContainerProperty(PROPERTY_VALUE, Integer.class, null); 485 result.addContainerProperty(PROPERTY_ALLOWED, Boolean.class, Boolean.FALSE); 486 result.addContainerProperty(PROPERTY_DISPLAY_ALLOWED, Label.class, null); 487 result.addContainerProperty(PROPERTY_DENIED, Boolean.class, Boolean.FALSE); 488 result.addContainerProperty(PROPERTY_DISPLAY_DENIED, Label.class, null); 489 for (String key : CmsPermissionSet.getPermissionKeys()) { 490 int flag = CmsPermissionSet.getPermissionValue(key); 491 Item entry = result.addItem(key); 492 entry.getItemProperty(PROPERTY_LABEL).setValue(CmsVaadinUtils.getMessageText(key)); 493 entry.getItemProperty(PROPERTY_ALLOWED).setValue(isAllowed(permissions, flag)); 494 entry.getItemProperty(PROPERTY_DISPLAY_ALLOWED).setValue(getCheckBoxLabel(isAllowed(permissions, flag))); 495 entry.getItemProperty(PROPERTY_DENIED).setValue(isDenied(permissions, flag)); 496 entry.getItemProperty(PROPERTY_DISPLAY_DENIED).setValue(getCheckBoxLabel(isDenied(permissions, flag))); 497 entry.getItemProperty(PROPERTY_VALUE).setValue(Integer.valueOf(flag)); 498 } 499 500 return result; 501 } 502 503 /** 504 * Sets the current permissions.<p> 505 */ 506 void setPermissions() { 507 508 IndexedContainer container = (IndexedContainer)m_permissions.getContainerDataSource(); 509 int allowed = 0; 510 int denied = 0; 511 for (Object itemId : container.getItemIds()) { 512 Item item = container.getItem(itemId); 513 Integer value = (Integer)item.getItemProperty(PROPERTY_VALUE).getValue(); 514 if (((Boolean)item.getItemProperty(PROPERTY_ALLOWED).getValue()).booleanValue()) { 515 allowed |= value.intValue(); 516 } 517 if (((Boolean)item.getItemProperty(PROPERTY_DENIED).getValue()).booleanValue()) { 518 denied |= value.intValue(); 519 } 520 } 521 int flags = m_entry.getFlags(); 522 523 // modify the ace flags to determine inheritance of the current ace 524 if (m_inheritCheckbox.getValue().booleanValue()) { 525 flags |= CmsAccessControlEntry.ACCESS_FLAGS_INHERIT; 526 } else { 527 flags &= ~CmsAccessControlEntry.ACCESS_FLAGS_INHERIT; 528 } 529 530 // modify the ace flags to determine overwriting of inherited ace 531 if (m_overwriteCheckbox.getValue().booleanValue()) { 532 flags |= CmsAccessControlEntry.ACCESS_FLAGS_OVERWRITE; 533 } else { 534 flags &= ~CmsAccessControlEntry.ACCESS_FLAGS_OVERWRITE; 535 } 536 537 if (m_responsibleCheckbox.getValue().booleanValue()) { 538 flags |= CmsAccessControlEntry.ACCESS_FLAGS_RESPONSIBLE; 539 } else { 540 flags &= ~CmsAccessControlEntry.ACCESS_FLAGS_RESPONSIBLE; 541 } 542 543 m_changeHandler.setPermissions(new CmsPermissionBean(m_principalType, m_principalName, allowed, denied, flags)); 544 } 545 546 /** 547 * Generates a check box label.<p> 548 * 549 * @param value the value to display 550 * 551 * @return the label 552 */ 553 private Label getCheckBoxLabel(Boolean value) { 554 555 String content; 556 if (value.booleanValue()) { 557 content = "<input type='checkbox' disabled='true' checked='true' />"; 558 } else { 559 content = "<input type='checkbox' disabled='true' />"; 560 } 561 562 return new Label(content, ContentMode.HTML); 563 } 564 565}