add check OTP api

This commit is contained in:
Martin Dimitrov 2025-10-08 13:52:19 -07:00
parent 946ec544fe
commit 29786f5780
2 changed files with 63 additions and 1 deletions

View File

@ -0,0 +1,53 @@
/**
* Try to get buzzer number for a given OTP
*/
import { ServerlessEventObject, ServerlessFunctionSignature } from "@twilio-labs/serverless-runtime-types/types";
import { TwilioContext } from "../../../types/TwilioContext";
import { createDynaBridgeClient } from "../../../utils/ddb";
import { withMetrics } from "../../../common/DoormanHandler";
import { z } from "zod";
import { UserAgentHeader } from "../../../utils/blockUserAgent";
import { setResponseJson } from "../../../utils/responseUtils";
import { getLogCallID } from "../../../schema/LogCall";
import { isTTLInFuture } from "../../../common/TTLHelper";
export const CheckOtpRequestSchema = z.object({
otp: z.string(),
});
export type CheckOtpRequest = z.infer<typeof CheckOtpRequestSchema>;
export interface CheckOtpRequestTwilio extends ServerlessEventObject<CheckOtpRequest, UserAgentHeader> { };
export const CheckOtpResponseSchema = z.object({
buzzer: z.string(),
});
export type CheckOtpResponse = z.infer<typeof CheckOtpResponseSchema>;
export const handler: ServerlessFunctionSignature<TwilioContext, CheckOtpRequestTwilio> = withMetrics("checkotp", async (context, event, callback, metricsRegistry) => {
const response = new Twilio.Response();
const req = CheckOtpRequestSchema.parse(event);
let otp = req.otp;
const db = createDynaBridgeClient(context);
const log = await db.entities.logCall.findById(getLogCallID(otp));
if (!log || !isTTLInFuture(log)) {
setResponseJson(response, 404, {
msg: "OTP expired or not found",
})
} else {
setResponseJson(response, 200, {
buzzer: log.caller,
});
}
// destroy the internal client after
// @ts-ignore
db.ddbClient.destroy();
return callback(null, response);
});

View File

@ -5,6 +5,7 @@ import { StatusResponse } from "../src/functions/api/door/status";
import { sleep } from "bun";
import { ONBOARDING_DOOR_NAME, ONBOARDING_DOOR_PIN } from "../src/schema/DoorConfig";
import { LogCallResponse } from "../src/functions/api/door/logCall";
import { CheckOtpResponse } from "../src/functions/api/door/checkOtp";
// these tests should only run locally
if (process.env.STAGE === 'staging') {
@ -109,7 +110,15 @@ describe("call log path works", () => {
expect(logCallRes.status).toBe(200);
const otp = (await logCallRes.json() as LogCallResponse).otp
expect(otp.length).toBe(4)
expect(otp.length).toBe(4);
const checkOtpRes = await fetch(baseUrl + `/api/door/checkOtp?otp=${otp}`);
expect(checkOtpRes.status).toBe(200);
// check OTP
const caller = (await checkOtpRes.json() as CheckOtpResponse).buzzer;
expect(caller).toBe(buzzerNumber);
});
test("call log after door closed, should not return OTP", async () => {