introduced account based configuration
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,3 +8,4 @@
|
|||||||
/shiro-faces/target/
|
/shiro-faces/target/
|
||||||
/pdf/target/
|
/pdf/target/
|
||||||
/shared-poi-util/target/
|
/shared-poi-util/target/
|
||||||
|
/account/nb-configuration.xml
|
||||||
@ -3,7 +3,7 @@
|
|||||||
CAUTION: Do not modify this file unless you know what you are doing.
|
CAUTION: Do not modify this file unless you know what you are doing.
|
||||||
Unexpected results may occur if the code is changed deliberately.
|
Unexpected results may occur if the code is changed deliberately.
|
||||||
-->
|
-->
|
||||||
<dbmodel pgmodeler-ver="0.9.1" author="Joern Muehlencord" last-position="773,0" last-zoom="0.85"
|
<dbmodel pgmodeler-ver="0.9.1" author="Joern Muehlencord" last-position="37,0" last-zoom="0.85"
|
||||||
default-schema="public" default-owner="postgres">
|
default-schema="public" default-owner="postgres">
|
||||||
<database name="account_test" encoding="UTF8" lc-collate="German_Germany.1252" lc-ctype="German_Germany.1252" is-template="false" allow-conns="true" sql-disabled="true">
|
<database name="account_test" encoding="UTF8" lc-collate="German_Germany.1252" lc-ctype="German_Germany.1252" is-template="false" allow-conns="true" sql-disabled="true">
|
||||||
</database>
|
</database>
|
||||||
@ -17,17 +17,17 @@ CAUTION: Do not modify this file unless you know what you are doing.
|
|||||||
<column name="config_key" not-null="true">
|
<column name="config_key" not-null="true">
|
||||||
<type name="varchar" length="100"/>
|
<type name="varchar" length="100"/>
|
||||||
</column>
|
</column>
|
||||||
|
<column name="config_key_account" not-null="true">
|
||||||
|
<type name="uuid" length="0"/>
|
||||||
|
</column>
|
||||||
<column name="config_key_group">
|
<column name="config_key_group">
|
||||||
<type name="varchar" length="200"/>
|
<type name="varchar" length="200"/>
|
||||||
</column>
|
</column>
|
||||||
<column name="config_key_account">
|
|
||||||
<type name="uuid" length="0"/>
|
|
||||||
</column>
|
|
||||||
<column name="config_value">
|
<column name="config_value">
|
||||||
<type name="varchar" length="200"/>
|
<type name="varchar" length="200"/>
|
||||||
</column>
|
</column>
|
||||||
<constraint name="config_pk" type="pk-constr" table="public.config">
|
<constraint name="config_pk" type="pk-constr" table="public.config">
|
||||||
<columns names="config_key" ref-type="src-columns"/>
|
<columns names="config_key,config_key_account" ref-type="src-columns"/>
|
||||||
</constraint>
|
</constraint>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
-- config
|
|
||||||
INSERT INTO config (config_key, config_value) VALUES ('account.maxFailedLogins', '5');
|
|
||||||
|
|
||||||
-- application configuration
|
-- application configuration
|
||||||
INSERT INTO application_permission (id, permission_name, permission_description) values ('dfd0f8f1-4a51-4fdc-9a1c-a942bee9b649', 'test:view', 'Display test view');
|
INSERT INTO application_permission (id, permission_name, permission_description) values ('dfd0f8f1-4a51-4fdc-9a1c-a942bee9b649', 'test:view', 'Display test view');
|
||||||
@ -7,5 +5,14 @@ INSERT INTO application_role (id, role_name, role_description) values ('5cd0aca0
|
|||||||
INSERT INTO application_role (id, role_name, role_description) values ('da30060e-fd23-4016-a506-4e12e9322148', 'User', 'Standard user role');
|
INSERT INTO application_role (id, role_name, role_description) values ('da30060e-fd23-4016-a506-4e12e9322148', 'User', 'Standard user role');
|
||||||
|
|
||||||
-- account
|
-- account
|
||||||
|
INSERT INTO account (id, username, firstname, lastname, emailaddress, account_password, created_by, last_updated_by) values ('2a712ed4-30f8-47b4-a002-7d87441b7013', 'system', 'system', 'system', 'n/a', 'n/a', 'system', 'system');
|
||||||
INSERT INTO account (id, username, emailaddress, firstname, lastname, account_password, created_by, last_updated_by) values('ab5c8337-6872-4aea-a9b9-78ea63706b8f','admin', 'joern@muehlencord.de', 'Joern', 'Muehlencord','$shiro1$SHA-256$500000$4bHPNH9k539UjdFLgm/HOA==$T/n8skgoGSOtNw/c9ScDlXCiGrx2cZF0Esrvf6WPq6g=', 'admin','admin'); --admin/secret
|
INSERT INTO account (id, username, emailaddress, firstname, lastname, account_password, created_by, last_updated_by) values('ab5c8337-6872-4aea-a9b9-78ea63706b8f','admin', 'joern@muehlencord.de', 'Joern', 'Muehlencord','$shiro1$SHA-256$500000$4bHPNH9k539UjdFLgm/HOA==$T/n8skgoGSOtNw/c9ScDlXCiGrx2cZF0Esrvf6WPq6g=', 'admin','admin'); --admin/secret
|
||||||
INSERT INTO account_role (account, account_role) values ('ab5c8337-6872-4aea-a9b9-78ea63706b8f', '5cd0aca0-5466-483d-8f3e-c369f8061131');
|
INSERT INTO account_role (account, account_role) values ('ab5c8337-6872-4aea-a9b9-78ea63706b8f', '5cd0aca0-5466-483d-8f3e-c369f8061131');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- config
|
||||||
|
INSERT INTO config (config_key, config_key_account, config_value) VALUES ('account.maxFailedLogins', '2a712ed4-30f8-47b4-a002-7d87441b7013', '5');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import de.muehlencord.shared.account.business.mail.entity.MailException;
|
|||||||
import de.muehlencord.shared.account.business.mail.boundary.MailService;
|
import de.muehlencord.shared.account.business.mail.boundary.MailService;
|
||||||
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||||
import de.muehlencord.shared.account.business.account.entity.ApplicationRoleEntity;
|
import de.muehlencord.shared.account.business.account.entity.ApplicationRoleEntity;
|
||||||
|
import de.muehlencord.shared.account.business.config.entity.ConfigException;
|
||||||
import de.muehlencord.shared.account.util.SecurityUtil;
|
import de.muehlencord.shared.account.util.SecurityUtil;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -254,25 +255,33 @@ public class AccountControl implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addLoginError(AccountEntity account) {
|
public void addLoginError(AccountEntity account) {
|
||||||
Date now = new Date(); // TODO now in UTC
|
try {
|
||||||
account.setLastFailedLogin(now);
|
Date now = new Date(); // TODO now in UTC
|
||||||
account.setFailureCount(account.getFailureCount() + 1);
|
account.setLastFailedLogin(now);
|
||||||
|
account.setFailureCount(account.getFailureCount() + 1);
|
||||||
|
|
||||||
int maxFailedLogins = configService.getMaxFailedLogins();
|
int maxFailedLogins = Integer.parseInt(configService.getConfigValue("account.maxFailedLogins"));
|
||||||
if ((account.getFailureCount() >= maxFailedLogins) && (!account.getStatus().equals("LOCKED"))) { // TOD add status enum
|
if ((account.getFailureCount() >= maxFailedLogins) && (!account.getStatus().equals("LOCKED"))) { // TOD add status enum
|
||||||
// max failed logins reached, disabling user
|
// max failed logins reached, disabling user
|
||||||
LOGGER.info("Locking account " + account.getUsername() + " due to " + account.getFailureCount() + " failed logins");
|
LOGGER.info("Locking account " + account.getUsername() + " due to " + account.getFailureCount() + " failed logins");
|
||||||
account.setStatus(AccountStatus.BLOCKED.name());
|
account.setStatus(AccountStatus.BLOCKED.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
} catch (ConfigException ex) {
|
||||||
|
if (LOGGER.isDebugEnabled()) {
|
||||||
|
LOGGER.debug(ex.toString(), ex);
|
||||||
|
} else {
|
||||||
|
LOGGER.error(ex.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package de.muehlencord.shared.account.business.account.entity;
|
package de.muehlencord.shared.account.business.account.entity;
|
||||||
|
|
||||||
|
import de.muehlencord.shared.account.business.config.entity.ConfigEntity;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -149,6 +150,10 @@ public class AccountEntity implements Serializable, Account {
|
|||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AccountEntity (String name) {
|
||||||
|
this.username = name;
|
||||||
|
}
|
||||||
|
|
||||||
public AccountEntity(UUID id, String username, String emailaddress, String firstname, String lastname, String accountPassword, int failureCount, String status, boolean passwordResetOngoing, Date createdOn, String createdBy, Date lastUpdatedOn, String lastUpdatedBy) {
|
public AccountEntity(UUID id, String username, String emailaddress, String firstname, String lastname, String accountPassword, int failureCount, String status, boolean passwordResetOngoing, Date createdOn, String createdBy, Date lastUpdatedOn, String lastUpdatedBy) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.username = username;
|
this.username = username;
|
||||||
|
|||||||
@ -1,12 +1,21 @@
|
|||||||
package de.muehlencord.shared.account.business.config.boundary;
|
package de.muehlencord.shared.account.business.config.boundary;
|
||||||
|
|
||||||
|
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||||
import de.muehlencord.shared.account.business.config.entity.ConfigEntity;
|
import de.muehlencord.shared.account.business.config.entity.ConfigEntity;
|
||||||
|
import de.muehlencord.shared.account.business.config.entity.ConfigEntityPK;
|
||||||
|
import de.muehlencord.shared.account.business.config.entity.ConfigException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.ejb.Lock;
|
||||||
|
import javax.ejb.LockType;
|
||||||
import javax.ejb.Singleton;
|
import javax.ejb.Singleton;
|
||||||
import javax.ejb.Startup;
|
import javax.ejb.Startup;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.Query;
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -21,46 +30,142 @@ public class ConfigService implements Serializable {
|
|||||||
@Inject
|
@Inject
|
||||||
EntityManager em;
|
EntityManager em;
|
||||||
|
|
||||||
private String storagePath = null;
|
// private String storagePath = null;
|
||||||
private int maxFailedLogins = 5;
|
// private int maxFailedLogins = 5;
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
ConfigEntity configEntity = em.find(ConfigEntity.class, "storage.path");
|
// ConfigEntity configEntity = em.find(ConfigEntity.class, "storage.path");
|
||||||
if (configEntity != null) {
|
// if (configEntity != null) {
|
||||||
this.storagePath = configEntity.getConfigValue();
|
// this.storagePath = configEntity.getConfigValue();
|
||||||
}
|
// }
|
||||||
configEntity = em.find(ConfigEntity.class, "account.maxFailedLogins");
|
// configEntity = em.find(ConfigEntity.class, "account.maxFailedLogins");
|
||||||
if (configEntity != null) {
|
// if (configEntity != null) {
|
||||||
this.maxFailedLogins = Integer.parseInt(configEntity.getConfigValue());
|
// this.maxFailedLogins = Integer.parseInt(configEntity.getConfigValue());
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns global config key which is not assigned to any. If more than one
|
||||||
|
* value is defined for the given key, the key assigned to system is
|
||||||
|
* returned. If more than one key is defined but system key is not defined,
|
||||||
|
* an exception is thrown.
|
||||||
|
*
|
||||||
|
* @param configKey the key to return
|
||||||
|
* @return the configValue belonging to the given configKey
|
||||||
|
* @throws
|
||||||
|
* de.muehlencord.shared.account.business.config.entity.ConfigException if
|
||||||
|
* more than one value is defined for the given key but none of the values
|
||||||
|
* is defined for the system user
|
||||||
|
*/
|
||||||
|
public String getConfigValue(String configKey) throws ConfigException {
|
||||||
|
Query query = em.createNamedQuery("ConfigEntity.findByConfigKey");
|
||||||
|
query.setParameter("configKey", configKey);
|
||||||
|
List<ConfigEntity> configList = query.getResultList();
|
||||||
|
if ((configList == null) || (configList.isEmpty())) {
|
||||||
|
// key is not found in the database at all
|
||||||
|
return null;
|
||||||
|
} else if (configList.size() == 1) {
|
||||||
|
// exact one element found, return this one
|
||||||
|
return configList.get(0).getConfigValue();
|
||||||
|
} else {
|
||||||
|
// if more than one result found, return the one which is assigned to system if present
|
||||||
|
// if not present, throw exception
|
||||||
|
Optional<ConfigEntity> firstItem = configList.stream()
|
||||||
|
.filter(config -> config.getConfigPK().getConfigKeyAccount().getUsername().equals("system"))
|
||||||
|
.findFirst();
|
||||||
|
if (firstItem.isPresent()) {
|
||||||
|
return firstItem.get().getConfigValue();
|
||||||
|
} else {
|
||||||
|
throw new ConfigException("ConfigKey " + configKey + " not unique and system value not defined");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getConfigValue(String configKey) {
|
public String getConfigValue(String configKey, AccountEntity account) throws ConfigException {
|
||||||
ConfigEntity configEntity = em.find(ConfigEntity.class, configKey);
|
Query query = em.createNamedQuery("ConfigEntity.findByConfigKeyAndAccount");
|
||||||
return (configEntity == null ? null : configEntity.getConfigValue());
|
query.setParameter("configKey", configKey);
|
||||||
|
query.setParameter("configKeyAccount", account);
|
||||||
|
List<ConfigEntity> configList = query.getResultList();
|
||||||
|
if ((configList == null) || (configList.isEmpty())) {
|
||||||
|
// key is not found in the database at all
|
||||||
|
return null;
|
||||||
|
} else if (configList.size() == 1) {
|
||||||
|
// exact one element found, return this one
|
||||||
|
return configList.get(0).getConfigValue();
|
||||||
|
} else {
|
||||||
|
// more than one value must not happen - this is not possible per the defintion of the datamodel
|
||||||
|
throw new ConfigException("Cannot have more than one value for the the given key " + configKey + " and the given account " + account.getUsername());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Lock(LockType.WRITE)
|
||||||
|
public boolean updateConfigValue(String configKey, String accountName, String configValue) {
|
||||||
|
if ((configKey == null) || (configKey.equals ("")) || (configValue == null) || (configValue.equals (""))) {
|
||||||
|
// null or empty key / values are not possible
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
AccountEntity account;
|
||||||
|
if (accountName == null) {
|
||||||
|
account = getAccount("system");
|
||||||
|
} else {
|
||||||
|
account = getAccount(accountName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (account == null) {
|
||||||
|
// must not happen we have no account - if accountName is null, then the system account has to be used
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigEntityPK pk = new ConfigEntityPK(configKey, account);
|
||||||
|
ConfigEntity currentEntity = em.find(ConfigEntity.class, pk);
|
||||||
|
if (currentEntity == null) {
|
||||||
|
currentEntity = new ConfigEntity(pk);
|
||||||
|
currentEntity.setConfigValue(configValue);
|
||||||
|
em.persist(currentEntity);
|
||||||
|
return true; // config item created - udpate performed
|
||||||
|
} else {
|
||||||
|
if ((currentEntity.getConfigValue() != null) && (currentEntity.getConfigValue().equals(configValue))) {
|
||||||
|
// value is the same - no update
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
currentEntity.setConfigValue(configValue);
|
||||||
|
em.merge(currentEntity);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private AccountEntity getAccount(String accountName) {
|
||||||
|
Query query = em.createNamedQuery("AccountEntity.findByUsername");
|
||||||
|
query.setParameter("username", accountName);
|
||||||
|
List<AccountEntity> accountList = query.getResultList();
|
||||||
|
if ((accountList == null) || (accountList.isEmpty())) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return accountList.get(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* *** getter *** */
|
/* *** getter *** */
|
||||||
/**
|
/**
|
||||||
* FIXME remove, this is application specific
|
* FIXME remove, this is application specific
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* @deprecated replace by getConfigValue ("storage.path")
|
* @deprecated replace by getConfigValue ("storage.path")
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
// @Deprecated
|
||||||
public String getStoragePath() {
|
// public String getStoragePath() {
|
||||||
return storagePath;
|
// return storagePath;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* // TODO move to accountControl
|
* // TODO move to accountControl
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* @deprecated replace by getConfigValue ("account.maxFailedLogins")
|
* @deprecated replace by getConfigValue ("account.maxFailedLogins")
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
// @Deprecated
|
||||||
public int getMaxFailedLogins() {
|
// public int getMaxFailedLogins() {
|
||||||
return maxFailedLogins;
|
// return maxFailedLogins;
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* 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.business.config.entity;
|
package de.muehlencord.shared.account.business.config.entity;
|
||||||
|
|
||||||
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import javax.persistence.Basic;
|
|
||||||
import javax.persistence.Cacheable;
|
import javax.persistence.Cacheable;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.EmbeddedId;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.Id;
|
|
||||||
import javax.persistence.JoinColumn;
|
|
||||||
import javax.persistence.ManyToOne;
|
|
||||||
import javax.persistence.NamedQueries;
|
import javax.persistence.NamedQueries;
|
||||||
import javax.persistence.NamedQuery;
|
import javax.persistence.NamedQuery;
|
||||||
import javax.persistence.QueryHint;
|
import javax.persistence.QueryHint;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import javax.validation.constraints.Size;
|
import javax.validation.constraints.Size;
|
||||||
import javax.xml.bind.annotation.XmlRootElement;
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
import org.hibernate.annotations.Cache;
|
import org.hibernate.annotations.Cache;
|
||||||
@ -21,7 +22,7 @@ import org.hibernate.annotations.CacheConcurrencyStrategy;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author joern.muehlencord
|
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "config")
|
@Table(name = "config")
|
||||||
@ -29,11 +30,15 @@ import org.hibernate.annotations.CacheConcurrencyStrategy;
|
|||||||
@Cacheable(true)
|
@Cacheable(true)
|
||||||
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL, region = "Configuration")
|
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL, region = "Configuration")
|
||||||
@NamedQueries({
|
@NamedQueries({
|
||||||
@NamedQuery(name = "ConfigEntity.findAll", query = "SELECT c FROM ConfigEntity c ORDER BY c.configKey",
|
@NamedQuery(name = "ConfigEntity.findAll", query = "SELECT c FROM ConfigEntity c ORDER BY c.configPK.configKey",
|
||||||
hints = {
|
hints = {
|
||||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
||||||
@NamedQuery(name = "ConfigEntity.findByConfigKey", query = "SELECT c FROM ConfigEntity c WHERE c.configKey = :configKey",
|
@NamedQuery(name = "ConfigEntity.findByConfigKey", query = "SELECT c FROM ConfigEntity c WHERE c.configPK.configKey = :configKey",
|
||||||
|
hints = {
|
||||||
|
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||||
|
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
||||||
|
@NamedQuery(name = "ConfigEntity.findByConfigKeyAndAccount", query = "SELECT c FROM ConfigEntity c WHERE c.configPK.configKey = :configKey AND c.configPK.configKeyAccount = :account",
|
||||||
hints = {
|
hints = {
|
||||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
||||||
@ -47,58 +52,32 @@ public class ConfigEntity implements Serializable {
|
|||||||
|
|
||||||
private static final long serialVersionUID = -2013982316933782223L;
|
private static final long serialVersionUID = -2013982316933782223L;
|
||||||
|
|
||||||
@Id
|
@EmbeddedId
|
||||||
@Basic(optional = false)
|
protected ConfigEntityPK configPK;
|
||||||
@NotNull
|
|
||||||
@Size(min = 1, max = 100)
|
|
||||||
@Column(name = "config_key")
|
|
||||||
private String configKey;
|
|
||||||
@Basic(optional = true)
|
|
||||||
@Size(min = 1, max = 200)
|
|
||||||
@Column(name = "config_key_group")
|
|
||||||
private String configKeyGroup;
|
|
||||||
@JoinColumn(name = "config_key_account", referencedColumnName = "id")
|
|
||||||
@ManyToOne(optional = true)
|
|
||||||
private AccountEntity configKeyAccount;
|
|
||||||
|
|
||||||
@Size(max = 200)
|
@Size(max = 200)
|
||||||
@Column(name = "config_value")
|
@Column(name = "config_value")
|
||||||
private String configValue;
|
private String configValue;
|
||||||
|
@Size(max = 200)
|
||||||
|
@Column(name = "config_key_group")
|
||||||
|
private String configKeyGroup;
|
||||||
|
|
||||||
public ConfigEntity() {
|
public ConfigEntity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigEntity(String configKey) {
|
public ConfigEntity(String configKey, AccountEntity account) {
|
||||||
this.configKey = configKey;
|
this.configPK = new ConfigEntityPK(configKey, account);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigEntity(String configKey, String configValue) {
|
public ConfigEntity(ConfigEntityPK configPK) {
|
||||||
this.configKey = configKey;
|
this.configPK = configPK;
|
||||||
this.configValue = configValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getConfigKey() {
|
public ConfigEntityPK getConfigPK() {
|
||||||
return configKey;
|
return configPK;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setConfigKey(String configKey) {
|
public void setConfigPK(ConfigEntityPK configPK) {
|
||||||
this.configKey = configKey;
|
this.configPK = configPK;
|
||||||
}
|
|
||||||
|
|
||||||
public String getConfigKeyGroup() {
|
|
||||||
return configKeyGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setConfigKeyGroup(String configKeyGroup) {
|
|
||||||
this.configKeyGroup = configKeyGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AccountEntity getConfigKeyAccount() {
|
|
||||||
return configKeyAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setConfigKeyAccount(AccountEntity configKeyAccount) {
|
|
||||||
this.configKeyAccount = configKeyAccount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getConfigValue() {
|
public String getConfigValue() {
|
||||||
@ -109,10 +88,18 @@ public class ConfigEntity implements Serializable {
|
|||||||
this.configValue = configValue;
|
this.configValue = configValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getConfigKeyGroup() {
|
||||||
|
return configKeyGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfigKeyGroup(String configKeyGroup) {
|
||||||
|
this.configKeyGroup = configKeyGroup;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int hash = 0;
|
int hash = 0;
|
||||||
hash += (configKey != null ? configKey.hashCode() : 0);
|
hash += (configPK != null ? configPK.hashCode() : 0);
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +110,7 @@ public class ConfigEntity implements Serializable {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ConfigEntity other = (ConfigEntity) object;
|
ConfigEntity other = (ConfigEntity) object;
|
||||||
if ((this.configKey == null && other.configKey != null) || (this.configKey != null && !this.configKey.equals(other.configKey))) {
|
if ((this.configPK == null && other.configPK != null) || (this.configPK != null && !this.configPK.equals(other.configPK))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -131,7 +118,7 @@ public class ConfigEntity implements Serializable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "de.muehlencord.shared.account.entity.Config[ configKey=" + configKey + " ]";
|
return "de.muehlencord.shared.account.business.config.entity.Config[ configPK=" + configPK + " ]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* 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.business.config.entity;
|
||||||
|
|
||||||
|
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||||
|
*/
|
||||||
|
@Embeddable
|
||||||
|
public class ConfigEntityPK implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 8133795368429249008L;
|
||||||
|
|
||||||
|
@Basic(optional = false)
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 100)
|
||||||
|
@Column(name = "config_key")
|
||||||
|
private String configKey;
|
||||||
|
@JoinColumn(name = "config_key_account", referencedColumnName = "id")
|
||||||
|
@ManyToOne(optional = false)
|
||||||
|
private AccountEntity configKeyAccount;
|
||||||
|
|
||||||
|
public ConfigEntityPK() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigEntityPK(String configKey, AccountEntity configKeyAccount) {
|
||||||
|
this.configKey = configKey;
|
||||||
|
this.configKeyAccount = configKeyAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConfigKey() {
|
||||||
|
return configKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfigKey(String configKey) {
|
||||||
|
this.configKey = configKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccountEntity getConfigKeyAccount() {
|
||||||
|
return configKeyAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfigKeyAccount(AccountEntity configKeyAccount) {
|
||||||
|
this.configKeyAccount = configKeyAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 0;
|
||||||
|
hash += (configKey != null ? configKey.hashCode() : 0);
|
||||||
|
hash += (configKeyAccount != null ? configKeyAccount.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 ConfigEntityPK)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ConfigEntityPK other = (ConfigEntityPK) object;
|
||||||
|
if ((this.configKey == null && other.configKey != null) || (this.configKey != null && !this.configKey.equals(other.configKey))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((this.configKeyAccount == null && other.configKeyAccount != null) || (this.configKeyAccount != null && !this.configKeyAccount.equals(other.configKeyAccount))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "de.muehlencord.shared.account.business.config.entity.ConfigPK[ configKey=" + configKey + ", configKeyAccount=" + configKeyAccount + " ]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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.business.config.entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||||
|
*/
|
||||||
|
public class ConfigException extends Exception {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 7246584814637280123L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance of <code>ConfigException</code> without detail
|
||||||
|
* message.
|
||||||
|
*/
|
||||||
|
public ConfigException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance of <code>ConfigException</code> with the specified
|
||||||
|
* detail message.
|
||||||
|
*
|
||||||
|
* @param msg the detail message.
|
||||||
|
*/
|
||||||
|
public ConfigException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance of <code>ConfigException</code> with the specified
|
||||||
|
* detail message and root cause.
|
||||||
|
*
|
||||||
|
* @param msg the detail message.
|
||||||
|
* @param th the root cause
|
||||||
|
*/
|
||||||
|
public ConfigException(String msg, Throwable th) {
|
||||||
|
super(msg, th);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,12 +1,13 @@
|
|||||||
|
|
||||||
package de.muehlencord.shared.account.business.config.boundary;
|
package de.muehlencord.shared.account.business.config.boundary;
|
||||||
|
|
||||||
import de.muehlencord.shared.account.business.config.boundary.ConfigService;
|
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||||
import de.muehlencord.shared.account.business.config.entity.ConfigEntity;
|
import de.muehlencord.shared.account.business.config.entity.ConfigEntity;
|
||||||
|
import de.muehlencord.shared.account.business.config.entity.ConfigEntityPK;
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.InjectMocks;
|
import org.mockito.InjectMocks;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
@ -28,15 +29,19 @@ public class ConfigServiceTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void init() {
|
public void init() {
|
||||||
ConfigEntity configEntity = new ConfigEntity ("account.maxFailedLogins");
|
AccountEntity account = new AccountEntity ("system");
|
||||||
|
ConfigEntityPK pk = new ConfigEntityPK("account.maxFailedLogins", account);
|
||||||
|
ConfigEntity configEntity = new ConfigEntity (pk);
|
||||||
configEntity.setConfigValue("7");
|
configEntity.setConfigValue("7");
|
||||||
when (entityManagerMock.find(ConfigEntity.class, "account.maxFailedLogins")).thenReturn (configEntity);
|
when (entityManagerMock.find(ConfigEntity.class, "account.maxFailedLogins")).thenReturn (configEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Ignore
|
||||||
|
// TODO move to account test
|
||||||
public void testGetMaxFailedLogins() {
|
public void testGetMaxFailedLogins() {
|
||||||
configService.init();
|
configService.init();
|
||||||
assertEquals ("maxFailedLogins", 7, configService.getMaxFailedLogins());
|
// assertEquals ("maxFailedLogins", 7, configService.getMaxFailedLogins());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user