feat: 支持工作流对话匿名分享
- 增加免登录公共接口、访客隔离、限流和匿名上传校验 - 分离 SSE 连接与运行生命周期,支持刷新恢复服务端权威状态 - 持久化分享页对话并优化时间线滚动与输入区交互
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { authenticateResponseInterceptor } from './preset-interceptors';
|
||||
|
||||
function createInterceptor(
|
||||
shouldHandleUnauthorized?: (config: any) => boolean,
|
||||
) {
|
||||
const doReAuthenticate = vi.fn(async () => undefined);
|
||||
const interceptor = authenticateResponseInterceptor({
|
||||
client: {} as any,
|
||||
doReAuthenticate,
|
||||
doRefreshToken: vi.fn(async () => 'new-token'),
|
||||
enableRefreshToken: false,
|
||||
formatToken: (token) => token,
|
||||
shouldHandleUnauthorized,
|
||||
});
|
||||
return { doReAuthenticate, interceptor };
|
||||
}
|
||||
|
||||
describe('authenticate response interceptor', () => {
|
||||
it('leaves anonymous endpoint 401 errors to the page', async () => {
|
||||
const { doReAuthenticate, interceptor } = createInterceptor(() => false);
|
||||
const error = {
|
||||
config: { method: 'get', url: '/api/v1/workflowShare/resolve' },
|
||||
response: { status: 401 },
|
||||
};
|
||||
|
||||
await expect(interceptor.rejected?.(error)).rejects.toBe(error);
|
||||
expect(doReAuthenticate).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('keeps the existing reauthentication behavior by default', async () => {
|
||||
const { doReAuthenticate, interceptor } = createInterceptor();
|
||||
const error = {
|
||||
config: { method: 'get', url: '/api/v1/workflow/page' },
|
||||
response: { status: 401 },
|
||||
};
|
||||
|
||||
await expect(interceptor.rejected?.(error)).rejects.toBe(error);
|
||||
expect(doReAuthenticate).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
@@ -59,12 +59,14 @@ export const authenticateResponseInterceptor = ({
|
||||
doRefreshToken,
|
||||
enableRefreshToken,
|
||||
formatToken,
|
||||
shouldHandleUnauthorized,
|
||||
}: {
|
||||
client: RequestClient;
|
||||
doReAuthenticate: () => Promise<void>;
|
||||
doRefreshToken: () => Promise<string>;
|
||||
enableRefreshToken: boolean;
|
||||
formatToken: (token: string) => null | string;
|
||||
shouldHandleUnauthorized?: (config: any) => boolean;
|
||||
}): ResponseInterceptorConfig => {
|
||||
return {
|
||||
rejected: async (error) => {
|
||||
@@ -73,6 +75,10 @@ export const authenticateResponseInterceptor = ({
|
||||
if (response?.status !== 401) {
|
||||
throw error;
|
||||
}
|
||||
// 匿名接口的 401 由页面自身处理,不能触发刷新登录态或跳转登录页。
|
||||
if (shouldHandleUnauthorized?.(config) === false) {
|
||||
throw error;
|
||||
}
|
||||
// 判断是否启用了 refreshToken 功能
|
||||
// 如果没有启用或者已经是重试请求了,直接跳转到重新登录
|
||||
if (!enableRefreshToken || config.__isRetryRequest) {
|
||||
|
||||
Reference in New Issue
Block a user