package com.lightinit.hsdatashow.spring;

import com.lightinit.hsdatashow.entity.Admin;
import com.lightinit.hsdatashow.entity.SentryRole;
import com.lightinit.hsdatashow.entity.SentryRoleAction;
import com.lightinit.hsdatashow.service.IAdminService;
import com.lightinit.hsdatashow.service.IRoleService;
import com.lightinit.hsdatashow.service.IShiroPermissionsService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.authz.permission.WildcardPermission;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Created by Mr.Yao on 2017/3/22.
 */
public class SentryRealm extends AuthorizingRealm {
    @Autowired
    private IAdminService adminService;
    @Autowired
    private IRoleService roleService;
    @Autowired
    private IShiroPermissionsService shiroPermissionsService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals){
        String username = (String)principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        //暂时不加权限
        Set<String> roles = new HashSet<String>();
        List<SentryRole> adminRoleList= roleService.QueryRoleList(username);
        boolean isSuperAdmin=false;
        for (SentryRole role:adminRoleList) {
            if(isSuperAdmin==false)
                isSuperAdmin=role.getRolecode().equalsIgnoreCase("admin");
            roles.add(role.getRolecode());
        }
        authorizationInfo.setRoles(roles);
        Set<Permission> actions = new HashSet<Permission>();
        if(isSuperAdmin==false) {
            List<SentryRoleAction> sentryRoleActionList = shiroPermissionsService.selectSentryRoleAction(new ArrayList<String>(roles));
            for (SentryRoleAction action : sentryRoleActionList) {
                Permission wildcardPermission = new WildcardPermission(MessageFormat.format("{0}:{1}", action.getMenucode(), action.getActioncode()));
                if (actions.contains(wildcardPermission) == false) {
                    actions.add(wildcardPermission);
                }
            }
        }else{
            Permission wildcardPermission = new WildcardPermission("*:*");
            actions.add(wildcardPermission);
        }
        authorizationInfo.setObjectPermissions(actions);
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = (String)token.getPrincipal();
        // TODO: 2017/4/7 验证当前用户的是否合法
        Admin adminEntity=adminService.SelectOne(username);
        if(adminEntity==null)
            return null;
//        adminEntity.setUsername("admin");
//        adminEntity.setId(1L);
//        String salt = new SecureRandomNumberGenerator().nextBytes().toHex();
//        String password_cipherText= new Md5Hash("admin",username+salt,3).toHex();
//        adminEntity.setPassword(password_cipherText);


        //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配，如果觉得人家的不好可以自定义实现
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                adminEntity.getUsername(), //用户名
                adminEntity.getPassword(), //密码
                ByteSource.Util.bytes(username+adminEntity.getSalt()),//salt=username+salt
                getName()  //realm name
        );
        return authenticationInfo;
    }

    @Override
    public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        super.clearCachedAuthorizationInfo(principals);
    }

    @Override
    public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
        super.clearCachedAuthenticationInfo(principals);
    }

    @Override
    public void clearCache(PrincipalCollection principals) {
        super.clearCache(principals);
    }

    public void clearAllCachedAuthorizationInfo() {
        getAuthorizationCache().clear();
    }

    public void clearAllCachedAuthenticationInfo() {
        getAuthenticationCache().clear();
    }

    public void clearAllCache() {
        clearAllCachedAuthenticationInfo();
        clearAllCachedAuthorizationInfo();
    }
}
