fix: 鉴权加强

This commit is contained in:
ggyy
2026-05-25 00:19:29 +08:00
parent 1980c7a989
commit c09f2fb79d
12 changed files with 72 additions and 12 deletions

View File

@@ -1,5 +1,5 @@
{
"version": "1.4.1",
"version": "1.4.2",
"scripts": {
"dev": "vike dev",
"build": "bun run db:generate && vike build",

View File

@@ -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);
}

View File

@@ -4,8 +4,12 @@ import type { PageContextServer } from "vike/types";
export type Data = Awaited<ReturnType<typeof data>>;
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([

View File

@@ -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;
}

View File

@@ -4,7 +4,14 @@ import { listMediaRecords } from "../../../modules/media/repository";
export type Data = ReturnType<typeof data>;
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 }),

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -3,7 +3,14 @@ import { getTurnstileConfig } from "../../../server/turnstile";
export type Data = ReturnType<typeof data>;
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,

View File

@@ -3,7 +3,14 @@ import { getSiteSetting } from "../../../modules/site/service";
export type Data = ReturnType<typeof data>;
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),
};

View File

@@ -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

View File

@@ -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,

View File

@@ -1,5 +0,0 @@
import type { Context, Next } from "hono";
export async function adminAuthMiddleware(_c: Context, next: Next) {
await next();
}