Skip to content

Commit

Permalink
[backend|frontend]Add the ability to customize the expiration time fo…
Browse files Browse the repository at this point in the history
…r expectations
  • Loading branch information
johanah29 committed Sep 25, 2024
1 parent 513ba2e commit f65620b
Show file tree
Hide file tree
Showing 11 changed files with 271 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,74 +20,83 @@
@Log
public class ExpectationsExpirationManagerService {

private final InjectExpectationService injectExpectationService;
private final ExpectationsExpirationManagerConfig config;
private final InjectExpectationService injectExpectationService;
private final ExpectationsExpirationManagerConfig config;


@Transactional(rollbackFor = Exception.class)
public void computeExpectations() {
List<InjectExpectation> expectations = this.injectExpectationService.expectationsNotFill();
if (!expectations.isEmpty()) {
this.computeExpectationsForAssets(expectations);
this.computeExpectationsForAssetGroups(expectations);
this.computeExpectations(expectations);
}
@Transactional(rollbackFor = Exception.class)
public void computeExpectations() {
List<InjectExpectation> expectations = this.injectExpectationService.expectationsNotFill();
if (!expectations.isEmpty()) {
this.computeExpectationsForAssets(expectations);
this.computeExpectationsForAssetGroups(expectations);
this.computeExpectations(expectations);
}
}

// -- PRIVATE --
// -- PRIVATE --

private void computeExpectations(@NotNull final List<InjectExpectation> expectations) {
List<InjectExpectation> expectationAssets = expectations.stream().toList();
expectationAssets.forEach((expectation) -> {
// Maximum time for detection
if (isExpired(expectation, this.config.getExpirationTimeInMinute())) {
String result = computeFailedMessage(expectation.getType());
this.injectExpectationService.computeExpectation(
expectation,
this.config.getId(),
"collector",
PRODUCT_NAME,
result,
false
);
}
});
}
private void computeExpectations(@NotNull final List<InjectExpectation> expectations) {
List<InjectExpectation> expectationAssets = expectations.stream().toList();
expectationAssets.forEach((expectation) -> {
Long userExpirationTime = expectation.getExpirationTime();
if (userExpirationTime != null) {
// Maximum time for detection
if (isExpired(expectation, Math.toIntExact(userExpirationTime / 60))) {
String result = computeFailedMessage(expectation.getType());
this.injectExpectationService.computeExpectation(
expectation,
this.config.getId(),
"collector",
PRODUCT_NAME,
result,
false
);
}
}

private void computeExpectationsForAssets(@NotNull final List<InjectExpectation> expectations) {
List<InjectExpectation> expectationAssets = expectations.stream().filter(e -> e.getAsset() != null).toList();
expectationAssets.forEach((expectation) -> {
// Maximum time for detection
if (isExpired(expectation, this.config.getAssetExpirationTimeInMinute())) {
String result = computeFailedMessage(expectation.getType());
this.injectExpectationService.computeExpectation(
expectation,
this.config.getId(),
"collector",
PRODUCT_NAME,
result,
false
);
}
});
}
});
}

private void computeExpectationsForAssetGroups(@NotNull final List<InjectExpectation> expectations) {
List<InjectExpectation> expectationAssetGroups = expectations.stream().filter(e -> e.getAssetGroup() != null).toList();
expectationAssetGroups.forEach((expectationAssetGroup -> {
List<InjectExpectation> expectationAssets = this.injectExpectationService.expectationsForAssets(
expectationAssetGroup.getInject(), expectationAssetGroup.getAssetGroup(), expectationAssetGroup.getType()
);
// Every expectation assets are filled
if (expectationAssets.stream().noneMatch(e -> e.getResults().isEmpty())) {
this.injectExpectationService.computeExpectationGroup(
expectationAssetGroup,
expectationAssets,
this.config.getId(),
"collector",
PRODUCT_NAME
);
}
}));
}
private void computeExpectationsForAssets(@NotNull final List<InjectExpectation> expectations) {
List<InjectExpectation> expectationAssets = expectations.stream().filter(e -> e.getAsset() != null).toList();
expectationAssets.forEach((expectation) -> {
Long userExpirationTime = expectation.getExpirationTime();
if (userExpirationTime != null) {
// Maximum time for detection
if (isExpired(expectation, Math.toIntExact(userExpirationTime / 60))) {
String result = computeFailedMessage(expectation.getType());
this.injectExpectationService.computeExpectation(
expectation,
this.config.getId(),
"collector",
PRODUCT_NAME,
result,
false
);
}
}

});
}

private void computeExpectationsForAssetGroups(@NotNull final List<InjectExpectation> expectations) {
List<InjectExpectation> expectationAssetGroups = expectations.stream().filter(e -> e.getAssetGroup() != null)
.toList();
expectationAssetGroups.forEach((expectationAssetGroup -> {
List<InjectExpectation> expectationAssets = this.injectExpectationService.expectationsForAssets(
expectationAssetGroup.getInject(), expectationAssetGroup.getAssetGroup(), expectationAssetGroup.getType()
);
// Every expectation assets are filled
if (expectationAssets.stream().noneMatch(e -> e.getResults().isEmpty())) {
this.injectExpectationService.computeExpectationGroup(
expectationAssetGroup,
expectationAssets,
this.config.getId(),
"collector",
PRODUCT_NAME
);
}
}));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.openbas.migration;

import org.flywaydb.core.api.migration.BaseJavaMigration;
import org.flywaydb.core.api.migration.Context;

import java.sql.Connection;
import java.sql.Statement;

public class V3_40__Add_column_expiration_time_expectations extends BaseJavaMigration {

@Override
public void migrate(Context context) throws Exception {
Statement select = context.getConnection().createStatement();
Connection connection = context.getConnection();
Statement statement = connection.createStatement();
long technicalMinutesExpirationTime = 60L;
long manualMinutesExpirationTime = 360L;

select.execute("ALTER TABLE injects_expectations ADD inject_expiration_time bigint;");
select.execute(
"UPDATE injects_expectations SET inject_expiration_time = " + technicalMinutesExpirationTime + " "
+ "WHERE inject_expectation_type = 'DETECTION' OR inject_expectation_type = 'PREVENTION';");

select.execute(
"UPDATE injects_expectations SET inject_expiration_time = " + manualMinutesExpirationTime + " "
+ "WHERE inject_expectation_type = 'MANUAL' OR inject_expectation_type = 'CHALLENGE' "
+ "OR inject_expectation_type = 'ARTICLE' OR inject_expectation_type = 'DOCUMENT' OR inject_expectation_type = 'TEXT';");

select.execute(
"ALTER TABLE injects_expectations ALTER COLUMN inject_expiration_time SET NOT NULL;");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ export interface ExpectationInput {
expectation_description?: string;
expectation_score: number;
expectation_expectation_group: boolean;
expectation_expiration_time: number;
}

export interface ExpectationInputForm extends Omit<ExpectationInput, 'expectation_expiration_time'> {
expiration_time_days: number;
expiration_time_hours: number;
expiration_time_minutes: number;
}

export enum ExpectationType {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import React, { FunctionComponent, SyntheticEvent, useEffect } from 'react';
import { SubmitHandler, useForm } from 'react-hook-form';
import { Alert, Button, InputLabel, MenuItem, Select as MUISelect, TextField as MuiTextField, Typography } from '@mui/material';
import { Alert, Button, InputLabel, MenuItem, Select as MUISelect, TextField, TextField as MuiTextField, Typography } from '@mui/material';
import { makeStyles } from '@mui/styles';
import type { ExpectationInput } from './Expectation';
import { ExpectationInput, ExpectationInputForm } from './Expectation';
import { formProps, infoMessage } from './ExpectationFormUtils';
import { useFormatter } from '../../../../../components/i18n';
import type { Theme } from '../../../../../components/Theme';
import ExpectationGroupField from './field/ExpectationGroupField';
import { isTechnicalExpectation } from './ExpectationUtils';
import ScaleBar from '../../../../../components/scalebar/ScaleBar';
import { splitDuration } from '../../../../../utils/Time';

const useStyles = makeStyles((theme: Theme) => ({
marginTop_2: {
Expand All @@ -20,11 +21,26 @@ const useStyles = makeStyles((theme: Theme) => ({
gap: theme.spacing(2),
marginTop: theme.spacing(2),
},
duration: {
marginTop: 20,
width: '100%',
display: 'flex',
justifyContent: 'space-between',
border: `1px solid ${theme.palette.primary.main}`,
borderRadius: 4,
padding: 15,
},
trigger: {
fontFamily: 'Consolas, monaco, monospace',
fontSize: 12,
paddingTop: 15,
color: theme.palette.primary.main,
},
}));

interface Props {
predefinedExpectations: ExpectationInput[];
onSubmit: SubmitHandler<ExpectationInput>;
onSubmit: SubmitHandler<ExpectationInputForm>;
handleClose: () => void;
}

Expand All @@ -45,6 +61,7 @@ const ExpectationFormCreate: FunctionComponent<Props> = ({
expectation_description: predefinedExpectation.expectation_description ?? '',
expectation_score: predefinedExpectation.expectation_score > 0 ? predefinedExpectation.expectation_score : 100,
expectation_expectation_group: predefinedExpectation.expectation_expectation_group ?? false,
expectation_expiration_time: predefinedExpectation.expectation_expiration_time,
};
}
return {
Expand All @@ -53,11 +70,19 @@ const ExpectationFormCreate: FunctionComponent<Props> = ({
expectation_description: '',
expectation_score: 100,
expectation_expectation_group: false,
expectation_expiration_time: 3600,
};
};

const predefinedTypes = predefinedExpectations.map((e) => e.expectation_type);
const initialValues = computeValuesFromType(predefinedTypes[0]);
const valuesFromComputedTypes = computeValuesFromType(predefinedTypes[0]);
const expirationTime = splitDuration(valuesFromComputedTypes.expectation_expiration_time || 0);
const initialValues: ExpectationInputForm = {
...valuesFromComputedTypes,
expiration_time_days: parseInt(expirationTime.days, 10),
expiration_time_hours: parseInt(expirationTime.hours, 10),
expiration_time_minutes: parseInt(expirationTime.minutes, 10),
};

const {
register,
Expand All @@ -66,8 +91,8 @@ const ExpectationFormCreate: FunctionComponent<Props> = ({
watch,
reset,
getValues,
control,
} = useForm<ExpectationInput>(formProps(initialValues, t));
} = useForm<ExpectationInputForm>(formProps(initialValues, t));
const { control } = useForm<ExpectationInput>();
const watchType = watch('expectation_type');

const handleSubmitWithoutPropagation = (e: SyntheticEvent) => {
Expand Down Expand Up @@ -128,6 +153,32 @@ const ExpectationFormCreate: FunctionComponent<Props> = ({
}
inputProps={register('expectation_description')}
/>
<div className={classes.duration}>
<div className={classes.trigger}>
{t('Expiration time')}
</div>
<TextField
variant="standard"
type="number"
label={t('Days')}
style={{ width: '20%' }}
inputProps={register('expiration_time_days')}
/>
<TextField
variant="standard"
inputProps={register('expiration_time_hours')}
type="number"
label={t('Hours')}
style={{ width: '20%' }}
/>
<TextField
variant="standard"
inputProps={register('expiration_time_minutes')}
type="number"
label={t('Minutes')}
style={{ width: '20%' }}
/>
</div>
<div style={{ marginTop: 20 }}>
<Typography variant="h4">{t('Scores')}</Typography>
<ScaleBar expectationScore={watch('expectation_score')} />
Expand Down
Loading

0 comments on commit f65620b

Please sign in to comment.