@retracedhq/retraced
Advanced tools
Comparing version 0.6.2 to 0.6.3
import { NewEventRecord } from "./retraced-js"; | ||
export interface EventFields { | ||
[key: string]: string; | ||
} | ||
export interface Target { | ||
@@ -7,5 +10,3 @@ id: string; | ||
type?: string; | ||
fields?: { | ||
[key: string]: string; | ||
}; | ||
fields?: EventFields; | ||
} | ||
@@ -16,5 +17,3 @@ export interface Actor { | ||
href?: string; | ||
fields?: { | ||
[key: string]: string; | ||
}; | ||
fields?: EventFields; | ||
} | ||
@@ -25,7 +24,10 @@ export interface Group { | ||
} | ||
export interface Event { | ||
interface EventCreation { | ||
created?: Date; | ||
} | ||
export type CRUD = "c" | "r" | "u" | "d"; | ||
export interface EventInternal { | ||
action: string; | ||
group?: Group; | ||
crud?: string; | ||
created?: Date; | ||
crud?: CRUD; | ||
actor?: Actor; | ||
@@ -37,11 +39,14 @@ target?: Target; | ||
is_anonymous?: boolean; | ||
fields?: { | ||
[key: string]: string; | ||
}; | ||
fields?: EventFields; | ||
external_id?: string; | ||
metadata?: EventFields; | ||
} | ||
export interface Event extends EventCreation, EventInternal { | ||
} | ||
export declare function verifyHash(event: Event, newEvent: NewEventRecord): string; | ||
export declare function computeHash(event: Event, newEvent: NewEventRecord): { | ||
export declare function computeHash(event: Event, id: string): { | ||
hashResult: string; | ||
hashTarget: string; | ||
}; | ||
export declare function buildHashTarget(event: Event, newEvent: NewEventRecord): string; | ||
export declare function buildHashTarget(event: Event, id: string): string; | ||
export {}; |
@@ -13,3 +13,3 @@ "use strict"; | ||
function verifyHash(event, newEvent) { | ||
const { hashResult, hashTarget } = computeHash(event, newEvent); | ||
const { hashResult, hashTarget } = computeHash(event, newEvent.id); | ||
if (hashResult !== newEvent.hash) { | ||
@@ -21,3 +21,6 @@ throw new Error(`hash mismatch, local=${hashResult}, remote=${newEvent.hash}, target=${hashTarget}`); | ||
exports.verifyHash = verifyHash; | ||
function computeHash(event, newEvent) { | ||
function computeHash(event, id) { | ||
if (!id) { | ||
throw new Error("Canonicalization failed: missing required event attribute 'id'"); | ||
} | ||
for (const fieldName of requiredFields) { | ||
@@ -32,6 +35,6 @@ if (_.isEmpty(_.get(event, fieldName))) { | ||
if (missingSubfield) { | ||
throw new Error(`Canonicalization failed: attribute '${requiredSubfield}' is required if '${fieldName}' is present.`); | ||
throw new Error(`Canonicalization failed: missing attribute '${requiredSubfield}' which is required when '${fieldName}' is present.`); | ||
} | ||
} | ||
const hashTarget = buildHashTarget(event, newEvent); | ||
const hashTarget = buildHashTarget(event, id); | ||
const hasher = crypto.createHash("sha256"); | ||
@@ -43,5 +46,5 @@ hasher.update(hashTarget); | ||
exports.computeHash = computeHash; | ||
function buildHashTarget(event, newEvent) { | ||
function buildHashTarget(event, id) { | ||
let canonicalString = ""; | ||
canonicalString += `${encodePassOne(newEvent.id)}:`; | ||
canonicalString += `${encodePassOne(id)}:`; | ||
canonicalString += `${encodePassOne(event.action)}:`; | ||
@@ -66,2 +69,15 @@ canonicalString += _.isEmpty(event.target) ? ":" : `${encodePassOne(event.target.id)}:`; | ||
} | ||
if (event.external_id) { | ||
canonicalString += `:${encodePassOne(event.external_id)}`; | ||
} | ||
if (event.metadata) { | ||
canonicalString += ":"; | ||
const sortedKeys = _.keys(event.metadata).sort(); | ||
for (const key of sortedKeys) { | ||
const value = event.metadata[key]; | ||
const encodedKey = encodePassTwo(encodePassOne(key)); | ||
const encodedValue = encodePassTwo(encodePassOne(value)); | ||
canonicalString += `${encodedKey}=${encodedValue};`; | ||
} | ||
} | ||
return canonicalString; | ||
@@ -71,6 +87,6 @@ } | ||
function encodePassOne(valueIn) { | ||
return valueIn.replace(/%/g, "%25").replace(/:/g, "%3A"); | ||
return valueIn ? (valueIn.replace ? valueIn.replace(/%/g, "%25").replace(/:/g, "%3A") : valueIn) : valueIn; | ||
} | ||
function encodePassTwo(valueIn) { | ||
return valueIn.replace(/=/g, "%3D").replace(/;/g, "%3B"); | ||
return valueIn ? (valueIn.replace ? valueIn.replace(/=/g, "%3D").replace(/;/g, "%3B") : valueIn) : valueIn; | ||
} |
@@ -44,2 +44,3 @@ export interface GraphQLSearchData { | ||
location?: string; | ||
external_id?: string; | ||
} | ||
@@ -84,2 +85,4 @@ export interface EventNodeMask { | ||
raw?: boolean; | ||
external_id?: boolean; | ||
metadata?: boolean; | ||
} | ||
@@ -132,2 +135,4 @@ export interface FieldItem { | ||
raw?: string; | ||
external_id?: string; | ||
metadata?: FieldItem[]; | ||
} | ||
@@ -176,2 +181,6 @@ export interface EventNode { | ||
raw?: string; | ||
external_id?: string; | ||
metadata?: { | ||
[key: string]: string; | ||
}; | ||
} | ||
@@ -178,0 +187,0 @@ export declare const formatRawEventNode: (node: RawEventNode) => EventNode; |
@@ -128,6 +128,2 @@ "use strict"; | ||
(mask.target.id || mask.target.name || mask.target.href || mask.target.type || mask.target.fields)) { | ||
const fields = `fields { | ||
key | ||
value | ||
}`; | ||
target = `target { | ||
@@ -186,2 +182,9 @@ ${mask.target.id ? "id" : ""} | ||
${mask.raw ? "raw" : ""} | ||
${mask.external_id ? "external_id" : ""} | ||
${mask.metadata | ||
? `metadata { | ||
key | ||
value | ||
}` | ||
: ""} | ||
} | ||
@@ -188,0 +191,0 @@ } |
@@ -18,2 +18,3 @@ import { Event } from "./event"; | ||
constructor(config: Config); | ||
private mapping; | ||
reportEvent(event: Event): Promise<string>; | ||
@@ -20,0 +21,0 @@ reportEvents(events: Event[]): Promise<string[]>; |
@@ -16,5 +16,4 @@ "use strict"; | ||
} | ||
async reportEvent(event) { | ||
const { endpoint, apiKey, projectId } = this.config; | ||
const requestBody = { | ||
mapping(event) { | ||
return { | ||
action: event.action, | ||
@@ -33,3 +32,9 @@ group: event.group, | ||
version: this.config.version, | ||
external_id: event.external_id, | ||
metadata: event.metadata, | ||
}; | ||
} | ||
async reportEvent(event) { | ||
const { endpoint, apiKey, projectId } = this.config; | ||
const requestBody = this.mapping(event); | ||
let newEvent; | ||
@@ -61,17 +66,3 @@ try { | ||
const requestBody = _.map(events, (event) => { | ||
return { | ||
action: event.action, | ||
group: event.group, | ||
crud: event.crud, | ||
created: event.created, | ||
actor: event.actor, | ||
target: event.target, | ||
source_ip: event.source_ip, | ||
description: event.description, | ||
is_failure: event.is_failure, | ||
is_anonymous: event.is_anonymous, | ||
fields: event.fields, | ||
component: this.config.component, | ||
version: this.config.version, | ||
}; | ||
return this.mapping(event); | ||
}); | ||
@@ -78,0 +69,0 @@ let newEvents; |
@@ -105,3 +105,3 @@ "use strict"; | ||
const expected = "kfbr392:even.more.of.a.test:some_object01234:user@domain.xyz:::1:0:abc%3Dxyz=nothing special;"; | ||
(0, chai_1.expect)(Retraced.buildHashTarget(testEvent, fakeNew)).to.equal(expected); | ||
(0, chai_1.expect)(Retraced.buildHashTarget(testEvent, fakeNew.id)).to.equal(expected); | ||
} | ||
@@ -108,0 +108,0 @@ "should generate a GraphQL query string requesting all fields"() { |
{ | ||
"name": "@retracedhq/retraced", | ||
"author": "Replicated Inc., BoxyHQ Inc.", | ||
"version": "0.6.2", | ||
"version": "0.6.3", | ||
"engines": { | ||
@@ -40,5 +40,5 @@ "node": ">=14.x" | ||
"@types/chai-as-promised": "7.1.5", | ||
"@types/lodash": "4.14.191", | ||
"@types/lodash": "4.14.192", | ||
"@types/mocha": "10.0.1", | ||
"@types/node": "18.11.18", | ||
"@types/node": "18.15.11", | ||
"@types/axios": "0.14.0", | ||
@@ -49,6 +49,6 @@ "chai": "4.3.7", | ||
"tslint": "6.1.3", | ||
"typescript": "4.9.5" | ||
"typescript": "5.0.4" | ||
}, | ||
"dependencies": { | ||
"axios": "1.3.0", | ||
"axios": "1.3.5", | ||
"lodash": "4.17.21" | ||
@@ -55,0 +55,0 @@ }, |
49152
1110
+ Addedaxios@1.3.5(transitive)
- Removedaxios@1.3.0(transitive)
Updatedaxios@1.3.5