コンテンツへスキップ
Fumadocs

アクセス制御

コンテンツへのアクセスを制限します。

概要

Fumadocs は柔軟に設計されているため、アクセス制御も簡単に実装できます。

ローダー API

loader() API を使用している場合は、ローダーを必要に応じて作成し、コンテンツソースのファイルをフィルタリングすることで、アクセスできるコンテンツを制限できます。

たとえば、Fumadocs MDX を使った次の設定では、フロントマターに 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 を使わない場合は、ルートやミドルウェアなど、Next.js 側でアクセス制御を実装します。

たとえば、特定のページへのアクセスを制限するには次のようにします。

app/docs/[[...slug]]/page.tsx
import { notFound } from 'next/navigation';
import { source } from '@/lib/source';

export default async function Page(props: PageProps<'/docs/[[...slug]]'>) {
  const params = await props.params;
  const user = await getUser();
  const page = source.getPage(params.slug);

  if (!page) notFound();
  if (page.data.permission !== user.permission) notFound();

  // ページをレンダリング...
}

なお、ページツリー (サイドバーの項目) 、検索、Markdown ルートなどの細かな部分は、ご自身で管理する必要があります。

この方法は最も柔軟性が高い反面、Fumadocs はアクセス制御に関与しません。セットアップにも手間がかかるため、実装する際は Next.js のドキュメントを参照してください。

How is this guide?

最終更新日