/* (C) 2021 YiRing, Inc. */
package com.yiring.auth.config;

import cn.dev33.satoken.exception.*;
import com.yiring.common.core.Result;
import com.yiring.common.core.Status;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 授权异常拦截处理
 *
 * @author Jim
 * @version 0.1
 * 2023/1/12 14:06
 */
@Slf4j
@Order(1)
@RestControllerAdvice
@RequiredArgsConstructor
public class AuthExceptionHandler {

    /**
     * 未登录异常（鉴权失败）
     *
     * @return 异常信息反馈 {@link Status#UNAUTHORIZED
     */
    @ExceptionHandler(NotLoginException.class)
    public Result<String> unauthorizedErrorHandler() {
        return Result.no(Status.UNAUTHORIZED);
    }

    /**
     * 1. 二级认证失败异常
     * 2. 角色条件不满足
     * 3. 权限条件不满足
     * 4. HTTP Basic 验证不通过
     * 5. 用户被禁止访问该服务
     * 6. API 被禁用
     *
     * @return 异常信息反馈 {@link Status#FORBIDDEN
     */
    @ExceptionHandler(
        {
            // https://sa-token.dev33.cn/doc.html#/up/safe-auth
            NotSafeException.class,
            // https://sa-token.dev33.cn/doc.html#/use/at-check
            NotRoleException.class,
            NotPermissionException.class,
            // https://sa-token.dev33.cn/doc.html#/up/basic-auth
            NotHttpBasicAuthException.class,
            // https://sa-token.dev33.cn/doc.html#/up/disable
            DisableServiceException.class,
            ApiDisabledException.class,
        }
    )
    public Result<String> forbiddenHandler(Exception e) {
        if (e instanceof NotSafeException) {
            return Result.no(Status.FORBIDDEN, "Code.10000");
        }
        if (e instanceof NotRoleException) {
            return Result.no(Status.FORBIDDEN, "Code.10001");
        }
        if (e instanceof NotPermissionException) {
            return Result.no(Status.FORBIDDEN, "Code.10002");
        }
        if (e instanceof NotHttpBasicAuthException) {
            return Result.no(Status.FORBIDDEN, "Code.10003");
        }

        log.warn(e.getMessage(), e);
        return Result.no(Status.FORBIDDEN);
    }
}
