package com.qmth.boot.api.interceptor.impl;

import com.qmth.boot.api.config.ApiConfig;
import com.qmth.boot.api.config.ApiConfigService;
import com.qmth.boot.api.config.ApiProperties;
import com.qmth.boot.api.exception.DefaultExceptionEnum;
import com.qmth.boot.api.interceptor.AbstractInterceptor;
import com.qmth.boot.api.valve.IPFilterService;
import com.qmth.boot.core.logger.constant.LoggerConstant;
import com.qmth.boot.core.security.exception.AuthorizationException;
import com.qmth.boot.core.security.model.AccessEntity;
import com.qmth.boot.core.security.service.AuthorizationSupport;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class AuthorizationInterceptor extends AbstractInterceptor implements LoggerConstant {

    @Resource
    private ApiProperties apiProperties;

    @Resource
    private ApiConfigService apiConfigService;

    @Resource
    private AuthorizationSupport authorizationSupport;

    @Resource
    private IPFilterService ipFilterService;

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        ApiConfig config = getApiConfig(apiProperties, apiConfigService, request, handler);
        if (config.isAuth()) {
            AccessEntity entity;
            try {
                // 获取鉴权对象
                entity = authorizationSupport
                        .validateSignature(request.getHeader(HEADER_AUTHORIZATION), request.getMethod(),
                                request.getServletPath(), request.getHeader(HEADER_TIME), config.getSignType());
                // 默认对象名
                request.setAttribute(ATTRIBUTE_ACCESS_ENTITY, entity);
                // 以实现类名首字母小写后作为对象名
                request.setAttribute(StringUtils.uncapitalize(entity.getClass().getSimpleName()), entity);
                // 默认取签名标识作为接口访问者标识
                request.setAttribute(ATTRIBUTE_CALLER, entity.getLogName());
                // 设置日志CALLER变量
                MDC.put(MDC_CALLER, entity.getLogName());
            } catch (AuthorizationException ae) {
                log.warn("Authorization faile: path={}, reason={}", request.getServletPath(), ae.getMessage());
                throw DefaultExceptionEnum.AUTHORIZATION_ERROR.exception(ae.getCode(), ae.getMessage());
            } catch (Exception e) {
                log.warn("Authorization error: path={}, reason={}", request.getServletPath(), e.getMessage());
                throw DefaultExceptionEnum.AUTHORIZATION_ERROR.exception(e.getMessage());
            }
            // 按照动态规则二次过滤IP
            ipFilterService.filter(request, entity.getAllowIP(), entity.getDenyIP());
        }
        return true;
    }

}
