Skip to content

Commit 5b0966e

Browse files
committed
Add User.role field
1 parent 9cb1020 commit 5b0966e

File tree

7 files changed

+165
-73
lines changed

7 files changed

+165
-73
lines changed

docs/auth-implementation-plan.md

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# NextAuth.js Role実装計画
2+
3+
## 現状の課題
4+
- `src/app/q/page.tsx``session.user.role` にアクセスしようとすると型エラーが発生
5+
- `prisma/schema.prisma` では User モデルに role フィールドが定義済み(@default("user"))
6+
- `src/app/auth.ts` で NextAuth の設定を行っているが、role の型定義が不足
7+
8+
## 実装方針
9+
NextAuth.js の TypeScript サポートを活用して、最小限の変更でセッションの型を拡張する
10+
11+
### 必要な変更点
12+
13+
1. `src/app/auth.ts` に以下の型定義を追加:
14+
```typescript
15+
import { DefaultSession } from "next-auth"
16+
17+
declare module "next-auth" {
18+
interface Session {
19+
user: {
20+
role: string
21+
} & DefaultSession["user"]
22+
}
23+
}
24+
```
25+
26+
2. NextAuth の設定に callbacks を追加:
27+
```typescript
28+
export const { handlers, signIn, signOut, auth } = NextAuth({
29+
providers: [Twitter],
30+
adapter: PrismaAdapter(prisma),
31+
callbacks: {
32+
session: ({ session, user }) => ({
33+
...session,
34+
user: {
35+
...session.user,
36+
role: user.role,
37+
},
38+
}),
39+
},
40+
});
41+
```
42+
43+
## 期待される結果
44+
- `session.user.role` へのアクセスが型安全に行えるようになる
45+
- Prisma の User モデルで定義された role フィールドの値がセッションに正しく反映される
46+
- デフォルトで "user" という値が設定される(Prisma スキーマの @default("user") による)
47+
48+
## 次のステップ
49+
1. Code モードに切り替えて実装を行う
50+
2. 実装後、型エラーが解消されることを確認
51+
3. 必要に応じて、role の値に基づいた機能制限の実装を検討

package-lock.json

+73-72
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"site:www3.nhk.or.jp:fetch": "node --loader ts-node/esm ./scripts/www3.nhk.or.jp/fetch.ts"
2424
},
2525
"dependencies": {
26+
"@auth/core": "^0.37.4",
2627
"@auth/prisma-adapter": "^2.7.4",
2728
"@codemirror/lang-yaml": "^6.1.1",
2829
"@ducanh2912/next-pwa": "^10.0.0",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- AlterTable
2+
ALTER TABLE "User" ADD COLUMN "role" TEXT NOT NULL DEFAULT 'user';

prisma/schema.prisma

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ model User {
1313
email String? @unique
1414
emailVerified DateTime?
1515
image String?
16+
role String @default("user")
1617
accounts Account[]
1718
sessions Session[]
1819

src/app/api/q/route.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { NextResponse } from "next/server";
22
import { prisma } from "@/app/prisma";
3+
import { auth } from "@/app/auth";
34

45
export async function GET() {
56
try {
@@ -23,6 +24,14 @@ import { NextRequest } from "next/server";
2324

2425
export async function POST(req: NextRequest) {
2526
try {
27+
const session = await auth();
28+
29+
if (session?.user?.role !== "admin") {
30+
return NextResponse.json(
31+
{ error: "You do not have permission to create tasks" },
32+
{ status: 403 }
33+
);
34+
}
2635
const body = await req.json();
2736
const { task } = body;
2837
const createdTask = await prisma.jGeoGLUETask.create({
@@ -39,4 +48,4 @@ export async function POST(req: NextRequest) {
3948
{ status: 500 }
4049
);
4150
}
42-
}
51+
}

src/app/auth.ts

+27
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import NextAuth from "next-auth";
2+
import { DefaultSession } from "next-auth";
23

34
// Providers
45
import Twitter from "next-auth/providers/twitter";
@@ -7,7 +8,33 @@ import Twitter from "next-auth/providers/twitter";
78
import { PrismaAdapter } from "@auth/prisma-adapter";
89
import { prisma } from "@/app/prisma";
910

11+
// Prisma Types
12+
import { User as PrismaUser } from "@prisma/client";
13+
14+
type UserWithRole = {
15+
role: string;
16+
} & DefaultSession["user"];
17+
18+
declare module "next-auth" {
19+
interface Session {
20+
user: UserWithRole;
21+
}
22+
}
23+
24+
// Configure NextAuth
1025
export const { handlers, signIn, signOut, auth } = NextAuth({
1126
providers: [Twitter],
1227
adapter: PrismaAdapter(prisma),
28+
callbacks: {
29+
session: async ({ session, user }) => {
30+
const dbUser = user as PrismaUser;
31+
return {
32+
...session,
33+
user: {
34+
...session.user,
35+
role: dbUser.role,
36+
},
37+
};
38+
},
39+
},
1340
});

0 commit comments

Comments
 (0)