migrate auth route

This commit is contained in:
Martin Dimitrov 2025-05-31 14:47:43 -07:00
parent ff2b5f9b9e
commit 50c4e9ae2c
2 changed files with 40 additions and 40 deletions

View File

@ -5,14 +5,14 @@
import { ServerlessEventObject, ServerlessFunctionSignature } from "@twilio-labs/serverless-runtime-types/types"; import { ServerlessEventObject, ServerlessFunctionSignature } from "@twilio-labs/serverless-runtime-types/types";
import { TwilioContext } from "../../../types/TwilioContext"; import { TwilioContext } from "../../../types/TwilioContext";
import { UserAgentHeader } from "../../../utils/blockUserAgent"; import { UserAgentHeader } from "../../../utils/blockUserAgent";
import { clearLockStatusCommand, createDDBClient, ddbItemToJSON, getDoorConfigCommand, getLockStatusCommand, isLockOpen, setLockStatusCommand } from "../../../utils/ddb"; import { createDynaBridgeClient } from "../../../utils/ddb";
import { DoorConfig } from "../../../types/DoorConfig";
import { AuthMethod } from "../../../types/AuthMethod"; import { AuthMethod } from "../../../types/AuthMethod";
import { Lock } from "../../../types/Lock";
import { DoorStatus } from "../../../types/DoorStatus"; import { DoorStatus } from "../../../types/DoorStatus";
import { getMetricFromRegistry, withMetrics } from "../../../common/DoormanHandler"; import { getMetricFromRegistry, withMetrics } from "../../../common/DoormanHandler";
import { AuthMetrics, registerMetrics } from "../../../metrics/AuthMetrics"; import { AuthMetrics, registerMetrics } from "../../../metrics/AuthMetrics";
import { Counter } from "prom-client"; import { Counter } from "prom-client";
import { DoorConfig, getDoorConfigID } from "../../../schema/DoorConfig";
import { createLockStatusWithTimeout, getLockStatusID, isLockOpen } from "../../../schema/LockStatus";
export interface AuthRequest extends ServerlessEventObject<{}, UserAgentHeader> { export interface AuthRequest extends ServerlessEventObject<{}, UserAgentHeader> {
door?: string; door?: string;
@ -34,10 +34,9 @@ export const handler: ServerlessFunctionSignature<TwilioContext, AuthRequest> =
return callback(null, response); return callback(null, response);
} }
const client = createDDBClient(context); const db = createDynaBridgeClient(context);
const ddbConfig = await client.send(getDoorConfigCommand(door)); const config: DoorConfig | undefined = await db.entities.doorConfig.findById(getDoorConfigID(door));
const config: DoorConfig = ddbItemToJSON<DoorConfig>(ddbConfig);
if (!config) { if (!config) {
getMetricFromRegistry<Counter>(metricsRegistry, AuthMetrics.DOOR_CONFIG_NOT_FOUND).inc({ door }, 1); getMetricFromRegistry<Counter>(metricsRegistry, AuthMetrics.DOOR_CONFIG_NOT_FOUND).inc({ door }, 1);
@ -76,41 +75,32 @@ export const handler: ServerlessFunctionSignature<TwilioContext, AuthRequest> =
const timeout = event.timeout ? parseInt(event.timeout) : config.timeout; const timeout = event.timeout ? parseInt(event.timeout) : config.timeout;
// check lock status if locked, then unlock. If unlocked then lock // check lock status if locked, then unlock. If unlocked then lock
await client.send(getLockStatusCommand(door)) const lock = await db.entities.lockStatus.findById(getLockStatusID(door));
.then(async (lockDdb) => { const isOpen = isLockOpen(lock);
const isOpen = isLockOpen(lockDdb);
if (isOpen) { if (isOpen && lock) {
const lock: Lock = ddbItemToJSON<Lock>(lockDdb); const fingerprint = JSON.parse(lock.fingerprint);
const fingerprint = JSON.parse(lock.fingerprint);
response response
.setStatusCode(200) .setStatusCode(200)
.appendHeader('Content-Type', 'application/json') .appendHeader('Content-Type', 'application/json')
.setBody({ .setBody({
status: DoorStatus.CLOSED, status: DoorStatus.CLOSED,
fingerprint, fingerprint,
}); });
await client.send(clearLockStatusCommand(lockDdb)); await db.entities.lockStatus.deleteById(getLockStatusID(door));
return; } else {
} await db.entities.lockStatus.save(createLockStatusWithTimeout(door, timeout, fingerprint));
response
.setStatusCode(200)
.appendHeader('Content-Type', 'application/json')
.setBody({ msg: `Opened the door "${door}" for ${timeout}s` });
}
await client.send(setLockStatusCommand(door, timeout, fingerprint)) // destroy the internal client after
.then(async (item) => { // @ts-ignore
response db.ddbClient.destroy();
.setStatusCode(200)
.appendHeader('Content-Type', 'application/json')
.setBody({ msg: `Opened the door "${door}" for ${timeout}s` });
}).catch((e) => {
console.log(e);
response
.setStatusCode(500)
.appendHeader('Content-Type', 'application/json')
.setBody({ err: e });
});
});
await client.destroy();
return callback(null, response); return callback(null, response);
}); });

View File

@ -5,14 +5,15 @@ export const LOCK_STATUS_SK = "lock";
export const LockStatusSchema = z.object({ export const LockStatusSchema = z.object({
// keys // keys
PK: z.string(), // phone number (buzzer number) PK: z.string(), // door name
SK: z.literal(LOCK_STATUS_SK).default(LOCK_STATUS_SK), SK: z.literal(LOCK_STATUS_SK).default(LOCK_STATUS_SK),
TTL: z.number(), TTL: z.number(),
fingerprint: z.string(), fingerprint: z.string(),
}); });
export const getLockStatusID = (buzzer: string): string[] => { export const getLockStatusID = (door: string): string[] => {
return [buzzer, LOCK_STATUS_SK]; return [door, LOCK_STATUS_SK];
} }
export type LockStatus = z.infer<typeof LockStatusSchema>; export type LockStatus = z.infer<typeof LockStatusSchema>;
@ -28,3 +29,12 @@ export const isLockOpen = (lock?: LockStatus) => {
return parseInt("" + ttl) > Date.now(); return parseInt("" + ttl) > Date.now();
}; };
export const createLockStatusWithTimeout = (door: string, timeoutSeconds: number, fingerprint: any): LockStatus => {
return {
PK: door,
SK: LOCK_STATUS_SK,
TTL: Date.now() + timeoutSeconds * 1000,
fingerprint: JSON.stringify(fingerprint),
};
};