Return-Path: X-Original-To: apmail-cassandra-commits-archive@www.apache.org Delivered-To: apmail-cassandra-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id E42F210EF6 for ; Thu, 29 May 2014 20:00:11 +0000 (UTC) Received: (qmail 17218 invoked by uid 500); 29 May 2014 20:00:11 -0000 Delivered-To: apmail-cassandra-commits-archive@cassandra.apache.org Received: (qmail 17175 invoked by uid 500); 29 May 2014 20:00:11 -0000 Mailing-List: contact commits-help@cassandra.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cassandra.apache.org Delivered-To: mailing list commits@cassandra.apache.org Received: (qmail 17166 invoked by uid 99); 29 May 2014 20:00:11 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 29 May 2014 20:00:11 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 7B24F50892; Thu, 29 May 2014 20:00:11 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: aleksey@apache.org To: commits@cassandra.apache.org Date: Thu, 29 May 2014 20:00:11 -0000 Message-Id: <7392a430e5684554a35aca35d15e3445@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [1/2] git commit: Add conditional CREATE/DROP USER support Repository: cassandra Updated Branches: refs/heads/cassandra-2.1 77f06b8c7 -> a8d18c9c1 Add conditional CREATE/DROP USER support patch by Aleksey Yeschenko; reviewed by Tyler Hobbs for CASSANDRA-7264 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/7216639e Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/7216639e Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/7216639e Branch: refs/heads/cassandra-2.1 Commit: 7216639e512c2f5d4834bd5213d7e30af68aefa3 Parents: 6574de5 Author: Aleksey Yeschenko Authored: Thu May 29 22:55:38 2014 +0300 Committer: Aleksey Yeschenko Committed: Thu May 29 22:55:38 2014 +0300 ---------------------------------------------------------------------- CHANGES.txt | 1 + doc/cql3/CQL.textile | 1 + src/java/org/apache/cassandra/cql3/Cql.g | 12 +++++++----- .../cassandra/cql3/statements/CreateUserStatement.java | 10 ++++++++-- .../cassandra/cql3/statements/DropUserStatement.java | 10 ++++++++-- 5 files changed, 25 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/7216639e/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 98a0a33..28c2ad6 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 2.0.9 + * Add conditional CREATE/DROP USER support (CASSANDRA-7264) * Swap local and global default read repair chances (CASSANDRA-7320) * Add missing iso8601 patterns for date strings (CASSANDRA-6973) * Support selecting multiple rows in a partition using IN (CASSANDRA-6875) http://git-wip-us.apache.org/repos/asf/cassandra/blob/7216639e/doc/cql3/CQL.textile ---------------------------------------------------------------------- diff --git a/doc/cql3/CQL.textile b/doc/cql3/CQL.textile index 393dc0d..f53448e 100644 --- a/doc/cql3/CQL.textile +++ b/doc/cql3/CQL.textile @@ -1173,6 +1173,7 @@ The following describes the addition/changes brought for each version of CQL. h3. 3.1.7 * @SELECT@ statements now support selecting multiple rows in a single partition using an @IN@ clause on combinations of clustering columns. See "SELECT WHERE":#selectWhere clauses. +* @IF NOT EXISTS@ and @IF EXISTS@ syntax is now supported by @CREATE USER@ and @DROP USER@ statmenets, respectively. h3. 3.1.6 http://git-wip-us.apache.org/repos/asf/cassandra/blob/7216639e/src/java/org/apache/cassandra/cql3/Cql.g ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/Cql.g b/src/java/org/apache/cassandra/cql3/Cql.g index ceb2bde..06dbc3a 100644 --- a/src/java/org/apache/cassandra/cql3/Cql.g +++ b/src/java/org/apache/cassandra/cql3/Cql.g @@ -687,17 +687,18 @@ dataResource returns [DataResource res] ; /** - * CREATE USER [WITH PASSWORD ] [SUPERUSER|NOSUPERUSER] + * CREATE USER [IF NOT EXISTS] [WITH PASSWORD ] [SUPERUSER|NOSUPERUSER] */ createUserStatement returns [CreateUserStatement stmt] @init { UserOptions opts = new UserOptions(); boolean superuser = false; + boolean ifNotExists = false; } - : K_CREATE K_USER username + : K_CREATE K_USER (K_IF K_NOT K_EXISTS { ifNotExists = true; })? username ( K_WITH userOptions[opts] )? ( K_SUPERUSER { superuser = true; } | K_NOSUPERUSER { superuser = false; } )? - { $stmt = new CreateUserStatement($username.text, opts, superuser); } + { $stmt = new CreateUserStatement($username.text, opts, superuser, ifNotExists); } ; /** @@ -715,10 +716,11 @@ alterUserStatement returns [AlterUserStatement stmt] ; /** - * DROP USER + * DROP USER [IF EXISTS] */ dropUserStatement returns [DropUserStatement stmt] - : K_DROP K_USER username { $stmt = new DropUserStatement($username.text); } + @init { boolean ifExists = false; } + : K_DROP K_USER (K_IF K_EXISTS { ifExists = true; })? username { $stmt = new DropUserStatement($username.text, ifExists); } ; /** http://git-wip-us.apache.org/repos/asf/cassandra/blob/7216639e/src/java/org/apache/cassandra/cql3/statements/CreateUserStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/CreateUserStatement.java b/src/java/org/apache/cassandra/cql3/statements/CreateUserStatement.java index a82b38d..0903659 100644 --- a/src/java/org/apache/cassandra/cql3/statements/CreateUserStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/CreateUserStatement.java @@ -32,12 +32,14 @@ public class CreateUserStatement extends AuthenticationStatement private final String username; private final UserOptions opts; private final boolean superuser; + private final boolean ifNotExists; - public CreateUserStatement(String username, UserOptions opts, boolean superuser) + public CreateUserStatement(String username, UserOptions opts, boolean superuser, boolean ifNotExists) { this.username = username; this.opts = opts; this.superuser = superuser; + this.ifNotExists = ifNotExists; } public void validate(ClientState state) throws RequestValidationException @@ -50,7 +52,7 @@ public class CreateUserStatement extends AuthenticationStatement // validate login here before checkAccess to avoid leaking user existence to anonymous users. state.ensureNotAnonymous(); - if (Auth.isExistingUser(username)) + if (!ifNotExists && Auth.isExistingUser(username)) throw new InvalidRequestException(String.format("User %s already exists", username)); } @@ -62,6 +64,10 @@ public class CreateUserStatement extends AuthenticationStatement public ResultMessage execute(ClientState state) throws RequestValidationException, RequestExecutionException { + // not rejected in validate() + if (ifNotExists && Auth.isExistingUser(username)) + return null; + DatabaseDescriptor.getAuthenticator().create(username, opts.getOptions()); Auth.insertUser(username, superuser); return null; http://git-wip-us.apache.org/repos/asf/cassandra/blob/7216639e/src/java/org/apache/cassandra/cql3/statements/DropUserStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/DropUserStatement.java b/src/java/org/apache/cassandra/cql3/statements/DropUserStatement.java index 0894db0..9e92b26 100644 --- a/src/java/org/apache/cassandra/cql3/statements/DropUserStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/DropUserStatement.java @@ -30,10 +30,12 @@ import org.apache.cassandra.transport.messages.ResultMessage; public class DropUserStatement extends AuthenticationStatement { private final String username; + private final boolean ifExists; - public DropUserStatement(String username) + public DropUserStatement(String username, boolean ifExists) { this.username = username; + this.ifExists = ifExists; } public void validate(ClientState state) throws RequestValidationException @@ -41,7 +43,7 @@ public class DropUserStatement extends AuthenticationStatement // validate login here before checkAccess to avoid leaking user existence to anonymous users. state.ensureNotAnonymous(); - if (!Auth.isExistingUser(username)) + if (!ifExists && !Auth.isExistingUser(username)) throw new InvalidRequestException(String.format("User %s doesn't exist", username)); AuthenticatedUser user = state.getUser(); @@ -57,6 +59,10 @@ public class DropUserStatement extends AuthenticationStatement public ResultMessage execute(ClientState state) throws RequestValidationException, RequestExecutionException { + // not rejected in validate() + if (ifExists && !Auth.isExistingUser(username)) + return null; + // clean up permissions after the dropped user. DatabaseDescriptor.getAuthorizer().revokeAll(username); Auth.deleteUser(username);