@retracedhq/retraced
Version:
The official NodeJS client for interacting with the Retraced audit logging API.
230 lines (229 loc) • 7.24 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.stringifyStructuredQuery = exports.graphQLQuery = exports.formatRawEventNode = exports.EventsConnection = void 0;
const _ = require("lodash");
const axios_1 = require("axios");
class EventsConnection {
constructor(url, authorization, query, mask, pageSize) {
this.url = url;
this.authorization = authorization;
this.query = query;
this.mask = mask;
this.pageSize = pageSize;
this.cursors = [];
this.totalCount = 0;
}
totalPages() {
return Math.ceil(this.totalCount / this.pageSize);
}
hasPreviousPage() {
return this.currentPageNumber > 1;
}
hasNextPage() {
return this.currentPageNumber < this.totalPages();
}
async init() {
this.cursors.push("");
await this.call();
}
async nextPage() {
await this.call();
}
async call() {
const cursor = _.last(this.cursors);
const body = {
query: (0, exports.graphQLQuery)(this.mask),
variables: {
query: (0, exports.stringifyStructuredQuery)(this.query),
last: this.pageSize,
before: cursor,
},
};
let searchData;
try {
const rsp = await axios_1.default.post(this.url, body, {
headers: {
Accept: "application/json",
Authorization: this.authorization,
},
});
searchData = rsp.data;
}
catch (err) {
const status = err.response ? err.response.status : 500;
const statusText = err.response ? err.response.statusText : "Unknown";
throw new Error(`Unexpected HTTP response: ${status} ${statusText}`);
}
const { data } = searchData;
this.totalCount = data.search.totalCount;
this.currentResults = data.search.edges.map((edge) => {
return (0, exports.formatRawEventNode)(edge.node);
});
this.currentPageNumber = this.cursors.length;
if (data.search.pageInfo.hasPreviousPage) {
this.cursors.push(_.last(data.search.edges).cursor);
}
}
}
exports.EventsConnection = EventsConnection;
const fieldsMap = (fieldsList) => {
const fields = {};
return fieldsList.reduce((accm, field) => {
accm[field.key] = field.value;
return accm;
}, fields);
};
const formatRawEventNode = (node) => {
const conversions = {};
if (node.received) {
conversions.received = new Date(node.received);
}
if (node.created) {
conversions.created = new Date(node.created);
}
if (node.canonical_time) {
conversions.canonical_time = new Date(node.canonical_time);
}
if (node.fields) {
conversions.fields = fieldsMap(node.fields);
}
if (node.actor && node.actor.fields) {
conversions.actor = _.extend(node.actor, {
fields: fieldsMap(node.actor.fields),
});
}
if (node.target && node.target.fields) {
conversions.target = _.extend(node.target, {
fields: fieldsMap(node.target.fields),
});
}
return _.extend(node, conversions);
};
exports.formatRawEventNode = formatRawEventNode;
const graphQLQuery = (mask) => {
let group = "";
if (mask.group && (mask.group.id || mask.group.name)) {
group = `group {
${mask.group.id ? "id" : ""}
${mask.group.name ? "name" : ""}
}`;
}
let actor = "";
if (mask.actor && (mask.actor.id || mask.actor.name || mask.actor.href || mask.actor.fields)) {
actor = `actor {
${mask.actor.id ? "id" : ""}
${mask.actor.name ? "name" : ""}
${mask.actor.href ? "href" : ""}
${mask.actor.fields
? `fields {
key
value
}`
: ""}
}`;
}
let target = "";
if (mask.target &&
(mask.target.id || mask.target.name || mask.target.href || mask.target.type || mask.target.fields)) {
target = `target {
${mask.target.id ? "id" : ""}
${mask.target.name ? "name" : ""}
${mask.target.href ? "href" : ""}
${mask.target.type ? "type" : ""}
${mask.target.fields
? `fields {
key
value
}`
: ""}
}`;
}
let display = "";
if (mask.display && mask.display.markdown) {
display = `display {
markdown
}`;
}
const q = `query Search($query: String!, $last: Int, $before: String) {
search(query: $query, last: $last, before: $before) {
totalCount,
pageInfo {
hasPreviousPage
}
edges {
cursor
node {
${mask.id ? "id" : ""}
${mask.action ? "action" : ""}
${mask.description ? "description" : ""}
${group}
${actor}
${target}
${mask.crud ? "crud" : ""}
${display}
${mask.received ? "received" : ""}
${mask.created ? "created" : ""}
${mask.canonical_time ? "canonical_time" : ""}
${mask.is_failure ? "is_failure" : ""}
${mask.is_anonymous ? "is_anonymous" : ""}
${mask.source_ip ? "country" : ""}
${mask.loc_subdiv1 ? "loc_subdiv1" : ""}
${mask.loc_subdiv2 ? "loc_subdiv2" : ""}
${mask.component ? "component" : ""}
${mask.version ? "version" : ""}
${mask.fields
? `fields {
key
value
}`
: ""}
${mask.external_id ? "external_id" : ""}
${mask.metadata
? `metadata {
key
value
}`
: ""}
}
}
}
}`;
return q
.split(/\n/)
.filter((line) => line.trim())
.join("\n");
};
exports.graphQLQuery = graphQLQuery;
const stringifyStructuredQuery = (queryObj) => {
const params = [];
if (queryObj.action) {
params.push(`action:"${queryObj.action}"`);
}
if (queryObj.crud) {
params.push(`crud:${queryObj.crud}`);
}
if (queryObj.received_start || queryObj.received_end) {
const start = queryObj.received_start ? queryObj.received_start.toISOString() : "";
const end = queryObj.received_end ? queryObj.received_end.toISOString() : "";
params.push(`received:${start},${end}`);
}
if (queryObj.created_start || queryObj.created_end) {
const start = queryObj.created_start ? queryObj.created_start.toISOString() : "";
const end = queryObj.created_end ? queryObj.created_end.toISOString() : "";
params.push(`created:${start},${end}`);
}
if (queryObj.actor_name) {
params.push(`actor.name:"${queryObj.actor_name}"`);
}
if (queryObj.actor_id) {
params.push(`actor.id:${queryObj.actor_id}`);
}
if (queryObj.description) {
params.push(`description:"${queryObj.description}"`);
}
if (queryObj.location) {
params.push(`location:"${queryObj.location}"`);
}
return params.join(" ");
};
exports.stringifyStructuredQuery = stringifyStructuredQuery;