跳至內容
Fumadocs

存取控制

限制內容的存取權限。

概覽

由於 Fumadocs 的設計相當有彈性,實作存取控制十分簡單。

載入器 API

如果您使用 loader() API,可以視需要建立載入器,並篩選內容來源中的檔案,藉此限制可存取的內容。

例如,以下搭配 Fumadocs MDX 的設定只會顯示 frontmatter 含有 permission: public 的 MDX 檔案。

lib/source.ts
import { docs } from 'collections/server';
import { loader, update } from 'fumadocs-core/source';

const filteredSource = update(docs.toFumadocsSource())
  .files((files) =>
    files.filter((file) => {
      // 保留 meta 檔案(例如 `meta.json`)
      if (file.type === 'meta') return true;

      // 存取檔案資料(型別安全)
      return file.data.permission === 'public';
    }),
  )
  .build();

export const source = loader(filteredSource, {
  baseUrl: '/docs',
});

若設定較為複雜,您可以將 source 改寫為工廠函式。

lib/source.ts
import { docs } from 'collections/server';
import { loader, update } from 'fumadocs-core/source';

// 未快取,實際使用時建議快取在記憶體中。
export function createSource(permission: 'public' | 'admin') {
  const filteredSource = update(docs.toFumadocsSource())
    .files((files) =>
      files.filter((file) => {
        if (file.type === 'meta') return true;

        return file.data.permission === permission;
      }),
    )
    .build();

  return loader(filteredSource, {
    baseUrl: '/docs',
  });
}

接著為每位使用者建立來源:

import { source } from '@/lib/source';
import { createSource } from '@/lib/source';

const user = await getUser();
const source = createSource(user.permission);

const page = source.getPage(params.slugs);

優點

這種做法的特別之處在於,存取限制是在輸入層級就套用,而不是在算繪階段或建置時才進行。

如此可確保受保護的內容完全被過濾掉,且絲毫不犧牲彈性。

自訂實作

若不使用載入器 API,請直接在 React Router 中實作存取控制,例如在路由或中介軟體中處理。

例如,若要限制特定頁面的存取權限:

app/routes/docs.tsx
import type { Route } from './+types/docs';
import { source } from '@/lib/source';

export async function loader({ params, request }: Route.LoaderArgs) {
  const user = await getUser(request);
  const page = source.getPage(params['*'].split('/').filter((v) => v.length > 0));

  if (!page) throw new Response('Not found', { status: 404 });
  if (page.data.permission !== user.permission) throw new Response('Not found', { status: 404 });

  // 回傳頁面資料...
}

請注意,頁面樹 (側邊欄項目) 、搜尋、Markdown 路由及其他細節都需要由您自行處理。

這種做法彈性最高,但 Fumadocs 不會替您處理存取控制。設定較為費工,實作時請參閱 React Router 的文件。

How is this guide?

最後更新於