package com.tofly.common.oauth.auth;

import com.tofly.common.core.constant.SecurityConstants;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.Ordered;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @author Administrator
 * @date 2019/9/18  11:08
 */
@Slf4j
@Aspect
@Component
@AllArgsConstructor
public class InnerCallAspect implements Ordered {

    private final HttpServletRequest request;

    // 配置织入点
    @Pointcut("@annotation(com.tofly.common.oauth.auth.innerCall)")
    public void innerPointCut() {
    }

    @Around(value="innerPointCut()")
    @SneakyThrows
    public Object round(ProceedingJoinPoint joinPoint) {
        return innerHander(joinPoint);
    }

    @SneakyThrows
    private Object innerHander(ProceedingJoinPoint joinPoint){

        innerCall inner = getAnnotation(joinPoint);
        if(inner==null) {
            return null;
        }

        String header = request.getHeader(SecurityConstants.FROM);
        if (inner.value() && !SecurityConstants.FROM_IN.equals(header)) {
            log.warn("访问接口 {} 没有权限", joinPoint.getSignature().getName());
            throw new AccessDeniedException("该接口不允许外部访问");
        }
        return joinPoint.proceed();
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE + 1;
    }

    //判断是否存在注解
    private innerCall getAnnotation(JoinPoint joinPoint) throws Exception {


        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method != null) {
            return method.getAnnotation(innerCall.class);
        }
        return null;
    }
}
