Java tutorial
/* * Copyright (C) 2005 - 2014 TIBCO Software Inc. All rights reserved. * http://www.jaspersoft.com. * * Unless you have purchased a commercial license agreement from Jaspersoft, * the following license terms apply: * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.jaspersoft.jasperserver.api.metadata.user.service.impl; import com.jaspersoft.jasperserver.api.JSException; import com.jaspersoft.jasperserver.api.common.domain.ExecutionContext; import com.jaspersoft.jasperserver.api.common.domain.impl.ExecutionContextImpl; import com.jaspersoft.jasperserver.api.logging.audit.context.AuditContext; import com.jaspersoft.jasperserver.api.logging.audit.domain.AuditEvent; import com.jaspersoft.jasperserver.api.logging.diagnostic.domain.DiagnosticAttribute; import com.jaspersoft.jasperserver.api.logging.diagnostic.helper.DiagnosticAttributeBuilder; import com.jaspersoft.jasperserver.api.logging.diagnostic.service.Diagnostic; import com.jaspersoft.jasperserver.api.logging.diagnostic.service.DiagnosticCallback; import com.jaspersoft.jasperserver.api.metadata.common.service.ResourceFactory; import com.jaspersoft.jasperserver.api.metadata.common.service.impl.HibernateDaoImpl; import com.jaspersoft.jasperserver.api.metadata.common.service.impl.hibernate.util.IlikeEscapeAwareExpression; import com.jaspersoft.jasperserver.api.metadata.common.util.DatabaseCharactersEscapeResolver; import com.jaspersoft.jasperserver.api.metadata.tenant.service.TenantPersistenceResolver; import com.jaspersoft.jasperserver.api.metadata.user.domain.Role; import com.jaspersoft.jasperserver.api.metadata.user.domain.Tenant; import com.jaspersoft.jasperserver.api.metadata.user.domain.User; import com.jaspersoft.jasperserver.api.metadata.user.domain.impl.client.MetadataUserDetails; import com.jaspersoft.jasperserver.api.metadata.user.domain.impl.hibernate.RepoRole; import com.jaspersoft.jasperserver.api.metadata.user.domain.impl.hibernate.RepoTenant; import com.jaspersoft.jasperserver.api.metadata.user.domain.impl.hibernate.RepoUser; import com.jaspersoft.jasperserver.api.metadata.user.service.ProfileAttributeService; import com.jaspersoft.jasperserver.api.metadata.user.service.TenantService; import com.jaspersoft.jasperserver.api.metadata.view.domain.FilterCriteria; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.Predicate; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.Criteria; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.MatchMode; import org.hibernate.criterion.Order; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; import org.springframework.dao.DataAccessException; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.security.Authentication; import org.springframework.security.GrantedAuthority; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.security.ui.switchuser.SwitchUserGrantedAuthority; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UserDetailsService; import org.springframework.security.userdetails.UsernameNotFoundException; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; /** * @author swood * @version $Id: UserAuthorityServiceImpl.java 47331 2014-07-18 09:13:06Z kklein $ */ @Transactional(propagation = Propagation.SUPPORTS, readOnly = true) public class UserAuthorityServiceImpl extends HibernateDaoImpl implements UserDetailsService, ExternalUserService, UserAuthorityPersistenceService, Diagnostic { protected static final Log log = LogFactory.getLog(UserAuthorityServiceImpl.class); private ResourceFactory objectFactory; private ResourceFactory persistentClassFactory; private ProfileAttributeService profileAttributeService; private TenantPersistenceResolver tenantPersistenceResolver; private AuditContext auditContext; private List defaultInternalRoles; private DatabaseCharactersEscapeResolver databaseCharactersEscapeResolver; private boolean isUsernameCaseSensitive; private Pattern passwordPattern = Pattern.compile("^.*$"); public void setDatabaseCharactersEscapeResolver( DatabaseCharactersEscapeResolver databaseCharactersEscapeResolver) { this.databaseCharactersEscapeResolver = databaseCharactersEscapeResolver; } public DatabaseCharactersEscapeResolver getDatabaseCharactersEscapeResolver() { return this.databaseCharactersEscapeResolver; } public ResourceFactory getObjectMappingFactory() { return objectFactory; } public void setObjectMappingFactory(ResourceFactory objectFactory) { this.objectFactory = objectFactory; } public ResourceFactory getPersistentClassFactory() { return persistentClassFactory; } public void setPersistentClassFactory(ResourceFactory persistentClassFactory) { this.persistentClassFactory = persistentClassFactory; } public ProfileAttributeService getProfileAttributeService() { return profileAttributeService; } public void setProfileAttributeService(ProfileAttributeService pas) { this.profileAttributeService = pas; } public void setAuditContext(AuditContext auditContext) { this.auditContext = auditContext; } public boolean isUsernameCaseSensitive() { return isUsernameCaseSensitive; } public void setUsernameCaseSensitive(boolean usernameCaseSensitive) { isUsernameCaseSensitive = usernameCaseSensitive; } protected RepoUser getRepoUser(ExecutionContext context, String username) { return getRepoUser(username, null); } protected RepoUser getRepoUser(String username, String tenantId) { RepoTenant tenant = getPersistentTenant(tenantId, false); if (tenant == null && !isNullTenant(tenantId)) { //if the requested tenant was not found, return null if (log.isDebugEnabled()) { log.debug("Tenant " + tenantId + " not found, returning null user."); } return null; } // Search with sensitivity according to the configuration. List userList = getHibernateTemplate() .findByCriteria(createUserSearchCriteria(username, tenant, isUsernameCaseSensitive)); // Before 5.0.1 we had case sensitive usernames. But there was a bug 24226 opened with at least 4 customer // cases that username should be case insensitive. Because of previous case sensitive logic existing customers // could have several users whose username is the same when case insensitive logic is applied but different // when case sensitive logic is applied. So, we decided to implement adaptive logic which will allow both worlds // live together. // It means that by default we are trying to find the user using case insensitive logic (this is the matter of // configuration). If more then 1 user was found we do one more search with case sensitive logic applied. if (userList.size() > 1) { log.warn(userList.size() + " users were found during case insensitive search for \"" + username + "\". Retrying with case sensitive search."); // Case sensitive search. userList = getHibernateTemplate().findByCriteria(createUserSearchCriteria(username, tenant, true)); } return extractUser(username, tenantId, userList); } private RepoUser extractUser(String username, String tenantId, List userList) { RepoUser user = null; if (userList.isEmpty()) { log.debug("User not found with username \"" + username + "\" in tenant " + tenantId + "."); } else if (userList.size() == 1) { user = (RepoUser) userList.get(0); } return user; } private DetachedCriteria createUserSearchCriteria(String username, RepoTenant tenant, boolean isCaseSensitive) { DetachedCriteria criteria = DetachedCriteria.forClass(getPersistentUserClass()); criteria.add( isCaseSensitive ? Restrictions.eq("username", username) : Restrictions.ilike("username", username)); criteria.add(Restrictions.eq("tenant", tenant)); criteria.getExecutableCriteria(getSession()).setCacheable(true); return criteria; } protected RepoUser getRepoUser(ExecutionContext context, User user) { return getRepoUser(user.getUsername(), user.getTenantId()); } protected Class getPersistentUserClass() { return getPersistentClassFactory().getImplementationClass(User.class); } protected Class getPersistentTenantClass() { return getPersistentClassFactory().getImplementationClass(Tenant.class); } /* (non-Javadoc) * @see com.jaspersoft.jasperserver.api.metadata.user.service.UserAuthorityService#getUser(com.jaspersoft.jasperserver.api.common.domain.ExecutionContext, java.lang.String) */ @Transactional(propagation = Propagation.REQUIRED) public User getUser(ExecutionContext context, String username) { RepoUser user = getRepoUser(context, username); User userDTO = null; if (user != null) { userDTO = (User) user.toClient(getObjectMappingFactory()); List attrs = getProfileAttributeService().getProfileAttributesForPrincipal(null, user); userDTO.setAttributes(attrs); } else { log.debug("No such user as: " + username); } return userDTO; } protected RepoUser getRepoUser(ExecutionContext context, Long id) { RepoUser user = (RepoUser) getHibernateTemplate().load(getPersistentUserClass(), id); return user; } /* (non-Javadoc) * @see com.jaspersoft.jasperserver.api.metadata.user.service.UserAuthorityService#getUser(com.jaspersoft.jasperserver.api.common.domain.ExecutionContext, java.lang.Long) */ protected User getUser(ExecutionContext context, Long id) { RepoUser user = getRepoUser(context, id); User userDTO = null; if (user != null) { userDTO = (User) user.toClient(getObjectMappingFactory()); } return userDTO; } /* (non-Javadoc) * @see org.springframework.security.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) */ @Transactional(propagation = Propagation.REQUIRED) public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { User u = getUser(null, username); if (u == null) { throw new UsernameNotFoundException("User not found with username \"" + username + "\""); } else { return makeUserDetails(u); } } protected MetadataUserDetails makeUserDetails(User user) { return new MetadataUserDetails(user); } /* * 11-11-08 bob * Modified to deal with bogus behavior allowed by a method signature that isn't specific enough. * This fixes bug 12382. * This method expects a client object (UserImpl), * but its signature just says User which has both RepoUser and UserImpl (client) implementations. * When you pass in a RepoUser, it does a copyFromClient() on it, which is wrong, but doesn't * burn anyone most of the time. * It DOES burn you when you have password encryption turned on, in which case it encrypts your already-encrypted password. * Guess what, you can't log in anymore! * * TODO Per Sherman, if there are methods calling putUser() with a RepoUser, they need to be fixed. * I looked at all the callers (about 20) and found three that do this: addRole(), removeRole(), and removeAllRoles(). * We should probably change the interface so it can't be called with RepoUser, but we should probably look at other API's. * (non-Javadoc) * @see com.jaspersoft.jasperserver.api.metadata.user.service.UserAuthorityService#putUser(com.jaspersoft.jasperserver.api.common.domain.ExecutionContext, com.jaspersoft.jasperserver.api.metadata.user.domain.User) */ @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public void putUser(ExecutionContext context, User aUser) { if (!aUser.isExternallyDefined() ? isPasswordStrongEnough(aUser.getPassword()) : true) { doPutUser(context, aUser); } else { throw new JSException("Weak password stored in the database does not conform the allowed pattern."); } } protected void doPutUser(ExecutionContext context, User aUser) { RepoUser existingUser; if (aUser instanceof RepoUser) { existingUser = (RepoUser) aUser; } else { existingUser = getRepoUser(context, aUser); if (existingUser == null) { existingUser = (RepoUser) getPersistentClassFactory().newObject(User.class); } updatePersistentUser(aUser, existingUser); } addPropertiesToUserEvent(new String[] { "createUser", "updateUser" }, existingUser); getHibernateTemplate().saveOrUpdate(existingUser); } protected boolean isPasswordStrongEnough(String password) { return passwordPattern.matcher(password).matches(); } protected void updatePersistentUser(User user, RepoUser persistentUser) { persistentUser.copyFromClient(user, this); } /** * return everything for now * * (non-Javadoc) * @see com.jaspersoft.jasperserver.api.metadata.user.service.UserAuthorityService#getUsers(com.jaspersoft.jasperserver.api.common.domain.ExecutionContext, com.jaspersoft.jasperserver.api.metadata.view.domain.FilterCriteria) */ @Transactional(propagation = Propagation.REQUIRED) public List<User> getUsers(ExecutionContext context, FilterCriteria filterCriteria) { // make User DTOs List results = getHibernateTemplate().loadAll(getPersistentUserClass()); List userDTOs = null; if (results != null) { userDTOs = new ArrayList(results.size()); Iterator it = results.iterator(); while (it.hasNext()) { RepoUser u = (RepoUser) it.next(); User newUser = (User) u.toClient(getObjectMappingFactory()); userDTOs.add(newUser); } } return userDTOs; } /** * return everything for now * * (non-Javadoc) * @see com.jaspersoft.jasperserver.api.metadata.user.service.UserAuthorityService#getUsersByCriteria(com.jaspersoft.jasperserver.api.common.domain.ExecutionContext, org.hibernate.criterion.DetachedCriteria) */ @Transactional(propagation = Propagation.REQUIRED) public List<User> getUsersByCriteria(ExecutionContext context, DetachedCriteria detachedCriteria) { // make User DTOs List results = getHibernateTemplate().findByCriteria(detachedCriteria); List userDTOs = null; if (results != null) { userDTOs = new ArrayList(results.size()); Iterator it = results.iterator(); while (it.hasNext()) { RepoUser u = (RepoUser) it.next(); User newUser = (User) u.toClient(getObjectMappingFactory()); userDTOs.add(newUser); } } return userDTOs; } @Transactional(propagation = Propagation.REQUIRED) public int getUsersCountExceptExcluded(ExecutionContext executionContext, final Set<String> excludedUserNames, final boolean excludeDisabledUsers) { return (Integer) getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException, SQLException { Criteria criteria = session.createCriteria(getPersistentUserClass()); if (excludedUserNames != null && excludedUserNames.size() > 0) { criteria.add(Restrictions.not(Restrictions.in("username", excludedUserNames))); } if (excludeDisabledUsers) { criteria.add(Restrictions.eq("enabled", true)); } criteria.setProjection(Projections.count("id")); return criteria.uniqueResult(); } }); } /** * DTO for the User interface * * (non-Javadoc) * @see com.jaspersoft.jasperserver.api.metadata.user.service.UserAuthorityService#newUser(com.jaspersoft.jasperserver.api.common.domain.ExecutionContext) */ public User newUser(ExecutionContext context) { return (User) getObjectMappingFactory().newObject(User.class); } /* (non-Javadoc) * @see com.jaspersoft.jasperserver.api.metadata.user.service.UserAuthorityService#disableUser(com.jaspersoft.jasperserver.api.common.domain.ExecutionContext, java.lang.Long) */ protected boolean disableUser(ExecutionContext context, Long id) { RepoUser user = getRepoUser(context, id); if (user != null && user.isEnabled()) { user.setEnabled(false); return true; } else { return false; } } /* (non-Javadoc) * @see com.jaspersoft.jasperserver.api.metadata.user.service.UserAuthorityService#disableUser(com.jaspersoft.jasperserver.api.common.domain.ExecutionContext, java.lang.String) */ @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public boolean disableUser(ExecutionContext context, String username) { RepoUser user = getRepoUser(context, username); if (user != null && user.isEnabled()) { user.setEnabled(false); return true; } else { return false; } } /* (non-Javadoc) * @see com.jaspersoft.jasperserver.api.metadata.user.service.UserAuthorityService#enableUser(com.jaspersoft.jasperserver.api.common.domain.ExecutionContext, java.lang.Long) */ protected boolean enableUser(ExecutionContext context, Long id) { RepoUser user = getRepoUser(context, id); if (user != null && !user.isEnabled()) { user.setEnabled(true); return true; } else { return false; } } /* (non-Javadoc) * @see com.jaspersoft.jasperserver.api.metadata.user.service.UserAuthorityService#enableUser(com.jaspersoft.jasperserver.api.common.domain.ExecutionContext, java.lang.String) */ @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public boolean enableUser(ExecutionContext context, String username) { RepoUser user = getRepoUser(context, username); if (user != null && !user.isEnabled()) { user.setEnabled(true); return true; } else { return false; } } private void addPropertiesToUserEvent(final String[] auditEventTypes, final User user) { auditContext.doInAuditContext(auditEventTypes, new AuditContext.AuditContextCallbackWithEvent() { public void execute(AuditEvent auditEvent) { if (user != null) { auditContext.addPropertyToAuditEvent("username", user.getUsername(), auditEvent); auditContext.addPropertyToAuditEvent("tenantId", user.getTenantId(), auditEvent); auditContext.addPropertyToAuditEvent("email", user.getEmailAddress(), auditEvent); auditContext.addPropertyToAuditEvent("fullName", user.getFullName(), auditEvent); auditContext.addPropertyToAuditEvent("passwordChangeTime", user.getPreviousPasswordChangeTime(), auditEvent); auditContext.addPropertyToAuditEvent("enabled", user.isEnabled(), auditEvent); auditContext.addPropertyToAuditEvent("externallyDefined", user.isExternallyDefined(), auditEvent); List attrs = getProfileAttributeService().getProfileAttributesForPrincipal(null, user); if (attrs != null && !attrs.isEmpty()) { for (Object attribute : attrs) { auditContext.addPropertyToAuditEvent("attribute", attribute, auditEvent); } } if (user.getRoles() != null && !user.getRoles().isEmpty()) { for (Object roleObject : user.getRoles()) { Role role = (Role) roleObject; auditContext.addPropertyToAuditEvent("roleName", role.getRoleName(), auditEvent); } } } } }); } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public void deleteUser(ExecutionContext context, String username) { RepoUser user = getRepoUser(context, username); if (user == null) { return; } addPropertiesToUserEvent(new String[] { "deleteUser" }, user); removeAllRoles(context, (User) user); getHibernateTemplate().delete(user); } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public void addRole(ExecutionContext context, User user, Role role) { if (user == null) { return; } RepoUser existingUser = getRepoUser(context, user); if (existingUser != null) { RepoRole existingRole = getRepoRole(role); existingUser.addRole(existingRole); doPutUser(null, existingUser); } user.addRole(role); } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public void removeRole(ExecutionContext context, User user, Role role) { if (user == null || role == null) { return; } RepoUser existingUser = getRepoUser(context, user); if (existingUser != null) { RepoRole r = getRepoRole(role); if (r != null) { existingUser.removeRole(r); doPutUser(null, existingUser); } else { log.debug("removeRole: No role such as " + role.getRoleName()); } } else { log.debug("removeRole: No user such as " + user.getUsername()); } user.removeRole(role); } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public void removeAllRoles(ExecutionContext context, User user) { if (user == null) { return; } RepoUser existingUser = getRepoUser(context, user); if (existingUser == null) { return; } /* for (Iterator it = existingUser.getRoles().iterator(); it.hasNext(); ) { Role role = (Role) it.next(); existingUser.removeRole(role); user.removeRole(role); } */ existingUser.getRoles().clear(); //to avoid ConcurrentModificationException doPutUser(null, existingUser); } /* (non-Javadoc) * @see com.jaspersoft.jasperserver.api.metadata.user.service.UserAuthorityService#getRole(com.jaspersoft.jasperserver.api.common.domain.ExecutionContext, java.lang.String) */ @Transactional(propagation = Propagation.REQUIRED) public Role getRole(ExecutionContext context, String roleName) { RepoRole repoRole = getRepoRole(context, roleName); Role role = null; if (repoRole != null) { role = (Role) repoRole.toClient(getObjectMappingFactory()); } return role; } protected Class getPersistentRoleClass() { return getPersistentClassFactory().getImplementationClass(Role.class); } /* (non-Javadoc) * @see com.jaspersoft.jasperserver.api.metadata.user.service.UserAuthorityService#getRole(com.jaspersoft.jasperserver.api.common.domain.ExecutionContext, java.lang.Long) */ protected RepoRole getRepoRole(ExecutionContext context, String roleName) { return getRepoRole(roleName, (String) null); } protected RepoRole getRepoRole(Role role) { return getRepoRole(role.getRoleName(), role.getTenantId()); } protected RepoRole getRepoRole(String roleName, String tenantId) { RepoTenant tenant = getPersistentTenant(tenantId, false); if (tenant == null && !isNullTenant(tenantId)) { //if the requested tenant was not found, return null if (log.isDebugEnabled()) { log.debug("Tenant " + tenantId + " not found, returning null role"); } return null; } DetachedCriteria criteria = DetachedCriteria.forClass(getPersistentRoleClass()); if (tenant == null) { criteria.add(Restrictions.isNull("tenant")).add(Restrictions.eq("roleName", roleName)); } else { criteria.add(Restrictions.naturalId().set("tenant", tenant).set("roleName", roleName)); } List roleList = getHibernateTemplate().findByCriteria(criteria); RepoRole role = null; if (roleList.isEmpty()) { if (log.isDebugEnabled()) { log.debug("Role not found with role name \"" + roleName + "\"" + (tenantId == null ? "" : (", tenant \"" + tenantId + "\""))); } } else { role = (RepoRole) roleList.get(0); } return role; } /* (non-Javadoc) * @see com.jaspersoft.jasperserver.api.metadata.user.service.UserAuthorityService#putRole(com.jaspersoft.jasperserver.api.common.domain.ExecutionContext, com.jaspersoft.jasperserver.api.metadata.user.domain.Role) */ @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public void putRole(ExecutionContext context, Role aRole) { RepoRole existingRole = getRepoRole(aRole); log.debug("putRole: " + aRole.getRoleName() + ", " + existingRole); if (existingRole == null) { existingRole = (RepoRole) getPersistentClassFactory().newObject(Role.class); log.debug("New Object"); } Set existingRoleUserIds = getIdsFromUserSet(existingRole.getUsers()); existingRole.copyFromClient(aRole, this); Set newRoleUserIds = getIdsFromUserSet(existingRole.getUsers()); addParametersToRoleManagementAuditEvent(new String[] { "createRole", "updateRole" }, existingRole, false); addUserIdsToRoleManagementAuditEvent(existingRoleUserIds, newRoleUserIds); getHibernateTemplate().saveOrUpdate(existingRole); updateRoleUsers(context, existingRole, aRole); } private void updateRoleUsers(ExecutionContext context, RepoRole existingRole, Role aRole) { Set repoUsers = existingRole.getUsers(); for (Iterator it = repoUsers.iterator(); it.hasNext();) { RepoUser repoUser = (RepoUser) it.next(); repoUser.getRoles().remove(getPersistentObject(aRole)); } Set users = aRole.getUsers(); for (Iterator it = users.iterator(); it.hasNext();) { User user = (User) it.next(); addRole(context, user, aRole); } } /** * Return everything for now * * (non-Javadoc) * @see com.jaspersoft.jasperserver.api.metadata.user.service.UserAuthorityService#getRoles(com.jaspersoft.jasperserver.api.common.domain.ExecutionContext, com.jaspersoft.jasperserver.api.metadata.view.domain.FilterCriteria) */ @Transactional(propagation = Propagation.REQUIRED) public List getRoles(ExecutionContext context, FilterCriteria filterCriteria) { List results = getHibernateTemplate().loadAll(getPersistentRoleClass()); List roleDTOs = null; if (results != null) { roleDTOs = new ArrayList(results.size()); Iterator it = results.iterator(); while (it.hasNext()) { RepoRole r = (RepoRole) it.next(); Role newRole = (Role) r.toClient((ResourceFactory) getObjectMappingFactory()); roleDTOs.add(newRole); } } return roleDTOs; } /* (non-Javadoc) * @see com.jaspersoft.jasperserver.api.metadata.user.service.UserAuthorityService#newRole(com.jaspersoft.jasperserver.api.common.domain.ExecutionContext) */ public Role newRole(ExecutionContext context) { // return a Role DTO return (Role) getObjectMappingFactory().newObject(Role.class); } private void addParametersToRoleManagementAuditEvent(final String[] auditEventTypes, final RepoRole role, final boolean logUsers) { auditContext.doInAuditContext(auditEventTypes, new AuditContext.AuditContextCallbackWithEvent() { public void execute(AuditEvent auditEvent) { auditContext.addPropertyToAuditEvent("roleName", role.getRoleName(), auditEvent); auditContext.addPropertyToAuditEvent("tenantId", role.getTenantId(), auditEvent); auditContext.addPropertyToAuditEvent("externallyDefined", role.isExternallyDefined(), auditEvent); if (role.getAttributes() != null && !role.getAttributes().isEmpty()) { for (Object attribute : role.getAttributes()) { auditContext.addPropertyToAuditEvent("attribute", attribute, auditEvent); } } if (logUsers && role.getUsers() != null && !role.getUsers().isEmpty()) { for (Object userObject : role.getUsers()) { RepoUser user = (RepoUser) userObject; auditContext.addPropertyToAuditEvent("userId", user.getId(), auditEvent); } } } }); } private Set getIdsFromUserSet(Set userSet) { if (userSet != null && !userSet.isEmpty()) { Set userIds = new HashSet(userSet.size()); for (Object user : userSet) { userIds.add(((RepoUser) user).getId()); } return userIds; } else { return null; } } private void addUserIdsToRoleManagementAuditEvent(final Set usersIdsBeforeUpdate, final Set usersIdsAfterUpdate) { auditContext.doInAuditContext(new String[] { "createRole", "updateRole" }, new AuditContext.AuditContextCallbackWithEvent() { public void execute(AuditEvent auditEvent) { if (usersIdsAfterUpdate != null && !usersIdsAfterUpdate.isEmpty()) { for (Iterator i = usersIdsAfterUpdate.iterator(); i.hasNext();) { Long id = (Long) i.next(); if (usersIdsBeforeUpdate != null && usersIdsBeforeUpdate.contains(id)) { usersIdsBeforeUpdate.remove(id); i.remove(); } } } if (usersIdsBeforeUpdate != null && !usersIdsBeforeUpdate.isEmpty()) { for (Object removedId : usersIdsBeforeUpdate) { auditContext.addPropertyToAuditEvent("removedUserId", removedId, auditEvent); } } if (usersIdsAfterUpdate != null && !usersIdsAfterUpdate.isEmpty()) { for (Object addedId : usersIdsAfterUpdate) { auditContext.addPropertyToAuditEvent("addedUserId", addedId, auditEvent); } } } }); } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public void deleteRole(ExecutionContext context, String roleName) { RepoRole role = getRepoRole(context, roleName); if (role == null) { return; } addParametersToRoleManagementAuditEvent(new String[] { "deleteRole" }, role, true); // Get all users that have this role and remove the role from them Set userList = role.getUsers(); for (Iterator it = userList.iterator(); it.hasNext();) { RepoUser u = (RepoUser) it.next(); u.removeRole(role); } // role.getUsers().clear(); // then delete the role getHibernateTemplate().delete(role); } @Transactional(propagation = Propagation.REQUIRED) public List getUsersNotInRole(ExecutionContext context, String roleName) { List allUsers = getUsers(context, null); List usersInRole = getUsersInRole(context, roleName); allUsers.removeAll(usersInRole); return allUsers; } @Transactional(propagation = Propagation.REQUIRED) public List getUsersInRole(ExecutionContext context, String roleName) { RepoRole repoRole = getRepoRole(context, roleName); Set repoUsers = repoRole.getUsers(); List users = new ArrayList(); for (Iterator it = repoUsers.iterator(); it.hasNext();) { RepoUser repoUser = (RepoUser) it.next(); User user = (User) repoUser.toClient(getObjectMappingFactory()); users.add(user); } return users; } @Transactional(propagation = Propagation.REQUIRED) public List getAssignedRoles(ExecutionContext context, String userName) { RepoUser repoUser = getRepoUser(context, userName); Set repoRoles = repoUser.getRoles(); List roles = new ArrayList(); for (Iterator it = repoRoles.iterator(); it.hasNext();) { RepoRole repoRole = (RepoRole) it.next(); Role role = (Role) repoRole.toClient(getObjectMappingFactory()); roles.add(role); } return roles; } @Transactional(propagation = Propagation.REQUIRED) public List getAvailableRoles(ExecutionContext context, String userName) { List allRoles = getRoles(context, null); List assignedRoles = getAssignedRoles(null, userName); allRoles.removeAll(assignedRoles); return allRoles; } public boolean roleExists(ExecutionContext context, String roleName) { return (getRole(context, roleName) != null); } /* * TODO this should be generalized. Maybe get the Repo* objects to return a * DetachedCriteria filled with the key from the client object? * * (non-Javadoc) * @see com.jaspersoft.jasperserver.api.metadata.common.service.impl.hibernate.PersistentObjectResolver#getPersistentObject(java.lang.Object) */ @Transactional(propagation = Propagation.REQUIRED) public Object getPersistentObject(Object clientObject) { if (clientObject instanceof Role) { Role r = (Role) clientObject; return getRepoRole(r); } else if (clientObject instanceof User) { User u = (User) clientObject; return getRepoUser(null, u); } return null; } /** * From an external UserDetails + GrantedAuthority[], maintain the shadow internal user * * @param externalUserDetails */ @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public User maintainInternalUser(UserDetails externalUserDetails, GrantedAuthority[] authorities) { log.debug("External user: " + externalUserDetails.getUsername()); User user = getUser(new ExecutionContextImpl(), externalUserDetails.getUsername()); if (user == null) { user = createNewExternalUser(externalUserDetails.getUsername()); } Set roles = persistRoles(getRolesFromGrantedAuthorities(authorities)); alignInternalAndExternalUser(roles, user); return user; } /** * From an external user (string user name) + GrantedAuthority[], maintain the shadow internal user * * @param userName * @param authorities */ @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public User maintainInternalUser(String userName, GrantedAuthority[] authorities) { log.debug("External user(String): " + userName); User user = getUser(new ExecutionContextImpl(), userName); if (user == null) { user = createNewExternalUser(userName); } Set roles = persistRoles(getRolesFromGrantedAuthorities(authorities)); alignInternalAndExternalUser(roles, user); return user; } /** * New user created from given authentication details. No password is set or needed. * Roles are set elsewhere. * * @param userName * @return created User */ protected User createNewExternalUser(String userName) { User user = newUser(new ExecutionContextImpl()); user.setUsername(userName); // If it is externally authenticated, no save of password //user.setPassword(userDetails.getPassword()); user.setFullName(userName); // We don't know the real name user.setExternallyDefined(true); user.setEnabled(true); log.warn("Created new external user: " + user.getUsername()); return user; } /** * Ensure the external user has the right roles. Roles attached to the userDetails are the definitive list * of externally defined roles. * * @param externalRoles * @param user */ protected void alignInternalAndExternalUser(Set externalRoles, User user) { final Predicate externallyDefinedRoles = new Predicate() { public boolean evaluate(Object input) { if (!(input instanceof Role)) { return false; } return ((Role) input).isExternallyDefined(); } }; Set currentRoles = user.getRoles(); // we may have a new user, so always persist them boolean persistUserNeeded = (currentRoles.size() == 0); /* // If it is externally authenticated, no save of password if (!user.getPassword().equals(userDetails.getPassword())) { user.setPassword(userDetails.getPassword()); persistUserNeeded = true; } */ Collection currentExternalRoles = CollectionUtils.select(user.getRoles(), externallyDefinedRoles); if (log.isDebugEnabled()) { log.debug("Login of external User: " + user.getUsername()); log.debug("Roles from authentication:\n" + roleCollectionToString(externalRoles)); log.debug("Current roles from metadata:\n" + roleCollectionToString(user.getRoles())); log.debug("Current external roles for user from metadata: " + user.getUsername() + "\n" + roleCollectionToString(currentExternalRoles)); } /* * If we have new external roles, we want to add them */ Collection newExternalRoles = CollectionUtils.subtract(externalRoles, currentExternalRoles); if (newExternalRoles.size() > 0) { currentRoles.addAll(newExternalRoles); if (log.isWarnEnabled()) { log.warn("Added following external roles to: " + user.getUsername() + "\n" + roleCollectionToString(newExternalRoles)); } persistUserNeeded = true; } /* * If external roles have been removed, we need to remove them */ Collection rolesNeedingRemoval = CollectionUtils.subtract(currentExternalRoles, externalRoles); if (rolesNeedingRemoval.size() > 0) { currentRoles.removeAll(rolesNeedingRemoval); if (log.isWarnEnabled()) { log.warn("Removed following external roles from: " + user.getUsername() + "\n" + roleCollectionToString(rolesNeedingRemoval)); } persistUserNeeded = true; } /* * If we have new default internal roles, we want to add them */ Collection defaultInternalRolesToAdd = CollectionUtils.subtract(getNewDefaultInternalRoles(), currentRoles); if (defaultInternalRolesToAdd.size() > 0) { if (log.isDebugEnabled()) { log.debug("Default internal roles: " + roleCollectionToString(getNewDefaultInternalRoles())); } currentRoles.addAll(defaultInternalRolesToAdd); if (log.isWarnEnabled()) { log.warn("Added following new default internal roles to: " + user.getUsername() + "\n" + roleCollectionToString(defaultInternalRolesToAdd)); } persistUserNeeded = true; } if (persistUserNeeded) { if (log.isWarnEnabled()) { log.warn("Updated user: " + user.getUsername() + ". Roles are now:\n" + roleCollectionToString(currentRoles)); } user.setRoles(currentRoles); // persist user and roles doPutUser(new ExecutionContextImpl(), user); if (log.isWarnEnabled()) { log.warn("Updated user: " + user.getUsername() + ". Roles are now:\n" + roleCollectionToString(currentRoles)); } } } private String roleCollectionToString(Collection coll) { Iterator it = coll.iterator(); StringBuffer rolesPrint = new StringBuffer(); while (it.hasNext()) { String s = ((Role) it.next()).getRoleName(); rolesPrint.append(s).append("\n"); } return rolesPrint.toString(); } /** * Get a set of roles based on the given GrantedAuthority[]. Roles are created * in the metadata if they do not exist. * * @param authorities from authenticated user * @return Set of externally defined Roles */ protected Set getRolesFromGrantedAuthorities(GrantedAuthority[] authorities) { Set set = new HashSet(); if (authorities == null || authorities.length == 0) return set; for (int i = 0; i < authorities.length; i++) { GrantedAuthority auth = authorities[i]; String authorityName = auth.getAuthority(); // Make spaces in the authority name be underscores authorityName = authorityName.replace(' ', '_'); if (!authorityName.startsWith("ROLE_")) { authorityName = "ROLE_" + authorityName; } Role r = newRole(new ExecutionContextImpl()); r.setRoleName(authorityName); r.setExternallyDefined(true); set.add(r); } return set; } /* * */ protected Set persistRoles(Set roles) { Set persistedRoles = new HashSet(); for (Iterator iter = roles.iterator(); iter.hasNext();) { Role r = (Role) iter.next(); persistedRoles.add(getOrCreateRole(r.getRoleName(), r.isExternallyDefined())); } return persistedRoles; } /** * @return the Authentication corresponding to the principal who used * the "Switch User" feature to login as the current principal if any, * or null, if the current principal is not a switched user. */ public static Authentication getSourceAuthentication() { Authentication current = SecurityContextHolder.getContext().getAuthentication(); Authentication original = null; // iterate over granted authorities and find the 'switch user' authority GrantedAuthority[] authorities = current.getAuthorities(); for (int i = 0; i < authorities.length; i++) { // check for switch user type of authority if (authorities[i] instanceof SwitchUserGrantedAuthority) { original = ((SwitchUserGrantedAuthority) authorities[i]).getSource(); log.debug("Found original switch user granted authority [" + original + "]"); } } return original; } public static boolean isUserSwitched() { return (getSourceAuthentication() != null); } /** * Get a set of roles that are the defaults for a new external user. Roles are created * in the metadata if they do not exist. * * @return Set of internally defined Roles */ private Set getNewDefaultInternalRoles() { Set set = new HashSet(); if (getDefaultInternalRoles() == null || getDefaultInternalRoles().size() == 0) return set; for (int i = 0; i < getDefaultInternalRoles().size(); i++) { String roleName = (String) getDefaultInternalRoles().get(i); set.add(getOrCreateRole(roleName, false)); } return set; } private Role getOrCreateRole(String roleName, boolean externallyDefined) { Role r = getRole(new ExecutionContextImpl(), roleName); if (r == null) { r = newRole(new ExecutionContextImpl()); r.setRoleName(roleName); r.setExternallyDefined(externallyDefined); putRole(new ExecutionContextImpl(), r); log.warn("Created new " + (externallyDefined ? "external" : "internal") + " role: " + roleName); } return r; } /** * From an external UserDetails + GrantedAuthority[], maintain the shadow internal user * which is used only in integration tests (applicationContext-testProviders.xml) * * @deprecated deprecated per emerald SSO work */ @Deprecated @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public User maintainInternalUser() { final Authentication auth = SecurityContextHolder.getContext().getAuthentication(); final Object authPrincipal = auth.getPrincipal(); String userName = null; if (authPrincipal instanceof UserDetails) { UserDetails userDetails = (UserDetails) authPrincipal; userName = userDetails.getUsername(); } else if (authPrincipal instanceof String) { userName = String.valueOf(authPrincipal); } else { throw new JSException("Cannot synchronize user details. Unknown principal class: " + authPrincipal.getClass().getName()); } log.debug("Processing external user: " + userName); User user = getUser(new ExecutionContextImpl(), userName); if (user == null) { user = createNewExternalUser(userName); } Set roles = persistRoles(getRolesFromGrantedAuthorities(auth.getAuthorities())); alignInternalAndExternalUser(roles, user); return user; } public void makeUserLoggedIn(User user) { try { // Make our user the Authentication! UserDetails ourUserDetails = makeUserDetails(user); // Don't set the authentication if we have no roles if (ourUserDetails.getAuthorities().length != 0) { UsernamePasswordAuthenticationToken ourAuthentication = new UsernamePasswordAuthenticationToken( ourUserDetails, ourUserDetails.getPassword(), ourUserDetails.getAuthorities()); if (log.isDebugEnabled()) { log.debug("Setting Authentication to: " + ourAuthentication); } SecurityContextHolder.getContext().setAuthentication(ourAuthentication); } else { // There was some error - maybe no roles? // Remove authentication to allow anonymous access to catch things // later in the filter chain SecurityContextHolder.getContext().setAuthentication(null); } } catch (UsernameNotFoundException e) { log.warn("User: " + user.getUsername() + " was not found to make them logged in"); } } /** * @return Returns the defaultInternalRoles. */ public List getDefaultInternalRoles() { return defaultInternalRoles; } /** * @param defaultInternalRoles The defaultInternalRoles to set. */ public void setDefaultInternalRoles(List defaultInternalRoles) { this.defaultInternalRoles = defaultInternalRoles; } public boolean userExists(ExecutionContext context, String username) { return (getUser(context, username) != null); } protected boolean isDateExpired(int nDate, Date previousExpirationDate) { long during = nDate * 3600 * 24; return ((previousExpirationDate.getTime() / 1000) + during) <= ((new Date()).getTime() / 1000); } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public boolean isPasswordExpired(ExecutionContext context, String username, int nDate) { Date previousExpirationDate = getUser(context, username).getPreviousPasswordChangeTime(); // TO-DO what if previousExpirationDate is empty if ((previousExpirationDate == null) || ("".equals(previousExpirationDate))) { resetPasswordExpiration(context, username); return false; } return isDateExpired(nDate, previousExpirationDate); } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public void resetPasswordExpiration(ExecutionContext context, String username) { User user = getUser(context, username); if (user != null) { user.setPreviousPasswordChangeTime(new Date()); doPutUser(context, user); } } @Transactional(propagation = Propagation.REQUIRED) public String getTenantId(ExecutionContext context, String userName) { User user = getUser(context, userName); return user.getTenantId(); } @Transactional(propagation = Propagation.REQUIRED) public List getTenantUsers(ExecutionContext context, final Set tenantIds, final String name) { List userList = (List) getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException, SQLException { Criteria criteria = createTenantUsersCriteria(session, tenantIds, name); return criteria.list(); } }); List userDTOs = convertUserListToDtoList(userList); return userDTOs; } @Transactional(propagation = Propagation.REQUIRED) public List getTenantUsers(ExecutionContext context, final Set tenantIds, final String name, final int firstResult, final int maxResults) { List userList = (List) getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException, SQLException { Criteria criteria = createTenantUsersCriteria(session, tenantIds, name); if (firstResult >= 0) { criteria.setFirstResult(firstResult); } if (maxResults > 0) { criteria.setMaxResults(maxResults); } return criteria.list(); } }); List userDTOs = convertUserListToDtoList(userList); return userDTOs; } @Transactional(propagation = Propagation.REQUIRED) public List getTenantRoles(ExecutionContext context, final Set tenantIds, final String name) { List roleList = (List) getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException, SQLException { Criteria criteria = createTenantRolesCriteria(session, tenantIds, name); return criteria.list(); } }); return convertRoleListToDtoList(roleList); } @Transactional(propagation = Propagation.REQUIRED) public List getTenantRoles(ExecutionContext context, final Set tenantIds, final String name, final int firstResult, final int maxResults) { List roleList = (List) getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException, SQLException { Criteria criteria = createTenantRolesCriteria(session, tenantIds, name); if (firstResult >= 0) { criteria.setFirstResult(firstResult); } if (maxResults > 0) { criteria.setMaxResults(maxResults); } return criteria.list(); } }); return convertRoleListToDtoList(roleList); } @Transactional(propagation = Propagation.REQUIRED) public List getTenantVisibleRoles(ExecutionContext context, Set tenantIds, String name, int firstResult, int maxResults) { DetachedCriteria criteria = createTenantVisibleRolesCriteria(tenantIds, name); List results = getHibernateTemplate().findByCriteria(criteria, firstResult, maxResults); List roleDTOs = convertRoleListToDtoList(results); return roleDTOs; } @Transactional(propagation = Propagation.REQUIRED) public int getTenantVisibleRolesCount(ExecutionContext context, Set tenantIds, String name) { DetachedCriteria criteria = createTenantVisibleRolesCriteria(tenantIds, name, false); criteria.setProjection(Projections.rowCount()); List results = getHibernateTemplate().findByCriteria(criteria); Integer rowCount = new Integer(0); if (results != null && !results.isEmpty()) { rowCount = (Integer) results.get(0); } return rowCount.intValue(); } @Transactional(propagation = Propagation.REQUIRED) public int getTenantUsersCount(ExecutionContext context, final Set tenantIds, final String name) { Integer rowCount = (Integer) getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException, SQLException { Criteria criteria = createTenantUsersCriteria(session, tenantIds, name, false); criteria.setProjection(Projections.rowCount()); return criteria.uniqueResult(); } }); return rowCount.intValue(); } @Transactional(propagation = Propagation.REQUIRED) public int getTenantRolesCount(ExecutionContext context, final Set tenantIds, final String name) { Integer rowCount = (Integer) getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException, SQLException { Criteria criteria = createTenantRolesCriteria(session, tenantIds, name, false); criteria.setProjection(Projections.rowCount()); return criteria.uniqueResult(); } }); return rowCount.intValue(); } private Criteria createTenantUsersCriteria(Session session, Set tenantIds, String name) { return createTenantUsersCriteria(session, tenantIds, name, true); } private Criteria createTenantUsersCriteria(Session session, Set tenantIds, String name, boolean order) { Set internalTenantIds = null; if (tenantIds != null) { internalTenantIds = new HashSet(); internalTenantIds.addAll(tenantIds); if (internalTenantIds.contains(null)) { internalTenantIds.remove(null); internalTenantIds.add(TenantService.ORGANIZATIONS); } } Criteria criteria = session.createCriteria(getPersistentUserClass()); criteria.createAlias("tenant", "tenant", Criteria.LEFT_JOIN); if (internalTenantIds == null) { criteria.add(Restrictions.eq("tenant.tenantId", TenantService.ORGANIZATIONS)); } else { if (!internalTenantIds.isEmpty()) { criteria.add(Restrictions.in("tenant.tenantId", internalTenantIds)); } } if (name != null) { name = databaseCharactersEscapeResolver.getEscapedText(name.trim()); if (name.length() > 0) { // Criterion userNameCriterion = Restrictions.ilike("username", "%" + name + "%"); // Criterion fullNameCriterion = Restrictions.ilike("fullName", "%" + name + "%"); Criterion userNameCriterion = new IlikeEscapeAwareExpression("username", name, MatchMode.ANYWHERE); Criterion fullNameCriterion = new IlikeEscapeAwareExpression("fullName", name, MatchMode.ANYWHERE); criteria.add(Restrictions.or(userNameCriterion, fullNameCriterion)); } } if (order) { criteria.addOrder(Order.asc("username")); criteria.addOrder(Order.asc("tenant.tenantId")); } return criteria; } protected Criteria createTenantRolesCriteria(Session session, Set tenantIds, String name) { return createTenantRolesCriteria(session, tenantIds, name, true); } protected Criteria createTenantRolesCriteria(Session session, Set tenantIds, String name, boolean order) { Criteria criteria = session.createCriteria(getPersistentRoleClass()); String roleNameField = "roleName"; addTenantCriteria(criteria, tenantIds); if (name != null && name.trim().length() > 0) { Criterion roleNameCriterion = Restrictions.ilike(roleNameField, "%" + name.trim() + "%"); criteria.add(roleNameCriterion); } if (order) { criteria.addOrder(Order.asc(roleNameField)); } return criteria; } protected DetachedCriteria createTenantVisibleRolesCriteria(Set tenantIds, String name) { return createTenantVisibleRolesCriteria(tenantIds, name, true); } protected DetachedCriteria createTenantVisibleRolesCriteria(Set tenantIds, String name, boolean order) { DetachedCriteria criteria = DetachedCriteria.forClass(getPersistentRoleClass()); String roleNameField = "roleName"; addVisibleTenantCriteria(criteria, tenantIds); if (name != null) { name = databaseCharactersEscapeResolver.getEscapedText(name.trim()); if (name.length() > 0) { // Criterion roleNameCriterion = Restrictions.ilike(roleNameField, "%" // + name.trim() + "%"); // criteria.add(roleNameCriterion); criteria.add(new IlikeEscapeAwareExpression(roleNameField, name, MatchMode.ANYWHERE)); } } if (order) { criteria.addOrder(Order.asc(roleNameField)); } return criteria; } private List convertUserListToDtoList(List userList) { List userDTOs = null; if (userList != null) { userDTOs = new ArrayList(userList.size()); Iterator it = userList.iterator(); while (it.hasNext()) { RepoUser u = (RepoUser) it.next(); User newUser = (User) u.toClient(getObjectMappingFactory()); userDTOs.add(newUser); } } return userDTOs; } @Transactional(propagation = Propagation.REQUIRED) public List getAvailableRoles(ExecutionContext context, String roleName, Set userRoles, String userName, int firstResult, int maxResults) { DetachedCriteria criteria = createAvailableRolesCriteria(roleName, userRoles, userName); List results = getHibernateTemplate().findByCriteria(criteria, firstResult, maxResults); List roleDTOs = convertRoleListToDtoList(results); return roleDTOs; } @Transactional(propagation = Propagation.REQUIRED) public int getAvailableRolesCount(ExecutionContext context, String roleName, Set userRoles, String userName) { DetachedCriteria criteria = createAvailableRolesCriteria(roleName, userRoles, userName, false); criteria.setProjection(Projections.rowCount()); List results = getHibernateTemplate().findByCriteria(criteria); Integer rowCount = new Integer(0); if (results != null && !results.isEmpty()) { rowCount = (Integer) results.get(0); } return rowCount.intValue(); } protected DetachedCriteria createAvailableRolesCriteria(String roleName, Set userRoles, String userName) { return createAvailableRolesCriteria(roleName, userRoles, userName, true); } protected DetachedCriteria createAvailableRolesCriteria(String roleName, Set userRoles, String userName, boolean order) { DetachedCriteria criteria = DetachedCriteria.forClass(getPersistentRoleClass()); String roleNameField = "roleName"; String externallyDefinedField = "externallyDefined"; if (userRoles != null && userRoles.size() > 0) { List userRoleIdList = getRoleIdList(userRoles); criteria.add(Restrictions.not(Restrictions.in("id", userRoleIdList))); } Criterion roleNameCriterion = Restrictions.ilike(roleNameField, "%" + roleName.trim() + "%"); criteria.add(roleNameCriterion); criteria.add(Restrictions.eq(externallyDefinedField, Boolean.FALSE)); if (order) { criteria.addOrder(Order.asc(roleNameField)); } return criteria; } protected List getRoleIdList(Set roleNames) { DetachedCriteria criteria = DetachedCriteria.forClass(getPersistentRoleClass()); if (roleNames != null && roleNames.size() > 0) { criteria.add(Restrictions.in("roleName", roleNames)); } else { return new ArrayList(); } criteria.setProjection(Projections.id()); return getHibernateTemplate().findByCriteria(criteria); } private List<Role> convertRoleListToDtoList(List roleList) { List<Role> roleDTOs = null; if (roleList != null) { roleDTOs = new ArrayList<Role>(roleList.size()); for (Object aRoleList : roleList) { RepoRole r = (RepoRole) aRoleList; Role newRole = (Role) r.toClient((ResourceFactory) getObjectMappingFactory()); roleDTOs.add(newRole); } } return roleDTOs; } @Transactional(propagation = Propagation.REQUIRED) public List<Role> getAvailableRoles(ExecutionContext context, String userName, String text, int firstResult, int maxResults) { DetachedCriteria criteria = createAvailableRolesCriteria(context, userName, text, true); List results = getHibernateTemplate().findByCriteria(criteria, firstResult, maxResults); return convertRoleListToDtoList(results); } @Transactional(propagation = Propagation.REQUIRED) public int getAvailableRolesCount(ExecutionContext context, String userName, String text) { DetachedCriteria criteria = createAvailableRolesCriteria(context, userName, text, false); criteria.setProjection(Projections.rowCount()); List results = getHibernateTemplate().findByCriteria(criteria); int rowCount = 0; if (results != null && !results.isEmpty()) { rowCount = (Integer) results.get(0); } return rowCount; } protected DetachedCriteria createAvailableRolesCriteria(ExecutionContext context, String userName, String text, boolean order) { final String roleNameField = "roleName"; final String externallyDefinedField = "externallyDefined"; RepoUser user = getRepoUser(context, userName); DetachedCriteria criteria = DetachedCriteria.forClass(getPersistentRoleClass()); List<Long> assignedRolesIds = getUserRolesIds(user); if (assignedRolesIds != null && assignedRolesIds.size() > 0) { criteria.add(Restrictions.not(Restrictions.in("id", assignedRolesIds))); } final String roleNameLikeValue = text == null ? "" : text; Criterion roleNameCriterion = Restrictions.ilike(roleNameField, "%" + roleNameLikeValue + "%"); criteria.add(roleNameCriterion); criteria.add(Restrictions.eq(externallyDefinedField, Boolean.FALSE)); if (order) { criteria.addOrder(Order.asc(roleNameField)); } return criteria; } @SuppressWarnings({ "unchecked" }) protected List<Long> getUserRolesIds(RepoUser user) { DetachedCriteria criteria = createAssignedRolesCriteria(null, user, null, true); criteria.setProjection(Projections.id()); return (List<Long>) getHibernateTemplate().findByCriteria(criteria); } @Transactional(propagation = Propagation.REQUIRED) public List getAssignedRoles(ExecutionContext context, String userName, String text, int firstResult, int maxResults) { RepoUser user = getRepoUser(context, userName); DetachedCriteria criteria = createAssignedRolesCriteria(context, user, text, true); List results = getHibernateTemplate().findByCriteria(criteria, firstResult, maxResults); return convertRoleListToDtoList(results); } @Transactional(propagation = Propagation.REQUIRED) public int getAssignedRolesCount(ExecutionContext context, String userName, String text) { RepoUser user = getRepoUser(context, userName); DetachedCriteria criteria = createAssignedRolesCriteria(context, user, text, false); criteria.setProjection(Projections.rowCount()); List results = getHibernateTemplate().findByCriteria(criteria); int rowCount = 0; if (results != null && !results.isEmpty()) { rowCount = (Integer) results.get(0); } return rowCount; } public String getAllowedPasswordPattern() { return passwordPattern.pattern(); } private DetachedCriteria createAssignedRolesCriteria(ExecutionContext context, RepoUser user, String text, boolean order) { final String roleNameField = "roleName"; final String externallyDefinedField = "externallyDefined"; DetachedCriteria criteria = DetachedCriteria.forClass(getPersistentRoleClass()); DetachedCriteria usersCriteria = criteria.createCriteria("users"); usersCriteria.add(Restrictions.idEq(user.getId())); final String roleNameLikeValue = text == null ? "" : text; Criterion roleNameCriterion = Restrictions.ilike(roleNameField, "%" + roleNameLikeValue + "%"); criteria.add(roleNameCriterion); criteria.add(Restrictions.eq(externallyDefinedField, Boolean.FALSE)); if (order) { criteria.addOrder(Order.asc(roleNameField)); } return criteria; } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public void updateUser(ExecutionContext context, String userName, User aUser) { RepoUser existingUser = getRepoUser(context, userName); log.debug("updateUser: " + userName + ", " + existingUser); if (existingUser == null) { log.debug("User not found"); throw new IllegalArgumentException("Cannot find user with name : " + userName); } updatePersistentUser(aUser, existingUser); addPropertiesToUserEvent(new String[] { "updateUser" }, existingUser); getHibernateTemplate().saveOrUpdate(existingUser); } /* (non-Javadoc) * @see com.jaspersoft.jasperserver.api.metadata.user.service.UserAuthorityService#updateRole(com.jaspersoft.jasperserver.api.common.domain.ExecutionContext, com.jaspersoft.jasperserver.api.metadata.user.domain.Role) */ @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public void updateRole(ExecutionContext context, String roleName, Role roleDetails) throws IllegalArgumentException { RepoRole existingRole = getRepoRole(context, roleName); log.debug("updateRole: " + roleName + ", " + existingRole); if (existingRole == null) { log.debug("Role not found"); throw new IllegalArgumentException("Cannot find role with name : " + roleName); } final String newName = roleDetails.getRoleName(); final String tenantId = roleDetails.getTenantId(); if (!existingRole.getRoleName().equals(newName) && getRepoRole(newName, tenantId) != null) { throw new IllegalArgumentException(newName + " must be unique within the organization."); } existingRole.copyFromClient(roleDetails, this); addParametersToRoleManagementAuditEvent(new String[] { "updateRole" }, existingRole, false); getHibernateTemplate().saveOrUpdate(existingRole); } @Transactional(propagation = Propagation.REQUIRED) public List getUsersWithoutRole(ExecutionContext context, String roleName, String userName, int firstResult, int maxResults) { DetachedCriteria criteria = createUsersWithoutRoleCriteria(roleName, userName); List userList = getHibernateTemplate().findByCriteria(criteria, firstResult, maxResults); return convertUserListToDtoList(userList); } @Transactional(propagation = Propagation.REQUIRED) public int getUsersCountWithoutRole(ExecutionContext context, String roleName, String userName) { DetachedCriteria criteria = createUsersWithoutRoleCriteria(roleName, userName, false); criteria.setProjection(Projections.rowCount()); List results = getHibernateTemplate().findByCriteria(criteria); return getRowCountFromResult(results); } protected DetachedCriteria createUsersWithoutRoleCriteria(String roleName, String userName) { return createUsersWithoutRoleCriteria(roleName, userName, true); } protected DetachedCriteria createUsersWithoutRoleCriteria(String roleName, String userName, boolean order) { DetachedCriteria criteria = DetachedCriteria.forClass(getPersistentUserClass()); DetachedCriteria usersWithRoleCriteria = createUsersWithRoleCriteria(roleName, ""); usersWithRoleCriteria.setProjection(Projections.id()); List usersWithRole = getHibernateTemplate().findByCriteria(usersWithRoleCriteria); String userNameField = "username"; // addTenantCriteria(criteria, tenantIds); createSearchByUserNameCriteria(criteria, userName); if (usersWithRole != null && usersWithRole.size() > 0) { criteria.add(Restrictions.not(Restrictions.in("id", usersWithRole))); } if (order) { criteria.addOrder(Order.asc(userNameField)); } return criteria; } private void addTenantCriteria(Criteria criteria, Set tenantIds) { Set internalTenantIds = null; if (tenantIds != null) { internalTenantIds = new HashSet(); internalTenantIds.addAll(tenantIds); if (internalTenantIds.contains(null)) { internalTenantIds.remove(null); internalTenantIds.add(TenantService.ORGANIZATIONS); } } criteria.createAlias("tenant", "tenant", Criteria.LEFT_JOIN); if (internalTenantIds == null) { criteria.add(Restrictions.eq("tenant.tenantId", TenantService.ORGANIZATIONS)); } else { if (!internalTenantIds.isEmpty()) { Criterion idInCriterion = Restrictions.in("tenant.tenantId", internalTenantIds); criteria.add(idInCriterion); } } } protected List getIdByTenantIdSet(Set tenantIds) { DetachedCriteria idCriteria = DetachedCriteria.forClass(getPersistentTenantClass()); idCriteria.add(Restrictions.in("tenantId", tenantIds)); idCriteria.setProjection(Projections.id()); return getHibernateTemplate().findByCriteria(idCriteria); } protected void addVisibleTenantCriteria(DetachedCriteria criteria, Set tenantIds) { Set internalTenantIds = null; if (tenantIds != null) { internalTenantIds = new HashSet(); internalTenantIds.addAll(tenantIds); if (internalTenantIds.contains(null)) { internalTenantIds.remove(null); internalTenantIds.add(TenantService.ORGANIZATIONS); } } if (internalTenantIds == null) { RepoTenant tenant = tenantPersistenceResolver.getPersistentTenant(TenantService.ORGANIZATIONS, true); criteria.add(Restrictions.eq("tenant.id", tenant.getId())); } else { if (!internalTenantIds.isEmpty()) { Criterion idInCriterion = Restrictions.in("tenant.id", getIdByTenantIdSet(internalTenantIds)); criteria.add(idInCriterion); } } } @Transactional(propagation = Propagation.REQUIRED) public List getUsersWithRole(ExecutionContext context, String roleName, String userName, int firstResult, int maxResults) { DetachedCriteria criteria = createUsersWithRoleCriteria(roleName, userName); List userList = getHibernateTemplate().findByCriteria(criteria, firstResult, maxResults); return convertUserListToDtoList(userList); } @Transactional(propagation = Propagation.REQUIRED) public int getUsersCountWithRole(ExecutionContext context, String roleName, String userName) { DetachedCriteria criteria = createUsersWithRoleCriteria(roleName, userName, false); criteria.setProjection(Projections.rowCount()); List results = getHibernateTemplate().findByCriteria(criteria); return getRowCountFromResult(results); } protected DetachedCriteria createUsersWithRoleCriteria(String roleName, String userName) { return createUsersWithRoleCriteria(roleName, userName, true); } protected DetachedCriteria createUsersWithRoleCriteria(String roleName, String userName, boolean order) { DetachedCriteria criteria = DetachedCriteria.forClass(getPersistentUserClass()); String userNameField = "username"; String roleNameField = "roleName"; // addTenantCriteria(criteria, tenantIds); createSearchByUserNameCriteria(criteria, userName); if (roleName != null && roleName.trim().length() > 0) { Criterion roleNameCriterion = Restrictions.eq(roleNameField, roleName.trim()); criteria.createCriteria("roles").add(roleNameCriterion); } if (order) { criteria.addOrder(Order.asc(userNameField)); } return criteria; } protected void createSearchByUserNameCriteria(DetachedCriteria criteria, String userName) { if (userName != null && userName.trim().length() > 0) { Criterion userNameCriterion = Restrictions.ilike("username", "%" + userName.trim() + "%"); Criterion fullNameCriterion = Restrictions.ilike("fullName", "%" + userName.trim() + "%"); criteria.add(Restrictions.or(userNameCriterion, fullNameCriterion)); } } protected int getRowCountFromResult(List results) { Integer rowCount = new Integer(0); if (results != null && !results.isEmpty()) { rowCount = (Integer) results.get(0); } return rowCount.intValue(); } private void addUserParamsToUpdateRoleAuditEvent(final String actionPrefix, final List users) { auditContext.doInAuditContext("updateRole", new AuditContext.AuditContextCallbackWithEvent() { public void execute(AuditEvent auditEvent) { if (users != null && !users.isEmpty()) { for (Object userObject : users) { RepoUser user = (RepoUser) userObject; auditContext.addPropertyToAuditEvent(actionPrefix + "UserId", user.getId(), auditEvent); } } } }); } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public void assignUsers(ExecutionContext context, String roleName, Set userNames) { if (userNames != null && !userNames.isEmpty()) { List users = getUsersByUserNames(context, userNames); addUserParamsToUpdateRoleAuditEvent("added", users); RepoRole role = getRepoRole(context, roleName); for (Iterator it = users.iterator(); it.hasNext();) { RepoUser user = (RepoUser) it.next(); user.addRole(role); } } } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public void unassignUsers(ExecutionContext context, String roleName, Set userNames) { if (userNames != null && !userNames.isEmpty()) { List users = getUsersByUserNames(context, userNames); addUserParamsToUpdateRoleAuditEvent("removed", users); RepoRole role = getRepoRole(context, roleName); for (Iterator it = users.iterator(); it.hasNext();) { RepoUser user = (RepoUser) it.next(); user.removeRole(role); } } } protected List getUsersByUserNames(ExecutionContext context, Set userNames) { DetachedCriteria criteria = DetachedCriteria.forClass(getPersistentUserClass()); if (userNames != null && !userNames.isEmpty()) { criteria.add(Restrictions.in("username", userNames)); } return getHibernateTemplate().findByCriteria(criteria); } @Transactional(propagation = Propagation.REQUIRED) public RepoUser getPersistentUser(String username) { return getRepoUser((ExecutionContext) null, username); } protected boolean isNullTenant(String tenantId) { return tenantId == null || tenantId.length() == 0 || TenantService.ORGANIZATIONS.equals(tenantId); } @Transactional(propagation = Propagation.REQUIRED) public RepoTenant getPersistentTenant(String tenantId, boolean required) { if (isNullTenant(tenantId)) { return getTenantPersistenceResolver().getPersistentTenant(TenantService.ORGANIZATIONS, true); } throw new IllegalArgumentException("This implementation does not support tenants"); } @Transactional(propagation = Propagation.REQUIRED) public RepoTenant getPersistentTenantByAlias(String tenantAlias, boolean required) { if (isNullTenant(tenantAlias)) { return getTenantPersistenceResolver().getPersistentTenant(TenantService.ORGANIZATIONS, true); } throw new IllegalArgumentException("This implementation does not support tenants"); } public TenantPersistenceResolver getTenantPersistenceResolver() { return tenantPersistenceResolver; } public void setTenantPersistenceResolver(TenantPersistenceResolver tenantPersistenceResolver) { this.tenantPersistenceResolver = tenantPersistenceResolver; } @Override public Map<DiagnosticAttribute, DiagnosticCallback> getDiagnosticData() { return new DiagnosticAttributeBuilder().addDiagnosticAttribute(DiagnosticAttributeBuilder.TOTAL_USERS_COUNT, new DiagnosticCallback<Integer>() { @Override public Integer getDiagnosticAttributeValue() { return getUsersCountExceptExcluded(ExecutionContextImpl.getRuntimeExecutionContext(), null, false); } }).addDiagnosticAttribute(DiagnosticAttributeBuilder.TOTAL_ENABLED_USERS_COUNT, new DiagnosticCallback<Integer>() { @Override public Integer getDiagnosticAttributeValue() { return getUsersCountExceptExcluded( ExecutionContextImpl.getRuntimeExecutionContext(), null, true); } }) .addDiagnosticAttribute(DiagnosticAttributeBuilder.TOTAL_ROLES_COUNT, new DiagnosticCallback<Integer>() { @Override public Integer getDiagnosticAttributeValue() { return getTenantRolesCount(ExecutionContextImpl.getRuntimeExecutionContext(), null, null); } }) .build(); } public void setAllowedPasswordPattern(String passwordPattern) { this.passwordPattern = Pattern.compile(passwordPattern); } }