Author: eevans
Date: Wed Oct  6 15:19:13 2010
New Revision: 1005080

URL: http://svn.apache.org/viewvc?rev=1005080&view=rev
Log:
refactor ClientState and RPC for CF authorizations

Patch by eevans; reviewed by Stu Hood for CASSANDRA-1554

Modified:
    cassandra/trunk/src/java/org/apache/cassandra/avro/CassandraServer.java
    cassandra/trunk/src/java/org/apache/cassandra/service/ClientState.java
    cassandra/trunk/src/java/org/apache/cassandra/thrift/CassandraServer.java

Modified: 
cassandra/trunk/src/java/org/apache/cassandra/avro/CassandraServer.java
URL: 
http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/avro/CassandraServer.java?rev=1005080&r1=1005079&r2=1005080&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/avro/CassandraServer.java 
(original)
+++ cassandra/trunk/src/java/org/apache/cassandra/avro/CassandraServer.java Wed 
Oct  6 15:19:13 2010
@@ -823,7 +823,7 @@ public class CassandraServer implements 
     {
         try
         {
-            state().hasKeyspaceAccess(perm);
+            state().hasColumnFamilyListAccess(perm);
         }
         catch (org.apache.cassandra.thrift.InvalidRequestException e)
         {
@@ -1040,7 +1040,7 @@ public class CassandraServer implements 
 
         try
         {
-            state().hasKeyspaceAccess(Permission.WRITE);
+            state().hasColumnFamilyAccess((String)columnFamily, 
Permission.WRITE);
             schedule();
             StorageProxy.truncateBlocking(state().getKeyspace(), 
columnFamily.toString());
         }
@@ -1073,7 +1073,7 @@ public class CassandraServer implements 
         String keyspace = state().getKeyspace();
         try
         {
-            state().hasKeyspaceAccess(Permission.READ);
+            
state().hasColumnFamilyAccess(column_parent.column_family.toString(), 
Permission.READ);
         }
         catch (org.apache.cassandra.thrift.InvalidRequestException thriftE)
         {
@@ -1139,7 +1139,7 @@ public class CassandraServer implements 
 
         try
         {
-            state().hasKeyspaceAccess(Permission.READ);
+            
state().hasColumnFamilyAccess(column_parent.column_family.toString(), 
Permission.READ);
         }
         catch (org.apache.cassandra.thrift.InvalidRequestException thriftE)
         {

Modified: cassandra/trunk/src/java/org/apache/cassandra/service/ClientState.java
URL: 
http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/service/ClientState.java?rev=1005080&r1=1005079&r2=1005080&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/service/ClientState.java 
(original)
+++ cassandra/trunk/src/java/org/apache/cassandra/service/ClientState.java Wed 
Oct  6 15:19:13 2010
@@ -26,7 +26,6 @@ import org.slf4j.LoggerFactory;
 import org.apache.cassandra.auth.AuthenticatedUser;
 import org.apache.cassandra.auth.Permission;
 import org.apache.cassandra.auth.Resources;
-import org.apache.cassandra.config.Config.RequestSchedulerId;
 import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.thrift.AuthenticationException;
 import org.apache.cassandra.thrift.InvalidRequestException;
@@ -42,8 +41,6 @@ public class ClientState
     // Current user for the session
     private AuthenticatedUser user;
     private String keyspace;
-    private Set<Permission> keyspaceAccess;
-    private List<Object> resource = new ArrayList<Object>();
 
     /**
      * Construct a new, empty ClientState: can be reused after logout() or 
reset().
@@ -52,26 +49,7 @@ public class ClientState
     {
         reset();
     }
-
-    /**
-     * Called when the keyspace or user have changed.
-     */
-    private void updateKeyspaceAccess()
-    {
-        if (user == null || keyspace == null)
-            // user is not logged in or keyspace is not set
-            keyspaceAccess = null;
-        else
-        {
-            // authorize the user for the current keyspace
-            resource.clear();
-            resource.add(Resources.ROOT);
-            resource.add(Resources.KEYSPACES);
-            resource.add(keyspace);
-            keyspaceAccess = DatabaseDescriptor.getAuthority().authorize(user, 
resource);
-        }
-    }
-
+    
     public String getKeyspace()
     {
         return keyspace;
@@ -80,7 +58,6 @@ public class ClientState
     public void setKeyspace(String ks)
     {
         keyspace = ks;
-        updateKeyspaceAccess();
     }
 
     public String getSchedulingValue()
@@ -101,7 +78,6 @@ public class ClientState
         if (logger.isDebugEnabled())
             logger.debug("logged in: {}", user);
         this.user = user;
-        updateKeyspaceAccess();
     }
 
     public void logout()
@@ -115,8 +91,6 @@ public class ClientState
     {
         user = DatabaseDescriptor.getAuthenticator().defaultUser();
         keyspace = null;
-        keyspaceAccess = null;
-        resource.clear();
     }
 
     /**
@@ -124,25 +98,54 @@ public class ClientState
      */
     public void hasKeyspaceListAccess(Permission perm) throws 
InvalidRequestException
     {
-        if (user == null)
-            throw new InvalidRequestException("You have not logged in");
+        validateLogin();
+        
         List<Object> resource = Arrays.<Object>asList(Resources.ROOT, 
Resources.KEYSPACES);
         Set<Permission> perms = 
DatabaseDescriptor.getAuthority().authorize(user, resource);
 
         hasAccess(user, perms, perm, resource);
     }
-
+    
     /**
-     * Confirms that the client thread has the given Permission in the context 
of the current Keyspace.
+     * Confirms that the client thread has the given Permission for the 
ColumnFamily list of
+     * the current keyspace.
      */
-    public void hasKeyspaceAccess(Permission perm) throws 
InvalidRequestException
+    public void hasColumnFamilyListAccess(Permission perm) throws 
InvalidRequestException
+    {
+        validateLogin();
+        validateKeyspace();
+        
+        List<Object> resource = Arrays.<Object>asList(Resources.ROOT, 
Resources.KEYSPACES, keyspace);
+        Set<Permission> perms = 
DatabaseDescriptor.getAuthority().authorize(user, resource);
+        
+        hasAccess(user, perms, perm, resource);
+    }
+    
+    /**
+     * Confirms that the client thread has the given Permission in the context 
of the given
+     * ColumnFamily and the current keyspace.
+     */
+    public void hasColumnFamilyAccess(String columnFamily, Permission perm) 
throws InvalidRequestException
+    {
+        validateLogin();
+        validateKeyspace();
+        
+        List<Object> resource = Arrays.<Object>asList(Resources.ROOT, 
Resources.KEYSPACES, keyspace, columnFamily);
+        Set<Permission> perms = 
DatabaseDescriptor.getAuthority().authorize(user, resource);
+        
+        hasAccess(user, perms, perm, resource);
+    }
+
+    private void validateLogin() throws InvalidRequestException
     {
         if (user == null)
             throw new InvalidRequestException("You have not logged in");
-        if (keyspaceAccess == null)
+    }
+    
+    private void validateKeyspace() throws InvalidRequestException
+    {
+        if (keyspace == null)
             throw new InvalidRequestException("You have not set a keyspace for 
this session");
-
-        hasAccess(user, keyspaceAccess, perm, resource);
     }
 
     private static void hasAccess(AuthenticatedUser user, Set<Permission> 
perms, Permission perm, List<Object> resource) throws InvalidRequestException

Modified: 
cassandra/trunk/src/java/org/apache/cassandra/thrift/CassandraServer.java
URL: 
http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/thrift/CassandraServer.java?rev=1005080&r1=1005079&r2=1005080&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/thrift/CassandraServer.java 
(original)
+++ cassandra/trunk/src/java/org/apache/cassandra/thrift/CassandraServer.java 
Wed Oct  6 15:19:13 2010
@@ -257,7 +257,7 @@ public class CassandraServer implements 
         if (logger.isDebugEnabled())
             logger.debug("get_slice");
         
-        state().hasKeyspaceAccess(Permission.READ);
+        state().hasColumnFamilyAccess(column_parent.column_family, 
Permission.READ);
         return multigetSliceInternal(state().getKeyspace(), 
Collections.singletonList(key), column_parent, predicate, 
consistency_level).get(key);
     }
     
@@ -267,7 +267,7 @@ public class CassandraServer implements 
         if (logger.isDebugEnabled())
             logger.debug("multiget_slice");
 
-        state().hasKeyspaceAccess(Permission.READ);
+        state().hasColumnFamilyAccess(column_parent.column_family, 
Permission.READ);
 
         return multigetSliceInternal(state().getKeyspace(), keys, 
column_parent, predicate, consistency_level);
     }
@@ -306,7 +306,7 @@ public class CassandraServer implements 
         if (logger.isDebugEnabled())
             logger.debug("get");
 
-        state().hasKeyspaceAccess(Permission.READ);
+        state().hasColumnFamilyAccess(column_path.column_family, 
Permission.READ);
         String keyspace = state().getKeyspace();
 
         ThriftValidation.validateColumnPath(keyspace, column_path);
@@ -334,7 +334,7 @@ public class CassandraServer implements 
         if (logger.isDebugEnabled())
             logger.debug("get_count");
 
-        state().hasKeyspaceAccess(Permission.READ);
+        state().hasColumnFamilyAccess(column_parent.column_family, 
Permission.READ);
 
         return get_slice(key, column_parent, predicate, 
consistency_level).size();
     }
@@ -345,7 +345,7 @@ public class CassandraServer implements 
         if (logger.isDebugEnabled())
             logger.debug("multiget_count");
 
-        state().hasKeyspaceAccess(Permission.READ);
+        state().hasColumnFamilyAccess(column_parent.column_family, 
Permission.READ);
         String keyspace = state().getKeyspace();
 
         Map<byte[], Integer> counts = new HashMap<byte[], Integer>();
@@ -363,7 +363,7 @@ public class CassandraServer implements 
         if (logger.isDebugEnabled())
             logger.debug("insert");
 
-        state().hasKeyspaceAccess(Permission.WRITE);
+        state().hasColumnFamilyAccess(column_parent.column_family, 
Permission.WRITE);
 
         ThriftValidation.validateKey(key);
         ThriftValidation.validateColumnParent(state().getKeyspace(), 
column_parent);
@@ -386,8 +386,8 @@ public class CassandraServer implements 
     {
         if (logger.isDebugEnabled())
             logger.debug("batch_mutate");
-
-        state().hasKeyspaceAccess(Permission.WRITE);
+        
+        List<String> cfamsSeen = new ArrayList<String>();
 
         List<RowMutation> rowMutations = new ArrayList<RowMutation>();
         for (Map.Entry<byte[], Map<String, List<Mutation>>> mutationEntry: 
mutation_map.entrySet())
@@ -399,6 +399,13 @@ public class CassandraServer implements 
             for (Map.Entry<String, List<Mutation>> columnFamilyMutations : 
columnFamilyToMutations.entrySet())
             {
                 String cfName = columnFamilyMutations.getKey();
+                
+                // Avoid unneeded authorizations
+                if (!(cfamsSeen.contains(cfName)))
+                {
+                    state().hasColumnFamilyAccess(cfName, Permission.WRITE);
+                    cfamsSeen.add(cfName);
+                }
 
                 for (Mutation mutation : columnFamilyMutations.getValue())
                 {
@@ -417,7 +424,7 @@ public class CassandraServer implements 
         if (logger.isDebugEnabled())
             logger.debug("remove");
 
-        state().hasKeyspaceAccess(Permission.WRITE);
+        state().hasColumnFamilyAccess(column_path.column_family, 
Permission.WRITE);
 
         ThriftValidation.validateKey(key);
         ThriftValidation.validateColumnPathOrParent(state().getKeyspace(), 
column_path);
@@ -472,7 +479,7 @@ public class CassandraServer implements 
             logger.debug("range_slice");
 
         String keyspace = state().getKeyspace();
-        state().hasKeyspaceAccess(Permission.READ);
+        state().hasColumnFamilyAccess(column_parent.column_family, 
Permission.READ);
 
         ThriftValidation.validateColumnParent(keyspace, column_parent);
         ThriftValidation.validatePredicate(keyspace, column_parent, predicate);
@@ -535,7 +542,7 @@ public class CassandraServer implements 
         if (logger.isDebugEnabled())
             logger.debug("scan");
 
-        state().hasKeyspaceAccess(Permission.READ);
+        state().hasColumnFamilyAccess(column_parent.column_family, 
Permission.READ);
         String keyspace = state().getKeyspace();
         ThriftValidation.validateColumnParent(keyspace, column_parent);
         ThriftValidation.validatePredicate(keyspace, column_parent, 
column_predicate);
@@ -689,7 +696,7 @@ public class CassandraServer implements 
 
     public String system_add_column_family(CfDef cf_def) throws 
InvalidRequestException, TException
     {
-        state().hasKeyspaceAccess(Permission.WRITE);
+        state().hasColumnFamilyListAccess(Permission.WRITE);
         try
         {
             applyMigrationOnStage(new 
AddColumnFamily(convertToCFMetaData(cf_def)));
@@ -711,7 +718,7 @@ public class CassandraServer implements 
 
     public String system_drop_column_family(String column_family) throws 
InvalidRequestException, TException
     {
-        state().hasKeyspaceAccess(Permission.WRITE);
+        state().hasColumnFamilyListAccess(Permission.WRITE);
         
         try
         {
@@ -734,7 +741,7 @@ public class CassandraServer implements 
 
     public String system_rename_column_family(String old_name, String 
new_name) throws InvalidRequestException, TException
     {
-        state().hasKeyspaceAccess(Permission.WRITE);
+        state().hasColumnFamilyListAccess(Permission.WRITE);
         
         try
         {
@@ -834,7 +841,7 @@ public class CassandraServer implements 
 
     public String system_rename_keyspace(String old_name, String new_name) 
throws InvalidRequestException, TException
     {
-        state().hasKeyspaceAccess(Permission.WRITE);
+        state().hasColumnFamilyListAccess(Permission.WRITE);
         
         try
         {
@@ -858,7 +865,7 @@ public class CassandraServer implements 
     /** update an existing keyspace, but do not allow column family 
modifications. */
     public String system_update_keyspace(KsDef ks_def) throws 
InvalidRequestException, TException
     {
-        state().hasKeyspaceAccess(Permission.WRITE);
+        state().hasColumnFamilyListAccess(Permission.WRITE);
         
         if (ks_def.getCf_defs() != null && ks_def.getCf_defs().size() > 0)
             throw new InvalidRequestException("Keyspace update must not 
contain any column family definitions.");
@@ -896,7 +903,7 @@ public class CassandraServer implements 
 
     public String system_update_column_family(CfDef cf_def) throws 
InvalidRequestException, TException
     {
-        state().hasKeyspaceAccess(Permission.WRITE);
+        state().hasColumnFamilyListAccess(Permission.WRITE);
         
         if (cf_def.keyspace == null || cf_def.name == null)
             throw new InvalidRequestException("Keyspace and CF name must be 
set.");
@@ -956,7 +963,7 @@ public class CassandraServer implements 
     public void truncate(String cfname) throws InvalidRequestException, 
UnavailableException, TException
     {
         logger.debug("truncating {} in {}", cfname, state().getKeyspace());
-        state().hasKeyspaceAccess(Permission.WRITE);
+        state().hasColumnFamilyAccess(cfname, Permission.WRITE);
         try
         {
             schedule();


Reply via email to