001package org.apache.fulcrum.security.model.turbine; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.util.HashMap; 023import java.util.Map; 024import java.util.Set; 025 026import org.apache.avalon.framework.logger.Logger; 027import org.apache.fulcrum.security.GroupManager; 028import org.apache.fulcrum.security.RoleManager; 029import org.apache.fulcrum.security.entity.Group; 030import org.apache.fulcrum.security.entity.Permission; 031import org.apache.fulcrum.security.entity.Role; 032import org.apache.fulcrum.security.model.turbine.entity.TurbineRole; 033import org.apache.fulcrum.security.model.turbine.entity.TurbineUserGroupRole; 034import org.apache.fulcrum.security.util.FulcrumSecurityException; 035import org.apache.fulcrum.security.util.GroupSet; 036import org.apache.fulcrum.security.util.PermissionSet; 037import org.apache.fulcrum.security.util.RoleSet; 038 039/** 040 * This is a control class that makes it easy to find out if a 041 * particular User has a given Permission. It also determines if a 042 * User has a a particular Role. 043 * 044 * @author <a href="mailto:jmcnally@collab.net">John D. McNally</a> 045 * @author <a href="mailto:bmclaugh@algx.net">Brett McLaughlin</a> 046 * @author <a href="mailto:greg@shwoop.com">Greg Ritter</a> 047 * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a> 048 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a> 049 * @author <a href="mailto:marco@intermeta.de">Marco Knüttel</a> 050 * @version $Id: TurbineAccessControlList.java 1096130 2019-03-25 10:37:19Z painter $ 051 */ 052@SuppressWarnings("rawtypes") 053public class TurbineAccessControlListImpl 054 implements TurbineAccessControlList 055{ 056 /** Serial version */ 057 private static final long serialVersionUID = 2678947159949477950L; 058 059 /** The sets of roles that the user has in different groups */ 060 private Map<Group, RoleSet> roleSets; 061 062 /** The sets of permissions that the user has in different groups */ 063 private Map<Group, PermissionSet> permissionSets; 064 065 /** The global group */ 066 private Group globalGroup; 067 068 /** The group manager */ 069 private GroupManager groupManager; 070 071 /** The distinct list of groups that this user is part of */ 072 private GroupSet groupSet = new GroupSet(); 073 074 /** The distinct list of roles that this user is part of */ 075 private RoleSet roleSet = new RoleSet(); 076 077 /** the distinct list of permissions that this user has */ 078 private PermissionSet permissionSet = new PermissionSet(); 079 080 /** the Avalon logger */ 081 private transient Logger logger; 082 083 /** 084 * Constructs a new AccessControlList. 085 * 086 * This class follows 'immutable' pattern - it's objects can't be modified 087 * once they are created. This means that the permissions the users have are 088 * in effect form the moment they log in to the moment they log out, and 089 * changes made to the security settings in that time are not reflected 090 * in the state of this object. If you need to reset an user's permissions 091 * you need to invalidate his session. <br> 092 * 093 * @param turbineUserGroupRoleSet 094 * The set of user/group/role relations that this acl is built from 095 * @param groupManager the Group manager 096 * @param roleManager the Role manager 097 * @param modelManager the model Manager 098 * @param logger 099 * 100 * @throws FulcrumSecurityException if the global group cannot be retrieved 101 */ 102 public TurbineAccessControlListImpl( 103 Set<? extends TurbineUserGroupRole> turbineUserGroupRoleSet, 104 GroupManager groupManager, RoleManager roleManager, TurbineModelManager modelManager, Logger logger) throws FulcrumSecurityException 105 { 106 this.roleSets = new HashMap<Group, RoleSet>(); 107 this.permissionSets = new HashMap<Group, PermissionSet>(); 108 this.groupManager = groupManager; 109 110 this.logger = logger; 111 112 for (TurbineUserGroupRole ugr : turbineUserGroupRoleSet) 113 { 114 Group group = ugr.getGroup(); 115 // check if group matches 116 if (this.logger != null && this.groupManager != null && group.getClass() != this.groupManager.getGroupInstance().getClass()) { 117 this.logger.warn( "Turbine group classes do not match, some lookup might fail, check in componentConfiguration.xml. Expected class: " + 118 this.groupManager.getGroupInstance().getClass() + ", actual class: " +group.getClass() 119 ); 120 } 121 groupSet.add(group); 122 123 Role role = ugr.getRole(); 124 if (!roleSet.containsId(role.getId())) 125 { 126 // get fresh reference from role manager to make sure the related 127 // permissions are populated 128 if (roleManager != null) 129 { 130 role = roleManager.getRoleById(role.getId()); 131 } 132 roleSet.add(role); 133 } 134 else 135 { 136 role = roleSet.getById(role.getId()); 137 } 138 if (roleSets.containsKey(group)) 139 { 140 roleSets.get(group).add(role); 141 } 142 else 143 { 144 RoleSet rs = new RoleSet(); 145 rs.add(role); 146 roleSets.put(group, rs); 147 } 148 // if required, otherwise skip 149 if (role instanceof TurbineRole) { 150 PermissionSet ps = ((TurbineRole) role).getPermissions(); 151 permissionSet.add(ps); 152 if (permissionSets.containsKey(group)) 153 { 154 permissionSets.get(group).add(ps); 155 } 156 else 157 { 158 permissionSets.put(group, ps); 159 } 160 } 161 } 162 // this check might be not needed any more, required for custom group 163 if (modelManager != null) 164 { 165 this.globalGroup = modelManager.getGlobalGroup(); 166 } 167 } 168 169 /** 170 * Retrieves a set of Roles an user is assigned in a Group. 171 * 172 * @param group the Group 173 * @return the set of Roles this user has within the Group. 174 */ 175 @Override 176 public RoleSet getRoles(Group group) 177 { 178 if (group == null) 179 { 180 return null; 181 } 182 return roleSets.get(group); 183 } 184 185 /** 186 * Retrieves a set of Roles an user is assigned in the global Group. 187 * 188 * @return the set of Roles this user has within the global Group or null. 189 */ 190 @Override 191 public RoleSet getRoles() 192 { 193 return getRoles(globalGroup); 194 } 195 196 /** 197 * Retrieves a set of Permissions an user is assigned in a Group. 198 * 199 * @param group the Group 200 * @return the set of Permissions this user has within the Group. 201 */ 202 @Override 203 public PermissionSet getPermissions(Group group) 204 { 205 if (group == null) 206 { 207 return null; 208 } 209 return permissionSets.get(group); 210 } 211 212 /** 213 * Retrieves a set of Permissions an user is assigned in the global Group. 214 * 215 * @return the set of Permissions this user has within the global Group. 216 */ 217 @Override 218 public PermissionSet getPermissions() 219 { 220 return getPermissions(globalGroup); 221 } 222 223 /** 224 * Checks if the user is assigned a specific Role in the Group. 225 * 226 * @param role the Role 227 * @param group the Group 228 * @return <code>true</code> if the user is assigned the Role in the Group. 229 */ 230 @Override 231 public boolean hasRole(Role role, Group group) 232 { 233 RoleSet set = getRoles(group); 234 if (set == null || role == null) 235 { 236 return false; 237 } 238 return set.contains(role); 239 } 240 241 /** 242 * Checks if the user is assigned a specific Role in any of the given 243 * Groups 244 * 245 * @param role the Role 246 * @param groupset a Groupset 247 * @return <code>true</code> if the user is assigned the Role in any of 248 * the given Groups. 249 */ 250 @Override 251 public boolean hasRole(Role role, GroupSet groupset) 252 { 253 if (role == null) 254 { 255 return false; 256 } 257 258 for (Group group : groupset) 259 { 260 RoleSet roles = getRoles(group); 261 if (roles != null && roles.contains(role)) 262 { 263 return true; 264 } 265 } 266 267 return false; 268 } 269 270 /** 271 * Checks if the user is assigned a specific Role in the Group. 272 * 273 * @param roleName the Role name 274 * @param groupName the Group name 275 * @return <code>true</code> if the user is assigned the Role in the Group. 276 */ 277 @Override 278 public boolean hasRole(String roleName, String groupName) 279 { 280 try 281 { 282 return hasRole(roleSet.getByName(roleName), groupSet.getByName(groupName)); 283 } 284 catch (Exception e) 285 { 286 return false; 287 } 288 } 289 290 /** 291 * Checks if the user is assigned a specific Role in any of the given 292 * Groups 293 * 294 * @param rolename the name of the Role 295 * @param groupset a Groupset 296 * @return <code>true</code> if the user is assigned the Role in any of 297 * the given Groups. 298 */ 299 @Override 300 public boolean hasRole(String rolename, GroupSet groupset) 301 { 302 try 303 { 304 return hasRole(roleSet.getByName(rolename), groupset); 305 } 306 catch (Exception e) 307 { 308 return false; 309 } 310 } 311 312 /** 313 * Checks if the user is assigned a specific Role in the global Group. 314 * 315 * @param role the Role 316 * @return <code>true</code> if the user is assigned the Role in the global Group. 317 */ 318 @Override 319 public boolean hasRole(Role role) 320 { 321 return hasRole(role, globalGroup); 322 } 323 324 /** 325 * Checks if the user is assigned a specific Role in the global Group. 326 * 327 * @param role the Role 328 * @return <code>true</code> if the user is assigned the Role in the global Group. 329 */ 330 @Override 331 public boolean hasRole(String role) 332 { 333 try 334 { 335 return hasRole(roleSet.getByName(role)); 336 } 337 catch (Exception e) 338 { 339 return false; 340 } 341 } 342 343 /** 344 * Checks if the user is assigned a specific Permission in the Group. 345 * 346 * @param permission the Permission 347 * @param group the Group 348 * @return <code>true</code> if the user is assigned the Permission in the Group. 349 */ 350 @Override 351 public boolean hasPermission(Permission permission, Group group) 352 { 353 PermissionSet set = getPermissions(group); 354 if (set == null || permission == null) 355 { 356 return false; 357 } 358 return set.contains(permission); 359 } 360 361 /** 362 * Checks if the user is assigned a specific Permission in any of the given 363 * Groups 364 * 365 * @param permission the Permission 366 * @param groupset a Groupset 367 * @return <code>true</code> if the user is assigned the Permission in any 368 * of the given Groups. 369 */ 370 @Override 371 public boolean hasPermission(Permission permission, GroupSet groupset) 372 { 373 if (permission == null) 374 { 375 return false; 376 } 377 378 for (Group group : groupset) 379 { 380 PermissionSet permissions = getPermissions(group); 381 if (permissions != null && permissions.contains(permission)) 382 { 383 return true; 384 } 385 } 386 387 return false; 388 } 389 390 /** 391 * Checks if the user is assigned a specific Permission in the Group. 392 * 393 * @param permission the Permission 394 * @param group the Group 395 * @return <code>true</code> if the user is assigned the Permission in the Group. 396 */ 397 @Override 398 public boolean hasPermission(String permission, String group) 399 { 400 try 401 { 402 return hasPermission(permissionSet.getByName(permission), groupSet.getByName(group)); 403 } 404 catch (Exception e) 405 { 406 return false; 407 } 408 } 409 410 /** 411 * Checks if the user is assigned a specific Permission in the Group. 412 * 413 * @param permission the Permission 414 * @param group the Group 415 * @return <code>true</code> if the user is assigned the Permission in the Group. 416 */ 417 @Override 418 public boolean hasPermission(String permission, Group group) 419 { 420 try 421 { 422 return hasPermission(permissionSet.getByName(permission), group); 423 } 424 catch (Exception e) 425 { 426 return false; 427 } 428 } 429 430 /** 431 * Checks if the user is assigned a specific Permission in any of the given 432 * Groups 433 * 434 * @param permissionName the name of the Permission 435 * @param groupset a Groupset 436 * @return <code>true</code> if the user is assigned the Permission in any 437 * of the given Groups. 438 */ 439 @Override 440 public boolean hasPermission(String permissionName, GroupSet groupset) 441 { 442 Permission permission; 443 try 444 { 445 permission = permissionSet.getByName(permissionName); 446 } 447 catch (Exception e) 448 { 449 return false; 450 } 451 452 if (permission == null) 453 { 454 return false; 455 } 456 457 for (Group group : groupset) 458 { 459 PermissionSet permissions = getPermissions(group); 460 if (permissions != null && permissions.contains(permission)) 461 { 462 return true; 463 } 464 } 465 return false; 466 } 467 468 /** 469 * Checks if the user is assigned a specific Permission in the global Group. 470 * 471 * @param permission the Permission 472 * @return <code>true</code> if the user is assigned the Permission in the global Group. 473 */ 474 @Override 475 public boolean hasPermission(Permission permission) 476 { 477 return hasPermission(permission, globalGroup); 478 } 479 480 /** 481 * Checks if the user is assigned a specific Permission in the global Group. 482 * 483 * @param permission the Permission 484 * @return <code>true</code> if the user is assigned the Permission in the global Group. 485 */ 486 @Override 487 public boolean hasPermission(String permission) 488 { 489 try 490 { 491 return hasPermission(permissionSet.getByName(permission)); 492 } 493 catch (Exception e) 494 { 495 return false; 496 } 497 } 498 499 /** 500 * Returns all groups defined in the system. 501 * 502 * This is useful for debugging, when you want to display all roles 503 * and permissions an user is assigned. This method is needed 504 * because you can't call static methods of TurbineSecurity class 505 * from within WebMacro/Velocity template 506 * 507 * @return A Group [] of all groups in the system. 508 */ 509 @Override 510 public Group[] getAllGroups() 511 { 512 try 513 { 514 return (groupManager != null)? groupManager.getAllGroups().toArray(new Group[0]) 515 : new Group[0]; 516 } 517 catch (FulcrumSecurityException e) 518 { 519 return new Group[0]; 520 } 521 } 522 523 @Override 524 public GroupSet getGroupSet() 525 { 526 return groupSet; 527 } 528}