diff --git a/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthConfig.java b/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthConfig.java
index 697e5d09b..81f353932 100644
--- a/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthConfig.java
+++ b/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthConfig.java
@@ -36,9 +36,15 @@ public final class OneTimeAuthConfig {
@Setting
private int tokenValid = 3600;
+ /**
+ * Length of the one time auth token (characters)
+ */
+ @Setting
+ private int tokenLength = 64;
+
public static OneTimeAuthConfig getConfig() {
final ConfigurationManager confManager = CdiUtil.createCdiUtil()
- .findBean(ConfigurationManager.class);
+ .findBean(ConfigurationManager.class);
return confManager.findConfiguration(OneTimeAuthConfig.class);
}
@@ -54,10 +60,19 @@ public final class OneTimeAuthConfig {
this.tokenValid = tokenValid;
}
+ public int getTokenLength() {
+ return tokenLength;
+ }
+
+ public void setTokenLength(final int tokenLength) {
+ this.tokenLength = tokenLength;
+ }
+
@Override
public int hashCode() {
int hash = 7;
hash = 79 * hash + tokenValid;
+ hash = 79 * hash + tokenLength;
return hash;
}
@@ -73,15 +88,22 @@ public final class OneTimeAuthConfig {
return false;
}
final OneTimeAuthConfig other = (OneTimeAuthConfig) obj;
- return this.tokenValid == other.getTokenValid();
+ if (tokenValid != other.getTokenValid()) {
+ return false;
+ }
+
+ return this.tokenLength == other.getTokenLength();
}
@Override
public String toString() {
return String.format("%s{ "
- + "tokenValid = %d"
- + " }",
- tokenValid);
+ + "tokenValid = %d,"
+ + "tokenLength = %d"
+ + " }",
+ super.toString(),
+ tokenValid,
+ tokenLength);
}
}
diff --git a/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthManager.java b/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthManager.java
index 6969ba17a..eb22ba951 100644
--- a/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthManager.java
+++ b/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthManager.java
@@ -18,11 +18,18 @@
*/
package org.libreccm.security;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
import org.libreccm.configuration.ConfigurationManager;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+import org.apache.commons.lang.RandomStringUtils;
/**
*
@@ -30,32 +37,142 @@ import javax.persistence.EntityManager;
*/
@RequestScoped
public class OneTimeAuthManager {
-
+
@Inject
private EntityManager entityManager;
-
+
@Inject
private ConfigurationManager configurationManager;
-
- public OneTimeAuthToken createForUser(final User user) {
- throw new UnsupportedOperationException();
+
+ /**
+ * Creates a new one time auth token which for the provided user and the
+ * provided purpose. The length of the token and how long the token is valid
+ * are configured by the {@link OneTimeAuthConfig}.
+ *
+ * This method generates the token and saves it in the database.
+ *
+ * @param user The user for which the one time auth token is generated.
+ * @param purpose The purpose for which the token is generated.
+ *
+ * @return The one time auth token.
+ */
+ public OneTimeAuthToken createForUser(
+ final User user, final OneTimeAuthTokenPurpose purpose) {
+ if (user == null || purpose == null) {
+ throw new IllegalArgumentException(
+ "user and purpose and mandatory for creating a one "
+ + "time auth token.");
+ }
+
+ final OneTimeAuthConfig config = configurationManager.findConfiguration(
+ OneTimeAuthConfig.class);
+
+ final OneTimeAuthToken token = new OneTimeAuthToken();
+ token.setUser(user);
+ token.setPurpose(purpose);
+
+ final String tokenStr = RandomStringUtils.randomAscii(config.
+ getTokenLength());
+ token.setToken(tokenStr);
+
+ final LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
+ final LocalDateTime valid = now.plusSeconds(config.getTokenValid());
+ final Date validUntil = Date.from(valid.toInstant(ZoneOffset.UTC));
+
+ token.setValidUntil(validUntil);
+
+ entityManager.persist(token);
+
+ return token;
}
-
- public OneTimeAuthToken retrieveForUser(final User user) {
- throw new UnsupportedOperationException();
+
+ /**
+ * Retrieves the one time auth token for the provided user and purpose. This
+ * method does not not check of the token is still valid!
+ *
+ * @param user The user for which the token is retrieved.
+ * @param purpose The purpose of the token to retrieve.
+ *
+ * @return The one time auth token for the provided user and purpose or
+ * {@code null} if there is no such token.
+ */
+ public Optional retrieveForUser(
+ final User user, final OneTimeAuthTokenPurpose purpose) {
+ if (user == null || purpose == null) {
+ throw new IllegalArgumentException(
+ "user and purpose and mandatory for retrieving a one "
+ + "time auth token.");
+ }
+
+ final TypedQuery query = entityManager.createNamedQuery(
+ "OneTimeAuthToken.findByUserAndPurpose", OneTimeAuthToken.class);
+ query.setParameter("user", user);
+ query.setParameter("purpose", purpose);
+
+ final List queryResult = query.getResultList();
+ if (queryResult.isEmpty()) {
+ return Optional.empty();
+ } else {
+ return Optional.of(queryResult.get(0));
+ }
}
-
- public boolean validTokenExistsForUser(final User user) {
- throw new UnsupportedOperationException();
+
+ /**
+ * Checks of there is a valid one time auth token for the provided user and
+ * purpose.
+ *
+ * @param user The user.
+ * @param purpose The purpose of the token.
+ *
+ * @return {@code true} if there is a valid token for the provided user and
+ * purpose, {@code false} if not.
+ */
+ public boolean validTokenExistsForUser(
+ final User user, final OneTimeAuthTokenPurpose purpose) {
+ if (user == null || purpose == null) {
+ throw new IllegalArgumentException(
+ "user and purpose and mandatory for validiting a one time "
+ + "auth token.");
+ }
+
+ final Optional token = retrieveForUser(user, purpose);
+ if (token.isPresent()) {
+ return isValid(token.get());
+ } else {
+ return false;
+ }
}
-
+
+ /**
+ * Validates a {@link OneTimeAuthToken}.
+ *
+ * @param token The token to valid.
+ *
+ * @return {@code true} if the token is valid, {@code false} if not.
+ */
public boolean isValid(final OneTimeAuthToken token) {
- throw new UnsupportedOperationException();
+ if (token == null) {
+ throw new IllegalArgumentException("Can't validate a token null");
+ }
+
+ final LocalDateTime validUntil = LocalDateTime.
+ ofInstant(token.getValidUntil().toInstant(),
+ ZoneOffset.UTC);
+ final LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
+ return validUntil.isAfter(now);
}
-
+
+ /**
+ * Invalides (deletes) a {@link OneTimeAuthToken}.
+ *
+ * @param token The token to invalidate.
+ */
public void invalidate(final OneTimeAuthToken token) {
- throw new UnsupportedOperationException();
+ if (token == null) {
+ throw new IllegalArgumentException("Can't invalidate a token null");
+ }
+
+ entityManager.remove(token);
}
-
-
+
}
diff --git a/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthToken.java b/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthToken.java
index e1267be53..e0e2e8528 100644
--- a/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthToken.java
+++ b/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthToken.java
@@ -19,7 +19,6 @@
package org.libreccm.security;
import java.io.Serializable;
-import java.time.LocalDateTime;
import java.util.Date;
import java.util.Objects;
@@ -31,17 +30,27 @@ import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
+import static org.libreccm.core.CoreConstants.*;
+
/**
*
* @author Jens Pelzetter
*/
@Entity
-@Table(name = "ONE_TIME_AUTH_TOKENS")
+@Table(name = "ONE_TIME_AUTH_TOKENS", schema = DB_SCHEMA)
+@NamedQueries({
+ @NamedQuery(
+ name = "OneTimeAuthToken.findByUserAndPurpose",
+ query = "SELECT t FROM OneTimeAuthToken t "
+ + "WHERE t.user = :user AND t.purpose = :purpose "
+ + "ORDER BY t.validUntil")})
public class OneTimeAuthToken implements Serializable {
private static final long serialVersionUID = -9088185274208292873L;
@@ -58,8 +67,8 @@ public class OneTimeAuthToken implements Serializable {
@Column(name = "TOKEN", length = 255)
private String token;
- @Column(name = "VALID_UNIT")
- @Temporal(TemporalType.DATE)
+ @Column(name = "VALID_UNTIL")
+ @Temporal(TemporalType.TIMESTAMP)
private Date validUntil;
@Column(name = "PURPOSE")
@@ -91,7 +100,11 @@ public class OneTimeAuthToken implements Serializable {
}
public Date getValidUntil() {
- return new Date(validUntil.getTime());
+ if (validUntil == null) {
+ return null;
+ } else {
+ return new Date(validUntil.getTime());
+ }
}
public void setValidUntil(final Date validUntil) {
@@ -155,10 +168,10 @@ public class OneTimeAuthToken implements Serializable {
public String toString(final String data) {
return String.format("%s{ "
- + "tokenId = %d, "
- + "user = { %s }, "
- + "validUnit = %tF %Jens Pelzetter
+ */
+@RunWith(Parameterized.class)
+@Category(UnitTest.class)
+public class DatasetsXmlTest extends DatasetsVerifier {
+
+ @Parameterized.Parameters(name = "Dataset {0}")
+ public static Collection data() {
+ return Arrays.asList(new String[]{
+ "/datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml",
+ "/datasets/org/libreccm/security/OneTimeAuthManagerTest/after-create.xml",
+ "/datasets/org/libreccm/security/OneTimeAuthManagerTest/after-invalidate.xml",});
+ }
+
+ public DatasetsXmlTest(final String datasetPath) {
+ super(datasetPath);
+ }
+
+ @Override
+ public DatasetType getDatasetType() {
+ return FLAT_XML;
+ }
+
+ @Override
+ public String[] getSchemas() {
+ return new String[]{"ccm_core"};
+ }
+
+}
diff --git a/ccm-core/src/test/java/org/libreccm/security/OneTimeAuthManagerTest.java b/ccm-core/src/test/java/org/libreccm/security/OneTimeAuthManagerTest.java
new file mode 100644
index 000000000..cc3622d0f
--- /dev/null
+++ b/ccm-core/src/test/java/org/libreccm/security/OneTimeAuthManagerTest.java
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2016 LibreCCM Foundation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+package org.libreccm.security;
+
+import java.io.File;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.time.temporal.ChronoUnit;
+import java.util.Date;
+import java.util.Optional;
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.ShouldThrowException;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.junit.InSequence;
+import org.jboss.arquillian.persistence.CreateSchema;
+import org.jboss.arquillian.persistence.PersistenceTest;
+import org.jboss.arquillian.persistence.ShouldMatchDataSet;
+import org.jboss.arquillian.persistence.UsingDataSet;
+import org.jboss.arquillian.transaction.api.annotation.TransactionMode;
+import org.jboss.arquillian.transaction.api.annotation.Transactional;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.resolver.api.maven.Maven;
+import org.jboss.shrinkwrap.resolver.api.maven.PomEquippedResolveStage;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.libreccm.categorization.Categorization;
+import org.libreccm.core.CcmObject;
+import org.libreccm.jpa.EntityManagerProducer;
+import org.libreccm.jpa.utils.MimeTypeConverter;
+import org.libreccm.l10n.LocalizedString;
+import org.libreccm.tests.categories.IntegrationTest;
+import org.libreccm.testutils.EqualsVerifier;
+import org.libreccm.web.CcmApplication;
+import org.libreccm.workflow.Workflow;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@Category(IntegrationTest.class)
+@RunWith(Arquillian.class)
+@PersistenceTest
+@Transactional(TransactionMode.COMMIT)
+@CreateSchema("create_ccm_core_schema.sql")
+public class OneTimeAuthManagerTest {
+
+ @Inject
+ private OneTimeAuthManager oneTimeAuthManager;
+
+ @Inject
+ private UserRepository userRepository;
+
+ @Inject
+ private EntityManager entityManager;
+
+ public OneTimeAuthManagerTest() {
+
+ }
+
+ @BeforeClass
+ public static void setUpClass() {
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ }
+
+ @Before
+ public void setUp() {
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ @Deployment
+ public static WebArchive createDeployment() {
+ final PomEquippedResolveStage pom = Maven
+ .resolver()
+ .loadPomFromFile("pom.xml");
+ final PomEquippedResolveStage dependencies = pom.
+ importCompileAndRuntimeDependencies();
+ final File[] libs = dependencies.resolve().withTransitivity().asFile();
+
+ for (File lib : libs) {
+ System.err.printf("Adding file '%s' to test archive...%n",
+ lib.getName());
+ }
+
+ return ShrinkWrap
+ .create(WebArchive.class,
+ "LibreCCM-org.libreccm.security.OneTimeAuthManagerTest.war")
+ .addPackage(org.libreccm.security.OneTimeAuthManager.class.
+ getPackage())
+ .addPackage(org.libreccm.core.CcmObject.class.getPackage())
+ .addPackage(org.libreccm.categorization.Categorization.class.
+ getPackage())
+ .addPackage(
+ org.libreccm.configuration.ConfigurationManager.class.
+ getPackage())
+ .addPackage(org.libreccm.l10n.LocalizedString.class.getPackage()).
+ addPackage(org.libreccm.web.CcmApplication.class.getPackage())
+ .addPackage(org.libreccm.workflow.Workflow.class.getPackage())
+ .addPackage(org.libreccm.jpa.EntityManagerProducer.class.
+ getPackage())
+ .addPackage(org.libreccm.jpa.utils.MimeTypeConverter.class.
+ getPackage())
+ .addPackage(org.libreccm.testutils.EqualsVerifier.class.
+ getPackage())
+ .addPackage(org.libreccm.tests.categories.IntegrationTest.class.
+ getPackage())
+ .addAsLibraries(libs)
+ .addAsResource("test-persistence.xml",
+ "META-INF/persistence.xml")
+ .addAsWebInfResource("test-web.xml", "WEB-INF/web.xml")
+ .addAsWebInfResource(EmptyAsset.INSTANCE, "WEB-INF/beans.xml");
+ }
+
+ @Test
+ @InSequence(10)
+ public void isManagerInjected() {
+ assertThat(oneTimeAuthManager, is(not(nullValue())));
+ }
+
+ @Test
+ @UsingDataSet(
+ "datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml")
+ @ShouldMatchDataSet(
+ value = "datasets/org/libreccm/security/OneTimeAuthManagerTest/"
+ + "after-create.xml",
+ excludeColumns = {"token_id", "token", "valid_until"})
+ @InSequence(100)
+ public void createTokenForUser() {
+ final User mmuster = userRepository.findByName("mmuster");
+ final OneTimeAuthToken token = oneTimeAuthManager.createForUser(
+ mmuster,
+ OneTimeAuthTokenPurpose.EMAIL_VERIFICATION);
+
+ final LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
+ final LocalDateTime tokenValidUntil = LocalDateTime.ofInstant(
+ token.getValidUntil().toInstant(), ZoneOffset.UTC);
+
+ assertThat(String.format(
+ "tokenValidUntil = \"%s\" is not after now = \"%s\"",
+ tokenValidUntil.toString(),
+ now.toString()),
+ tokenValidUntil.isAfter(now),
+ is(true));
+
+ final long diff = now.until(tokenValidUntil, ChronoUnit.SECONDS);
+ assertThat(diff, is(greaterThan(3590L)));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ @UsingDataSet(
+ "datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml")
+ @ShouldThrowException(IllegalArgumentException.class)
+ @InSequence(200)
+ public void createTokenNullUser() {
+ oneTimeAuthManager.createForUser(
+ null, OneTimeAuthTokenPurpose.RECOVER_PASSWORD);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ @UsingDataSet(
+ "datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml")
+ @ShouldThrowException(IllegalArgumentException.class)
+ @InSequence(300)
+ public void createTokenNullPurpose() {
+ final User user = new User();
+ oneTimeAuthManager.createForUser(user, null);
+ }
+
+ @Test
+ @UsingDataSet(
+ "datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml")
+ @InSequence(400)
+ public void retrieveTokenForUser() {
+ final User jdoe = userRepository.findByName("jdoe");
+
+ final Optional result = oneTimeAuthManager.
+ retrieveForUser(
+ jdoe, OneTimeAuthTokenPurpose.EMAIL_VERIFICATION);
+
+ assertThat(result.isPresent(), is(true));
+
+ final OneTimeAuthToken token = result.get();
+ assertThat(token.getUser(), is(not(nullValue())));
+ assertThat(token.getUser().getName(), is(equalTo("jdoe")));
+ assertThat(token.getToken(), is(equalTo(
+ "biXOpuxIPXuRgx9jhk1PzZVIeKGaTmg2qTKoTQ4tl9iiweQ0e5mfmdFI1KjDwjPi")));
+ }
+
+ @Test
+ @UsingDataSet(
+ "datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml")
+ @InSequence(500)
+ public void retrieveNotExistingTokenForUser() {
+ final User mmuster = userRepository.findByName("mmuster");
+
+ final Optional result = oneTimeAuthManager.
+ retrieveForUser(
+ mmuster, OneTimeAuthTokenPurpose.EMAIL_VERIFICATION);
+
+ assertThat(result.isPresent(), is(false));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ @UsingDataSet(
+ "datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml")
+ @ShouldThrowException(IllegalArgumentException.class)
+ @InSequence(600)
+ public void retrieveTokenNullUser() {
+ oneTimeAuthManager.retrieveForUser(
+ null, OneTimeAuthTokenPurpose.RECOVER_PASSWORD);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ @UsingDataSet(
+ "datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml")
+ @ShouldThrowException(IllegalArgumentException.class)
+ @InSequence(700)
+ public void retrieveTokenNullPurpose() {
+ final User mmuster = userRepository.findByName("mmuster");
+
+ oneTimeAuthManager.retrieveForUser(mmuster, null);
+ }
+
+ @Test
+ @UsingDataSet(
+ "datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml")
+ @InSequence(800)
+ public void validTokenExistsForUser() {
+ final User user = userRepository.findByName("jdoe");
+
+ assertThat(
+ oneTimeAuthManager.validTokenExistsForUser(
+ user, OneTimeAuthTokenPurpose.EMAIL_VERIFICATION),
+ is(true));
+ }
+
+ @Test
+ @UsingDataSet(
+ "datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml")
+ @InSequence(900)
+ public void validTokenDoesNotExist() {
+ final User user = userRepository.findByName("mmuster");
+
+ assertThat(
+ oneTimeAuthManager.validTokenExistsForUser(
+ user, OneTimeAuthTokenPurpose.EMAIL_VERIFICATION),
+ is(false));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ @UsingDataSet(
+ "datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml")
+ @ShouldThrowException(IllegalArgumentException.class)
+ @InSequence(1000)
+ public void validTokenNullUser() {
+ oneTimeAuthManager.validTokenExistsForUser(
+ null, OneTimeAuthTokenPurpose.EMAIL_VERIFICATION);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ @UsingDataSet(
+ "datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml")
+ @ShouldThrowException(IllegalArgumentException.class)
+ @InSequence(1100)
+ public void validTokenNullPurpose() {
+ final User user = userRepository.findByName("mmuster");
+ oneTimeAuthManager.validTokenExistsForUser(
+ user, null);
+ }
+
+ @Test
+ @UsingDataSet(
+ "datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml")
+ @InSequence(1200)
+ public void isValid() {
+ final User jdoe = userRepository.findByName("jdoe");
+
+ final Optional result = oneTimeAuthManager.
+ retrieveForUser(
+ jdoe, OneTimeAuthTokenPurpose.EMAIL_VERIFICATION);
+
+ assertThat(result.isPresent(), is(true));
+ assertThat(oneTimeAuthManager.isValid(result.get()), is(true));
+ }
+
+ @Test
+ @UsingDataSet(
+ "datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml")
+ @InSequence(1300)
+ public void isInvalid() {
+ final User jdoe = userRepository.findByName("jdoe");
+
+ final Optional result = oneTimeAuthManager.
+ retrieveForUser(
+ jdoe, OneTimeAuthTokenPurpose.EMAIL_VERIFICATION);
+
+ assertThat(result.isPresent(), is(true));
+ final OneTimeAuthToken token = result.get();
+
+ final LocalDateTime date = LocalDateTime
+ .now(ZoneOffset.UTC).minus(1800, ChronoUnit.SECONDS);
+ token.setValidUntil(Date.from(date.toInstant(ZoneOffset.UTC)));
+
+ assertThat(oneTimeAuthManager.isValid(token), is(false));
+
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ @UsingDataSet(
+ "datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml")
+ @ShouldThrowException(IllegalArgumentException.class)
+ @InSequence(1400)
+ public void isValidNullToken() {
+ oneTimeAuthManager.isValid(null);
+ }
+
+ @Test
+ @UsingDataSet(
+ "datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml")
+ @ShouldMatchDataSet(
+ value = "datasets/org/libreccm/security/OneTimeAuthManagerTest/"
+ + "after-invalidate.xml")
+ @InSequence(1500)
+ public void invalidateToken() {
+ final User jdoe = userRepository.findByName("jdoe");
+
+ final Optional result = oneTimeAuthManager.
+ retrieveForUser(
+ jdoe, OneTimeAuthTokenPurpose.EMAIL_VERIFICATION);
+
+ assertThat(result.isPresent(), is(true));
+ oneTimeAuthManager.invalidate(result.get());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ @UsingDataSet(
+ "datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml")
+ @ShouldThrowException(IllegalArgumentException.class)
+ @InSequence(1400)
+ public void invalidateNullToken() {
+ oneTimeAuthManager.invalidate(null);
+ }
+
+}
diff --git a/ccm-core/src/test/resources-wildfly8-remote-h2-mem/scripts/create_ccm_core_schema.sql b/ccm-core/src/test/resources-wildfly8-remote-h2-mem/scripts/create_ccm_core_schema.sql
index 95ef56c77..d126c7ae8 100644
--- a/ccm-core/src/test/resources-wildfly8-remote-h2-mem/scripts/create_ccm_core_schema.sql
+++ b/ccm-core/src/test/resources-wildfly8-remote-h2-mem/scripts/create_ccm_core_schema.sql
@@ -629,11 +629,11 @@ CREATE SCHEMA ccm_core;
primary key (TASK_ID)
);
- create table ONE_TIME_AUTH_TOKENS (
+ create table CCM_CORE.ONE_TIME_AUTH_TOKENS (
TOKEN_ID bigint not null,
PURPOSE varchar(255),
TOKEN varchar(255),
- VALID_UNIT date,
+ VALID_UNTIL timestamp,
USER_ID bigint,
primary key (TOKEN_ID)
);
@@ -1140,7 +1140,7 @@ CREATE SCHEMA ccm_core;
foreign key (WORKFLOW_ID)
references CCM_CORE.WORKFLOWS;
- alter table ONE_TIME_AUTH_TOKENS
+ alter table CCM_CORE.ONE_TIME_AUTH_TOKENS
add constraint FK_fvr3t6w3nsm3u29mjuh4tplno
foreign key (USER_ID)
references CCM_CORE.USERS;
diff --git a/ccm-core/src/test/resources-wildfly8-remote-pgsql/scripts/create_ccm_core_schema.sql b/ccm-core/src/test/resources-wildfly8-remote-pgsql/scripts/create_ccm_core_schema.sql
index acca5129c..3b3fd5008 100644
--- a/ccm-core/src/test/resources-wildfly8-remote-pgsql/scripts/create_ccm_core_schema.sql
+++ b/ccm-core/src/test/resources-wildfly8-remote-pgsql/scripts/create_ccm_core_schema.sql
@@ -629,11 +629,11 @@ CREATE SCHEMA ccm_core;
primary key (TASK_ID)
);
- create table ONE_TIME_AUTH_TOKENS (
+ create table CCM_CORE.ONE_TIME_AUTH_TOKENS (
TOKEN_ID int8 not null,
PURPOSE varchar(255),
TOKEN varchar(255),
- VALID_UNIT date,
+ VALID_UNTIL timestamp,
USER_ID int8,
primary key (TOKEN_ID)
);
@@ -1140,7 +1140,7 @@ CREATE SCHEMA ccm_core;
foreign key (WORKFLOW_ID)
references CCM_CORE.WORKFLOWS;
- alter table ONE_TIME_AUTH_TOKENS
+ alter table CCM_CORE.ONE_TIME.AUTH_TOKENS
add constraint FK_fvr3t6w3nsm3u29mjuh4tplno
foreign key (USER_ID)
references CCM_CORE.USERS;
diff --git a/ccm-core/src/test/resources/datasets/org/libreccm/security/OneTimeAuthManagerTest/after-create.xml b/ccm-core/src/test/resources/datasets/org/libreccm/security/OneTimeAuthManagerTest/after-create.xml
new file mode 100644
index 000000000..5a518ba00
--- /dev/null
+++ b/ccm-core/src/test/resources/datasets/org/libreccm/security/OneTimeAuthManagerTest/after-create.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ccm-core/src/test/resources/datasets/org/libreccm/security/OneTimeAuthManagerTest/after-invalidate.xml b/ccm-core/src/test/resources/datasets/org/libreccm/security/OneTimeAuthManagerTest/after-invalidate.xml
new file mode 100644
index 000000000..022e78c88
--- /dev/null
+++ b/ccm-core/src/test/resources/datasets/org/libreccm/security/OneTimeAuthManagerTest/after-invalidate.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ccm-core/src/test/resources/datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml b/ccm-core/src/test/resources/datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml
new file mode 100644
index 000000000..2987c8027
--- /dev/null
+++ b/ccm-core/src/test/resources/datasets/org/libreccm/security/OneTimeAuthManagerTest/data.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ccm-core/src/test/resources/scripts/h2-cleanup.sql b/ccm-core/src/test/resources/scripts/h2-cleanup.sql
index 4a9045c62..abf9ddbcf 100644
--- a/ccm-core/src/test/resources/scripts/h2-cleanup.sql
+++ b/ccm-core/src/test/resources/scripts/h2-cleanup.sql
@@ -34,6 +34,8 @@ DELETE FROM ccm_core.group_memberships;
DELETE FROM ccm_core.groups;
+DELETE FROM ccm_core.one_time_auth_tokens;
+
DELETE FROM ccm_core.users;
DELETE FROM ccm_core.user_email_addresses;
diff --git a/ccm-core/src/test/resources/scripts/mysql-cleanup.sql b/ccm-core/src/test/resources/scripts/mysql-cleanup.sql
deleted file mode 100644
index 04e4086bb..000000000
--- a/ccm-core/src/test/resources/scripts/mysql-cleanup.sql
+++ /dev/null
@@ -1,17 +0,0 @@
-DELETE FROM ccm_core.permissions;
-
-DELETE FROM ccm_core.ccm_privileges;
-
-DELETE FROM ccm_core.ccm_objects;
-
-DELETE FROM ccm_core.ccm_roles;
-
-DELETE FROM ccm_core.group_memberships;
-
-DELETE FROM ccm_core.ccm_groups;
-
-DELETE FROM ccm_core.user_email_addresses;
-
-DELETE FROM ccm_core.ccm_users;
-
-DELETE FROM ccm_core.subjects;
\ No newline at end of file
diff --git a/ccm-core/src/test/resources/scripts/pgsql-cleanup.sql b/ccm-core/src/test/resources/scripts/pgsql-cleanup.sql
index 31b2125db..fbc42db36 100644
--- a/ccm-core/src/test/resources/scripts/pgsql-cleanup.sql
+++ b/ccm-core/src/test/resources/scripts/pgsql-cleanup.sql
@@ -34,6 +34,8 @@ DELETE FROM ccm_core.group_memberships;
DELETE FROM ccm_core.groups;
+DELETE FROM ccm_core.one_time_auth_tokens;
+
DELETE FROM ccm_core.users;
DELETE FROM ccm_core.user_email_addresses;
diff --git a/ccm-docrepo/src/test/resources/scripts/h2-cleanup.sql b/ccm-docrepo/src/test/resources/scripts/h2-cleanup.sql
index 4a9045c62..d618630d0 100644
--- a/ccm-docrepo/src/test/resources/scripts/h2-cleanup.sql
+++ b/ccm-docrepo/src/test/resources/scripts/h2-cleanup.sql
@@ -42,4 +42,6 @@ DELETE FROM ccm_core.parties;
DELETE FROM ccm_core.ccm_roles;
+DELETE FROM ccm_core.one_time_auth_tokens;
+
ALTER SEQUENCE hibernate_sequence RESTART WITH 1;
\ No newline at end of file