diff --git a/src/java/org/apache/cassandra/auth/AuthenticatedUser.java b/src/java/org/apache/cassandra/auth/AuthenticatedUser.java index d703abc9a4..7988f00dfa 100644 --- a/src/java/org/apache/cassandra/auth/AuthenticatedUser.java +++ b/src/java/org/apache/cassandra/auth/AuthenticatedUser.java @@ -71,6 +71,6 @@ public class AuthenticatedUser @Override public String toString() { - return "#".format(username, groups); + return String.format("#", username, groups); } } diff --git a/src/java/org/apache/cassandra/avro/CassandraServer.java b/src/java/org/apache/cassandra/avro/CassandraServer.java index 9e7d853cba..cd0b82afee 100644 --- a/src/java/org/apache/cassandra/avro/CassandraServer.java +++ b/src/java/org/apache/cassandra/avro/CassandraServer.java @@ -56,6 +56,7 @@ import org.apache.cassandra.db.marshal.MarshalException; import org.apache.cassandra.db.migration.AddKeyspace; import org.apache.cassandra.locator.AbstractReplicationStrategy; import org.apache.cassandra.scheduler.IRequestScheduler; +import org.apache.cassandra.service.ClientState; import org.apache.cassandra.service.StorageProxy; import org.apache.cassandra.service.StorageService; @@ -75,22 +76,8 @@ public class CassandraServer implements Cassandra { private final static String D_CF_COMPTYPE = "BytesType"; private final static String D_CF_SUBCOMPTYPE = ""; - private ThreadLocal loginDone = new ThreadLocal() - { - @Override - protected AccessLevel initialValue() - { - return AccessLevel.NONE; - } - }; - - // Session keyspace. - private ThreadLocal curKeyspace = new ThreadLocal(); - - /* - * An associated Id for scheduling the requests - */ - private ThreadLocal requestSchedulerId = new ThreadLocal(); + // thread local state containing session information + private final ClientState clientState = new ClientState(); /* * RequestScheduler to perform the scheduling of incoming requests @@ -108,7 +95,7 @@ public class CassandraServer implements Cassandra { if (logger.isDebugEnabled()) logger.debug("get"); - AvroValidation.validateColumnPath(curKeyspace.get(), columnPath); + AvroValidation.validateColumnPath(clientState.getKeyspace(), columnPath); // FIXME: This is repetitive. byte[] column, super_column; @@ -118,7 +105,7 @@ public class CassandraServer implements Cassandra { QueryPath path = new QueryPath(columnPath.column_family.toString(), column == null ? null : super_column); List nameAsList = Arrays.asList(column == null ? super_column : column); AvroValidation.validateKey(key.array()); - ReadCommand command = new SliceByNamesReadCommand(curKeyspace.get(), key.array(), path, nameAsList); + ReadCommand command = new SliceByNamesReadCommand(clientState.getKeyspace(), key.array(), path, nameAsList); Map, ColumnFamily> cfamilies = readColumnFamily(Arrays.asList(command), consistencyLevel); ColumnFamily cf = cfamilies.get(StorageService.getPartitioner().decorateKey(command.key)); @@ -289,7 +276,7 @@ public class CassandraServer implements Cassandra { GenericArray keys = new GenericData.Array(1, bytesArray); keys.add(key); - return multigetSliceInternal(curKeyspace.get(), keys, columnParent, predicate, consistencyLevel).iterator().next().columns; + return multigetSliceInternal(clientState.getKeyspace(), keys, columnParent, predicate, consistencyLevel).iterator().next().columns; } private GenericArray multigetSliceInternal(String keyspace, GenericArray keys, @@ -366,7 +353,7 @@ public class CassandraServer implements Cassandra { if (logger.isDebugEnabled()) logger.debug("multiget_slice"); - return multigetSliceInternal(curKeyspace.get(), keys, columnParent, predicate, consistencyLevel); + return multigetSliceInternal(clientState.getKeyspace(), keys, columnParent, predicate, consistencyLevel); } @Override @@ -377,10 +364,10 @@ public class CassandraServer implements Cassandra { logger.debug("insert"); AvroValidation.validateKey(key.array()); - AvroValidation.validateColumnParent(curKeyspace.get(), parent); - AvroValidation.validateColumn(curKeyspace.get(), parent, column); + AvroValidation.validateColumnParent(clientState.getKeyspace(), parent); + AvroValidation.validateColumn(clientState.getKeyspace(), parent, column); - RowMutation rm = new RowMutation(curKeyspace.get(), key.array()); + RowMutation rm = new RowMutation(clientState.getKeyspace(), key.array()); try { rm.add(new QueryPath(parent.column_family.toString(), @@ -407,10 +394,10 @@ public class CassandraServer implements Cassandra { logger.debug("remove"); AvroValidation.validateKey(key.array()); - AvroValidation.validateColumnPath(curKeyspace.get(), columnPath); + AvroValidation.validateColumnPath(clientState.getKeyspace(), columnPath); IClock dbClock = AvroValidation.validateClock(clock); - RowMutation rm = new RowMutation(curKeyspace.get(), key.array()); + RowMutation rm = new RowMutation(clientState.getKeyspace(), key.array()); byte[] superName = columnPath.super_column == null ? null : columnPath.super_column.array(); rm.delete(new QueryPath(columnPath.column_family.toString(), superName), dbClock); @@ -474,9 +461,9 @@ public class CassandraServer implements Cassandra { String cfName = cfMutations.getKey().toString(); for (Mutation mutation : cfMutations.getValue()) - AvroValidation.validateMutation(curKeyspace.get(), cfName, mutation); + AvroValidation.validateMutation(clientState.getKeyspace(), cfName, mutation); } - rowMutations.add(getRowMutationFromMutations(curKeyspace.get(), pair.key.array(), cfToMutations)); + rowMutations.add(getRowMutationFromMutations(clientState.getKeyspace(), pair.key.array(), cfToMutations)); } if (consistencyLevel == ConsistencyLevel.ZERO) @@ -611,16 +598,7 @@ public class CassandraServer implements Cassandra { throw newInvalidRequestException("Keyspace does not exist"); } - // If switching, invalidate previous access level; force a new login. - if (this.curKeyspace.get() != null && !this.curKeyspace.get().equals(keyspaceStr)) - loginDone.set(AccessLevel.NONE); - - this.curKeyspace.set(keyspaceStr); - - if (DatabaseDescriptor.getRequestSchedulerId().equals(Config.RequestSchedulerId.keyspace)) { - requestSchedulerId.set(curKeyspace.get()); - } - + clientState.setKeyspace(keyspaceStr); return null; } @@ -742,7 +720,7 @@ public class CassandraServer implements Cassandra { */ private void schedule() { - requestScheduler.queue(Thread.currentThread(), requestSchedulerId.get()); + requestScheduler.queue(Thread.currentThread(), clientState.getSchedulingId()); } /** diff --git a/src/java/org/apache/cassandra/service/ClientState.java b/src/java/org/apache/cassandra/service/ClientState.java new file mode 100644 index 0000000000..3532357647 --- /dev/null +++ b/src/java/org/apache/cassandra/service/ClientState.java @@ -0,0 +1,146 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.cassandra.service; + +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.apache.cassandra.auth.AuthenticatedUser; +import org.apache.cassandra.avro.AccessLevel; +import org.apache.cassandra.config.Config.RequestSchedulerId; +import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.cassandra.config.KSMetaData; +import org.apache.cassandra.thrift.AuthenticationException; +import org.apache.cassandra.thrift.AuthorizationException; +import org.apache.cassandra.thrift.InvalidRequestException; + +/** + * A container for per-client, thread-local state that Avro/Thrift threads must hold. + */ +public class ClientState +{ + private static Logger logger = LoggerFactory.getLogger(ClientState.class); + + // true if the keyspace should be used as the scheduling id + private final boolean SCHEDULE_ON_KEYSPACE = DatabaseDescriptor.getRequestSchedulerId().equals(RequestSchedulerId.keyspace); + + // Current user for the session + private final ThreadLocal user = new ThreadLocal() + { + @Override + public AuthenticatedUser initialValue() + { + return DatabaseDescriptor.getAuthenticator().defaultUser(); + } + }; + + // Keyspace and keyspace AccessLevels associated with the session + private final ThreadLocal keyspace = new ThreadLocal(); + private final ThreadLocal keyspaceAccess = new ThreadLocal(); + + /** + * Called when the keyspace or user have changed. + */ + private void updateKeyspaceAccess() + { + if (user.get() == null) + // user is not logged in + keyspaceAccess.set(null); + else if (user.get().isSuper) + // super user + keyspaceAccess.set(AccessLevel.FULL); + else if (keyspace.get() != null) + { + // lookup the access level for the user in the current keyspace + KSMetaData ksm = DatabaseDescriptor.getTableDefinition(keyspace.get()); + keyspaceAccess.set(user.get().levelFor(ksm.usersAccess, ksm.groupsAccess)); + } + else + // user is logged in, but no keyspace is set + keyspaceAccess.set(null); + } + + public String getKeyspace() + { + return keyspace.get(); + } + + public void setKeyspace(String ks) + { + keyspace.set(ks); + updateKeyspaceAccess(); + } + + public String getSchedulingId() + { + if (SCHEDULE_ON_KEYSPACE) + return keyspace.get(); + return "default"; + } + + /** + * Attempts to login this client with the given credentials map. + * TODO: Kill thrift exceptions + */ + public void login(Map credentials) throws AuthenticationException, AuthorizationException + { + AuthenticatedUser user = DatabaseDescriptor.getAuthenticator().login(credentials); + if (logger.isDebugEnabled()) + logger.debug("logged in: {}", user); + this.user.set(user); + updateKeyspaceAccess(); + } + + public void logout() + { + if (logger.isDebugEnabled()) + logger.debug("logged out: {}", user.get()); + user.remove(); + keyspace.remove(); + keyspaceAccess.remove(); + } + + /** + * Confirms that the client thread has the given AccessLevel in the 'base' context (where Keyspace + * management occurs). + */ + public void hasBaseAccess(AccessLevel level) throws InvalidRequestException + { + if (user.get() == null) + throw new InvalidRequestException("You have not logged in"); + // FIXME: only checking for the super user until 1271 lands + if (!user.get().isSuper) + throw new InvalidRequestException("Only a 'super' user may modify keyspaces"); + } + + /** + * Confirms that the client thread has the given AccessLevel in the context of the current Keyspace. + */ + public void hasKeyspaceAccess(AccessLevel level) throws InvalidRequestException + { + if (user.get() == null) + throw new InvalidRequestException("You have not logged in"); + if (keyspaceAccess.get() == null) + throw new InvalidRequestException("You have not set a keyspace for this session"); + if (keyspaceAccess.get().ordinal() < level.ordinal()) + throw new InvalidRequestException(String.format("Your user (%s) does not have permission to perform %s operations", user, level)); + } +} diff --git a/src/java/org/apache/cassandra/thrift/CassandraDaemon.java b/src/java/org/apache/cassandra/thrift/CassandraDaemon.java index 3447c7b04f..3ab9769c96 100644 --- a/src/java/org/apache/cassandra/thrift/CassandraDaemon.java +++ b/src/java/org/apache/cassandra/thrift/CassandraDaemon.java @@ -189,7 +189,7 @@ public class CassandraDaemon extends org.apache.cassandra.service.AbstractCassan protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); - cassandraServer.logout(); + cassandraServer.clientState.logout(); } }; serverEngine = new CustomTThreadPoolServer(new TProcessorFactory(processor), diff --git a/src/java/org/apache/cassandra/thrift/CassandraServer.java b/src/java/org/apache/cassandra/thrift/CassandraServer.java index 7736913230..d35931aeac 100644 --- a/src/java/org/apache/cassandra/thrift/CassandraServer.java +++ b/src/java/org/apache/cassandra/thrift/CassandraServer.java @@ -29,6 +29,8 @@ import org.apache.cassandra.db.migration.Migration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +// importing avro.AccessLevel hides thrift.AccessLevel +import org.apache.cassandra.avro.AccessLevel; import org.apache.cassandra.auth.AllowAllAuthenticator; import org.apache.cassandra.auth.AuthenticatedUser; import org.apache.cassandra.concurrent.StageManager; @@ -54,6 +56,7 @@ import org.apache.cassandra.dht.IPartitioner; import org.apache.cassandra.dht.Range; import org.apache.cassandra.dht.Token; import org.apache.cassandra.scheduler.IRequestScheduler; +import org.apache.cassandra.service.ClientState; import org.apache.cassandra.service.StorageProxy; import org.apache.cassandra.service.StorageService; import org.apache.thrift.TException; @@ -66,24 +69,8 @@ public class CassandraServer implements Cassandra.Iface private final static List EMPTY_COLUMNS = Collections.emptyList(); private final static List EMPTY_SUBCOLUMNS = Collections.emptyList(); - // will be set only by login() - private ThreadLocal loginDone = new ThreadLocal() { - @Override - public AuthenticatedUser initialValue() - { - return DatabaseDescriptor.getAuthenticator().defaultUser(); - } - }; - - /* - * Keyspace associated with session - */ - private ThreadLocal keySpace = new ThreadLocal(); - - /* - * An associated Id for scheduling the requests - */ - private ThreadLocal requestSchedulerId = new ThreadLocal(); + // thread local state containing session information + public final ClientState clientState = new ClientState(); /* * RequestScheduler to perform the scheduling of incoming requests @@ -226,12 +213,12 @@ public class CassandraServer implements Cassandra.Iface return thrift_clock; } - private static Map unthriftifyAccessMap(Map map) + private static Map unthriftifyAccessMap(Map map) { - Map out = new HashMap(); + Map out = new HashMap(); if (map == null) return out; - for (Map.Entry entry : map.entrySet()) + for (Map.Entry entry : map.entrySet()) out.put(entry.getKey(), Enum.valueOf(org.apache.cassandra.avro.AccessLevel.class, entry.getValue().name())); return out; } @@ -277,8 +264,8 @@ public class CassandraServer implements Cassandra.Iface if (logger.isDebugEnabled()) logger.debug("get_slice"); - checkKeyspaceAndLoginAuthorized(AccessLevel.READONLY); - return multigetSliceInternal(keySpace.get(), Arrays.asList(key), column_parent, predicate, consistency_level).get(key); + clientState.hasKeyspaceAccess(AccessLevel.READONLY); + return multigetSliceInternal(clientState.getKeyspace(), Arrays.asList(key), column_parent, predicate, consistency_level).get(key); } public Map> multiget_slice(List keys, ColumnParent column_parent, SlicePredicate predicate, ConsistencyLevel consistency_level) @@ -287,9 +274,9 @@ public class CassandraServer implements Cassandra.Iface if (logger.isDebugEnabled()) logger.debug("multiget_slice"); - checkKeyspaceAndLoginAuthorized(AccessLevel.READONLY); + clientState.hasKeyspaceAccess(AccessLevel.READONLY); - return multigetSliceInternal(keySpace.get(), keys, column_parent, predicate, consistency_level); + return multigetSliceInternal(clientState.getKeyspace(), keys, column_parent, predicate, consistency_level); } private Map> multigetSliceInternal(String keyspace, List keys, ColumnParent column_parent, SlicePredicate predicate, ConsistencyLevel consistency_level) @@ -326,8 +313,8 @@ public class CassandraServer implements Cassandra.Iface if (logger.isDebugEnabled()) logger.debug("get"); - checkKeyspaceAndLoginAuthorized(AccessLevel.READONLY); - String keyspace = keySpace.get(); + clientState.hasKeyspaceAccess(AccessLevel.READONLY); + String keyspace = clientState.getKeyspace(); ThriftValidation.validateColumnPath(keyspace, column_path); @@ -354,7 +341,7 @@ public class CassandraServer implements Cassandra.Iface if (logger.isDebugEnabled()) logger.debug("get_count"); - checkKeyspaceAndLoginAuthorized(AccessLevel.READONLY); + clientState.hasKeyspaceAccess(AccessLevel.READONLY); return get_slice(key, column_parent, predicate, consistency_level).size(); } @@ -365,7 +352,7 @@ public class CassandraServer implements Cassandra.Iface if (logger.isDebugEnabled()) logger.debug("multiget_count"); - checkKeyspaceAndLoginAuthorized(AccessLevel.READONLY); + clientState.hasKeyspaceAccess(AccessLevel.READONLY); Map counts = new HashMap(); Map> columnFamiliesMap = multigetSliceInternal(table, keys, column_parent, predicate, consistency_level); @@ -382,14 +369,14 @@ public class CassandraServer implements Cassandra.Iface if (logger.isDebugEnabled()) logger.debug("insert"); - checkKeyspaceAndLoginAuthorized(AccessLevel.READWRITE); + clientState.hasKeyspaceAccess(AccessLevel.READWRITE); ThriftValidation.validateKey(key); - ThriftValidation.validateColumnParent(keySpace.get(), column_parent); - ThriftValidation.validateColumn(keySpace.get(), column_parent, column); + ThriftValidation.validateColumnParent(clientState.getKeyspace(), column_parent); + ThriftValidation.validateColumn(clientState.getKeyspace(), column_parent, column); IClock cassandra_clock = ThriftValidation.validateClock(column.clock); - RowMutation rm = new RowMutation(keySpace.get(), key); + RowMutation rm = new RowMutation(clientState.getKeyspace(), key); try { rm.add(new QueryPath(column_parent.column_family, column_parent.super_column, column.name), column.value, cassandra_clock, column.ttl); @@ -425,7 +412,7 @@ public class CassandraServer implements Cassandra.Iface } } - checkKeyspaceAndLoginAuthorized(needed); + clientState.hasKeyspaceAccess(needed); List rowMutations = new ArrayList(); for (Map.Entry>> mutationEntry: mutation_map.entrySet()) @@ -440,10 +427,10 @@ public class CassandraServer implements Cassandra.Iface for (Mutation mutation : columnFamilyMutations.getValue()) { - ThriftValidation.validateMutation(keySpace.get(), cfName, mutation); + ThriftValidation.validateMutation(clientState.getKeyspace(), cfName, mutation); } } - rowMutations.add(RowMutation.getRowMutationFromMutations(keySpace.get(), key, columnFamilyToMutations)); + rowMutations.add(RowMutation.getRowMutationFromMutations(clientState.getKeyspace(), key, columnFamilyToMutations)); } doInsert(consistency_level, rowMutations); @@ -455,14 +442,14 @@ public class CassandraServer implements Cassandra.Iface if (logger.isDebugEnabled()) logger.debug("remove"); - checkKeyspaceAndLoginAuthorized(AccessLevel.FULL); + clientState.hasKeyspaceAccess(AccessLevel.FULL); ThriftValidation.validateKey(key); - ThriftValidation.validateColumnPathOrParent(keySpace.get(), column_path); + ThriftValidation.validateColumnPathOrParent(clientState.getKeyspace(), column_path); IClock cassandra_clock = ThriftValidation.validateClock(clock); - RowMutation rm = new RowMutation(keySpace.get(), key); + RowMutation rm = new RowMutation(clientState.getKeyspace(), key); rm.delete(new QueryPath(column_path), cassandra_clock); doInsert(consistency_level, Arrays.asList(rm)); @@ -530,8 +517,8 @@ public class CassandraServer implements Cassandra.Iface if (logger.isDebugEnabled()) logger.debug("range_slice"); - String keyspace = keySpace.get(); - checkKeyspaceAndLoginAuthorized(AccessLevel.READONLY); + String keyspace = clientState.getKeyspace(); + clientState.hasKeyspaceAccess(AccessLevel.READONLY); return getRangeSlicesInternal(keyspace, column_parent, range, predicate, consistency_level); } @@ -600,11 +587,11 @@ public class CassandraServer implements Cassandra.Iface if (logger.isDebugEnabled()) logger.debug("scan"); - checkKeyspaceAndLoginAuthorized(AccessLevel.READONLY); + clientState.hasKeyspaceAccess(AccessLevel.READONLY); if (row_predicate.keys != null) { - Map> rowMap = multigetSliceInternal(keySpace.get(), row_predicate.keys, column_parent, column_predicate, consistency_level); + Map> rowMap = multigetSliceInternal(clientState.getKeyspace(), row_predicate.keys, column_parent, column_predicate, consistency_level); List rows = new ArrayList(rowMap.size()); for (Map.Entry> entry : rowMap.entrySet()) { @@ -615,12 +602,12 @@ public class CassandraServer implements Cassandra.Iface if (row_predicate.key_range != null) { - return getRangeSlicesInternal(keySpace.get(), column_parent, row_predicate.key_range, column_predicate, consistency_level); + return getRangeSlicesInternal(clientState.getKeyspace(), column_parent, row_predicate.key_range, column_predicate, consistency_level); } if (row_predicate.index_clause != null) { - return scanIndexInternal(keySpace.get(), column_parent, row_predicate.index_clause, column_predicate, consistency_level); + return scanIndexInternal(clientState.getKeyspace(), column_parent, row_predicate.index_clause, column_predicate, consistency_level); } throw new InvalidRequestException("row predicate must specify keys, key_range, or index_clause"); @@ -709,30 +696,7 @@ public class CassandraServer implements Cassandra.Iface public void login(AuthenticationRequest auth_request) throws AuthenticationException, AuthorizationException, TException { - AuthenticatedUser user = DatabaseDescriptor.getAuthenticator().login(auth_request.getCredentials()); - - if (logger.isDebugEnabled()) - logger.debug("login confirmed; user is " + user); - - loginDone.set(user); - } - - public void logout() - { - keySpace.remove(); - loginDone.remove(); - - if (logger.isDebugEnabled()) - logger.debug("logout complete"); - } - - protected void checkKeyspaceAndLoginAuthorized(AccessLevel level) throws InvalidRequestException - { - if (loginDone.get() == null) - throw new InvalidRequestException("You have not logged in"); - - // FIXME: if no keyspace set, check against global authlist. otherwise, check - // against keyspace authlist + clientState.login(auth_request.getCredentials()); } /** @@ -740,7 +704,7 @@ public class CassandraServer implements Cassandra.Iface */ private void schedule() { - requestScheduler.queue(Thread.currentThread(), requestSchedulerId.get()); + requestScheduler.queue(Thread.currentThread(), clientState.getSchedulingId()); } /** @@ -792,7 +756,8 @@ public class CassandraServer implements Cassandra.Iface public String system_add_column_family(CfDef cf_def) throws InvalidRequestException, TException { - checkKeyspaceAndLoginAuthorized(AccessLevel.FULL); + clientState.hasBaseAccess(AccessLevel.FULL); + try { applyMigrationOnStage(new AddColumnFamily(convertToCFMetaData(cf_def))); @@ -814,11 +779,11 @@ public class CassandraServer implements Cassandra.Iface public String system_drop_column_family(String column_family) throws InvalidRequestException, TException { - checkKeyspaceAndLoginAuthorized(AccessLevel.FULL); + clientState.hasBaseAccess(AccessLevel.FULL); try { - applyMigrationOnStage(new DropColumnFamily(keySpace.get(), column_family, true)); + applyMigrationOnStage(new DropColumnFamily(clientState.getKeyspace(), column_family, true)); return DatabaseDescriptor.getDefsVersion().toString(); } catch (ConfigurationException e) @@ -837,11 +802,11 @@ public class CassandraServer implements Cassandra.Iface public String system_rename_column_family(String old_name, String new_name) throws InvalidRequestException, TException { - checkKeyspaceAndLoginAuthorized(AccessLevel.FULL); + clientState.hasBaseAccess(AccessLevel.FULL); try { - applyMigrationOnStage(new RenameColumnFamily(keySpace.get(), old_name, new_name)); + applyMigrationOnStage(new RenameColumnFamily(clientState.getKeyspace(), old_name, new_name)); return DatabaseDescriptor.getDefsVersion().toString(); } catch (ConfigurationException e) @@ -907,7 +872,7 @@ public class CassandraServer implements Cassandra.Iface public String system_drop_keyspace(String keyspace) throws InvalidRequestException, TException { - checkKeyspaceAndLoginAuthorized(AccessLevel.FULL); + clientState.hasBaseAccess(AccessLevel.FULL); try { @@ -930,7 +895,7 @@ public class CassandraServer implements Cassandra.Iface public String system_rename_keyspace(String old_name, String new_name) throws InvalidRequestException, TException { - checkKeyspaceAndLoginAuthorized(AccessLevel.FULL); + clientState.hasBaseAccess(AccessLevel.FULL); try { @@ -993,12 +958,12 @@ public class CassandraServer implements Cassandra.Iface public void truncate(String cfname) throws InvalidRequestException, UnavailableException, TException { - logger.debug("truncating {} in {}", cfname, keySpace.get()); - checkKeyspaceAndLoginAuthorized(AccessLevel.FULL); + logger.debug("truncating {} in {}", cfname, clientState.getKeyspace()); + clientState.hasKeyspaceAccess(AccessLevel.READWRITE); try { schedule(); - StorageProxy.truncateBlocking(keySpace.get(), cfname); + StorageProxy.truncateBlocking(clientState.getKeyspace(), cfname); } catch (TimeoutException e) { @@ -1021,8 +986,7 @@ public class CassandraServer implements Cassandra.Iface throw new InvalidRequestException("Keyspace does not exist"); } - keySpace.set(keyspace); - requestSchedulerId.set(keyspace); + clientState.setKeyspace(keyspace); } public Map> check_schema_agreement() throws TException, InvalidRequestException