001/* 002 * (C) Copyright 2006-2007 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nuxeo - initial API and implementation 018 * 019 * $Id$ 020 */ 021 022package org.nuxeo.ecm.webapp.security; 023 024import java.io.Serializable; 025import java.util.ArrayList; 026import java.util.HashMap; 027import java.util.Iterator; 028import java.util.List; 029import java.util.Map; 030 031import org.apache.commons.logging.Log; 032import org.apache.commons.logging.LogFactory; 033import org.nuxeo.common.utils.i18n.Labeler; 034import org.nuxeo.ecm.core.api.security.SecurityConstants; 035 036/** 037 * Holds the formatted security data, ready to be displayed. Holds the data on each map on the following structure: <br> 038 * <p> 039 * current doc grants: <br> 040 * user 1 - perm1, perm2 <br> 041 * user 2 - perm1, perm2 <br> 042 * user 3 - perm2 <br> 043 * current doc denies:<br> 044 * ... <br> 045 * parent doc grants:<br> 046 * ... <br> 047 * parent doc denies:<br> 048 * ...<br> 049 * <p> 050 * Also has methods that allow manipulation of the contained data, such as add/remove security privileges. The end 051 * result after add/remove has been called will be converted to a backend security DTO and then submitted on backend. 052 * 053 * @author Razvan Caraghin 054 */ 055public class SecurityData implements Serializable { 056 057 protected static final Labeler labeler = new Labeler("label.security.permission"); 058 059 private static final long serialVersionUID = -7958330304227141087L; 060 061 private static final Log log = LogFactory.getLog(SecurityData.class); 062 063 protected Map<String, List<String>> currentDocGrant = new HashMap<String, List<String>>(); 064 065 protected Map<String, List<String>> currentDocDeny = new HashMap<String, List<String>>(); 066 067 protected Map<String, List<String>> parentDocsGrant = new HashMap<String, List<String>>(); 068 069 protected Map<String, List<String>> parentDocsDeny = new HashMap<String, List<String>>(); 070 071 protected final List<String> currentDocumentUsers = new ArrayList<String>(); 072 073 protected final List<String> parentDocumentsUsers = new ArrayList<String>(); 074 075 protected String documentType = ""; 076 077 protected boolean needSave = false; 078 079 public void setNeedSave(boolean needSave) { 080 this.needSave = needSave; 081 } 082 083 public boolean getNeedSave() { 084 return needSave; 085 } 086 087 public Map<String, List<String>> getCurrentDocDeny() { 088 return currentDocDeny; 089 } 090 091 public void setCurrentDocDeny(Map<String, List<String>> deny) { 092 currentDocDeny = deny; 093 } 094 095 public Map<String, List<String>> getCurrentDocGrant() { 096 return currentDocGrant; 097 } 098 099 public void setCurrentDocGrant(Map<String, List<String>> grant) { 100 currentDocGrant = grant; 101 } 102 103 public Map<String, List<String>> getParentDocsDenyLabels() { 104 return buildLabelMap(parentDocsDeny); 105 } 106 107 /** 108 * @since 6.0 109 */ 110 public Map<String, List<String>> getCurrentDocDenyLabels() { 111 return buildLabelMap(currentDocDeny); 112 } 113 114 public Map<String, List<String>> getParentDocsDeny() { 115 return parentDocsDeny; 116 } 117 118 public void setParentDocsDeny(Map<String, List<String>> parentDocsDeny) { 119 this.parentDocsDeny = parentDocsDeny; 120 } 121 122 public Map<String, List<String>> getParentDocsGrant() { 123 return parentDocsGrant; 124 } 125 126 public Map<String, List<String>> getParentDocsGrantLabels() { 127 return buildLabelMap(parentDocsGrant); 128 } 129 130 /** 131 * @since 6.0 132 */ 133 public Map<String, List<String>> getCurrentDocGrantLabels() { 134 return buildLabelMap(currentDocGrant); 135 } 136 137 public void setParentDocsGrant(Map<String, List<String>> parentDocsGrant) { 138 this.parentDocsGrant = parentDocsGrant; 139 } 140 141 public List<String> getCurrentDocumentUsers() { 142 return currentDocumentUsers; 143 } 144 145 public List<String> getParentDocumentsUsers() { 146 return parentDocumentsUsers; 147 } 148 149 protected Map<String, List<String>> buildLabelMap(Map<String, List<String>> permissions) { 150 Map<String, List<String>> labelMap = new HashMap<String, List<String>>(); 151 152 for (String user : permissions.keySet()) { 153 List<String> labels = new ArrayList<String>(); 154 for (String perm : permissions.get(user)) { 155 labels.add(labeler.makeLabel(perm)); 156 } 157 labelMap.put(user, labels); 158 } 159 return labelMap; 160 } 161 162 public void rebuildUserLists() { 163 List<String> users = new ArrayList<String>(); 164 users.addAll(currentDocGrant.keySet()); 165 for (String user : currentDocDeny.keySet()) { 166 if (!users.contains(user)) { 167 users.add(user); 168 } 169 } 170 171 currentDocumentUsers.clear(); 172 currentDocumentUsers.addAll(users); 173 174 users.clear(); 175 users.addAll(parentDocsGrant.keySet()); 176 for (String user : parentDocsDeny.keySet()) { 177 if (!users.contains(user)) { 178 users.add(user); 179 } 180 } 181 182 parentDocumentsUsers.clear(); 183 parentDocumentsUsers.addAll(users); 184 } 185 186 /** 187 * Adds a privilege to the displayed list. This does not submit anything to the backend. 188 */ 189 public void addModifiablePrivilege(String principalName, String permissionName, boolean grant) { 190 if (null == principalName || null == permissionName) { 191 log.error("Null params received, returning..."); 192 return; 193 } 194 195 needSave = true; 196 if (grant) { 197 // if we already have the user stored with rights we dont add the 198 // user again, just update the list if needed 199 if (null != currentDocGrant.get(principalName)) { 200 // we already have the user - add the right to him 201 boolean shouldAddPermission = true; 202 for (String permission : currentDocGrant.get(principalName)) { 203 // only add the right to list if the right is not already 204 // there 205 if (permission.equals(permissionName)) { 206 shouldAddPermission = false; 207 break; 208 } 209 } 210 211 if (shouldAddPermission) { 212 currentDocGrant.get(principalName).add(permissionName); 213 } 214 } else { 215 // add the user and create a new list of rights for him 216 List<String> permissions = new ArrayList<String>(); 217 permissions.add(permissionName); 218 currentDocGrant.put(principalName, permissions); 219 } 220 } else { 221 // if we already have the user stored with rights we dont add the 222 // user again, just update the list if needed 223 if (null != currentDocDeny.get(principalName)) { 224 // we already have the user - add the right to him 225 boolean shouldAddPermission = true; 226 for (String permission : currentDocDeny.get(principalName)) { 227 // only add the right to list if the right is not already 228 // there 229 if (permission.equals(permissionName)) { 230 shouldAddPermission = false; 231 break; 232 } 233 } 234 235 if (shouldAddPermission) { 236 currentDocDeny.get(principalName).add(permissionName); 237 } 238 } else { 239 // add the user and create a new list of rights for him 240 List<String> permissions = new ArrayList<String>(); 241 permissions.add(permissionName); 242 currentDocDeny.put(principalName, permissions); 243 } 244 } 245 246 rebuildUserLists(); 247 } 248 249 /** 250 * Removes a privilege from the displayed list. This does not submit anything to backend. 251 * 252 * @return true if a privilege was indeed removed 253 */ 254 public boolean removeModifiablePrivilege(String principalName, String permissionName, boolean grant) { 255 256 if (null == principalName || null == permissionName) { 257 log.error("Null params received, returning..."); 258 return false; 259 } 260 261 needSave = true; 262 boolean removed = false; 263 if (grant) { 264 if (null != currentDocGrant.get(principalName)) { 265 // we have the specified user, check if we have the right 266 Iterator<String> permissionIterator = currentDocGrant.get(principalName).iterator(); 267 while (permissionIterator.hasNext()) { 268 if (permissionIterator.next().equals(permissionName)) { 269 permissionIterator.remove(); 270 removed = true; 271 break; 272 } 273 } 274 } 275 } else { 276 if (null != currentDocDeny.get(principalName)) { 277 // we have the specified user, check if we have the right 278 Iterator<String> permissionIterator = currentDocDeny.get(principalName).iterator(); 279 while (permissionIterator.hasNext()) { 280 if (permissionIterator.next().equals(permissionName)) { 281 permissionIterator.remove(); 282 removed = true; 283 break; 284 } 285 } 286 } 287 } 288 289 rebuildUserLists(); 290 return removed; 291 } 292 293 /** 294 * Removes all privileges for a given user. This does not edit the backend. 295 */ 296 public void removeModifiablePrivilege(String principalName) { 297 if (null == principalName) { 298 log.error("Null principal received, returning..."); 299 return; 300 } 301 currentDocGrant.remove(principalName); 302 303 // if user everyone had deny everything perm, then we have to 304 // keep this perm 305 if (principalName.equals(SecurityConstants.EVERYONE)) { 306 307 final List<String> deniedPerms = currentDocDeny.get(principalName); 308 boolean keepDenyAll = deniedPerms != null ? deniedPerms.contains(SecurityConstants.EVERYTHING) : false; 309 310 currentDocDeny.remove(principalName); 311 312 if (keepDenyAll) { 313 addModifiablePrivilege(SecurityConstants.EVERYONE, SecurityConstants.EVERYTHING, false); 314 } 315 } else { 316 currentDocDeny.remove(principalName); 317 } 318 319 needSave = true; 320 rebuildUserLists(); 321 } 322 323 /** 324 * Adds an unmodifiable privilege to the displayed list (these are related to the parent documents). 325 */ 326 public void addUnModifiablePrivilege(String principalName, String permissionName, boolean grant) { 327 if (null == principalName || null == permissionName) { 328 log.error("Null params received, returning..."); 329 return; 330 } 331 332 if (grant) { 333 // if we already have the user stored with rights we dont add the 334 // user again, just update the list if needed 335 if (null != parentDocsGrant.get(principalName)) { 336 // we already have the user - add the right to him 337 boolean shouldAddPermission = true; 338 for (String permission : parentDocsGrant.get(principalName)) { 339 // only add the right to list if the right is not already 340 // there 341 if (permission.equals(permissionName)) { 342 shouldAddPermission = false; 343 break; 344 } 345 } 346 347 if (shouldAddPermission) { 348 parentDocsGrant.get(principalName).add(permissionName); 349 } 350 } else { 351 // add the user and create a new list of rights for him 352 List<String> permissions = new ArrayList<String>(); 353 permissions.add(permissionName); 354 parentDocsGrant.put(principalName, permissions); 355 } 356 } else { 357 // if we already have the user stored with rights we dont add the 358 // user again, just update the list if needed 359 if (null != parentDocsDeny.get(principalName)) { 360 // we already have the user - add the right to him 361 boolean shouldAddPermission = true; 362 for (String permission : parentDocsDeny.get(principalName)) { 363 // only add the right to list if the right is not already 364 // there 365 if (permission.equals(permissionName)) { 366 shouldAddPermission = false; 367 break; 368 } 369 } 370 371 if (shouldAddPermission) { 372 parentDocsDeny.get(principalName).add(permissionName); 373 } 374 } else { 375 // add the user and create a new list of rights for him 376 List<String> permissions = new ArrayList<String>(); 377 permissions.add(permissionName); 378 parentDocsDeny.put(principalName, permissions); 379 } 380 381 } 382 383 rebuildUserLists(); 384 } 385 386 public void clear() { 387 currentDocDeny.clear(); 388 currentDocGrant.clear(); 389 parentDocsDeny.clear(); 390 parentDocsGrant.clear(); 391 392 currentDocumentUsers.clear(); 393 parentDocumentsUsers.clear(); 394 395 log.debug("Cleared data..."); 396 needSave = false; 397 } 398 399 public String getDocumentType() { 400 return documentType; 401 } 402 403 public void setDocumentType(String documentType) { 404 this.documentType = documentType; 405 } 406 407}