Author: matthieu
Date: Mon Nov  2 14:45:36 2015
New Revision: 1712020

URL: http://svn.apache.org/viewvc?rev=1712020&view=rev
Log:
JAMES-1586 implement a cassandra user repository

           Contributed by Antoine Duprat

Added:
    
james/project/trunk/server/data/data-cassandra/src/main/java/org/apache/james/user/
    
james/project/trunk/server/data/data-cassandra/src/main/java/org/apache/james/user/cassandra/
    
james/project/trunk/server/data/data-cassandra/src/main/java/org/apache/james/user/cassandra/CassandraUsersRepository.java
    
james/project/trunk/server/data/data-cassandra/src/main/java/org/apache/james/user/cassandra/CassandraUsersRepositoryModule.java
    
james/project/trunk/server/data/data-cassandra/src/main/java/org/apache/james/user/cassandra/tables/
    
james/project/trunk/server/data/data-cassandra/src/main/java/org/apache/james/user/cassandra/tables/CassandraUserTable.java
    
james/project/trunk/server/data/data-cassandra/src/test/java/org/apache/james/user/
    
james/project/trunk/server/data/data-cassandra/src/test/java/org/apache/james/user/cassandra/
    
james/project/trunk/server/data/data-cassandra/src/test/java/org/apache/james/user/cassandra/CassandraUsersRepositoryTest.java

Added: 
james/project/trunk/server/data/data-cassandra/src/main/java/org/apache/james/user/cassandra/CassandraUsersRepository.java
URL: 
http://svn.apache.org/viewvc/james/project/trunk/server/data/data-cassandra/src/main/java/org/apache/james/user/cassandra/CassandraUsersRepository.java?rev=1712020&view=auto
==============================================================================
--- 
james/project/trunk/server/data/data-cassandra/src/main/java/org/apache/james/user/cassandra/CassandraUsersRepository.java
 (added)
+++ 
james/project/trunk/server/data/data-cassandra/src/main/java/org/apache/james/user/cassandra/CassandraUsersRepository.java
 Mon Nov  2 14:45:36 2015
