001package org.apache.archiva.redback.role.processor; 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 org.apache.archiva.redback.rbac.Operation; 023import org.apache.archiva.redback.rbac.Permission; 024import org.apache.archiva.redback.rbac.RBACManager; 025import org.apache.archiva.redback.rbac.RbacManagerException; 026import org.apache.archiva.redback.rbac.Resource; 027import org.apache.archiva.redback.rbac.Role; 028import org.apache.archiva.redback.role.RoleManagerException; 029import org.apache.archiva.redback.role.model.ModelApplication; 030import org.apache.archiva.redback.role.model.ModelOperation; 031import org.apache.archiva.redback.role.model.ModelPermission; 032import org.apache.archiva.redback.role.model.ModelResource; 033import org.apache.archiva.redback.role.model.ModelRole; 034import org.apache.archiva.redback.role.model.RedbackRoleModel; 035import org.apache.archiva.redback.role.util.RoleModelUtils; 036import org.apache.commons.lang3.time.StopWatch; 037import org.slf4j.Logger; 038import org.slf4j.LoggerFactory; 039import org.springframework.stereotype.Service; 040 041import javax.inject.Inject; 042import javax.inject.Named; 043import java.util.ArrayList; 044import java.util.HashMap; 045import java.util.HashSet; 046import java.util.List; 047import java.util.Map; 048import java.util.Set; 049 050/** 051 * DefaultRoleModelProcessor: inserts the components of the model that can be populated into the rbac manager 052 * 053 * @author: Jesse McConnell 054 */ 055@Service( "roleModelProcessor" ) 056public class DefaultRoleModelProcessor 057 implements RoleModelProcessor 058{ 059 private Logger log = LoggerFactory.getLogger( DefaultRoleModelProcessor.class ); 060 061 @Inject 062 @Named( value = "rbacManager#default" ) 063 private RBACManager rbacManager; 064 065 private Map<String, Resource> resourceMap = new HashMap<String, Resource>(); 066 067 private Map<String, Operation> operationMap = new HashMap<String, Operation>(); 068 069 public void process( RedbackRoleModel model ) 070 throws RoleManagerException 071 { 072 // must process resources and operations first, they are required for the 073 // permissions in the roles to add in correctly 074 processResources( model ); 075 processOperations( model ); 076 077 processRoles( model ); 078 } 079 080 @SuppressWarnings( "unchecked" ) 081 private void processResources( RedbackRoleModel model ) 082 throws RoleManagerException 083 { 084 for ( ModelApplication application : model.getApplications() ) 085 { 086 for ( ModelResource profileResource : application.getResources() ) 087 { 088 try 089 { 090 if ( !rbacManager.resourceExists( profileResource.getName() ) ) 091 { 092 093 Resource resource = rbacManager.createResource( profileResource.getName() ); 094 resource.setPermanent( profileResource.isPermanent() ); 095 resource = rbacManager.saveResource( resource ); 096 097 // store for use in permission creation 098 resourceMap.put( profileResource.getId(), resource ); 099 100 } 101 else 102 { 103 resourceMap.put( profileResource.getId(), 104 rbacManager.getResource( profileResource.getName() ) ); 105 } 106 } 107 catch ( RbacManagerException e ) 108 { 109 throw new RoleManagerException( "error creating resource '" + profileResource.getName() + "'", e ); 110 } 111 } 112 } 113 } 114 115 @SuppressWarnings( "unchecked" ) 116 private void processOperations( RedbackRoleModel model ) 117 throws RoleManagerException 118 { 119 for ( ModelApplication application : model.getApplications() ) 120 { 121 for ( ModelOperation profileOperation : application.getOperations() ) 122 { 123 try 124 { 125 if ( !rbacManager.operationExists( profileOperation.getName() ) ) 126 { 127 128 Operation operation = rbacManager.createOperation( profileOperation.getName() ); 129 operation.setPermanent( profileOperation.isPermanent() ); 130 operation.setDescription( profileOperation.getDescription() ); 131 operation = rbacManager.saveOperation( operation ); 132 133 // store for use in permission creation 134 operationMap.put( profileOperation.getId(), operation ); 135 136 } 137 else 138 { 139 operationMap.put( profileOperation.getId(), 140 rbacManager.getOperation( profileOperation.getName() ) ); 141 } 142 } 143 catch ( RbacManagerException e ) 144 { 145 throw new RoleManagerException( "error creating operation '" + profileOperation.getName() + "'", 146 e ); 147 } 148 } 149 } 150 } 151 152 @SuppressWarnings( "unchecked" ) 153 private void processRoles( RedbackRoleModel model ) 154 throws RoleManagerException 155 { 156 StopWatch stopWatch = new StopWatch(); 157 stopWatch.reset(); 158 stopWatch.start(); 159 List<String> sortedGraph = RoleModelUtils.reverseTopologicalSortedRoleList(model); 160 161 List<? extends Role> allRoles; 162 try 163 { 164 allRoles = rbacManager.getAllRoles(); 165 } 166 catch ( RbacManagerException e ) 167 { 168 throw new RoleManagerException( e.getMessage(), e ); 169 } 170 171 Set<String> allRoleNames = new HashSet<String>( allRoles.size() ); 172 for ( Role role : allRoles ) 173 { 174 allRoleNames.add( role.getName() ); 175 } 176 177 for ( String roleId : sortedGraph ) 178 { 179 ModelRole roleProfile = RoleModelUtils.getModelRole( model, roleId ); 180 181 List<? extends Permission> permissions = processPermissions( roleProfile.getPermissions() ); 182 183 boolean roleExists = allRoleNames.contains( roleProfile.getName() );// false; 184 185 /*try 186 { 187 roleExists = rbacManager.roleExists( roleProfile.getName() ); 188 } 189 catch ( RbacManagerException e ) 190 { 191 throw new RoleManagerException( e.getMessage(), e ); 192 }*/ 193 194 if ( !roleExists ) 195 { 196 try 197 { 198 Role role = rbacManager.createRole( roleProfile.getName() ); 199 role.setId( roleProfile.getId() ); 200 role.setModelId( roleProfile.getId() ); 201 role.setTemplateInstance( false ); 202 role.setDescription( roleProfile.getDescription() ); 203 role.setPermanent( roleProfile.isPermanent() ); 204 role.setAssignable( roleProfile.isAssignable() ); 205 206 // add any permissions associated with this role 207 for ( Permission permission : permissions ) 208 { 209 role.addPermission( permission ); 210 } 211 212 // add child roles to this role 213 if ( roleProfile.getChildRoles() != null ) 214 { 215 for ( String childRoleId : roleProfile.getChildRoles() ) 216 { 217 ModelRole childRoleProfile = RoleModelUtils.getModelRole( model, childRoleId ); 218 role.addChildRoleName( childRoleProfile.getName() ); 219 role.addChildRoleId( childRoleProfile.getId() ); 220 } 221 } 222 223 rbacManager.saveRole( role ); 224 allRoleNames.add( role.getName() ); 225 226 // add link from parent roles to this new role 227 if ( roleProfile.getParentRoles() != null ) 228 { 229 for ( String parentRoleId : roleProfile.getParentRoles() ) 230 { 231 ModelRole parentModelRole = RoleModelUtils.getModelRole( model, parentRoleId ); 232 Role parentRole = rbacManager.getRole( parentModelRole.getName() ); 233 parentRole.addChildRole( role ); 234 rbacManager.saveRole( parentRole ); 235 allRoleNames.add( parentRole.getName() ); 236 } 237 } 238 239 } 240 catch ( RbacManagerException e ) 241 { 242 throw new RoleManagerException( "error creating role '" + roleProfile.getName() + "'", e ); 243 } 244 } 245 else 246 { 247 try 248 { 249 Role role = rbacManager.getRole( roleProfile.getName() ); 250 251 boolean changed = false; 252 for ( Permission permission : permissions ) 253 { 254 if ( !role.getPermissions().contains( permission ) ) 255 { 256 log.info( "Adding new permission '{}' to role '{}'", permission.getName(), role.getName() ); 257 role.addPermission( permission ); 258 changed = true; 259 } 260 } 261 262 // Copy list to avoid concurrent modification [REDBACK-220] 263 List<Permission> oldPermissions = new ArrayList<Permission>( role.getPermissions() ); 264 for ( Permission permission : oldPermissions ) 265 { 266 if ( !permissions.contains( permission ) ) 267 { 268 log.info( 269 "Removing old permission '{}' from role '{}'", permission.getName(), role.getName() ); 270 role.removePermission( permission ); 271 changed = true; 272 } 273 } 274 if ( changed ) 275 { 276 rbacManager.saveRole( role ); 277 allRoleNames.add( role.getName() ); 278 } 279 } 280 catch ( RbacManagerException e ) 281 { 282 throw new RoleManagerException( "error updating role '" + roleProfile.getName() + "'", e ); 283 } 284 } 285 } 286 stopWatch.stop(); 287 log.info( "time to process roles model: {} ms", stopWatch.getTime() ); 288 } 289 290 private List<? extends Permission> processPermissions( List<ModelPermission> permissions ) 291 throws RoleManagerException 292 { 293 List<Permission> rbacPermissions = new ArrayList<Permission>( permissions.size() ); 294 295 for ( ModelPermission profilePermission : permissions ) 296 { 297 try 298 { 299 if ( !rbacManager.permissionExists( profilePermission.getName() ) ) 300 { 301 302 Permission permission = rbacManager.createPermission( profilePermission.getName() ); 303 304 // get the operation out of the map we stored it in when we created it _by_ the id in the model 305 Operation operation = (Operation) operationMap.get( profilePermission.getOperation() ); 306 // same with resource 307 Resource resource = (Resource) resourceMap.get( profilePermission.getResource() ); 308 309 permission.setOperation( operation ); 310 permission.setResource( resource ); 311 permission.setPermanent( profilePermission.isPermanent() ); 312 permission.setDescription( profilePermission.getDescription() ); 313 314 permission = rbacManager.savePermission( permission ); 315 316 rbacPermissions.add( permission ); 317 318 } 319 else 320 { 321 rbacPermissions.add( rbacManager.getPermission( profilePermission.getName() ) ); 322 } 323 } 324 catch ( RbacManagerException e ) 325 { 326 throw new RoleManagerException( "error creating permission '" + profilePermission.getName() + "'", e ); 327 } 328 } 329 return rbacPermissions; 330 } 331 332 public RBACManager getRbacManager() 333 { 334 return rbacManager; 335 } 336 337 public void setRbacManager( RBACManager rbacManager ) 338 { 339 this.rbacManager = rbacManager; 340 } 341} 342 343