001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH (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 GmbH, 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.security; 029 030import java.util.Collections; 031import java.util.LinkedHashMap; 032import java.util.Map; 033import java.util.Set; 034 035/** 036 * An immutable permission set that contains both allowed and denied permissions as bitsets.<p> 037 * 038 * Currently supported permissions are:<ul> 039 * <li><code>{@link CmsPermissionSet#PERMISSION_READ}</code> (r) the right to read the contents of a resource</li> 040 * <li><code>{@link CmsPermissionSet#PERMISSION_WRITE}</code> (w) the right to write the contents of a resource</li> 041 * <li><code>{@link CmsPermissionSet#PERMISSION_VIEW}</code> (v) the right to see a resource in listings (workplace)</li> 042 * <li><code>{@link CmsPermissionSet#PERMISSION_CONTROL}</code> (c) the right to set permissions of a resource</li> 043 * <li><code>{@link CmsPermissionSet#PERMISSION_DIRECT_PUBLISH}</code> (d) the right direct publish a resource even without publish project permissions</li></ul><p> 044 * 045 * @since 6.0.0 046 */ 047public class CmsPermissionSet { 048 049 /** Permission set to check control access. */ 050 public static final CmsPermissionSet ACCESS_CONTROL = new CmsPermissionSet(CmsPermissionSet.PERMISSION_CONTROL); 051 052 /** Permission set to check direct publish permissions. */ 053 public static final CmsPermissionSet ACCESS_DIRECT_PUBLISH = new CmsPermissionSet( 054 CmsPermissionSet.PERMISSION_DIRECT_PUBLISH); 055 056 /** Permission set to check read access. */ 057 public static final CmsPermissionSet ACCESS_READ = new CmsPermissionSet(CmsPermissionSet.PERMISSION_READ); 058 059 /** Permission set to check view access. */ 060 public static final CmsPermissionSet ACCESS_VIEW = new CmsPermissionSet(CmsPermissionSet.PERMISSION_VIEW); 061 062 /** Permission set to check write access. */ 063 public static final CmsPermissionSet ACCESS_WRITE = new CmsPermissionSet(CmsPermissionSet.PERMISSION_WRITE); 064 065 /** The permission to control a resource. */ 066 public static final int PERMISSION_CONTROL = 8; 067 068 /** The permission to direct publish a resource. */ 069 public static final int PERMISSION_DIRECT_PUBLISH = 16; 070 071 /** No permissions for a resource (used especially for denied permissions). */ 072 public static final int PERMISSION_EMPTY = 0; 073 074 /** All allowed permissions for a resource. */ 075 public static final int PERMISSION_FULL = CmsPermissionSet.PERMISSION_READ 076 + CmsPermissionSet.PERMISSION_WRITE 077 + CmsPermissionSet.PERMISSION_VIEW 078 + CmsPermissionSet.PERMISSION_CONTROL 079 + CmsPermissionSet.PERMISSION_DIRECT_PUBLISH; 080 081 /** The permission to read a resource. */ 082 public static final int PERMISSION_READ = 1; 083 084 /** The permission to view a resource. */ 085 public static final int PERMISSION_VIEW = 4; 086 087 /** The permission to write a resource. */ 088 public static final int PERMISSION_WRITE = 2; 089 090 /** HashMap of all available permissions. */ 091 private static Map<String, Integer> m_permissions; 092 093 /** The set of allowed permissions. */ 094 protected int m_allowed; 095 096 /** The set of denied permissions. */ 097 protected int m_denied; 098 099 /** 100 * Constructor to create a permission set with preset allowed and denied permissions.<p> 101 * 102 * @param allowedPermissions the set of permissions to allow 103 * @param deniedPermissions the set of permissions to deny 104 */ 105 public CmsPermissionSet(int allowedPermissions, int deniedPermissions) { 106 107 m_allowed = allowedPermissions; 108 m_denied = deniedPermissions; 109 } 110 111 /** 112 * Constructor to create an empty permission set.<p> 113 */ 114 protected CmsPermissionSet() { 115 116 // noop 117 } 118 119 /** 120 * Constructor to create a permission set with preset allowed permissions.<p> 121 * 122 * @param allowedPermissions bitset of allowed permissions 123 */ 124 protected CmsPermissionSet(int allowedPermissions) { 125 126 m_allowed = allowedPermissions; 127 m_denied = 0; 128 } 129 130 /** 131 * Returns the message keys of each permission known in the system.<p> 132 * 133 * @return Enumeration of message keys 134 */ 135 public static Set<String> getPermissionKeys() { 136 137 return permissions().keySet(); 138 } 139 140 /** 141 * Returns the value of a single permission.<p> 142 * 143 * @param key the key of the permission 144 * @return the value of the given permission 145 */ 146 public static int getPermissionValue(String key) { 147 148 return (permissions().get(key)).intValue(); 149 } 150 151 /** 152 * Initializes and returns the linked hash map of all permissions known in the system.<p> 153 * 154 * @return a linked hash map with permission keys and values 155 */ 156 private static Map<String, Integer> permissions() { 157 158 if (m_permissions == null) { 159 LinkedHashMap<String, Integer> permissions = new LinkedHashMap<String, Integer>(); 160 permissions.put("GUI_PERMISSION_TYPE_READ_0", new Integer(CmsPermissionSet.PERMISSION_READ)); 161 permissions.put("GUI_PERMISSION_TYPE_WRITE_0", new Integer(CmsPermissionSet.PERMISSION_WRITE)); 162 permissions.put("GUI_PERMISSION_TYPE_VIEW_0", new Integer(CmsPermissionSet.PERMISSION_VIEW)); 163 permissions.put("GUI_PERMISSION_TYPE_CONTROL_0", new Integer(CmsPermissionSet.PERMISSION_CONTROL)); 164 permissions.put( 165 "GUI_PERMISSION_TYPE_DIRECT_PUBLISH_0", 166 new Integer(CmsPermissionSet.PERMISSION_DIRECT_PUBLISH)); 167 m_permissions = Collections.unmodifiableMap(permissions); 168 } 169 return m_permissions; 170 } 171 172 /** 173 * @see java.lang.Object#equals(java.lang.Object) 174 */ 175 @Override 176 public boolean equals(Object obj) { 177 178 if (obj == this) { 179 return true; 180 } 181 if (obj instanceof CmsPermissionSet) { 182 CmsPermissionSet other = (CmsPermissionSet)obj; 183 return (other.m_allowed == m_allowed) && (other.m_denied == m_denied); 184 } 185 return false; 186 } 187 188 /** 189 * Returns the currently allowed permissions of ths permission set.<p> 190 * 191 * @return the allowed permissions as bitset 192 */ 193 public int getAllowedPermissions() { 194 195 return m_allowed; 196 } 197 198 /** 199 * Returns the currently denied permissions of this permission set.<p> 200 * 201 * @return the denied permissions as bitset. 202 */ 203 public int getDeniedPermissions() { 204 205 return m_denied; 206 } 207 208 /** 209 * Returns the permissions calculated from this permission set.<p> 210 * These are all permissions allowed but not denied. 211 * 212 * @return the resulting permission set 213 */ 214 public int getPermissions() { 215 216 return m_allowed & ~m_denied; 217 } 218 219 /** 220 * Returns the string representation of the current permissions in this permission set.<p> 221 * 222 * @return string of the format {{+|-}{r|w|v|c|d}}* 223 */ 224 public String getPermissionString() { 225 226 StringBuffer p = new StringBuffer(""); 227 228 if ((m_denied & CmsPermissionSet.PERMISSION_READ) > 0) { 229 p.append("-r"); 230 } else if (requiresReadPermission()) { 231 p.append("+r"); 232 } 233 234 if ((m_denied & CmsPermissionSet.PERMISSION_WRITE) > 0) { 235 p.append("-w"); 236 } else if (requiresWritePermission()) { 237 p.append("+w"); 238 } 239 240 if ((m_denied & CmsPermissionSet.PERMISSION_VIEW) > 0) { 241 p.append("-v"); 242 } else if (requiresViewPermission()) { 243 p.append("+v"); 244 } 245 246 if ((m_denied & CmsPermissionSet.PERMISSION_CONTROL) > 0) { 247 p.append("-c"); 248 } else if (requiresControlPermission()) { 249 p.append("+c"); 250 } 251 252 if ((m_denied & CmsPermissionSet.PERMISSION_DIRECT_PUBLISH) > 0) { 253 p.append("-d"); 254 } else if (requiresDirectPublishPermission()) { 255 p.append("+d"); 256 } 257 258 return p.toString(); 259 } 260 261 /** 262 * @see java.lang.Object#hashCode() 263 */ 264 @Override 265 public int hashCode() { 266 267 return m_allowed * m_denied; 268 } 269 270 /** 271 * Returns true if control permissions (+c) are required by this permission set.<p> 272 * 273 * @return true if control permissions (+c) are required by this permission set 274 */ 275 public boolean requiresControlPermission() { 276 277 return 0 < (m_allowed & CmsPermissionSet.PERMISSION_CONTROL); 278 } 279 280 /** 281 * Returns true if direct publish permissions (+d) are required by this permission set.<p> 282 * 283 * @return true if direct publish permissions (+d) are required by this permission set 284 */ 285 public boolean requiresDirectPublishPermission() { 286 287 return 0 < (m_allowed & CmsPermissionSet.PERMISSION_DIRECT_PUBLISH); 288 } 289 290 /** 291 * Returns true if read permissions (+r) are required by this permission set.<p> 292 * 293 * @return true if read permissions (+r) are required by this permission set 294 */ 295 public boolean requiresReadPermission() { 296 297 return 0 < (m_allowed & CmsPermissionSet.PERMISSION_READ); 298 } 299 300 /** 301 * Returns true if view permissions (+v) are required by this permission set.<p> 302 * 303 * @return true if view permissions (+v) are required by this permission set 304 */ 305 public boolean requiresViewPermission() { 306 307 return 0 < (m_allowed & CmsPermissionSet.PERMISSION_VIEW); 308 } 309 310 /** 311 * Returns true if write permissions (+w) are required by this permission set.<p> 312 * 313 * @return true if write permissions (+w) are required by this permission set 314 */ 315 public boolean requiresWritePermission() { 316 317 return 0 < (m_allowed & CmsPermissionSet.PERMISSION_WRITE); 318 } 319 320 /** 321 * Returns the String representation of this permission set object.<p> 322 * 323 * @see java.lang.Object#toString() 324 */ 325 @Override 326 public String toString() { 327 328 return "[PermissionSet:] " + getPermissionString(); 329 } 330}