From c09f2fb79dec91cec005166e63c28c8be72cc034 Mon Sep 17 00:00:00 2001 From: ggyy <34892002@qq.com> Date: Mon, 25 May 2026 00:19:29 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E9=89=B4=E6=9D=83=E5=8A=A0=E5=BC=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- .../categories/deleteCategory.telefunc.ts | 2 ++ pages/admin/discount-codes/+data.ts | 8 +++-- .../discount-codes/discountCodes.telefunc.ts | 2 ++ pages/admin/media/+data.ts | 9 +++++- .../admin/products/deleteProduct.telefunc.ts | 2 ++ .../admin/products/queryProducts.telefunc.ts | 2 ++ pages/admin/security/+data.ts | 9 +++++- pages/admin/settings/+data.ts | 9 +++++- server/authjs-handler.ts | 29 +++++++++++++++++++ server/entry.ts | 5 +++- server/middleware/admin-auth.ts | 5 ---- 12 files changed, 72 insertions(+), 12 deletions(-) delete mode 100644 server/middleware/admin-auth.ts diff --git a/package.json b/package.json index 59013d9..3c0315e 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "1.4.1", + "version": "1.4.2", "scripts": { "dev": "vike dev", "build": "bun run db:generate && vike build", diff --git a/pages/admin/categories/deleteCategory.telefunc.ts b/pages/admin/categories/deleteCategory.telefunc.ts index 88d4393..a41819d 100644 --- a/pages/admin/categories/deleteCategory.telefunc.ts +++ b/pages/admin/categories/deleteCategory.telefunc.ts @@ -1,5 +1,7 @@ +import { assertAdminAccess } from "../../../modules/auth/service"; import { deleteCategory } from "../../../modules/catalog/service"; export async function onDeleteCategory(input: { id: number }) { + assertAdminAccess(); return deleteCategory(input); } diff --git a/pages/admin/discount-codes/+data.ts b/pages/admin/discount-codes/+data.ts index 673a6a3..18b0178 100644 --- a/pages/admin/discount-codes/+data.ts +++ b/pages/admin/discount-codes/+data.ts @@ -4,8 +4,12 @@ import type { PageContextServer } from "vike/types"; export type Data = Awaited>; export async function data(pageContext: PageContextServer) { - const { prisma } = pageContext as any; - + const { prisma, session } = pageContext as any; + + if (session?.user?.role !== "admin") { + return { discountCodes: { items: [], total: 0 }, products: [] }; + } + const PAGE_SIZE = 20; const [discountCodesResult, products] = await Promise.all([ diff --git a/pages/admin/discount-codes/discountCodes.telefunc.ts b/pages/admin/discount-codes/discountCodes.telefunc.ts index db770b3..dc9d970 100644 --- a/pages/admin/discount-codes/discountCodes.telefunc.ts +++ b/pages/admin/discount-codes/discountCodes.telefunc.ts @@ -1,8 +1,10 @@ +import { assertAdminAccess } from "../../../modules/auth/service"; import { listDiscountCodes, createDiscountCode, updateDiscountCode, deleteDiscountCode } from "../../../modules/discount/service"; import type { PrismaClient } from "../../../generated/prisma/client"; import { getContext } from "telefunc"; function getAdminPrisma(): PrismaClient { + assertAdminAccess(); return getContext<{ prisma: PrismaClient }>().prisma; } diff --git a/pages/admin/media/+data.ts b/pages/admin/media/+data.ts index 1693fab..b3d684f 100644 --- a/pages/admin/media/+data.ts +++ b/pages/admin/media/+data.ts @@ -4,7 +4,14 @@ import { listMediaRecords } from "../../../modules/media/repository"; export type Data = ReturnType; -export async function data(pageContext: { prisma: PrismaClient }) { +export async function data(pageContext: { + prisma: PrismaClient; + session?: { user?: { role?: string } }; +}) { + if (pageContext.session?.user?.role !== "admin") { + return { s3Config: null, mediaList: { items: [], total: 0, page: 1, pageSize: 24, totalPages: 0 } }; + } + const [s3Config, mediaList] = await Promise.all([ getS3Config(pageContext.prisma), listMediaRecords(pageContext.prisma, { page: 1, pageSize: 24 }), diff --git a/pages/admin/products/deleteProduct.telefunc.ts b/pages/admin/products/deleteProduct.telefunc.ts index cd24bb8..9ae6542 100644 --- a/pages/admin/products/deleteProduct.telefunc.ts +++ b/pages/admin/products/deleteProduct.telefunc.ts @@ -1,5 +1,7 @@ +import { assertAdminAccess } from "../../../modules/auth/service"; import { deleteProduct } from "../../../modules/catalog/service"; export async function onDeleteProduct(input: { id: number }) { + assertAdminAccess(); return deleteProduct(input); } diff --git a/pages/admin/products/queryProducts.telefunc.ts b/pages/admin/products/queryProducts.telefunc.ts index e970b90..4acc8eb 100644 --- a/pages/admin/products/queryProducts.telefunc.ts +++ b/pages/admin/products/queryProducts.telefunc.ts @@ -1,3 +1,4 @@ +import { assertAdminAccess } from "../../../modules/auth/service"; import { listAdminProducts } from "../../../modules/catalog/queries"; import { getContext } from "telefunc"; @@ -7,6 +8,7 @@ export async function onQueryProducts(input: { page: number; pageSize: number; }) { + assertAdminAccess(); const { prisma } = getContext() as any; const all = await listAdminProducts(prisma); diff --git a/pages/admin/security/+data.ts b/pages/admin/security/+data.ts index e941992..17001e1 100644 --- a/pages/admin/security/+data.ts +++ b/pages/admin/security/+data.ts @@ -3,7 +3,14 @@ import { getTurnstileConfig } from "../../../server/turnstile"; export type Data = ReturnType; -export async function data(pageContext: { prisma: PrismaClient }) { +export async function data(pageContext: { + prisma: PrismaClient; + session?: { user?: { role?: string } }; +}) { + if (pageContext.session?.user?.role !== "admin") { + return { turnstileEnabled: false }; + } + const config = getTurnstileConfig(); return { turnstileEnabled: config.enabled, diff --git a/pages/admin/settings/+data.ts b/pages/admin/settings/+data.ts index 1e52a2a..90739d4 100644 --- a/pages/admin/settings/+data.ts +++ b/pages/admin/settings/+data.ts @@ -3,7 +3,14 @@ import { getSiteSetting } from "../../../modules/site/service"; export type Data = ReturnType; -export async function data(pageContext: { prisma: PrismaClient }) { +export async function data(pageContext: { + prisma: PrismaClient; + session?: { user?: { role?: string } }; +}) { + if (pageContext.session?.user?.role !== "admin") { + return { site: null }; + } + return { site: await getSiteSetting(pageContext.prisma), }; diff --git a/server/authjs-handler.ts b/server/authjs-handler.ts index d0f880f..217deb0 100644 --- a/server/authjs-handler.ts +++ b/server/authjs-handler.ts @@ -225,6 +225,35 @@ export const authjsSessionMiddleware: UniversalMiddleware = enhance( }, ); +function isAdminPageContextRequest(url: string): boolean { + const parsed = new URL(url); + return /^\/admin\/.*\.pageContext\.json$/.test(parsed.pathname); +} + +export const adminAuthMiddleware: UniversalMiddleware = enhance( + async (request, context) => { + const ctx = context as unknown as AuthContext & { url?: string }; + const url = ctx.url ?? request.url; + + if (!isAdminPageContextRequest(url)) { + return context; + } + + if (ctx.session?.user?.role === "admin") { + return context; + } + + return new Response(JSON.stringify({ error: "Unauthorized" }), { + status: 401, + headers: { "Content-Type": "application/json" }, + }); + }, + { + name: "my-app:admin-auth", + immutable: false, + }, +); + // Note: You can directly define a server middleware instead of defining a Universal Middleware. (You can remove @universal-middleware/* — Vike's scaffolder uses it only to simplify its internal logic, see https://github.com/vikejs/vike/discussions/3116) /** * Auth.js route diff --git a/server/entry.ts b/server/entry.ts index 43e485a..105d707 100644 --- a/server/entry.ts +++ b/server/entry.ts @@ -1,4 +1,4 @@ -import { authjsHandler, authjsSessionMiddleware } from "./authjs-handler"; +import { adminAuthMiddleware, authjsHandler, authjsSessionMiddleware } from "./authjs-handler"; import { getPrismaForD1 } from "./prisma-factory"; import { telefuncHandler } from "./telefunc-handler"; import { prismaMiddleware } from "./prisma-middleware"; @@ -69,6 +69,9 @@ export function createApp() { // Append Auth.js session to context authjsSessionMiddleware, + // Protect admin pageContext.json endpoints + adminAuthMiddleware, + // Auth.js route. See https://authjs.dev/getting-started/installation authjsHandler, diff --git a/server/middleware/admin-auth.ts b/server/middleware/admin-auth.ts deleted file mode 100644 index ca8067c..0000000 --- a/server/middleware/admin-auth.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { Context, Next } from "hono"; - -export async function adminAuthMiddleware(_c: Context, next: Next) { - await next(); -}