This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch postgresql
in repository https://gitbox.apache.org/repos/asf/james-project.git
The following commit(s) were added to refs/heads/postgresql by this push:
new 52ebcbc2c4 JAMES-2586 postgres users dao and repository (#1803)
52ebcbc2c4 is described below
commit 52ebcbc2c4b374afd8091d17402eb45ef2b3b141
Author: hungphan227 <[email protected]>
AuthorDate: Thu Nov 23 11:02:46 2023 +0700
JAMES-2586 postgres users dao and repository (#1803)
---
.../backends/postgres/utils/PostgresUtils.java | 20 +-
.../postgres/mail/dao/PostgresMailboxDAO.java | 10 +-
.../org/apache/james/PostgresJamesServerMain.java | 12 +-
.../src/main/resources/META-INF/persistence.xml | 1 -
...{JPADataModule.java => PostgresDataModule.java} | 3 +-
...ule.java => PostgresUsersRepositoryModule.java} | 37 ++-
server/data/data-postgres/pom.xml | 11 +
.../org/apache/james/user/jpa/JPAUsersDAO.java | 267 ---------------------
.../org/apache/james/user/jpa/model/JPAUser.java | 193 ---------------
.../james/user/postgres/PostgresUserModule.java} | 46 ++--
.../james/user/postgres/PostgresUsersDAO.java | 143 +++++++++++
.../user/postgres/PostgresUsersRepository.java} | 28 +--
.../PostgresUsersRepositoryConfiguration.java} | 57 ++---
.../rrt/jpa/JPARecipientRewriteTableTest.java | 5 +-
.../java/org/apache/james/rrt/jpa/JPAStepdefs.java | 7 +-
.../apache/james/user/jpa/model/JPAUserTest.java | 73 ------
.../PostgresUsersRepositoryTest.java} | 41 ++--
17 files changed, 288 insertions(+), 666 deletions(-)
diff --git
a/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/JPADataModule.java
b/backends-common/postgres/src/main/java/org/apache/james/backends/postgres/utils/PostgresUtils.java
similarity index 70%
copy from
server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/JPADataModule.java
copy to
backends-common/postgres/src/main/java/org/apache/james/backends/postgres/utils/PostgresUtils.java
index ff1b84b449..9f8b075c14 100644
---
a/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/JPADataModule.java
+++
b/backends-common/postgres/src/main/java/org/apache/james/backends/postgres/utils/PostgresUtils.java
@@ -16,18 +16,16 @@
* specific language governing permissions and limitations *
* under the License. *
****************************************************************/
-package org.apache.james.modules.data;
-import org.apache.james.CoreDataModule;
+package org.apache.james.backends.postgres.utils;
-import com.google.inject.AbstractModule;
+import java.util.function.Predicate;
-public class JPADataModule extends AbstractModule {
- @Override
- protected void configure() {
- install(new CoreDataModule());
- install(new JPADomainListModule());
- install(new JPARecipientRewriteTableModule());
- install(new JPAMailRepositoryModule());
- }
+import org.jooq.exception.DataAccessException;
+
+public class PostgresUtils {
+ private static final String UNIQUE_CONSTRAINT_VIOLATION_MESSAGE =
"duplicate key value violates unique constraint";
+
+ public static final Predicate<Throwable>
UNIQUE_CONSTRAINT_VIOLATION_PREDICATE =
+ throwable -> throwable instanceof DataAccessException &&
throwable.getMessage().contains(UNIQUE_CONSTRAINT_VIOLATION_MESSAGE);
}
diff --git
a/mailbox/postgres/src/main/java/org/apache/james/mailbox/postgres/mail/dao/PostgresMailboxDAO.java
b/mailbox/postgres/src/main/java/org/apache/james/mailbox/postgres/mail/dao/PostgresMailboxDAO.java
index ab0aec9532..f820a2ce07 100644
---
a/mailbox/postgres/src/main/java/org/apache/james/mailbox/postgres/mail/dao/PostgresMailboxDAO.java
+++
b/mailbox/postgres/src/main/java/org/apache/james/mailbox/postgres/mail/dao/PostgresMailboxDAO.java
@@ -19,6 +19,7 @@
package org.apache.james.mailbox.postgres.mail.dao;
+import static
org.apache.james.backends.postgres.utils.PostgresUtils.UNIQUE_CONSTRAINT_VIOLATION_PREDICATE;
import static
org.apache.james.mailbox.postgres.PostgresMailboxIdFaker.getMailboxId;
import static
org.apache.james.mailbox.postgres.mail.PostgresMailboxModule.PostgresMailboxTable.MAILBOX_ACL;
import static
org.apache.james.mailbox.postgres.mail.PostgresMailboxModule.PostgresMailboxTable.MAILBOX_HIGHEST_MODSEQ;
@@ -54,7 +55,6 @@ import org.apache.james.mailbox.model.search.MailboxQuery;
import org.apache.james.mailbox.postgres.PostgresMailboxId;
import org.apache.james.mailbox.store.MailboxExpressionBackwardCompatibility;
import org.jooq.Record;
-import org.jooq.exception.DataAccessException;
import org.jooq.impl.DSL;
import org.jooq.postgres.extensions.types.Hstore;
import org.slf4j.Logger;
@@ -69,7 +69,6 @@ import reactor.core.publisher.Mono;
public class PostgresMailboxDAO {
private static final Logger LOGGER =
LoggerFactory.getLogger(PostgresMailboxDAO.class);
private static final char SQL_WILDCARD_CHAR = '%';
- private static final String DUPLICATE_VIOLATION_MESSAGE = "duplicate key
value violates unique constraint";
private static final Function<MailboxACL, Hstore>
MAILBOX_ACL_TO_HSTORE_FUNCTION = acl -> Hstore.hstore(acl.getEntries()
.entrySet()
.stream()
@@ -105,10 +104,11 @@ public class PostgresMailboxDAO {
public Mono<Mailbox> create(MailboxPath mailboxPath, UidValidity
uidValidity) {
final PostgresMailboxId mailboxId = PostgresMailboxId.generate();
- return postgresExecutor.executeVoid(dslContext ->
Mono.from(dslContext.insertInto(TABLE_NAME, MAILBOX_ID, MAILBOX_NAME,
USER_NAME, MAILBOX_NAMESPACE, MAILBOX_UID_VALIDITY)
- .values(mailboxId.asUuid(), mailboxPath.getName(),
mailboxPath.getUser().asString(), mailboxPath.getNamespace(),
uidValidity.asLong())))
+ return postgresExecutor.executeVoid(dslContext ->
+ Mono.from(dslContext.insertInto(TABLE_NAME, MAILBOX_ID,
MAILBOX_NAME, USER_NAME, MAILBOX_NAMESPACE, MAILBOX_UID_VALIDITY)
+ .values(mailboxId.asUuid(), mailboxPath.getName(),
mailboxPath.getUser().asString(), mailboxPath.getNamespace(),
uidValidity.asLong())))
.thenReturn(new Mailbox(mailboxPath, uidValidity, mailboxId))
- .onErrorMap(e -> e instanceof DataAccessException &&
e.getMessage().contains(DUPLICATE_VIOLATION_MESSAGE),
+ .onErrorMap(UNIQUE_CONSTRAINT_VIOLATION_PREDICATE,
e -> new MailboxExistsException(mailboxPath.getName()));
}
diff --git
a/server/apps/postgres-app/src/main/java/org/apache/james/PostgresJamesServerMain.java
b/server/apps/postgres-app/src/main/java/org/apache/james/PostgresJamesServerMain.java
index fe536100f7..7c5f47c086 100644
---
a/server/apps/postgres-app/src/main/java/org/apache/james/PostgresJamesServerMain.java
+++
b/server/apps/postgres-app/src/main/java/org/apache/james/PostgresJamesServerMain.java
@@ -23,8 +23,8 @@ import org.apache.james.data.UsersRepositoryModuleChooser;
import org.apache.james.modules.MailboxModule;
import org.apache.james.modules.MailetProcessingModule;
import org.apache.james.modules.RunArgumentsModule;
-import org.apache.james.modules.data.JPADataModule;
-import org.apache.james.modules.data.JPAUsersRepositoryModule;
+import org.apache.james.modules.data.PostgresDataModule;
+import org.apache.james.modules.data.PostgresUsersRepositoryModule;
import org.apache.james.modules.data.SieveJPARepositoryModules;
import org.apache.james.modules.mailbox.DefaultEventModule;
import org.apache.james.modules.mailbox.JPAMailboxModule;
@@ -82,9 +82,9 @@ public class PostgresJamesServerMain implements
JamesServerMain {
new ActiveMQQueueModule(),
new NaiveDelegationStoreModule(),
new DefaultProcessorsConfigurationProviderModule(),
- new JPADataModule(),
new JPAMailboxModule(),
new PostgresMailboxModule(),
+ new PostgresDataModule(),
new MailboxModule(),
new LuceneSearchMailboxModule(),
new NoJwtModule(),
@@ -114,8 +114,8 @@ public class PostgresJamesServerMain implements
JamesServerMain {
static GuiceJamesServer createServer(PostgresJamesConfiguration
configuration) {
return GuiceJamesServer.forConfiguration(configuration)
- .combineWith(POSTGRES_MODULE_AGGREGATE)
- .combineWith(new UsersRepositoryModuleChooser(new
JPAUsersRepositoryModule())
-
.chooseModules(configuration.getUsersRepositoryImplementation()));
+ .combineWith(new UsersRepositoryModuleChooser(new
PostgresUsersRepositoryModule())
+
.chooseModules(configuration.getUsersRepositoryImplementation()))
+ .combineWith(POSTGRES_MODULE_AGGREGATE);
}
}
diff --git
a/server/apps/postgres-app/src/main/resources/META-INF/persistence.xml
b/server/apps/postgres-app/src/main/resources/META-INF/persistence.xml
index d9e49513f3..5d55f9b767 100644
--- a/server/apps/postgres-app/src/main/resources/META-INF/persistence.xml
+++ b/server/apps/postgres-app/src/main/resources/META-INF/persistence.xml
@@ -33,7 +33,6 @@
<class>org.apache.james.domainlist.jpa.model.JPADomain</class>
<class>org.apache.james.mailrepository.jpa.model.JPAUrl</class>
<class>org.apache.james.mailrepository.jpa.model.JPAMail</class>
- <class>org.apache.james.user.jpa.model.JPAUser</class>
<class>org.apache.james.rrt.jpa.model.JPARecipientRewrite</class>
<class>org.apache.james.sieve.jpa.model.JPASieveQuota</class>
<class>org.apache.james.sieve.jpa.model.JPASieveScript</class>
diff --git
a/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/JPADataModule.java
b/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/PostgresDataModule.java
similarity index 96%
rename from
server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/JPADataModule.java
rename to
server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/PostgresDataModule.java
index ff1b84b449..125746063b 100644
---
a/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/JPADataModule.java
+++
b/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/PostgresDataModule.java
@@ -16,13 +16,14 @@
* specific language governing permissions and limitations *
* under the License. *
****************************************************************/
+
package org.apache.james.modules.data;
import org.apache.james.CoreDataModule;
import com.google.inject.AbstractModule;
-public class JPADataModule extends AbstractModule {
+public class PostgresDataModule extends AbstractModule {
@Override
protected void configure() {
install(new CoreDataModule());
diff --git
a/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/JPAUsersRepositoryModule.java
b/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/PostgresUsersRepositoryModule.java
similarity index 52%
copy from
server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/JPAUsersRepositoryModule.java
copy to
server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/PostgresUsersRepositoryModule.java
index 5a719244a4..99289c5ce4 100644
---
a/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/JPAUsersRepositoryModule.java
+++
b/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/PostgresUsersRepositoryModule.java
@@ -16,29 +16,42 @@
* specific language governing permissions and limitations *
* under the License. *
****************************************************************/
+
package org.apache.james.modules.data;
+import org.apache.commons.configuration2.ex.ConfigurationException;
+import org.apache.james.backends.postgres.PostgresModule;
import org.apache.james.server.core.configuration.ConfigurationProvider;
import org.apache.james.user.api.UsersRepository;
-import org.apache.james.user.jpa.JPAUsersRepository;
-import org.apache.james.utils.InitializationOperation;
-import org.apache.james.utils.InitilizationOperationBuilder;
+import org.apache.james.user.lib.UsersDAO;
+import org.apache.james.user.postgres.PostgresUserModule;
+import org.apache.james.user.postgres.PostgresUsersDAO;
+import org.apache.james.user.postgres.PostgresUsersRepository;
+import org.apache.james.user.postgres.PostgresUsersRepositoryConfiguration;
import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
import com.google.inject.Scopes;
-import com.google.inject.multibindings.ProvidesIntoSet;
+import com.google.inject.Singleton;
+import com.google.inject.multibindings.Multibinder;
-public class JPAUsersRepositoryModule extends AbstractModule {
+public class PostgresUsersRepositoryModule extends AbstractModule {
@Override
public void configure() {
- bind(JPAUsersRepository.class).in(Scopes.SINGLETON);
- bind(UsersRepository.class).to(JPAUsersRepository.class);
+ bind(PostgresUsersRepository.class).in(Scopes.SINGLETON);
+ bind(UsersRepository.class).to(PostgresUsersRepository.class);
+
+ bind(PostgresUsersDAO.class).in(Scopes.SINGLETON);
+ bind(UsersDAO.class).to(PostgresUsersDAO.class);
+
+ Multibinder<PostgresModule> postgresDataDefinitions =
Multibinder.newSetBinder(binder(), PostgresModule.class);
+
postgresDataDefinitions.addBinding().toInstance(PostgresUserModule.MODULE);
}
- @ProvidesIntoSet
- InitializationOperation configureJpaUsers(ConfigurationProvider
configurationProvider, JPAUsersRepository usersRepository) {
- return InitilizationOperationBuilder
- .forClass(JPAUsersRepository.class)
- .init(() ->
usersRepository.configure(configurationProvider.getConfiguration("usersrepository")));
+ @Provides
+ @Singleton
+ public PostgresUsersRepositoryConfiguration
provideConfiguration(ConfigurationProvider configurationProvider) throws
ConfigurationException {
+ return PostgresUsersRepositoryConfiguration.from(
+ configurationProvider.getConfiguration("usersrepository"));
}
}
diff --git a/server/data/data-postgres/pom.xml
b/server/data/data-postgres/pom.xml
index dc021f1075..82e0bec73b 100644
--- a/server/data/data-postgres/pom.xml
+++ b/server/data/data-postgres/pom.xml
@@ -65,6 +65,12 @@
<artifactId>james-server-dnsservice-test</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>${james.groupId}</groupId>
+ <artifactId>james-server-guice-common</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>${james.groupId}</groupId>
<artifactId>james-server-lifecycle-api</artifactId>
@@ -134,6 +140,11 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.testcontainers</groupId>
+ <artifactId>postgresql</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
diff --git
a/server/data/data-postgres/src/main/java/org/apache/james/user/jpa/JPAUsersDAO.java
b/server/data/data-postgres/src/main/java/org/apache/james/user/jpa/JPAUsersDAO.java
deleted file mode 100644
index fc12e0eaa0..0000000000
---
a/server/data/data-postgres/src/main/java/org/apache/james/user/jpa/JPAUsersDAO.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/****************************************************************
- * 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.jpa;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Optional;
-
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
-import javax.persistence.EntityTransaction;
-import javax.persistence.NoResultException;
-import javax.persistence.PersistenceException;
-
-import org.apache.commons.configuration2.HierarchicalConfiguration;
-import org.apache.commons.configuration2.tree.ImmutableNode;
-import org.apache.james.backends.jpa.EntityManagerUtils;
-import org.apache.james.core.Username;
-import org.apache.james.lifecycle.api.Configurable;
-import org.apache.james.user.api.UsersRepositoryException;
-import org.apache.james.user.api.model.User;
-import org.apache.james.user.jpa.model.JPAUser;
-import org.apache.james.user.lib.UsersDAO;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-
-/**
- * JPA based UserRepository
- */
-public class JPAUsersDAO implements UsersDAO, Configurable {
- private static final Logger LOGGER =
LoggerFactory.getLogger(JPAUsersDAO.class);
-
- private EntityManagerFactory entityManagerFactory;
- private String algo;
-
- @Override
- public void configure(HierarchicalConfiguration<ImmutableNode> config) {
- algo = config.getString("algorithm", "PBKDF2");
- }
-
- /**
- * Sets entity manager.
- *
- * @param entityManagerFactory
- * the entityManager to set
- */
- public final void setEntityManagerFactory(EntityManagerFactory
entityManagerFactory) {
- this.entityManagerFactory = entityManagerFactory;
- }
-
- public void init() {
- EntityManagerUtils.safelyClose(createEntityManager());
- }
-
- /**
- * Get the user object with the specified user name. Return null if no such
- * user.
- *
- * @param name
- * the name of the user to retrieve
- * @return the user being retrieved, null if the user doesn't exist
- *
- * @since James 1.2.2
- */
- @Override
- public Optional<User> getUserByName(Username name) throws
UsersRepositoryException {
- EntityManager entityManager =
entityManagerFactory.createEntityManager();
-
- try {
- JPAUser singleResult = (JPAUser) entityManager
- .createNamedQuery("findUserByName")
- .setParameter("name", name.asString())
- .getSingleResult();
- return Optional.of(singleResult);
- } catch (NoResultException e) {
- return Optional.empty();
- } catch (PersistenceException e) {
- LOGGER.debug("Failed to find user", e);
- throw new UsersRepositoryException("Unable to search user", e);
- } finally {
- EntityManagerUtils.safelyClose(entityManager);
- }
- }
-
- /**
- * Update the repository with the specified user object. A user object with
- * this username must already exist.
- */
- @Override
- public void updateUser(User user) throws UsersRepositoryException {
- Preconditions.checkNotNull(user);
-
- EntityManager entityManager =
entityManagerFactory.createEntityManager();
-
- final EntityTransaction transaction = entityManager.getTransaction();
- try {
- if (contains(user.getUserName())) {
- transaction.begin();
- entityManager.merge(user);
- transaction.commit();
- } else {
- LOGGER.debug("User not found");
- throw new UsersRepositoryException("User " +
user.getUserName() + " not found");
- }
- } catch (PersistenceException e) {
- LOGGER.debug("Failed to update user", e);
- if (transaction.isActive()) {
- transaction.rollback();
- }
- throw new UsersRepositoryException("Failed to update user " +
user.getUserName().asString(), e);
- } finally {
- EntityManagerUtils.safelyClose(entityManager);
- }
- }
-
- /**
- * Removes a user from the repository
- *
- * @param name
- * the user to remove from the repository
- */
- @Override
- public void removeUser(Username name) throws UsersRepositoryException {
- EntityManager entityManager =
entityManagerFactory.createEntityManager();
-
- final EntityTransaction transaction = entityManager.getTransaction();
- try {
- transaction.begin();
- if
(entityManager.createNamedQuery("deleteUserByName").setParameter("name",
name.asString()).executeUpdate() < 1) {
- transaction.commit();
- throw new UsersRepositoryException("User " + name.asString() +
" does not exist");
- } else {
- transaction.commit();
- }
- } catch (PersistenceException e) {
- LOGGER.debug("Failed to remove user", e);
- if (transaction.isActive()) {
- transaction.rollback();
- }
- throw new UsersRepositoryException("Failed to remove user " +
name.asString(), e);
- } finally {
- EntityManagerUtils.safelyClose(entityManager);
- }
- }
-
- /**
- * Returns whether or not this user is in the repository
- *
- * @param name
- * the name to check in the repository
- * @return whether the user is in the repository
- */
- @Override
- public boolean contains(Username name) throws UsersRepositoryException {
- EntityManager entityManager =
entityManagerFactory.createEntityManager();
-
- try {
- return (Long) entityManager.createNamedQuery("containsUser")
- .setParameter("name", name.asString().toLowerCase(Locale.US))
- .getSingleResult() > 0;
- } catch (PersistenceException e) {
- LOGGER.debug("Failed to find user", e);
- throw new UsersRepositoryException("Failed to find user" +
name.asString(), e);
- } finally {
- EntityManagerUtils.safelyClose(entityManager);
- }
- }
-
- /**
- * Returns a count of the users in the repository.
- *
- * @return the number of users in the repository
- */
- @Override
- public int countUsers() throws UsersRepositoryException {
- EntityManager entityManager =
entityManagerFactory.createEntityManager();
-
- try {
- return ((Long)
entityManager.createNamedQuery("countUsers").getSingleResult()).intValue();
- } catch (PersistenceException e) {
- LOGGER.debug("Failed to find user", e);
- throw new UsersRepositoryException("Failed to count users", e);
- } finally {
- EntityManagerUtils.safelyClose(entityManager);
- }
- }
-
- /**
- * List users in repository.
- *
- * @return Iterator over a collection of Strings, each being one user in
the
- * repository.
- */
- @Override
- @SuppressWarnings("unchecked")
- public Iterator<Username> list() throws UsersRepositoryException {
- EntityManager entityManager =
entityManagerFactory.createEntityManager();
-
- try {
- return ((List<String>)
entityManager.createNamedQuery("listUserNames").getResultList())
- .stream()
- .map(Username::of)
- .collect(ImmutableList.toImmutableList()).iterator();
-
- } catch (PersistenceException e) {
- LOGGER.debug("Failed to find user", e);
- throw new UsersRepositoryException("Failed to list users", e);
- } finally {
- EntityManagerUtils.safelyClose(entityManager);
- }
- }
-
- /**
- * Return a new {@link EntityManager} instance
- *
- * @return manager
- */
- private EntityManager createEntityManager() {
- return entityManagerFactory.createEntityManager();
- }
-
- @Override
- public void addUser(Username username, String password) throws
UsersRepositoryException {
- Username lowerCasedUsername =
Username.of(username.asString().toLowerCase(Locale.US));
- if (contains(lowerCasedUsername)) {
- throw new UsersRepositoryException(lowerCasedUsername.asString() +
" already exists.");
- }
- EntityManager entityManager =
entityManagerFactory.createEntityManager();
- final EntityTransaction transaction = entityManager.getTransaction();
- try {
- transaction.begin();
- JPAUser user = new JPAUser(lowerCasedUsername.asString(),
password, algo);
- entityManager.persist(user);
- transaction.commit();
- } catch (PersistenceException e) {
- LOGGER.debug("Failed to save user", e);
- if (transaction.isActive()) {
- transaction.rollback();
- }
- throw new UsersRepositoryException("Failed to add user" +
username.asString(), e);
- } finally {
- EntityManagerUtils.safelyClose(entityManager);
- }
- }
-
-}
diff --git
a/server/data/data-postgres/src/main/java/org/apache/james/user/jpa/model/JPAUser.java
b/server/data/data-postgres/src/main/java/org/apache/james/user/jpa/model/JPAUser.java
deleted file mode 100644
index 8a5cad22ef..0000000000
---
a/server/data/data-postgres/src/main/java/org/apache/james/user/jpa/model/JPAUser.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/****************************************************************
- * 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.jpa.model;
-
-import java.nio.charset.StandardCharsets;
-import java.util.Optional;
-import java.util.function.Function;
-
-import javax.persistence.Basic;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import javax.persistence.Version;
-
-import org.apache.james.core.Username;
-import org.apache.james.user.api.model.User;
-import org.apache.james.user.lib.model.Algorithm;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.hash.HashFunction;
-import com.google.common.hash.Hashing;
-
-@Entity(name = "JamesUser")
-@Table(name = "JAMES_USER")
-@NamedQueries({
- @NamedQuery(name = "findUserByName", query = "SELECT user FROM JamesUser
user WHERE user.name=:name"),
- @NamedQuery(name = "deleteUserByName", query = "DELETE FROM JamesUser user
WHERE user.name=:name"),
- @NamedQuery(name = "containsUser", query = "SELECT COUNT(user) FROM
JamesUser user WHERE user.name=:name"),
- @NamedQuery(name = "countUsers", query = "SELECT COUNT(user) FROM
JamesUser user"),
- @NamedQuery(name = "listUserNames", query = "SELECT user.name FROM
JamesUser user") })
-public class JPAUser implements User {
-
- /**
- * Hash password.
- *
- * @param password
- * not null
- * @return not null
- */
- @VisibleForTesting
- static String hashPassword(String password, String nullableSalt, String
nullableAlgorithm) {
- Algorithm algorithm =
Algorithm.of(Optional.ofNullable(nullableAlgorithm).orElse("SHA-512"));
- if (algorithm.isPBKDF2()) {
- return algorithm.digest(password, nullableSalt);
- }
- String credentials = password;
- if (algorithm.isSalted() && nullableSalt != null) {
- credentials = nullableSalt + password;
- }
- return chooseHashFunction(algorithm.getName()).apply(credentials);
- }
-
- interface PasswordHashFunction extends Function<String, String> {}
-
- private static PasswordHashFunction chooseHashFunction(String algorithm) {
- switch (algorithm) {
- case "NONE":
- return password -> password;
- default:
- return password ->
chooseHashing(algorithm).hashString(password,
StandardCharsets.UTF_8).toString();
- }
- }
-
- @SuppressWarnings("deprecation")
- private static HashFunction chooseHashing(String algorithm) {
- switch (algorithm) {
- case "MD5":
- return Hashing.md5();
- case "SHA-256":
- return Hashing.sha256();
- case "SHA-512":
- return Hashing.sha512();
- case "SHA-1":
- case "SHA1":
- return Hashing.sha1();
- default:
- return Hashing.sha512();
- }
- }
-
- /** Prevents concurrent modification */
- @Version
- private int version;
-
- /** Key by user name */
- @Id
- @Column(name = "USER_NAME", nullable = false, length = 100)
- private String name;
-
- /** Hashed password */
- @Basic
- @Column(name = "PASSWORD", nullable = false, length = 128)
- private String password;
-
- @Basic
- @Column(name = "PASSWORD_HASH_ALGORITHM", nullable = false, length = 100)
- private String alg;
-
- protected JPAUser() {
- }
-
- public JPAUser(String userName, String password, String alg) {
- super();
- this.name = userName;
- this.alg = alg;
- this.password = hashPassword(password, userName, alg);
- }
-
- @Override
- public Username getUserName() {
- return Username.of(name);
- }
-
- @Override
- public boolean setPassword(String newPass) {
- final boolean result;
- if (newPass == null) {
- result = false;
- } else {
- password = hashPassword(newPass, name, alg);
- result = true;
- }
- return result;
- }
-
- @Override
- public boolean verifyPassword(String pass) {
- final boolean result;
- if (pass == null) {
- result = password == null;
- } else {
- result = password != null && password.equals(hashPassword(pass,
name, alg));
- }
-
- return result;
- }
-
- @Override
- public int hashCode() {
- final int PRIME = 31;
- int result = 1;
- result = PRIME * result + ((name == null) ? 0 : name.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- final JPAUser other = (JPAUser) obj;
- if (name == null) {
- if (other.name != null) {
- return false;
- }
- } else if (!name.equals(other.name)) {
- return false;
- }
- return true;
- }
-
- @Override
- public String toString() {
- return "[User " + name + "]";
- }
-
-}
diff --git
a/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/JPAUsersRepositoryModule.java
b/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUserModule.java
similarity index 50%
copy from
server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/JPAUsersRepositoryModule.java
copy to
server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUserModule.java
index 5a719244a4..6aae9183f8 100644
---
a/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/JPAUsersRepositoryModule.java
+++
b/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUserModule.java
@@ -16,29 +16,35 @@
* specific language governing permissions and limitations *
* under the License. *
****************************************************************/
-package org.apache.james.modules.data;
-import org.apache.james.server.core.configuration.ConfigurationProvider;
-import org.apache.james.user.api.UsersRepository;
-import org.apache.james.user.jpa.JPAUsersRepository;
-import org.apache.james.utils.InitializationOperation;
-import org.apache.james.utils.InitilizationOperationBuilder;
+package org.apache.james.user.postgres;
-import com.google.inject.AbstractModule;
-import com.google.inject.Scopes;
-import com.google.inject.multibindings.ProvidesIntoSet;
+import org.apache.james.backends.postgres.PostgresModule;
+import org.apache.james.backends.postgres.PostgresTable;
+import org.jooq.Field;
+import org.jooq.Record;
+import org.jooq.Table;
+import org.jooq.impl.DSL;
+import org.jooq.impl.SQLDataType;
-public class JPAUsersRepositoryModule extends AbstractModule {
- @Override
- public void configure() {
- bind(JPAUsersRepository.class).in(Scopes.SINGLETON);
- bind(UsersRepository.class).to(JPAUsersRepository.class);
- }
+public interface PostgresUserModule {
+ interface PostgresUserTable {
+ Table<Record> TABLE_NAME = DSL.table("users");
+
+ Field<String> USERNAME = DSL.field("username",
SQLDataType.VARCHAR(255).notNull());
+ Field<String> HASHED_PASSWORD = DSL.field("hashed_password",
SQLDataType.VARCHAR.notNull());
+ Field<String> ALGORITHM = DSL.field("algorithm",
SQLDataType.VARCHAR(100).notNull());
- @ProvidesIntoSet
- InitializationOperation configureJpaUsers(ConfigurationProvider
configurationProvider, JPAUsersRepository usersRepository) {
- return InitilizationOperationBuilder
- .forClass(JPAUsersRepository.class)
- .init(() ->
usersRepository.configure(configurationProvider.getConfiguration("usersrepository")));
+ PostgresTable TABLE = PostgresTable.name(TABLE_NAME.getName())
+ .createTableStep(((dsl, tableName) ->
dsl.createTableIfNotExists(tableName)
+ .column(USERNAME)
+ .column(HASHED_PASSWORD)
+ .column(ALGORITHM)
+ .constraint(DSL.primaryKey(USERNAME))))
+ .disableRowLevelSecurity();
}
+
+ PostgresModule MODULE = PostgresModule.builder()
+ .addTable(PostgresUserTable.TABLE)
+ .build();
}
diff --git
a/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUsersDAO.java
b/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUsersDAO.java
new file mode 100644
index 0000000000..67c998b09a
--- /dev/null
+++
b/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUsersDAO.java
@@ -0,0 +1,143 @@
+/****************************************************************
+ * 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.postgres;
+
+import static
org.apache.james.backends.postgres.utils.PostgresUtils.UNIQUE_CONSTRAINT_VIOLATION_PREDICATE;
+import static
org.apache.james.user.postgres.PostgresUserModule.PostgresUserTable.ALGORITHM;
+import static
org.apache.james.user.postgres.PostgresUserModule.PostgresUserTable.HASHED_PASSWORD;
+import static
org.apache.james.user.postgres.PostgresUserModule.PostgresUserTable.TABLE_NAME;
+import static
org.apache.james.user.postgres.PostgresUserModule.PostgresUserTable.USERNAME;
+import static org.jooq.impl.DSL.count;
+
+import java.util.Iterator;
+import java.util.Optional;
+
+import javax.inject.Inject;
+
+import org.apache.james.backends.postgres.utils.JamesPostgresConnectionFactory;
+import org.apache.james.backends.postgres.utils.PostgresExecutor;
+import org.apache.james.core.Username;
+import org.apache.james.user.api.AlreadyExistInUsersRepositoryException;
+import org.apache.james.user.api.UsersRepositoryException;
+import org.apache.james.user.api.model.User;
+import org.apache.james.user.lib.UsersDAO;
+import org.apache.james.user.lib.model.Algorithm;
+import org.apache.james.user.lib.model.DefaultUser;
+
+import com.google.common.base.Preconditions;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public class PostgresUsersDAO implements UsersDAO {
+ private final PostgresExecutor postgresExecutor;
+ private final Algorithm algorithm;
+ private final Algorithm.HashingMode fallbackHashingMode;
+
+ @Inject
+ public PostgresUsersDAO(JamesPostgresConnectionFactory
jamesPostgresConnectionFactory,
+ PostgresUsersRepositoryConfiguration
postgresUsersRepositoryConfiguration) {
+ this.postgresExecutor = new
PostgresExecutor(jamesPostgresConnectionFactory.getConnection(Optional.empty()));
+ this.algorithm =
postgresUsersRepositoryConfiguration.getPreferredAlgorithm();
+ this.fallbackHashingMode =
postgresUsersRepositoryConfiguration.getFallbackHashingMode();
+ }
+
+ @Override
+ public Optional<? extends User> getUserByName(Username name) {
+ return getUserByNameReactive(name).blockOptional();
+ }
+
+ private Mono<DefaultUser> getUserByNameReactive(Username name) {
+ return postgresExecutor.executeRow(dsl ->
Mono.from(dsl.selectFrom(TABLE_NAME)
+ .where(USERNAME.eq(name.asString()))))
+ .map(record -> new DefaultUser(name, record.get(HASHED_PASSWORD),
+ Algorithm.of(record.get(ALGORITHM), fallbackHashingMode),
algorithm));
+ }
+
+ @Override
+ public void updateUser(User user) throws UsersRepositoryException {
+ Preconditions.checkArgument(user instanceof DefaultUser);
+ DefaultUser defaultUser = (DefaultUser) user;
+
+ boolean executed = postgresExecutor.executeRow(dslContext ->
Mono.from(dslContext.update(TABLE_NAME)
+ .set(HASHED_PASSWORD, defaultUser.getHashedPassword())
+ .set(ALGORITHM, defaultUser.getHashAlgorithm().asString())
+ .where(USERNAME.eq(user.getUserName().asString()))
+ .returning(USERNAME)))
+ .map(record -> record.get(USERNAME))
+ .blockOptional()
+ .isPresent();
+
+ if (!executed) {
+ throw new UsersRepositoryException("Unable to update user");
+ }
+ }
+
+ @Override
+ public void removeUser(Username name) throws UsersRepositoryException {
+ boolean executed = postgresExecutor.executeRow(dslContext ->
Mono.from(dslContext.deleteFrom(TABLE_NAME)
+ .where(USERNAME.eq(name.asString()))
+ .returning(USERNAME)))
+ .map(record -> record.get(USERNAME))
+ .blockOptional()
+ .isPresent();
+
+ if (!executed) {
+ throw new UsersRepositoryException("Unable to update user");
+ }
+ }
+
+ @Override
+ public boolean contains(Username name) {
+ return getUserByName(name).isPresent();
+ }
+
+ @Override
+ public int countUsers() {
+ return postgresExecutor.executeRow(dsl ->
Mono.from(dsl.select(count()).from(TABLE_NAME)))
+ .map(record -> record.get(0, Integer.class))
+ .block();
+ }
+
+ @Override
+ public Iterator<Username> list() throws UsersRepositoryException {
+ return listReactive()
+ .toIterable()
+ .iterator();
+ }
+
+ @Override
+ public Flux<Username> listReactive() {
+ return postgresExecutor.executeRows(dslContext ->
Flux.from(dslContext.selectFrom(TABLE_NAME)))
+ .map(record -> Username.of(record.get(USERNAME)));
+ }
+
+ @Override
+ public void addUser(Username username, String password) {
+ DefaultUser user = new DefaultUser(username, algorithm, algorithm);
+ user.setPassword(password);
+
+ postgresExecutor.executeVoid(dslContext ->
Mono.from(dslContext.insertInto(TABLE_NAME, USERNAME, HASHED_PASSWORD,
ALGORITHM)
+ .values(user.getUserName().asString(),
user.getHashedPassword(), user.getHashAlgorithm().asString())))
+ .onErrorMap(UNIQUE_CONSTRAINT_VIOLATION_PREDICATE,
+ e -> new AlreadyExistInUsersRepositoryException("User with
username " + username + " already exist!"))
+ .block();
+ }
+}
diff --git
a/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/JPAUsersRepositoryModule.java
b/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUsersRepository.java
similarity index 53%
rename from
server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/JPAUsersRepositoryModule.java
rename to
server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUsersRepository.java
index 5a719244a4..610dc90529 100644
---
a/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/JPAUsersRepositoryModule.java
+++
b/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUsersRepository.java
@@ -16,29 +16,17 @@
* specific language governing permissions and limitations *
* under the License. *
****************************************************************/
-package org.apache.james.modules.data;
-import org.apache.james.server.core.configuration.ConfigurationProvider;
-import org.apache.james.user.api.UsersRepository;
-import org.apache.james.user.jpa.JPAUsersRepository;
-import org.apache.james.utils.InitializationOperation;
-import org.apache.james.utils.InitilizationOperationBuilder;
+package org.apache.james.user.postgres;
-import com.google.inject.AbstractModule;
-import com.google.inject.Scopes;
-import com.google.inject.multibindings.ProvidesIntoSet;
+import javax.inject.Inject;
-public class JPAUsersRepositoryModule extends AbstractModule {
- @Override
- public void configure() {
- bind(JPAUsersRepository.class).in(Scopes.SINGLETON);
- bind(UsersRepository.class).to(JPAUsersRepository.class);
- }
+import org.apache.james.domainlist.api.DomainList;
+import org.apache.james.user.lib.UsersRepositoryImpl;
- @ProvidesIntoSet
- InitializationOperation configureJpaUsers(ConfigurationProvider
configurationProvider, JPAUsersRepository usersRepository) {
- return InitilizationOperationBuilder
- .forClass(JPAUsersRepository.class)
- .init(() ->
usersRepository.configure(configurationProvider.getConfiguration("usersrepository")));
+public class PostgresUsersRepository extends
UsersRepositoryImpl<PostgresUsersDAO> {
+ @Inject
+ public PostgresUsersRepository(DomainList domainList, PostgresUsersDAO
usersDAO) {
+ super(domainList, usersDAO);
}
}
diff --git
a/server/data/data-postgres/src/main/java/org/apache/james/user/jpa/JPAUsersRepository.java
b/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUsersRepositoryConfiguration.java
similarity index 50%
rename from
server/data/data-postgres/src/main/java/org/apache/james/user/jpa/JPAUsersRepository.java
rename to
server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUsersRepositoryConfiguration.java
index b3f9397abe..8e891c185f 100644
---
a/server/data/data-postgres/src/main/java/org/apache/james/user/jpa/JPAUsersRepository.java
+++
b/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUsersRepositoryConfiguration.java
@@ -17,48 +17,41 @@
* under the License. *
****************************************************************/
-package org.apache.james.user.jpa;
-
-import javax.annotation.PostConstruct;
-import javax.inject.Inject;
-import javax.persistence.EntityManagerFactory;
-import javax.persistence.PersistenceUnit;
+package org.apache.james.user.postgres;
import org.apache.commons.configuration2.HierarchicalConfiguration;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.configuration2.tree.ImmutableNode;
-import org.apache.james.domainlist.api.DomainList;
-import org.apache.james.user.lib.UsersRepositoryImpl;
+import org.apache.james.user.lib.model.Algorithm;
+import org.apache.james.user.lib.model.Algorithm.HashingMode;
+
+public class PostgresUsersRepositoryConfiguration {
+ public static final String DEFAULT_ALGORITHM = "PBKDF2-SHA512";
+ public static final String DEFAULT_HASHING_MODE = HashingMode.PLAIN.name();
+
+ public static final PostgresUsersRepositoryConfiguration DEFAULT = new
PostgresUsersRepositoryConfiguration(
+ Algorithm.of(DEFAULT_ALGORITHM),
HashingMode.parse(DEFAULT_HASHING_MODE)
+ );
+
+ private final Algorithm preferredAlgorithm;
+ private final HashingMode fallbackHashingMode;
-/**
- * JPA based UserRepository
- */
-public class JPAUsersRepository extends UsersRepositoryImpl<JPAUsersDAO> {
- @Inject
- public JPAUsersRepository(DomainList domainList) {
- super(domainList, new JPAUsersDAO());
+ public PostgresUsersRepositoryConfiguration(Algorithm preferredAlgorithm,
HashingMode fallbackHashingMode) {
+ this.preferredAlgorithm = preferredAlgorithm;
+ this.fallbackHashingMode = fallbackHashingMode;
}
- /**
- * Sets entity manager.
- *
- * @param entityManagerFactory
- * the entityManager to set
- */
- @Inject
- @PersistenceUnit(unitName = "James")
- public final void setEntityManagerFactory(EntityManagerFactory
entityManagerFactory) {
- usersDAO.setEntityManagerFactory(entityManagerFactory);
+ public Algorithm getPreferredAlgorithm() {
+ return preferredAlgorithm;
}
- @PostConstruct
- public void init() {
- usersDAO.init();
+ public HashingMode getFallbackHashingMode() {
+ return fallbackHashingMode;
}
- @Override
- public void configure(HierarchicalConfiguration<ImmutableNode> config)
throws ConfigurationException {
- usersDAO.configure(config);
- super.configure(config);
+ public static PostgresUsersRepositoryConfiguration
from(HierarchicalConfiguration<ImmutableNode> config) throws
ConfigurationException {
+ return new PostgresUsersRepositoryConfiguration(
+ Algorithm.of(config.getString("algorithm", DEFAULT_ALGORITHM)),
+ HashingMode.parse(config.getString("hashingMode",
DEFAULT_HASHING_MODE)));
}
}
diff --git
a/server/data/data-postgres/src/test/java/org/apache/james/rrt/jpa/JPARecipientRewriteTableTest.java
b/server/data/data-postgres/src/test/java/org/apache/james/rrt/jpa/JPARecipientRewriteTableTest.java
index 2f60f58192..308f448d69 100644
---
a/server/data/data-postgres/src/test/java/org/apache/james/rrt/jpa/JPARecipientRewriteTableTest.java
+++
b/server/data/data-postgres/src/test/java/org/apache/james/rrt/jpa/JPARecipientRewriteTableTest.java
@@ -25,7 +25,8 @@ import org.apache.james.domainlist.api.DomainList;
import org.apache.james.rrt.jpa.model.JPARecipientRewrite;
import org.apache.james.rrt.lib.AbstractRecipientRewriteTable;
import org.apache.james.rrt.lib.RecipientRewriteTableContract;
-import org.apache.james.user.jpa.JPAUsersRepository;
+import org.apache.james.user.postgres.PostgresUsersDAO;
+import org.apache.james.user.postgres.PostgresUsersRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
@@ -49,7 +50,7 @@ class JPARecipientRewriteTableTest implements
RecipientRewriteTableContract {
public void createRecipientRewriteTable() {
JPARecipientRewriteTable localVirtualUserTable = new
JPARecipientRewriteTable();
localVirtualUserTable.setEntityManagerFactory(JPA_TEST_CLUSTER.getEntityManagerFactory());
- localVirtualUserTable.setUsersRepository(new
JPAUsersRepository(mock(DomainList.class)));
+ localVirtualUserTable.setUsersRepository(new
PostgresUsersRepository(mock(DomainList.class), mock(PostgresUsersDAO.class)));
recipientRewriteTable = localVirtualUserTable;
}
diff --git
a/server/data/data-postgres/src/test/java/org/apache/james/rrt/jpa/JPAStepdefs.java
b/server/data/data-postgres/src/test/java/org/apache/james/rrt/jpa/JPAStepdefs.java
index 3908dfe98e..6ff9058402 100644
---
a/server/data/data-postgres/src/test/java/org/apache/james/rrt/jpa/JPAStepdefs.java
+++
b/server/data/data-postgres/src/test/java/org/apache/james/rrt/jpa/JPAStepdefs.java
@@ -18,12 +18,15 @@
****************************************************************/
package org.apache.james.rrt.jpa;
+import static org.mockito.Mockito.mock;
+
import org.apache.james.backends.jpa.JpaTestCluster;
import org.apache.james.rrt.jpa.model.JPARecipientRewrite;
import org.apache.james.rrt.lib.AbstractRecipientRewriteTable;
import org.apache.james.rrt.lib.RecipientRewriteTableFixture;
import org.apache.james.rrt.lib.RewriteTablesStepdefs;
-import org.apache.james.user.jpa.JPAUsersRepository;
+import org.apache.james.user.postgres.PostgresUsersDAO;
+import org.apache.james.user.postgres.PostgresUsersRepository;
import com.github.fge.lambdas.Throwing;
@@ -53,7 +56,7 @@ public class JPAStepdefs {
private AbstractRecipientRewriteTable getRecipientRewriteTable() throws
Exception {
JPARecipientRewriteTable localVirtualUserTable = new
JPARecipientRewriteTable();
localVirtualUserTable.setEntityManagerFactory(JPA_TEST_CLUSTER.getEntityManagerFactory());
- localVirtualUserTable.setUsersRepository(new
JPAUsersRepository(RecipientRewriteTableFixture.domainListForCucumberTests()));
+ localVirtualUserTable.setUsersRepository(new
PostgresUsersRepository(RecipientRewriteTableFixture.domainListForCucumberTests(),
mock(PostgresUsersDAO.class)));
localVirtualUserTable.setDomainList(RecipientRewriteTableFixture.domainListForCucumberTests());
return localVirtualUserTable;
}
diff --git
a/server/data/data-postgres/src/test/java/org/apache/james/user/jpa/model/JPAUserTest.java
b/server/data/data-postgres/src/test/java/org/apache/james/user/jpa/model/JPAUserTest.java
deleted file mode 100644
index fa11b2504d..0000000000
---
a/server/data/data-postgres/src/test/java/org/apache/james/user/jpa/model/JPAUserTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************
- * 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.jpa.model;
-
-import org.assertj.core.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-class JPAUserTest {
-
- private static final String RANDOM_PASSWORD = "baeMiqu7";
-
- @Test
- void hashPasswordShouldBeNoopWhenNone() {
- //I doubt the expected result was the author intent
- Assertions.assertThat(JPAUser.hashPassword(RANDOM_PASSWORD, null,
"NONE")).isEqualTo("baeMiqu7");
- }
-
- @Test
- void hashPasswordShouldHashWhenMD5() {
- Assertions.assertThat(JPAUser.hashPassword(RANDOM_PASSWORD, null,
"MD5")).isEqualTo("702000e50c9fd3755b8fc20ecb07d1ac");
- }
-
- @Test
- void hashPasswordShouldHashWhenSHA1() {
- Assertions.assertThat(JPAUser.hashPassword(RANDOM_PASSWORD, null,
"SHA1")).isEqualTo("05dbbaa7b4bcae245f14d19ae58ef1b80adf3363");
- }
-
- @Test
- void hashPasswordShouldHashWhenSHA256() {
- Assertions.assertThat(JPAUser.hashPassword(RANDOM_PASSWORD, null,
"SHA-256")).isEqualTo("6d06c72a578fe0b78ede2393b07739831a287774dcad0b18bc4bde8b0c948b82");
- }
-
- @Test
- void hashPasswordShouldHashWhenSHA512() {
- Assertions.assertThat(JPAUser.hashPassword(RANDOM_PASSWORD, null,
"SHA-512")).isEqualTo("f9cc82d1c04bb2ce0494a51f7a21d07ac60b6f79a8a55397f454603acac29d8589fdfd694d5c01ba01a346c76b090abca9ad855b5b0c92c6062ad6d93cdc0d03");
- }
-
- @Test
- void hashPasswordShouldSha512WhenRandomString() {
- Assertions.assertThat(JPAUser.hashPassword(RANDOM_PASSWORD, null,
"random")).isEqualTo("f9cc82d1c04bb2ce0494a51f7a21d07ac60b6f79a8a55397f454603acac29d8589fdfd694d5c01ba01a346c76b090abca9ad855b5b0c92c6062ad6d93cdc0d03");
- }
-
- @Test
- void hashPasswordShouldSha512WhenNull() {
- Assertions.assertThat(JPAUser.hashPassword(RANDOM_PASSWORD, null,
null)).isEqualTo("f9cc82d1c04bb2ce0494a51f7a21d07ac60b6f79a8a55397f454603acac29d8589fdfd694d5c01ba01a346c76b090abca9ad855b5b0c92c6062ad6d93cdc0d03");
- }
-
- @Test
- void hashPasswordShouldHashWithNullSalt() {
- Assertions.assertThat(JPAUser.hashPassword(RANDOM_PASSWORD, null,
"SHA-512/salted")).isEqualTo("f9cc82d1c04bb2ce0494a51f7a21d07ac60b6f79a8a55397f454603acac29d8589fdfd694d5c01ba01a346c76b090abca9ad855b5b0c92c6062ad6d93cdc0d03");
- }
-
- @Test
- void hashPasswordShouldHashWithSalt() {
- Assertions.assertThat(JPAUser.hashPassword(RANDOM_PASSWORD, "salt",
"SHA-512/salted")).isEqualTo("b7941dcdc380ec414623834919f7d5cbe241a2b6a23be79a61cd9f36178382901b8d83642b743297ac72e5de24e4111885dd05df06e14e47c943c05fdd1ff15a");
- }
-}
\ No newline at end of file
diff --git
a/server/data/data-postgres/src/test/java/org/apache/james/user/jpa/JpaUsersRepositoryTest.java
b/server/data/data-postgres/src/test/java/org/apache/james/user/postgres/PostgresUsersRepositoryTest.java
similarity index 74%
rename from
server/data/data-postgres/src/test/java/org/apache/james/user/jpa/JpaUsersRepositoryTest.java
rename to
server/data/data-postgres/src/test/java/org/apache/james/user/postgres/PostgresUsersRepositoryTest.java
index 55355b0a9d..e83f03bf10 100644
---
a/server/data/data-postgres/src/test/java/org/apache/james/user/jpa/JpaUsersRepositoryTest.java
+++
b/server/data/data-postgres/src/test/java/org/apache/james/user/postgres/PostgresUsersRepositoryTest.java
@@ -16,32 +16,34 @@
* specific language governing permissions and limitations *
* under the License. *
****************************************************************/
-package org.apache.james.user.jpa;
-import java.util.Optional;
+package org.apache.james.user.postgres;
import org.apache.commons.configuration2.BaseHierarchicalConfiguration;
-import org.apache.james.backends.jpa.JpaTestCluster;
+import org.apache.james.backends.postgres.PostgresExtension;
+import
org.apache.james.backends.postgres.utils.SinglePostgresConnectionFactory;
import org.apache.james.core.Username;
import org.apache.james.domainlist.api.DomainList;
import org.apache.james.user.api.UsersRepository;
-import org.apache.james.user.jpa.model.JPAUser;
import org.apache.james.user.lib.UsersRepositoryContract;
-import org.junit.jupiter.api.AfterEach;
+import org.apache.james.user.lib.UsersRepositoryImpl;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.extension.RegisterExtension;
-class JpaUsersRepositoryTest {
+import java.util.Optional;
+
+class PostgresUsersRepositoryTest {
- private static final JpaTestCluster JPA_TEST_CLUSTER =
JpaTestCluster.create(JPAUser.class);
+ @RegisterExtension
+ static PostgresExtension postgresExtension =
PostgresExtension.withoutRowLevelSecurity(PostgresUserModule.MODULE);
@Nested
class WhenEnableVirtualHosting implements
UsersRepositoryContract.WithVirtualHostingContract {
@RegisterExtension
UserRepositoryExtension extension =
UserRepositoryExtension.withVirtualHost();
- private JPAUsersRepository usersRepository;
+ private UsersRepositoryImpl<PostgresUsersDAO> usersRepository;
private TestSystem testSystem;
@BeforeEach
@@ -51,7 +53,7 @@ class JpaUsersRepositoryTest {
}
@Override
- public UsersRepository testee() {
+ public UsersRepositoryImpl<PostgresUsersDAO> testee() {
return usersRepository;
}
@@ -66,7 +68,7 @@ class JpaUsersRepositoryTest {
@RegisterExtension
UserRepositoryExtension extension =
UserRepositoryExtension.withoutVirtualHosting();
- private JPAUsersRepository usersRepository;
+ private UsersRepositoryImpl<PostgresUsersDAO> usersRepository;
private TestSystem testSystem;
@BeforeEach
@@ -76,7 +78,7 @@ class JpaUsersRepositoryTest {
}
@Override
- public UsersRepository testee() {
+ public UsersRepositoryImpl<PostgresUsersDAO> testee() {
return usersRepository;
}
@@ -86,18 +88,15 @@ class JpaUsersRepositoryTest {
}
}
- @AfterEach
- void tearDown() {
- JPA_TEST_CLUSTER.clear("JAMES_USER");
- }
-
- private static JPAUsersRepository getUsersRepository(DomainList
domainList, boolean enableVirtualHosting, Optional<Username> administrator)
throws Exception {
- JPAUsersRepository repos = new JPAUsersRepository(domainList);
-
repos.setEntityManagerFactory(JPA_TEST_CLUSTER.getEntityManagerFactory());
+ private static UsersRepositoryImpl<PostgresUsersDAO>
getUsersRepository(DomainList domainList, boolean enableVirtualHosting,
Optional<Username> administrator) throws Exception {
+ PostgresUsersDAO usersDAO = new PostgresUsersDAO(new
SinglePostgresConnectionFactory(postgresExtension.getConnection().block()),
+ PostgresUsersRepositoryConfiguration.DEFAULT);
BaseHierarchicalConfiguration configuration = new
BaseHierarchicalConfiguration();
configuration.addProperty("enableVirtualHosting",
String.valueOf(enableVirtualHosting));
administrator.ifPresent(username ->
configuration.addProperty("administratorId", username.asString()));
- repos.configure(configuration);
- return repos;
+
+ UsersRepositoryImpl<PostgresUsersDAO> usersRepository = new
PostgresUsersRepository(domainList, usersDAO);
+ usersRepository.configure(configuration);
+ return usersRepository;
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]