diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6210c667..3984c31f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -91,7 +91,7 @@ jobs: uses: cypress-io/github-action@v5 with: tag: node-${{ matrix.node }} - start: yarn start:dev + start: yarn start:test-app wait-on: 'http://localhost:4000/api/graphql, http://localhost:3500' browser: chrome group: 'Red Team - Chrome' @@ -140,7 +140,7 @@ jobs: uses: cypress-io/github-action@v5 with: tag: node-${{ matrix.node }} - start: yarn start:blue + start: yarn start:test-app wait-on: 'http://localhost:4000/api/graphql, http://localhost:3500' browser: chrome group: 'Blue Team - Chrome' @@ -152,6 +152,7 @@ jobs: ci-build-id: ${{ needs.prepare.outputs.uuid }} env: CYPRESS_PROJECT_ID: '46ahz3' + SERVER_BLUE_TEAM: 'true' CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY_BLUE }} # RedTeamFirefox: diff --git a/.moon/tasks.yml b/.moon/tasks.yml index 3dd7c2b4..8ecdf193 100644 --- a/.moon/tasks.yml +++ b/.moon/tasks.yml @@ -139,6 +139,18 @@ tasks: options: runInCI: false runDepsInParallel: false + preview-vite: + command: 'vite preview --port 3500' + inputs: + - '@globs(sources)' + - '@globs(assets)' + - 'vite.config.ts' + local: true + platform: node + deps: + - ~:build-vite + options: + runInCI: false # Library mode commands build-library: diff --git a/applications/client/src/env.d.ts b/applications/client/src/env.d.ts index 483d73bf..8e52e81f 100644 --- a/applications/client/src/env.d.ts +++ b/applications/client/src/env.d.ts @@ -12,3 +12,8 @@ declare module '*?worker' { // eslint-disable-next-line import/no-default-export export default workerConstructor; } + +declare global { + // eslint-disable-next-line no-var,vars-on-top + var Cypress: any | undefined; +} diff --git a/applications/client/src/store/auth.ts b/applications/client/src/store/auth.ts index 6b1c72d6..9564ecda 100644 --- a/applications/client/src/store/auth.ts +++ b/applications/client/src/store/auth.ts @@ -9,7 +9,7 @@ export class Auth extends ExtendedModel(RedEyeModel, { promptAuth: prop(false).withSetter(), hasClickedAuthDialog: prop(false).withSetter(), user: prop(() => localStorage.getItem('user') ?? ''), - serverUrl: prop(() => (import.meta.env.DEV ? defaultServerUrl : '')), + serverUrl: prop(() => (import.meta.env.DEV || globalThis.Cypress ? defaultServerUrl : '')), }) { get userName(): string | null { return localStorage.getItem('user'); diff --git a/applications/redeye-e2e/moon.yml b/applications/redeye-e2e/moon.yml index 3850ae6e..b8d9fa17 100644 --- a/applications/redeye-e2e/moon.yml +++ b/applications/redeye-e2e/moon.yml @@ -31,7 +31,7 @@ tasks: open-cy: command: 'noop' deps: - - 'client:start-dev' + - 'client:preview-vite' - 'server:start-dev' - 'redeye-e2e:start' local: true diff --git a/applications/redeye-e2e/src/integration/e2e/redteam/graphql/hide-beacon-bulk.cy.js b/applications/redeye-e2e/src/integration/e2e/redteam/graphql/hide-beacon-bulk.cy.js index 49a03906..f1c6ff73 100644 --- a/applications/redeye-e2e/src/integration/e2e/redteam/graphql/hide-beacon-bulk.cy.js +++ b/applications/redeye-e2e/src/integration/e2e/redteam/graphql/hide-beacon-bulk.cy.js @@ -62,13 +62,12 @@ describe('Hide a Beacon using GraphQL', () => { cy.clickBeaconsTab(); const beacs = []; cy.get('[cy-test=beacons-row]') - .each(($li) => beacs.push($li.text())) + .each(($li) => + beacs.push(`${$li.find('[cy-test=beacon-time]').text()}${$li.find('[cy-test=beacon-display-name]').text()}`) + ) .then(() => { cy.log(beacs.join(', ')); - cy.wrap(beacs).should('deep.equal', [ - '08/17—08/17500978634 · SYSTEM *SYSTEM *8', - '08/17—08/171042756528 · user01user0114', - ]); + cy.wrap(beacs).should('deep.equal', ['08/17—08/17500978634 · SYSTEM *', '08/17—08/171042756528 · user01']); }); }); diff --git a/applications/redeye-e2e/src/integration/e2e/redteam/graphql/hide-beacon.cy.js b/applications/redeye-e2e/src/integration/e2e/redteam/graphql/hide-beacon.cy.js index de52acf5..a29fb8e5 100644 --- a/applications/redeye-e2e/src/integration/e2e/redteam/graphql/hide-beacon.cy.js +++ b/applications/redeye-e2e/src/integration/e2e/redteam/graphql/hide-beacon.cy.js @@ -48,14 +48,16 @@ describe('Hide a Beacon using GraphQL', () => { cy.clickBeaconsTab(); const beacs = []; cy.get('[cy-test=beacons-row]') - .each(($li) => beacs.push($li.text())) + .each(($li) => + beacs.push(`${$li.find('[cy-test=beacon-time]').text()}${$li.find('[cy-test=beacon-display-name]').text()}`) + ) .then(() => { // cy.log(beacs.join(', ')); cy.wrap(beacs).should('deep.equal', [ - '08/17—08/17330588776 · jdoejdoe9', - '08/17—08/172146137244 · jdoe *jdoe *9', - '08/17—08/17500978634 · SYSTEM *SYSTEM *8', - '08/17—08/171042756528 · user01user0114', + '08/17—08/17330588776 · jdoe', + '08/17—08/172146137244 · jdoe *', + '08/17—08/17500978634 · SYSTEM *', + '08/17—08/171042756528 · user01', ]); }); }); diff --git a/applications/redeye-e2e/src/integration/e2e/redteam/uploadRawLogs.cy.js b/applications/redeye-e2e/src/integration/e2e/redteam/uploadRawLogs.cy.js index 5fff4499..7f23ddbd 100644 --- a/applications/redeye-e2e/src/integration/e2e/redteam/uploadRawLogs.cy.js +++ b/applications/redeye-e2e/src/integration/e2e/redteam/uploadRawLogs.cy.js @@ -17,7 +17,7 @@ describe('Upload raw log', () => { cy.reload(); - cy.get('[cy-test=beacon-count]').invoke('text').should('contain', '4'); + cy.get('[cy-test=beacon-count]', { timeout: 25000 }).invoke('text').should('contain', '3'); cy.get('[cy-test=command-count]').invoke('text').should('contain', '7'); }); diff --git a/applications/server/src/store/command-resolvers.ts b/applications/server/src/store/command-resolvers.ts index 22a7be59..88b107ab 100644 --- a/applications/server/src/store/command-resolvers.ts +++ b/applications/server/src/store/command-resolvers.ts @@ -211,35 +211,17 @@ export class CommandTypeCountResolvers { @Arg('hidden', () => Boolean, { defaultValue: false, nullable: true, description: 'Should show hidden values' }) hidden: boolean = false ): Promise { - const em = await connectToProjectEmOrFail(campaignId, ctx); - const commands = await em.find(Command, beaconHidden(hidden), { - populate: ['commandGroups', 'commandGroups.annotations'], - }); - const countObj = commands.reduce>((acc, current) => { - if (acc[current.inputText]) { - acc[current.inputText] = { - count: acc[current.inputText].count + 1, - beaconIds: [...acc[current.inputText].beaconIds, current.beacon.id], - commentsCount: current.commandGroups?.getItems().reduce((commentsCountItem, group) => { - if (!commentsCountItem.commandGroupIds.includes(group.id)) { - return { - commandGroupIds: [...commentsCountItem.commandGroupIds, group.id], - count: commentsCountItem.count + (group?.annotations?.count() ?? 0), - }; - } else { - return { - commandGroupIds: [...commentsCountItem.commandGroupIds, group.id], - count: commentsCountItem.count, - }; - } - }, acc[current.inputText].commentsCount), - }; - } else { - acc[current.inputText] = { - count: 1, - beaconIds: [current.beacon.id], - commentsCount: current.commandGroups?.getItems().reduce( - (commentsCountItem, group) => { + try { + const em = await connectToProjectEmOrFail(campaignId, ctx); + const commands = await em.find(Command, beaconHidden(hidden), { + populate: ['commandGroups', 'commandGroups.annotations'], + }); + const countObj = commands.reduce>((acc, current) => { + if (acc[current.inputText]) { + acc[current.inputText] = { + count: acc[current.inputText].count + 1, + beaconIds: [...acc[current.inputText].beaconIds, current.beacon.id], + commentsCount: current.commandGroups?.getItems().reduce((commentsCountItem, group) => { if (!commentsCountItem.commandGroupIds.includes(group.id)) { return { commandGroupIds: [...commentsCountItem.commandGroupIds, group.id], @@ -251,21 +233,44 @@ export class CommandTypeCountResolvers { count: commentsCountItem.count, }; } - }, - { commandGroupIds: [], count: 0 } as CommentsCountItem - ), - }; - } - return acc; - }, {}); + }, acc[current.inputText].commentsCount), + }; + } else { + acc[current.inputText] = { + count: 1, + beaconIds: [current.beacon.id], + commentsCount: current.commandGroups?.getItems().reduce( + (commentsCountItem, group) => { + if (!commentsCountItem.commandGroupIds.includes(group.id)) { + return { + commandGroupIds: [...commentsCountItem.commandGroupIds, group.id], + count: commentsCountItem.count + (group?.annotations?.count() ?? 0), + }; + } else { + return { + commandGroupIds: [...commentsCountItem.commandGroupIds, group.id], + count: commentsCountItem.count, + }; + } + }, + { commandGroupIds: [], count: 0 } as CommentsCountItem + ), + }; + } + return acc; + }, {}); - return Object.entries(countObj).map(([text, item]) => ({ - id: text, - text, - count: item.count, - beaconsCount: new Set(item.beaconIds).size, - commentsCount: item.commentsCount.count, - })) as CommandTypeCount[]; + return Object.entries(countObj || {}).map(([text, item]) => ({ + id: text, + text, + count: item.count, + beaconsCount: new Set(item.beaconIds).size, + commentsCount: item.commentsCount.count, + })) as CommandTypeCount[]; + } catch (e) { + console.error(e); + return []; + } } } diff --git a/package.json b/package.json index 8096088b..28feb968 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "start:client": "yarn moon run @redeye/client:start-dev", "start:server": "yarn moon run @redeye/server:start-dev", "start:dev": "yarn moon run @redeye/server:start-dev @redeye/client:start-dev", + "start:test-app": "yarn moon run @redeye/server:start-dev @redeye/client:preview-vite", "start:graph": "yarn moon run @redeye/graph:start-vite", "start:landing": "yarn moon run @redeye/landing:start-astro", "combine:reports": "jrm dist/applications/redeye-e2e/results/combined-report.xml \"dist/applications/redeye-e2e/results/*.xml\"",