リソースレベル権限システム¶
リソースレベル権限システムにより、ユーザーはプロジェクトや企画ごとに細かい粒度の権限を持つことができます。
概要¶
なぜリソースレベル権限が必要か?¶
従来のグローバルロールシステムでは: - ユーザーはシステム全体で1つのロールしか持てない - 特定のプロジェクトだけで管理者になることができない - 権限が粗く、細かい制御ができない
リソースレベル権限システムでは: - ✅ プロジェクトAでは管理者、プロジェクトBでは閲覧者 - ✅ 企画Xでは編集可能、企画Yでは読み取りのみ - ✅ 9種類の細かい権限で柔軟に制御 - ✅ 期限付き権限で一時的なアクセスを許可
リソースタイプ¶
PROJECT¶
イベント全体を表すリソース(例: 千葉大祭2024)
用途: - イベント全体の管理者を設定 - 企画承認権限の付与 - リソース割り当て権限の付与
CIRCLE_PROJECT¶
個別の企画を表すリソース(例: 特定サークルの出店企画)
用途: - 企画のマネージャー・メンバー設定 - 企画情報の編集権限 - チェックイン権限
権限の種類 (9種類)¶
| 権限 | 説明 | 用途例 |
|---|---|---|
| READ | リソースの閲覧 | 企画情報の確認 |
| WRITE | リソースの編集・更新 | 企画名・説明の変更 |
| DELETE | リソースの削除 | 企画のアーカイブ |
| MANAGE_MEMBERS | メンバーの追加・削除 | 企画メンバーの管理 |
| MANAGE_PERMISSIONS | 権限の付与・削除 | 他のユーザーに権限を与える |
| APPROVE | 申請の承認 | 企画申請の承認・却下 |
| CHECKIN | チェックイン操作 | 説明会の出席確認 |
| ALLOCATE_RESOURCES | リソースの割り当て | テント・予算の配分 |
| VIEW_PRIVATE | 非公開情報の閲覧 | 内部メモの閲覧 |
ロールテンプレート¶
よく使う権限セットをテンプレートとして保存できます。
Project用ロールテンプレート¶
ProjectAdmin (全権限)¶
すべての操作が可能です。
["READ", "WRITE", "DELETE", "MANAGE_MEMBERS", "MANAGE_PERMISSIONS",
"APPROVE", "ALLOCATE_RESOURCES", "VIEW_PRIVATE"]
ProjectManager (管理権限)¶
承認とリソース割り当てが可能です。
ProjectEditor (編集権限)¶
閲覧と編集が可能です。
ProjectViewer (閲覧のみ)¶
閲覧のみ可能です。
CircleProject用ロールテンプレート¶
Manager (企画管理者)¶
企画の全操作が可能です。
Editor (企画編集者)¶
編集とチェックインが可能です。
Member (一般メンバー)¶
閲覧とチェックインが可能です。
Viewer (閲覧のみ)¶
閲覧のみ可能です。
使用例¶
例1: プロジェクト管理者を追加¶
ユーザーAを「千葉大祭2024」の管理者にする:
curl -X POST /api/resource-permissions \
-d '{
"userId": "user-a-uuid",
"resourceType": "PROJECT",
"resourceId": "chibafes2024",
"roleTemplate": "ProjectManager"
}'
例2: 企画メンバーに編集権限を付与¶
ユーザーBを特定企画の編集者にする:
curl -X POST /api/resource-permissions \
-d '{
"userId": "user-b-uuid",
"resourceType": "CIRCLE_PROJECT",
"resourceId": "circle-project-123",
"roleTemplate": "Editor"
}'
例3: 期限付き権限の付与¶
ユーザーCに1ヶ月間の編集権限を付与:
curl -X POST /api/resource-permissions \
-d '{
"userId": "user-c-uuid",
"resourceType": "CIRCLE_PROJECT",
"resourceId": "circle-project-456",
"permissions": ["READ", "WRITE"],
"expiresAt": "2025-12-31T23:59:59Z"
}'
例4: カスタム権限セット¶
特定の権限のみを付与:
curl -X POST /api/resource-permissions \
-d '{
"userId": "user-d-uuid",
"resourceType": "PROJECT",
"resourceId": "chibafes2024",
"permissions": ["READ", "APPROVE", "VIEW_PRIVATE"]
}'
実装方法¶
エンドポイントでの使用¶
import { requireResourcePermission } from '@/lib/api/auth';
// 企画の更新エンドポイント(WRITE権限が必要)
app.put('/circle-project/:id',
requireResourcePermission('CIRCLE_PROJECT', 'id', ['WRITE']),
async (c) => {
// 権限チェック済み
const id = c.req.param('id');
// ...更新処理
}
);
プログラムからの権限チェック¶
import { hasResourcePermission } from '@/lib/api/auth';
const canEdit = await hasResourcePermission(
userId,
'CIRCLE_PROJECT',
projectId,
['WRITE']
);
if (canEdit) {
// 編集処理
}
フロントエンドでの使用¶
import { useResourcePermission } from '@/hooks/useResourcePermission';
function ProjectActions({ projectId }) {
const { hasPermission: canEdit } = useResourcePermission(
'CIRCLE_PROJECT',
projectId,
['WRITE']
);
return (
<div>
{canEdit && <button>編集</button>}
</div>
);
}
後方互換性¶
FullAccessAdminロールを持つユーザーは、すべてのリソースに対して全権限を自動的に持ちます。
ベストプラクティス¶
1. 最小権限の原則¶
必要最小限の権限のみを付与します。
❌ 悪い例:
// すべての権限を付与
permissions: ["READ", "WRITE", "DELETE", "MANAGE_MEMBERS",
"MANAGE_PERMISSIONS", "APPROVE", ...]
✅ 良い例:
2. ロールテンプレートの活用¶
カスタム権限セットより標準テンプレートを優先します。
❌ 悪い例:
✅ 良い例:
3. 期限の設定¶
一時的な権限には必ず有効期限を設定します。
❌ 悪い例:
✅ 良い例:
4. 監査ログ¶
権限の付与・変更・削除は記録されます。
{
userId: "user-uuid",
grantedBy: "admin-uuid",
grantedAt: "2024-01-01T00:00:00Z",
permissions: ["READ", "WRITE"]
}
トラブルシューティング¶
問題: 権限チェックが常にfalseを返す¶
原因: 1. リソースIDが間違っている 2. ResourcePermissionテーブルにデータが存在しない 3. 権限の有効期限が切れている
解決策:
# 権限チェックエンドポイントでデバッグ
curl "/api/resource-permissions/check?\
resourceType=CIRCLE_PROJECT&\
resourceId=YOUR_PROJECT_ID&\
permissions=READ,WRITE"
問題: FullAccessAdminなのにアクセスできない¶
原因: 新しい権限チェックロジックが正しく実装されていない
解決策:
hasResourcePermission関数でFullAccessAdminの特別扱いを確認
詳細情報¶
最終更新: 2026-01-07