/*! * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * 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 Lesser General Public License for more details. * * Copyright (c) 2002-2017 Pentaho Corporation.. All rights reserved. */ package org.pentaho.platform.web.http.api.resources.services; import org.apache.commons.lang3.StringUtils; import org.pentaho.platform.api.engine.IAuthorizationPolicy; import org.pentaho.platform.api.engine.IPentahoSession; import org.pentaho.platform.api.engine.security.userroledao.IPentahoRole; import org.pentaho.platform.api.engine.security.userroledao.IPentahoUser; import org.pentaho.platform.api.engine.security.userroledao.IUserRoleDao; import org.pentaho.platform.api.engine.security.userroledao.NotFoundException; import org.pentaho.platform.api.engine.security.userroledao.UncategorizedUserRoleDaoException; import org.pentaho.platform.api.mt.ITenant; import org.pentaho.platform.engine.core.system.PentahoSessionHolder; import org.pentaho.platform.engine.core.system.PentahoSystem; import org.pentaho.platform.engine.core.system.TenantUtils; import org.pentaho.platform.engine.security.SecurityHelper; import org.pentaho.platform.repository2.userroledao.jackrabbit.security.DefaultPentahoPasswordEncoder; import org.pentaho.platform.security.policy.rolebased.IRoleAuthorizationPolicyRoleBindingDao; import org.pentaho.platform.security.policy.rolebased.RoleBindingStruct; import org.pentaho.platform.security.policy.rolebased.actions.AdministerSecurityAction; import org.pentaho.platform.security.policy.rolebased.actions.RepositoryCreateAction; import org.pentaho.platform.security.policy.rolebased.actions.RepositoryReadAction; import org.pentaho.platform.web.http.api.resources.LocalizedLogicalRoleName; import org.pentaho.platform.web.http.api.resources.LogicalRoleAssignment; import org.pentaho.platform.web.http.api.resources.LogicalRoleAssignments; import org.pentaho.platform.web.http.api.resources.RoleListWrapper; import org.pentaho.platform.web.http.api.resources.SystemRolesMap; import org.pentaho.platform.web.http.api.resources.User; import org.pentaho.platform.web.http.api.resources.UserListWrapper; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import java.util.concurrent.Callable; public class UserRoleDaoService { private IUserRoleDao roleDao; private IAuthorizationPolicy policy; private IRoleAuthorizationPolicyRoleBindingDao roleBindingDao; public UserListWrapper getUsers() throws Exception { return new UserListWrapper( getRoleDao().getUsers() ); } public RoleListWrapper getRolesForUser( String user ) throws UncategorizedUserRoleDaoException { ITenant tenant = TenantUtils.getCurrentTenant(); return new RoleListWrapper( getRoleDao().getUserRoles( tenant, user ) ); } public void assignRolesToUser( String userName, String roleNames ) throws NotFoundException, UncategorizedUserRoleDaoException, SecurityException { if ( canAdminister() ) { StringTokenizer tokenizer = new StringTokenizer( roleNames, "\t" ); Set<String> assignedRoles = new HashSet<String>(); ITenant tenant = TenantUtils.getCurrentTenant(); //Build the set of roles the user already contians for ( IPentahoRole pentahoRole : getRoleDao().getUserRoles( tenant, userName ) ) { assignedRoles.add( pentahoRole.getName() ); } //Append the parameter of roles while ( tokenizer.hasMoreTokens() ) { assignedRoles.add( tokenizer.nextToken() ); } getRoleDao().setUserRoles( tenant, userName, assignedRoles.toArray( new String[ assignedRoles.size() ] ) ); } else { throw new SecurityException(); } } public void removeRolesFromUser( String userName, String roleNames ) throws NotFoundException, UncategorizedUserRoleDaoException, SecurityException { if ( canAdminister() ) { StringTokenizer tokenizer = new StringTokenizer( roleNames, "\t" ); Set<String> assignedRoles = new HashSet<String>(); ITenant tenant = TenantUtils.getCurrentTenant(); for ( IPentahoRole pentahoRole : getRoleDao().getUserRoles( tenant, userName ) ) { assignedRoles.add( pentahoRole.getName() ); } while ( tokenizer.hasMoreTokens() ) { assignedRoles.remove( tokenizer.nextToken() ); } getRoleDao().setUserRoles( tenant, userName, assignedRoles.toArray( new String[assignedRoles.size()] ) ); } else { throw new SecurityException(); } } public void createRole( String roleName ) throws Exception { if ( canAdminister() ) { if ( strNotEmpty( roleName ) ) { IUserRoleDao roleDao = PentahoSystem.get( IUserRoleDao.class, "userRoleDaoProxy", PentahoSessionHolder.getSession() ); roleDao.createRole( null, roleName, "", new String[0] ); } else { throw new ValidationFailedException(); } } else { throw new SecurityException(); } } public RoleListWrapper getRoles() throws UncategorizedUserRoleDaoException { return new RoleListWrapper( getRoleDao().getRoles() ); } public UserListWrapper getRoleMembers( String roleName ) throws UncategorizedUserRoleDaoException, SecurityException { if ( canAdminister() ) { return new UserListWrapper( getRoleDao().getRoleMembers( TenantUtils.getCurrentTenant(), roleName ) ); } else { throw new SecurityException(); } } private boolean containsReservedChars( String username ) { StringBuffer reservedChars = new FileService().doGetReservedChars(); return StringUtils.containsAny( username, reservedChars ); } private boolean strNotEmpty( String str ) { return str != null && str.length() > 0; } private boolean userValid( User user ) { String name = user.getUserName(); String pass = user.getPassword(); boolean nameValid = strNotEmpty( name ) && !containsReservedChars( name ); boolean passValid = strNotEmpty( pass ); return nameValid && passValid; } private String decode( String toDecode ) { try { return URLDecoder.decode( toDecode.replace( "+", "%2B" ), "UTF-8" ); } catch ( UnsupportedEncodingException e ) { return toDecode; } } public void createUser( User user ) throws Exception { if ( canAdminister() ) { if ( userValid( user ) ) { IUserRoleDao roleDao = PentahoSystem.get( IUserRoleDao.class, "userRoleDaoProxy", PentahoSessionHolder.getSession() ); roleDao.createUser( null, decode( user.getUserName() ), decode( user.getPassword() ), "", new String[0] ); } else { throw new ValidationFailedException(); } } else { throw new SecurityException(); } } private boolean inputValid( String userName, String newPass, String oldPass ) { boolean userNameValid = ( userName != null && userName.length() > 0 ); boolean newPassValid = ( newPass != null && newPass.length() > 0 ); boolean oldPassValid = ( oldPass != null && oldPass.length() > 0 ); return userNameValid && newPassValid && oldPassValid; } private boolean credentialValid( IPentahoUser pentahoUser, String oldPass ) { if ( pentahoUser != null ) { DefaultPentahoPasswordEncoder encoder = new DefaultPentahoPasswordEncoder(); return encoder.isPasswordValid( pentahoUser.getPassword(), oldPass, null ); } return false; } public void changeUserPassword( final String userName, final String newPass, String oldPass ) throws Exception { if ( inputValid( userName, newPass, oldPass ) ) { final IPentahoSession pentahoSession = PentahoSessionHolder.getSession(); //You must be either an admin or trying to change your own password if ( canAdminister() || ( null != pentahoSession && userName.equals( pentahoSession.getName() ) ) ) { final IUserRoleDao roleDao = PentahoSystem.get( IUserRoleDao.class, "userRoleDaoProxy", pentahoSession ); IPentahoUser pentahoUser = roleDao.getUser( null, userName ); if ( credentialValid( pentahoUser, oldPass ) ) { SecurityHelper.getInstance().runAsSystem( new Callable<Void>() { @Override public Void call() throws Exception { roleDao.setPassword( null, userName, newPass ); return null; } } ); } else { throw new SecurityException(); } } else { throw new SecurityException(); } } else { throw new ValidationFailedException(); } } public void deleteUsers( String userNames ) throws NotFoundException, UncategorizedUserRoleDaoException, SecurityException { if ( canAdminister() ) { StringTokenizer tokenizer = new StringTokenizer( userNames, "\t" ); while ( tokenizer.hasMoreTokens() ) { IPentahoUser user = getRoleDao().getUser( null, tokenizer.nextToken() ); if ( user != null ) { getRoleDao().deleteUser( user ); } } } else { throw new SecurityException(); } } public void deleteRoles( String roleNames ) throws SecurityException, UncategorizedUserRoleDaoException { if ( canAdminister() ) { StringTokenizer tokenizer = new StringTokenizer( roleNames, "\t" ); while ( tokenizer.hasMoreTokens() ) { IPentahoRole role = getRoleDao().getRole( null, tokenizer.nextToken() ); if ( role != null ) { getRoleDao().deleteRole( role ); } } } else { throw new SecurityException(); } } public SystemRolesMap getRoleBindingStruct( String locale ) throws SecurityException { if ( canAdminister() ) { RoleBindingStruct roleBindingStruct = getRoleBindingDao().getRoleBindingStruct( locale ); SystemRolesMap systemRolesMap = new SystemRolesMap(); for ( Map.Entry<String, String> localalizeNameEntry : roleBindingStruct.logicalRoleNameMap.entrySet() ) { systemRolesMap.getLocalizedRoleNames().add( new LocalizedLogicalRoleName( localalizeNameEntry.getKey(), localalizeNameEntry.getValue() ) ); } for ( Map.Entry<String, List<String>> logicalRoleAssignments : roleBindingStruct.bindingMap.entrySet() ) { systemRolesMap.getAssignments().add( new LogicalRoleAssignment( logicalRoleAssignments.getKey(), logicalRoleAssignments.getValue(), roleBindingStruct.immutableRoles.contains( logicalRoleAssignments.getKey() ) ) ); } return systemRolesMap; } else { throw new SecurityException(); } } public void setLogicalRoles( LogicalRoleAssignments roleAssignments ) throws SecurityException { if ( canAdminister() ) { for ( LogicalRoleAssignment roleAssignment : roleAssignments.getAssignments() ) { getRoleBindingDao().setRoleBindings( roleAssignment.getRoleName(), roleAssignment.getLogicalRoles() ); } } else { throw new SecurityException(); } } public void updatePassword( User user ) throws SecurityException { if ( canAdminister() ) { String userName = decode( user.getUserName() ); String password = decode( user.getPassword() ); IUserRoleDao roleDao = PentahoSystem.get( IUserRoleDao.class, "userRoleDaoProxy", PentahoSessionHolder.getSession() ); IPentahoUser puser = roleDao.getUser( null, userName ); if ( puser != null ) { roleDao.setPassword( null, userName, password ); } } else { throw new SecurityException(); } } private boolean canAdminister() { return getPolicy().isAllowed( RepositoryReadAction.NAME ) && getPolicy().isAllowed( RepositoryCreateAction.NAME ) && ( getPolicy().isAllowed( AdministerSecurityAction.NAME ) ); } private IRoleAuthorizationPolicyRoleBindingDao getRoleBindingDao() { if ( roleBindingDao == null ) { roleBindingDao = PentahoSystem.get( IRoleAuthorizationPolicyRoleBindingDao.class ); } return roleBindingDao; } private IAuthorizationPolicy getPolicy() { if ( policy == null ) { policy = PentahoSystem.get( IAuthorizationPolicy.class ); } return policy; } private IUserRoleDao getRoleDao() { if ( roleDao == null ) { roleDao = PentahoSystem.get( IUserRoleDao.class ); } return roleDao; } public static class ValidationFailedException extends Exception { } }