diff --git a/ccm-core/pom.xml b/ccm-core/pom.xml
index 219629e18..a59792f32 100644
--- a/ccm-core/pom.xml
+++ b/ccm-core/pom.xml
@@ -330,6 +330,7 @@
org.libreccm.web
org.libreccm.workflow
+ ${basedir}/src/main/resources/META-INF/persistence-ddl.xml
true
@@ -656,6 +657,7 @@
org.libreccm
true
+ ${basedir}/src/main/resources/META-INF/persistence-ddl.xml
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/login/LoginServlet.java b/ccm-core/src/main/java/com/arsdigita/ui/login/LoginServlet.java
index 4723a9755..354b369c6 100644
--- a/ccm-core/src/main/java/com/arsdigita/ui/login/LoginServlet.java
+++ b/ccm-core/src/main/java/com/arsdigita/ui/login/LoginServlet.java
@@ -98,6 +98,8 @@ public class LoginServlet extends BebopApplicationServlet {
public static final String RECOVER_USER_PASSWORD_PATH_INFO
= "/recover-password/";
+ public static final String VERIFY_EMAIL = "/verify-email/";
+
/**
* PathInfo into the Login application to access the (optional) newUser
* page. Ends with "/" because it is a servlet/directory
diff --git a/ccm-core/src/main/java/org/libreccm/security/ChallengeManager.java b/ccm-core/src/main/java/org/libreccm/security/ChallengeManager.java
new file mode 100644
index 000000000..ed5c121bc
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/security/ChallengeManager.java
@@ -0,0 +1,70 @@
+/*
+ * 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 javax.enterprise.context.RequestScoped;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+public class ChallengeManager {
+
+ public String createEmailVerification(final User user) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void sendEmailVerification(final User user) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void finishEmailVerification(final User user,
+ final String submittedToken) {
+ throw new UnsupportedOperationException();
+ }
+
+ public String createEmailActivation(final User user) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void sendUserActivation(final User user) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void finishUserActivation(final User user,
+ final String submittedToken) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void sendPasswordRecover(final User user) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void sendPasswordRevover(final User user) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void finishPasswordRecover(final User user,
+ final String submittedToken,
+ final String newPassword) {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthConfig.java b/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthConfig.java
new file mode 100644
index 000000000..697e5d09b
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthConfig.java
@@ -0,0 +1,87 @@
+/*
+ * 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 org.libreccm.cdi.utils.CdiUtil;
+import org.libreccm.configuration.Configuration;
+import org.libreccm.configuration.ConfigurationManager;
+import org.libreccm.configuration.Setting;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@Configuration
+public final class OneTimeAuthConfig {
+
+ /**
+ * How long is a OneTimeAuthToken valid (in seconds)?
+ */
+ @Setting
+ private int tokenValid = 3600;
+
+ public static OneTimeAuthConfig getConfig() {
+ final ConfigurationManager confManager = CdiUtil.createCdiUtil()
+ .findBean(ConfigurationManager.class);
+ return confManager.findConfiguration(OneTimeAuthConfig.class);
+ }
+
+ public OneTimeAuthConfig() {
+ super();
+ }
+
+ public int getTokenValid() {
+ return tokenValid;
+ }
+
+ public void setTokenValid(final int tokenValid) {
+ this.tokenValid = tokenValid;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 79 * hash + tokenValid;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OneTimeAuthConfig)) {
+ return false;
+ }
+ final OneTimeAuthConfig other = (OneTimeAuthConfig) obj;
+ return this.tokenValid == other.getTokenValid();
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s{ "
+ + "tokenValid = %d"
+ + " }",
+ tokenValid);
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthManager.java b/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthManager.java
new file mode 100644
index 000000000..6969ba17a
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthManager.java
@@ -0,0 +1,61 @@
+/*
+ * 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 org.libreccm.configuration.ConfigurationManager;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+public class OneTimeAuthManager {
+
+ @Inject
+ private EntityManager entityManager;
+
+ @Inject
+ private ConfigurationManager configurationManager;
+
+ public OneTimeAuthToken createForUser(final User user) {
+ throw new UnsupportedOperationException();
+ }
+
+ public OneTimeAuthToken retrieveForUser(final User user) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean validTokenExistsForUser(final User user) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isValid(final OneTimeAuthToken token) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void invalidate(final OneTimeAuthToken token) {
+ throw new UnsupportedOperationException();
+ }
+
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthToken.java b/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthToken.java
new file mode 100644
index 000000000..e1267be53
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthToken.java
@@ -0,0 +1,169 @@
+/*
+ * 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.Serializable;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.Objects;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@Entity
+@Table(name = "ONE_TIME_AUTH_TOKENS")
+public class OneTimeAuthToken implements Serializable {
+
+ private static final long serialVersionUID = -9088185274208292873L;
+
+ @Id
+ @Column(name = "TOKEN_ID")
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long tokenId;
+
+ @OneToOne
+ @JoinColumn(name = "USER_ID")
+ private User user;
+
+ @Column(name = "TOKEN", length = 255)
+ private String token;
+
+ @Column(name = "VALID_UNIT")
+ @Temporal(TemporalType.DATE)
+ private Date validUntil;
+
+ @Column(name = "PURPOSE")
+ @Enumerated(EnumType.STRING)
+ private OneTimeAuthTokenPurpose purpose;
+
+ public long getTokenId() {
+ return tokenId;
+ }
+
+ protected void setTokenId(final long tokenId) {
+ this.tokenId = tokenId;
+ }
+
+ public User getUser() {
+ return user;
+ }
+
+ public void setUser(final User user) {
+ this.user = user;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(final String token) {
+ this.token = token;
+ }
+
+ public Date getValidUntil() {
+ return new Date(validUntil.getTime());
+ }
+
+ public void setValidUntil(final Date validUntil) {
+ this.validUntil = new Date(validUntil.getTime());
+ }
+
+ public OneTimeAuthTokenPurpose getPurpose() {
+ return purpose;
+ }
+
+ public void setPurpose(final OneTimeAuthTokenPurpose purpose) {
+ this.purpose = purpose;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 97 * hash + Objects.hashCode(user);
+ hash = 97 * hash + Objects.hashCode(token);
+ hash = 97 * hash + Objects.hashCode(validUntil);
+ hash = 97 * hash + Objects.hashCode(purpose);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OneTimeAuthToken)) {
+ return false;
+ }
+ final OneTimeAuthToken other = (OneTimeAuthToken) obj;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+
+ if (!Objects.equals(token, other.getToken())) {
+ return false;
+ }
+ if (!Objects.equals(user, other.getUser())) {
+ return false;
+ }
+ if (!Objects.equals(validUntil, other.getValidUntil())) {
+ return false;
+ }
+ return purpose == other.getPurpose();
+ }
+
+ public boolean canEqual(final Object obj) {
+ return obj instanceof OneTimeAuthToken;
+ }
+
+ @Override
+ public final String toString() {
+ return toString("");
+ }
+
+ public String toString(final String data) {
+ return String.format("%s{ "
+ + "tokenId = %d, "
+ + "user = { %s }, "
+ + "validUnit = %tF %Jens Pelzetter
+ */
+public enum OneTimeAuthTokenPurpose {
+
+ ACCOUNT_ACTIVATION,
+ EMAIL_VERIFICATION,
+ RECOVER_PASSWORD
+
+
+}
diff --git a/ccm-core/src/main/resources/META-INF/persistence-ddl.xml b/ccm-core/src/main/resources/META-INF/persistence-ddl.xml
new file mode 100644
index 000000000..a98d422e3
--- /dev/null
+++ b/ccm-core/src/main/resources/META-INF/persistence-ddl.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+ org.hibernate.jpa.HibernatePersistenceProvider
+
+ java:/comp/env/jdbc/libreccm/db
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/h2/V7_0_0_1__create_one_time_auth_tokens.sql b/ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/h2/V7_0_0_1__create_one_time_auth_tokens.sql
new file mode 100644
index 000000000..196943f4f
--- /dev/null
+++ b/ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/h2/V7_0_0_1__create_one_time_auth_tokens.sql
@@ -0,0 +1,13 @@
+create table ONE_TIME_AUTH_TOKENS (
+ TOKEN_ID bigint not null,
+ PURPOSE varchar(255),
+ TOKEN varchar(255),
+ VALID_UNIT date,
+ USER_ID bigint,
+ primary key (TOKEN_ID)
+ );
+
+alter table ONE_TIME_AUTH_TOKENS
+ add constraint FK_fvr3t6w3nsm3u29mjuh4tplno
+ foreign key (USER_ID)
+ references CCM_CORE.USERS;
\ No newline at end of file
diff --git a/ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/pgsql/V7_0_0_1__create_one_time_auth_tokens.sql b/ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/pgsql/V7_0_0_1__create_one_time_auth_tokens.sql
new file mode 100644
index 000000000..fbcd26118
--- /dev/null
+++ b/ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/pgsql/V7_0_0_1__create_one_time_auth_tokens.sql
@@ -0,0 +1,13 @@
+ create table ONE_TIME_AUTH_TOKENS (
+ TOKEN_ID int8 not null,
+ PURPOSE varchar(255),
+ TOKEN varchar(255),
+ VALID_UNIT date,
+ USER_ID int8,
+ primary key (TOKEN_ID)
+ );
+
+ alter table ONE_TIME_AUTH_TOKENS
+ add constraint FK_fvr3t6w3nsm3u29mjuh4tplno
+ foreign key (USER_ID)
+ references CCM_CORE.USERS;
\ No newline at end of file
diff --git a/ccm-core/src/test/java/org/libreccm/security/EqualsAndHashCodeTest.java b/ccm-core/src/test/java/org/libreccm/security/EqualsAndHashCodeTest.java
index 96b988f7e..5256c8e42 100644
--- a/ccm-core/src/test/java/org/libreccm/security/EqualsAndHashCodeTest.java
+++ b/ccm-core/src/test/java/org/libreccm/security/EqualsAndHashCodeTest.java
@@ -42,6 +42,7 @@ public class EqualsAndHashCodeTest extends EqualsVerifier {
GroupMembership.class,
Party.class,
Permission.class,
+ OneTimeAuthToken.class,
Role.class,
RoleMembership.class,
User.class
diff --git a/ccm-core/src/test/java/org/libreccm/security/ToStringTest.java b/ccm-core/src/test/java/org/libreccm/security/ToStringTest.java
index b5e057af0..1055edd78 100644
--- a/ccm-core/src/test/java/org/libreccm/security/ToStringTest.java
+++ b/ccm-core/src/test/java/org/libreccm/security/ToStringTest.java
@@ -41,6 +41,7 @@ public class ToStringTest extends ToStringVerifier {
Group.class,
GroupMembership.class,
Party.class,
+ OneTimeAuthToken.class,
Permission.class,
Role.class,
RoleMembership.class,
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 ae332dcfa..95ef56c77 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,17 +629,26 @@ CREATE SCHEMA ccm_core;
primary key (TASK_ID)
);
- alter table CCM_CORE.CATEGORY_DOMAINS
- add constraint UK_mb1riernf8a88u3mwl0bgfj8y unique (DOMAIN_KEY);
+ create table ONE_TIME_AUTH_TOKENS (
+ TOKEN_ID bigint not null,
+ PURPOSE varchar(255),
+ TOKEN varchar(255),
+ VALID_UNIT date,
+ USER_ID bigint,
+ primary key (TOKEN_ID)
+ );
alter table CCM_CORE.CATEGORY_DOMAINS
- add constraint UK_i1xqotjvml7i6ro2jq22fxf5g unique (URI);
+ add constraint UK_mb1riernf8a88u3mwl0bgfj8y unique (DOMAIN_KEY);
+
+ alter table CCM_CORE.CATEGORY_DOMAINS
+ add constraint UK_i1xqotjvml7i6ro2jq22fxf5g unique (URI);
alter table CCM_CORE.HOSTS
- add constraint UK_9ramlv6uxwt13v0wj7q0tucsx unique (SERVER_NAME, SERVER_PORT);
+ add constraint UK_9ramlv6uxwt13v0wj7q0tucsx unique (SERVER_NAME, SERVER_PORT);
alter table CCM_CORE.INSTALLED_MODULES
- add constraint UK_11imwgfojyi4hpr18uw9g3jvx unique (MODULE_CLASS_NAME);
+ add constraint UK_11imwgfojyi4hpr18uw9g3jvx unique (MODULE_CLASS_NAME);
alter table CCM_CORE.APPLICATIONS
add constraint FK_sn1sqtx94nhxgv282ymoqiock
@@ -1131,4 +1140,9 @@ CREATE SCHEMA ccm_core;
foreign key (WORKFLOW_ID)
references CCM_CORE.WORKFLOWS;
+ alter table ONE_TIME_AUTH_TOKENS
+ add constraint FK_fvr3t6w3nsm3u29mjuh4tplno
+ foreign key (USER_ID)
+ references CCM_CORE.USERS;
+
create sequence hibernate_sequence start with 1 increment by 1;
\ No newline at end of file
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 4587fc532..acca5129c 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
@@ -4,7 +4,6 @@ DROP SEQUENCE IF EXISTS hibernate_sequence;
CREATE SCHEMA ccm_core;
-
create table CCM_CORE.APPLICATIONS (
APPLICATION_TYPE varchar(1024) not null,
PRIMARY_URL varchar(1024) not null,
@@ -630,17 +629,26 @@ CREATE SCHEMA ccm_core;
primary key (TASK_ID)
);
- alter table CCM_CORE.CATEGORY_DOMAINS
- add constraint UK_mb1riernf8a88u3mwl0bgfj8y unique (DOMAIN_KEY);
+ create table ONE_TIME_AUTH_TOKENS (
+ TOKEN_ID int8 not null,
+ PURPOSE varchar(255),
+ TOKEN varchar(255),
+ VALID_UNIT date,
+ USER_ID int8,
+ primary key (TOKEN_ID)
+ );
alter table CCM_CORE.CATEGORY_DOMAINS
- add constraint UK_i1xqotjvml7i6ro2jq22fxf5g unique (URI);
+ add constraint UK_mb1riernf8a88u3mwl0bgfj8y unique (DOMAIN_KEY);
+
+ alter table CCM_CORE.CATEGORY_DOMAINS
+ add constraint UK_i1xqotjvml7i6ro2jq22fxf5g unique (URI);
alter table CCM_CORE.HOSTS
- add constraint UK_9ramlv6uxwt13v0wj7q0tucsx unique (SERVER_NAME, SERVER_PORT);
+ add constraint UK_9ramlv6uxwt13v0wj7q0tucsx unique (SERVER_NAME, SERVER_PORT);
alter table CCM_CORE.INSTALLED_MODULES
- add constraint UK_11imwgfojyi4hpr18uw9g3jvx unique (MODULE_CLASS_NAME);
+ add constraint UK_11imwgfojyi4hpr18uw9g3jvx unique (MODULE_CLASS_NAME);
alter table CCM_CORE.APPLICATIONS
add constraint FK_sn1sqtx94nhxgv282ymoqiock
@@ -1132,4 +1140,9 @@ CREATE SCHEMA ccm_core;
foreign key (WORKFLOW_ID)
references CCM_CORE.WORKFLOWS;
+ alter table ONE_TIME_AUTH_TOKENS
+ add constraint FK_fvr3t6w3nsm3u29mjuh4tplno
+ foreign key (USER_ID)
+ references CCM_CORE.USERS;
+
create sequence hibernate_sequence start 1 increment 1;
\ No newline at end of file