// // Copyright 2009 Robin Komiwes, Bruno Verachten, Christophe Cordenier // // 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 com.wooki.domain.biz; import java.math.BigInteger; import java.util.Arrays; import java.util.Date; import org.springframework.context.ApplicationContext; import org.springframework.security.acls.AclPermissionEvaluator; import org.springframework.security.acls.domain.BasePermission; import org.springframework.security.acls.model.AclCache; import org.springframework.security.authentication.dao.SaltSource; import org.springframework.security.authentication.encoding.PasswordEncoder; import org.springframework.security.core.context.SecurityContextHolder; import com.ibm.icu.util.Calendar; import com.wooki.domain.dao.ActivityDAO; import com.wooki.domain.dao.UserDAO; import com.wooki.domain.exception.AuthorizationException; import com.wooki.domain.exception.UserAlreadyException; import com.wooki.domain.model.Authority; import com.wooki.domain.model.User; import com.wooki.domain.model.WookiGrantedAuthority; import com.wooki.domain.model.activity.AccountActivity; import com.wooki.domain.model.activity.AccountEventType; import com.wooki.services.security.WookiSecurityContext; public class UserManagerImpl implements UserManager { private AclCache aclCache; private final UserDAO userDao; private final ActivityDAO activityDao; private final WookiSecurityContext securityCtx; private final SecurityManager securityManager; private final SaltSource saltSource; private final PasswordEncoder passwordEncoder; private final AclPermissionEvaluator aclPermissionEvaluator; public UserManagerImpl(UserDAO userDAO, ActivityDAO activityDAO, ApplicationContext applicationContext) { this.userDao = userDAO; this.activityDao = activityDAO; this.securityCtx = applicationContext.getBean(WookiSecurityContext.class); this.saltSource = applicationContext.getBean(SaltSource.class); this.passwordEncoder = applicationContext.getBean(PasswordEncoder.class); this.aclPermissionEvaluator = applicationContext.getBean(AclPermissionEvaluator.class); this.securityManager = applicationContext.getBean(SecurityManager.class); this.aclCache = applicationContext.getBean(AclCache.class); } public void registerUser(User author) throws UserAlreadyException { if (findByUsername(author.getUsername()) != null) { throw new UserAlreadyException(); } // Encode password into database String pass = author.getPassword(); author.setCreationDate(new Date()); author.setPassword(this.passwordEncoder.encodePassword(pass, this.saltSource .getSalt(author))); // Add default Author Role author.setGrantedAuthorities(Arrays.asList(new Authority[] { this.securityManager.getOrCreateAuthority(WookiGrantedAuthority.ROLE_AUTHOR .getAuthority()) })); userDao.create(author); AccountActivity aa = new AccountActivity(); aa.setCreationDate(Calendar.getInstance().getTime()); aa.setType(AccountEventType.JOIN); aa.setUser(author); this.activityDao.create(aa); // Set permission this.securityCtx.log(author); this.securityManager.setOwnerPermission(author); } public User findByUsername(String username) { return userDao.findByUsername(username); } public User findById(Long userId) { assert userId != null; return userDao.findById(userId); } public String[] listUserNames(String prefix) { return userDao.listUserNames(prefix); } public User updateDetails(User user) throws UserAlreadyException { assert user != null; if (!this.securityCtx.isLoggedIn() || !this.aclPermissionEvaluator.hasPermission(SecurityContextHolder.getContext() .getAuthentication(), user, BasePermission.ADMINISTRATION)) { throw new AuthorizationException( "Action not authorized"); } User userByUsername = findByUsername(user.getUsername()); // check if the new username is not already taken by someone else if (userByUsername != null && userByUsername.getId() != user.getId()) { // Reset user state and throw an exception userDao.refresh(user); throw new UserAlreadyException(); } // Update sid BigInteger sidId = userDao.findSid(securityCtx.getUsername()); if (sidId != null) { userDao.updateSid(sidId, user.getUsername()); } // Force re-log this.securityCtx.log(user); userDao.update(user); // TODO Not satisfying, we should clear only the Acl for user object aclCache.clearCache(); return user; } public void resetPassword(User user, String newPassword) { assert user != null; assert newPassword != null; if (!securityCtx.hasAuthority(WookiGrantedAuthority.ROLE_ADMIN)) { throw new AuthorizationException(); } user.setPassword(this.passwordEncoder.encodePassword(newPassword, this.saltSource .getSalt(user))); userDao.update(user); } public User updatePassword(User user, String oldPassword, String newPassword) throws AuthorizationException { assert user != null; assert oldPassword != null; assert newPassword != null; // Check access if (this.aclPermissionEvaluator.hasPermission(SecurityContextHolder.getContext() .getAuthentication(), user, BasePermission.ADMINISTRATION)) { // In case of admin rights, bypass previous old password checking if (!securityCtx.hasAuthority(WookiGrantedAuthority.ROLE_ADMIN)) { String encodedPassword = this.passwordEncoder.encodePassword( oldPassword, this.saltSource.getSalt(user)); if (!encodedPassword.equals(this.securityCtx.getUser().getPassword())) { throw new AuthorizationException(); } } user.setPassword(this.passwordEncoder.encodePassword(newPassword, this.saltSource .getSalt(user))); this.securityCtx.log(userDao.update(user)); return user; } else { throw new AuthorizationException("You do not have enough rights to do this action"); } } }