package com.njzscloud.common.security.handler;

import cn.hutool.extra.servlet.ServletUtil;
import com.njzscloud.common.core.ex.ExceptionMsg;
import com.njzscloud.common.core.jackson.Jackson;
import com.njzscloud.common.core.utils.Mime;
import com.njzscloud.common.core.utils.R;
import com.njzscloud.common.security.ex.MissingPermissionException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.AuthorizationServiceException;
import org.springframework.security.web.access.AccessDeniedHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 权限异常
 */
@Slf4j
public class AccessDeniedExceptionHandler implements AccessDeniedHandler {

    public static final AccessDeniedExceptionHandler INSTANCE = new AccessDeniedExceptionHandler();

    private AccessDeniedExceptionHandler() {
    }

    @Override
    public void handle(
            HttpServletRequest request,
            HttpServletResponse response,
            AccessDeniedException accessDeniedException
    ) throws IOException, ServletException {
        R<?> r;
        if (accessDeniedException instanceof AuthorizationServiceException) {
            log.error("权限校验失败: {}", request.getRequestURI(), accessDeniedException);
            r = R.failed(ExceptionMsg.SYS_ERR_MSG, "权限加载失败");
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        } else if (accessDeniedException instanceof MissingPermissionException) {
            log.error("权限未配置: {}", request.getRequestURI(), accessDeniedException);
            r = R.failed(ExceptionMsg.SYS_ERR_MSG, "当前请求未分配权限");
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        } else {
            log.error("暂无权限: {}", request.getRequestURI(), accessDeniedException);
            r = R.failed(ExceptionMsg.CLI_ERR_MSG, "暂无权限");
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        }
        ServletUtil.write(response, Jackson.toJsonStr(r), Mime.u8Val(Mime.JSON));
    }
}
