package com.diagbot.config.security;

import com.diagbot.facade.TokenFacade;
import com.diagbot.util.HttpUtils;
import com.diagbot.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;


/**
 * @Description: 自定义权限拦截
 * @author: gaodm
 * @time: 2018/8/23 13:46
 */
@Service
public class UrlAccessDecisionManager implements AccessDecisionManager {
    @Autowired
    private TokenFacade tokenFacade;

    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
        HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
        String url, method;
        if (matchPermitAllUrl(request)) {
            return;
        }
        if ("anonymousUser".equals(authentication.getPrincipal())) {
            throw new AccessDeniedException("no right");
        } else {
            String tokenStr = HttpUtils.getHeaders(request).get("Authorization");
            if (StringUtil.isNotEmpty(tokenStr)) {
                tokenStr = tokenStr.replaceFirst("Bearer ", "");
                Boolean res = tokenFacade.verifyToken(tokenStr, 1);
                if (!res) {
                    throw new AccountExpiredException("token expire");
                }
            }
            for (GrantedAuthority ga : authentication.getAuthorities()) {
                String[] authority = ga.getAuthority().split(";");
                url = authority[0];
                method = authority[1];
                if (matchers(url, request)) {
                    if (method.equals(request.getMethod()) || "ALL".equals(method)) {
                        return;
                    }
                }
            }
        }
        throw new AccessDeniedException("no right");
    }


    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }

    private Boolean matchPermitAllUrl(HttpServletRequest request) {
        if (matchers("/swagger/**", request)
                || matchers("/v2/**", request)
                || matchers("/swagger-ui.html/**", request)
                || matchers("/swagger-resources/**", request)
                || matchers("/webjars/**", request)
                || matchers("/user/getJwt/**", request)
                || matchers("/user/registry/**", request)
                || matchers("/user/test/**", request)
                || matchers("/druid/**", request)
                || matchers("/actuator/**", request)
                || matchers("/hystrix/**", request)
                || matchers("/hi/**", request)
                || matchers("/test/**", request)
                || matchers("/user/refreshJwt", request)
                || matchers("/user/checkToken", request)
                || matchers("/userver/getImgVerification", request)
                || matchers("/userver/verifyImgVerification", request)
                || matchers("/userver/getSmsWithRegister", request)
                || matchers("/userver/getSmsWithResetPassword", request)
                || matchers("/userver/verifySmsVerification", request)
                || matchers("/getUserEnumsData", request)
                || matchers("/user/getPermission", request)
                || matchers("/user/resetPassword", request)
                || matchers("/user/index", request)
                || matchers("/user/getUserByOrgName", request)
                || matchers("/user/getUserAuthStatus", request)
                || matchers("/user/getUserAndOrg", request)
                || matchers("/user/verifyNoUsername", request)
                || matchers("/user/verifyExistUsername", request)
                || matchers("/userAuthentication/getAuthInfoCount", request)
                || matchers("/user/getUserAllInfo", request)
                || matchers("/user/verifyToken", request)
                || matchers("/user/getUserInfoByIds", request)
                || matchers("/", request)) {
            return true;
        }
        return false;
    }

    private boolean matchers(String url, HttpServletRequest request) {
        AntPathRequestMatcher matcher = new AntPathRequestMatcher(url);
        if (matcher.matches(request)) {
            return true;
        }
        return false;
    }
}
