001/**
002 *   GRANITE DATA SERVICES
003 *   Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S.
004 *
005 *   This file is part of the Granite Data Services Platform.
006 *
007 *   Granite Data Services 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 *   Granite Data Services 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 Lesser
015 *   General Public License for more details.
016 *
017 *   You should have received a copy of the GNU Lesser General Public
018 *   License along with this library; if not, write to the Free Software
019 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
020 *   USA, or see <http://www.gnu.org/licenses/>.
021 */
022package org.granite.tide.spring.security;
023
024import java.util.ArrayList;
025import java.util.List;
026import java.util.StringTokenizer;
027
028import org.granite.tide.annotations.TideEnabled;
029import org.springframework.security.acls.domain.DefaultPermissionFactory;
030import org.springframework.security.acls.domain.ObjectIdentityRetrievalStrategyImpl;
031import org.springframework.security.acls.domain.PermissionFactory;
032import org.springframework.security.acls.domain.SidRetrievalStrategyImpl;
033import org.springframework.security.acls.model.Acl;
034import org.springframework.security.acls.model.AclService;
035import org.springframework.security.acls.model.NotFoundException;
036import org.springframework.security.acls.model.ObjectIdentity;
037import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy;
038import org.springframework.security.acls.model.Permission;
039import org.springframework.security.acls.model.Sid;
040import org.springframework.security.acls.model.SidRetrievalStrategy;
041import org.springframework.security.core.Authentication;
042import org.springframework.security.core.context.SecurityContextHolder;
043
044
045/**
046 *      @author William DRAI
047 * 
048 *      Adapted from the Spring security JSP taglib
049 */
050@TideEnabled
051public class AclIdentity extends Identity {
052    
053    private SidRetrievalStrategy sidRetrievalStrategy = null;
054    private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = null;
055    private AclService aclService = null;
056    
057    
058    public AclIdentity() {
059        sidRetrievalStrategy = new SidRetrievalStrategyImpl();
060        objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
061    }
062    
063    public void setSidRetrievalStrategy(SidRetrievalStrategy strategy) {
064        sidRetrievalStrategy = strategy;
065    }
066    
067    public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy strategy) {
068        objectIdentityRetrievalStrategy = strategy;
069    }
070    
071    public void setAclService(AclService aclService) {
072        this.aclService = aclService;
073    }
074    
075    
076    public boolean hasPermission(Object entity, String permissions) {
077        if (entity == null)
078                return true;
079        
080        List<Permission> requiredPermissions = null;
081        try {
082            requiredPermissions = parsePermissionsString(permissions);
083        } 
084        catch (NumberFormatException nfe) {
085            throw new RuntimeException(nfe);
086        }
087
088        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
089        if (authentication == null)
090                return false;
091
092        List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
093        ObjectIdentity oid = objectIdentityRetrievalStrategy.getObjectIdentity(entity);
094
095        // Obtain aclEntrys applying to the current Authentication object
096        try {
097            Acl acl = aclService.readAclById(oid, sids);
098
099            return acl.isGranted(requiredPermissions, sids, false);
100        } 
101        catch (NotFoundException nfe) {
102            return false;
103        }
104    }
105    
106    @SuppressWarnings({ "unchecked", "rawtypes" })
107        private List<Permission> parsePermissionsString(String integersString) throws NumberFormatException {
108        final List permissions = new ArrayList();   // Voluntarily not typed to avoid compilation problem with both Spring 2 and Spring 3
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 permissions;
119    }
120}