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.List;
025import java.util.StringTokenizer;
026
027import org.granite.tide.annotations.TideEnabled;
028import org.springframework.security.acls.domain.DefaultPermissionFactory;
029import org.springframework.security.acls.domain.ObjectIdentityRetrievalStrategyImpl;
030import org.springframework.security.acls.domain.PermissionFactory;
031import org.springframework.security.acls.domain.SidRetrievalStrategyImpl;
032import org.springframework.security.acls.model.Acl;
033import org.springframework.security.acls.model.AclService;
034import org.springframework.security.acls.model.NotFoundException;
035import org.springframework.security.acls.model.ObjectIdentity;
036import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy;
037import org.springframework.security.acls.model.Permission;
038import org.springframework.security.acls.model.Sid;
039import org.springframework.security.acls.model.SidRetrievalStrategy;
040import org.springframework.security.core.Authentication;
041import org.springframework.security.core.context.SecurityContextHolder;
042
043
044/**
045 *      @author William DRAI
046 * 
047 *      Adapted from the Spring security JSP taglib
048 */
049@TideEnabled
050public class AclIdentity3 extends Identity3 {
051    
052    private SidRetrievalStrategy sidRetrievalStrategy = null;
053    private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = null;
054    private AclService aclService = null;
055    
056    
057    public AclIdentity3() {
058        sidRetrievalStrategy = new SidRetrievalStrategyImpl();
059        objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
060    }
061    
062    public void setSidRetrievalStrategy(SidRetrievalStrategy strategy) {
063        sidRetrievalStrategy = strategy;
064    }
065    
066    public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy strategy) {
067        objectIdentityRetrievalStrategy = strategy;
068    }
069    
070    public void setAclService(AclService aclService) {
071        this.aclService = aclService;
072    }
073    
074    
075    public boolean hasPermission(Object entity, String permissions) {
076        if (entity == null)
077                return true;
078        
079        List<Permission> requiredPermissions = null;
080        try {
081            requiredPermissions = parsePermissionsString(permissions);
082        } 
083        catch (NumberFormatException nfe) {
084            throw new RuntimeException(nfe);
085        }
086
087        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
088        if (authentication == null)
089                return false;
090
091        List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
092        ObjectIdentity oid = objectIdentityRetrievalStrategy.getObjectIdentity(entity);
093
094        // Obtain aclEntrys applying to the current Authentication object
095        try {
096            Acl acl = aclService.readAclById(oid, sids);
097
098            return acl.isGranted(requiredPermissions, sids, false);
099        } 
100        catch (NotFoundException nfe) {
101            return false;
102        }
103    }
104    
105    @SuppressWarnings({ "unchecked", "rawtypes" })
106        private List<Permission> parsePermissionsString(String integersString) throws NumberFormatException {
107        final List permissions = new ArrayList();   // Voluntarily not typed to avoid compilation problem with both Spring 2 and Spring 3
108        final StringTokenizer tokenizer;
109        tokenizer = new StringTokenizer(integersString, ",", false);
110        
111        PermissionFactory pf = new DefaultPermissionFactory();
112        while (tokenizer.hasMoreTokens()) {
113                String integer = tokenizer.nextToken();
114                permissions.add(pf.buildFromMask(new Integer(integer).intValue()));
115        }
116        
117        return permissions;
118    }
119}