@@ -0,0 +1,162 @@
+/****************************************************************
+ * 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.james.user.cassandra;
+
+import static com.datastax.driver.core.querybuilder.QueryBuilder.delete;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.insertInto;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.set;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.update;
+import static 
org.apache.james.user.cassandra.tables.CassandraUserTable.ALGORITHM;
+import static org.apache.james.user.cassandra.tables.CassandraUserTable.NAME;
+import static 
org.apache.james.user.cassandra.tables.CassandraUserTable.PASSWORD;
+import static 
org.apache.james.user.cassandra.tables.CassandraUserTable.REALNAME;
+import static 
org.apache.james.user.cassandra.tables.CassandraUserTable.TABLE_NAME;
+
+import java.util.Iterator;
+import java.util.Optional;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.apache.james.backends.cassandra.utils.CassandraConstants;
+import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.user.api.UsersRepositoryException;
+import org.apache.james.user.api.model.User;
+import org.apache.james.user.lib.AbstractUsersRepository;
+import org.apache.james.user.lib.model.DefaultUser;
+
+import com.datastax.driver.core.ResultSet;
+import com.datastax.driver.core.Session;
+import com.google.common.base.Preconditions;
+import com.google.common.primitives.Ints;
+
+public class CassandraUsersRepository extends AbstractUsersRepository {
+
+    private static final String DEFAULT_ALGO_VALUE = "SHA1";
+
+    private Session session;
+
+    @Inject
+    @Resource
+    public void setSession(@Named("cassandra-session") Session session) {
+        this.session = session;
+    }
+
+    @Override
+    public User getUserByName(String name){
+        ResultSet result = session.execute(
+                select(REALNAME, PASSWORD, ALGORITHM)
+                .from(TABLE_NAME)
+                .where(eq(REALNAME, name)));
+        return Optional.ofNullable(result.one())
+            .map(row -> new DefaultUser(row.getString(REALNAME), 
row.getString(PASSWORD), row.getString(ALGORITHM)))
+            .orElse(null);
+    }
+
+    @Override
+    public void updateUser(User user) throws UsersRepositoryException {
+        Preconditions.checkArgument(user instanceof DefaultUser);
+        DefaultUser defaultUser = (DefaultUser) user;
+        boolean executed = session.execute(
+                update(TABLE_NAME)
+                    .with(set(REALNAME, defaultUser.getUserName()))
+                    .and(set(PASSWORD, defaultUser.getHashedPassword()))
+                    .and(set(ALGORITHM, defaultUser.getHashAlgorithm()))
+                    .where(eq(NAME, defaultUser.getUserName().toLowerCase()))
+                    .ifExists())
+                .one()
+                .getBool(CassandraConstants.LIGHTWEIGHT_TRANSACTION_APPLIED);
+
+        if (!executed) {
+            throw new UsersRepositoryException("Unable to update user");
+        }
+    }
+
+    @Override
+    public void removeUser(String name) throws UsersRepositoryException {
+        boolean executed = session.execute(
+            delete()
+                .from(TABLE_NAME)
+                .where(eq(NAME, name))
+                .ifExists())
+            .one()
+            .getBool(CassandraConstants.LIGHTWEIGHT_TRANSACTION_APPLIED);
+
+        if (!executed) {
+            throw new UsersRepositoryException("unable to remove unknown user 
" + name);
+        }
+    }
+
+    @Override
+    public boolean contains(String name) {
+        return getUserByName(name) != null;
+    }
+
+    @Override
+    public boolean test(String name, String password) throws 
UsersRepositoryException {
+        return Optional.ofNullable(getUserByName(name))
+                .map(x -> x.verifyPassword(password))
+                .orElse(false);
+    }
+
+    @Override
+    public int countUsers() throws UsersRepositoryException {
+        ResultSet result = 
session.execute(select().countAll().from(TABLE_NAME));
+        return Ints.checkedCast(result.one().getLong(0));
+    }
+
+    @Override
+    public Iterator<String> list() throws UsersRepositoryException {
+        ResultSet result = session.execute(
+                select(REALNAME)
+                .from(TABLE_NAME));
+        return CassandraUtils.convertToStream(result)
+            .map(row -> row.getString(REALNAME))
+            .iterator();
+    }
+
+    @Override
+    public void addUser(String username, String password) throws 
UsersRepositoryException {
+        isValidUsername(username);
+        doAddUser(username, password);
+    }
+
+    @Override
+    protected void doAddUser(String username, String password) throws 
UsersRepositoryException {
+        DefaultUser user = new DefaultUser(username, DEFAULT_ALGO_VALUE);
+        user.setPassword(password);
+        boolean executed = session.execute(
+            insertInto(TABLE_NAME)
+                .value(NAME, user.getUserName().toLowerCase())
+                .value(REALNAME, user.getUserName())
+                .value(PASSWORD, user.getHashedPassword())
+                .value(ALGORITHM, user.getHashAlgorithm())
+                .ifNotExists())
+            .one()
+            .getBool(CassandraConstants.LIGHTWEIGHT_TRANSACTION_APPLIED);
+
+        if (!executed) {
+            throw new UsersRepositoryException("User with username " + 
username + " already exist!");
+        }
+    }
+}

Added: 
james/project/trunk/server/data/data-cassandra/src/main/java/org/apache/james/user/cassandra/CassandraUsersRepositoryModule.java
URL: 
http://svn.apache.org/viewvc/james/project/trunk/server/data/data-cassandra/src/main/java/org/apache/james/user/cassandra/CassandraUsersRepositoryModule.java?rev=1712020&view=auto
==============================================================================
--- 
james/project/trunk/server/data/data-cassandra/src/main/java/org/apache/james/user/cassandra/CassandraUsersRepositoryModule.java
 (added)
+++ 
james/project/trunk/server/data/data-cassandra/src/main/java/org/apache/james/user/cassandra/CassandraUsersRepositoryModule.java
 Mon Nov  2 14:45:36 2015
@@ -0,0 +1,75 @@
+/****************************************************************
+ * 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.james.user.cassandra;
+
+import static com.datastax.driver.core.DataType.text;
+
+import java.util.List;
+
+import org.apache.james.backends.cassandra.components.CassandraIndex;
+import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.backends.cassandra.components.CassandraTable;
+import org.apache.james.backends.cassandra.components.CassandraType;
+import org.apache.james.user.cassandra.tables.CassandraUserTable;
+
+import com.datastax.driver.core.schemabuilder.SchemaBuilder;
+import com.google.common.collect.ImmutableList;
+
+public class CassandraUsersRepositoryModule implements CassandraModule {
+
+    private final List<CassandraTable> tables;
+    private final List<CassandraIndex> index;
+    private final List<CassandraType> types;
+
+    public CassandraUsersRepositoryModule() {
+        tables = ImmutableList.of(
+                new CassandraTable(CassandraUserTable.TABLE_NAME,
+                    SchemaBuilder.createTable(CassandraUserTable.TABLE_NAME)
+                        .ifNotExists()
+                        .addPartitionKey(CassandraUserTable.NAME, text())
+                        .addColumn(CassandraUserTable.REALNAME, text())
+                        .addColumn(CassandraUserTable.PASSWORD, text())
+                        .addColumn(CassandraUserTable.ALGORITHM, text()))
+                    );
+        index = ImmutableList.of(
+                new CassandraIndex(
+                    SchemaBuilder.createIndex(CassandraIndex.INDEX_PREFIX + 
CassandraUserTable.TABLE_NAME + CassandraUserTable.REALNAME)
+                        .ifNotExists()
+                        .onTable(CassandraUserTable.TABLE_NAME)
+                        .andColumn(CassandraUserTable.REALNAME))
+                );
+        types = ImmutableList.of();
+    }
+
+    @Override
+    public List<CassandraTable> moduleTables() {
+        return tables;
+    }
+
+    @Override
+    public List<CassandraIndex> moduleIndex() {
+        return index;
+    }
+
+    @Override
+    public List<CassandraType> moduleTypes() {
+        return types;
+    }
+}

Added: 
james/project/trunk/server/data/data-cassandra/src/main/java/org/apache/james/user/cassandra/tables/CassandraUserTable.java
URL: 
http://svn.apache.org/viewvc/james/project/trunk/server/data/data-cassandra/src/main/java/org/apache/james/user/cassandra/tables/CassandraUserTable.java?rev=1712020&view=auto
==============================================================================
--- 
james/project/trunk/server/data/data-cassandra/src/main/java/org/apache/james/user/cassandra/tables/CassandraUserTable.java
 (added)
+++ 
james/project/trunk/server/data/data-cassandra/src/main/java/org/apache/james/user/cassandra/tables/CassandraUserTable.java
 Mon Nov  2 14:45:36 2015
@@ -0,0 +1,29 @@
+/****************************************************************
+ * 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.james.user.cassandra.tables;
+
+public interface CassandraUserTable {
+    String TABLE_NAME = "user";
+
+    String ALGORITHM = "algorithm";
+    String NAME = "name";
+    String PASSWORD = "passwd";
+    String REALNAME = "realname";
+}

Added: 
james/project/trunk/server/data/data-cassandra/src/test/java/org/apache/james/user/cassandra/CassandraUsersRepositoryTest.java
URL: 
http://svn.apache.org/viewvc/james/project/trunk/server/data/data-cassandra/src/test/java/org/apache/james/user/cassandra/CassandraUsersRepositoryTest.java?rev=1712020&view=auto
==============================================================================
--- 
james/project/trunk/server/data/data-cassandra/src/test/java/org/apache/james/user/cassandra/CassandraUsersRepositoryTest.java
 (added)
+++ 
james/project/trunk/server/data/data-cassandra/src/test/java/org/apache/james/user/cassandra/CassandraUsersRepositoryTest.java
 Mon Nov  2 14:45:36 2015
@@ -0,0 +1,43 @@
+/****************************************************************
+ * 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.james.user.cassandra;
+
+import org.apache.james.backends.cassandra.CassandraCluster;
+import org.apache.james.user.api.UsersRepository;
+import org.apache.james.user.lib.AbstractUsersRepositoryTest;
+import org.junit.After;
+
+public class CassandraUsersRepositoryTest extends AbstractUsersRepositoryTest {
+
+    private CassandraCluster cassandra;
+
+    @After
+    public void tearDown() {
+        cassandra.clearAllTables();
+    }
+
+    @Override
+    protected UsersRepository getUsersRepository() throws Exception {
+        cassandra = CassandraCluster.create(new 
CassandraUsersRepositoryModule());
+        CassandraUsersRepository cassandraUsersRepository = new 
CassandraUsersRepository();
+        cassandraUsersRepository.setSession(cassandra.getConf());
+        return cassandraUsersRepository;
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org
For additional commands, e-mail: server-dev-h...@james.apache.org

Reply via email to