@autional/shared 0.1.0-rc.32 → 0.1.0-rc.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -29,7 +29,7 @@ interface AuditStatsOnlyProps {
|
|
|
29
29
|
export function AuditStatsOnly({ title, description, children }: AuditStatsOnlyProps) {
|
|
30
30
|
return (
|
|
31
31
|
<div className="flex flex-col items-center justify-center min-h-[40vh] p-8">
|
|
32
|
-
<div className="w-full max-w-2xl bg-white dark:bg-slate-800 rounded-lg shadow-
|
|
32
|
+
<div className="w-full max-w-2xl bg-white dark:bg-slate-800 rounded-lg shadow-card border border-gray-200 dark:border-slate-700 p-8">
|
|
33
33
|
<div className="flex flex-col items-center text-center space-y-4">
|
|
34
34
|
{/* Lock icon via inline SVG (no external dependency) */}
|
|
35
35
|
<svg
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
*
|
|
7
7
|
* - usePublicTenantSlugs: 调公开 tenants API(无认证端点),staleTime 5m 缓存,
|
|
8
8
|
* retry 1,任何失败返回空数组(放行语义由 TenantIndexGuard 处理)。
|
|
9
|
-
* - TenantIndexGuard:
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* - TenantIndexGuard: 租户 slug 白名单守卫(P0-2),防止未知 slug 被贪婪渲染为
|
|
10
|
+
* 租户内容(index 首页与 /:slug/... 子路由通用)。404 页由各 portal 通过
|
|
11
|
+
* notFound prop 注入(shared 组件不能 import 具体 app 的 not-found/page)。
|
|
12
12
|
*
|
|
13
13
|
* ⚠️ 依赖约束: shared 包 dependencies 无 @autional/ui,禁止 import @autional/ui
|
|
14
14
|
* (会引入未声明依赖/循环依赖)。loading 默认值用内联 div 骨架,
|
|
@@ -105,22 +105,19 @@ function DefaultLoadingSkeleton() {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
/**
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
* -
|
|
111
|
-
* -
|
|
112
|
-
*
|
|
108
|
+
* 租户 slug 白名单守卫(P0-2):防止未知 slug 被贪婪渲染为租户内容。
|
|
109
|
+
* - URL 首段经 extractSlugFromPath 取为 slug(保留段/已注册业务段返回 undefined,放行)。
|
|
110
|
+
* - slug 命中公开租户列表 → children;未命中 → notFound(/nonexistent-tenant[/...] 均 404)。
|
|
111
|
+
* - 只校验 slug 一段,不看路径深度 —— 子路径合法性(/acme-corp/terms 等)由路由表决定。
|
|
112
|
+
* 2026-10-09 移除「URL 段数 > 1 → notFound」检查:它出自已废弃的动态 basename 方案
|
|
113
|
+
* (那时 basename 剥掉 slug,内部多段 = 未知路由);basename 改为 '/' 后它对 index
|
|
114
|
+
* 路由从未生效,却在包裹子路由处误杀 —— auth 站 /:tenantSlug/terms|privacy 曾因此恒 404。
|
|
113
115
|
* - 白名单为空数组时放行(public tenants API 挂掉时退化为不拦截,与 end-user 现状一致)
|
|
114
116
|
*/
|
|
115
117
|
export function TenantIndexGuard({ children, notFound, loading }: TenantIndexGuardProps) {
|
|
116
118
|
const { data: tenants, isLoading } = usePublicTenantSlugs();
|
|
117
119
|
const slug = useTenantSlugFromUrl();
|
|
118
120
|
|
|
119
|
-
if (typeof window !== 'undefined') {
|
|
120
|
-
const fullSegs = window.location.pathname.split('/').filter(Boolean);
|
|
121
|
-
if (fullSegs.length > 1) return <>{notFound}</>;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
121
|
if (isLoading && !tenants) return <>{loading ?? <DefaultLoadingSkeleton />}</>;
|
|
125
122
|
|
|
126
123
|
if (slug && tenants && tenants.length > 0 && !tenants.some((t) => (t.name || t.slug) === slug)) {
|
|
@@ -178,10 +178,19 @@ describe('TenantIndexGuard(P0-2 slug 白名单守卫)', () => {
|
|
|
178
178
|
await waitFor(() => expect(screen.getByTestId('children')).toBeInTheDocument());
|
|
179
179
|
});
|
|
180
180
|
|
|
181
|
-
it('
|
|
182
|
-
|
|
181
|
+
it('slug 有效 + 子路径(/acme-corp/terms)→ 渲染 children(回归:子路由此前被段数检查误杀)', async () => {
|
|
182
|
+
stubFetch([{ id: '1', name: 'acme-corp' }]);
|
|
183
|
+
setPath('/acme-corp/terms');
|
|
184
|
+
render(wrapper(<TenantIndexGuard notFound={notFound}>{children}</TenantIndexGuard>));
|
|
185
|
+
await waitFor(() => expect(screen.getByTestId('children')).toBeInTheDocument());
|
|
186
|
+
expect(screen.queryByTestId('notfound')).toBeNull();
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('slug 无效 + 子路径(/nonexistent-tenant/terms)→ 渲染 notFound', async () => {
|
|
190
|
+
stubFetch([{ id: '1', name: 'acme-corp' }]);
|
|
191
|
+
setPath('/nonexistent-tenant/terms');
|
|
183
192
|
render(wrapper(<TenantIndexGuard notFound={notFound}>{children}</TenantIndexGuard>));
|
|
184
|
-
expect(screen.getByTestId('notfound')).toBeInTheDocument();
|
|
193
|
+
await waitFor(() => expect(screen.getByTestId('notfound')).toBeInTheDocument());
|
|
185
194
|
expect(screen.queryByTestId('children')).toBeNull();
|
|
186
195
|
});
|
|
187
196
|
|