CCM NG: OneTimeAuth system, used for PasswordRecover, Account activation and email verification

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@3967 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2016-03-30 17:23:09 +00:00
parent 7d86a6db4c
commit 3eb86b41f2
14 changed files with 531 additions and 11 deletions

View File

@ -330,6 +330,7 @@
<param>org.libreccm.web</param>
<param>org.libreccm.workflow</param>
</packages>
<persistenceXml>${basedir}/src/main/resources/META-INF/persistence-ddl.xml</persistenceXml>
<useEnvers>true</useEnvers>
</configuration>
<executions>
@ -656,6 +657,7 @@
<param>org.libreccm</param>
</packages>
<useEnvers>true</useEnvers>
<persistenceXml>${basedir}/src/main/resources/META-INF/persistence-ddl.xml</persistenceXml>
</configuration>
<executions>
<execution>

View File

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

View File

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

View File

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

View File

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

View File

@ -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 <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@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 %<tT%s"
+ " }",
super.toString(),
tokenId,
Objects.toString(user),
validUntil,
data);
}
}

View File

@ -0,0 +1,32 @@
/*
* 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;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public enum OneTimeAuthTokenPurpose {
ACCOUNT_ACTIVATION,
EMAIL_VERIFICATION,
RECOVER_PASSWORD
}

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
author: Jens Pelzetter
-->
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="LibreCCM" transaction-type="JTA">
<!--
Enforce JPA provider
Not really necessary here because we don't use any Hibernate
specific features, but makes it easier to manage to database
creation scripts.
-->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>java:/comp/env/jdbc/libreccm/db</jta-data-source>
<properties>
<!-- Properties for Hibernate -->
<property name="hibernate.hbm2ddl.auto" value="validate"/>
<property name="hibernate.connection.autocommit" value="false" />
<property name="hibernate.id.new_generator_mappings" value="true"/>
<!--
Properties for Hibernate Envers
We are using the ValidityAuditStrategy here because it is faster
when querying data than the DefaultStrategy
-->
<property name="org.hibernate.envers.audit_strategy"
value="org.hibernate.envers.strategy.ValidityAuditStrategy"/>
</properties>
</persistence-unit>
</persistence>

View File

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

View File

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

View File

@ -42,6 +42,7 @@ public class EqualsAndHashCodeTest extends EqualsVerifier {
GroupMembership.class,
Party.class,
Permission.class,
OneTimeAuthToken.class,
Role.class,
RoleMembership.class,
User.class

View File

@ -41,6 +41,7 @@ public class ToStringTest extends ToStringVerifier {
Group.class,
GroupMembership.class,
Party.class,
OneTimeAuthToken.class,
Permission.class,
Role.class,
RoleMembership.class,

View File

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

View File

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