CCM NG: OneTimeAuthManager

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@3968 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2016-03-31 18:12:04 +00:00
parent 3eb86b41f2
commit b9397f01b7
16 changed files with 800 additions and 60 deletions

View File

@ -36,9 +36,15 @@ public final class OneTimeAuthConfig {
@Setting @Setting
private int tokenValid = 3600; private int tokenValid = 3600;
/**
* Length of the one time auth token (characters)
*/
@Setting
private int tokenLength = 64;
public static OneTimeAuthConfig getConfig() { public static OneTimeAuthConfig getConfig() {
final ConfigurationManager confManager = CdiUtil.createCdiUtil() final ConfigurationManager confManager = CdiUtil.createCdiUtil()
.findBean(ConfigurationManager.class); .findBean(ConfigurationManager.class);
return confManager.findConfiguration(OneTimeAuthConfig.class); return confManager.findConfiguration(OneTimeAuthConfig.class);
} }
@ -54,10 +60,19 @@ public final class OneTimeAuthConfig {
this.tokenValid = tokenValid; this.tokenValid = tokenValid;
} }
public int getTokenLength() {
return tokenLength;
}
public void setTokenLength(final int tokenLength) {
this.tokenLength = tokenLength;
}
@Override @Override
public int hashCode() { public int hashCode() {
int hash = 7; int hash = 7;
hash = 79 * hash + tokenValid; hash = 79 * hash + tokenValid;
hash = 79 * hash + tokenLength;
return hash; return hash;
} }
@ -73,15 +88,22 @@ public final class OneTimeAuthConfig {
return false; return false;
} }
final OneTimeAuthConfig other = (OneTimeAuthConfig) obj; final OneTimeAuthConfig other = (OneTimeAuthConfig) obj;
return this.tokenValid == other.getTokenValid(); if (tokenValid != other.getTokenValid()) {
return false;
}
return this.tokenLength == other.getTokenLength();
} }
@Override @Override
public String toString() { public String toString() {
return String.format("%s{ " return String.format("%s{ "
+ "tokenValid = %d" + "tokenValid = %d,"
+ " }", + "tokenLength = %d"
tokenValid); + " }",
super.toString(),
tokenValid,
tokenLength);
} }
} }

View File

@ -18,11 +18,18 @@
*/ */
package org.libreccm.security; 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 org.libreccm.configuration.ConfigurationManager;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.inject.Inject; import javax.inject.Inject;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import org.apache.commons.lang.RandomStringUtils;
/** /**
* *
@ -30,32 +37,142 @@ import javax.persistence.EntityManager;
*/ */
@RequestScoped @RequestScoped
public class OneTimeAuthManager { public class OneTimeAuthManager {
@Inject @Inject
private EntityManager entityManager; private EntityManager entityManager;
@Inject @Inject
private ConfigurationManager configurationManager; 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 <em>and</em> 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 <strong>not</strong> 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<OneTimeAuthToken> 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<OneTimeAuthToken> 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<OneTimeAuthToken> 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) { 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) { public void invalidate(final OneTimeAuthToken token) {
throw new UnsupportedOperationException(); if (token == null) {
throw new IllegalArgumentException("Can't invalidate a token null");
}
entityManager.remove(token);
} }
} }

View File

