Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[frontend/backend] add a start now for scenario (#1368) #1405

Merged
merged 11 commits into from
Sep 12, 2024
10 changes: 5 additions & 5 deletions .drone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ steps:
- name: frontend-tests
image: node:20-alpine
volumes:
- name: cache-node-frontend
path: /drone/src/openbas-front/node_modules
- name: cache-node-frontend
path: /drone/src/openbas-front/node_modules
commands:
- cd openbas-front
- yarn install
- yarn build
- yarn check-ts
- yarn lint
# - yarn i18n-checker
- yarn i18n-checker
- NODE_OPTIONS=--max_old_space_size=8192 yarn test

- name: app-e2e
Expand Down Expand Up @@ -66,8 +66,8 @@ steps:
- name: frontend-e2e-tests
image: node:20.16.0
volumes:
- name: cache-node-frontend-e2e
path: /drone/src/openbas-front/node_modules
- name: cache-node-frontend-e2e
path: /drone/src/openbas-front/node_modules
commands:
- apt update
- apt -y install netcat-traditional
Expand Down
476 changes: 243 additions & 233 deletions openbas-api/src/main/java/io/openbas/rest/scenario/ScenarioApi.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ private void createExercisesFromScenarios() {
validScenarios.stream()
.filter(scenario -> !alreadyExistIds.contains(scenario.getId()))
// Create simulation with start date provided by cron
.forEach(scenario -> this.scenarioToExerciseService.toExercise(scenario, cronToDate(scenario.getRecurrence())));
.forEach(scenario -> this.scenarioToExerciseService.toExercise(scenario, cronToDate(scenario.getRecurrence()),
false));
}

private void cleanOutdatedRecurringScenario() {
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import static io.openbas.utils.fixtures.InjectFixture.getInjectForEmailContract;
import static io.openbas.utils.fixtures.ObjectiveFixture.OBJECTIVE_NAME;
import static io.openbas.utils.fixtures.ObjectiveFixture.getObjective;
import static io.openbas.utils.fixtures.ScenarioFixture.getScenario;
import static io.openbas.utils.fixtures.TagFixture.getTag;
import static io.openbas.utils.fixtures.TeamFixture.getTeam;
import static io.openbas.utils.fixtures.UserFixture.getUser;
Expand Down Expand Up @@ -220,7 +219,7 @@ void scenarioToExerciseTest() {
VARIABLE_ID = variableSaved.getId();

// -- EXECUTE --
Exercise exercise = this.scenarioToExerciseService.toExercise(scenario, null);
Exercise exercise = this.scenarioToExerciseService.toExercise(scenario, null, false);
EXERCISE_ID = exercise.getId();
Exercise exerciseSaved = this.loadService.exercise(EXERCISE_ID);

Expand Down
16 changes: 11 additions & 5 deletions openbas-front/i18n-checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const checkLanguageSupport = (lang) => {
const match = (filePath) => {
try {
const data = fs.readFileSync(filePath, { encoding: 'utf8' });
const regexp = /t\('([\w\s]+)'\)/g;
const regexp = /(?<![a-zA-Z])t\('([\w\s]+)'\)/g;
const matches = [...data.matchAll(regexp)];
matches.forEach((m) => {
const regexWithQuote = `'${m[1]}':`;
Expand Down Expand Up @@ -57,16 +57,22 @@ const checkLanguageSupport = (lang) => {

const run = () => {
const languages = ['fr', 'zh'];
const _missingKeys = {};
const missingKeys = {};

languages.forEach((lang) => {
const keys = checkLanguageSupport(lang);
if (keys.length > 0) {
_missingKeys[lang] = keys;
missingKeys[lang] = keys;
}
});

return _missingKeys;
if (Object.keys(missingKeys).length) {
// eslint-disable-next-line no-console
console.error('Missing keys :', missingKeys);
process.exit(1);
} else {
process.exit(0);
}
};

const _missingKeys = run();
run();
5 changes: 0 additions & 5 deletions openbas-front/src/actions/Inject.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@ export const fetchInject = (injectId) => (dispatch) => {
return getReferential(schema.inject, uri)(dispatch);
};

export const tryInject = (injectId) => (dispatch) => {
const uri = `/api/injects/try/${injectId}`;
return getReferential(null, uri, null)(dispatch);
};

// -- EXERCISES --

export const fetchExerciseInjects = (exerciseId) => (dispatch) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const fetchInjectResultDto = (injectId: string) => {

export const deleteAtomicTesting = (injectId: string) => {
const uri = `${ATOMIC_TESTING_URI}/${injectId}`;
return simpleDelCall(uri, injectId);
return simpleDelCall(uri);
};

export const updateAtomicTesting = (injectId: string, data: AtomicTestingInput) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ export const fetchInjectTestStatus = (testId: string | undefined) => {

export const deleteInjectTest = (testId: string | undefined) => {
const uri = `/api/injects/test/${testId}`;
return simpleDelCall(uri, testId);
return simpleDelCall(uri);
};
6 changes: 5 additions & 1 deletion openbas-front/src/actions/injects/inject-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Dispatch } from 'redux';
import { getReferential, simpleCall, simplePostCall } from '../../utils/Action';
import type { Exercise, Scenario, SearchPaginationInput } from '../../utils/api-types';
import * as schema from '../Schema';
import { MESSAGING$ } from '../../utils/Environment';

export const testInject = (injectId: string) => {
const uri = `/api/injects/${injectId}/test`;
Expand All @@ -11,7 +12,10 @@ export const testInject = (injectId: string) => {
export const bulkTestInjects = (injectIds: string[]) => {
const data = injectIds;
const uri = '/api/injects/bulk/test';
return simplePostCall(uri, data, "Can't be tested");
return simplePostCall(uri, data, false).catch((error) => {
MESSAGING$.notifyError('Can\'t be tested');
throw error;
});
};

// -- EXERCISES --
Expand Down
2 changes: 1 addition & 1 deletion openbas-front/src/actions/mapper/mapper-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const fetchMapper = (mapperId: string) => {

export const deleteMapper = (mapperId: RawPaginationImportMapper['import_mapper_id']) => {
const uri = `${XLS_MAPPER_URI}/${mapperId}`;
return simpleDelCall(uri, mapperId);
return simpleDelCall(uri);
};

export const createMapper = (data: ImportMapperAddInput) => {
Expand Down
7 changes: 7 additions & 0 deletions openbas-front/src/actions/scenarios/scenario-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ export const duplicateScenario = (scenarioId: string) => (dispatch: Dispatch) =>
return postReferential(scenario, uri, null)(dispatch);
};

// -- SCENARIO TO EXERCISE

export const createRunningExerciseFromScenario = (scenarioId: string) => {
const uri = `${SCENARIO_URI}/${scenarioId}/exercise/running`;
return simplePostCall(uri);
};

// -- TEAMS --

export const fetchScenarioTeams = (scenarioId: Scenario['scenario_id']) => (dispatch: Dispatch) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, { FunctionComponent, useContext, useState } from 'react';
import { Link } from 'react-router-dom';
import { Alert, Button, Dialog, DialogActions, DialogContent, DialogContentText, IconButton, Menu, MenuItem, Table, TableBody, TableCell, TableRow } from '@mui/material';
import { Button, Dialog, DialogActions, DialogContent, DialogContentText, IconButton, Menu, MenuItem, Table, TableBody, TableCell, TableRow } from '@mui/material';
import { MoreVert } from '@mui/icons-material';
import { useFormatter } from '../../../../components/i18n';
import Transition from '../../../../components/common/Transition';
import { InjectContext, PermissionsContext } from '../Context';
import type { Inject, InjectStatus, InjectStatusExecution, InjectTestStatus } from '../../../../utils/api-types';
import { duplicateInjectForExercise, duplicateInjectForScenario, tryInject } from '../../../../actions/Inject';
import { duplicateInjectForExercise, duplicateInjectForScenario } from '../../../../actions/Inject';
import { testInject } from '../../../../actions/injects/inject-action';
import { useAppDispatch } from '../../../../utils/hooks';
import DialogDuplicate from '../../../../components/common/DialogDuplicate';
Expand Down Expand Up @@ -62,7 +62,6 @@ const InjectPopover: FunctionComponent<Props> = ({

const [openDelete, setOpenDelete] = useState(false);
const [duplicate, setDuplicate] = useState(false);
const [openTry, setOpenTry] = useState(false);
const [openTest, setOpenTest] = useState(false);
const [openEnable, setOpenEnable] = useState(false);
const [openDisable, setOpenDisable] = useState(false);
Expand Down Expand Up @@ -114,22 +113,11 @@ const InjectPopover: FunctionComponent<Props> = ({
});
};

const handleCloseTry = () => setOpenTry(false);

const handleCloseResult = () => {
setOpenResult(false);
setInjectResult(null);
};

const submitTry = () => {
// FIXME: remove try possibility
dispatch(tryInject(inject.inject_id)).then((payload: InjectStatus) => {
setInjectResult(payload);
setOpenResult(true);
});
handleCloseTry();
};

const handleOpenTest = () => {
setOpenTest(true);
handlePopoverClose();
Expand Down Expand Up @@ -254,15 +242,6 @@ const InjectPopover: FunctionComponent<Props> = ({
{t('Trigger now')}
</MenuItem>
)}
{/* TODO create an atomic testing when using this button */}
{/* {inject.inject_type !== 'openbas_manual' && ( */}
{/* <MenuItem */}
{/* onClick={handleOpenTry} */}
{/* disabled={isDisabled} */}
{/* > */}
{/* {t('Try the inject')} */}
{/* </MenuItem> */}
{/* )} */}
{inject.inject_enabled ? (
<MenuItem
onClick={handleOpenDisable}
Expand Down Expand Up @@ -328,29 +307,6 @@ const InjectPopover: FunctionComponent<Props> = ({
</Button>
</DialogActions>
</Dialog>
<Dialog
TransitionComponent={Transition}
open={openTry}
onClose={handleCloseTry}
PaperProps={{ elevation: 1 }}
>
<DialogContent>
<DialogContentText>
<p>{t(`Do you want to try this inject: ${inject.inject_title}?`)}</p>
<Alert severity="info">
{t('The inject will only be sent to you.')}
</Alert>
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleCloseTry}>
{t('Cancel')}
</Button>
<Button color="secondary" onClick={submitTry}>
{t('Try')}
</Button>
</DialogActions>
</Dialog>
<DialogTest
open={openTest}
handleClose={handleCloseTest}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const IndexScenarioComponent: FunctionComponent<{ scenario: ScenarioStore }> = (
tabValue = `/admin/scenarios/${scenario.scenario_id}/tests`;
}
const [openScenarioRecurringFormDialog, setOpenScenarioRecurringFormDialog] = useState<boolean>(false);
const [openInstantiateSimulationAndStart, setOpenInstantiateSimulationAndStart] = useState<boolean>(false);
const [selectRecurring, setSelectRecurring] = useState('noRepeat');
const [cronExpression, setCronExpression] = useState<string | null>(scenario.scenario_recurrence || null);
const [parsedCronExpression, setParsedCronExpression] = useState<ParsedCron | null>(scenario.scenario_recurrence ? parseCron(scenario.scenario_recurrence) : null);
Expand All @@ -74,7 +75,7 @@ const IndexScenarioComponent: FunctionComponent<{ scenario: ScenarioStore }> = (
if (!cronExpression || !parsedCronExpression) {
return null;
}
let sentence = '';
let sentence: string;
if (noRepeat) {
sentence = `${fld(scenario.scenario_recurrence_start)} ${t('recurrence_at')} ${ft(new Date().setUTCHours(parsedCronExpression.h, parsedCronExpression.m, 0))}`;
} else {
Expand Down Expand Up @@ -110,6 +111,8 @@ const IndexScenarioComponent: FunctionComponent<{ scenario: ScenarioStore }> = (
selectRecurring={selectRecurring}
setOpenScenarioRecurringFormDialog={setOpenScenarioRecurringFormDialog}
openScenarioRecurringFormDialog={openScenarioRecurringFormDialog}
setOpenInstantiateSimulationAndStart={setOpenInstantiateSimulationAndStart}
openInstantiateSimulationAndStart={openInstantiateSimulationAndStart}
noRepeat={noRepeat}
/>
<Box
Expand Down Expand Up @@ -175,7 +178,7 @@ const IndexScenarioComponent: FunctionComponent<{ scenario: ScenarioStore }> = (
</Box>
<Suspense fallback={<Loader />}>
<Routes>
<Route path="" element={errorWrapper(Scenario)({ setOpenScenarioRecurringFormDialog })} />
<Route path="" element={errorWrapper(Scenario)({ setOpenInstantiateSimulationAndStart })} />
<Route path="definition" element={errorWrapper(ScenarioDefinition)()} />
<Route path="injects" element={errorWrapper(Injects)()} />
<Route path="tests/:statusId?" element={errorWrapper(Tests)()} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const useStyles = makeStyles(() => ({
},
}));

const Scenario = ({ setOpenScenarioRecurringFormDialog }: { setOpenScenarioRecurringFormDialog: React.Dispatch<React.SetStateAction<boolean>> }) => {
const Scenario = ({ setOpenInstantiateSimulationAndStart }: { setOpenInstantiateSimulationAndStart: React.Dispatch<React.SetStateAction<boolean>> }) => {
// Standard hooks
const classes = useStyles();
const theme = useTheme<Theme>();
Expand Down Expand Up @@ -245,9 +245,9 @@ const Scenario = ({ setOpenScenarioRecurringFormDialog }: { setOpenScenarioRecur
variant="contained"
color="primary"
size="large"
onClick={() => setOpenScenarioRecurringFormDialog(true)}
onClick={() => setOpenInstantiateSimulationAndStart(true)}
>
{t('Simulate Now')}
{t('Launch simulation now')}
</Button>
</div>
)}
Expand Down
Loading