Skip to content

Commit

Permalink
Merge branch 'master' into use-full-relative-paths
Browse files Browse the repository at this point in the history
  • Loading branch information
wolfy1339 authored Jun 21, 2021
2 parents 216efe4 + 7d6a81d commit 8d7a936
Show file tree
Hide file tree
Showing 12 changed files with 1,277 additions and 1,709 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ webhooks.verify(eventPayload, signature);
eventPayload
</code>
<em>
(Object)
(Object or String)
</em>
</td>
<td>
Expand Down Expand Up @@ -260,7 +260,7 @@ webhooks.verifyAndReceive({ id, name, payload, signature });
payload
</code>
<em>
Object
Object or String
</em>
</td>
<td>
Expand Down
2,783 changes: 1,103 additions & 1,680 deletions package-lock.json

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,23 @@
"build": "pika build",
"coverage": "jest --coverage && open coverage/lcov-report/index.html",
"generate-types": "ts-node --transpile-only scripts/generate-types.ts",
"lint": "prettier --check 'src/**/*.{ts,json}' 'scripts/**/*' 'test/**/*' README.md package.json",
"lint:fix": "prettier --write 'src/**/*.{ts,json}' 'scripts/**/*' 'test/**/*' README.md package.json",
"lint": "prettier --check 'src/**/*.{ts,json}' 'scripts/**/*' 'test/**/*.ts' README.md package.json",
"lint:fix": "prettier --write 'src/**/*.{ts,json}' 'scripts/**/*' 'test/**/*.ts' README.md package.json",
"pretest": "npm run -s lint",
"test": "jest --coverage",
"validate:ts": "tsc --noEmit --noImplicitAny --target es2020 --esModuleInterop --moduleResolution node test/typescript-validate.ts"
},
"prettier": {},
"dependencies": {
"@octokit/request-error": "^2.0.2",
"@octokit/webhooks-methods": "^1.0.0",
"@octokit/webhooks-types": "3.75.2",
"@octokit/webhooks-methods": "^2.0.0",
"@octokit/webhooks-types": "4.0.1",
"aggregate-error": "^3.1.0"
},
"devDependencies": {
"@jest/types": "^27.0.0",
"@octokit/tsconfig": "^1.0.1",
"@octokit/webhooks-schemas": "3.75.2",
"@octokit/webhooks-schemas": "4.0.1",
"@pika/pack": "^0.5.0",
"@pika/plugin-build-node": "^0.9.2",
"@pika/plugin-build-web": "^0.9.2",
Expand All @@ -41,7 +41,7 @@
"get-port": "^5.0.0",
"jest": "^27.0.0",
"node-fetch": "^2.6.1",
"prettier": "2.3.0",
"prettier": "2.3.1",
"prettier-plugin-packagejson": "^2.2.9",
"semantic-release": "^17.0.0",
"ts-jest": "^27.0.0",
Expand Down
10 changes: 7 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { sign, verify } from "@octokit/webhooks-methods";

import { createLogger } from "./createLogger.js";
import { createEventHandler } from "./event-handler/index.js";
import { sign } from "./sign.js";
import { verify } from "./verify.js";
import { verifyAndReceive } from "./verify-and-receive.js";
import {
EmitterWebhookEvent,
Expand All @@ -11,6 +11,8 @@ import {
State,
WebhookError,
WebhookEventHandlerError,
EmitterWebhookEventWithStringPayloadAndSignature,
EmitterWebhookEventWithSignature,
} from "./types";

export { createNodeMiddleware } from "./middleware/node/index.js";
Expand All @@ -34,7 +36,9 @@ class Webhooks<TTransformed = unknown> {
) => void;
public receive: (event: EmitterWebhookEvent) => Promise<void>;
public verifyAndReceive: (
options: EmitterWebhookEvent & { signature: string }
options:
| EmitterWebhookEventWithStringPayloadAndSignature
| EmitterWebhookEventWithSignature
) => Promise<void>;

constructor(options: Options<TTransformed> & { secret: string }) {
Expand Down
13 changes: 13 additions & 0 deletions src/sign.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { sign as signMethod } from "@octokit/webhooks-methods";

import { toNormalizedJsonString } from "./to-normalized-json-string";

export async function sign(
secret: string,
payload: string | object
): Promise<any> {
return signMethod(
secret,
typeof payload === "string" ? payload : toNormalizedJsonString(payload)
);
}
9 changes: 9 additions & 0 deletions src/to-normalized-json-string.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* GitHub sends its JSON with an indentation of 2 spaces and a line break at the end
*/
export function toNormalizedJsonString(payload: object) {
const payloadString = JSON.stringify(payload, null, 2) + "\n";
return payloadString.replace(/[^\\]\\u[\da-f]{4}/g, (s) => {
return s.substr(0, 3) + s.substr(3).toUpperCase();
});
}
11 changes: 11 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ export type EmitterWebhookEvent<
}
: BaseWebhookEvent<Extract<TEmitterEvent, WebhookEventName>>;

export type EmitterWebhookEventWithStringPayloadAndSignature = {
id: string;
name: EmitterWebhookEventName;
payload: string;
signature: string;
};

export type EmitterWebhookEventWithSignature = EmitterWebhookEvent & {
signature: string;
};

interface BaseWebhookEvent<TName extends WebhookEventName> {
id: string;
name: TName;
Expand Down
20 changes: 16 additions & 4 deletions src/verify-and-receive.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
import { verify } from "@octokit/webhooks-methods";

import { EmitterWebhookEvent, State } from "./types";
import { toNormalizedJsonString } from "./to-normalized-json-string";
import {
EmitterWebhookEventWithStringPayloadAndSignature,
EmitterWebhookEventWithSignature,
State,
} from "./types";

export async function verifyAndReceive(
state: State & { secret: string },
event: EmitterWebhookEvent & { signature: string }
event:
| EmitterWebhookEventWithStringPayloadAndSignature
| EmitterWebhookEventWithSignature
): Promise<any> {
// verify will validate that the secret is not undefined
const matchesSignature = await verify(
state.secret,
event.payload,
typeof event.payload === "object"
? toNormalizedJsonString(event.payload)
: event.payload,
event.signature
);

Expand All @@ -26,6 +35,9 @@ export async function verifyAndReceive(
return state.eventHandler.receive({
id: event.id,
name: event.name,
payload: event.payload,
payload:
typeof event.payload === "string"
? JSON.parse(event.payload)
: event.payload,
});
}
15 changes: 15 additions & 0 deletions src/verify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { verify as verifyMethod } from "@octokit/webhooks-methods";

import { toNormalizedJsonString } from "./to-normalized-json-string";

export async function verify(
secret: string,
payload: string | object,
signature: string
): Promise<any> {
return verifyMethod(
secret,
typeof payload === "string" ? payload : toNormalizedJsonString(payload),
signature
);
}
8 changes: 6 additions & 2 deletions test/fixtures/push-payload.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
},
"added": [],
"removed": [],
"modified": ["README.md"]
"modified": [
"README.md"
]
}
],
"head_commit": {
Expand All @@ -49,7 +51,9 @@
},
"added": [],
"removed": [],
"modified": ["README.md"]
"modified": [
"README.md"
]
},
"repository": {
"id": 35129377,
Expand Down
28 changes: 16 additions & 12 deletions test/integration/node-middleware.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createServer } from "http";
import { readFileSync } from "fs";