@ -19,7 +19,6 @@
package org.libreccm.security; package org.libreccm.security;
import java.io.Serializable; import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date; import java.util.Date;
import java.util.Objects; import java.util.Objects;
@ -31,17 +30,27 @@ import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType; import javax.persistence.GenerationType;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne; import javax.persistence.OneToOne;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Temporal; import javax.persistence.Temporal;
import javax.persistence.TemporalType; import javax.persistence.TemporalType;
import static org.libreccm.core.CoreConstants.*;
/** /**
* *
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
@Entity @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 { public class OneTimeAuthToken implements Serializable {
private static final long serialVersionUID = -9088185274208292873L; private static final long serialVersionUID = -9088185274208292873L;
@ -58,8 +67,8 @@ public class OneTimeAuthToken implements Serializable {
@Column(name = "TOKEN", length = 255) @Column(name = "TOKEN", length = 255)
private String token; private String token;
@Column(name = "VALID_UNIT") @Column(name = "VALID_UNTIL")
@Temporal(TemporalType.DATE) @Temporal(TemporalType.TIMESTAMP)
private Date validUntil; private Date validUntil;
@Column(name = "PURPOSE") @Column(name = "PURPOSE")
@ -91,7 +100,11 @@ public class OneTimeAuthToken implements Serializable {
} }
public Date getValidUntil() { 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) { public void setValidUntil(final Date validUntil) {
@ -155,10 +168,10 @@ public class OneTimeAuthToken implements Serializable {
public String toString(final String data) { public String toString(final String data) {
return String.format("%s{ " return String.format("%s{ "
+ "tokenId = %d, " + "tokenId = %d, "
+ "user = { %s }, " + "user = { %s }, "
+ "validUnit = %tF %<tT%s" + "validUnit = %tF %<tT%s"
+ " }", + " }",
super.toString(), super.toString(),
tokenId, tokenId,
Objects.toString(user), Objects.toString(user),

View File

@ -1,13 +1,13 @@
create table ONE_TIME_AUTH_TOKENS ( create table CCM_CORE.ONE_TIME_AUTH_TOKENS (
TOKEN_ID bigint not null, TOKEN_ID bigint not null,
PURPOSE varchar(255), PURPOSE varchar(255),
TOKEN varchar(255), TOKEN varchar(255),
VALID_UNIT date, VALID_UNTIL timestamp,
USER_ID bigint, USER_ID bigint,
primary key (TOKEN_ID) primary key (TOKEN_ID)
); );
alter table ONE_TIME_AUTH_TOKENS alter table CCM_CORE.ONE_TIME_AUTH_TOKENS
add constraint FK_fvr3t6w3nsm3u29mjuh4tplno add constraint FK_fvr3t6w3nsm3u29mjuh4tplno
foreign key (USER_ID) foreign key (USER_ID)
references CCM_CORE.USERS; references CCM_CORE.USERS;

View File

@ -1,13 +1,13 @@
create table ONE_TIME_AUTH_TOKENS ( create table CCM_CORE.ONE_TIME_AUTH_TOKENS (
TOKEN_ID int8 not null, TOKEN_ID int8 not null,
PURPOSE varchar(255), PURPOSE varchar(255),
TOKEN varchar(255), TOKEN varchar(255),
VALID_UNIT date, VALID_UNTIL timestamp,
USER_ID int8, USER_ID int8,
primary key (TOKEN_ID) primary key (TOKEN_ID)
); );
alter table ONE_TIME_AUTH_TOKENS alter table CCM_CORE.ONE_TIME_AUTH_TOKENS
add constraint FK_fvr3t6w3nsm3u29mjuh4tplno add constraint FK_fvr3t6w3nsm3u29mjuh4tplno
foreign key (USER_ID) foreign key (USER_ID)
references CCM_CORE.USERS; references CCM_CORE.USERS;

View File

@ -0,0 +1,63 @@
/*
* 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 static org.libreccm.testutils.DatasetType.*;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.libreccm.tests.categories.UnitTest;
import org.libreccm.testutils.DatasetType;
import org.libreccm.testutils.DatasetsVerifier;
import java.util.Arrays;
import java.util.Collection;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RunWith(Parameterized.class)
@Category(UnitTest.class)
public class DatasetsXmlTest extends DatasetsVerifier {
@Parameterized.Parameters(name = "Dataset {0}")
public static Collection<String> 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"};
}
}

View File

@ -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 <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@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<OneTimeAuthToken> 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<OneTimeAuthToken> 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<OneTimeAuthToken> 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<OneTimeAuthToken> 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<OneTimeAuthToken> 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);
}
}

View File

@ -629,11 +629,11 @@ CREATE SCHEMA ccm_core;
primary key (TASK_ID) primary key (TASK_ID)
); );
create table ONE_TIME_AUTH_TOKENS ( create table CCM_CORE.ONE_TIME_AUTH_TOKENS (
TOKEN_ID bigint not null, TOKEN_ID bigint not null,
PURPOSE varchar(255), PURPOSE varchar(255),
TOKEN varchar(255), TOKEN varchar(255),
VALID_UNIT date, VALID_UNTIL timestamp,
USER_ID bigint, USER_ID bigint,
primary key (TOKEN_ID) primary key (TOKEN_ID)
); );
@ -1140,7 +1140,7 @@ CREATE SCHEMA ccm_core;
foreign key (WORKFLOW_ID) foreign key (WORKFLOW_ID)
references CCM_CORE.WORKFLOWS; references CCM_CORE.WORKFLOWS;
alter table ONE_TIME_AUTH_TOKENS alter table CCM_CORE.ONE_TIME_AUTH_TOKENS
add constraint FK_fvr3t6w3nsm3u29mjuh4tplno add constraint FK_fvr3t6w3nsm3u29mjuh4tplno
foreign key (USER_ID) foreign key (USER_ID)
references CCM_CORE.USERS; references CCM_CORE.USERS;

View File

@ -629,11 +629,11 @@ CREATE SCHEMA ccm_core;
primary key (TASK_ID) primary key (TASK_ID)
); );
create table ONE_TIME_AUTH_TOKENS ( create table CCM_CORE.ONE_TIME_AUTH_TOKENS (
TOKEN_ID int8 not null, TOKEN_ID int8 not null,
PURPOSE varchar(255), PURPOSE varchar(255),
TOKEN varchar(255), TOKEN varchar(255),
VALID_UNIT date, VALID_UNTIL timestamp,
USER_ID int8, USER_ID int8,
primary key (TOKEN_ID) primary key (TOKEN_ID)
); );
@ -1140,7 +1140,7 @@ CREATE SCHEMA ccm_core;
foreign key (WORKFLOW_ID) foreign key (WORKFLOW_ID)
references CCM_CORE.WORKFLOWS; references CCM_CORE.WORKFLOWS;
alter table ONE_TIME_AUTH_TOKENS alter table CCM_CORE.ONE_TIME.AUTH_TOKENS
add constraint FK_fvr3t6w3nsm3u29mjuh4tplno add constraint FK_fvr3t6w3nsm3u29mjuh4tplno
foreign key (USER_ID) foreign key (USER_ID)
references CCM_CORE.USERS; references CCM_CORE.USERS;

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<dataset>
<ccm_core.ccm_objects object_id="-1000"
display_name="registry"
uuid="f815d6f8-f915-4399-b16c-2e2dd76f4128"/>
<ccm_core.ccm_objects object_id="-2000"
display_name="registry_root"
uuid="1e5b1732-0a15-49b8-b4a6-8aae1a003147"/>
<ccm_core.categories object_id="-2000"
unique_id="bb93a964-bf66-424c-a22d-074d001db3b8"
name="registry-root"
enabled="true"
visible="true"
abstract_category="false"
category_order="0"/>
<ccm_core.category_domains object_id="-1000"
domain_key="registry"
root_category_id="-2000"
version="1.0"/>
<ccm_core.parties party_id="-10"
name="jdoe"/>
<ccm_core.parties party_id="-20"
name="mmuster"/>
<ccm_core.users party_id="-10"
family_name="Doe"
given_name="John"
email_address="john.doe@example.com"
password="$shiro1$SHA-512$500000$7xkDcZUN0/whJInHIvGsDw==$WhelBVmJU/cLV7lAkMOrE5B/mqCW0bUuid1WX+xBwzzAaekC5bYn9eeOFGJWhiDgmaC50ZCUmM96/iGsRoc4uA=="
bouncing="false"
banned="false"
password_reset_required="false"
verified="true"/>
<ccm_core.users party_id="-20"
family_name="Mustermann"
given_name="Max"
email_address="max.muster@example.org"
password="$shiro1$SHA-512$500000$Y7CnccN1h25sR7KCElMOXg==$CVLWBhetodaEzzhDfGjRcCFZtSW02xOnjH7xhBx0lbxO66grKIt6LWmXoUhLEydce1JZ7cbzNLYOxIwwTeqi5Q=="
bouncing="false"
banned="false"
password_reset_required="false"
verified="true"/>
<ccm_core.one_time_auth_tokens token_id="-100"
user_id="-10"
token="biXOpuxIPXuRgx9jhk1PzZVIeKGaTmg2qTKoTQ4tl9iiweQ0e5mfmdFI1KjDwjPi"
valid_until="2032-04-01 12:00:00"
purpose="EMAIL_VERIFICATION"/>
<ccm_core.one_time_auth_tokens token_id="-200"
user_id="-20"
token="IY2Pbn0TWxtQ53AiDjyGuniysSe5kZxt0gAqUNqfHhz7dgxZYlB88QBHtvEKkbrq"
valid_until="2032-04-01 12:00:00"
purpose="EMAIL_VERIFICATION"/>
</dataset>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<dataset>
<ccm_core.ccm_objects object_id="-1000"
display_name="registry"
uuid="f815d6f8-f915-4399-b16c-2e2dd76f4128"/>
<ccm_core.ccm_objects object_id="-2000"
display_name="registry_root"
uuid="1e5b1732-0a15-49b8-b4a6-8aae1a003147"/>
<ccm_core.categories object_id="-2000"
unique_id="bb93a964-bf66-424c-a22d-074d001db3b8"
name="registry-root"
enabled="true"
visible="true"
abstract_category="false"
category_order="0"/>
<ccm_core.category_domains object_id="-1000"
domain_key="registry"
root_category_id="-2000"
version="1.0"/>
<ccm_core.parties party_id="-10"
name="jdoe"/>
<ccm_core.parties party_id="-20"
name="mmuster"/>
<ccm_core.users party_id="-10"
family_name="Doe"
given_name="John"
email_address="john.doe@example.com"
password="$shiro1$SHA-512$500000$7xkDcZUN0/whJInHIvGsDw==$WhelBVmJU/cLV7lAkMOrE5B/mqCW0bUuid1WX+xBwzzAaekC5bYn9eeOFGJWhiDgmaC50ZCUmM96/iGsRoc4uA=="
bouncing="false"
banned="false"
password_reset_required="false"
verified="true"/>
<ccm_core.users party_id="-20"
family_name="Mustermann"
given_name="Max"
email_address="max.muster@example.org"
password="$shiro1$SHA-512$500000$Y7CnccN1h25sR7KCElMOXg==$CVLWBhetodaEzzhDfGjRcCFZtSW02xOnjH7xhBx0lbxO66grKIt6LWmXoUhLEydce1JZ7cbzNLYOxIwwTeqi5Q=="
bouncing="false"
banned="false"
password_reset_required="false"
verified="true"/>
</dataset>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<dataset>
<ccm_core.ccm_objects object_id="-1000"
display_name="registry"
uuid="f815d6f8-f915-4399-b16c-2e2dd76f4128"/>
<ccm_core.ccm_objects object_id="-2000"
display_name="registry_root"
uuid="1e5b1732-0a15-49b8-b4a6-8aae1a003147"/>
<ccm_core.categories object_id="-2000"
unique_id="bb93a964-bf66-424c-a22d-074d001db3b8"
name="registry-root"
enabled="true"
visible="true"
abstract_category="false"
category_order="0"/>
<ccm_core.category_domains object_id="-1000"
domain_key="registry"
root_category_id="-2000"
version="1.0"/>
<ccm_core.parties party_id="-10"
name="jdoe"/>
<ccm_core.parties party_id="-20"
name="mmuster"/>
<ccm_core.users party_id="-10"
family_name="Doe"
given_name="John"
email_address="john.doe@example.com"
password="$shiro1$SHA-512$500000$7xkDcZUN0/whJInHIvGsDw==$WhelBVmJU/cLV7lAkMOrE5B/mqCW0bUuid1WX+xBwzzAaekC5bYn9eeOFGJWhiDgmaC50ZCUmM96/iGsRoc4uA=="
bouncing="false"
banned="false"
password_reset_required="false"
verified="true"/>
<ccm_core.users party_id="-20"
family_name="Mustermann"
given_name="Max"
email_address="max.muster@example.org"
password="$shiro1$SHA-512$500000$Y7CnccN1h25sR7KCElMOXg==$CVLWBhetodaEzzhDfGjRcCFZtSW02xOnjH7xhBx0lbxO66grKIt6LWmXoUhLEydce1JZ7cbzNLYOxIwwTeqi5Q=="
bouncing="false"
banned="false"
password_reset_required="false"
verified="true"/>
<ccm_core.one_time_auth_tokens token_id="-100"
user_id="-10"
token="biXOpuxIPXuRgx9jhk1PzZVIeKGaTmg2qTKoTQ4tl9iiweQ0e5mfmdFI1KjDwjPi"
valid_until="2032-04-01 12:00:00"
purpose="EMAIL_VERIFICATION"/>
</dataset>

View File

@ -34,6 +34,8 @@ DELETE FROM ccm_core.group_memberships;
DELETE FROM ccm_core.groups; DELETE FROM ccm_core.groups;
DELETE FROM ccm_core.one_time_auth_tokens;
DELETE FROM ccm_core.users; DELETE FROM ccm_core.users;
DELETE FROM ccm_core.user_email_addresses; DELETE FROM ccm_core.user_email_addresses;

View File

@ -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;

View File

@ -34,6 +34,8 @@ DELETE FROM ccm_core.group_memberships;
DELETE FROM ccm_core.groups; DELETE FROM ccm_core.groups;
DELETE FROM ccm_core.one_time_auth_tokens;
DELETE FROM ccm_core.users; DELETE FROM ccm_core.users;
DELETE FROM ccm_core.user_email_addresses; DELETE FROM ccm_core.user_email_addresses;

View File

@ -42,4 +42,6 @@ DELETE FROM ccm_core.parties;
DELETE FROM ccm_core.ccm_roles; DELETE FROM ccm_core.ccm_roles;
DELETE FROM ccm_core.one_time_auth_tokens;
ALTER SEQUENCE hibernate_sequence RESTART WITH 1; ALTER SEQUENCE hibernate_sequence RESTART WITH 1;