Skip to content

Rename webhook response table #2032

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 29 additions & 29 deletions packages/api/src/controllers/webhook-log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,57 +14,57 @@ import {
} from "../store/errors";
import { resendWebhook } from "../webhooks/cannon";
import sql from "sql-template-strings";
import { WebhookResponse } from "../schema/types";
import { WebhookLog } from "../schema/types";
import { DBWebhook } from "../store/webhook-table";
import { Request, Router } from "express";

const app = Router({ mergeParams: true });

const requestsFieldsMap: FieldsMap = {
id: `webhook_response.ID`,
createdAt: { val: `webhook_response.data->'createdAt'`, type: "int" },
userId: `webhook_response.data->>'userId'`,
event: `webhook_response.data->>'event'`,
statusCode: `webhook_response.data->'response'->>'status'`,
id: `webhook_log.ID`,
createdAt: { val: `webhook_log.data->'createdAt'`, type: "int" },
userId: `webhook_log.data->>'userId'`,
event: `webhook_log.data->>'event'`,
statusCode: `webhook_log.data->'response'->>'status'`,
};

app.post("/:requestId/resend", authorizer({}), async (req, res) => {
const webhook = await db.webhook.get(req.params.id);
const webhookResponse = await db.webhookResponse.get(req.params.requestId);
await checkRequest(req, webhook, webhookResponse);
const webhookLog = await db.webhookLog.get(req.params.requestId);
await checkRequest(req, webhook, webhookLog);

const resent = await resendWebhook(webhook, webhookResponse);
const resent = await resendWebhook(webhook, webhookLog);
res.status(200);
return res.json(db.webhookResponse.cleanWriteOnlyResponse(resent));
return res.json(db.webhookLog.cleanWriteOnlyResponse(resent));
});

app.get("/:requestId", authorizer({}), async (req, res) => {
const webhook = await db.webhook.get(req.params.id);
const webhookResponse = await db.webhookResponse.get(req.params.requestId);
await checkRequest(req, webhook, webhookResponse);
const webhookLog = await db.webhookLog.get(req.params.requestId);
await checkRequest(req, webhook, webhookLog);

res.status(200);
return res.json(db.webhookResponse.cleanWriteOnlyResponse(webhookResponse));
return res.json(db.webhookLog.cleanWriteOnlyResponse(webhookLog));
});

