Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion packages/shared/lib/api/sqle/service/common.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,11 @@ export enum MatchConditionReqV1TypeEnum {

db_type = 'db_type',

sql_source = 'sql_source'
sql_source = 'sql_source',

schema = 'schema',

object_name = 'object_name'
}

export enum OperationRecordListStatusEnum {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@ import ExemptedAuditResultWithActions from '../ExemptedAuditResultWithActions';
import CollapsibleExemptedSection from './CollapsibleExemptedSection';
import FullSqlExemptedResultItem from '../FullSqlExemptedResultItem';
import { AuditResultExemptionPanelStyleWrapper } from './style';
import {
AuditResultExemptionPanelLayout,
AuditResultExemptionPanelProps
} from './types';
import { AuditResultExemptionPanelProps } from './types';
import { IAuditResultItem } from '../../ReportDrawer/index.type';

export type { AuditResultExemptionPanelLayout } from './types';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,32 @@
);
}

if (
type === MatchConditionReqV1TypeEnum.schema ||
type === MatchConditionReqV1TypeEnum.object_name
) {
return (
<Space align="center" size={8}>
<Form.Item
name={[fieldName, 'content']}
rules={[{ required: true, whitespace: true }]}
noStyle
>
<BasicInput
style={{ width: MATCH_ROW_CONTENT_WIDTH }}
placeholder={t('common.form.placeholder.input')}
/>
</Form.Item>
<EmptyBox if={type === MatchConditionReqV1TypeEnum.object_name}>
<BasicToolTips
title={t('ruleException.matchType.objectNameTip')}
suffixIcon
/>
</EmptyBox>
</Space>
);

Check warning on line 294 in packages/sqle/src/components/RuleExceptionMatchConditions/Form/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
}

Check warning on line 295 in packages/sqle/src/components/RuleExceptionMatchConditions/Form/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch

