moved account support to own ejb project
This commit is contained in:
94
account/pom.xml
Normal file
94
account/pom.xml
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>de.muehlencord.shared</groupId>
|
||||||
|
<artifactId>shared-account</artifactId>
|
||||||
|
<version>0.1-SNAPSHOT</version>
|
||||||
|
<packaging>ejb</packaging>
|
||||||
|
|
||||||
|
<name>shared-account</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.shiro</groupId>
|
||||||
|
<artifactId>shiro-core</artifactId>
|
||||||
|
<version>1.2.4</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-lang</groupId>
|
||||||
|
<artifactId>commons-lang</artifactId>
|
||||||
|
<version>2.6</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>log4j</groupId>
|
||||||
|
<artifactId>log4j</artifactId>
|
||||||
|
<version>1.2.17</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.freemarker</groupId>
|
||||||
|
<artifactId>freemarker</artifactId>
|
||||||
|
<version>2.3.23</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax</groupId>
|
||||||
|
<artifactId>javaee-api</artifactId>
|
||||||
|
<version>7.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-ejb-plugin</artifactId>
|
||||||
|
<version>2.5.1</version>
|
||||||
|
<configuration>
|
||||||
|
<ejbVersion>3.1</ejbVersion>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<version>2.10</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>validate</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${endorsed.dir}</outputDirectory>
|
||||||
|
<silent>true</silent>
|
||||||
|
<artifactItems>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>javax</groupId>
|
||||||
|
<artifactId>javaee-endorsed-api</artifactId>
|
||||||
|
<version>7.0</version>
|
||||||
|
<type>jar</type>
|
||||||
|
</artifactItem>
|
||||||
|
</artifactItems>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
8
account/sql/01_config.sql
Normal file
8
account/sql/01_config.sql
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
DROP TABLE config;
|
||||||
|
|
||||||
|
CREATE TABLE config (
|
||||||
|
config_key varchar(100),
|
||||||
|
config_value varchar(200),
|
||||||
|
CONSTRAINT config_pk PRIMARY KEY (config_key)
|
||||||
|
);
|
||||||
|
INSERT INTO config (config_key, config_value) VALUES ('account.maxFailedLogins', '5');
|
||||||
83
account/sql/02_accounts.sql
Normal file
83
account/sql/02_accounts.sql
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* Author: joern.muehlencord
|
||||||
|
* Created: 06.09.2015
|
||||||
|
*/
|
||||||
|
|
||||||
|
DROP TABLE account_role;
|
||||||
|
DROP TABLE account_history;
|
||||||
|
DROP TABLE account;
|
||||||
|
DROP TABLE role_permission;
|
||||||
|
DROP TABLE application_role;
|
||||||
|
DROP TABLE application_permission;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE application_role (
|
||||||
|
role_name varchar(80) NOT NULL,
|
||||||
|
role_description varchar(200) NOT NULL,
|
||||||
|
CONSTRAINT pk_application_role_pk PRIMARY KEY (role_name)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE account (
|
||||||
|
username varchar(32) NOT NULL,
|
||||||
|
emailaddress varchar(200) NOT NULL,
|
||||||
|
firstname varchar(100) NOT NULL,
|
||||||
|
lastname varchar(100) NOT NULL,
|
||||||
|
account_password char(200) NOT NULL,
|
||||||
|
last_login timestamp with time zone,
|
||||||
|
last_failed_login timestamp with time zone,
|
||||||
|
failure_count int NOT NULL DEFAULT 0,
|
||||||
|
status varchar(10) NOT NULL DEFAULT 'NEW', -- NEW, INIT, OK, BLOCKED,
|
||||||
|
password_reset_ongoing boolean NOT NULL DEFAULT false,
|
||||||
|
password_reset_valid_to timestamp with time zone,
|
||||||
|
password_reset_hash char(200),
|
||||||
|
created_on timestamp with time zone NOT NULL DEFAULT (now() at time zone 'utc'),
|
||||||
|
created_by varchar(32) NOT NULL,
|
||||||
|
last_updated_on timestamp with time zone NOT NULL DEFAULT (now() at time zone 'utc'),
|
||||||
|
last_updated_by varchar(32) NOT NULL,
|
||||||
|
CONSTRAINT pk_account PRIMARY KEY (username)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE account_history (
|
||||||
|
id SERIAL NOT NULL,
|
||||||
|
username varchar(32) NOT NULL,
|
||||||
|
message varchar(200),
|
||||||
|
failure_count int NOT NULL DEFAULT 0,
|
||||||
|
status varchar(20) NOT NULL, -- constants needed, after action - new, init, active, blocked, inactive, marked for deletion
|
||||||
|
last_updated_on timestamp with time zone NOT NULL DEFAULT (now() at time zone 'utc'),
|
||||||
|
last_updated_by varchar(32) NOT NULL,
|
||||||
|
CONSTRAINT pk_account_history PRIMARY KEY (id),
|
||||||
|
CONSTRAINT fk_account_history_username_fk FOREIGN KEY (username) REFERENCES account (username)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE account_role (
|
||||||
|
username varchar(32) NOT NULL,
|
||||||
|
role_name varchar(80) NOT NULL,
|
||||||
|
CONSTRAINT pk_account_role PRIMARY KEY (username, role_name),
|
||||||
|
CONSTRAINT fk_account_role_account FOREIGN KEY (username) REFERENCES account(username),
|
||||||
|
CONSTRAINT fk_account_role_role_name FOREIGN KEY (role_name) REFERENCES application_role(role_name)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE application_permission (
|
||||||
|
permission_name varchar(80) NOT NULL,
|
||||||
|
permission_description varchar(200) NOT NULL,
|
||||||
|
CONSTRAINT application_permission_pk PRIMARY KEY (permission_name)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE role_permission (
|
||||||
|
role_name varchar(80) NOT NULL,
|
||||||
|
permission_name varchar(80) NOT NULL,
|
||||||
|
CONSTRAINT pk_role_permission_role_permission_name PRIMARY KEY (role_name, permission_name),
|
||||||
|
CONSTRAINT fk_role_permission_role_name FOREIGN KEY (role_name) REFERENCES application_role(role_name),
|
||||||
|
CONSTRAINT fk_role_permission_permission_name FOREIGN KEY (permission_name) REFERENCES application_permission(permission_name)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO application_permission (permission_name, permission_description) values ('test:view', 'Display test view');
|
||||||
|
|
||||||
|
INSERT INTO application_role (role_name, role_description) values ('Admin', 'Admin role');
|
||||||
|
INSERT INTO application_role (role_name, role_description) values ('User', 'Standard user role');
|
||||||
|
|
||||||
|
-- INSERT INTO role_permission (role_name, permission_name) values ('Admin','test:view');
|
||||||
|
|
||||||
|
INSERT INTO account (username, emailaddress, firstname, lastname, account_password, created_by, last_updated_by) values('admin', 'joern@muehlencord.de', 'Joern', 'Muehlencord','$shiro1$SHA-256$500000$4bHPNH9k539UjdFLgm/HOA==$T/n8skgoGSOtNw/c9ScDlXCiGrx2cZF0Esrvf6WPq6g=', 'admin','admin'); --admin/secret
|
||||||
|
INSERT INTO account_role (username, role_name) values ('admin', 'Admin');
|
||||||
21
account/sql/03_templates.sql
Normal file
21
account/sql/03_templates.sql
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
DROP TABLE mail_template;
|
||||||
|
|
||||||
|
CREATE TABLE mail_template (
|
||||||
|
template_name varchar(40) NOT NULL,
|
||||||
|
template_value text NOT NULL,
|
||||||
|
CONSTRAINT mail_template_pk PRIMARY KEY (template_name)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
INSERT INTO mail_template (template_name, template_value) VALUES('password_reset_html',
|
||||||
|
'<#ftl strip_whitespace = true>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
Dear ${account.firstname},<br>
|
||||||
|
<br>
|
||||||
|
you requested to reset your password at ${parameter.url}. Please open the following URL to proceed.<br>
|
||||||
|
<a href="${parameter.resetUrl}">${parameter.resetUrl}</a><br>
|
||||||
|
<br>
|
||||||
|
</body>
|
||||||
|
</html>');
|
||||||
2
account/sql/create_tables.sql
Normal file
2
account/sql/create_tables.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
\i 01_accounts.sql
|
||||||
|
\i 02_templates.sql
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
package de.muehlencord.shared.account.business;
|
||||||
|
|
||||||
|
import de.muehlencord.shared.account.entity.ConfigEntity;
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.ejb.Singleton;
|
||||||
|
import javax.ejb.Startup;
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.PersistenceContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author joern.muehlencord
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
@Startup
|
||||||
|
public class ConfigService {
|
||||||
|
|
||||||
|
@PersistenceContext
|
||||||
|
EntityManager em;
|
||||||
|
|
||||||
|
private String storagePath = null;
|
||||||
|
private int maxFailedLogins = 5;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
ConfigEntity configEntity = em.find(ConfigEntity.class, "storage.path");
|
||||||
|
if (configEntity != null) {
|
||||||
|
this.storagePath = configEntity.getConfigValue();
|
||||||
|
}
|
||||||
|
configEntity = em.find(ConfigEntity.class, "account.maxFailedLogins");
|
||||||
|
if (configEntity != null) {
|
||||||
|
this.maxFailedLogins = Integer.parseInt(configEntity.getConfigValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* *** getter *** */
|
||||||
|
public String getStoragePath() {
|
||||||
|
return storagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxFailedLogins() {
|
||||||
|
return maxFailedLogins;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,278 @@
|
|||||||
|
package de.muehlencord.shared.account.business.account;
|
||||||
|
|
||||||
|
import de.muehlencord.shared.account.business.ConfigService;
|
||||||
|
import de.muehlencord.shared.account.business.mail.MailService;
|
||||||
|
import de.muehlencord.shared.account.business.mail.MailTemplateException;
|
||||||
|
import de.muehlencord.shared.account.entity.AccountEntity;
|
||||||
|
import de.muehlencord.shared.account.entity.RoleEntity;
|
||||||
|
import de.muehlencord.shared.account.util.SecurityUtil;
|
||||||
|
import freemarker.template.TemplateException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.ejb.EJB;
|
||||||
|
import javax.ejb.Stateless;
|
||||||
|
import javax.mail.MessagingException;
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.NoResultException;
|
||||||
|
import javax.persistence.PersistenceContext;
|
||||||
|
import javax.persistence.Query;
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
import org.apache.commons.lang.RandomStringUtils;
|
||||||
|
import org.apache.log4j.Level;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.apache.shiro.SecurityUtils;
|
||||||
|
import org.apache.shiro.subject.Subject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author joern.muehlencord
|
||||||
|
*/
|
||||||
|
@Stateless
|
||||||
|
public class AccountControl {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(AccountControl.class.getName());
|
||||||
|
|
||||||
|
@EJB
|
||||||
|
private ConfigService configService;
|
||||||
|
|
||||||
|
@EJB
|
||||||
|
private MailService mailService;
|
||||||
|
|
||||||
|
@PersistenceContext
|
||||||
|
EntityManager em;
|
||||||
|
|
||||||
|
public List<AccountEntity> getAccounts() {
|
||||||
|
Query query = em.createQuery("SELECT a FROM AccountEntity a WHERE a.status <> :status", AccountEntity.class);
|
||||||
|
query.setParameter("status", "DELETED"); // TODO add status enum
|
||||||
|
return query.getResultList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccountEntity getAccountEntity(String userName, boolean loadRoles) {
|
||||||
|
StringBuilder queryBuilder = new StringBuilder();
|
||||||
|
queryBuilder.append("SELECT a FROM AccountEntity a ");
|
||||||
|
if (loadRoles) {
|
||||||
|
queryBuilder.append("JOIN FETCH a.roleEntityList ");
|
||||||
|
}
|
||||||
|
queryBuilder.append("WHERE a.username = :username");
|
||||||
|
Query query = em.createQuery(queryBuilder.toString());
|
||||||
|
query.setParameter("username", userName);
|
||||||
|
try {
|
||||||
|
return (AccountEntity) query.getSingleResult();
|
||||||
|
} catch (NoResultException ex) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
// TODO add role names from application because only application can now how its roles are named
|
||||||
|
public AccountEntity saveAccount(AccountEntity account, boolean isAdmin) {
|
||||||
|
Date now = new Date(); // Todo now in UTC
|
||||||
|
Subject currentUser = SecurityUtils.getSubject();
|
||||||
|
String currentLoggedInUser = currentUser.getPrincipal().toString();
|
||||||
|
|
||||||
|
account.setLastUpdatedBy(currentLoggedInUser);
|
||||||
|
account.setLastUpdatedOn(now);
|
||||||
|
|
||||||
|
boolean newAccount = (account.getCreatedOn() == null);
|
||||||
|
|
||||||
|
// new account
|
||||||
|
if (newAccount) {
|
||||||
|
account.setCreatedOn(now);
|
||||||
|
account.setCreatedBy(currentLoggedInUser);
|
||||||
|
|
||||||
|
// set default random password, user has to get password via lost passwort option afterwards
|
||||||
|
String randomPassword = RandomStringUtils.random(20, true, true);
|
||||||
|
String hashedPassword = SecurityUtil.createPassword(randomPassword);
|
||||||
|
account.setAccountPassword(hashedPassword);
|
||||||
|
em.persist(account);
|
||||||
|
} else {
|
||||||
|
em.merge(account);
|
||||||
|
|
||||||
|
// reload account from db and join roles
|
||||||
|
account = getAccountEntity(account.getUsername(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// load Admin or User role from database
|
||||||
|
String roleName = (isAdmin ? "Admin" : "User");
|
||||||
|
Query roleQuery = em.createNamedQuery("RoleEntity.findByRoleName");
|
||||||
|
roleQuery.setParameter("roleName", roleName);
|
||||||
|
RoleEntity role = (RoleEntity) roleQuery.getSingleResult();
|
||||||
|
|
||||||
|
if (role != null) {
|
||||||
|
// add new user add required role
|
||||||
|
// do not request based on newUser variable; this way existing users with missing role (for whatever reason)
|
||||||
|
// will be fixed automatically
|
||||||
|
if (account.getRoleEntityList() == null || account.getRoleEntityList().isEmpty()) {
|
||||||
|
account.setRoleEntityList(new ArrayList<>());
|
||||||
|
account.getRoleEntityList().add(role);
|
||||||
|
em.merge(account);
|
||||||
|
LOGGER.log(Level.INFO, "Added role " + roleName + " to user " + account.getUsername());
|
||||||
|
|
||||||
|
} else if (!account.getRoleEntityList().get(0).equals(role)) {
|
||||||
|
// change role from User to Admin and vice versa
|
||||||
|
// user already exists, has existing role
|
||||||
|
// check if existing role is different from current role and change it
|
||||||
|
// be carefull: this only works as long as a user has exactly one role!
|
||||||
|
// he is either User or Admin
|
||||||
|
// TODO add "UserRole" to every user, make this default Role configurable
|
||||||
|
// TODO add AdminRole in addtion if needed
|
||||||
|
account.getRoleEntityList().remove(0);
|
||||||
|
account.getRoleEntityList().add(role);
|
||||||
|
em.merge(account);
|
||||||
|
LOGGER.log(Level.INFO, "Switched role of user " + account.getUsername() + " to " + roleName);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteAccount(AccountEntity account) throws AccountException {
|
||||||
|
Date now = new Date(); // Todo now in UTC
|
||||||
|
Subject currentUser = SecurityUtils.getSubject();
|
||||||
|
String currentUserName = currentUser.getPrincipal().toString();
|
||||||
|
|
||||||
|
if (account.getUsername().equals(currentUserName)) {
|
||||||
|
throw new AccountException ("Cannot delete own account");
|
||||||
|
} else {
|
||||||
|
account.setStatus("DELETED"); // TODO add enum
|
||||||
|
account.setLastUpdatedBy(currentUserName);
|
||||||
|
account.setLastUpdatedOn(now);
|
||||||
|
em.merge(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean initPasswordReset(String userName) {
|
||||||
|
try {
|
||||||
|
AccountEntity account = getAccountEntity(userName, false);
|
||||||
|
if (account == null) {
|
||||||
|
LOGGER.log(Level.WARN, "Account with name " + userName + " not found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (account.getStatus().equals("LOCKED")) { // TODO add enumType
|
||||||
|
LOGGER.log(Level.WARN, "Account " + userName + " is locked, cannot initialize password reset");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String randomString = RandomStringUtils.random(40, true, true);
|
||||||
|
|
||||||
|
Date validTo = new Date(); // TODO now in UTC
|
||||||
|
validTo = new Date(validTo.getTime() + 1000 * 600); // 10 minutes to react
|
||||||
|
|
||||||
|
account.setPasswordResetHash(randomString);
|
||||||
|
account.setPasswordResetOngoing(true);
|
||||||
|
account.setPasswordResetValidTo(validTo);
|
||||||
|
|
||||||
|
mailService.sendPasswortResetStartEmail(account, randomString);
|
||||||
|
|
||||||
|
em.merge(account);
|
||||||
|
return true;
|
||||||
|
} catch (MessagingException | MailTemplateException | URISyntaxException | IOException | TemplateException ex) {
|
||||||
|
LOGGER.log(Level.ERROR, "Error while sending password reset mail. " + ex.toString());
|
||||||
|
if (LOGGER.isDebugEnabled()) {
|
||||||
|
LOGGER.log(Level.DEBUG, "Error while sending password reset mail.", ex);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean resetPassword(String userName, String newPassword, String resetPasswordToken) {
|
||||||
|
AccountEntity account = getAccountEntity(userName, false);
|
||||||
|
|
||||||
|
if (account == null) {
|
||||||
|
LOGGER.log(Level.WARN, "Error while resetting password, no account with username " + userName + " found");
|
||||||
|
// TODO add extra logging for intrusion protection system like fail2ban
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (account.getPasswordResetOngoing() && (account.getPasswordResetHash() != null) && (account.getPasswordResetValidTo() != null)) {
|
||||||
|
Date now = new Date(); // TODO now in UTC
|
||||||
|
String storedHash = account.getPasswordResetHash().trim();
|
||||||
|
if (account.getPasswordResetValidTo().after(now)) {
|
||||||
|
if (storedHash.equals(resetPasswordToken)) {
|
||||||
|
// everything ok, reset password
|
||||||
|
executePasswordReset(account, newPassword);
|
||||||
|
LOGGER.log(Level.INFO, "Updated password for user " + userName);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// token is not valid, refuse to change password
|
||||||
|
LOGGER.log(Level.WARN, "Trying to reset password for user " + userName + " but wrong token " + resetPasswordToken + " provided");
|
||||||
|
addLoginError(account);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// password reset token no longer valid
|
||||||
|
LOGGER.log(Level.WARN, "Trying to reset password for user " + userName + " but token is no longer valid");
|
||||||
|
addLoginError(account);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// user is not is password reset mode
|
||||||
|
LOGGER.log(Level.WARN, "Trying to reset password for user " + userName + " but password reset was not requested");
|
||||||
|
addLoginError(account);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void executePasswordReset(AccountEntity account, String newPassword) {
|
||||||
|
Date now = new Date(); // TODO now in UTC
|
||||||
|
|
||||||
|
String hashedPassword = SecurityUtil.createPassword(newPassword);
|
||||||
|
account.setAccountPassword(hashedPassword);
|
||||||
|
|
||||||
|
account.setPasswordResetOngoing(false);
|
||||||
|
account.setPasswordResetHash(null);
|
||||||
|
account.setPasswordResetValidTo(null);
|
||||||
|
|
||||||
|
account.setLastUpdatedBy(account.getUsername());
|
||||||
|
account.setLastUpdatedOn(now);
|
||||||
|
em.merge(account);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateLogin(AccountEntity account) {
|
||||||
|
Date now = new Date(); // TODO now in UTC
|
||||||
|
// a scucessful login ends a password reset procedure
|
||||||
|
if (account.getPasswordResetOngoing()) {
|
||||||
|
account.setPasswordResetOngoing(false);
|
||||||
|
account.setPasswordResetHash(null);
|
||||||
|
account.setPasswordResetValidTo(null);
|
||||||
|
account.setLastUpdatedOn(now);
|
||||||
|
account.setLastUpdatedBy(account.getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
account.setLastLogin(now);
|
||||||
|
account.setFailureCount(0);
|
||||||
|
account.setStatus("OK"); // TODO add statusEnum
|
||||||
|
|
||||||
|
em.merge(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addLoginError(AccountEntity account) {
|
||||||
|
Date now = new Date(); // TODO now in UTC
|
||||||
|
account.setLastFailedLogin(now);
|
||||||
|
account.setFailureCount(account.getFailureCount() + 1);
|
||||||
|
|
||||||
|
int maxFailedLogins = configService.getMaxFailedLogins();
|
||||||
|
if ((account.getFailureCount() >= maxFailedLogins) && (!account.getStatus().equals("LOCKED"))) { // TOD add status enum
|
||||||
|
// max failed logins reached, disabling user
|
||||||
|
LOGGER.log(Level.INFO, "Locking account " + account.getUsername() + " due to " + account.getFailureCount() + " failed logins");
|
||||||
|
account.setStatus("LOCKED"); // TODO add enum
|
||||||
|
}
|
||||||
|
|
||||||
|
// on a failed login request, disable password reset
|
||||||
|
account.setPasswordResetOngoing(false);
|
||||||
|
account.setPasswordResetHash(null);
|
||||||
|
account.setPasswordResetValidTo(null);
|
||||||
|
|
||||||
|
account.setLastUpdatedBy("system");
|
||||||
|
account.setLastUpdatedOn(now);
|
||||||
|
em.merge(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
package de.muehlencord.shared.account.business.account;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Raimund
|
||||||
|
*/
|
||||||
|
public class AccountException extends Exception {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance of <code>AccountException</code> without detail
|
||||||
|
* message.
|
||||||
|
*/
|
||||||
|
public AccountException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance of <code>AccountException</code> with the
|
||||||
|
* specified detail message.
|
||||||
|
*
|
||||||
|
* @param msg the detail message.
|
||||||
|
*/
|
||||||
|
public AccountException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
package de.muehlencord.shared.account.business.mail;
|
||||||
|
|
||||||
|
import de.muehlencord.shared.account.entity.AccountEntity;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jomu
|
||||||
|
*/
|
||||||
|
public class MailDatamodel {
|
||||||
|
|
||||||
|
private final AccountEntity account;
|
||||||
|
private final Map<String,String> parameter;
|
||||||
|
|
||||||
|
public MailDatamodel(AccountEntity account) {
|
||||||
|
this.parameter = new HashMap<>();
|
||||||
|
this.account = account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addParameter(String name, String value) {
|
||||||
|
this.parameter.put(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* **** getter / setter **** */
|
||||||
|
|
||||||
|
public AccountEntity getAccount() {
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getParameter() {
|
||||||
|
return parameter;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package de.muehlencord.shared.account.business.mail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Raimund
|
||||||
|
*/
|
||||||
|
public class MailException extends Exception {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance of <code>MailException</code> without detail
|
||||||
|
* message.
|
||||||
|
*/
|
||||||
|
public MailException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance of <code>MailException</code> with the specified
|
||||||
|
* detail message.
|
||||||
|
*
|
||||||
|
* @param msg the detail message.
|
||||||
|
*/
|
||||||
|
public MailException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance of <code>MailException</code> with the specified
|
||||||
|
* detail message.
|
||||||
|
*
|
||||||
|
* @param msg the detail message.
|
||||||
|
* @param th the root cause
|
||||||
|
*/
|
||||||
|
public MailException(String msg, Throwable th) {
|
||||||
|
super(msg, th);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,104 @@
|
|||||||
|
package de.muehlencord.shared.account.business.mail;
|
||||||
|
|
||||||
|
import de.muehlencord.shared.account.entity.AccountEntity;
|
||||||
|
import freemarker.template.TemplateException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Date;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.ejb.EJB;
|
||||||
|
import javax.ejb.Stateless;
|
||||||
|
import javax.faces.application.FacesMessage;
|
||||||
|
import javax.faces.context.ExternalContext;
|
||||||
|
import javax.faces.context.FacesContext;
|
||||||
|
import javax.mail.BodyPart;
|
||||||
|
import javax.mail.Message;
|
||||||
|
import javax.mail.MessagingException;
|
||||||
|
import javax.mail.Multipart;
|
||||||
|
import javax.mail.Session;
|
||||||
|
import javax.mail.Transport;
|
||||||
|
import javax.mail.internet.InternetAddress;
|
||||||
|
import javax.mail.internet.MimeBodyPart;
|
||||||
|
import javax.mail.internet.MimeMessage;
|
||||||
|
import javax.mail.internet.MimeMultipart;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author joern.muehlencord
|
||||||
|
*/
|
||||||
|
@Stateless
|
||||||
|
public class MailService {
|
||||||
|
|
||||||
|
@EJB
|
||||||
|
private MailTemplateService mailTemplateService;
|
||||||
|
|
||||||
|
@Resource(lookup = "java:jboss/mail/ssgMail")
|
||||||
|
private Session mailSession;
|
||||||
|
|
||||||
|
public void sendTestEmail(String recipient) throws MailException {
|
||||||
|
sendMail(recipient, "Test email", "This is a test email");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendTestHtmlEmail(String recipient) {
|
||||||
|
Date now = new Date();
|
||||||
|
AccountEntity account = new AccountEntity("joern.muehlencord", "joern@muehlencord.de", "Jörn", "Mühlencord", "secret", 0, "NEW", now, "admin", now, "admin");
|
||||||
|
MailDatamodel dataModel = new MailDatamodel(account);
|
||||||
|
dataModel.addParameter("url", "http://url.de");
|
||||||
|
dataModel.addParameter("resetUrl", "http://reseturl.de");
|
||||||
|
sendHTMLMail(recipient, "Test HTML Email", dataModel, "password_reset");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendMail(String recipient, String subject, String body) throws MailException {
|
||||||
|
try {
|
||||||
|
MimeMessage message = new MimeMessage(mailSession);
|
||||||
|
message.setSubject(subject);
|
||||||
|
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipient, false));
|
||||||
|
message.setText(body);
|
||||||
|
Transport.send(message);
|
||||||
|
} catch (MessagingException ex) {
|
||||||
|
throw new MailException ("Error while sending email.", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendHTMLMail(String recipient, String subject, MailDatamodel dataModel, String templateName) {
|
||||||
|
try {
|
||||||
|
Message message = new MimeMessage(mailSession);
|
||||||
|
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipient, false));
|
||||||
|
message.setSubject(subject);
|
||||||
|
|
||||||
|
String body = mailTemplateService.getStringFromTemplate("password_reset_html", dataModel);
|
||||||
|
|
||||||
|
BodyPart bodyPart = new MimeBodyPart();
|
||||||
|
bodyPart.setContent(body, "text/html");
|
||||||
|
|
||||||
|
Multipart multipart = new MimeMultipart();
|
||||||
|
multipart.addBodyPart(bodyPart);
|
||||||
|
message.setContent(multipart, "text/html; charset=UTF-8");
|
||||||
|
|
||||||
|
Transport.send(message);
|
||||||
|
} catch (MessagingException | MailTemplateException ex) {
|
||||||
|
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error while sending email", "Exception: " + ex.toString());
|
||||||
|
FacesContext context = FacesContext.getCurrentInstance();
|
||||||
|
context.addMessage(null, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendPasswortResetStartEmail(AccountEntity account, String token) throws MessagingException, URISyntaxException, IOException, TemplateException, MailTemplateException {
|
||||||
|
MailDatamodel model = new MailDatamodel(account);
|
||||||
|
|
||||||
|
// String absoluteWebPath = FacesContext.getCurrentInstance().getExternalContext().getApplicationContextPath();
|
||||||
|
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
|
||||||
|
String resetPage = "/login.xhtml?token=" + token;
|
||||||
|
URL baseUrl = new URL(externalContext.getRequestScheme(),
|
||||||
|
externalContext.getRequestServerName(),
|
||||||
|
externalContext.getRequestServerPort(),
|
||||||
|
externalContext.getRequestContextPath());
|
||||||
|
|
||||||
|
model.addParameter("url", baseUrl.toString());
|
||||||
|
model.addParameter("resetUrl", baseUrl.toString() + resetPage);
|
||||||
|
|
||||||
|
sendHTMLMail(account.getEmailaddress(), "Reset your password", model, "password_reset");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,138 @@
|
|||||||
|
package de.muehlencord.shared.account.business.mail;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import javax.ejb.EJBHome;
|
||||||
|
import javax.ejb.EJBLocalHome;
|
||||||
|
import javax.jms.ConnectionFactory;
|
||||||
|
import javax.jms.Destination;
|
||||||
|
import javax.naming.InitialContext;
|
||||||
|
import javax.naming.NamingException;
|
||||||
|
import javax.rmi.PortableRemoteObject;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import javax.mail.Session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Raimund
|
||||||
|
*/
|
||||||
|
public class MailServiceLocator {
|
||||||
|
|
||||||
|
private InitialContext ic;
|
||||||
|
|
||||||
|
public MailServiceLocator() {
|
||||||
|
try {
|
||||||
|
ic = new InitialContext();
|
||||||
|
} catch (NamingException ne) {
|
||||||
|
throw new RuntimeException(ne);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object lookup(String jndiName) throws NamingException {
|
||||||
|
return ic.lookup(jndiName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will get the ejb Local home factory. Clients need to cast to the type of
|
||||||
|
* EJBHome they desire.
|
||||||
|
*
|
||||||
|
* @param jndiHomeName jndi home name matching the requested local home
|
||||||
|
* @return the Local EJB Home corresponding to the homeName
|
||||||
|
* @throws NamingException if the lookup fails
|
||||||
|
*/
|
||||||
|
public EJBLocalHome getLocalHome(String jndiHomeName) throws NamingException {
|
||||||
|
return (EJBLocalHome) lookup(jndiHomeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will get the ejb Remote home factory. Clients need to cast to the type of
|
||||||
|
* EJBHome they desire.
|
||||||
|
*
|
||||||
|
* @param jndiHomeName jndi home name matching the requested remote home
|
||||||
|
* @param className desired type of the object
|
||||||
|
* @return the EJB Home corresponding to the homeName
|
||||||
|
* @throws NamingException if the lookup fails
|
||||||
|
*/
|
||||||
|
public EJBHome getRemoteHome(String jndiHomeName, Class className) throws NamingException {
|
||||||
|
Object objref = lookup(jndiHomeName);
|
||||||
|
return (EJBHome) PortableRemoteObject.narrow(objref, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method helps in obtaining the JMS connection factory.
|
||||||
|
*
|
||||||
|
* @param connFactoryName name of the connection factory
|
||||||
|
* @return the factory for obtaining JMS connection
|
||||||
|
* @throws NamingException if the lookup fails
|
||||||
|
*/
|
||||||
|
public ConnectionFactory getConnectionFactory(String connFactoryName) throws NamingException {
|
||||||
|
return (ConnectionFactory) lookup(connFactoryName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method obtains the topic itself for a caller.
|
||||||
|
*
|
||||||
|
* @param destName destination name
|
||||||
|
* @return the Topic Destination to send messages to
|
||||||
|
* @throws NamingException if the lookup fails
|
||||||
|
*/
|
||||||
|
public Destination getDestination(String destName) throws NamingException {
|
||||||
|
return (Destination) lookup(destName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method obtains the datasource itself for a caller.
|
||||||
|
*
|
||||||
|
* @param dataSourceName data source name
|
||||||
|
* @return the DataSource corresponding to the name parameter
|
||||||
|
* @throws NamingException if the lookup fails
|
||||||
|
*/
|
||||||
|
public DataSource getDataSource(String dataSourceName) throws NamingException {
|
||||||
|
return (DataSource) lookup(dataSourceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method obtains the E-mail session itself for a caller.
|
||||||
|
*
|
||||||
|
* @param sessionName session name
|
||||||
|
* @return the Session corresponding to the name parameter
|
||||||
|
* @throws NamingException if the lookup fails
|
||||||
|
*/
|
||||||
|
public Session getSession(String sessionName) throws NamingException {
|
||||||
|
return (Session) lookup(sessionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the URL corresponding to the environment entry name.
|
||||||
|
*
|
||||||
|
* @param envName the environment name
|
||||||
|
* @return the URL value corresponding to the environment entry name
|
||||||
|
* @throws NamingException if the lookup fails
|
||||||
|
*/
|
||||||
|
public URL getUrl(String envName) throws NamingException {
|
||||||
|
return (URL) lookup(envName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets boolean value corresponding to the environment entry name.
|
||||||
|
*
|
||||||
|
* @param envName the environment name
|
||||||
|
* @return the boolean value corresponding to the environment entry
|
||||||
|
* @throws NamingException if the lookup fails
|
||||||
|
*/
|
||||||
|
public boolean getBoolean(String envName) throws NamingException {
|
||||||
|
Boolean bool = (Boolean) lookup(envName);
|
||||||
|
return bool.booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets string value corresponding to the environment entry name.
|
||||||
|
*
|
||||||
|
* @param envName the environment name
|
||||||
|
* @return the String value corresponding to the environment entry name
|
||||||
|
* @throws NamingException if the lookup fails
|
||||||
|
*/
|
||||||
|
public String getString(String envName) throws NamingException {
|
||||||
|
return (String) lookup(envName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package de.muehlencord.shared.account.business.mail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jomu
|
||||||
|
*/
|
||||||
|
public class MailTemplateException extends Exception {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance of <code>MailTemplateException</code> without
|
||||||
|
* detail message.
|
||||||
|
*/
|
||||||
|
public MailTemplateException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance of <code>MailTemplateException</code> with the
|
||||||
|
* specified detail message.
|
||||||
|
*
|
||||||
|
* @param msg the detail message.
|
||||||
|
*/
|
||||||
|
public MailTemplateException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance of <code>MailTemplateException</code> with the
|
||||||
|
* specified detail message.
|
||||||
|
*
|
||||||
|
* @param msg the detail message.
|
||||||
|
* @param th the root cause
|
||||||
|
*/
|
||||||
|
public MailTemplateException(String msg, Throwable th) {
|
||||||
|
super(msg, th);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
package de.muehlencord.shared.account.business.mail;
|
||||||
|
|
||||||
|
import de.muehlencord.shared.account.entity.MailTemplateEntity;
|
||||||
|
import freemarker.cache.StringTemplateLoader;
|
||||||
|
import freemarker.template.Configuration;
|
||||||
|
import freemarker.template.Template;
|
||||||
|
import freemarker.template.TemplateException;
|
||||||
|
import freemarker.template.TemplateExceptionHandler;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import javax.ejb.Stateless;
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.PersistenceContext;
|
||||||
|
import javax.persistence.Query;
|
||||||
|
import org.apache.log4j.Level;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jomu
|
||||||
|
*/
|
||||||
|
@Stateless
|
||||||
|
public class MailTemplateService {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(MailTemplateService.class.getName());
|
||||||
|
|
||||||
|
@PersistenceContext
|
||||||
|
EntityManager em;
|
||||||
|
|
||||||
|
public String getStringFromTemplate(String templateName, MailDatamodel dataModel) throws MailTemplateException {
|
||||||
|
try {
|
||||||
|
Query query = em.createNamedQuery("MailTemplateEntity.findByTemplateName");
|
||||||
|
query.setParameter("templateName", templateName);
|
||||||
|
MailTemplateEntity templateEntity = (MailTemplateEntity) query.getSingleResult();
|
||||||
|
if (templateEntity == null) {
|
||||||
|
LOGGER.log(Level.ERROR, "Tempate with name " + templateName + " not found");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);
|
||||||
|
configuration.setDefaultEncoding("UTF-8");
|
||||||
|
configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
|
||||||
|
|
||||||
|
StringTemplateLoader stringLoader = new StringTemplateLoader();
|
||||||
|
stringLoader.putTemplate(templateEntity.getTemplateName(), templateEntity.getTemplateValue());
|
||||||
|
configuration.setTemplateLoader(stringLoader);
|
||||||
|
|
||||||
|
Template template = configuration.getTemplate(templateEntity.getTemplateName());
|
||||||
|
|
||||||
|
Writer out = new StringWriter();
|
||||||
|
template.process(dataModel, out);
|
||||||
|
String templateString = out.toString();
|
||||||
|
return templateString;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
String hint = "Error while processing template with name " + templateName + ".";
|
||||||
|
LOGGER.log(Level.ERROR, hint + " " + ex.toString());
|
||||||
|
if (LOGGER.isDebugEnabled()) {
|
||||||
|
LOGGER.log(Level.DEBUG, hint, ex);
|
||||||
|
}
|
||||||
|
throw new MailTemplateException(hint, ex);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,322 @@
|
|||||||
|
package de.muehlencord.shared.account.entity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.JoinTable;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.Temporal;
|
||||||
|
import javax.persistence.TemporalType;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
import javax.xml.bind.annotation.XmlTransient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author joern.muehlencord
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "account")
|
||||||
|
@XmlRootElement
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name = "AccountEntity.findAll", query = "SELECT a FROM AccountEntity a"),
|
||||||
|
@NamedQuery(name = "AccountEntity.findByUsername", query = "SELECT a FROM AccountEntity a WHERE a.username = :username"),
|
||||||
|
@NamedQuery(name = "AccountEntity.findByEmailaddress", query = "SELECT a FROM AccountEntity a WHERE a.emailaddress = :emailaddress"),
|
||||||
|
@NamedQuery(name = "AccountEntity.findByFirstname", query = "SELECT a FROM AccountEntity a WHERE a.firstname = :firstname"),
|
||||||
|
@NamedQuery(name = "AccountEntity.findByLastname", query = "SELECT a FROM AccountEntity a WHERE a.lastname = :lastname"),
|
||||||
|
@NamedQuery(name = "AccountEntity.findByAccountPassword", query = "SELECT a FROM AccountEntity a WHERE a.accountPassword = :accountPassword"),
|
||||||
|
@NamedQuery(name = "AccountEntity.findByLastLogin", query = "SELECT a FROM AccountEntity a WHERE a.lastLogin = :lastLogin"),
|
||||||
|
@NamedQuery(name = "AccountEntity.findByLastFailedLogin", query = "SELECT a FROM AccountEntity a WHERE a.lastFailedLogin = :lastFailedLogin"),
|
||||||
|
@NamedQuery(name = "AccountEntity.findByFailureCount", query = "SELECT a FROM AccountEntity a WHERE a.failureCount = :failureCount"),
|
||||||
|
@NamedQuery(name = "AccountEntity.findByStatus", query = "SELECT a FROM AccountEntity a WHERE a.status = :status"),
|
||||||
|
@NamedQuery(name = "AccountEntity.findByCreatedOn", query = "SELECT a FROM AccountEntity a WHERE a.createdOn = :createdOn"),
|
||||||
|
@NamedQuery(name = "AccountEntity.findByCreatedBy", query = "SELECT a FROM AccountEntity a WHERE a.createdBy = :createdBy"),
|
||||||
|
@NamedQuery(name = "AccountEntity.findByLastUpdatedOn", query = "SELECT a FROM AccountEntity a WHERE a.lastUpdatedOn = :lastUpdatedOn"),
|
||||||
|
@NamedQuery(name = "AccountEntity.findByLastUpdatedBy", query = "SELECT a FROM AccountEntity a WHERE a.lastUpdatedBy = :lastUpdatedBy")})
|
||||||
|
public class AccountEntity implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
@Id
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 32)
|
||||||
|
@Column(name = "username")
|
||||||
|
private String username;
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 200)
|
||||||
|
@Column(name = "emailaddress")
|
||||||
|
private String emailaddress;
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 100)
|
||||||
|
@Column(name = "firstname")
|
||||||
|
private String firstname;
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 100)
|
||||||
|
@Column(name = "lastname")
|
||||||
|
private String lastname;
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 200)
|
||||||
|
@Column(name = "account_password", columnDefinition = "bpchar(200)")
|
||||||
|
private String accountPassword;
|
||||||
|
@Column(name = "last_login")
|
||||||
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
|
private Date lastLogin;
|
||||||
|
@Column(name = "last_failed_login")
|
||||||
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
|
private Date lastFailedLogin;
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "failure_count")
|
||||||
|
private int failureCount;
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 10)
|
||||||
|
@Column(name = "status")
|
||||||
|
private String status;
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "password_reset_ongoing")
|
||||||
|
private boolean passwordResetOngoing;
|
||||||
|
@Column(name = "password_reset_valid_to")
|
||||||
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
|
private Date passwordResetValidTo;
|
||||||
|
@Size(max = 200)
|
||||||
|
@Column(name = "password_reset_hash", columnDefinition = "bpchar(200)")
|
||||||
|
private String passwordResetHash;
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "created_on")
|
||||||
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
|
private Date createdOn;
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 32)
|
||||||
|
@Column(name = "created_by")
|
||||||
|
private String createdBy;
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "last_updated_on")
|
||||||
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
|
private Date lastUpdatedOn;
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 32)
|
||||||
|
@Column(name = "last_updated_by")
|
||||||
|
private String lastUpdatedBy;
|
||||||
|
@JoinTable(name = "account_role", joinColumns = {
|
||||||
|
@JoinColumn(name = "username", referencedColumnName = "username")}, inverseJoinColumns = {
|
||||||
|
@JoinColumn(name = "role_name", referencedColumnName = "role_name")})
|
||||||
|
@ManyToMany
|
||||||
|
private List<RoleEntity> roleEntityList;
|
||||||
|
@OneToMany(cascade = CascadeType.ALL, mappedBy = "username")
|
||||||
|
private List<AccountHistoryEntity> accountHistoryEntityList;
|
||||||
|
|
||||||
|
public AccountEntity() {
|
||||||
|
// empty constructor needed for JPA handling, do not remove
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccountEntity(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccountEntity(String username, String emailaddress, String firstname, String lastname, String accountPassword, int failureCount, String status, Date createdOn, String createdBy, Date lastUpdatedOn, String lastUpdatedBy) {
|
||||||
|
this.username = username;
|
||||||
|
this.emailaddress = emailaddress;
|
||||||
|
this.firstname = firstname;
|
||||||
|
this.lastname = lastname;
|
||||||
|
this.accountPassword = accountPassword;
|
||||||
|
this.failureCount = failureCount;
|
||||||
|
this.status = status;
|
||||||
|
this.createdOn = createdOn;
|
||||||
|
this.createdBy = createdBy;
|
||||||
|
this.lastUpdatedOn = lastUpdatedOn;
|
||||||
|
this.lastUpdatedBy = lastUpdatedBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmailaddress() {
|
||||||
|
return emailaddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmailaddress(String emailaddress) {
|
||||||
|
this.emailaddress = emailaddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstname() {
|
||||||
|
return firstname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstname(String firstname) {
|
||||||
|
this.firstname = firstname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastname() {
|
||||||
|
return lastname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastname(String lastname) {
|
||||||
|
this.lastname = lastname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAccountPassword() {
|
||||||
|
return accountPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccountPassword(String accountPassword) {
|
||||||
|
this.accountPassword = accountPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getLastLogin() {
|
||||||
|
return lastLogin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastLogin(Date lastLogin) {
|
||||||
|
this.lastLogin = lastLogin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getLastFailedLogin() {
|
||||||
|
return lastFailedLogin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastFailedLogin(Date lastFailedLogin) {
|
||||||
|
this.lastFailedLogin = lastFailedLogin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFailureCount() {
|
||||||
|
return failureCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFailureCount(int failureCount) {
|
||||||
|
this.failureCount = failureCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(String status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getPasswordResetOngoing() {
|
||||||
|
return passwordResetOngoing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPasswordResetOngoing(boolean passwordResetOngoing) {
|
||||||
|
this.passwordResetOngoing = passwordResetOngoing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getPasswordResetValidTo() {
|
||||||
|
return passwordResetValidTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPasswordResetValidTo(Date passwordResetValidTo) {
|
||||||
|
this.passwordResetValidTo = passwordResetValidTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPasswordResetHash() {
|
||||||
|
return passwordResetHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPasswordResetHash(String passwordResetHash) {
|
||||||
|
this.passwordResetHash = passwordResetHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreatedOn() {
|
||||||
|
return createdOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedOn(Date createdOn) {
|
||||||
|
this.createdOn = createdOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreatedBy() {
|
||||||
|
return createdBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedBy(String createdBy) {
|
||||||
|
this.createdBy = createdBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getLastUpdatedOn() {
|
||||||
|
return lastUpdatedOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastUpdatedOn(Date lastUpdatedOn) {
|
||||||
|
this.lastUpdatedOn = lastUpdatedOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastUpdatedBy() {
|
||||||
|
return lastUpdatedBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastUpdatedBy(String lastUpdatedBy) {
|
||||||
|
this.lastUpdatedBy = lastUpdatedBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlTransient
|
||||||
|
public List<RoleEntity> getRoleEntityList() {
|
||||||
|
return roleEntityList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoleEntityList(List<RoleEntity> roleEntityList) {
|
||||||
|
this.roleEntityList = roleEntityList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlTransient
|
||||||
|
public List<AccountHistoryEntity> getAccountHistoryEntityList() {
|
||||||
|
return accountHistoryEntityList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccountHistoryEntityList(List<AccountHistoryEntity> accountHistoryEntityList) {
|
||||||
|
this.accountHistoryEntityList = accountHistoryEntityList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 0;
|
||||||
|
hash += (username != null ? username.hashCode() : 0);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
// TODO: Warning - this method won't work in the case the id fields are not set
|
||||||
|
if (!(object instanceof AccountEntity)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
AccountEntity other = (AccountEntity) object;
|
||||||
|
if ((this.username == null && other.username != null) || (this.username != null && !this.username.equals(other.username))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "de.muehlencord.ssg.entity.AccountEntity[ username=" + username + " ]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,167 @@
|
|||||||
|
package de.muehlencord.shared.account.entity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.Temporal;
|
||||||
|
import javax.persistence.TemporalType;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author joern.muehlencord
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "account_history")
|
||||||
|
@XmlRootElement
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name = "AccountHistoryEntity.findAll", query = "SELECT a FROM AccountHistoryEntity a"),
|
||||||
|
@NamedQuery(name = "AccountHistoryEntity.findById", query = "SELECT a FROM AccountHistoryEntity a WHERE a.id = :id"),
|
||||||
|
@NamedQuery(name = "AccountHistoryEntity.findByMessage", query = "SELECT a FROM AccountHistoryEntity a WHERE a.message = :message"),
|
||||||
|
@NamedQuery(name = "AccountHistoryEntity.findByFailureCount", query = "SELECT a FROM AccountHistoryEntity a WHERE a.failureCount = :failureCount"),
|
||||||
|
@NamedQuery(name = "AccountHistoryEntity.findByStatus", query = "SELECT a FROM AccountHistoryEntity a WHERE a.status = :status"),
|
||||||
|
@NamedQuery(name = "AccountHistoryEntity.findByLastUpdatedOn", query = "SELECT a FROM AccountHistoryEntity a WHERE a.lastUpdatedOn = :lastUpdatedOn"),
|
||||||
|
@NamedQuery(name = "AccountHistoryEntity.findByLastUpdatedBy", query = "SELECT a FROM AccountHistoryEntity a WHERE a.lastUpdatedBy = :lastUpdatedBy")})
|
||||||
|
public class AccountHistoryEntity implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Basic(optional = false)
|
||||||
|
@Column(name = "id")
|
||||||
|
private Integer id;
|
||||||
|
@Size(max = 200)
|
||||||
|
@Column(name = "message")
|
||||||
|
private String message;
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "failure_count")
|
||||||
|
private int failureCount;
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 20)
|
||||||
|
@Column(name = "status")
|
||||||
|
private String status;
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "last_updated_on")
|
||||||
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
|
private Date lastUpdatedOn;
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 32)
|
||||||
|
@Column(name = "last_updated_by")
|
||||||
|
private String lastUpdatedBy;
|
||||||
|
@JoinColumn(name = "username", referencedColumnName = "username")
|
||||||
|
@ManyToOne(optional = false)
|
||||||
|
private AccountEntity username;
|
||||||
|
|
||||||
|
public AccountHistoryEntity() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccountHistoryEntity(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccountHistoryEntity(Integer id, int failureCount, String status, Date lastUpdatedOn, String lastUpdatedBy) {
|
||||||
|
this.id = id;
|
||||||
|
this.failureCount = failureCount;
|
||||||
|
this.status = status;
|
||||||
|
this.lastUpdatedOn = lastUpdatedOn;
|
||||||
|
this.lastUpdatedBy = lastUpdatedBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFailureCount() {
|
||||||
|
return failureCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFailureCount(int failureCount) {
|
||||||
|
this.failureCount = failureCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(String status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getLastUpdatedOn() {
|
||||||
|
return lastUpdatedOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastUpdatedOn(Date lastUpdatedOn) {
|
||||||
|
this.lastUpdatedOn = lastUpdatedOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastUpdatedBy() {
|
||||||
|
return lastUpdatedBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastUpdatedBy(String lastUpdatedBy) {
|
||||||
|
this.lastUpdatedBy = lastUpdatedBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccountEntity getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(AccountEntity username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 0;
|
||||||
|
hash += (id != null ? id.hashCode() : 0);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
// TODO: Warning - this method won't work in the case the id fields are not set
|
||||||
|
if (!(object instanceof AccountHistoryEntity)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
AccountHistoryEntity other = (AccountHistoryEntity) object;
|
||||||
|
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "de.muehlencord.ssg.entity.AccountHistoryEntity[ id=" + id + " ]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package de.muehlencord.shared.account.entity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jomu
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "config")
|
||||||
|
@XmlRootElement
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name = "ConfigEntity.findAll", query = "SELECT c FROM ConfigEntity c"),
|
||||||
|
@NamedQuery(name = "ConfigEntity.findByConfigKey", query = "SELECT c FROM ConfigEntity c WHERE c.configKey = :configKey"),
|
||||||
|
@NamedQuery(name = "ConfigEntity.findByConfigValue", query = "SELECT c FROM ConfigEntity c WHERE c.configValue = :configValue")})
|
||||||
|
public class ConfigEntity implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
@Id
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 100)
|
||||||
|
@Column(name = "config_key")
|
||||||
|
private String configKey;
|
||||||
|
@Size(max = 200)
|
||||||
|
@Column(name = "config_value")
|
||||||
|
private String configValue;
|
||||||
|
|
||||||
|
public ConfigEntity() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigEntity(String configKey) {
|
||||||
|
this.configKey = configKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConfigKey() {
|
||||||
|
return configKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfigKey(String configKey) {
|
||||||
|
this.configKey = configKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConfigValue() {
|
||||||
|
return configValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfigValue(String configValue) {
|
||||||
|
this.configValue = configValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 0;
|
||||||
|
hash += (configKey != null ? configKey.hashCode() : 0);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
// TODO: Warning - this method won't work in the case the id fields are not set
|
||||||
|
if (!(object instanceof ConfigEntity)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ConfigEntity other = (ConfigEntity) object;
|
||||||
|
if ((this.configKey == null && other.configKey != null) || (this.configKey != null && !this.configKey.equals(other.configKey))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "de.muehlencord.ssg.entity.ConfigEntity[ configKey=" + configKey + " ]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,94 @@
|
|||||||
|
package de.muehlencord.shared.account.entity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jomu
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "mail_template")
|
||||||
|
@XmlRootElement
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name = "MailTemplateEntity.findAll", query = "SELECT m FROM MailTemplateEntity m"),
|
||||||
|
@NamedQuery(name = "MailTemplateEntity.findByTemplateName", query = "SELECT m FROM MailTemplateEntity m WHERE m.templateName = :templateName"),
|
||||||
|
@NamedQuery(name = "MailTemplateEntity.findByTemplateValue", query = "SELECT m FROM MailTemplateEntity m WHERE m.templateValue = :templateValue")})
|
||||||
|
public class MailTemplateEntity implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
@Id
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 40)
|
||||||
|
@Column(name = "template_name")
|
||||||
|
private String templateName;
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 2147483647)
|
||||||
|
@Column(name = "template_value")
|
||||||
|
private String templateValue;
|
||||||
|
|
||||||
|
public MailTemplateEntity() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public MailTemplateEntity(String templateName) {
|
||||||
|
this.templateName = templateName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MailTemplateEntity(String templateName, String templateValue) {
|
||||||
|
this.templateName = templateName;
|
||||||
|
this.templateValue = templateValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTemplateName() {
|
||||||
|
return templateName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTemplateName(String templateName) {
|
||||||
|
this.templateName = templateName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTemplateValue() {
|
||||||
|
return templateValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTemplateValue(String templateValue) {
|
||||||
|
this.templateValue = templateValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 0;
|
||||||
|
hash += (templateName != null ? templateName.hashCode() : 0);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
// TODO: Warning - this method won't work in the case the id fields are not set
|
||||||
|
if (!(object instanceof MailTemplateEntity)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
MailTemplateEntity other = (MailTemplateEntity) object;
|
||||||
|
if ((this.templateName == null && other.templateName != null) || (this.templateName != null && !this.templateName.equals(other.templateName))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "de.muehlencord.ssg.entity.MailTemplateEntity[ templateName=" + templateName + " ]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,113 @@
|
|||||||
|
package de.muehlencord.shared.account.entity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.JoinTable;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
import javax.xml.bind.annotation.XmlTransient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author joern.muehlencord
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "application_permission")
|
||||||
|
@XmlRootElement
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name = "PermissionEntity.findAll", query = "SELECT p FROM PermissionEntity p"),
|
||||||
|
@NamedQuery(name = "PermissionEntity.findByPermissionName", query = "SELECT p FROM PermissionEntity p WHERE p.permissionName = :permissionName"),
|
||||||
|
@NamedQuery(name = "PermissionEntity.findByPermissionDescription", query = "SELECT p FROM PermissionEntity p WHERE p.permissionDescription = :permissionDescription")})
|
||||||
|
public class PermissionEntity implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
@Id
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 80)
|
||||||
|
@Column(name = "permission_name")
|
||||||
|
private String permissionName;
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 200)
|
||||||
|
@Column(name = "permission_description")
|
||||||
|
private String permissionDescription;
|
||||||
|
@JoinTable(name = "role_permission", joinColumns = {
|
||||||
|
@JoinColumn(name = "permission_name", referencedColumnName = "permission_name")}, inverseJoinColumns = {
|
||||||
|
@JoinColumn(name = "role_name", referencedColumnName = "role_name")})
|
||||||
|
@ManyToMany
|
||||||
|
private List<RoleEntity> roleEntityList;
|
||||||
|
|
||||||
|
public PermissionEntity() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public PermissionEntity(String permissionName) {
|
||||||
|
this.permissionName = permissionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PermissionEntity(String permissionName, String permissionDescription) {
|
||||||
|
this.permissionName = permissionName;
|
||||||
|
this.permissionDescription = permissionDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPermissionName() {
|
||||||
|
return permissionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPermissionName(String permissionName) {
|
||||||
|
this.permissionName = permissionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPermissionDescription() {
|
||||||
|
return permissionDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPermissionDescription(String permissionDescription) {
|
||||||
|
this.permissionDescription = permissionDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlTransient
|
||||||
|
public List<RoleEntity> getRoleEntityList() {
|
||||||
|
return roleEntityList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoleEntityList(List<RoleEntity> roleEntityList) {
|
||||||
|
this.roleEntityList = roleEntityList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 0;
|
||||||
|
hash += (permissionName != null ? permissionName.hashCode() : 0);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
// TODO: Warning - this method won't work in the case the id fields are not set
|
||||||
|
if (!(object instanceof PermissionEntity)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PermissionEntity other = (PermissionEntity) object;
|
||||||
|
if ((this.permissionName == null && other.permissionName != null) || (this.permissionName != null && !this.permissionName.equals(other.permissionName))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "de.muehlencord.ssg.entity.PermissionEntity[ permissionName=" + permissionName + " ]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,119 @@
|
|||||||
|
package de.muehlencord.shared.account.entity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
import javax.xml.bind.annotation.XmlTransient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author joern.muehlencord
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "application_role")
|
||||||
|
@XmlRootElement
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name = "RoleEntity.findAll", query = "SELECT r FROM RoleEntity r"),
|
||||||
|
@NamedQuery(name = "RoleEntity.findByRoleName", query = "SELECT r FROM RoleEntity r WHERE r.roleName = :roleName"),
|
||||||
|
@NamedQuery(name = "RoleEntity.findByRoleDescription", query = "SELECT r FROM RoleEntity r WHERE r.roleDescription = :roleDescription")})
|
||||||
|
public class RoleEntity implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
@Id
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 80)
|
||||||
|
@Column(name = "role_name")
|
||||||
|
private String roleName;
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 200)
|
||||||
|
@Column(name = "role_description")
|
||||||
|
private String roleDescription;
|
||||||
|
@ManyToMany(mappedBy = "roleEntityList")
|
||||||
|
private List<AccountEntity> accountEntityList;
|
||||||
|
@ManyToMany(mappedBy = "roleEntityList")
|
||||||
|
private List<PermissionEntity> permissionEntityList;
|
||||||
|
|
||||||
|
public RoleEntity() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoleEntity(String roleName) {
|
||||||
|
this.roleName = roleName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoleEntity(String roleName, String roleDescription) {
|
||||||
|
this.roleName = roleName;
|
||||||
|
this.roleDescription = roleDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRoleName() {
|
||||||
|
return roleName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoleName(String roleName) {
|
||||||
|
this.roleName = roleName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRoleDescription() {
|
||||||
|
return roleDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoleDescription(String roleDescription) {
|
||||||
|
this.roleDescription = roleDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlTransient
|
||||||
|
public List<AccountEntity> getAccountEntityList() {
|
||||||
|
return accountEntityList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccountEntityList(List<AccountEntity> accountEntityList) {
|
||||||
|
this.accountEntityList = accountEntityList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlTransient
|
||||||
|
public List<PermissionEntity> getPermissionEntityList() {
|
||||||
|
return permissionEntityList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPermissionEntityList(List<PermissionEntity> permissionEntityList) {
|
||||||
|
this.permissionEntityList = permissionEntityList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 0;
|
||||||
|
hash += (roleName != null ? roleName.hashCode() : 0);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
// TODO: Warning - this method won't work in the case the id fields are not set
|
||||||
|
if (!(object instanceof RoleEntity)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
RoleEntity other = (RoleEntity) object;
|
||||||
|
if ((this.roleName == null && other.roleName != null) || (this.roleName != null && !this.roleName.equals(other.roleName))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "de.muehlencord.ssg.entity.RoleEntity[ roleName=" + roleName + " ]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package de.muehlencord.shared.account.util;
|
||||||
|
|
||||||
|
import org.apache.log4j.Level;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.apache.shiro.authc.credential.DefaultPasswordService;
|
||||||
|
import org.apache.shiro.crypto.hash.DefaultHashService;
|
||||||
|
import org.apache.shiro.crypto.hash.Sha512Hash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jomu
|
||||||
|
*/
|
||||||
|
public class SecurityUtil {
|
||||||
|
|
||||||
|
private final static Logger LOGGER = Logger.getLogger (SecurityUtil.class.getName());
|
||||||
|
|
||||||
|
public static String createPassword(String clearTextPassword) {
|
||||||
|
// TODO read values from shiro.ini
|
||||||
|
DefaultHashService hashService = new DefaultHashService();
|
||||||
|
hashService.setHashIterations(500000); //
|
||||||
|
hashService.setHashAlgorithmName(Sha512Hash.ALGORITHM_NAME);
|
||||||
|
hashService.setGeneratePublicSalt(true);
|
||||||
|
|
||||||
|
DefaultPasswordService passwordService = new DefaultPasswordService();
|
||||||
|
passwordService.setHashService(hashService);
|
||||||
|
|
||||||
|
// try to encrypt password
|
||||||
|
String encryptedPassword = passwordService.encryptPassword(clearTextPassword);
|
||||||
|
LOGGER.log (Level.TRACE, encryptedPassword);
|
||||||
|
return encryptedPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
2
account/src/main/resources/META-INF/MANIFEST.MF
Normal file
2
account/src/main/resources/META-INF/MANIFEST.MF
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
|
||||||
Reference in New Issue
Block a user