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     */
022    package org.granite.tide.spring.security;
023    
024    import java.util.ArrayList;
025    import java.util.List;
026    import java.util.StringTokenizer;
027    
028    import org.granite.tide.annotations.TideEnabled;
029    import org.springframework.security.acls.domain.DefaultPermissionFactory;
030    import org.springframework.security.acls.domain.ObjectIdentityRetrievalStrategyImpl;
031    import org.springframework.security.acls.domain.PermissionFactory;
032    import org.springframework.security.acls.domain.SidRetrievalStrategyImpl;
033    import org.springframework.security.acls.model.Acl;
034    import org.springframework.security.acls.model.AclService;
035    import org.springframework.security.acls.model.NotFoundException;
036    import org.springframework.security.acls.model.ObjectIdentity;
037    import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy;
038    import org.springframework.security.acls.model.Permission;
039    import org.springframework.security.acls.model.Sid;
040    import org.springframework.security.acls.model.SidRetrievalStrategy;
041    import org.springframework.security.core.Authentication;
042    import 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
051    public 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    }