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