소스 검색

RHL-008-feat(auth): implement GET /api/auth/me endpoint with session identity retrieval

Code_Uwe 17 시간 전
부모
커밋
5cce198b45
2개의 변경된 파일86개의 추가작업 그리고 0개의 파일을 삭제
  1. 44 0
      app/api/auth/me/route.js
  2. 42 0
      app/api/auth/me/route.test.js

+ 44 - 0
app/api/auth/me/route.js

@@ -0,0 +1,44 @@
+// app/api/auth/me/route.js
+
+import { getSession } from "@/lib/auth/session";
+import { withErrorHandling, json } from "@/lib/api/errors";
+
+/**
+ * Force dynamic execution (RHL-006):
+ * - auth-related response must never be cached/shared accidentally.
+ */
+export const dynamic = "force-dynamic";
+
+/**
+ * GET /api/auth/me
+ *
+ * Purpose:
+ * - Provide the current session identity for frontend consumers.
+ *
+ * Semantics (frontend-friendly):
+ * - 200 with { user: null } when unauthenticated
+ * - 200 with { user: { userId, role, branchId } } when authenticated
+ *
+ * This avoids using 401 as control-flow for basic "am I logged in?" checks.
+ */
+export const GET = withErrorHandling(
+	async function GET() {
+		const session = await getSession();
+
+		if (!session) {
+			return json({ user: null }, 200);
+		}
+
+		return json(
+			{
+				user: {
+					userId: session.userId,
+					role: session.role,
+					branchId: session.branchId ?? null,
+				},
+			},
+			200
+		);
+	},
+	{ logPrefix: "[api/auth/me]" }
+);

+ 42 - 0
app/api/auth/me/route.test.js

@@ -0,0 +1,42 @@
+/* @vitest-environment node */
+
+import { describe, it, expect, vi, beforeEach } from "vitest";
+
+vi.mock("@/lib/auth/session", () => ({
+	getSession: vi.fn(),
+}));
+
+import { getSession } from "@/lib/auth/session";
+import { GET, dynamic } from "./route.js";
+
+describe("GET /api/auth/me", () => {
+	beforeEach(() => {
+		vi.clearAllMocks();
+	});
+
+	it('exports dynamic="force-dynamic" (RHL-006)', () => {
+		expect(dynamic).toBe("force-dynamic");
+	});
+
+	it("returns { user: null } when unauthenticated", async () => {
+		getSession.mockResolvedValue(null);
+
+		const res = await GET();
+		expect(res.status).toBe(200);
+		expect(await res.json()).toEqual({ user: null });
+	});
+
+	it("returns user payload when authenticated", async () => {
+		getSession.mockResolvedValue({
+			userId: "u1",
+			role: "branch",
+			branchId: "NL01",
+		});
+
+		const res = await GET();
+		expect(res.status).toBe(200);
+		expect(await res.json()).toEqual({
+			user: { userId: "u1", role: "branch", branchId: "NL01" },
+		});
+	});
+});