import fetch from "node-fetch";
import { sign } from "@octokit/webhooks-methods";
Expand All @@ -7,15 +8,18 @@ import { sign } from "@octokit/webhooks-methods";
const express = require("express");

import { Webhooks, createNodeMiddleware } from "../../src/index.js";
import { pushEventPayload } from "../fixtures/index.js";

const pushEventPayload = readFileSync(
"test/fixtures/push-payload.json",
"utf-8"
);
let signatureSha256: string;

describe("createNodeMiddleware(webhooks)", () => {
beforeAll(async () => {
signatureSha256 = await sign(
{ secret: "mySecret", algorithm: "sha256" },
JSON.stringify(pushEventPayload)
pushEventPayload
);
});

Expand Down Expand Up @@ -48,7 +52,7 @@ describe("createNodeMiddleware(webhooks)", () => {
"X-GitHub-Event": "push",
"X-Hub-Signature-256": signatureSha256,
},
body: JSON.stringify(pushEventPayload),
body: pushEventPayload,
}
);

Expand Down Expand Up @@ -92,7 +96,7 @@ describe("createNodeMiddleware(webhooks)", () => {
"X-GitHub-Event": "push",
"X-Hub-Signature-256": signatureSha256,
},
body: JSON.stringify(pushEventPayload),
body: pushEventPayload,
}
);

Expand Down Expand Up @@ -256,7 +260,7 @@ describe("createNodeMiddleware(webhooks)", () => {
"X-GitHub-Event": "push",
"X-Hub-Signature-256": signatureSha256,
},
body: JSON.stringify(pushEventPayload),
body: pushEventPayload,
}
);

Expand Down Expand Up @@ -292,7 +296,7 @@ describe("createNodeMiddleware(webhooks)", () => {
"X-GitHub-Event": "push",
"X-Hub-Signature-256": signatureSha256,
},
body: JSON.stringify(pushEventPayload),
body: pushEventPayload,
}
);

Expand Down Expand Up @@ -327,7 +331,7 @@ describe("createNodeMiddleware(webhooks)", () => {
"X-GitHub-Event": "push",
"X-Hub-Signature-256": signatureSha256,
},
body: JSON.stringify(pushEventPayload),
body: pushEventPayload,
}
);

Expand All @@ -352,7 +356,7 @@ describe("createNodeMiddleware(webhooks)", () => {

const response = await fetch(`http://localhost:${port}/test`, {
method: "POST",
body: JSON.stringify(pushEventPayload),
body: pushEventPayload,
});

await expect(response.text()).resolves.toBe("Dafuq");
Expand All @@ -376,15 +380,15 @@ describe("createNodeMiddleware(webhooks)", () => {

const response = await fetch(`http://localhost:${port}/test`, {
method: "POST",
body: JSON.stringify(pushEventPayload),
body: pushEventPayload,
});

await expect(response.text()).resolves.toContain("Cannot POST /test");
expect(response.status).toEqual(404);

const responseForFoo = await fetch(`http://localhost:${port}/foo`, {
method: "POST",
body: JSON.stringify(pushEventPayload),
body: pushEventPayload,
});

await expect(responseForFoo.text()).resolves.toContain("ok\n");
Expand Down Expand Up @@ -415,7 +419,7 @@ describe("createNodeMiddleware(webhooks)", () => {
"X-GitHub-Event": "push",
"X-Hub-Signature-256": signatureSha256,
},
body: JSON.stringify(pushEventPayload),
body: pushEventPayload,
});

await expect(response.text()).resolves.toBe("ok\n");
Expand Down Expand Up @@ -446,7 +450,7 @@ describe("createNodeMiddleware(webhooks)", () => {
"X-GitHub-Event": "push",
"X-Hub-Signature-256": signatureSha256,
},
body: JSON.stringify(pushEventPayload),
body: pushEventPayload,
});

await expect(response.text()).resolves.toBe("ok\n");
Expand Down
Loading

0 comments on commit 8d7a936

Please sign in to comment.