UserRepositoryImpl.java
package com.tradecloud.repository.user;
import com.tradecloud.authentication.Role;
import com.tradecloud.authentication.User;
import com.tradecloud.authentication.UserInfo;
import com.tradecloud.domain.party.Employee;
import com.tradecloud.domain.party.base.Contact;
import com.tradecloud.domain.place.Region;
import com.tradecloud.repository.base.impl.RepositoryBaseImpl;
import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.query.NativeQuery;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.Query;
import javax.persistence.criteria.*;
import java.util.*;
/**
* User Repository.
* Note the SessionFactory used here is hard coded for the 'tradecloud'
* database.
* This is wired directly into the Spring security classes to be used for login.
* ALso used by our UserService for other user actions.
*/
@Repository(value = "userRepository")
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_UNCOMMITTED)
public class UserRepositoryImpl extends RepositoryBaseImpl<User, Object> implements UserRepository, UserDetailsService {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(UserRepositoryImpl.class);
/**
* Method need to satisfy Spring security interface.
*/
@Override
public UserDetails loadUserByUsername(String username) {
return findByUsername(username);
}
/**
* Scan through the users list and pick out any of the users with a role
* matching the one we're interested in.
*
* @param currentRole
* @return
*/
@Override
public List<User> findUsersInRole(String currentRole) {
Role searchRole = new Role(currentRole);
List<User> allUsers = super.findAll();
List<User> matchedUsers = new ArrayList<User>();
for (User user : allUsers) {
if (user.getRoles().contains(searchRole)) {
matchedUsers.add(user);
}
}
return matchedUsers;
}
@Override
public User findByUsername(String username) {
CriteriaBuilder criteriaBuilder = getSession().getCriteriaBuilder();
CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class);
Root<User> c = criteriaQuery.from(User.class);
criteriaQuery = criteriaQuery.select(c).where(criteriaBuilder.equal(c.get("username"), username));
org.hibernate.query.Query<User> q = getSession().createQuery(criteriaQuery);
return q.uniqueResult();
}
@Override
public User findByEmail(String email) {
CriteriaBuilder criteriaBuilder = getSession().getCriteriaBuilder();
CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class);
Root<User> c = criteriaQuery.from(User.class);
criteriaQuery = criteriaQuery.select(c).where(criteriaBuilder.equal(c.get("userInfo").get("email"), email));
org.hibernate.query.Query<User> q = getSession().createQuery(criteriaQuery);
return q.uniqueResult();
}
@Override
public User findByContact(Contact contact) {
CriteriaBuilder criteriaBuilder = getSession().getCriteriaBuilder();
CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class);
Root<User> c = criteriaQuery.from(User.class);
criteriaQuery = criteriaQuery.select(c).where(criteriaBuilder.equal(c.get("contact"), contact));
org.hibernate.query.Query<User> q = getSession().createQuery(criteriaQuery);
return q.uniqueResult();
}
@Override
public User findByEmployee(Employee employee) {
CriteriaBuilder criteriaBuilder = getSession().getCriteriaBuilder();
CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class);
Root<User> c = criteriaQuery.from(User.class);
criteriaQuery = criteriaQuery.select(c).where(criteriaBuilder.equal(c.get("employee"), employee));
org.hibernate.query.Query<User> q = getSession().createQuery(criteriaQuery);
return q.uniqueResult();
}
@Override
public List<User> findUserByEmailAddress(String emailAddress, boolean caseSensitive) {
CriteriaBuilder criteriaBuilder = getSession().getCriteriaBuilder();
CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class);
Root<User> root = criteriaQuery.from(User.class);
Join<User, UserInfo> childJoin = root.join("userInfo");
Path<String> emailPath = childJoin.get("email");
Predicate predicate = caseSensitive
? criteriaBuilder.equal(emailPath, emailAddress)
: criteriaBuilder.equal(criteriaBuilder.lower(emailPath), emailAddress.toLowerCase());
criteriaQuery.where(predicate);
org.hibernate.query.Query<User> query = getSession().createQuery(criteriaQuery);
return query.list();
}
private void updateIncorrectLoginAttemps(String username, int val) {
String update = "";
if (val == 0) {
update = "UPDATE User SET lastlogindate = now(), incorrectLoginAttempts = :incorrectLoginAttempts WHERE username=:username";
} else {
update = "UPDATE User u SET u.incorrectLoginAttempts = :incorrectLoginAttempts WHERE u.username=:username";
}
javax.persistence.Query query = getSessionCustom().createQuery(update);
query.setParameter("incorrectLoginAttempts", val);
query.setParameter("username", username);
query.executeUpdate();
}
@Override
public void clearIncorrectLoginAttempts(String username) {
updateIncorrectLoginAttemps(username, 0);
}
@Override
public void incrementIncorrectLoginAttempts(String username) {
String update = "SELECT u.incorrectLoginAttempts from User u WHERE u.username=:username";
Query query = getSessionCustom().createQuery(update);
query.setParameter("username", username);
List list = query.getResultList();
// If the user didn't exist
if (list != null && !list.isEmpty()) {
updateIncorrectLoginAttemps(username, ((Integer) list.get(0)) + 1);
}
}
@Override
public Date findUserPasswordChangeDate(Long userId) {
String update = "SELECT u.passwordChangedDate from User u WHERE u.id=:id";
Query query = getSessionCustom().createQuery(update);
query.setParameter("id", userId);
List resultList = query.getResultList();
if (!resultList.isEmpty())
return (Date) resultList.get(0);
return null;
}
@Override
public User findByUsernameAndClientCode(String username, String client, boolean fetchHistory) {
Session session = null;
try {
session = getSessionFactory().withOptions().tenantIdentifier("tradecloud_" + client).openSession();
String queryString = "select u from User u " + (fetchHistory ? "LEFT JOIN FETCH u.passwordHistory" : "") +
" where u.username =:userName ";
org.hibernate.query.Query query = session.createQuery(queryString);
query.setParameter("userName", username);
User user = (User) query.uniqueResult();
user.getRolesList();
return user;
} finally {
if (session != null) {
session.close();
}
}
}
@Override
public void updateUserForPasswordReset(User user) {
Session session = null;
try {
session = getSessionFactory().withOptions().tenantIdentifier("tradecloud_" + user.getActiveClient()).openSession();
Transaction transaction = session.beginTransaction();
//session.isReadOnly(user);
NativeQuery nativeQuery = session.createNativeQuery("update users set password =:password, lastlogindate=:lastlogindate, " +
" passwordchangeddate=:passwordchangeddate, accountNonExpired='t'" +
" where username=:userName");
nativeQuery.setParameter("lastlogindate", user.getLastLoginDate());
nativeQuery.setParameter("password", user.getPassword());
nativeQuery.setParameter("passwordchangeddate", user.getPasswordChangedDate());
nativeQuery.setParameter("userName", user.getUsername());
int i = nativeQuery.executeUpdate();
logger.debug("" + i);
session.flush();
transaction.commit();
} finally {
if (session != null) {
session.close();
}
}
}
@Override
public Set<User> findByUsernames(List<String> usersNames) {
if (usersNames != null && !usersNames.isEmpty()) {
org.hibernate.query.Query query = getSession().createQuery("from User where username in (:usersNames)");
query.setParameterList("usersNames", usersNames);
return new HashSet<>(query.list());
} else {
return Collections.EMPTY_SET;
}
}
@Override
public List<User> findAllUsersWithRegionsLinked(String role) {
//can only link regions with FD
String q = "select distinct u from User u join u.roles r where r.authority = :role and u.regions is not empty";
return getSession().createQuery(q, User.class).setParameter("role", role).getResultList();
}
@Override
public List<User> findUsersByRoleAndRegions(String role, Set<Region> regions) {
if (regions == null || regions.isEmpty()) {
return Collections.emptyList();
}
String q = "select distinct u from User u join u.roles r join u.regions reg where r.authority = :role and reg in (:regions)";
return getSession().createQuery(q, User.class)
.setParameter("role", role)
.setParameterList("regions", regions)
.getResultList();
}
public List<User> findEmployees() {
String hql = """
select u
from User u
join u.employee e
join e.employeeRoles r
where r.code = :roleCode
""";
return getSession()
.createQuery(hql, User.class)
.setParameter("roleCode", "SHIPPING_CONTROLLER")
.list();
}
}