async function checkRequest(
req: Request,
webhook: DBWebhook,
webhookResponse: WebhookResponse
webhookLog: WebhookLog
) {
if (!webhook || webhook.deleted) {
throw new NotFoundError(`webhook not found`);
}
if (!webhookResponse || webhookResponse.deleted) {
if (!webhookLog || webhookLog.deleted) {
throw new NotFoundError(`webhook log not found`);
}
if (
!req.user.admin &&
(req.user.id !== webhook.userId || req.user.id !== webhookResponse.userId)
(req.user.id !== webhook.userId || req.user.id !== webhookLog.userId)
) {
throw new ForbiddenError(`invalid user`);
}
if (webhookResponse.webhookId !== webhook.id) {
if (webhookLog.webhookId !== webhook.id) {
throw new BadRequestError(`mismatch between webhook and webhook log`);
}
}
Expand All @@ -82,18 +82,18 @@ app.get("/", authorizer({}), async (req, res) => {

if (req.user.admin && allUsers && allUsers !== "false") {
const query = parseFilters(requestsFieldsMap, filters);
query.push(sql`webhook_response.data->>'webhookId' = ${req.params.id}`);
query.push(sql`webhook_log.data->>'webhookId' = ${req.params.id}`);
if (!all || all === "false") {
query.push(sql`webhook_response.data->>'deleted' IS NULL`);
query.push(sql`webhook_log.data->>'deleted' IS NULL`);
}

let fields =
" webhook_response.id as id, webhook_response.data as data, users.id as usersId, users.data as usersdata";
" webhook_log.id as id, webhook_log.data as data, users.id as usersId, users.data as usersdata";
if (count) {
fields = fields + ", count(*) OVER() AS count";
}
const from = `webhook_response left join users on webhook_response.data->>'userId' = users.id`;
const [output, newCursor] = await db.webhookResponse.find(query, {
const from = `webhook_log left join users on webhook_log.data->>'userId' = users.id`;
const [output, newCursor] = await db.webhookLog.find(query, {
limit,
cursor,
fields,
Expand All @@ -116,19 +116,19 @@ app.get("/", authorizer({}), async (req, res) => {
}

const query = parseFilters(requestsFieldsMap, filters);
query.push(sql`webhook_response.data->>'userId' = ${req.user.id}`);
query.push(sql`webhook_response.data->>'webhookId' = ${req.params.id}`);
query.push(sql`webhook_log.data->>'userId' = ${req.user.id}`);
query.push(sql`webhook_log.data->>'webhookId' = ${req.params.id}`);

if (!all || all === "false" || !req.user.admin) {
query.push(sql`webhook_response.data->>'deleted' IS NULL`);
query.push(sql`webhook_log.data->>'deleted' IS NULL`);
}

let fields = " webhook_response.id as id, webhook_response.data as data";
let fields = " webhook_log.id as id, webhook_log.data as data";
if (count) {
fields = fields + ", count(*) OVER() AS count";
}
const from = `webhook_response`;
const [output, newCursor] = await db.webhookResponse.find(query, {
const from = `webhook_log`;
const [output, newCursor] = await db.webhookLog.find(query, {
limit,
cursor,
fields,
Expand All @@ -148,7 +148,7 @@ app.get("/", authorizer({}), async (req, res) => {
res.links({ next: makeNextHREF(req, newCursor) });
}

return res.json(db.webhookResponse.cleanWriteOnlyResponses(output));
return res.json(db.webhookLog.cleanWriteOnlyResponses(output));
});

export default app;
8 changes: 4 additions & 4 deletions packages/api/src/schema/api-schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ components:
Timestamp (in milliseconds) at which the webhook last was
triggered
example: 1587667174725
webhook-response:
webhook-log:
type: object
required:
- id
Expand Down Expand Up @@ -2834,7 +2834,7 @@ paths:
schema:
type: array
items:
$ref: "#/components/schemas/webhook-response"
$ref: "#/components/schemas/webhook-log"
default:
description: Error
content:
Expand All @@ -2861,7 +2861,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/webhook-response"
$ref: "#/components/schemas/webhook-log"
default:
description: Error
content:
Expand Down Expand Up @@ -2892,7 +2892,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/webhook-response"
$ref: "#/components/schemas/webhook-log"
default:
description: Error
content:
Expand Down
6 changes: 3 additions & 3 deletions packages/api/src/schema/db-schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -586,13 +586,13 @@ components:
deleted:
type: boolean
default: false
webhook-response:
table: webhook_response
webhook-log:
table: webhook_log
properties:
kind:
readOnly: true
type: string
example: webhookResponse
example: webhookLog
userId:
readOnly: true
type: string
Expand Down
8 changes: 4 additions & 4 deletions packages/api/src/store/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import {
PasswordResetToken,
Usage,
Region,
WebhookResponse,
Session,
SigningKey,
Room,
Attestation,
JwtRefreshToken,
WebhookLog,
} from "../schema/types";
import BaseTable, { TableOptions } from "./table";
import StreamTable from "./stream-table";
Expand Down Expand Up @@ -60,7 +60,7 @@ export class DB {
attestation: AttestationTable;
usage: Table<Usage>;
webhook: WebhookTable;
webhookResponse: Table<WebhookResponse>;
webhookLog: Table<WebhookLog>;
passwordResetToken: Table<PasswordResetToken>;
region: Table<Region>;
session: SessionTable;
Expand Down Expand Up @@ -169,9 +169,9 @@ export class DB {
});

this.region = makeTable<Region>({ db: this, schema: schemas["region"] });
this.webhookResponse = makeTable<WebhookResponse>({
this.webhookLog = makeTable<WebhookLog>({
db: this,
schema: schemas["webhook-response"],
schema: schemas["webhook-log"],
});
this.session = new SessionTable({ db: this, schema: schemas["session"] });
this.room = makeTable<Room>({ db: this, schema: schemas["room"] });
Expand Down
42 changes: 21 additions & 21 deletions packages/api/src/webhooks/cannon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { BadRequestError, UnprocessableEntityError } from "../store/errors";
import { db } from "../store";
import { buildRecordingUrl } from "../controllers/session";
import { isExperimentSubject } from "../store/experiment-table";
import { WebhookResponse } from "../schema/types";
import { WebhookLog } from "../schema/types";

const WEBHOOK_TIMEOUT = 5 * 1000;
const MAX_BACKOFF = 60 * 60 * 1000;
Expand Down Expand Up @@ -596,13 +596,13 @@ async function storeResponse(
responseBody: string,
sharedSecret: string,
params
): Promise<WebhookResponse> {
): Promise<WebhookLog> {
const hrDuration = process.hrtime(startTime);
const encodedResponseBody = Buffer.from(
responseBody.substring(0, 1024)
).toString("base64");

const webhookResponse = {
const webhookLog = {
id: uuid(),
webhookId: webhook.id,
eventId: eventId,
Expand All @@ -624,14 +624,14 @@ async function storeResponse(
},
sharedSecret: sharedSecret,
};
await db.webhookResponse.create(webhookResponse);
return webhookResponse;
await db.webhookLog.create(webhookLog);
return webhookLog;
}

export async function resendWebhook(
webhook: DBWebhook,
webhookResponse: WebhookResponse
): Promise<WebhookResponse> {
webhookLog: WebhookLog
): Promise<WebhookLog> {
const triggerTime = Date.now();
const startTime = process.hrtime();
let resp: Response;
Expand All @@ -640,26 +640,26 @@ export async function resendWebhook(
let errorMessage: string;
try {
const timestamp = Date.now();
const requestBody = JSON.parse(webhookResponse.request.body);
webhookResponse.request.body = JSON.stringify({
const requestBody = JSON.parse(webhookLog.request.body);
webhookLog.request.body = JSON.stringify({
...requestBody,
timestamp,
});
const sigHeaders = signatureHeaders(
webhookResponse.request.body,
webhookResponse.sharedSecret,
webhookLog.request.body,
webhookLog.sharedSecret,
timestamp
);
webhookResponse.request.headers = {
...webhookResponse.request.headers,
webhookLog.request.headers = {
...webhookLog.request.headers,
...sigHeaders,
};

resp = await fetchWithTimeout(webhookResponse.request.url, {
method: webhookResponse.request.method,
headers: webhookResponse.request.headers,
resp = await fetchWithTimeout(webhookLog.request.url, {
method: webhookLog.request.method,
headers: webhookLog.request.headers,
timeout: WEBHOOK_TIMEOUT,
body: webhookResponse.request.body,
body: webhookLog.request.body,
});
responseBody = await resp.text();
statusCode = resp.status;
Expand All @@ -676,13 +676,13 @@ export async function resendWebhook(
);
return await storeResponse(
webhook,
webhookResponse.eventId,
webhookResponse.event,
webhookLog.eventId,
webhookLog.event,
resp,
startTime,
responseBody,
webhookResponse.sharedSecret,
webhookResponse.request
webhookLog.sharedSecret,
webhookLog.request
);
}
}
Expand Down