return (
<Form.Item
name={[fieldName, 'content']}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ export const AuditWhitelistMatchTypeDirection: Record<
| MatchConditionReqV1TypeEnum.audit_task_type
| MatchConditionReqV1TypeEnum.audit_task_id
| MatchConditionReqV1TypeEnum.db_type
| MatchConditionReqV1TypeEnum.sql_source,
| MatchConditionReqV1TypeEnum.sql_source
| MatchConditionReqV1TypeEnum.schema
| MatchConditionReqV1TypeEnum.object_name,
string
> = {
sql: t('ruleException.matchType.sql'),
Expand All @@ -31,6 +33,10 @@ export const AuditWhitelistMatchTypeDirection: Record<
[MatchConditionReqV1TypeEnum.db_type]: t('ruleException.matchType.db_type'),
[MatchConditionReqV1TypeEnum.sql_source]: t(
'ruleException.matchType.sql_source'
),
[MatchConditionReqV1TypeEnum.schema]: t('ruleException.matchType.schema'),
[MatchConditionReqV1TypeEnum.object_name]: t(
'ruleException.matchType.object_name'
)
};

Expand Down Expand Up @@ -74,6 +80,8 @@ export const AuditWhitelistExtendedMatchTypeOptions = [
MatchConditionReqV1TypeEnum.audit_task_id,
MatchConditionReqV1TypeEnum.db_type,
MatchConditionReqV1TypeEnum.sql_source,
MatchConditionReqV1TypeEnum.schema,
MatchConditionReqV1TypeEnum.object_name,
MatchConditionReqV1TypeEnum.fp_sql,
MatchConditionReqV1TypeEnum.sql
].map((value) => ({
Expand All @@ -87,7 +95,9 @@ export const AuditWhitelistAllMatchTypeOptions = [
MatchConditionReqV1TypeEnum.audit_task_type,
MatchConditionReqV1TypeEnum.audit_task_id,
MatchConditionReqV1TypeEnum.db_type,
MatchConditionReqV1TypeEnum.sql_source
MatchConditionReqV1TypeEnum.sql_source,
MatchConditionReqV1TypeEnum.schema,
MatchConditionReqV1TypeEnum.object_name
].map((value) => ({
label:
AuditWhitelistMatchTypeDirection[
Expand Down
3 changes: 3 additions & 0 deletions packages/sqle/src/locale/en-US/ruleException.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ export default {
audit_task_type: 'Scan task type',
audit_task_id: 'Scan task',
sql_source: 'Source',
schema: 'Schema',
object_name: 'Object name',
objectNameTip: 'Includes tables and views',
sqlSource: {
sql_audit_record: 'Quick audit',
audit_plan: 'Scan task'
Expand Down
3 changes: 3 additions & 0 deletions packages/sqle/src/locale/zh-CN/ruleException.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ export default {
audit_task_type: '扫描任务类型',
audit_task_id: '扫描任务',
sql_source: '来源',
schema: '库名',
object_name: '对象名',
objectNameTip: '含表与视图',
sqlSource: {
sql_audit_record: '快捷审核',
audit_plan: '扫描任务'
Expand Down
176 changes: 176 additions & 0 deletions packages/sqle/src/page/RuleException/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
normalizeMatchRowsOrder,
rowsToAuditWhitelistBody,
rowsToBlacklistBody,
toSqlManageRuleExceptionRecord,
validateAuditWhitelistMatchRows,
validateMatchRows
} from '../utils';
Expand Down Expand Up @@ -87,6 +88,181 @@ describe('sqle/page/RuleException/utils', () => {
});
});

it('buildBlacklistPrefillFromSqlManage prefers schema+object_name when preferSchemaObjectMatch', () => {
expect(
buildBlacklistPrefillFromSqlManage(
{
sql_fingerprint: 'CREATE TABLE `v_exc_target` (`id` int)',
instance_id: '123',
db_type: 'MySQL',
schema_name: 'sqle',
schema_meta_name: 'v_exc_target',
source: {
sql_source_type: 'mysql_schema_meta',
sql_source_ids: ['1']
}
},
{ preferSchemaObjectMatch: true }
)
).toEqual({
match_conditions: [
{
type: MatchConditionReqV1TypeEnum.schema,
content: 'sqle'
},
{
type: MatchConditionReqV1TypeEnum.object_name,
content: 'v_exc_target'
},
{
type: MatchConditionReqV1TypeEnum.instance,
content: '123'
},
{
type: MatchConditionReqV1TypeEnum.audit_task_type,
content: 'mysql_schema_meta'
},
{
type: MatchConditionReqV1TypeEnum.audit_task_id,
content: '1'
},
{
type: MatchConditionReqV1TypeEnum.sql_source,
content: 'audit_plan'
},
{
type: MatchConditionReqV1TypeEnum.db_type,
content: 'MySQL'
}
]
});
});

it('buildBlacklistPrefillFromSqlManage falls back to fp_sql when preferSchemaObjectMatch lacks object (AC-001b)', () => {
expect(
buildBlacklistPrefillFromSqlManage(
{
sql_fingerprint: 'CREATE TABLE `t` (`id` int)',
instance_id: '123',
db_type: 'MySQL',
schema_name: 'sqle',
source: {
sql_source_type: 'mysql_schema_meta',
sql_source_ids: ['1']
}
},
{ preferSchemaObjectMatch: true }
)
).toEqual({
match_conditions: [
{
type: MatchConditionReqV1TypeEnum.fp_sql,
content: 'CREATE TABLE `t` (`id` int)'
},
{
type: MatchConditionReqV1TypeEnum.instance,
content: '123'
},
{
type: MatchConditionReqV1TypeEnum.audit_task_type,
content: 'mysql_schema_meta'
},
{
type: MatchConditionReqV1TypeEnum.audit_task_id,
content: '1'
},
{
type: MatchConditionReqV1TypeEnum.sql_source,
content: 'audit_plan'
},
{
type: MatchConditionReqV1TypeEnum.db_type,
content: 'MySQL'
}
]
});
});

it('buildBlacklistPrefillFromSqlManage falls back to fp_sql when preferSchemaObjectMatch lacks schema (AC-001b)', () => {
expect(
buildBlacklistPrefillFromSqlManage(
{
sql_fingerprint: 'CREATE TABLE `t` (`id` int)',
instance_id: '123',
db_type: 'MySQL',
schema_meta_name: 't',
source: {
sql_source_type: 'mysql_schema_meta',
sql_source_ids: ['1']
}
},
{ preferSchemaObjectMatch: true }
)
).toEqual({
match_conditions: [
{
type: MatchConditionReqV1TypeEnum.fp_sql,
content: 'CREATE TABLE `t` (`id` int)'
},
{
type: MatchConditionReqV1TypeEnum.instance,
content: '123'
},
{
type: MatchConditionReqV1TypeEnum.audit_task_type,
content: 'mysql_schema_meta'
},
{
type: MatchConditionReqV1TypeEnum.audit_task_id,
content: '1'
},
{
type: MatchConditionReqV1TypeEnum.sql_source,
content: 'audit_plan'
},
{
type: MatchConditionReqV1TypeEnum.db_type,
content: 'MySQL'
}
]
});
});

it('toSqlManageRuleExceptionRecord reads schema_name and info.schema_meta_name (AC-011 consume)', () => {
const withObject = {
sql_fingerprint: 'CREATE TABLE `v` (`id` int)',
schema_name: 'sqle',
info: { schema_meta_name: 'v_exc_target' }
};
expect(toSqlManageRuleExceptionRecord(withObject)).toMatchObject({
schema_name: 'sqle',
schema_meta_name: 'v_exc_target'
});

const emptyObjectName = {
sql_fingerprint: 'select 1',
schema_name: 'sqle',
info: { schema_meta_name: '' }
};
expect(
toSqlManageRuleExceptionRecord(emptyObjectName)?.schema_meta_name
).toBeUndefined();

const missingKey = {
sql_fingerprint: 'select 1',
info: {}
};
expect(
toSqlManageRuleExceptionRecord(missingKey)?.schema_meta_name
).toBeUndefined();

expect(
toSqlManageRuleExceptionRecord({
sql_fingerprint: 'select 1'
})?.schema_meta_name
).toBeUndefined();
});

it('buildBlacklistPrefillFromSqlManage skips audit task match for quick audit source', () => {
expect(
buildBlacklistPrefillFromSqlManage({
Expand Down
1 change: 0 additions & 1 deletion packages/sqle/src/page/RuleException/index.type.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
IAuditResult,
IAuditWhitelistResV1,
ISkippedByRuleExceptionItem
} from '@actiontech/shared/lib/api/sqle/service/common';
Expand Down
Loading
Loading