Skip to content

Commit

Permalink
[frontend] improve confidence overrides edition + bugfixes (#6837)
Browse files Browse the repository at this point in the history
  • Loading branch information
labo-flg committed May 3, 2024
1 parent a668df2 commit ea7f0ec
Show file tree
Hide file tree
Showing 14 changed files with 95 additions and 82 deletions.
1 change: 1 addition & 0 deletions opencti-platform/opencti-front/lang/front/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -1472,6 +1472,7 @@
"Matches all indicator main observable types if none is listed.": "Entspricht allen Indikator-Hauptbeobachtungstypen, wenn keiner aufgeführt ist.",
"Matrix view": "Matrixansicht",
"Max Confidence": "Maximalvertrauen",
"Max Confidence is overridden for some entity types:": "Max Confidence wird für einige Entitätstypen außer Kraft gesetzt:",
"Max Confidence Level": "Max. Konfidenzniveau",
"Max Confidence Level:": "Max. Konfidenzniveau:",
"Max file size (in MB)": "Maximale Dateigröße (in MB)",
Expand Down
1 change: 1 addition & 0 deletions opencti-platform/opencti-front/lang/front/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1472,6 +1472,7 @@
"Matches all indicator main observable types if none is listed.": "Matches all indicator main observable types if none is listed.",
"Matrix view": "Matrix view",
"Max Confidence": "Max Confidence",
"Max Confidence is overridden for some entity types:": "Max Confidence is overridden for some entity types:",
"Max Confidence Level": "Max Confidence Level",
"Max Confidence Level:": "Max Confidence Level:",
"Max file size (in MB)": "Max file size (in MB)",
Expand Down
1 change: 1 addition & 0 deletions opencti-platform/opencti-front/lang/front/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -1472,6 +1472,7 @@
"Matches all indicator main observable types if none is listed.": "Coincide con todos los tipos observables principales del indicador si no se enumera ninguno.",
"Matrix view": "Vista en matriz",
"Max Confidence": "Max Confianza",
"Max Confidence is overridden for some entity types:": "La confianza máxima se anula para algunos tipos de entidad:",
"Max Confidence Level": "Nivel de confianza máximo",
"Max Confidence Level:": "Nivel Máximo de Confianza:",
"Max file size (in MB)": "Tamaño máximo del archivo (en MB)",
Expand Down
1 change: 1 addition & 0 deletions opencti-platform/opencti-front/lang/front/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1472,6 +1472,7 @@
"Matches all indicator main observable types if none is listed.": "Correspond à tous les types d'observables principaux des indicateurs si aucun n'est listé.",
"Matrix view": "Vue matricielle",
"Max Confidence": "Confiance max",
"Max Confidence is overridden for some entity types:": "La confiance max est surchargée pour certains types d'entités :",
"Max Confidence Level": "Niveau de confiance maximal",
"Max Confidence Level:": "Niveau de confiance maximum :",
"Max file size (in MB)": "Taille maximale du fichier (en Mo)",
Expand Down
1 change: 1 addition & 0 deletions opencti-platform/opencti-front/lang/front/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -1472,6 +1472,7 @@
"Matches all indicator main observable types if none is listed.": "もし何もリストされていなければ、全ての指標となる主要な観測可能な型にマッチします。",
"Matrix view": "マトリックス表示",
"Max Confidence": "マックス・コンフィデンス",
"Max Confidence is overridden for some entity types:": "エンティティの種類によっては、最大信頼度がオーバーライドされます:",
"Max Confidence Level": "最大信頼度",
"Max Confidence Level:": "最大信頼度:",
"Max file size (in MB)": "最大ファイルサイズ(単位:MB)",
Expand Down
1 change: 1 addition & 0 deletions opencti-platform/opencti-front/lang/front/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -1472,6 +1472,7 @@
"Matches all indicator main observable types if none is listed.": "如果没有列出主要观测指标类型,则匹配所有指标类型。",
"Matrix view": "矩阵视图",
"Max Confidence": "最大置信度",
"Max Confidence is overridden for some entity types:": "对于某些实体类型,最大置信度会被覆盖:",
"Max Confidence Level": "最大置信度",
"Max Confidence Level:": "最大置信度:",
"Max file size (in MB)": "最大文件大小(兆字节)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ const ConfidenceField: FunctionComponent<ConfidenceFieldProps> = ({
const { t_i18n } = useFormatter();
const finalLabel = label || t_i18n('Confidence level');
const classes = useStyles();
const { effectiveConfidenceLevel } = useConfidenceLevel();
const getConfidenceLevel = effectiveConfidenceLevel(entityType);
const { getEffectiveConfidenceLevel } = useConfidenceLevel();
const getConfidenceLevel = getEffectiveConfidenceLevel(entityType);
return (
<Alert
classes={{ root: classes.alert, message: classes.message }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,17 @@ type OverridesProps = {
};

const Overrides: React.FC<OverridesProps> = ({ overrides }) => {
return (
<>
{overrides?.map((override, index) => (
<div key={index} style={{ marginTop: '5px' }}>
{`${override.entity_type}: ${override.max_confidence}`}
const { t_i18n } = useFormatter();
return overrides?.length ? (
<div style={{ marginTop: '5px' }}>
<div>{t_i18n('Max Confidence is overridden for some entity types:')}</div>
{overrides.map((override, index) => (
<div key={index}>
{`- ${t_i18n(`entity_${override.entity_type}`)}: ${override.max_confidence}`}
</div>
))}
</>
);
</div>
) : null;
};

const ConfidenceSource: React.FC<UserConfidenceLevelProps> = ({ user }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ const UserConfidenceOverrideField: FunctionComponent<UserConfidenceOverridesFiel
if (isEmptyField(override.entity_type)) {
return `${number} ${t_i18n('New override of an entity')}`;
}
const label = `${t_i18n(`entity_${override.entity_type}`)}`;
const label = `${t_i18n(`entity_${override.entity_type}`)}: ${override.max_confidence}`;
return `${number} ${label[0].toUpperCase()}${label.slice(1)}`;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { userMutationFieldPatch } from '@components/settings/users/edition/UserE
import UserConfidenceOverrideField from '@components/settings/users/edition/UserConfidenceOverrideField';
import { fieldSpacingContainerStyle } from '../../../../../utils/field';
import { useFormatter } from '../../../../../components/i18n';
import { isNotEmptyField } from '../../../../../utils/utils';
import { isEmptyField, isNotEmptyField } from '../../../../../utils/utils';
import useApiMutation from '../../../../../utils/hooks/useApiMutation';

export interface OverrideFormData {
Expand Down Expand Up @@ -73,61 +73,63 @@ const UserEditionConfidence: FunctionComponent<UserEditionConfidenceProps> = ({
userConfidenceValidation(t_i18n)
.validateAt(name, { [name]: value })
.then(() => {
if (name === 'user_confidence_level') {
let finalValue;
if (user.user_confidence_level && isNotEmptyField(value)) {
// We edit an existing value inside the object: use object_path
finalValue = parseInt(value, 10);
} else if (!user.user_confidence_level && value) {
// We have no user_confidence_level, and we add one: push a complete object
finalValue = {
max_confidence: parseInt(value, 10),
overrides: [],
};
} else if (user.user_confidence_level && !value) {
// we have an existing value, but we want to remove it: push [null] (and not null!)
finalValue = [null];
}
if (finalValue) {
commitFieldPatch({
variables: {
id: user.id,
input: {
key: 'user_confidence_level',
object_path: '/user_confidence_level/max_confidence',
value: finalValue,
},
let finalValue;
let object_path;
if (user.user_confidence_level && isNotEmptyField(value)) {
// we are updating the value
object_path = '/user_confidence_level/max_confidence';
finalValue = parseInt(value, 10);
} else if (!user.user_confidence_level && value) {
// We have no user_confidence_level, and we add one: push a complete object
object_path = '/user_confidence_level';
finalValue = {
max_confidence: parseInt(value, 10),
overrides: [],
};
} else if (user.user_confidence_level && !value) {
// we have an existing value, but we want to remove it: push [null] (and not null!)
object_path = '/user_confidence_level/max_confidence';
finalValue = [null];
}
if (finalValue) {
commitFieldPatch({
variables: {
id: user.id,
input: {
key: 'user_confidence_level',
object_path,
value: finalValue,
},
});
}
},
});
}
})
.catch(() => false);
};

const handleSubmitOverride = (index: number, value: OverrideFormData | null) => {
const name = `overrides[${index}]`;
if (!user.user_confidence_level) {
if (isNotEmptyField(value?.entity_type) && isNotEmptyField(value?.max_confidence)) {
let object_path = '';
let finalValue;
// If there is no user_confidence_level defined and value is provided, initialize it with an override
if (isNotEmptyField(value) && value.entity_type && isNotEmptyField(value.max_confidence)) {
commitFieldPatch({
variables: {
id: user.id,
input: {
key: 'user_confidence_level',
value: {
max_confidence: null, // Initialize max_confidence as null
overrides: [{
entity_type: value.entity_type,
max_confidence: parseInt(value.max_confidence ?? '0', 10),
}],
},
},
},
});
if (!user.user_confidence_level) {
object_path = 'user_confidence_level';
finalValue = {
max_confidence: null, // Initialize global max_confidence as null
overrides: [{
entity_type: value.entity_type,
max_confidence: parseInt(value.max_confidence ?? '0', 10),
}],
};
} else {
// If user_confidence_level already exists, just update or add the override
object_path = `/user_confidence_level/overrides/${index}`;
finalValue = [{
entity_type: value.entity_type,
max_confidence: parseInt(value.max_confidence ?? '0', 10),
}];
}
} else if (isNotEmptyField(value) && value.entity_type && isNotEmptyField(value.max_confidence)) {
// If user_confidence_level already exists, just update or add the override
const name = `overrides[${index}]`;
userConfidenceValidation(t_i18n)
.validateAt(name, { [name]: value })
.then(() => {
Expand All @@ -136,17 +138,14 @@ const UserEditionConfidence: FunctionComponent<UserEditionConfidenceProps> = ({
id: user.id,
input: {
key: 'user_confidence_level',
object_path: `/user_confidence_level/overrides/${index}`,
value: [{
entity_type: value.entity_type,
max_confidence: parseInt(value.max_confidence ?? '0', 10),
}],
object_path,
value: finalValue,
},
},
});
})
.catch(() => false);
} else if (!isNotEmptyField(value)) {
} else if (isEmptyField(value)) {
commitFieldPatch({
variables: {
id: user.id,
Expand Down Expand Up @@ -191,6 +190,7 @@ const UserEditionConfidence: FunctionComponent<UserEditionConfidenceProps> = ({
onClick={() => arrayHelpers.push({ entity_type: '', max_confidence: 0 })}
style={{ marginTop: '5px' }}
size="large"
disabled={user.effective_confidence_level === null}
>
<Add fontSize="small" />
</IconButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,21 @@ const useConfidenceLevel = () => {
const userEffectiveConfidenceLevel = me.effective_confidence_level;
const overrides = userEffectiveConfidenceLevel?.overrides ?? [];

const effectiveConfidenceLevel = (entityType: string | null | undefined) => {
const getEffectiveConfidenceLevel = (entityType: string | null | undefined) => {
if (!userEffectiveConfidenceLevel) {
return null;
}
// asking for the global CL
if (!entityType) {
return userEffectiveConfidenceLevel?.max_confidence ?? 0;
return userEffectiveConfidenceLevel.max_confidence;
}
// otherwise, check if an override exist
const override = overrides.find((n) => n.entity_type === entityType);
if (override) {
return override.max_confidence;
}
return userEffectiveConfidenceLevel?.max_confidence ?? 0;
// no override for this entity_type, return the global value
return userEffectiveConfidenceLevel.max_confidence;
};

const checkConfidenceForEntity = (entity: { entity_type?: string | null, confidence?: number | null }, notifyError = false) => {
Expand All @@ -27,7 +33,10 @@ const useConfidenceLevel = () => {
return false;
}

const entityConfidenceLevel = effectiveConfidenceLevel(entity.entity_type);
const entityConfidenceLevel = getEffectiveConfidenceLevel(entity.entity_type);
if (entityConfidenceLevel === null) {
return false;
}

if (entity.confidence && entityConfidenceLevel >= entity.confidence) {
return true;
Expand All @@ -42,7 +51,7 @@ const useConfidenceLevel = () => {
return true;
};

return { checkConfidenceForEntity, effectiveConfidenceLevel };
return { checkConfidenceForEntity, getEffectiveConfidenceLevel };
};

export default useConfidenceLevel;
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { now } from '../Time';
import { AuthorizedMembers, authorizedMembersToOptions, INPUT_AUTHORIZED_MEMBERS } from '../authorizedMembers';
import useConfidenceLevel from './useConfidenceLevel';

const DEFAULT_CONFIDENCE = 75;

export const useComputeDefaultValues = () => {
const { fieldToCategory } = useVocabularyCategory();

Expand Down Expand Up @@ -82,7 +84,7 @@ const useDefaultValues = <Values extends FormikValues>(
notEmptyValues?: Partial<Values>,
) => {
const computeDefaultValues = useComputeDefaultValues();
const { effectiveConfidenceLevel } = useConfidenceLevel();
const { getEffectiveConfidenceLevel } = useConfidenceLevel();

const entitySettings = useEntitySettings(id).at(0);
if (!entitySettings) {
Expand Down Expand Up @@ -115,10 +117,10 @@ const useDefaultValues = <Values extends FormikValues>(
},
);

// Default confidence
// Default confidence is computed from the user's effective level
if (keys.includes('confidence') && isEmptyField(initialValues.confidence) && isEmptyField(defaultValues.confidence)) {
const getEffectiveConfidence = effectiveConfidenceLevel(id);
defaultValues.confidence = getEffectiveConfidence ?? 75;
const level = getEffectiveConfidenceLevel(id);
defaultValues.confidence = level ?? DEFAULT_CONFIDENCE;
}

// Default published
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,13 @@ export const computeUserEffectiveConfidenceLevel = (user: AuthUser) => {
const overrides = Array.from(overridesMap.entries())
.map(([key, value]) => ({ entity_type: key, max_confidence: value }));

if (isEmptyField(maxLevel) && overrides.length === 0) {
// note that a user cannot have only overrides
if (isEmptyField(maxLevel)) {
return null;
}

return {
max_confidence: isNotEmptyField(maxLevel) ? cropNumber(maxLevel as number, 0, 100) : null,
max_confidence: cropNumber(maxLevel as number, 0, 100),
overrides,
source,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,7 @@ describe('Confidence level utilities', () => {
groups: [groupNull, groupNull],
capabilities: []
};
expect(computeUserEffectiveConfidenceLevel(userK as unknown as AuthUser)).toEqual({
max_confidence: null,
source: null,
overrides: [
{ entity_type: 'Report', max_confidence: 50 },
{ entity_type: 'Malware', max_confidence: 35 }
],
});
expect(computeUserEffectiveConfidenceLevel(userK as unknown as AuthUser)).toEqual(null);
});
});

Expand Down

0 comments on commit ea7f0ec

Please sign in to comment.