001/*
002  GRANITE DATA SERVICES
003  Copyright (C) 2011 GRANITE DATA SERVICES S.A.S.
004
005  This file is part of Granite Data Services.
006
007  Granite Data Services is free software; you can redistribute it and/or modify
008  it under the terms of the GNU Library General Public License as published by
009  the Free Software Foundation; either version 2 of the License, or (at your
010  option) any later version.
011
012  Granite Data Services is distributed in the hope that it will be useful, but
013  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015  for more details.
016
017  You should have received a copy of the GNU Library General Public License
018  along with this library; if not, see <http://www.gnu.org/licenses/>.
019*/
020
021package org.granite.tide.spring.security;
022
023import java.util.ArrayList;
024import java.util.HashSet;
025import java.util.List;
026import java.util.Set;
027import java.util.StringTokenizer;
028
029import org.granite.tide.annotations.TideEnabled;
030import org.springframework.security.Authentication;
031import org.springframework.security.acls.Acl;
032import org.springframework.security.acls.AclService;
033import org.springframework.security.acls.NotFoundException;
034import org.springframework.security.acls.Permission;
035import org.springframework.security.acls.domain.DefaultPermissionFactory;
036import org.springframework.security.acls.domain.PermissionFactory;
037import org.springframework.security.acls.objectidentity.ObjectIdentity;
038import org.springframework.security.acls.objectidentity.ObjectIdentityRetrievalStrategy;
039import org.springframework.security.acls.objectidentity.ObjectIdentityRetrievalStrategyImpl;
040import org.springframework.security.acls.sid.Sid;
041import org.springframework.security.acls.sid.SidRetrievalStrategy;
042import org.springframework.security.acls.sid.SidRetrievalStrategyImpl;
043import org.springframework.security.context.SecurityContextHolder;
044
045
046/**
047 *      @author William DRAI
048 * 
049 *      Adapted from the Spring security JSP taglib
050 */
051@TideEnabled
052public class AclIdentity extends Identity {
053    
054    private SidRetrievalStrategy sidRetrievalStrategy = null;
055    private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = null;
056    private AclService aclService = null;
057    
058    
059    public AclIdentity() {
060        sidRetrievalStrategy = new SidRetrievalStrategyImpl();
061        objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
062    }
063    
064    public void setSidRetrievalStrategy(SidRetrievalStrategy strategy) {
065        sidRetrievalStrategy = strategy;
066    }
067    
068    public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy strategy) {
069        objectIdentityRetrievalStrategy = strategy;
070    }
071    
072    public void setAclService(AclService aclService) {
073        this.aclService = aclService;
074    }
075    
076    
077    public boolean hasPermission(Object entity, String permissions) {
078        if (entity == null)
079                return true;
080        
081        List<Permission> requiredPermissions = null;
082        try {
083            requiredPermissions = parsePermissionsString(permissions);
084        } 
085        catch (NumberFormatException nfe) {
086            throw new RuntimeException(nfe);
087        }
088
089        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
090        if (authentication == null)
091                return false;
092
093        Sid[] sids = sidRetrievalStrategy.getSids(authentication);
094        ObjectIdentity oid = objectIdentityRetrievalStrategy.getObjectIdentity(entity);
095
096        // Obtain aclEntrys applying to the current Authentication object
097        try {
098            Acl acl = aclService.readAclById(oid, sids);
099
100            return acl.isGranted(requiredPermissions.toArray(new Permission[requiredPermissions.size()]), sids, false);
101        } 
102        catch (NotFoundException nfe) {
103            return false;
104        }
105    }
106    
107    private List<Permission> parsePermissionsString(String integersString) throws NumberFormatException {
108        final Set<Permission> permissions = new HashSet<Permission>();
109        final StringTokenizer tokenizer;
110        tokenizer = new StringTokenizer(integersString, ",", false);
111        
112        PermissionFactory pf = new DefaultPermissionFactory();
113        while (tokenizer.hasMoreTokens()) {
114                String integer = tokenizer.nextToken();
115                permissions.add(pf.buildFromMask(new Integer(integer).intValue()));
116        }
117        
118        return new ArrayList<Permission>(permissions);
119    }
120}