feat: 支持工作流对话匿名分享
- 增加免登录公共接口、访客隔离、限流和匿名上传校验 - 分离 SSE 连接与运行生命周期,支持刷新恢复服务端权威状态 - 持久化分享页对话并优化时间线滚动与输入区交互
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import { createMemoryHistory, createRouter } from 'vue-router';
|
||||
|
||||
import { useAccessStore } from '@easyflow/stores';
|
||||
|
||||
import { createPinia, setActivePinia } from 'pinia';
|
||||
import { beforeEach, describe, expect, it } from 'vitest';
|
||||
|
||||
import { createRouterGuard } from '../guard';
|
||||
|
||||
describe('public route guard', () => {
|
||||
beforeEach(() => {
|
||||
setActivePinia(createPinia());
|
||||
});
|
||||
|
||||
it('bypasses stale login state for an anonymous workflow share', async () => {
|
||||
const accessStore = useAccessStore();
|
||||
accessStore.setAccessToken('stale-token');
|
||||
const router = createRouter({
|
||||
history: createMemoryHistory(),
|
||||
routes: [
|
||||
{
|
||||
component: { template: '<div>login</div>' },
|
||||
name: 'Login',
|
||||
path: '/auth/login',
|
||||
},
|
||||
{
|
||||
component: { template: '<div>workflow share</div>' },
|
||||
meta: { ignoreAccess: true, title: 'Workflow Share' },
|
||||
name: 'WorkflowShare',
|
||||
path: '/share/workflow',
|
||||
},
|
||||
],
|
||||
});
|
||||
createRouterGuard(router);
|
||||
|
||||
await router.push('/share/workflow?shareKey=share-key');
|
||||
await router.isReady();
|
||||
|
||||
expect(router.currentRoute.value.name).toBe('WorkflowShare');
|
||||
expect(router.currentRoute.value.query.shareKey).toBe('share-key');
|
||||
});
|
||||
});
|
||||
@@ -11,6 +11,7 @@ describe('external share routes', () => {
|
||||
hideInBreadcrumb: true,
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
ignoreAccess: true,
|
||||
noBasicLayout: true,
|
||||
});
|
||||
});
|
||||
@@ -19,6 +20,7 @@ describe('external share routes', () => {
|
||||
const route = routes.find((item) => item.name === 'WorkflowShareExpired');
|
||||
|
||||
expect(route?.path).toBe('/share/workflow/expired');
|
||||
expect(route?.meta?.ignoreAccess).toBe(true);
|
||||
expect(route?.meta?.noBasicLayout).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -152,6 +152,12 @@ function setupAccessGuard(router: Router) {
|
||||
let devLoginPromise: null | Promise<void> = null;
|
||||
|
||||
router.beforeEach(async (to, from) => {
|
||||
// 公开路由必须在读取或刷新登录态之前短路,避免浏览器残留的过期
|
||||
// token 把匿名分享页重定向到登录页。
|
||||
if (to.meta.ignoreAccess) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const accessStore = useAccessStore();
|
||||
const userStore = useUserStore();
|
||||
const authStore = useAuthStore();
|
||||
@@ -227,11 +233,6 @@ function setupAccessGuard(router: Router) {
|
||||
|
||||
// accessToken 检查
|
||||
if (!accessStore.accessToken) {
|
||||
// 明确声明忽略权限访问权限,则可以访问
|
||||
if (to.meta.ignoreAccess) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 没有访问权限,跳转登录页面
|
||||
if (to.fullPath !== LOGIN_PATH) {
|
||||
const cleanFullPath =
|
||||
|
||||
@@ -33,6 +33,7 @@ const routes: RouteRecordRaw[] = [
|
||||
component: () => import('#/views/ai/workflow/WorkflowShareView.vue'),
|
||||
meta: {
|
||||
title: 'Workflow Share',
|
||||
ignoreAccess: true,
|
||||
noBasicLayout: true,
|
||||
hideInMenu: true,
|
||||
hideInBreadcrumb: true,
|
||||
@@ -46,6 +47,7 @@ const routes: RouteRecordRaw[] = [
|
||||
import('#/views/ai/documentCollection/KnowledgeShareExpired.vue'),
|
||||
meta: {
|
||||
title: 'Workflow Share Expired',
|
||||
ignoreAccess: true,
|
||||
noBasicLayout: true,
|
||||
hideInMenu: true,
|
||||
hideInBreadcrumb: true,
|
||||
|
||||
Reference in New Issue
Block a user