Skip to content

Commit 4ad53f9

Browse files
committed
feat: Start adding git webhook integration
1 parent 4f48761 commit 4ad53f9

6 files changed

Lines changed: 60 additions & 6 deletions

File tree

.eslintrc.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
"@typescript-eslint/no-unused-vars": [
2222
"error",
2323
{
24-
"varsIgnorePattern": "^_"
24+
"varsIgnorePattern": "^_",
25+
"argsIgnorePattern": "^_"
2526
}
2627
],
2728
"@typescript-eslint/consistent-type-imports": "error",

src/utils/webError.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const DEFAULT_ERROR_MESSAGES: Record<number, string> = {
2+
401: 'Invalid input.',
3+
404: 'Page/resource not found.',
4+
501: 'An internal server error occurred.',
5+
};
6+
7+
export class WebError extends Error {
8+
statusCode: number;
9+
10+
/**
11+
* @param {string} arg Error message
12+
* @param {number} [code=401] Error code
13+
*/
14+
constructor(arg?: string, code?: number);
15+
/**
16+
* @param {number} [code=401] Error code
17+
*/
18+
constructor(code: number);
19+
constructor(arg?: string | number, fallbackCode?: number) {
20+
const code = typeof arg === 'number' ? arg : (fallbackCode ?? 401);
21+
const message = typeof arg === 'string' ? arg : (DEFAULT_ERROR_MESSAGES[code] ?? DEFAULT_ERROR_MESSAGES[501]);
22+
super(message);
23+
this.name = this.constructor.name;
24+
this.statusCode = code;
25+
}
26+
}

src/web/api/github.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import crypto from 'crypto';
2+
3+
import { log } from '@/utils/logger';
4+
import { WebError } from '@/utils/webError';
5+
6+
import type { RequestHandler } from 'express';
7+
8+
export const handler: RequestHandler = async (req, _res) => {
9+
const { payload } = req.body as { payload: string };
10+
const signature = req.header('X-Hub-Signature-256');
11+
log({ req, body: req.body, payload, signature });
12+
if (!signature) throw new WebError('Signature not provided.');
13+
const SHA256 = crypto.createHash('sha256').update(req.body).digest('hex');
14+
if (signature !== SHA256) throw new WebError('Signature invalid.');
15+
throw new WebError('Not added yet');
16+
};

src/web/api/quotes/[room].ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
import { getAllQuotes } from '@/database/quotes';
2+
import { WebError } from '@/utils/webError';
23

34
import type { RequestHandler } from 'express';
45

56
export const handler: RequestHandler = async (req, res) => {
67
const { room } = req.params as { room: string };
78
const quotes = await getAllQuotes(room);
8-
if (!quotes.length) {
9-
// https://github.com/microsoft/TypeScript/issues/12871
10-
res.sendStatus(404);
11-
return;
12-
}
9+
if (!quotes.length) throw new WebError(404);
1310
res.json(quotes);
1411
};

src/web/loaders/api.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Router } from 'express';
22

33
import { fsPath } from '@/utils/fsPath';
4+
import { errorHandler } from '@/web/loaders/errors';
45
import { readFileStructure } from '@/web/loaders/util';
56

67
import type { APIRoute } from '@/types/web';
@@ -18,4 +19,5 @@ export default async function init(app: Application): Promise<void> {
1819
);
1920

2021
app.use('/api', router);
22+
app.use('/api', errorHandler);
2123
}

src/web/loaders/errors.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { log } from '@/utils/logger';
2+
import { WebError } from '@/utils/webError';
3+
4+
import type { NextFunction, Request, Response } from 'express';
5+
6+
export function errorHandler(err: Error, req: Request, res: Response, _next: NextFunction): void {
7+
if (!(err instanceof WebError)) log(req, err);
8+
res
9+
// .header('content-type', 'application/text')
10+
.status('statusCode' in err && typeof err.statusCode === 'number' ? err.statusCode : 501)
11+
.send(err.message ?? 'An internal server error occurred!');
12+
}

0 commit comments

Comments
 (0)