From 694e9a207a484a7ab614ed1d8520278feed1d304 Mon Sep 17 00:00:00 2001 From: kkfluous Date: Thu, 16 Apr 2026 22:04:52 +0800 Subject: [PATCH] feat(scheduling): enable department/personal permission filtering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Disable BYPASS_AUTH (was true, now false) — backend enforces JWT auth - Scheduling suggestions filtered by department/manager permissions: - full: see all suggestions - department: see only own department's vehicles - personal: see only own managed vehicles - Candidate vehicles (inventory) remain fully visible to all - Summary recalculated after permission filtering - Consistent with mileage module permission model Co-Authored-By: Claude Opus 4.6 (1M context) --- src/server/auth/middleware.ts | 2 +- src/server/routes/scheduling/suggestions.ts | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/server/auth/middleware.ts b/src/server/auth/middleware.ts index eba6c5b..1586009 100644 --- a/src/server/auth/middleware.ts +++ b/src/server/auth/middleware.ts @@ -5,7 +5,7 @@ import type { JwtPayload, AuthUser } from './types.js'; const JWT_SECRET = process.env.JWT_SECRET || 'ln-bi-default-secret'; // 临时:跳过所有认证(保留完整逻辑便于快速恢复) -const BYPASS_AUTH = true; +const BYPASS_AUTH = false; export async function authMiddleware(c: Context, next: Next) { const path = c.req.path; diff --git a/src/server/routes/scheduling/suggestions.ts b/src/server/routes/scheduling/suggestions.ts index 387daab..a42b34d 100644 --- a/src/server/routes/scheduling/suggestions.ts +++ b/src/server/routes/scheduling/suggestions.ts @@ -5,7 +5,7 @@ import { fetchVehicleInfoMap } from '../mileage/vehicle-info.js'; import { mapRegion } from '../vehicles.js'; import { filterByPermission, maskCustomerNames } from '../../auth/permissions.js'; import { classifyVehicle, generateSuggestions } from './algorithm.js'; -import type { EnrichedVehicle, InventoryVehicle, SchedulingResponse } from './types.js'; +import type { EnrichedVehicle, InventoryVehicle, SchedulingResponse, SchedulingSummary } from './types.js'; import type { AuthUser } from '../../auth/types.js'; // --------------------------------------------------------------------------- @@ -305,8 +305,20 @@ app.get('/', async (c) => { vehicleCount: targetVehicleCounts.get(t.id) || 0, })); + // Recalculate summary based on permission-filtered results + const filteredQualified = masked.filter((s: any) => s.type === 'replace_qualified').length; + const filteredHopeless = masked.filter((s: any) => s.type === 'rescue_hopeless').length; + const filteredSummary: SchedulingSummary = { + qualifiedCount: summary.qualifiedCount, + hopelessCount: summary.hopelessCount, + suggestionCount: masked.length, + estimatedGain: masked.filter((s: any) => + s.candidates?.some((c: any) => c.canQualifyAfterSwap) + ).length, + }; + const response: SchedulingResponse = { - summary, + summary: filteredSummary, suggestions: masked, targets: targetOptions, };