/* * Copyright 2013-2017 Simba Open Source * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.simbasecurity.core.service.manager; import org.simbasecurity.api.service.thrift.AuthorizationService; import org.simbasecurity.api.service.thrift.SSOToken; import org.simbasecurity.core.config.ConfigurationService; import org.simbasecurity.core.domain.*; import org.simbasecurity.core.domain.generator.PasswordGenerator; import org.simbasecurity.core.domain.repository.*; import org.simbasecurity.core.exception.SimbaException; import org.simbasecurity.core.service.manager.assembler.*; import org.simbasecurity.core.service.manager.dto.*; import org.simbasecurity.core.service.manager.interceptor.ManagerSecurityInterceptor; import org.simbasecurity.core.service.manager.web.JsonBody; import org.simbasecurity.core.service.validation.DTOValidator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; import java.util.Collection; import java.util.List; import java.util.Set; import static org.simbasecurity.common.request.RequestConstants.SIMBA_SSO_TOKEN; import static org.simbasecurity.core.config.SimbaConfigurationParameter.PASSWORD_CHANGE_REQUIRED; import static org.simbasecurity.core.exception.SimbaMessageKey.USER_ALREADY_EXISTS; import static org.simbasecurity.core.service.ErrorSender.*; /** * Called from the manager GUI. This service is guarded by the * {@link ManagerSecurityInterceptor}. The chain called there contains a Command * that check if you are admin. */ @Transactional @Controller @RequestMapping("user") public class UserManagerService { @Autowired private AuthorizationService.Iface authorizationService; @Autowired private UserRepository userRepository; @Autowired private RoleRepository roleRepository; @Autowired private PolicyRepository policyRepository; @Autowired private GroupRepository groupRepository; @Autowired private SessionRepository sessionRepository; @Autowired private ConfigurationService configurationService; @Autowired private EntityFilterService filterService; @Autowired private PasswordGenerator passwordGenerator; @RequestMapping("findAll") @ResponseBody public Collection<UserDTO> findAll() { return UserDTOAssembler.assemble(filterService.filterUsers(userRepository.findAll())); } @RequestMapping("findByRole") @ResponseBody public Collection<UserDTO> find(@RequestBody RoleDTO role) { return UserDTOAssembler.assemble(filterService.filterUsers(userRepository.findForRole(roleRepository.lookUp(role)))); } @RequestMapping("findRoles") @ResponseBody public Collection<RoleDTO> findRoles(@RequestBody UserDTO user) { return RoleDTOAssembler.assemble(filterService.filterRoles(roleRepository.findForUser(userRepository.lookUp(user)))); } @RequestMapping("findRolesNotLinked") @ResponseBody public Collection<RoleDTO> findRolesNotLinked(@RequestBody UserDTO user) { return RoleDTOAssembler.assemble(filterService.filterRoles(roleRepository.findNotLinked(userRepository.lookUp(user)))); } @RequestMapping("removeRole") @ResponseBody public void removeRole(@JsonBody("user") UserDTO user, @JsonBody("role") RoleDTO role) { User attachedUser = userRepository.refreshWithOptimisticLocking(user); Role attachedRole = roleRepository.refreshWithOptimisticLocking(role); attachedUser.removeRole(attachedRole); } @RequestMapping("addRoles") @ResponseBody public void addRoles(@JsonBody("user") UserDTO user, @JsonBody("roles") Set<RoleDTO> roles) { User attachedUser = userRepository.refreshWithOptimisticLocking(user); Collection<Role> attachedRoles = roleRepository.refreshWithOptimisticLocking(roles); attachedUser.addRoles(attachedRoles); } @RequestMapping("findPolicies") @ResponseBody public Collection<PolicyDTO> findPolicies(@RequestBody UserDTO user) { return PolicyDTOAssembler.assemble(filterService.filterPolicies(policyRepository.find(userRepository.lookUp(user)))); } @RequestMapping("findGroups") @ResponseBody public Collection<GroupDTO> findGroups(@RequestBody UserDTO user) { return GroupDTOAssembler.assemble(groupRepository.find(userRepository.lookUp(user))); } @RequestMapping("resetPassword") @ResponseBody public UserDTO resetPassword(@RequestBody UserDTO user, HttpServletResponse response) { User attachedUser = userRepository.refreshWithOptimisticLocking(user); try { attachedUser.resetPassword(); } catch (SimbaException ex) { sendError(UNABLE_TO_RESET_PASSWORD_ERROR_CODE, response, "Something went wrong while resetting the password of user '" + attachedUser.getUserName() + "'. Message: " + ex.getMessage()); } userRepository.flush(); return UserDTOAssembler.assemble(attachedUser); } @RequestMapping("changePassword") @ResponseBody public void changeUserPassword(@RequestHeader(value = SIMBA_SSO_TOKEN, required = false) String ssoTokenFromHeader, @CookieValue(value = SIMBA_SSO_TOKEN, required = false) String ssoTokenFromCookie, @RequestBody ChangePasswordDTO changePasswordDTO, HttpServletResponse response) { String ssoToken = (ssoTokenFromHeader != null ? ssoTokenFromHeader : ssoTokenFromCookie); if (ssoToken == null) { sendUnauthorizedError(response); return; } Session activeSession = sessionRepository.findBySSOToken(new SSOToken(ssoToken)); if (activeSession == null) { sendUnauthorizedError(response); } else { User attachedUser = userRepository.findByName(changePasswordDTO.getUserName()); if (attachedUser == null) { sendError(NO_USER_FOUND_ERROR_CODE, response, "User with user name '" + changePasswordDTO.getUserName() + "' not found"); return; } try { attachedUser.changePassword(changePasswordDTO.getNewPassword(), changePasswordDTO.getNewPasswordConfirmation()); } catch (SimbaException ex) { sendError(UNABLE_TO_CHANGE_PASSWORD_ERROR_CODE, response, "Something went wrong while changing the password of user : " + attachedUser.getUserName() + ". Message : " + ex.getMessage()); return; } userRepository.flush(); } } @RequestMapping("createWithRoles") @ResponseBody public UserDTO create(@JsonBody("user") UserDTO user, @JsonBody("roleNames") List<String> roleNames) { User newUser = createUser(user); for (String roleName : roleNames) { Role role = roleRepository.findByName(roleName); if (role == null) { throw new IllegalArgumentException("Role name " + roleName + " doesn't exist"); } newUser.addRole(role); } return UserDTOAssembler.assemble(newUser); } @RequestMapping("create") @ResponseBody public UserDTO create(@RequestBody UserDTO user) { return UserDTOAssembler.assemble(createUser(user)); } @RequestMapping("createAsClone") @ResponseBody public UserDTO create(@JsonBody("user") UserDTO user, @JsonBody("userName") String userName) { Set<Role> roles = userRepository.findByName(userName).getRoles(); User newUser = createUser(user); newUser.addRoles(roles); return UserDTOAssembler.assemble(newUser); } private User createUser(UserDTO user) { DTOValidator.assertValid(user); if (userRepository.findByName(user.getUserName()) != null) { throw new SimbaException(USER_ALREADY_EXISTS, user.getUserName()); } Boolean passwordChangeRequired = configurationService.getValue(PASSWORD_CHANGE_REQUIRED); user.setPasswordChangeRequired(passwordChangeRequired); return userRepository.persist(UserAssembler.assemble(user)); } @RequestMapping("createRestUser") @ResponseBody public String createRestUser(@JsonBody("userName") String username) { UserDTO userDTO = new UserDTO(); userDTO.setUserName(username); userDTO.setPasswordChangeRequired(false); userDTO.setChangePasswordOnNextLogon(false); userDTO.setLanguage(Language.nl_NL); userDTO.setStatus(Status.ACTIVE); UserEntity userEntity = userRepository.persist(UserAssembler.assemble(userDTO)); String password = passwordGenerator.generatePassword(); userEntity.changePassword(password, password); return password; } @RequestMapping("update") @ResponseBody public UserDTO update(@RequestBody UserDTO user) { DTOValidator.assertValid(user); User attachedUser = userRepository.refreshWithOptimisticLocking(user); attachedUser.setFirstName(user.getFirstName()); attachedUser.setName(user.getName()); attachedUser.setLanguage(user.getLanguage()); attachedUser.setChangePasswordOnNextLogon(user.isChangePasswordOnNextLogon()); attachedUser.setStatus(user.getStatus()); attachedUser.setSuccessURL(user.getSuccessURL()); userRepository.flush(); return UserDTOAssembler.assemble(attachedUser); } @RequestMapping("refresh") @ResponseBody public UserDTO refresh(@RequestBody UserDTO user) { return UserDTOAssembler.assemble(userRepository.lookUp(user)); } }