fix(auth): harden confidential knowledge access checks and sensitivity filtering

This commit is contained in:
2026-02-09 17:09:34 +08:00
parent 71f8f7d1c3
commit 2f8645a011
19 changed files with 383 additions and 80 deletions

View File

@@ -1,6 +1,6 @@
import { useCallback, useEffect, useMemo, useState } from "react";
import { Card, Button, Table, Tooltip, Tag, App, Statistic } from "antd";
import { DeleteOutlined, EditOutlined } from "@ant-design/icons";
import { DeleteOutlined, EditOutlined, LockOutlined } from "@ant-design/icons";
import { useNavigate } from "react-router";
import CardView from "@/components/CardView";
import { SearchControls } from "@/components/SearchControls";
@@ -15,8 +15,14 @@ import {
knowledgeStatusOptions,
mapKnowledgeSet,
KnowledgeSetView,
sensitivityMap,
sensitivityOptions,
} from "../knowledge-management.const";
import { KnowledgeManagementStatistics, KnowledgeSet } from "../knowledge-management.model";
import {
KnowledgeManagementStatistics,
KnowledgeSensitivityType,
KnowledgeSet,
} from "../knowledge-management.model";
import CreateKnowledgeSet from "../components/CreateKnowledgeSet";
import {
createDatasetTagUsingPost,
@@ -76,6 +82,11 @@ export default function KnowledgeManagementPage() {
label: "状态",
options: knowledgeStatusOptions,
},
{
key: "sensitivity",
label: "敏感级别",
options: sensitivityOptions,
},
{
key: "tags",
label: "标签",
@@ -101,7 +112,16 @@ export default function KnowledgeManagementPage() {
30000,
false,
[],
0
0,
(filters) => {
const sensitivity = Array.isArray(filters?.sensitivity)
? (filters.sensitivity[0] as string | undefined)
: undefined;
if (!sensitivity || sensitivity === "all") {
return {};
}
return { sensitivity: sensitivity.toUpperCase() };
}
);
const fetchStatistics = useCallback(async () => {
@@ -204,6 +224,25 @@ export default function KnowledgeManagementPage() {
<Tag color={status?.color}>{status?.label}</Tag>
),
},
{
title: "敏感级别",
dataIndex: "sensitivity",
key: "sensitivity",
width: 100,
render: (sensitivity: string) => {
const normalized = sensitivity ? sensitivity.toUpperCase() : "";
const meta = normalized ? sensitivityMap[normalized] : null;
if (!meta) return "-";
return (
<Tag
color={meta.color}
icon={normalized === KnowledgeSensitivityType.CONFIDENTIAL ? <LockOutlined /> : undefined}
>
{meta.label}
</Tag>
);
},
},
{
title: "领域",
dataIndex: "domain",

View File

@@ -9,10 +9,11 @@ import {
import {
knowledgeSourceTypeOptions,
knowledgeStatusOptions,
// sensitivityOptions,
sensitivityOptions,
} from "../knowledge-management.const";
import {
KnowledgeSet,
KnowledgeSensitivityType,
KnowledgeStatusType,
} from "../knowledge-management.model";
import { queryDatasetTagsUsingGet } from "@/pages/DataManagement/dataset.api";
@@ -65,7 +66,7 @@ export default function CreateKnowledgeSet({
validFrom: data.validFrom ? dayjs(data.validFrom) : null,
validTo: data.validTo ? dayjs(data.validTo) : null,
sourceType: data.sourceType,
sensitivity: data.sensitivity,
sensitivity: data.sensitivity?.toUpperCase() || undefined,
tags: data.tags?.map((tag) => tag.name) || [],
metadata: data.metadata,
});
@@ -85,6 +86,9 @@ export default function CreateKnowledgeSet({
const payload = {
...values,
sensitivity: values.sensitivity
? String(values.sensitivity).toUpperCase()
: undefined,
validFrom,
validTo,
tags: values.tags || [],
@@ -124,7 +128,11 @@ export default function CreateKnowledgeSet({
icon={<PlusOutlined />}
onClick={() => {
form.resetFields();
form.setFieldsValue({ status: KnowledgeStatusType.DRAFT, tags: [] });
form.setFieldsValue({
status: KnowledgeStatusType.DRAFT,
sensitivity: KnowledgeSensitivityType.INTERNAL,
tags: [],
});
setOpen(true);
}}
>
@@ -170,9 +178,9 @@ export default function CreateKnowledgeSet({
<Form.Item label="负责人" name="owner">
<Input placeholder="请输入负责人" />
</Form.Item>
{/* <Form.Item label="敏感级别" name="sensitivity">
<Select options={sensitivityOptions} placeholder="请选择敏感级别" />
</Form.Item> */}
<Form.Item label="敏感级别" name="sensitivity">
<Select options={sensitivityOptions} placeholder="请选择敏感级别" allowClear />
</Form.Item>
</div>
<div className="grid grid-cols-2 gap-4">
<Form.Item label="有效期开始" name="validFrom">

View File

@@ -11,6 +11,7 @@ import {
KnowledgeContentType,
KnowledgeItem,
KnowledgeSet,
KnowledgeSensitivityType,
KnowledgeSourceType,
KnowledgeStatusType,
} from "./knowledge-management.model";
@@ -66,10 +67,22 @@ export const knowledgeSourceTypeOptions = [
{ label: "文件上传", value: KnowledgeSourceType.FILE_UPLOAD },
];
// export const sensitivityOptions = [
// { label: "敏感", value: "敏感" },
// { label: "不敏感", value: "不敏感" },
// ];
export const sensitivityOptions = [
{ label: "公开", value: KnowledgeSensitivityType.PUBLIC },
{ label: "内部", value: KnowledgeSensitivityType.INTERNAL },
{ label: "保密", value: KnowledgeSensitivityType.CONFIDENTIAL },
];
export type SensitivityMeta = {
label: string;
color: string;
};
export const sensitivityMap: Record<string, SensitivityMeta> = {
[KnowledgeSensitivityType.PUBLIC]: { label: "公开", color: "#52c41a" },
[KnowledgeSensitivityType.INTERNAL]: { label: "内部", color: "#1677ff" },
[KnowledgeSensitivityType.CONFIDENTIAL]: { label: "保密", color: "#f5222d" },
};
export type KnowledgeSetView = {
id: string;
@@ -118,6 +131,7 @@ export type KnowledgeItemView = {
};
export function mapKnowledgeSet(data: KnowledgeSet): KnowledgeSetView {
const normalizedSensitivity = data.sensitivity?.toUpperCase();
return {
id: data.id,
name: data.name,
@@ -131,7 +145,7 @@ export function mapKnowledgeSet(data: KnowledgeSet): KnowledgeSetView {
validFrom: data.validFrom,
validTo: data.validTo,
sourceType: data.sourceType,
sensitivity: data.sensitivity,
sensitivity: normalizedSensitivity,
metadata: data.metadata,
createdAt: data.createdAt ? formatDateTime(data.createdAt) : "",
updatedAt: data.updatedAt ? formatDateTime(data.updatedAt) : "",
@@ -142,6 +156,7 @@ export function mapKnowledgeSet(data: KnowledgeSet): KnowledgeSetView {
}
export function mapKnowledgeItem(data: KnowledgeItem): KnowledgeItemView {
const normalizedSensitivity = data.sensitivity?.toUpperCase();
return {
id: data.id,
setId: data.setId,
@@ -156,7 +171,7 @@ export function mapKnowledgeItem(data: KnowledgeItem): KnowledgeItemView {
validFrom: data.validFrom,
validTo: data.validTo,
sourceType: data.sourceType,
sensitivity: data.sensitivity,
sensitivity: normalizedSensitivity,
sourceDatasetId: data.sourceDatasetId,
sourceFileId: data.sourceFileId,
relativePath: data.relativePath,

View File

@@ -17,6 +17,12 @@ export enum KnowledgeSourceType {
FILE_UPLOAD = "FILE_UPLOAD",
}
export enum KnowledgeSensitivityType {
PUBLIC = "PUBLIC",
INTERNAL = "INTERNAL",
CONFIDENTIAL = "CONFIDENTIAL",
}
export interface KnowledgeTag {
id: string;
name: string;