package com.bstek.bdf3.security.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.bstek.bdf3.jpa.JpaUtil;
import com.bstek.bdf3.security.decision.manager.SecurityDecisionManager;
import com.bstek.bdf3.security.orm.Permission;
import com.bstek.bdf3.security.orm.Url;
import com.bstek.bdf3.security.orm.User;

/**
 * @author Kevin Yang (mailto:kevin.yang@bstek.com)
 * @since 2016年1月30日
 */
@Service
@Transactional(readOnly = true)
public class UrlServiceImpl implements UrlService {
	@Autowired
	private UrlServiceCache urlServiceCache;
	
	@Autowired
	private UserService userService;
	
	@Autowired
	private SecurityDecisionManager securityDecisionManager;
	
	@Autowired
	private GrantedAuthorityService grantedAuthorityService;
	
	@Override
	public List<Url> findAll() {
		List<Url> urls = JpaUtil.linq(Url.class).list();
		List<Permission> permissions = JpaUtil.linq(Permission.class).equal("resourceType", Url.RESOURCE_TYPE).list();
		if (!permissions.isEmpty()) {
			Map<String, Url> urlMap = JpaUtil.index(urls);
			for (Permission permission : permissions) {
				Url url = urlMap.get(permission.getResourceId());
				List<ConfigAttribute> configAttributes = url.getAttributes();
				if (configAttributes == null) {
					configAttributes = new ArrayList<ConfigAttribute>();
					url.setAttributes(configAttributes);
				}
				configAttributes.add(permission);
			}
		}
		return urls;
	}
	
	public List<Url> findTree() {
		return urlServiceCache.findTree();
	}
	
	@Override
	public List<Url> findTreeByUsername(String username) {
		List<Url> urls = urlServiceCache.findTree();
		List<Url> result = new ArrayList<Url>();
		rebuildLoginUserGrantedAuthorities();
		for (Url url : urls) {
			if (decide(null, url, userService.isAdministrator())) {
				result.add(url);
			}
		}
		return result;
	}
	
	@Override
	public List<Url> getAccessibleUrlsByUsername(String username) {
		List<Url> urls = urlServiceCache.findTree();
		List<Url> result = new ArrayList<Url>();
		for (Url url : urls) {
			if (decide(username, url, userService.isAdministrator(username))) {
				result.add(url);
			}
		}
		return result;
	}
		
	private void rebuildLoginUserGrantedAuthorities() {
		User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		user.setAuthorities(grantedAuthorityService.getGrantedAuthorities(user));
	}

	private boolean decide(String username, Url url, boolean administrator) {
		if (!url.isNavigable()) {
			return false;
		}
		if (administrator || securityDecisionManager.decide(username, url)) {
			List<Url> children = url.getChildren();
			List<Url> newChildren = new ArrayList<Url>();
			url.setChildren(newChildren);
			if (!CollectionUtils.isEmpty(children)) {
				for (Url child : children) {
					if (decide(username, child, administrator)) {
						newChildren.add(child);
					}
				}
			}
			return true;
		}
		return false;
		
		
	}


}

@@ -2090,23 +2090,61 @@
 %0A%09%09%09
-if (decide(null
+Url copy = copyFor(url);%0A%09%09%09if (decide(username, copy
 , ur
@@ -2187,35 +2187,36 @@
 %0A%09%09%09%09result.add(
-url
+copy
 );%0A%09%09%09%7D%0A%09%09%7D%0A%09%09re
@@ -2229,24 +2229,349 @@
 esult;%0A%09%7D%0A%09%0A
+%09protected Url copyFor(Url url) %7B%0A%09%09Url u = new Url();%0A%09%09u.setId(url.getId());%0A%09%09u.setIcon(url.getIcon());%0A%09%09u.setDescription(url.getDescription());%0A%09%09u.setName(url.getName());%0A%09%09u.setNavigable(url.isNavigable());%0A%09%09u.setOrder(url.getOrder());%0A%09%09u.setParentId(url.getParentId());%0A%09%09u.setPath(url.getPath());%0A%09%09return u;%0A%09%7D%0A%09%0A
 %09@Override%0A%09
@@ -2749,16 +2749,44 @@
 urls) %7B%0A
+%09%09%09Url copy = copyFor(url);%0A
 %09%09%09if (d
@@ -2796,24 +2796,30 @@
 de(username,
+ copy,
  url, userSe
@@ -2869,19 +2869,20 @@
 ult.add(
-url
+copy
 );%0A%09%09%09%7D%0A
@@ -3173,16 +3173,26 @@
 sername,
+ Url copy,
  Url url
@@ -3434,19 +3434,20 @@
 %3E();%0A%09%09%09
-url
+copy
 .setChil
@@ -3539,24 +3539,61 @@
 children) %7B%0A
+%09%09%09%09%09Url copyChild = copyFor(child);%0A
 %09%09%09%09%09if (dec
@@ -3605,16 +3605,27 @@
 sername,
+ copyChild,
  child, 
@@ -3665,16 +3665,20 @@
 en.add(c
+opyC
 hild);%0A%09

修复权限管理模块在分配权限后，不同用户切换登录后出现不正确的菜单