Files
its-a-feature-Mythic/MythicReactUI/src/components/pages/Payloads/Payloads.js
T

343 lines
10 KiB
JavaScript

import React from 'react';
import { PayloadsTable } from './PayloadsTable';
import {useMutation, gql, useSubscription, useQuery, useLazyQuery} from '@apollo/client';
import { snackActions } from '../../utilities/Snackbar';
import {getSkewedNow} from "../../utilities/Time";
export const payloadFragment = gql`
fragment payloadData on payload {
build_message
build_phase
build_stderr
callback_alert
callback_allowed
id
uuid
description
deleted
auto_generated
payloadtype {
id
name
}
payload_build_steps(order_by: {step_number: asc}) {
step_name
step_number
step_success
step_skip
start_time
end_time
step_stdout
step_stderr
id
}
tags {
tagtype {
name
color
id
}
id
}
filemetum {
agent_file_id
filename_text
id
tags {
tagtype {
name
color
id
}
id
}
}
payloadc2profiles {
c2profile {
running
name
is_p2p
container_running
}
}
}
`;
const SUB_Payloads = gql`
${payloadFragment}
subscription SubPayloadsQuery($now: timestamp!) {
payload_stream(batch_size: 10, cursor: {initial_value: {timestamp: $now}, ordering: ASC}) {
...payloadData
}
}
`;
const PayloadsQuery = gql`
${payloadFragment}
query PayloadsQuery($offset: Int!, $limit: Int!, $showDeleted: Boolean!, $showAutogenerated: Boolean!) {
payload(order_by: {id: desc}, offset: $offset, limit: $limit, where: {auto_generated: {_eq: $showAutogenerated}, deleted: {_eq: $showDeleted}}) {
...payloadData
}
payload_aggregate(where: {auto_generated: {_eq: $showAutogenerated}, deleted: {_eq: $showDeleted}}) {
aggregate {
count
}
}
}
`;
export const payloadsDelete = gql`
mutation PayloadsDeletePayloadMutation($payload_uuid: String!) {
updatePayload(payload_uuid: $payload_uuid, deleted: true) {
status
error
id
deleted
}
}
`;
export const payloadsCallbackAlert = gql`
mutation PayloadsCallbackAlertMutation($payload_uuid: String!, $callback_alert: Boolean!) {
updatePayload(callback_alert: $callback_alert, payload_uuid: $payload_uuid) {
id
callback_alert
status
error
}
}
`;
export const restorePayloadMutation = gql`
mutation RestorePayloadToUndeleted($payload_uuid: String!){
updatePayload(deleted: false, payload_uuid: $payload_uuid) {
id
deleted
status
error
}
}
`;
export const payloadsCallbackAllowed = gql`
mutation PayloadsCallbackAllowedMutation($payload_uuid: String!, $callback_allowed: Boolean!) {
updatePayload(callback_allowed: $callback_allowed, payload_uuid: $payload_uuid) {
id
callback_allowed
status
error
}
}
`;
export function Payloads(props){
const [fromNow, setFromNow] = React.useState((getSkewedNow()).toISOString());
const [payloads, setPayloads] = React.useState([]);
const [pageData, setPageData] = React.useState({
"totalCount": 0,
"fetchLimit": 20,
"showDeleted": false,
"showAutogenerated": false,
});
const mountedRef = React.useRef(true);
const [openBackdrop, setOpenBackdrop] = React.useState(true);
useSubscription(SUB_Payloads, {
variables: {now: fromNow},
fetchPolicy: "no-cache",
onData: ({data}) => {
//console.log("got data", subscriptionData.data.payload_stream)
if(!mountedRef.current){
return null;
}
const updated = data.data.payload_stream.reduce( (prev, cur) => {
const index = prev.findIndex( (p) => p.id === cur.id );
if(index > -1){
prev[index] = {...cur};
return [...prev];
}else{
return [cur, ...prev];
}
}, [...payloads])
updated.sort( (a,b) => a.id > b.id ? -1 : 1);
setPayloads(updated);
},
onCompleted: (data) => {
console.log("completed")
},
onError: (data) => {
snackActions.warning("Failed to get payloads");
console.log(data);
}
});
useQuery(PayloadsQuery, {
variables: {offset: 0, limit: pageData.fetchLimit, showDeleted: false, showAutogenerated: false},
fetchPolicy: "no-cache",
onCompleted: (data) => {
let tempPageData = {...pageData};
tempPageData.totalCount = data.payload_aggregate.aggregate.count;
setPageData(tempPageData);
setPayloads(data.payload);
setOpenBackdrop(false);
},
onError: (data) => {
}
})
const [fetchNewPage] = useLazyQuery(PayloadsQuery, {
onCompleted: (data) => {
snackActions.dismiss();
let tempPageData = {...pageData};
tempPageData.totalCount = data.payload_aggregate.aggregate.count;
setPageData(tempPageData);
setPayloads(data.payload);
setOpenBackdrop(false);
},
onError: (data) => {
}
})
const onChangePage = (event, value) => {
snackActions.info("Fetching page...");
setOpenBackdrop(true);
fetchNewPage({variables: {offset: (value - 1) * pageData.fetchLimit, limit: pageData.fetchLimit, showDeleted: pageData.showDeleted, showAutogenerated: pageData.showAutogenerated}})
}
const [deletePayload] = useMutation(payloadsDelete, {
onCompleted: (data) => {
if(data.updatePayload.status === "success"){
const updated = payloads.map( (p) => {
if(data.updatePayload.id === p.id){
return {...p, deleted: true};
}else{
return {...p}
}
});
setPayloads(updated);
snackActions.success("Successfully deleted");
}else{
snackActions.error(data.updatePayload.error);
}
},
onError: (data) => {
snackActions.warning("Failed to delete payload");
console.log(data);
}
});
const [restorePayload] = useMutation(restorePayloadMutation, {
onCompleted: (data) => {
const updated = payloads.map( (payload) => {
if(payload.id === data.updatePayload.id){
return {...payload, ...data.updatePayload};
}else{
return {...payload};
}
});
setPayloads(updated);
if(data.updatePayload.deleted === false){
snackActions.success("Successfully marked payload as not deleted");
}
},
onError: (data) => {
snackActions.warning("Failed to mark as not deleted");
console.log(data);
}
});
const [callbackAlert] = useMutation(payloadsCallbackAlert, {
onCompleted: (data) => {
const updated = payloads.map( (payload) => {
if(payload.id === data.updatePayload.id){
return {...payload, ...data.updatePayload};
}else{
return {...payload};
}
});
if(data.updatePayload.callback_alert){
snackActions.success("Now Alerting on New Callbacks");
}else{
snackActions.success("No Longer Alerting on New Callbacks");
}
setPayloads(updated);
},
onError: (data) => {
snackActions.warning("Failed to update callback alerting status");
console.log(data);
}
});
const [callbackAllowed] = useMutation(payloadsCallbackAllowed, {
onCompleted: (data) => {
const updated = payloads.map( (payload) => {
if(payload.id === data.updatePayload.id){
return {...payload, ...data.updatePayload};
}else{
return {...payload};
}
});
if(data.updatePayload.callback_allowed){
snackActions.success("Now Allowing New Callbacks from this Payload");
}else{
snackActions.success("No Longer Allowing New Callbacks from this Payload");
}
setPayloads(updated);
},
onError: (data) => {
snackActions.warning("Failed to update callback alerting status");
console.log(data);
}
});
const onDeletePayload = (payload_uuid) => {
deletePayload({variables: {payload_uuid}});
}
const onUpdateCallbackAlert = (payload_uuid, callback_alert) => {
callbackAlert({
variables: {payload_uuid, callback_alert}
});
}
const onRestorePayload = (payload_uuid) => {
restorePayload({
variables: {payload_uuid}
})
}
const onChangeShowDeleted = (showDeleted) => {
setPageData({...pageData, showDeleted: showDeleted});
if(showDeleted){
snackActions.info("Fetching deleted payloads...");
} else {
snackActions.info("Hiding deleted payloads...");
}
fetchNewPage({variables: {offset:0, limit: pageData.fetchLimit, showDeleted: showDeleted, showAutogenerated: pageData.showAutogenerated}});
}
const onChangeShowAutogenerated = (showAutogenerated) => {
setPageData({...pageData, showAutogenerated: showAutogenerated});
if(showAutogenerated){
snackActions.info("Fetching auto generated payloads...");
} else {
snackActions.info("Hiding auto generated payloads...");
}
fetchNewPage({variables: {offset:0, limit: pageData.fetchLimit, showDeleted: pageData.showDeleted, showAutogenerated: showAutogenerated}});
}
const onCallbacksAllowedChanged = (payload_uuid, callback_allowed) => {
callbackAllowed({variables: {payload_uuid, callback_allowed}});
}
React.useEffect( () => {
return() => {
mountedRef.current = false;
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
return (
<div style={{display: "flex", height: "100%", flexDirection: "column", position: "relative"}}>
<PayloadsTable pageData={pageData} me={props.me}
openBackdrop={openBackdrop}
onDeletePayload={onDeletePayload}
onUpdateCallbackAlert={onUpdateCallbackAlert}
payload={payloads}
onRestorePayload={onRestorePayload}
onChangePage={onChangePage}
onChangeShowDeleted={onChangeShowDeleted}
onCallbacksAllowedChanged={onCallbacksAllowedChanged}
onChangeShowAutogenerated={onChangeShowAutogenerated}
/>
</div>
);
}