# Fumadocs (Framework Mode, Astro): アクセス制御
URL: /ja/docs/astro/guides/access-control
Source: https://raw.githubusercontent.com/fuma-nama/fumadocs/refs/heads/main/apps/docs/content/docs/(framework)/[framework]/guides/access-control.ja.mdx

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

## 概要 [#overview]

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

## ローダー API [#loader-api]

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

たとえば、次の設定では、フロントマターに `permission: public` が指定されたページのみを表示します。

```ts title="src/lib/source.ts"
import { getCollection } from 'astro:content';
import { loader, update } from 'fumadocs-core/source';
import { toFumadocsSource } from '@fumadocs/astro/source';

const filteredSource = update(
  toFumadocsSource(await getCollection('docs'), await getCollection('meta')),
)
  .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` をファクトリー関数にすることもできます。

```ts title="src/lib/source.ts"
import { getCollection } from 'astro:content';
import { loader, update } from 'fumadocs-core/source';
import { toFumadocsSource } from '@fumadocs/astro/source';

const pages = await getCollection('docs');
const metas = await getCollection('meta');

// キャッシュなし。実際のユースケースではインメモリでキャッシュすることをおすすめします。
export function createSource(permission: 'public' | 'admin') {
  const filteredSource = update(toFumadocsSource(pages, metas))
    .files((files) =>
      files.filter((file) => {
        if (file.type === 'meta') return true;

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

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

次に、ユーザーごとにソースを作成します。

```ts
// [!code --]
import { source } from '@/lib/source';
// [!code ++:4]
import { createSource } from '@/lib/source';

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

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

### 利点 [#advantages]

このアプローチの特長は、レンダリング段階やビルド時ではなく、**入力の段階でアクセスを制限する**点です。

これにより、柔軟性を損なうことなく、保護されたコンテンツを完全に除外できます。

## カスタム実装 [#custom-implementation]

ローダー API を使わない場合は、ルートやミドルウェアなど、Astro 側でアクセス制御を実装します。

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

```astro title="src/pages/docs/[...slug].astro"
---
import { source } from '@/lib/source';

// リクエストごとにレンダリング（アダプターが必要）
export const prerender = false;

const slugs = Astro.params.slug?.split('/').filter((v) => v.length > 0) ?? [];
const user = await getUser(Astro.request);
const page = source.getPage(slugs);

if (!page || page.data.permission !== user.permission) {
  return Astro.rewrite('/404');
}
---

<!-- ページをレンダリング... -->
```

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

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