diff --git a/openbas-front/src/actions/Schema.js b/openbas-front/src/actions/Schema.js index fc0b5aa5eb8..0b97c1f865e 100644 --- a/openbas-front/src/actions/Schema.js +++ b/openbas-front/src/actions/Schema.js @@ -1,5 +1,5 @@ +import { fromJS, List, Map } from 'immutable'; import { schema } from 'normalizr'; -import * as R from 'ramda'; import locale from '../utils/BrowserLanguage.js'; @@ -261,40 +261,18 @@ user.define({ user_organization: organization }); const maps = (key, state) => state.referential.getIn(['entities', key]); const entities = (key, state) => maps(key, state).valueSeq(); const entity = (id, key, state) => state.referential.getIn(['entities', key, id]); -const me = (state) => { - return state.referential.getIn(['entities', 'users', state.app.getIn(['logged', 'user'])]); -}; - -const getInjectWithParsedInjectorContractContent = (i) => { - if (!i) { - return i; - } - return ({ - ...i, - inject_injector_contract: { - ...i.inject_injector_contract, - injector_contract_content_parsed: i.inject_injector_contract?.injector_contract_content - ? JSON.parse(i.inject_injector_contract.injector_contract_content) - : null, - }, - }); -}; -const getInjectsWithParsedInjectorContractContent = (injects) => { - if (R.isEmpty(injects)) { - return injects; - } - return injects.map(getInjectWithParsedInjectorContractContent); -}; +const me = state => state.referential.getIn(['entities', 'users', state.app.getIn(['logged', 'user'])]); export const storeHelper = state => ({ logged: () => state.app.get('logged'), getMe: () => me(state), + getMeAdmin: () => me(state)?.get('user_admin') ?? false, getMeTokens: () => entities('tokens', state).filter( - t => t.token_user === me(state)?.user_id, + t => t.get('token_user') === me(state)?.get('user_id'), ), getUserLang: () => { const rawPlatformLang = state.referential.getIn(['entities', 'platformParameters', 'parameters', 'platform_lang']) ?? 'auto'; - const rawUserLang = me(state)?.user_lang ?? 'auto'; + const rawUserLang = me(state)?.get('user_lang') ?? 'auto'; const platformLang = rawPlatformLang !== 'auto' ? rawPlatformLang : locale; const userLang = rawUserLang !== 'auto' ? rawUserLang : platformLang; return userLang; @@ -304,37 +282,38 @@ export const storeHelper = state => ({ getExercises: () => entities('exercises', state), getExercisesMap: () => maps('exercises', state), getExercise: id => entity(id, 'exercises', state), - getExerciseComchecks: id => entities('comchecks', state).filter(i => i.comcheck_exercise === id), - getExerciseTeams: id => entities('teams', state).filter(i => i.team_exercises?.includes(id)), - getExerciseVariables: id => entities('variables', state).filter(i => i.variable_exercise === id), - getExerciseArticles: id => entities('articles', state).filter(i => i.article_exercise === id), - getExerciseInjects: id => getInjectsWithParsedInjectorContractContent(entities('injects', state).filter(i => i.inject_exercise === id)), + getExerciseComchecks: id => entities('comchecks', state).filter(i => i.get('comcheck_exercise') === id), + getExerciseTeams: id => entities('teams', state).filter(i => i.get('team_exercises')?.includes(id)), + getExerciseVariables: id => entities('variables', state).filter(i => i.get('variable_exercise') === id), + getExerciseArticles: id => entities('articles', state).filter(i => i.get('article_exercise') === id), + getExerciseInjects: id => entities('injects', state).filter(i => i.get('inject_exercise') === id), getExerciseCommunications: id => entities('communications', state).filter( - i => i.communication_exercise === id, + i => i.get('communication_exercise') === id, ), - getExerciseObjectives: id => entities('objectives', state).filter(o => o.objective_exercise === id), - getExerciseLogs: id => entities('logs', state).filter(l => l.log_exercise === id), + getExerciseObjectives: id => entities('objectives', state).filter(o => o.get('objective_exercise') === id), + getExerciseLogs: id => entities('logs', state).filter(l => l.get('log_exercise') === id), getExerciseLessonsCategories: id => entities('lessonscategorys', state).filter( - l => l.lessons_category_exercise === id, + l => l.get('lessons_category_exercise') === id, ), getExerciseLessonsQuestions: id => entities('lessonsquestions', state).filter( - l => l.lessons_question_exercise === id, + l => l.get('lessons_question_exercise') === id, ), getExerciseLessonsAnswers: exerciseId => entities('lessonsanswers', state).filter( - l => l.lessons_answer_exercise === exerciseId, + l => l.get('lessons_answer_exercise') === exerciseId, ), getExerciseUserLessonsAnswers: (exerciseId, userId) => entities('lessonsanswers', state).filter( - l => l.lessons_answer_exercise === exerciseId - && l.lessons_answer_user === userId, + l => l.get('lessons_answer_exercise') === exerciseId + && l.get('lessons_answer_user') === userId, ), - getExerciseReports: exerciseId => entities('reports', state).filter(l => l.report_exercise === exerciseId), + isExercise: id => !maps('exercises', state)?.get(id)?.isEmpty(), + getExerciseReports: exerciseId => entities('reports', state).filter(l => l.get('report_exercise') === exerciseId), // report getReport: id => entity(id, 'reports', state), // comcheck getComcheck: id => entity(id, 'comchecks', state), getComcheckStatus: id => entity(id, 'comcheckstatuses', state), getComcheckStatuses: id => entities('comcheckstatuses', state).filter( - i => i.comcheckstatus_comcheck === id, + i => i.get('comcheckstatus_comcheck') === id, ), getChannelReader: id => entity(id, 'channelreaders', state), getChallengesReader: id => entity(id, 'challengesreaders', state), @@ -346,35 +325,25 @@ export const storeHelper = state => ({ getOrganizationsMap: () => maps('organizations', state), // objectives getObjective: id => entity(id, 'objectives', state), - getObjectiveEvaluations: id => entities('evaluations', state).filter(e => e.evaluation_objective === id), + getObjectiveEvaluations: id => entities('evaluations', state).filter(e => e.get('evaluation_objective') === id), // tags getTag: id => entity(id, 'tags', state), getTags: () => entities('tags', state), getTagsMap: () => maps('tags', state), // injects - getInject: id => getInjectWithParsedInjectorContractContent(entity(id, 'injects', state)), + getInject: id => entity(id, 'injects', state), getAtomicTesting: id => entity(id, 'atomics', state), getAtomicTestingDetail: id => entity(id, 'atomicdetails', state), getAtomicTestings: () => entities('atomics', state), - getTargetResults: (id, injectId) => entities('targetresults', state).filter(r => (r.target_id === id) && (r.target_inject_id === injectId)), - getInjectsMap: () => getInjectsWithParsedInjectorContractContent(entities('injects', state)).reduce((map, i) => { - map[i.inject_id] = i; - return map; - }, {}), - getNextInjects: () => { - const sortFn = (a, b) => new Date(a.inject_date).getTime() - new Date(b.inject_date).getTime(); - const injects = entities('injects', state).filter( - i => i.inject_date !== null && i.inject_status === null, - ); - return R.take(6, R.sort(sortFn, injects)); - }, + getTargetResults: (id, injectId) => entities('targetresults', state).filter(r => (r.get('target_id') === id) && (r.get('target_inject_id') === injectId)), + getInjectsMap: () => maps('injects', state), getInjectCommunications: id => entities('communications', state).filter( - i => i.communication_inject === id, + i => i.get('communication_inject') === id, ), // injectexpectation getInjectExpectations: () => entities('injectexpectations', state), getExerciseInjectExpectations: id => entities('injectexpectations', state).filter( - i => i.inject_expectation_exercise === id, + i => i.get('inject_expectation_exercise') === id, ), getInjectExpectationsMap: () => maps('injectexpectations', state), // documents @@ -382,16 +351,20 @@ export const storeHelper = state => ({ getDocumentsMap: () => maps('documents', state), // teams getTeam: id => entity(id, 'teams', state), - getTeamUsers: id => entities('users', state).filter(u => (entity(id, 'teams', state) || {}).team_users?.includes( - u.user_id, - )), - getTeamExerciseInjects: id => entities('injects', state).filter(i => (entity(id, 'teams', state) || {}).team_exercise_injects?.includes( - i.inject_id, - )), + getTeamUsers: (id) => { + const team = entity(id, 'teams', state); + if (!team) return List([]); + return team.get('team_users').map(tu => entity(tu, 'users', state)); + }, + getTeamExerciseInjects: (id) => { + const team = entity(id, 'teams', state); + if (!team) return List([]); + return team.get('team_exercise_injects').map(te => entity(te, 'injects', state)); + }, getTeams: () => entities('teams', state), getTeamsMap: () => maps('teams', state), getPlatformSettings: () => { - return state.referential.getIn(['entities', 'platformParameters', 'parameters']) || {}; + return state.referential.getIn(['entities', 'platformParameters', 'parameters']) || Map({}); }, getPlatformName: () => { return state.referential.getIn(['entities', 'platformParameters', 'parameters', 'platform_name']) || 'OpenBAS - Breach and Attack Simulation Platform'; @@ -415,13 +388,10 @@ export const storeHelper = state => ({ // injector contracts getInjectorContract: (id) => { const i = entity(id, 'injector_contracts', state); - if (!i) { + if (i.isEmpty()) { return i; } - return ({ - ...i, - ...JSON.parse(i.injector_contract_content), - }); + return i.merge(fromJS(JSON.parse(i.get('injector_contract_content')))); }, getInjectorContracts: () => entities('injector_contracts', state), // collectors @@ -446,19 +416,19 @@ export const storeHelper = state => ({ getArticlesMap: () => maps('articles', state), // challenges getChallenges: () => entities('challenges', state), - getExerciseChallenges: id => entities('challenges', state).filter(c => c.challenge_exercises.includes(id)), + getExerciseChallenges: id => entities('challenges', state).filter(c => c.get('challenge_exercises').includes(id)), getChallengesMap: () => maps('challenges', state), // lessons templates getLessonsTemplate: id => entity(id, 'lessonstemplates', state), getLessonsTemplates: () => entities('lessonstemplates', state), getLessonsTemplatesMap: () => maps('lessonstemplates', state), getLessonsTemplateCategories: id => entities('lessonstemplatecategorys', state).filter( - c => c.lessons_template_category_template === id, + c => c.get('lessons_template_category_template') === id, ), getLessonsTemplateQuestions: () => entities('lessonstemplatequestions', state), getLessonsTemplateQuestionsMap: () => maps('lessonstemplatequestions', state), getLessonsTemplateCategoryQuestions: id => entities('lessonstemplatequestions', state).filter( - c => c.lessons_template_question_category === id, + c => c.get('lessons_template_question_category') === id, ), // assets getEndpoint: id => entity(id, 'endpoints', state), @@ -476,19 +446,21 @@ export const storeHelper = state => ({ getScenarios: () => entities('scenarios', state), getScenariosMap: () => maps('scenarios', state), getScenario: id => entity(id, 'scenarios', state), - getScenarioTeams: id => entities('teams', state).filter(i => i.team_scenarios.includes(id)), - getScenarioVariables: id => entities('variables', state).filter(i => i.variable_scenario === id), - getScenarioArticles: id => entities('articles', state).filter(i => i.article_scenario === id), - getScenarioChallenges: id => entities('challenges', state).filter(c => c.challenge_scenarios.includes(id)), - getScenarioInjects: id => getInjectsWithParsedInjectorContractContent(entities('injects', state).filter(i => i.inject_scenario === id)), - getTeamScenarioInjects: id => entities('injects', state).filter(i => (entity(id, 'teams', state) || {}).team_scenario_injects?.includes( - i.inject_id, - )), - getScenarioObjectives: id => entities('objectives', state).filter(o => o.objective_scenario === id), + getScenarioTeams: id => entities('teams', state).filter(i => i.get('team_scenarios').includes(id)), + getScenarioVariables: id => entities('variables', state).filter(i => i.get('variable_scenario') === id), + getScenarioArticles: id => entities('articles', state).filter(i => i.get('article_scenario') === id), + getScenarioChallenges: id => entities('challenges', state).filter(c => c.get('challenge_scenarios').includes(id)), + getScenarioInjects: id => entities('injects', state).filter(i => i.get('inject_scenario') === id), + getTeamScenarioInjects: (id) => { + const team = entity(id, 'teams', state); + if (!team) return List([]); + return team.get('team_scenario_injects').map(te => entity(te, 'injects', state)); + }, + getScenarioObjectives: id => entities('objectives', state).filter(o => o.get('objective_scenario') === id), getScenarioLessonsCategories: id => entities('lessonscategorys', state).filter( - l => l.lessons_category_scenario === id, + l => l.get('lessons_category_scenario') === id, ), getScenarioLessonsQuestions: id => entities('lessonsquestions', state).filter( - l => l.lessons_question_scenario === id, + l => l.get('lessons_question_scenario') === id, ), }); diff --git a/openbas-front/src/actions/exercises/exercise-helper.d.ts b/openbas-front/src/actions/exercises/exercise-helper.d.ts index 7747d05309c..8d9aeed5525 100644 --- a/openbas-front/src/actions/exercises/exercise-helper.d.ts +++ b/openbas-front/src/actions/exercises/exercise-helper.d.ts @@ -1,6 +1,7 @@ import { type Exercise, type ExerciseSimple, type InjectExpectation, type LessonsAnswer, type LessonsCategory, type LessonsQuestion, type Objective, type Team } from '../../utils/api-types'; export interface ExercisesHelper { + isExercise: (exerciseId: string) => boolean; getExercise: (exerciseId: string) => Exercise; getExercises: () => ExerciseSimple[]; getExercisesMap: () => Record; diff --git a/openbas-front/src/actions/helper.d.ts b/openbas-front/src/actions/helper.d.ts index 1e9dadb60d2..2f26012b940 100644 --- a/openbas-front/src/actions/helper.d.ts +++ b/openbas-front/src/actions/helper.d.ts @@ -2,6 +2,7 @@ import { type Challenge, type Document, type Exercise, type Organization, type P export interface UserHelper { getMe: () => User; + getMeAdmin: () => boolean; getUsersMap: () => Record; } diff --git a/openbas-front/src/actions/injector_contracts/InjectorContract.d.ts b/openbas-front/src/actions/injector_contracts/InjectorContract.d.ts index 836320387dc..0b7d7d5370b 100644 --- a/openbas-front/src/actions/injector_contracts/InjectorContract.d.ts +++ b/openbas-front/src/actions/injector_contracts/InjectorContract.d.ts @@ -38,7 +38,13 @@ export type InjectorContractConverted = Omit; + }; + label: Record; }; }; diff --git a/openbas-front/src/actions/injects/Inject.d.ts b/openbas-front/src/actions/injects/Inject.d.ts index 68aa3e6da26..e900db6f053 100644 --- a/openbas-front/src/actions/injects/Inject.d.ts +++ b/openbas-front/src/actions/injects/Inject.d.ts @@ -1,34 +1,15 @@ import { type Inject, type InjectOutput } from '../../utils/api-types'; +import { type InjectorContractConverted } from '../injector_contracts/InjectorContract'; export type InjectStore = Omit & { - inject_content: { + inject_content?: { expectationScore: number; challenges: string[] | undefined; }; - inject_injector_contract: { - // as we don't know the type of the content of a contract we need to put any here - // eslint-disable-next-line @typescript-eslint/no-explicit-any - injector_contract_content_parsed: any; - convertedContent: { - label: Record; - config: { expose: boolean }; - }; - } & Inject['inject_injector_contract']; + inject_injector_contract: Omit & { convertedContent: InjectorContractConverted['convertedContent'] }; }; -export type InjectorContractConvertedContent = { - label: Record; - config: { expose: boolean }; -}; - -export type InjectOutputType = InjectOutput & { - inject_injector_contract: { - // as we don't know the type of the content of a contract we need to put any here - // eslint-disable-next-line @typescript-eslint/no-explicit-any - injector_contract_content_parsed: any; - convertedContent: InjectorContractConvertedContent; - } & Inject['inject_injector_contract']; -}; +export type InjectOutputType = InjectOutput & { inject_injector_contract: { convertedContent: InjectorContractConverted['convertedContent'] } & Inject['inject_injector_contract'] }; export interface ConditionElement { name: string; diff --git a/openbas-front/src/admin/components/agents/ExecutorDocumentationLink.tsx b/openbas-front/src/admin/components/agents/ExecutorDocumentationLink.tsx index f4b5e7d5891..06e65f66cdb 100644 --- a/openbas-front/src/admin/components/agents/ExecutorDocumentationLink.tsx +++ b/openbas-front/src/admin/components/agents/ExecutorDocumentationLink.tsx @@ -18,7 +18,7 @@ const ExecutorDocumentationLink: FunctionComponent = ({ executor }) => { {t('To install the agent please follow the ')} - {`${executor.executor_name} ${t('documentation')}`} + {t('{executor_name} documentation', { executor_name: executor.executor_name })} . diff --git a/openbas-front/src/admin/components/agents/InstructionSelector.tsx b/openbas-front/src/admin/components/agents/InstructionSelector.tsx index 83853d4f288..f3a12c67ceb 100644 --- a/openbas-front/src/admin/components/agents/InstructionSelector.tsx +++ b/openbas-front/src/admin/components/agents/InstructionSelector.tsx @@ -341,7 +341,7 @@ SHA512: ca07dc1d0a5297e29327e483f4f35dadb254d96a16a5c33da5ad048e6965a3863d621518 > {`${t('The agent runs in the background as a session and only executes when the user is logged in and active.')} ${t('For further details, refer to the')} `} - {`${selectedExecutor?.executor_name} ${t('documentation.')}`} + {t('{executor_name} documentation.', { executor_name: selectedExecutor?.executor_name })}

@@ -362,7 +362,7 @@ SHA512: ca07dc1d0a5297e29327e483f4f35dadb254d96a16a5c33da5ad048e6965a3863d621518 > {`${t('The agent runs in the background as a service and starts automatically when the machine powers on.')} ${t('For further details, refer to the')} `} - {`${selectedExecutor?.executor_name} ${t('documentation.')}`} + {t('{executor_name} documentation.', { executor_name: selectedExecutor?.executor_name })}

diff --git a/openbas-front/src/admin/components/assets/asset_groups/AssetGroupManagement.tsx b/openbas-front/src/admin/components/assets/asset_groups/AssetGroupManagement.tsx index 3e738ad2488..2b579764760 100644 --- a/openbas-front/src/admin/components/assets/asset_groups/AssetGroupManagement.tsx +++ b/openbas-front/src/admin/components/assets/asset_groups/AssetGroupManagement.tsx @@ -68,7 +68,7 @@ const AssetGroupManagement: FunctionComponent = ({ // Fetching data const { assetGroup, userAdmin } = useHelper((helper: AssetGroupsHelper & UserHelper) => ({ assetGroup: helper.getAssetGroup(assetGroupId), - userAdmin: helper.getMe()?.user_admin ?? false, + userAdmin: helper.getMeAdmin(), })); useDataLoader(() => { dispatch(fetchAssetGroup(assetGroupId)); diff --git a/openbas-front/src/admin/components/assets/asset_groups/AssetGroups.tsx b/openbas-front/src/admin/components/assets/asset_groups/AssetGroups.tsx index f6a62881117..9ed02a497cf 100644 --- a/openbas-front/src/admin/components/assets/asset_groups/AssetGroups.tsx +++ b/openbas-front/src/admin/components/assets/asset_groups/AssetGroups.tsx @@ -128,7 +128,7 @@ const AssetGroups = () => { const [searchId] = searchParams.getAll('id'); // Fetching data - const { userAdmin } = useHelper((helper: EndpointHelper & UserHelper & TagHelper) => ({ userAdmin: helper.getMe()?.user_admin ?? false })); + const { userAdmin } = useHelper((helper: EndpointHelper & UserHelper & TagHelper) => ({ userAdmin: helper.getMeAdmin() })); // Headers const headers: Header[] = useMemo(() => [ diff --git a/openbas-front/src/admin/components/assets/endpoints/Endpoints.tsx b/openbas-front/src/admin/components/assets/endpoints/Endpoints.tsx index b02de15e4f5..7300c4a2eb7 100644 --- a/openbas-front/src/admin/components/assets/endpoints/Endpoints.tsx +++ b/openbas-front/src/admin/components/assets/endpoints/Endpoints.tsx @@ -30,7 +30,10 @@ import AssetStatus from '../AssetStatus'; import AgentPrivilege from './AgentPrivilege'; import EndpointPopover from './EndpointPopover'; -const useStyles = makeStyles()(() => ({ itemHead: { textTransform: 'uppercase' } })); +const useStyles = makeStyles()(() => ({ + itemHead: { textTransform: 'uppercase' }, + item: { height: 50 }, +})); const inlineStyles: Record = { asset_name: { width: '25%' }, @@ -65,7 +68,7 @@ const Endpoints = () => { // Fetching data const { userAdmin, executorsMap } = useHelper((helper: ExecutorHelper & UserHelper) => ({ - userAdmin: helper.getMe()?.user_admin ?? false, + userAdmin: helper.getMeAdmin(), executorsMap: helper.getExecutorsMap(), })); useDataLoader(() => { @@ -338,6 +341,7 @@ const Endpoints = () => { diff --git a/openbas-front/src/admin/components/assets/endpoints/endpoint/EndpointHeader.tsx b/openbas-front/src/admin/components/assets/endpoints/endpoint/EndpointHeader.tsx index 8f91cccee8c..81dda11977b 100644 --- a/openbas-front/src/admin/components/assets/endpoints/endpoint/EndpointHeader.tsx +++ b/openbas-front/src/admin/components/assets/endpoints/endpoint/EndpointHeader.tsx @@ -25,7 +25,7 @@ const EndpointHeader = () => { // Fetching data const { userAdmin, endpoint } = useHelper((helper: EndpointHelper & UserHelper) => ({ - userAdmin: helper.getMe()?.user_admin ?? false, + userAdmin: helper.getMeAdmin(), endpoint: helper.getEndpoint(endpointId), })); diff --git a/openbas-front/src/admin/components/assets/security_platforms/SecurityPlatforms.tsx b/openbas-front/src/admin/components/assets/security_platforms/SecurityPlatforms.tsx index d79b94754ce..ea219490998 100644 --- a/openbas-front/src/admin/components/assets/security_platforms/SecurityPlatforms.tsx +++ b/openbas-front/src/admin/components/assets/security_platforms/SecurityPlatforms.tsx @@ -58,7 +58,7 @@ const SecurityPlatforms = () => { const [searchId] = searchParams.getAll('id'); // Fetching data - const { userAdmin } = useHelper((helper: UserHelper) => ({ userAdmin: helper.getMe()?.user_admin ?? false })); + const { userAdmin } = useHelper((helper: UserHelper) => ({ userAdmin: helper.getMeAdmin() })); // Headers const headers = [ diff --git a/openbas-front/src/admin/components/atomic_testings/AtomicTestings.tsx b/openbas-front/src/admin/components/atomic_testings/AtomicTestings.tsx index fcc38441219..aa914d97b2f 100644 --- a/openbas-front/src/admin/components/atomic_testings/AtomicTestings.tsx +++ b/openbas-front/src/admin/components/atomic_testings/AtomicTestings.tsx @@ -24,7 +24,7 @@ const AtomicTestings = () => { const navigate = useNavigate(); const [openCreateDrawer, setOpenCreateDrawer] = useState(false); - const { userAdmin } = useHelper((helper: UserHelper) => ({ userAdmin: helper.getMe()?.user_admin ?? false })); + const { userAdmin } = useHelper((helper: UserHelper) => ({ userAdmin: helper.getMeAdmin() })); const onCreateAtomicTesting = async (data: AtomicTestingInput) => { const toCreate = R.pipe( diff --git a/openbas-front/src/admin/components/common/ToolBar.js b/openbas-front/src/admin/components/common/ToolBar.js index 659032e80ec..3d467737c45 100644 --- a/openbas-front/src/admin/components/common/ToolBar.js +++ b/openbas-front/src/admin/components/common/ToolBar.js @@ -815,13 +815,13 @@ ToolBar.propTypes = { const select = (state, ownProps) => { const helper = storeHelper(state); - const endpoints = helper.getEndpoints() + const endpoints = helper.getEndpoints().toJS() .map(n => ({ label: n.asset_name, value: n.asset_id, })) .sort((a, b) => a.label.localeCompare(b.label)); - const assetGroups = helper.getAssetGroups() + const assetGroups = helper.getAssetGroups().toJS() .map(n => ({ label: n.asset_group_name, value: n.asset_group_id, diff --git a/openbas-front/src/admin/components/common/entreprise_edition/EETooltip.tsx b/openbas-front/src/admin/components/common/entreprise_edition/EETooltip.tsx index 7cbed19ab49..3dd25221c54 100644 --- a/openbas-front/src/admin/components/common/entreprise_edition/EETooltip.tsx +++ b/openbas-front/src/admin/components/common/entreprise_edition/EETooltip.tsx @@ -21,10 +21,7 @@ const EETooltip = ({ const [feedbackCreation, setFeedbackCreation] = useState(false); const [openEnableAI, setOpenEnableAI] = useState(false); const [openConfigAI, setOpenConfigAI] = useState(false); - const userAdmin = useHelper((helper: UserHelper) => { - const me = helper.getMe(); - return me?.user_admin ?? false; - }); + const { userAdmin } = useHelper((helper: UserHelper) => ({ userAdmin: helper.getMeAdmin() })); const isEnterpriseEdition = useEnterpriseEdition(); const { enabled, configured } = useAI(); if (isEnterpriseEdition && (!forAi || (forAi && enabled && configured))) { diff --git a/openbas-front/src/admin/components/common/entreprise_edition/EnterpriseEditionButton.tsx b/openbas-front/src/admin/components/common/entreprise_edition/EnterpriseEditionButton.tsx index 06a3d72b8bb..ae489ba6e59 100644 --- a/openbas-front/src/admin/components/common/entreprise_edition/EnterpriseEditionButton.tsx +++ b/openbas-front/src/admin/components/common/entreprise_edition/EnterpriseEditionButton.tsx @@ -30,10 +30,7 @@ interface Props { const EnterpriseEditionButton = ({ style = {}, classes }: Props) => { const { t } = useFormatter(); const [openEnterpriseEditionConsent, setOpenEnterpriseEditionConsent] = useState(false); - const userAdmin = useHelper((helper: UserHelper) => { - const me = helper.getMe(); - return me?.user_admin ?? false; - }); + const { userAdmin } = useHelper((helper: UserHelper) => ({ userAdmin: helper.getMeAdmin() })); return ( <> ({ const TagsFilter = (props) => { const { classes } = useStyles(); const { t } = useFormatter(); - const tags = useHelper(helper => helper.getTags()); + const { tags } = useHelper(helper => ({ tags: helper.getTags() })); const { onAddTag, onClearTag, onRemoveTag, currentTags, fullWidth } = props; const tagTransform = n => ({ id: n.tag_id, diff --git a/openbas-front/src/admin/components/common/injects/InjectDistributionByType.tsx b/openbas-front/src/admin/components/common/injects/InjectDistributionByType.tsx index 3d2cc5c4363..8e3094b7867 100644 --- a/openbas-front/src/admin/components/common/injects/InjectDistributionByType.tsx +++ b/openbas-front/src/admin/components/common/injects/InjectDistributionByType.tsx @@ -45,7 +45,7 @@ const InjectDistributionByType: FunctionComponent = ({ exerciseId }) => { data: injectsByType.map((a: InjectStore & { number: number }) => ({ x: tPick(a.inject_injector_contract?.injector_contract_labels), y: a.number, - fillColor: a.inject_injector_contract?.injector_contract_content_parsed?.config?.color, + fillColor: a.inject_injector_contract?.convertedContent?.config?.[`color_${theme.palette.mode}`], })), }, ]; diff --git a/openbas-front/src/admin/components/common/injects/InjectPopover.tsx b/openbas-front/src/admin/components/common/injects/InjectPopover.tsx index 66c115d72f2..4f70664211d 100644 --- a/openbas-front/src/admin/components/common/injects/InjectPopover.tsx +++ b/openbas-front/src/admin/components/common/injects/InjectPopover.tsx @@ -83,7 +83,7 @@ const InjectPopover: FunctionComponent = ({ const [anchorEl, setAnchorEl] = useState(null); const [openExportDialog, setOpenExportDialog] = useState(false); - const isExercise = useHelper((helper: ExercisesHelper) => helper.getExercisesMap()[exerciseOrScenarioId!] !== undefined); + const { isExercise } = useHelper((helper: ExercisesHelper) => ({ isExercise: helper.isExercise(exerciseOrScenarioId!) })); const handlePopoverOpen = (event: ReactMouseEvent) => { event.stopPropagation(); diff --git a/openbas-front/src/admin/components/common/injects/Injects.tsx b/openbas-front/src/admin/components/common/injects/Injects.tsx index 5db69369504..7c74fdfeaa4 100644 --- a/openbas-front/src/admin/components/common/injects/Injects.tsx +++ b/openbas-front/src/admin/components/common/injects/Injects.tsx @@ -6,7 +6,8 @@ import { type CSSProperties, type FunctionComponent, type SyntheticEvent, useCon import { Link } from 'react-router'; import { makeStyles } from 'tss-react/mui'; -import { type InjectorContractConvertedContent, type InjectOutputType, type InjectStore } from '../../../../actions/injects/Inject'; +import { type InjectorContractConverted } from '../../../../actions/injector_contracts/InjectorContract'; +import { type InjectOutputType, type InjectStore } from '../../../../actions/injects/Inject'; import { exportInjectSearch } from '../../../../actions/injects/inject-action'; import ChainedTimeline from '../../../../components/ChainedTimeline'; import ButtonCreate from '../../../../components/common/ButtonCreate'; @@ -123,7 +124,7 @@ const Injects: FunctionComponent = ({ field: 'inject_type', label: 'Type', isSortable: false, - value: (_: InjectOutputType, injectContract: InjectorContractConvertedContent) => { + value: (_: InjectOutputType, injectContract: InjectorContractConverted['convertedContent']) => { const injectorContractName = tPick(injectContract?.label); return injectContract ? ( @@ -140,13 +141,13 @@ const Injects: FunctionComponent = ({ field: 'inject_title', label: 'Title', isSortable: true, - value: (inject: InjectOutputType, _: InjectorContractConvertedContent) => <>{inject.inject_title}, + value: (inject: InjectOutputType, _: InjectorContractConverted['convertedContent']) => <>{inject.inject_title}, }, { field: 'inject_depends_duration', label: 'Trigger', isSortable: true, - value: (inject: InjectOutputType, _: InjectorContractConvertedContent) => { + value: (inject: InjectOutputType, _: InjectorContractConverted['convertedContent']) => { const duration = splitDuration( inject.inject_depends_duration || 0, ); @@ -165,7 +166,7 @@ const Injects: FunctionComponent = ({ field: 'inject_platforms', label: 'Platform(s)', isSortable: false, - value: (inject: InjectOutputType, _: InjectorContractConvertedContent) => ( + value: (inject: InjectOutputType, _: InjectorContractConverted['convertedContent']) => ( <> { inject.inject_injector_contract?.injector_contract_platforms?.map( @@ -186,7 +187,7 @@ const Injects: FunctionComponent = ({ field: 'inject_enabled', label: 'Status', isSortable: false, - value: (inject: InjectOutputType, _: InjectorContractConvertedContent) => { + value: (inject: InjectOutputType, _: InjectorContractConverted['convertedContent']) => { let injectStatus = inject.inject_enabled ? t('Enabled') : t('Disabled'); @@ -208,7 +209,7 @@ const Injects: FunctionComponent = ({ field: 'inject_tags', label: 'Tags', isSortable: false, - value: (inject: InjectOutputType, _: InjectorContractConvertedContent) => , + value: (inject: InjectOutputType, _: InjectorContractConverted['convertedContent']) => , }, ], []); diff --git a/openbas-front/src/admin/components/common/injects/UpdateInject.tsx b/openbas-front/src/admin/components/common/injects/UpdateInject.tsx index 7f4c2b64e26..0fcc31a60cf 100644 --- a/openbas-front/src/admin/components/common/injects/UpdateInject.tsx +++ b/openbas-front/src/admin/components/common/injects/UpdateInject.tsx @@ -4,20 +4,19 @@ import { type SyntheticEvent, useEffect, useRef, useState } from 'react'; import { fetchInject } from '../../../../actions/Inject'; import { type InjectorContractConverted } from '../../../../actions/injector_contracts/InjectorContract'; -import { type InjectOutputType } from '../../../../actions/injects/Inject'; +import { type InjectOutputType, type InjectStore } from '../../../../actions/injects/Inject'; import { type InjectHelper } from '../../../../actions/injects/inject-helper'; import Drawer from '../../../../components/common/Drawer'; import { useFormatter } from '../../../../components/i18n'; import PlatformIcon from '../../../../components/PlatformIcon'; import { useHelper } from '../../../../store'; -import { type AttackPattern, type Inject, type InjectInput, type InjectorContractOutput, type KillChainPhase } from '../../../../utils/api-types'; +import { type AttackPattern, type Inject, type InjectInput, type KillChainPhase } from '../../../../utils/api-types'; import { useAppDispatch } from '../../../../utils/hooks'; import useDataLoader from '../../../../utils/hooks/useDataLoader'; import { isNotEmptyField } from '../../../../utils/utils'; import InjectDetailsForm from './form/InjectDetailsForm'; import InjectIcon from './InjectIcon'; import UpdateInjectLogicalChains from './UpdateInjectLogicalChains'; - interface Props { open: boolean; handleClose: () => void; @@ -37,7 +36,7 @@ const UpdateInject: React.FC = ({ open, handleClose, onUpdateInject, mass const [activeTab, setActiveTab] = useState(availableTabs[0]); const [isInjectLoading, setIsInjectLoading] = useState(true); // Fetching data - const { inject } = useHelper((helper: InjectHelper) => ({ inject: helper.getInject(injectId) })); + const { inject }: { inject: InjectStore } = useHelper((helper: InjectHelper) => ({ inject: helper.getInject(injectId) })); useDataLoader(() => { setIsInjectLoading(true); @@ -103,7 +102,7 @@ const UpdateInject: React.FC = ({ open, handleClose, onUpdateInject, mass }} > {inject?.inject_injector_contract?.injector_contract_platforms?.map( - (platform: InjectorContractOutput['injector_contract_platforms']) => ( + platform => ( void; onUpdateInject?: (data: Inject[]) => Promise; injects?: InjectOutputType[]; diff --git a/openbas-front/src/admin/components/common/injects/form/InjectDefinition.js b/openbas-front/src/admin/components/common/injects/form/InjectDefinition.js index 6c56e5ba178..87673231c9d 100644 --- a/openbas-front/src/admin/components/common/injects/form/InjectDefinition.js +++ b/openbas-front/src/admin/components/common/injects/form/InjectDefinition.js @@ -1037,7 +1037,6 @@ InjectDefinition.propTypes = { handleClose: PropTypes.func, injectorContract: PropTypes.object, fetchDocuments: PropTypes.func, - tagsMap: PropTypes.object, articlesFromExerciseOrScenario: PropTypes.array, variablesFromExerciseOrScenario: PropTypes.array, readOnly: PropTypes.bool, @@ -1050,10 +1049,10 @@ InjectDefinition.propTypes = { const select = (state) => { const helper = storeHelper(state); - const documentsMap = helper.getDocumentsMap(); - const channelsMap = helper.getChannelsMap(); - const articlesMap = helper.getArticlesMap(); - const challengesMap = helper.getChallengesMap(); + const documentsMap = helper.getDocumentsMap().toJS(); + const channelsMap = helper.getChannelsMap().toJS(); + const articlesMap = helper.getArticlesMap().toJS(); + const challengesMap = helper.getChallengesMap().toJS(); return { documentsMap, articlesMap, diff --git a/openbas-front/src/admin/components/common/injects/form/InjectDetailsForm.tsx b/openbas-front/src/admin/components/common/injects/form/InjectDetailsForm.tsx index 96d10d03979..72f91ab114a 100644 --- a/openbas-front/src/admin/components/common/injects/form/InjectDetailsForm.tsx +++ b/openbas-front/src/admin/components/common/injects/form/InjectDetailsForm.tsx @@ -6,7 +6,6 @@ import { useContext, useEffect, useState } from 'react'; import { useForm } from 'react-hook-form'; import { z } from 'zod'; -import type { TagHelper } from '../../../../../actions/helper'; import { type ContractElement, type FieldValue, @@ -14,7 +13,6 @@ import { } from '../../../../../actions/injector_contracts/InjectorContract'; import { useFormatter } from '../../../../../components/i18n'; import Loader from '../../../../../components/Loader'; -import { useHelper } from '../../../../../store'; import { type Inject, type InjectInput } from '../../../../../utils/api-types'; import { splitDuration } from '../../../../../utils/Time'; import { isEmptyField } from '../../../../../utils/utils'; @@ -72,7 +70,6 @@ const InjectDetailsForm = ({ expectations: [], }); - const { tagsMap } = useHelper((helper: TagHelper) => ({ tagsMap: helper.getTagsMap() })); const toggleInjectContent = () => { setPristineOpenDetails(false); if (openDetails) { @@ -331,7 +328,6 @@ const InjectDetailsForm = ({ inject={defaultValues} injectorContract={{ ...injectorContractContent }} handleClose={handleClose} - tagsMap={tagsMap} readOnly={permissions.readOnly} articlesFromExerciseOrScenario={[]} variablesFromExerciseOrScenario={[]} diff --git a/openbas-front/src/admin/components/components/channels/Channel.js b/openbas-front/src/admin/components/components/channels/Channel.js index ce6aa9b0589..641ca3f3833 100644 --- a/openbas-front/src/admin/components/components/channels/Channel.js +++ b/openbas-front/src/admin/components/components/channels/Channel.js @@ -31,15 +31,12 @@ const Channel = () => { const { channelId } = useParams(); const dispatch = useDispatch(); const { t } = useFormatter(); - const { channel, documentsMap, userAdmin } = useHelper((helper) => { - const med = helper.getChannel(channelId); - const docsMap = helper.getDocumentsMap(); - return { - channel: med, - documentsMap: docsMap, - userAdmin: helper.getMe()?.user_admin ?? false, - }; - }); + const { channel, documentsMap, userAdmin } = useHelper(helper => ({ + channel: helper.getChannel(channelId), + documentsMap: helper.getDocumentsMap(), + userAdmin: helper.getMeAdmin(), + }), + ); useDataLoader(() => { dispatch(fetchDocuments()); }); diff --git a/openbas-front/src/admin/components/components/channels/ChannelHeader.js b/openbas-front/src/admin/components/components/channels/ChannelHeader.js index 72d4e92031e..dcf986386a6 100644 --- a/openbas-front/src/admin/components/components/channels/ChannelHeader.js +++ b/openbas-front/src/admin/components/components/channels/ChannelHeader.js @@ -18,7 +18,7 @@ const ChannelHeader = () => { const { channelId } = useParams(); const { channel, userAdmin } = useHelper(helper => ({ channel: helper.getChannel(channelId), - userAdmin: helper.getMe()?.user_admin ?? false, + userAdmin: helper.getMeAdmin(), })); return (

diff --git a/openbas-front/src/admin/components/components/channels/Channels.tsx b/openbas-front/src/admin/components/components/channels/Channels.tsx index aafee3b196f..9fdda4ce7d1 100644 --- a/openbas-front/src/admin/components/components/channels/Channels.tsx +++ b/openbas-front/src/admin/components/components/channels/Channels.tsx @@ -104,7 +104,7 @@ const Channels = () => { userAdmin: boolean; } = useHelper((helper: ChannelsHelper & UserHelper) => ({ channels: helper.getChannels(), - userAdmin: helper.getMe()?.user_admin ?? false, + userAdmin: helper.getMeAdmin(), })); useDataLoader(() => { dispatch(fetchChannels()); diff --git a/openbas-front/src/admin/components/components/channels/ChannelsFilter.tsx b/openbas-front/src/admin/components/components/channels/ChannelsFilter.tsx index c55eb3b6cc0..5779a8eb5bc 100644 --- a/openbas-front/src/admin/components/components/channels/ChannelsFilter.tsx +++ b/openbas-front/src/admin/components/components/channels/ChannelsFilter.tsx @@ -43,7 +43,7 @@ const ChannelsFilter: FunctionComponent = (props) => { useEffect(() => { dispatch(fetchChannels()); }, []); - const channels = useHelper((helper: ChannelsHelper) => helper.getChannels()); + const { channels } = useHelper((helper: ChannelsHelper) => ({ channels: helper.getChannels() })); const { onChannelsChange, onClearChannels = () => { }, fullWidth } = props; const channelColor = (type?: string) => { diff --git a/openbas-front/src/admin/components/components/documents/Documents.js b/openbas-front/src/admin/components/components/documents/Documents.js index 8fd82819dd9..f3dfcdd9a70 100644 --- a/openbas-front/src/admin/components/components/documents/Documents.js +++ b/openbas-front/src/admin/components/components/documents/Documents.js @@ -74,7 +74,7 @@ const Documents = () => { const { exercisesMap, scenariosMap, userAdmin } = useHelper(helper => ({ exercisesMap: helper.getExercisesMap(), scenariosMap: helper.getScenariosMap(), - userAdmin: helper.getMe()?.user_admin ?? false, + userAdmin: helper.getMeAdmin(), })); useDataLoader(() => { dispatch(fetchExercises()); diff --git a/openbas-front/src/admin/components/components/lessons/LessonsTemplate.tsx b/openbas-front/src/admin/components/components/lessons/LessonsTemplate.tsx index 70b22d7841f..913c3ff1601 100644 --- a/openbas-front/src/admin/components/components/lessons/LessonsTemplate.tsx +++ b/openbas-front/src/admin/components/components/lessons/LessonsTemplate.tsx @@ -43,7 +43,7 @@ const LessonsTemplate = () => { return { categories: helper.getLessonsTemplateCategories(lessonsTemplateId), questions: helper.getLessonsTemplateQuestions(), - userAdmin: helper.getMe()?.user_admin ?? false, + userAdmin: helper.getMeAdmin(), }; }); useDataLoader(() => { diff --git a/openbas-front/src/admin/components/components/lessons/LessonsTemplateHeader.tsx b/openbas-front/src/admin/components/components/lessons/LessonsTemplateHeader.tsx index 4a62c8e73bc..fc5ec5208e8 100644 --- a/openbas-front/src/admin/components/components/lessons/LessonsTemplateHeader.tsx +++ b/openbas-front/src/admin/components/components/lessons/LessonsTemplateHeader.tsx @@ -26,7 +26,7 @@ const LessonsTemplateHeader = () => { const { lessonsTemplateId } = useParams() as { lessonsTemplateId: string }; const { lessonsTemplate, userAdmin } = useHelper((helper: LessonsTemplatesHelper & UserHelper) => ({ lessonsTemplate: helper.getLessonsTemplate(lessonsTemplateId), - userAdmin: helper.getMe()?.user_admin ?? false, + userAdmin: helper.getMeAdmin(), })); return ( <> diff --git a/openbas-front/src/admin/components/components/lessons/LessonsTemplates.tsx b/openbas-front/src/admin/components/components/lessons/LessonsTemplates.tsx index 41a68253f3e..48a6081e184 100644 --- a/openbas-front/src/admin/components/components/lessons/LessonsTemplates.tsx +++ b/openbas-front/src/admin/components/components/lessons/LessonsTemplates.tsx @@ -40,7 +40,7 @@ const LessonsTemplates = () => { // Fetching data const { userAdmin } = useHelper((helper: UserHelper) => { - return { userAdmin: helper.getMe()?.user_admin ?? false }; + return { userAdmin: helper.getMeAdmin() }; }); // Headers diff --git a/openbas-front/src/admin/components/components/teams/Teams.tsx b/openbas-front/src/admin/components/components/teams/Teams.tsx index df3453cce39..e40a603779f 100644 --- a/openbas-front/src/admin/components/components/teams/Teams.tsx +++ b/openbas-front/src/admin/components/components/teams/Teams.tsx @@ -4,8 +4,7 @@ import { type CSSProperties, useState } from 'react'; import { useSearchParams } from 'react-router'; import { makeStyles } from 'tss-react/mui'; -import { type EndpointHelper } from '../../../../actions/assets/asset-helper'; -import { type TagHelper, type UserHelper } from '../../../../actions/helper'; +import { type UserHelper } from '../../../../actions/helper'; import { searchTeams } from '../../../../actions/teams/team-actions'; import { type TeamsHelper } from '../../../../actions/teams/team-helper'; import Breadcrumbs from '../../../../components/Breadcrumbs'; @@ -68,7 +67,7 @@ const Teams = () => { const [searchId] = searchParams.getAll('id'); // Fetching data - const { userAdmin } = useHelper((helper: EndpointHelper & UserHelper & TagHelper) => ({ userAdmin: helper.getMe()?.user_admin ?? false })); + const { userAdmin } = useHelper((helper: UserHelper) => ({ userAdmin: helper.getMeAdmin() })); // Headers const headers = [ diff --git a/openbas-front/src/admin/components/findings/Findings.tsx b/openbas-front/src/admin/components/findings/Findings.tsx index 77445d29f91..8b816974992 100644 --- a/openbas-front/src/admin/components/findings/Findings.tsx +++ b/openbas-front/src/admin/components/findings/Findings.tsx @@ -1,8 +1,12 @@ import { searchFindings } from '../../../actions/findings/finding-actions'; +import Breadcrumbs from '../../../components/Breadcrumbs'; +import { useFormatter } from '../../../components/i18n'; import type { FindingOutput } from '../../../utils/api-types'; import FindingList from './FindingList'; const Findings = () => { + const { t } = useFormatter(); + const additionalFilterNames = [ 'finding_inject_id', 'finding_scenario', @@ -30,12 +34,21 @@ const Findings = () => { }, ]; return ( - + <> + + + ); }; diff --git a/openbas-front/src/admin/components/lessons/scenarios/Lessons.tsx b/openbas-front/src/admin/components/lessons/scenarios/Lessons.tsx index 0017e5335c4..cf891b31052 100644 --- a/openbas-front/src/admin/components/lessons/scenarios/Lessons.tsx +++ b/openbas-front/src/admin/components/lessons/scenarios/Lessons.tsx @@ -4,7 +4,7 @@ import { type ChangeEvent, type FunctionComponent, useContext, useState } from ' import Transition from '../../../../components/common/Transition'; import { useFormatter } from '../../../../components/i18n'; -import { type Inject, type LessonsAnswer, type LessonsCategory, type LessonsQuestion, type LessonsTemplate, type Objective, type Team, type User } from '../../../../utils/api-types'; +import { type LessonsAnswer, type LessonsCategory, type LessonsQuestion, type LessonsTemplate, type Objective, type Team, type User } from '../../../../utils/api-types'; import { LessonContext } from '../../common/Context'; import CreateLessonsTemplate from '../../components/lessons/CreateLessonsTemplate'; import CreateLessonsCategory from '../categories/CreateLessonsCategory'; @@ -30,7 +30,6 @@ interface GenericSource { interface Props { source: GenericSource; objectives: Objective[]; - injects: Inject[]; teamsMap: Record; teams: Team[]; lessonsCategories: LessonsCategory[]; diff --git a/openbas-front/src/admin/components/nav/LeftBar.tsx b/openbas-front/src/admin/components/nav/LeftBar.tsx index 5c39c699ceb..3836c1f47d2 100644 --- a/openbas-front/src/admin/components/nav/LeftBar.tsx +++ b/openbas-front/src/admin/components/nav/LeftBar.tsx @@ -23,10 +23,7 @@ import LeftMenu from '../../../components/common/menu/leftmenu/LeftMenu'; import { useHelper } from '../../../store'; const LeftBar = () => { - const userAdmin = useHelper((helper: UserHelper) => { - const me = helper.getMe(); - return me?.user_admin ?? false; - }); + const { userAdmin } = useHelper((helper: UserHelper) => ({ userAdmin: helper.getMeAdmin() })); const entries = [ { items: [ diff --git a/openbas-front/src/admin/components/payloads/PayloadComponent.tsx b/openbas-front/src/admin/components/payloads/PayloadComponent.tsx index 9a526a6fc9f..ae65a3f8b1a 100644 --- a/openbas-front/src/admin/components/payloads/PayloadComponent.tsx +++ b/openbas-front/src/admin/components/payloads/PayloadComponent.tsx @@ -43,7 +43,7 @@ const PayloadComponent: FunctionComponent = ({ selectedPayload }) => { const { t } = useFormatter(); const theme = useTheme(); - const { attackPatternsMap } = useHelper((helper: AttackPatternHelper) => ({ attackPatternsMap: helper.getAttackPatternsMap() })); + const { attackPatternsMap }: { attackPatternsMap: ReturnType } = useHelper((helper: AttackPatternHelper) => ({ attackPatternsMap: helper.getAttackPatternsMap() })); const getAttackCommand = (payload: PayloadType | null): string => { if (!payload) return ''; @@ -96,7 +96,7 @@ const PayloadComponent: FunctionComponent = ({ selectedPayload }) => { {t('Attack patterns')} - {selectedPayload?.payload_attack_patterns && selectedPayload?.payload_attack_patterns.length === 0 ? '-' : selectedPayload?.payload_attack_patterns?.map((attackPatternId: string) => attackPatternsMap[attackPatternId]).map((attackPattern: AttackPattern) => ( + {selectedPayload?.payload_attack_patterns && selectedPayload?.payload_attack_patterns.length === 0 ? '-' : selectedPayload?.payload_attack_patterns?.map((attackPatternId: string) => attackPatternsMap?.[attackPatternId]).map((attackPattern: AttackPattern) => ( = ({ selectedPayload }) => { variant="body2" gutterBottom > - {t(selectedPayload?.payload_execution_arch)} + {selectedPayload && t(selectedPayload?.payload_execution_arch)}
- = ({ selectedPayload }) => { - {selectedPayload?.payload_prerequisites?.map((prerequisite: PayloadPrerequisite) => { - return ( - <> - - - {prerequisite.executor} - - -
-                                    
-                                  
-
- - {prerequisite.check_command !== undefined - ? ( -
-                                          
-                                        
- ) : '-'} - -
-
- - ); - })} + {selectedPayload?.payload_prerequisites?.map((prerequisite: PayloadPrerequisite) => ( + + + {prerequisite.executor} + + +
+                                
+                              
+
+ + {prerequisite.check_command !== undefined + ? ( +
+                                      
+                                    
+ ) : '-'} +
+
+ ))}
diff --git a/openbas-front/src/admin/components/scenarios/Scenarios.tsx b/openbas-front/src/admin/components/scenarios/Scenarios.tsx index 961fa34a346..28b212a4ee9 100644 --- a/openbas-front/src/admin/components/scenarios/Scenarios.tsx +++ b/openbas-front/src/admin/components/scenarios/Scenarios.tsx @@ -55,7 +55,7 @@ const Scenarios = () => { const [loading, setLoading] = useState(true); // Fetching data - const { userAdmin } = useHelper((helper: TagHelper & UserHelper) => ({ userAdmin: helper.getMe()?.user_admin ?? false })); + const { userAdmin } = useHelper((helper: TagHelper & UserHelper) => ({ userAdmin: helper.getMeAdmin() })); // Headers const headers = useMemo(() => [ diff --git a/openbas-front/src/admin/components/scenarios/scenario/Index.tsx b/openbas-front/src/admin/components/scenarios/scenario/Index.tsx index 40f1ee62e12..4ff7d929983 100644 --- a/openbas-front/src/admin/components/scenarios/scenario/Index.tsx +++ b/openbas-front/src/admin/components/scenarios/scenario/Index.tsx @@ -223,7 +223,7 @@ const Index = () => { const { t } = useFormatter(); // Fetching data const { scenarioId } = useParams() as { scenarioId: Scenario['scenario_id'] }; - const scenario = useHelper((helper: ScenariosHelper) => helper.getScenario(scenarioId)); + const { scenario } = useHelper((helper: ScenariosHelper) => ({ scenario: helper.getScenario(scenarioId) })); useDataLoader(() => { setLoading(true); dispatch(fetchScenario(scenarioId)).finally(() => { diff --git a/openbas-front/src/admin/components/scenarios/scenario/ScenarioPopover.tsx b/openbas-front/src/admin/components/scenarios/scenario/ScenarioPopover.tsx index 49cdf1c49c8..f1c0c3e6a4d 100644 --- a/openbas-front/src/admin/components/scenarios/scenario/ScenarioPopover.tsx +++ b/openbas-front/src/admin/components/scenarios/scenario/ScenarioPopover.tsx @@ -1,7 +1,7 @@ import { type FunctionComponent, useState } from 'react'; import { useNavigate } from 'react-router'; -import { type TagHelper, type UserHelper } from '../../../../actions/helper'; +import { type UserHelper } from '../../../../actions/helper'; import { deleteScenario, duplicateScenario, exportScenarioUri } from '../../../../actions/scenarios/scenario-actions'; import ButtonPopover from '../../../../components/common/ButtonPopover'; import DialogDelete from '../../../../components/common/DialogDelete'; @@ -36,7 +36,7 @@ const ScenarioPopover: FunctionComponent = ({ const permissions = useScenarioPermissions(scenario.scenario_id); // Fetching data - const { userAdmin } = useHelper((helper: TagHelper & UserHelper) => ({ userAdmin: helper.getMe()?.user_admin ?? false })); + const { userAdmin } = useHelper((helper: UserHelper) => ({ userAdmin: helper.getMeAdmin() })); // Duplicate const [duplicate, setDuplicate] = useState(false); diff --git a/openbas-front/src/admin/components/scenarios/scenario/articles/ScenarioArticles.tsx b/openbas-front/src/admin/components/scenarios/scenario/articles/ScenarioArticles.tsx index e0273e4e2c5..6fe4ec4ba88 100644 --- a/openbas-front/src/admin/components/scenarios/scenario/articles/ScenarioArticles.tsx +++ b/openbas-front/src/admin/components/scenarios/scenario/articles/ScenarioArticles.tsx @@ -15,7 +15,7 @@ const ScenarioArticles = () => { const dispatch = useAppDispatch(); // Fetching data const { scenarioId } = useParams() as { scenarioId: Scenario['scenario_id'] }; - const articles = useHelper((helper: ArticlesHelper) => helper.getScenarioArticles(scenarioId)); + const { articles } = useHelper((helper: ArticlesHelper) => ({ articles: helper.getScenarioArticles(scenarioId) })); useDataLoader(() => { dispatch(fetchScenarioArticles(scenarioId)); }); diff --git a/openbas-front/src/admin/components/scenarios/scenario/challenges/ScenarioChallenges.tsx b/openbas-front/src/admin/components/scenarios/scenario/challenges/ScenarioChallenges.tsx index 7c9c2b3a1c0..20bf0c7f3b3 100644 --- a/openbas-front/src/admin/components/scenarios/scenario/challenges/ScenarioChallenges.tsx +++ b/openbas-front/src/admin/components/scenarios/scenario/challenges/ScenarioChallenges.tsx @@ -14,7 +14,7 @@ const ScenarioChallenges = () => { const dispatch = useAppDispatch(); // Fetching data const { scenarioId } = useParams() as { scenarioId: Scenario['scenario_id'] }; - const challenges = useHelper((helper: ChallengeHelper) => helper.getScenarioChallenges(scenarioId)); + const { challenges } = useHelper((helper: ChallengeHelper) => ({ challenges: helper.getScenarioChallenges(scenarioId) })); useDataLoader(() => { dispatch(fetchScenarioChallenges(scenarioId)); }); diff --git a/openbas-front/src/admin/components/scenarios/scenario/injects/ScenarioInjects.tsx b/openbas-front/src/admin/components/scenarios/scenario/injects/ScenarioInjects.tsx index 517db16da51..53a350edc82 100644 --- a/openbas-front/src/admin/components/scenarios/scenario/injects/ScenarioInjects.tsx +++ b/openbas-front/src/admin/components/scenarios/scenario/injects/ScenarioInjects.tsx @@ -28,7 +28,6 @@ const ScenarioInjects: FunctionComponent = () => { const { scenario, teams, articles, variables } = useHelper( (helper: InjectHelper & ScenariosHelper & ArticlesHelper & ChallengeHelper & VariablesHelper) => { return { - injects: helper.getScenarioInjects(scenarioId), scenario: helper.getScenario(scenarioId), teams: helper.getScenarioTeams(scenarioId), articles: helper.getScenarioArticles(scenarioId), diff --git a/openbas-front/src/admin/components/scenarios/scenario/lessons/ScenarioLessons.tsx b/openbas-front/src/admin/components/scenarios/scenario/lessons/ScenarioLessons.tsx index 0db66735c5d..db783d9b194 100644 --- a/openbas-front/src/admin/components/scenarios/scenario/lessons/ScenarioLessons.tsx +++ b/openbas-front/src/admin/components/scenarios/scenario/lessons/ScenarioLessons.tsx @@ -3,7 +3,6 @@ import { useParams } from 'react-router'; import { addScenarioEvaluation, fetchScenarioEvaluations, updateScenarioEvaluation } from '../../../../../actions/Evaluation'; import { type ExercisesHelper } from '../../../../../actions/exercises/exercise-helper'; import { type UserHelper } from '../../../../../actions/helper'; -import { fetchScenarioInjects } from '../../../../../actions/Inject'; import { type InjectHelper } from '../../../../../actions/injects/inject-helper'; import { fetchLessonsTemplates } from '../../../../../actions/Lessons'; import { type LessonsTemplatesHelper } from '../../../../../actions/lessons/lesson-helper'; @@ -65,7 +64,6 @@ const ScenarioLessons = () => { scenario, source, objectives, - injects, teams, teamsMap, lessonsCategories, @@ -78,7 +76,6 @@ const ScenarioLessons = () => { scenario: scenarioData, source: processToGenericSource(helper.getScenario(scenarioId)), objectives: helper.getScenarioObjectives(scenarioId), - injects: helper.getScenarioInjects(scenarioId), lessonsCategories: helper.getScenarioLessonsCategories(scenarioId), lessonsQuestions: helper.getScenarioLessonsQuestions(scenarioId), lessonsTemplates: helper.getLessonsTemplates(), @@ -94,7 +91,6 @@ const ScenarioLessons = () => { dispatch(fetchLessonsCategories(scenarioId)); dispatch(fetchLessonsQuestions(scenarioId)); dispatch(fetchScenarioObjectives(scenarioId)); - dispatch(fetchScenarioInjects(scenarioId)); dispatch(fetchScenarioTeams(scenarioId)); }); @@ -145,7 +141,6 @@ const ScenarioLessons = () => { isUpdatable: permissions.canWrite, }} objectives={objectives} - injects={injects} teamsMap={teamsMap} teams={teams} lessonsCategories={lessonsCategories} diff --git a/openbas-front/src/admin/components/scenarios/scenario/variables/ScenarioVariables.tsx b/openbas-front/src/admin/components/scenarios/scenario/variables/ScenarioVariables.tsx index 1250a29bee9..80bcece47c8 100644 --- a/openbas-front/src/admin/components/scenarios/scenario/variables/ScenarioVariables.tsx +++ b/openbas-front/src/admin/components/scenarios/scenario/variables/ScenarioVariables.tsx @@ -23,7 +23,7 @@ const ScenarioVariables = () => { // Fetching data const { scenarioId } = useParams() as { scenarioId: Scenario['scenario_id'] }; const { permissions } = useContext(PermissionsContext); - const variables = useHelper((helper: VariablesHelper) => helper.getScenarioVariables(scenarioId)); + const { variables } = useHelper((helper: VariablesHelper) => ({ variables: helper.getScenarioVariables(scenarioId) })); useDataLoader(() => { dispatch(fetchVariablesForScenario(scenarioId)); }); diff --git a/openbas-front/src/admin/components/settings/groups/CreateGroup.js b/openbas-front/src/admin/components/settings/groups/CreateGroup.js index 6cbadf2b93a..5318040db5b 100644 --- a/openbas-front/src/admin/components/settings/groups/CreateGroup.js +++ b/openbas-front/src/admin/components/settings/groups/CreateGroup.js @@ -7,6 +7,7 @@ import { connect } from 'react-redux'; import { withStyles } from 'tss-react/mui'; import { addGroup } from '../../../../actions/Group'; +import { storeHelper } from '../../../../actions/Schema.js'; import Drawer from '../../../../components/common/Drawer'; import inject18n from '../../../../components/i18n'; import GroupForm from './GroupForm'; @@ -78,7 +79,10 @@ CreateGroup.propTypes = { addGroup: PropTypes.func, }; -const select = state => ({ organizations: state.referential.entities.organizations }); +const select = (state) => { + const helper = storeHelper(state); + return { organizations: helper.getOrganizations().toJS() }; +}; export default R.compose( connect(select, { addGroup }), diff --git a/openbas-front/src/admin/components/settings/groups/GroupPopover.js b/openbas-front/src/admin/components/settings/groups/GroupPopover.js index e9ac143b12b..bfbc836192f 100644 --- a/openbas-front/src/admin/components/settings/groups/GroupPopover.js +++ b/openbas-front/src/admin/components/settings/groups/GroupPopover.js @@ -516,10 +516,10 @@ GroupPopover.propTypes = { const select = (state) => { const helper = storeHelper(state); return { - organizations: helper.getOrganizations(), - organizationsMap: helper.getOrganizationsMap(), - exercises: helper.getExercises(), - scenarios: helper.getScenarios(), + organizations: helper.getOrganizations().toJS(), + organizationsMap: helper.getOrganizationsMap().toJS(), + exercises: helper.getExercises().toJS(), + scenarios: helper.getScenarios().toJS(), }; }; diff --git a/openbas-front/src/admin/components/settings/kill_chain_phases/CreateKillChainPhase.js b/openbas-front/src/admin/components/settings/kill_chain_phases/CreateKillChainPhase.js index 5a63e1c5d27..f316dae82f0 100644 --- a/openbas-front/src/admin/components/settings/kill_chain_phases/CreateKillChainPhase.js +++ b/openbas-front/src/admin/components/settings/kill_chain_phases/CreateKillChainPhase.js @@ -7,6 +7,7 @@ import { connect } from 'react-redux'; import { withStyles } from 'tss-react/mui'; import { addKillChainPhase } from '../../../../actions/KillChainPhase'; +import { storeHelper } from '../../../../actions/Schema.js'; import Drawer from '../../../../components/common/Drawer'; import inject18n from '../../../../components/i18n'; import KillChainPhaseForm from './KillChainPhaseForm'; @@ -79,7 +80,10 @@ CreateKillChainPhase.propTypes = { onCreate: PropTypes.func, }; -const select = state => ({ organizations: state.referential.entities.organizations }); +const select = (state) => { + const helper = storeHelper(state); + return { organizations: helper.getOrganizations().toJS() }; +}; export default R.compose( connect(select, { addKillChainPhase }), diff --git a/openbas-front/src/admin/components/settings/tag_rules/TagRules.tsx b/openbas-front/src/admin/components/settings/tag_rules/TagRules.tsx index f8a2f942d2c..f906d755c88 100644 --- a/openbas-front/src/admin/components/settings/tag_rules/TagRules.tsx +++ b/openbas-front/src/admin/components/settings/tag_rules/TagRules.tsx @@ -3,7 +3,7 @@ import { SelectGroup } from 'mdi-material-ui'; import { type CSSProperties, useMemo, useState } from 'react'; import { makeStyles } from 'tss-react/mui'; -import { type TagHelper, type UserHelper } from '../../../../actions/helper'; +import { type UserHelper } from '../../../../actions/helper'; import { searchTagRules } from '../../../../actions/tag_rules/tagrule-actions'; import Breadcrumbs from '../../../../components/Breadcrumbs'; import PaginationComponentV2 from '../../../../components/common/queryable/pagination/PaginationComponentV2'; @@ -31,7 +31,7 @@ const TagRules = () => { const { classes } = useStyles(); const bodyItemsStyles = useBodyItemsStyles(); - const { userAdmin } = useHelper((helper: TagHelper & UserHelper) => ({ userAdmin: helper.getMe()?.user_admin ?? false })); + const { userAdmin } = useHelper((helper: UserHelper) => ({ userAdmin: helper.getMeAdmin() })); const [tagRules, setTagRules] = useState([]); diff --git a/openbas-front/src/admin/components/simulations/Simulations.tsx b/openbas-front/src/admin/components/simulations/Simulations.tsx index 0b864e47023..04570fa3fd5 100644 --- a/openbas-front/src/admin/components/simulations/Simulations.tsx +++ b/openbas-front/src/admin/components/simulations/Simulations.tsx @@ -24,7 +24,7 @@ const Simulations = () => { const { t } = useFormatter(); // Fetching data - const { userAdmin } = useHelper((helper: ExercisesHelper & UserHelper) => ({ userAdmin: helper.getMe()?.user_admin ?? false })); + const { userAdmin } = useHelper((helper: ExercisesHelper & UserHelper) => ({ userAdmin: helper.getMeAdmin() })); const [loading, setLoading] = useState(true); const [exercises, setExercises] = useState([]); diff --git a/openbas-front/src/admin/components/simulations/simulation/ExercisePopover.tsx b/openbas-front/src/admin/components/simulations/simulation/ExercisePopover.tsx index ea93a08f2b1..509f599b464 100644 --- a/openbas-front/src/admin/components/simulations/simulation/ExercisePopover.tsx +++ b/openbas-front/src/admin/components/simulations/simulation/ExercisePopover.tsx @@ -3,7 +3,7 @@ import { useNavigate } from 'react-router'; import { deleteExercise, duplicateExercise, updateExercise } from '../../../../actions/Exercise'; import { checkExerciseTagRules } from '../../../../actions/exercises/exercise-action'; -import { type TagHelper, type UserHelper } from '../../../../actions/helper'; +import { type UserHelper } from '../../../../actions/helper'; import ButtonPopover from '../../../../components/common/ButtonPopover'; import DialogApplyTagRule from '../../../../components/common/DialogApplyTagRule'; import DialogDelete from '../../../../components/common/DialogDelete'; @@ -116,7 +116,7 @@ const ExercisePopover: FunctionComponent = ({ const permissions = usePermissions(exercise.exercise_id); // Fetching data - const { userAdmin } = useHelper((helper: TagHelper & UserHelper) => ({ userAdmin: helper.getMe()?.user_admin ?? false })); + const { userAdmin } = useHelper((helper: UserHelper) => ({ userAdmin: helper.getMeAdmin() })); // Button Popover const entries = []; diff --git a/openbas-front/src/admin/components/simulations/simulation/Index.tsx b/openbas-front/src/admin/components/simulations/simulation/Index.tsx index e6cbc814c99..94b025844f3 100644 --- a/openbas-front/src/admin/components/simulations/simulation/Index.tsx +++ b/openbas-front/src/admin/components/simulations/simulation/Index.tsx @@ -179,7 +179,7 @@ const Index = () => { const dispatch = useAppDispatch(); // Fetching data const { exerciseId } = useParams() as { exerciseId: ExerciseType['exercise_id'] }; - const exercise = useHelper((helper: ExercisesHelper) => helper.getExercise(exerciseId)); + const { exercise } = useHelper((helper: ExercisesHelper) => ({ exercise: helper.getExercise(exerciseId) })); useDataLoader(() => { setLoading(true); dispatch(fetchExercise(exerciseId)).finally(() => { diff --git a/openbas-front/src/admin/components/simulations/simulation/articles/ExerciseArticles.tsx b/openbas-front/src/admin/components/simulations/simulation/articles/ExerciseArticles.tsx index 18a6b35d193..58a3ad916c6 100644 --- a/openbas-front/src/admin/components/simulations/simulation/articles/ExerciseArticles.tsx +++ b/openbas-front/src/admin/components/simulations/simulation/articles/ExerciseArticles.tsx @@ -15,7 +15,7 @@ const ExerciseArticles = () => { const dispatch = useAppDispatch(); // Fetching data const { exerciseId } = useParams() as { exerciseId: Exercise['exercise_id'] }; - const articles = useHelper((helper: ArticlesHelper) => helper.getExerciseArticles(exerciseId)); + const { articles } = useHelper((helper: ArticlesHelper) => ({ articles: helper.getExerciseArticles(exerciseId) })); useDataLoader(() => { dispatch(fetchExerciseArticles(exerciseId)); }); diff --git a/openbas-front/src/admin/components/simulations/simulation/injects/QuickInject.js b/openbas-front/src/admin/components/simulations/simulation/injects/QuickInject.js index 15786d74ba7..007d045a777 100644 --- a/openbas-front/src/admin/components/simulations/simulation/injects/QuickInject.js +++ b/openbas-front/src/admin/components/simulations/simulation/injects/QuickInject.js @@ -1446,10 +1446,10 @@ QuickInject.propTypes = { const select = (state, ownProps) => { const helper = storeHelper(state); - const documentsMap = helper.getDocumentsMap(); - const teamsMap = helper.getTeamsMap(); + const documentsMap = helper.getDocumentsMap().toJS(); + const teamsMap = helper.getTeamsMap().toJS(); const { exerciseId } = ownProps; - const exerciseVariables = helper.getExerciseVariables(exerciseId); + const exerciseVariables = helper.getExerciseVariables(exerciseId).toJS(); return { documentsMap, teamsMap, diff --git a/openbas-front/src/admin/components/simulations/simulation/logs/LogPopover.js b/openbas-front/src/admin/components/simulations/simulation/logs/LogPopover.js index c5b612f41e6..f4842acd013 100644 --- a/openbas-front/src/admin/components/simulations/simulation/logs/LogPopover.js +++ b/openbas-front/src/admin/components/simulations/simulation/logs/LogPopover.js @@ -149,8 +149,8 @@ const select = (state, ownProps) => { const helper = storeHelper(state); const { exerciseId } = ownProps; return { - exercise: helper.getExercise(exerciseId), - tagsMap: helper.getTagsMap(), + exercise: helper.getExercise(exerciseId).toJS(), + tagsMap: helper.getTagsMap().toJS(), }; }; diff --git a/openbas-front/src/admin/components/simulations/simulation/overview/ExerciseDistributionByInjectorContract.tsx b/openbas-front/src/admin/components/simulations/simulation/overview/ExerciseDistributionByInjectorContract.tsx index f48262c00e4..927175e6e1c 100644 --- a/openbas-front/src/admin/components/simulations/simulation/overview/ExerciseDistributionByInjectorContract.tsx +++ b/openbas-front/src/admin/components/simulations/simulation/overview/ExerciseDistributionByInjectorContract.tsx @@ -19,7 +19,10 @@ const ExerciseDistributionByInjectorContract: FunctionComponent = ({ exer const theme = useTheme(); // Fetching data - const { injectsMap, injectExpectations } = useHelper((helper: InjectHelper) => ({ + const { injectsMap, injectExpectations }: { + injectsMap: Record; + injectExpectations: InjectExpectation[]; + } = useHelper((helper: InjectHelper) => ({ injectsMap: helper.getInjectsMap(), injectExpectations: helper.getExerciseInjectExpectations(exerciseId), })); @@ -47,7 +50,7 @@ const ExerciseDistributionByInjectorContract: FunctionComponent = ({ exer data: sortedInjectorContractsByTotalScore.map((i: InjectStore & { inject_total_score: number }) => ({ x: tPick(i.inject_injector_contract?.injector_contract_labels), y: i.inject_total_score, - fillColor: i.inject_injector_contract?.injector_contract_content_parsed?.config?.color, + fillColor: i.inject_injector_contract?.convertedContent?.config?.[`color_${theme.palette.mode}`], })), }, ]; diff --git a/openbas-front/src/admin/components/simulations/simulation/overview/ExerciseDistributionScoreOverTimeByInjectorContract.tsx b/openbas-front/src/admin/components/simulations/simulation/overview/ExerciseDistributionScoreOverTimeByInjectorContract.tsx index bde03f6d02d..84d66389df6 100644 --- a/openbas-front/src/admin/components/simulations/simulation/overview/ExerciseDistributionScoreOverTimeByInjectorContract.tsx +++ b/openbas-front/src/admin/components/simulations/simulation/overview/ExerciseDistributionScoreOverTimeByInjectorContract.tsx @@ -8,7 +8,7 @@ import { type InjectHelper } from '../../../../../actions/injects/inject-helper' import Empty from '../../../../../components/Empty'; import { useFormatter } from '../../../../../components/i18n'; import { useHelper } from '../../../../../store'; -import { type Exercise, type Inject, type InjectExpectation } from '../../../../../utils/api-types'; +import { type Exercise, type InjectExpectation } from '../../../../../utils/api-types'; import { lineChartOptions } from '../../../../../utils/Charts'; interface Props { exerciseId: Exercise['exercise_id'] } @@ -20,7 +20,7 @@ const ExerciseDistributionScoreOverTimeByInjectorContract: FunctionComponent; + injectsMap: Record; injectExpectations: InjectExpectation[]; } = useHelper((helper: InjectHelper) => ({ injectsMap: helper.getInjectsMap(), @@ -55,7 +55,7 @@ const ExerciseDistributionScoreOverTimeByInjectorContract: FunctionComponent]) => ({ name: tPick(n[1][0].inject_expectation_inject.inject_injector_contract?.injector_contract_labels), - color: n[1][0].inject_expectation_inject.inject_injector_contract?.injector_contract_content_parsed?.config?.color, + color: n[1][0].inject_expectation_inject.inject_injector_contract?.convertedContent?.config?.[`color_${theme.palette.mode}`], data: n[1].map((i: InjectExpectation & { inject_expectation_cumulated_score: number }) => ({ x: i.inject_expectation_updated_at, y: i.inject_expectation_cumulated_score, diff --git a/openbas-front/src/admin/components/simulations/simulation/reports/ExerciseReports.tsx b/openbas-front/src/admin/components/simulations/simulation/reports/ExerciseReports.tsx index 963025338cc..f07a9dda6b7 100644 --- a/openbas-front/src/admin/components/simulations/simulation/reports/ExerciseReports.tsx +++ b/openbas-front/src/admin/components/simulations/simulation/reports/ExerciseReports.tsx @@ -34,7 +34,7 @@ const ExerciseReports: FunctionComponent = ({ exerciseId, exerc const onCreateReportSubmit = (data: ReportInput) => dispatch(addReportForExercise(exerciseId, data)).finally(() => handleCloseCreate()); // Fetching data - const reports = useHelper((helper: ReportsHelper) => helper.getExerciseReports(exerciseId)); + const { reports } = useHelper((helper: ReportsHelper) => ({ reports: helper.getExerciseReports(exerciseId) })); useDataLoader(() => { dispatch(fetchReportsForExercise(exerciseId)); }); diff --git a/openbas-front/src/admin/components/simulations/simulation/timeline/TimelineOverview.tsx b/openbas-front/src/admin/components/simulations/simulation/timeline/TimelineOverview.tsx index 7ac1071ccc3..ef2e6077ed4 100644 --- a/openbas-front/src/admin/components/simulations/simulation/timeline/TimelineOverview.tsx +++ b/openbas-front/src/admin/components/simulations/simulation/timeline/TimelineOverview.tsx @@ -82,10 +82,10 @@ const TimelineOverview = () => { searchColumns, ); - const isEnable = (inject: InjectStore): boolean => inject.inject_injector_contract.injector_contract_content_parsed?.config.expose && inject.inject_enabled; - const filteredInjects = filtering.filterAndSort(injects.filter((inject: InjectStore) => isEnable(inject))); - const pendingInjects = filtering.filterAndSort(filteredInjects.filter((inject: InjectStore) => inject.inject_status === null)); - const processedInjects = filtering.filterAndSort(filteredInjects.filter((i: InjectStore) => i.inject_status !== null)); + const isEnable = (inject: InjectStore): boolean => inject.inject_injector_contract?.convertedContent?.config.expose && !!inject.inject_enabled; + const filteredInjects: InjectStore[] = filtering.filterAndSort(injects.filter((inject: InjectStore) => isEnable(inject))); + const pendingInjects: InjectStore[] = filtering.filterAndSort(filteredInjects.filter((inject: InjectStore) => inject.inject_status === null)); + const processedInjects: InjectStore[] = filtering.filterAndSort(filteredInjects.filter((i: InjectStore) => i.inject_status !== null)); const onUpdateInject = async (inject: Inject) => { if (selectedInjectId) { @@ -149,9 +149,9 @@ const TimelineOverview = () => { > { > { {Object.entries(groupedByInject).map(([injectId, expectationsByInject]) => { const inject = injectsMap[injectId] || {}; - const injectContract = inject.inject_injector_contract.injector_contract_content_parsed || {}; + const injectContract = inject.inject_injector_contract.convertedContent || {}; return (
diff --git a/openbas-front/src/admin/components/teams/Organizations.tsx b/openbas-front/src/admin/components/teams/Organizations.tsx index f0d9de42046..86895ff558d 100644 --- a/openbas-front/src/admin/components/teams/Organizations.tsx +++ b/openbas-front/src/admin/components/teams/Organizations.tsx @@ -81,11 +81,16 @@ const Organizations = () => { const { t } = useFormatter(); // Fetching data - const { organizations, tagsMap, userAdmin } = useHelper((helper: UserHelper & TagHelper & OrganizationHelper) => ({ - organizations: helper.getOrganizations(), - tagsMap: helper.getTagsMap(), - userAdmin: helper.getMe()?.user_admin, - })); + const { organizations, tagsMap, userAdmin }: { + organizations: ReturnType; + tagsMap: ReturnType; + userAdmin: ReturnType; + } + = useHelper((helper: UserHelper & TagHelper & OrganizationHelper) => ({ + organizations: helper.getOrganizations(), + tagsMap: helper.getTagsMap(), + userAdmin: helper.getMeAdmin(), + })); useDataLoader(() => { dispatch(fetchOrganizations()); diff --git a/openbas-front/src/admin/components/teams/Players.tsx b/openbas-front/src/admin/components/teams/Players.tsx index 53d9b235d6f..3e3543a4cc9 100644 --- a/openbas-front/src/admin/components/teams/Players.tsx +++ b/openbas-front/src/admin/components/teams/Players.tsx @@ -50,8 +50,8 @@ const Players = () => { const { t } = useFormatter(); // Fetching data - const { isPlanner, organizationsMap } = useHelper((helper: UserHelper & OrganizationHelper) => ({ - isPlanner: helper.getMe().user_is_planner, + const { me, organizationsMap } = useHelper((helper: UserHelper & OrganizationHelper) => ({ + me: helper.getMe(), organizationsMap: helper.getOrganizationsMap(), })); @@ -209,7 +209,7 @@ const Players = () => { ))} - {isPlanner + {me.user_is_planner && ( setPlayers([result, ...players])} diff --git a/openbas-front/src/admin/components/teams/players/PlayerPopover.tsx b/openbas-front/src/admin/components/teams/players/PlayerPopover.tsx index 27debbe6c01..5cf1d8a8e9b 100644 --- a/openbas-front/src/admin/components/teams/players/PlayerPopover.tsx +++ b/openbas-front/src/admin/components/teams/players/PlayerPopover.tsx @@ -38,7 +38,7 @@ const PlayerPopover: FunctionComponent = ({ helper: UserHelper & OrganizationHelper & TagHelper, ) => { return { - userAdmin: helper.getMe()?.user_admin, + userAdmin: helper.getMeAdmin(), organizationsMap: helper.getOrganizationsMap(), tagsMap: helper.getTagsMap(), }; diff --git a/openbas-front/src/components/ChainedTimeline.tsx b/openbas-front/src/components/ChainedTimeline.tsx index 46aa25577d0..cb36ee1ce38 100644 --- a/openbas-front/src/components/ChainedTimeline.tsx +++ b/openbas-front/src/components/ChainedTimeline.tsx @@ -101,12 +101,15 @@ const ChainedTimelineFlow: FunctionComponent = ({ const reactFlow = useReactFlow(); - const injectsMap = useHelper((injectHelper: InjectHelper) => injectHelper.getInjectsMap()); - const teams = useHelper((teamsHelper: TeamsHelper) => teamsHelper.getTeamsMap()); - const assets = useHelper((endpointHelper: EndpointHelper) => endpointHelper.getEndpointsMap()); - const assetGroups = useHelper((assetGroupsHelper: AssetGroupsHelper) => assetGroupsHelper.getAssetGroupMaps()); - const scenario = useHelper((helper: ScenariosHelper) => helper.getScenario(exerciseOrScenarioId)); - const exercise = useHelper((helper: ExercisesHelper) => helper.getExercise(exerciseOrScenarioId)); + const { injectsMap, teams, assets, assetGroups, scenario, exercise } + = useHelper((helper: ExercisesHelper & InjectHelper & TeamsHelper & EndpointHelper & AssetGroupsHelper & ScenariosHelper) => ({ + injectsMap: helper.getInjectsMap(), + teams: helper.getTeamsMap(), + assets: helper.getEndpointsMap(), + assetGroups: helper.getAssetGroupMaps(), + scenario: helper.getScenario(exerciseOrScenarioId), + exercise: helper.getExercise(exerciseOrScenarioId), + })); const { t } = useFormatter(); diff --git a/openbas-front/src/components/KillChainPhaseField.js b/openbas-front/src/components/KillChainPhaseField.js index 557f08d94ec..b5f2f6dea7f 100644 --- a/openbas-front/src/components/KillChainPhaseField.js +++ b/openbas-front/src/components/KillChainPhaseField.js @@ -125,8 +125,8 @@ class KillChainPhaseField extends Component { const select = (state) => { const helper = storeHelper(state); return { - killChainPhases: helper.getKillChainPhases(), - userAdmin: helper.getMe()?.user_admin ?? false, + killChainPhases: helper.getKillChainPhases().toJS(), + userAdmin: helper.getMeAdmin(), }; }; diff --git a/openbas-front/src/components/OldAttackPatternField.js b/openbas-front/src/components/OldAttackPatternField.js index b211b165ab2..f2b46f5375d 100644 --- a/openbas-front/src/components/OldAttackPatternField.js +++ b/openbas-front/src/components/OldAttackPatternField.js @@ -137,9 +137,9 @@ class OldAttackPatternField extends Component { const select = (state) => { const helper = storeHelper(state); return { - killChainPhasesMap: helper.getKillChainPhasesMap(), - attackPatterns: helper.getAttackPatterns(), - userAdmin: helper.getMe()?.user_admin ?? false, + killChainPhasesMap: helper.getKillChainPhasesMap().toJS(), + attackPatterns: helper.getAttackPatterns().toJS(), + userAdmin: helper.getMeAdmin(), }; }; diff --git a/openbas-front/src/components/OrganizationField.js b/openbas-front/src/components/OrganizationField.js index c4cd170d6c1..7e474066b5a 100644 --- a/openbas-front/src/components/OrganizationField.js +++ b/openbas-front/src/components/OrganizationField.js @@ -116,7 +116,7 @@ class OrganizationField extends Component { const select = (state) => { const helper = storeHelper(state); - return { organizations: helper.getOrganizations() }; + return { organizations: helper.getOrganizations().toJS() }; }; export default R.compose( diff --git a/openbas-front/src/components/TagField.js b/openbas-front/src/components/TagField.js index 166350f68b5..ed89324cf79 100644 --- a/openbas-front/src/components/TagField.js +++ b/openbas-front/src/components/TagField.js @@ -130,8 +130,8 @@ class TagField extends Component { const select = (state) => { const helper = storeHelper(state); return { - tags: helper.getTags(), - userAdmin: helper.getMe()?.user_admin ?? false, + tags: helper.getTags().toJS(), + userAdmin: helper.getMeAdmin(), }; }; diff --git a/openbas-front/src/components/Timeline.tsx b/openbas-front/src/components/Timeline.tsx index 0485230f0ec..9cbfafa0b5d 100644 --- a/openbas-front/src/components/Timeline.tsx +++ b/openbas-front/src/components/Timeline.tsx @@ -118,8 +118,6 @@ const Timeline: FunctionComponent = ({ injects, onSelectInject, teams }) if ( inject.inject_injector_contract?.convertedContent && 'fields' in inject.inject_injector_contract.convertedContent - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error && inject.inject_injector_contract.convertedContent.fields.some( /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ (field: any) => field.key === 'teams', @@ -266,9 +264,9 @@ const Timeline: FunctionComponent = ({ injects, onSelectInject, teams }) return ( { const { attackPatterns, killChainPhasesMap, userAdmin } = useHelper((helper: AttackPatternHelper & KillChainPhaseHelper & UserHelper) => ({ attackPatterns: helper.getAttackPatterns(), killChainPhasesMap: helper.getKillChainPhasesMap(), - userAdmin: helper.getMe()?.user_admin ?? false, + userAdmin: helper.getMeAdmin(), })); const [attackPatternCreation, setAttackPatternCreation] = useState(false); diff --git a/openbas-front/src/components/fields/FileTransferDialog.tsx b/openbas-front/src/components/fields/FileTransferDialog.tsx index b6b9cebb28c..953e081e038 100644 --- a/openbas-front/src/components/fields/FileTransferDialog.tsx +++ b/openbas-front/src/components/fields/FileTransferDialog.tsx @@ -69,7 +69,7 @@ const FileTransferDialog: FunctionComponent = ({ userAdmin: string; } = useHelper((helper: DocumentHelper & UserHelper) => ({ documents: helper.getDocuments(), - userAdmin: helper.getMe()?.user_admin, + userAdmin: helper.getMeAdmin(), })); useEffect(() => { diff --git a/openbas-front/src/components/fields/TagField.tsx b/openbas-front/src/components/fields/TagField.tsx index e0e82fec245..7c8e702fd55 100644 --- a/openbas-front/src/components/fields/TagField.tsx +++ b/openbas-front/src/components/fields/TagField.tsx @@ -51,7 +51,7 @@ const TagField: FunctionComponent = ({ userAdmin: boolean; } = useHelper((helper: TagHelper & UserHelper) => ({ tags: helper.getTags(), - userAdmin: helper.getMe()?.user_admin ?? false, + userAdmin: helper.getMeAdmin(), })); const dispatch = useAppDispatch(); diff --git a/openbas-front/src/components/fields/TagFieldSingle.tsx b/openbas-front/src/components/fields/TagFieldSingle.tsx index 65c797970a3..4eea1d74dd7 100644 --- a/openbas-front/src/components/fields/TagFieldSingle.tsx +++ b/openbas-front/src/components/fields/TagFieldSingle.tsx @@ -56,7 +56,7 @@ const TagFieldSingle: FunctionComponent = ({ userAdmin: boolean; } = useHelper((helper: TagHelper & UserHelper) => ({ tags: helper.getTags().filter(tag => !forbiddenOptions.includes(tag.tag_name)), - userAdmin: helper.getMe()?.user_admin ?? false, + userAdmin: helper.getMeAdmin(), })); const dispatch = useAppDispatch(); diff --git a/openbas-front/src/public/components/login/Login.tsx b/openbas-front/src/public/components/login/Login.tsx index 1f727dd8b2e..f76f3fa8e52 100644 --- a/openbas-front/src/public/components/login/Login.tsx +++ b/openbas-front/src/public/components/login/Login.tsx @@ -4,7 +4,7 @@ import { useEffect, useState } from 'react'; import Markdown from 'react-markdown'; import { makeStyles } from 'tss-react/mui'; -import { askToken, checkKerberos, fetchPlatformParameters } from '../../../actions/Application'; +import { askToken, checkKerberos } from '../../../actions/Application'; import { type LoggedHelper } from '../../../actions/helper'; import { useFormatter } from '../../../components/i18n'; import byFiligranDark from '../../../static/images/by_filigran_dark.png'; @@ -83,7 +83,6 @@ const Login = () => { return () => window.removeEventListener('resize', updateWindowDimensions); }); useEffect(() => { - dispatch(fetchPlatformParameters()); dispatch(checkKerberos()); }); const onSubmit = (data: { diff --git a/openbas-front/src/reducers/Referential.ts b/openbas-front/src/reducers/Referential.ts index 67286ed3f49..f18e2df2a8b 100644 --- a/openbas-front/src/reducers/Referential.ts +++ b/openbas-front/src/reducers/Referential.ts @@ -1,4 +1,4 @@ -import { List, Map } from 'immutable'; +import { fromJS, List, Map } from 'immutable'; import * as R from 'ramda'; import * as Constants from '../constants/ActionTypes'; @@ -57,11 +57,19 @@ export const entitiesInitializer = Map({ }); // eslint-disable-next-line @typescript-eslint/no-explicit-any -const mergeDeepOverwriteLists = (a: any, b: any) => { +const mergeDeepOverwriteLists = (a: any, b: any, deep = 0) => { // First, check if 'b' is null to avoid overwriting 'a', even if 'a' is mergeable. // Then, check if 'a' is mergeable. - if (b !== null && a && typeof a === 'object' && typeof a.mergeWith === 'function' && !List.isList(a)) { - return a.mergeWith(mergeDeepOverwriteLists, b); + // Then, merge a is not a list & b is immutable then merge them otherwise return b + if (!b) { + return b; + } + if (deep < 3 && a && Map.isMap(a)) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return a.mergeWith((c: any, d: any): any => mergeDeepOverwriteLists(c, d, deep + 1), b); + } + if (!List.isList(a) && Map.isMap(b)) { + return a.merge(b); } return b; }; @@ -71,7 +79,7 @@ const referential = (state: any = Map({}), action: any = {}) => { switch (action.type) { case Constants.DATA_UPDATE_SUCCESS: case Constants.DATA_FETCH_SUCCESS: { - return mergeDeepOverwriteLists(state, R.dissoc('result', action.payload)); + return mergeDeepOverwriteLists(state, fromJS(R.dissoc('result', action.payload))); } case Constants.DATA_DELETE_SUCCESS: { const toDeleteIn = state.getIn(['entities', action.payload.type]); diff --git a/openbas-front/src/store.ts b/openbas-front/src/store.ts index 5c5d23c3be9..302232605c7 100644 --- a/openbas-front/src/store.ts +++ b/openbas-front/src/store.ts @@ -1,6 +1,7 @@ import { composeWithDevTools } from '@redux-devtools/extension'; import { fromJS, isImmutable } from 'immutable'; import * as R from 'ramda'; +import { useEffect, useState } from 'react'; import { useSelector } from 'react-redux'; import { applyMiddleware, createStore } from 'redux'; import { thunk } from 'redux-thunk'; @@ -34,30 +35,40 @@ const initStore = () => { ); }; -// TODO type selector object // eslint-disable-next-line @typescript-eslint/no-explicit-any -export const useHelper = (selector: any) => (() => { - const selected = useSelector(state => selector(storeHelper(state)), R.equals); - - if (!selected) { - return selected; +const getJS = (selectorValue: any) => { + if (!selectorValue) { + return selectorValue; } - if (isImmutable(selected)) { - return selected.toJS(); + if (isImmutable(selectorValue)) { + return selectorValue.toJS(); } // eslint-disable-next-line @typescript-eslint/no-explicit-any const result: Record = {}; - for (const key in selected) { - if (Object.prototype.hasOwnProperty.call(selected, key)) { - if (selected[key] && isImmutable(selected[key])) { - result[key] = selected[key].toJS(); + for (const key in selectorValue) { + if (Object.prototype.hasOwnProperty.call(selectorValue, key)) { + if (selectorValue[key] && isImmutable(selectorValue[key])) { + result[key] = selectorValue[key].toJS(); } else { - result[key] = selected[key]; + result[key] = selectorValue[key]; } } } return result; -})(); +}; + +// TODO type selector object +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const useHelper = (selector: any) => { + const selectorValue = useSelector(state => selector(storeHelper(state)), R.equals); + const [selected, setSelected] = useState(getJS(selectorValue)); + + useEffect(() => { + setSelected(getJS(selectorValue)); + }, [selectorValue]); + + return selected; +}; export const store = initStore(); diff --git a/openbas-front/src/utils/lang/en.json b/openbas-front/src/utils/lang/en.json index c89a3a3d74a..55c5c982ded 100644 --- a/openbas-front/src/utils/lang/en.json +++ b/openbas-front/src/utils/lang/en.json @@ -5,6 +5,8 @@ ".": ".", "(last 180 days)": "(last 180 days)", "[${exercise.name}] Lessons learned questionnaire": "[${exercise.name}] Lessons learned questionnaire", + "{executor_name} documentation": "{executor_name} documentation", + "{executor_name} documentation.": "{executor_name} documentation.", "&": "&", "|": "|", "1 month": "1 month", @@ -153,6 +155,7 @@ "backlabel": "backlabel", "backuri": "backuri", "Bad request": "Bad request", + "base_attack_patterns_side": "Attack patterns", "Bash": "Bash", "Best regards": "Best regards", "Bitter": "Bitter", @@ -640,7 +643,6 @@ "INJECT EXECUTED": "INJECT EXECUTED", "Inject Execution Status": "Inject Execution Status", "Inject expectations": "inject expectations", - "InjectExpectation": "Inject expectations", "Inject importer description": "Inject importer description", "Inject importer name": "Inject importer name", "Inject importer rules": "Inject importer rules", @@ -652,12 +654,11 @@ "Inject types scores over time": "Inject types scores over time", "inject_asset_groups": "Asset groups", "inject_assets": "Assets", + "inject_expectation_status": "Inject expectation status", + "inject_expectation_type": "Inject expectation type", "inject_export_json_selection": "Export selection(JSON)", "inject_export_json_single": "Exporter (JSON)", "inject_export_prompt": "Export this inject", - "inject_expectation_type": "Inject expectation type", - "inject_expectation_status": "Inject expectation status", - "base_attack_patterns_side": "Attack patterns", "inject_import_file_must_be_zip": "File must be a zip archive", "inject_import_json_action": "Import JSON", "inject_import_xls_action": "XLS import (mapper)", @@ -669,6 +670,7 @@ "inject_title": "Title", "inject_type": "Type", "inject_updated_at": "Updated at", + "InjectExpectation": "Inject expectations", "injector_contract_arch": "Architecture", "injector_contract_injector": "Injector", "injector_contract_kill_chain_phases": "Kill chain phase", @@ -1522,4 +1524,4 @@ "Your overall evaluation about this question.": "Your overall evaluation about this question.", "your trial license online": "your trial license online", "YYYY": "YYYY" -} +} \ No newline at end of file diff --git a/openbas-front/src/utils/lang/fr.json b/openbas-front/src/utils/lang/fr.json index 9f44c1c7081..90ebd5a6a7c 100644 --- a/openbas-front/src/utils/lang/fr.json +++ b/openbas-front/src/utils/lang/fr.json @@ -5,6 +5,8 @@ ".": ".", "(last 180 days)": "(180 derniers jours)", "[${exercise.name}] Lessons learned questionnaire": "[${exercise.name}] Questionnaire de retour d'expérience", + "{executor_name} documentation": "documentation {executor_name}", + "{executor_name} documentation.": "documentation {executor_name}.", "&": "& ;", "|": "|", "1 month": "1 mois", @@ -153,6 +155,7 @@ "backlabel": "étiquette de retour", "backuri": "uri de retour", "Bad request": "Mauvaise requête", + "base_attack_patterns_side": "Modèles d'attaque", "Bash": "Bash", "Best regards": "Bien cordialement", "Bitter": "Amer", @@ -651,6 +654,8 @@ "Inject types scores over time": "Score des types de stimuli dans le temps", "inject_asset_groups": "Groupes d'actifs", "inject_assets": "Actifs", + "inject_expectation_status": "Injecter un statut d'attente", + "inject_expectation_type": "Type d'attente injectée", "inject_export_json_selection": "Exporter la sélection(JSON)", "inject_export_json_single": "Exporter (JSON)", "inject_export_prompt": "Exporter cette injection", @@ -665,6 +670,7 @@ "inject_title": "Titre", "inject_type": "Type", "inject_updated_at": "Mis à jour à", + "InjectExpectation": "Injecter des attentes", "injector_contract_arch": "Architecture", "injector_contract_injector": "Injector", "injector_contract_kill_chain_phases": "Phase de kill chain", diff --git a/openbas-front/src/utils/lang/zh.json b/openbas-front/src/utils/lang/zh.json index 31506d445e0..8d33b30d3ad 100644 --- a/openbas-front/src/utils/lang/zh.json +++ b/openbas-front/src/utils/lang/zh.json @@ -5,6 +5,8 @@ ".": ".", "(last 180 days)": "(过去 180 天)", "[${exercise.name}] Lessons learned questionnaire": "[${exercise.name}] 经验教训调查问卷", + "{executor_name} documentation": "{executor_name}文件", + "{executor_name} documentation.": "{executor_name} 文档。", "&": "&;", "|": "|", "1 month": "一个月", @@ -153,6 +155,7 @@ "backlabel": "后台标签", "backuri": "后台URI", "Bad request": "錯誤嘅請求", + "base_attack_patterns_side": "攻击模式", "Bash": "Bash", "Best regards": "此致", "Bitter": "痛苦", @@ -651,6 +654,8 @@ "Inject types scores over time": "时间段注入类型分数", "inject_asset_groups": "资产组", "inject_assets": "资产", + "inject_expectation_status": "注入期望状态", + "inject_expectation_type": "注入期望类型", "inject_export_json_selection": "导出选择(JSON)", "inject_export_json_single": "导出器(JSON)", "inject_export_prompt": "导出注入", @@ -665,6 +670,7 @@ "inject_title": "标题", "inject_type": "类型", "inject_updated_at": "更新于", + "InjectExpectation": "注入期望", "injector_contract_arch": "建築", "injector_contract_injector": "注入器", "injector_contract_kill_chain_phases": "杀伤链阶段",