package com.sobey.cmop.mvc.service.account;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.google.common.collect.Lists;
import com.sobey.cmop.mvc.comm.BaseSevcie;
import com.sobey.cmop.mvc.constant.AccountConstant;
import com.sobey.cmop.mvc.dao.DepartmentDao;
import com.sobey.cmop.mvc.dao.GroupDao;
import com.sobey.cmop.mvc.dao.UserDao;
import com.sobey.cmop.mvc.dao.custom.AccountDaoCustom;
import com.sobey.cmop.mvc.entity.Department;
import com.sobey.cmop.mvc.entity.Group;
import com.sobey.cmop.mvc.entity.User;
import com.sobey.framework.utils.Digests;
import com.sobey.framework.utils.DynamicSpecifications;
import com.sobey.framework.utils.Encodes;
import com.sobey.framework.utils.SearchFilter;
import com.sobey.framework.utils.SearchFilter.Operator;
/**
* 安全相关实体的管理类,包括用户和权限组.
*
* @author calvin
*/
// Spring Bean的标识.
@Service
// 默认将类中的所有public函数纳入事务管理.
@Transactional(readOnly = true)
public class AccountService extends BaseSevcie {
private static Logger logger = LoggerFactory.getLogger(AccountService.class);
private UserDao userDao;
private GroupDao groupDao;
private AccountDaoCustom accountDao;
private DepartmentDao departmentDao;
private ShiroDbRealm shiroRealm;
// -- User Manager --//
/**
* 根据用户ID获得用户对象
*
* @param id
* @return
*/
public User getUser(Integer id) {
return userDao.findOne(id);
}
/**
* 获得当前登录User
*
* @return
*/
public User getCurrentUser() {
return userDao.findOne(getCurrentUserId());
}
/**
* User的分页查询.
*
* @param searchParams
* 页面传递过来的参数
* @param pageNumber
* @param pageSize
* @return
*/
public Page<User> getUserPageable(Map<String, Object> searchParams, int pageNumber, int pageSize) {
PageRequest pageRequest = buildPageRequest(pageNumber, pageSize);
// User创建动态查询条件组合.
Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
filters.put("user.status",
new SearchFilter("status", Operator.EQ, AccountConstant.UserStatus.ENABLED.toInteger()));
Specification<User> spec = DynamicSpecifications.bySearchFilter(filters.values(), User.class);
return userDao.findAll(spec, pageRequest);
}
/**
* 注册用户
*
* @param user
*/
@Transactional(readOnly = false)
public void registerUser(User user) {
user.setStatus(AccountConstant.UserStatus.ENABLED.toInteger());
entryptPassword(user);
user.setCreateTime(new Date());
userDao.save(user);
shiroRealm.clearCachedAuthorizationInfo(user.getLoginName());
}
/**
* 更新User
*
* @param user
*/
@Transactional(readOnly = false)
public void updateUser(User user) {
if (StringUtils.isNotBlank(user.getPlainPassword())) {
entryptPassword(user);
}
userDao.save(user);
shiroRealm.clearCachedAuthorizationInfo(user.getLoginName());
}
/**
* 设定安全的密码,生成随机的salt并经过1024次 sha-1 hash
*/
private void entryptPassword(User user) {
byte[] salt = Digests.generateSalt(AccountConstant.SALT_SIZE);
user.setSalt(Encodes.encodeHex(salt));
byte[] hashPassword = Digests.sha1(user.getPlainPassword().getBytes(), salt, AccountConstant.HASH_INTERATIONS);
user.setPassword(Encodes.encodeHex(hashPassword));
}
/**
* 删除用户,如果尝试删除超级管理员将抛出异常.
*/
@Transactional(readOnly = false)
public boolean deleteUser(Integer id) {
boolean flag = false;
if (this.isSupervisor(id)) {
logger.warn("操作员{}尝试删除超级管理员用户", SecurityUtils.getSubject().getPrincipal());
} else {
userDao.delete(id);
flag = true;
}
return flag;
}
/**
* 判断是否超级管理员.
*/
private boolean isSupervisor(Integer id) {
return id == 1;
}
/**
* 根据邮箱Email 获得所属的User
*
* @param email
* @return
*/
public User findUserByEmail(String email) {
return userDao.findByEmail(email);
}
/**
* 根据登录名获得所属的User
*
* @param loginName
* @return
*/
public User findUserByLoginName(String loginName) {
return userDao.findByLoginName(loginName);
}
/**
* 获得指派人的User
*
* @param redmineUserId
* @return
*/
public User findUserByRedmineUserId(Integer redmineUserId) {
return userDao.findByRedmineUserId(redmineUserId);
}
/**
* 根据Type字段获得用户List.
*
* type从 枚举 DefaultGroups 获得:1-管理员;2-申请人;3-审批人. 设置type为 3.审批人. 获得领导列表
*
* @param type
*/
public List<User> getUserListByType(Integer type) {
return userDao.findByType(type);
}
/**
* 获得所有的用户列表
*
* @return
*/
public List<User> getUsers() {
return (List<User>) userDao.findAll();
}
/**
* 初始化所有User的密码和LoginName, 将老系统的邮箱@前的字符串设置为新的loginName.
*/
@Transactional(readOnly = false)
public void initializeUser() {
List<User> users = (List<User>) userDao.findAll();
for (User user : users) {
String email = user.getEmail();
// 如果email中包含@,取@前的字符串赋予给loginName
String loginName = email.indexOf("@") == -1 ? email : email.substring(0, email.indexOf("@"));
user.setLoginName(loginName);
user.setPlainPassword(AccountConstant.DEFAULT_PASSWORD);
entryptPassword(user);
user.setCreateTime(new Date());
user.setEmail(email + "@sobey.com");
userDao.save(user);
}
}
// -- Group Manager --//
public Group getGroup(Integer id) {
return groupDao.findOne(id);
}
public Group findGroupByName(String name) {
return groupDao.findByName(name);
}
/**
* 获得指定用户所拥有的权限组
*
* 如果指定用户没有权限组,则返回默认权限:2.apply 申请人
*
* @param userId
* @return
*/
@SuppressWarnings("rawtypes")
public Group findGroupByUserId(Integer userId) {
List list = accountDao.getUserGroupByUserId(userId);
return list.isEmpty() ? getGroup(AccountConstant.DefaultGroups.apply.toInteger()) : getGroup((Integer) list
.get(0));
}
public List<Group> findAllGroup() {
return (List<Group>) groupDao.findAll((new Sort(Direction.ASC, "id")));
}
/**
* 根据groupId获得Group所拥有的授权.
*
* @param groupId
* @return
*/
public List<String> getPermissionByGroupId(Integer groupId) {
return accountDao.getGroupPermissionByGroupId(groupId);
}
/**
* 根据groupId获得GroupList 集合.
*/
public List<Group> getGroupListById(Integer groupId) {
List<Group> groupList = Lists.newArrayList();
groupList.add(this.getGroup(groupId));
return groupList;
}
/**
* Group的分页查询.
*
* @param searchParams
* @param pageNumber
* @param pageSize
* @return
*/
public Page<Group> getGroupPageable(Map<String, Object> searchParams, int pageNumber, int pageSize) {
PageRequest pageRequest = buildPageRequest(pageNumber, pageSize);
Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
Specification<Group> spec = DynamicSpecifications.bySearchFilter(filters.values(), Group.class);
return groupDao.findAll(spec, pageRequest);
}
@Transactional(readOnly = false)
public void saveGroup(Group group) {
groupDao.save(group);
shiroRealm.clearAllCachedAuthorizationInfo();
}
@Transactional(readOnly = false)
public boolean deleteGroup(Integer id) {
if (this.isDefautlGroup(id)) {
logger.warn("操作员{}尝试删除默认权限组", SecurityUtils.getSubject().getPrincipal());
return false;
} else {
groupDao.delete(id);
shiroRealm.clearAllCachedAuthorizationInfo();
return true;
}
}
/**
* 判断是否是默认的Group
*
* <pre>
* 1.admin
* 2.apply
* 3.audit
* 4.om_a
* 5.om_b
* </pre>
*
* @param id
* groupId
* @return
*/
private boolean isDefautlGroup(Integer id) {
List<Integer> list = new ArrayList<Integer>();
list.add(AccountConstant.DefaultGroups.admin.toInteger());
list.add(AccountConstant.DefaultGroups.apply.toInteger());
list.add(AccountConstant.DefaultGroups.audit.toInteger());
list.add(AccountConstant.DefaultGroups.om_a.toInteger());
list.add(AccountConstant.DefaultGroups.om_b.toInteger());
return list.contains(id);
}
// -- Department Manager --//
public Department getDepartment(Integer id) {
return departmentDao.findOne(id);
}
@Resource
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Resource
public void setGroupDao(GroupDao groupDao) {
this.groupDao = groupDao;
}
@Resource
public void setAccountDao(AccountDaoCustom accountDao) {
this.accountDao = accountDao;
}
@Resource
public void setDepartmentDao(DepartmentDao departmentDao) {
this.departmentDao = departmentDao;
}
@Resource
public void setShiroRealm(ShiroDbRealm shiroRealm) {
this.shiroRealm = shiroRealm;
}
}