Compare commits
3 Commits
8f75081e6b
...
fa2fa11449
| Author | SHA1 | Date | |
|---|---|---|---|
| fa2fa11449 | |||
| 80dddd9a55 | |||
| 5595a29352 |
@ -52,10 +52,6 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
ACCOUNT_SID: ${{ secrets.TWILIO_ACCOUNT_SID }}
|
ACCOUNT_SID: ${{ secrets.TWILIO_ACCOUNT_SID }}
|
||||||
AUTH_TOKEN: ${{ secrets.TWILIO_AUTH_TOKEN }}
|
AUTH_TOKEN: ${{ secrets.TWILIO_AUTH_TOKEN }}
|
||||||
AWS_ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY }}
|
|
||||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
||||||
DISCORD_BOT_TOKEN: ${{ secrets.DISCORD_BOT_TOKEN }}
|
|
||||||
DISCORD_CLIENT_SECRET: ${{ secrets.DISCORD_CLIENT_SECRET }}
|
|
||||||
|
|
||||||
- name: Deploy Doorman Buzzer Client
|
- name: Deploy Doorman Buzzer Client
|
||||||
run: bun run deploy-buzzer-client
|
run: bun run deploy-buzzer-client
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
"watch-build": "bun run --watch src/index.ts",
|
"watch-build": "bun run --watch src/index.ts",
|
||||||
"start": "concurrently \"bun run watch-build\" \"bun run start-twilio\"",
|
"start": "concurrently \"bun run watch-build\" \"bun run start-twilio\"",
|
||||||
"build": "bun run src/index.ts",
|
"build": "bun run src/index.ts",
|
||||||
"deploy": "twilio-run deploy --load-system-env --env .env.example --service-name doorman --environment=prod --override-existing-project",
|
"deploy": "twilio-run promote --environment=staging --to=prod",
|
||||||
"deploy:staging": "twilio-run deploy --load-system-env --env .env.example --service-name doorman --environment=staging --override-existing-project"
|
"deploy:staging": "twilio-run deploy --load-system-env --env .env.example --service-name doorman --environment=staging --override-existing-project"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import LokiTransport from "winston-loki";
|
|||||||
import pTimeout, { TimeoutError } from "promise.timeout";
|
import pTimeout, { TimeoutError } from "promise.timeout";
|
||||||
import { ZodError } from "zod";
|
import { ZodError } from "zod";
|
||||||
import { fromError } from "zod-validation-error";
|
import { fromError } from "zod-validation-error";
|
||||||
|
import { setResponseJson } from "../utils/responseUtils";
|
||||||
|
|
||||||
export type BaseEvent = { request: { cookies: {}; headers: {}; }; }
|
export type BaseEvent = { request: { cookies: {}; headers: {}; }; }
|
||||||
|
|
||||||
@ -248,13 +249,12 @@ export function withMetrics<T extends DoormanLambdaContext, U extends BaseEvent>
|
|||||||
} else if (e instanceof ZodError) {
|
} else if (e instanceof ZodError) {
|
||||||
// global catch for validation errors
|
// global catch for validation errors
|
||||||
const response = new Twilio.Response();
|
const response = new Twilio.Response();
|
||||||
response.setStatusCode(400);
|
|
||||||
response.setHeaders({
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
});
|
|
||||||
|
|
||||||
// return nice to read error message from ZOD
|
// return nice to read error message from ZOD
|
||||||
response.setBody({ err: fromError(e).toString() });
|
setResponseJson(response, 400, {
|
||||||
|
msg: fromError(e).toString(),
|
||||||
|
});
|
||||||
|
|
||||||
callbackResult = [null, response];
|
callbackResult = [null, response];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, AuthRequestTwil
|
|||||||
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);
|
||||||
setResponseJson(response, 404, {
|
setResponseJson(response, 404, {
|
||||||
err: `Door ${door} not found`,
|
msg: `Door ${door} not found`,
|
||||||
});
|
});
|
||||||
|
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
@ -57,7 +57,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, AuthRequestTwil
|
|||||||
|
|
||||||
if (!method) {
|
if (!method) {
|
||||||
setResponseJson(response, 401, {
|
setResponseJson(response, 401, {
|
||||||
err: "Invalid PIN",
|
msg: "Invalid PIN",
|
||||||
});
|
});
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -71,7 +71,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, EditRequestTwil
|
|||||||
|
|
||||||
if (!newConfigRaw) {
|
if (!newConfigRaw) {
|
||||||
setResponseJson(response, 400, {
|
setResponseJson(response, 400, {
|
||||||
err: "Missing new config",
|
msg: "Missing new config",
|
||||||
});
|
});
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, EditRequestTwil
|
|||||||
|
|
||||||
if (!config) {
|
if (!config) {
|
||||||
setResponseJson(response, 404, {
|
setResponseJson(response, 404, {
|
||||||
err: `Door not found ${door}`,
|
msg: `Door not found ${door}`,
|
||||||
});
|
});
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
}
|
}
|
||||||
@ -95,7 +95,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, EditRequestTwil
|
|||||||
// if nothing changed, we should throw since this is a pointless change
|
// if nothing changed, we should throw since this is a pointless change
|
||||||
if (isDeepSubset(config, newConfig)) {
|
if (isDeepSubset(config, newConfig)) {
|
||||||
setResponseJson(response, 400, {
|
setResponseJson(response, 400, {
|
||||||
err: "Nothing changed in the new config",
|
msg: "Nothing changed in the new config",
|
||||||
});
|
});
|
||||||
|
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
|
|||||||
@ -48,7 +48,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, InfoRequestTwil
|
|||||||
.then(async (alias) => {
|
.then(async (alias) => {
|
||||||
if (!alias) {
|
if (!alias) {
|
||||||
setResponseJson(response, 404, {
|
setResponseJson(response, 404, {
|
||||||
err: "This buzzer is not registered",
|
msg: "This buzzer is not registered",
|
||||||
});
|
});
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, InfoRequestTwil
|
|||||||
|
|
||||||
if (!config) {
|
if (!config) {
|
||||||
setResponseJson(response, 404, {
|
setResponseJson(response, 404, {
|
||||||
err: "This buzzer is not registered",
|
msg: "This buzzer is not registered",
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (buzzer) {
|
if (buzzer) {
|
||||||
|
|||||||
@ -33,7 +33,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, NotifyRequestTw
|
|||||||
if (req.key !== context.NOTIFY_SECRET_KEY) {
|
if (req.key !== context.NOTIFY_SECRET_KEY) {
|
||||||
getMetricFromRegistry<Counter>(metricsRegistry, NotifyMetrics.UNAUTHENTICATED_CALL).inc(1);
|
getMetricFromRegistry<Counter>(metricsRegistry, NotifyMetrics.UNAUTHENTICATED_CALL).inc(1);
|
||||||
setResponseJson(response, 401, {
|
setResponseJson(response, 401, {
|
||||||
err: "Unauthenticated call", event
|
msg: "Unauthenticated call", event
|
||||||
});
|
});
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, NotifyRequestTw
|
|||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
setResponseJson(response, 500, { err: e, event });
|
setResponseJson(response, 500, { msg: e, event });
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -55,7 +55,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, OnboardRequestT
|
|||||||
|
|
||||||
const config = await db.entities.onboardDoorConfig.findById(getOnboardDoorId(discordState.name));
|
const config = await db.entities.onboardDoorConfig.findById(getOnboardDoorId(discordState.name));
|
||||||
if (!config || config.nonce !== discordState.id) {
|
if (!config || config.nonce !== discordState.id) {
|
||||||
setResponseJson(response, 404, { err: "approval not found" });
|
setResponseJson(response, 404, { msg: "approval not found" });
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, OnboardRequestT
|
|||||||
console.log(profileId);
|
console.log(profileId);
|
||||||
|
|
||||||
if (!profileId) {
|
if (!profileId) {
|
||||||
setResponseJson(response, 404, { err: "profile not found" });
|
setResponseJson(response, 404, { msg: "profile not found" });
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +144,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, OnboardRequestT
|
|||||||
getMetricFromRegistry<Counter>(metricsRegistry, OnboardMetrics.TRANSACTION_CONFLICT).inc(1);
|
getMetricFromRegistry<Counter>(metricsRegistry, OnboardMetrics.TRANSACTION_CONFLICT).inc(1);
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|
||||||
setResponseJson(response, 409, { err: "something went wrong during onboarding" });
|
setResponseJson(response, 409, { msg: "something went wrong during onboarding" });
|
||||||
}
|
}
|
||||||
|
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
@ -153,7 +153,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, OnboardRequestT
|
|||||||
let newConfig = req.newConfig;
|
let newConfig = req.newConfig;
|
||||||
|
|
||||||
if (!newConfig) {
|
if (!newConfig) {
|
||||||
setResponseJson(response, 400, { err: "missing newConfig" });
|
setResponseJson(response, 400, { msg: "missing newConfig" });
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, OnboardRequestT
|
|||||||
|
|
||||||
if (existingAlias) {
|
if (existingAlias) {
|
||||||
getMetricFromRegistry<Counter>(metricsRegistry, OnboardMetrics.BUZZER_CONFLICT).inc({ buzzer: newConfigObj.buzzer }, 1);
|
getMetricFromRegistry<Counter>(metricsRegistry, OnboardMetrics.BUZZER_CONFLICT).inc({ buzzer: newConfigObj.buzzer }, 1);
|
||||||
setResponseJson(response, 409, { err: `A buzzer is already registered with the number ${newConfigObj.buzzer}` });
|
setResponseJson(response, 409, { msg: `A buzzer is already registered with the number ${newConfigObj.buzzer}` });
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, OnboardRequestT
|
|||||||
|
|
||||||
if (existingConfig) {
|
if (existingConfig) {
|
||||||
getMetricFromRegistry<Counter>(metricsRegistry, OnboardMetrics.NAME_CONFLICT).inc({ name: newConfigObj.name }, 1);
|
getMetricFromRegistry<Counter>(metricsRegistry, OnboardMetrics.NAME_CONFLICT).inc({ name: newConfigObj.name }, 1);
|
||||||
setResponseJson(response, 409, { err: `A buzzer is already registered with the name ${newConfigObj.name}` });
|
setResponseJson(response, 409, { msg: `A buzzer is already registered with the name ${newConfigObj.name}` });
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { waitForService, baseUrl, doorName, buzzerNumber, key, buzzerUrl } from
|
|||||||
import { DoorStatus } from "../src/types/DoorStatus";
|
import { DoorStatus } from "../src/types/DoorStatus";
|
||||||
import { StatusResponse } from "../src/functions/api/door/status";
|
import { StatusResponse } from "../src/functions/api/door/status";
|
||||||
import { sleep } from "bun";
|
import { sleep } from "bun";
|
||||||
|
import { InfoResponseClient } from "../src/functions/api/door/info";
|
||||||
|
|
||||||
// these tests should only run locally
|
// these tests should only run locally
|
||||||
if (process.env.STAGE === 'staging') {
|
if (process.env.STAGE === 'staging') {
|
||||||
@ -21,6 +22,15 @@ describe("info path works", () => {
|
|||||||
expect(resp.buzzer).toBe(buzzerNumber);
|
expect(resp.buzzer).toBe(buzzerNumber);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("unknown info repsonds with a msg", async () => {
|
||||||
|
const resp = await fetch(baseUrl + `/api/door/info?door=baddoor`);
|
||||||
|
|
||||||
|
expect(resp.status).toBe(404);
|
||||||
|
const body = await resp.json() as any;
|
||||||
|
expect(body.msg).toContain("not registered");
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
test("info works from client", async () => {
|
test("info works from client", async () => {
|
||||||
const resp = await fetch(baseUrl + `/api/door/info?buzzer=${buzzerNumber}`).then(res => res.json()) as any;
|
const resp = await fetch(baseUrl + `/api/door/info?buzzer=${buzzerNumber}`).then(res => res.json()) as any;
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
"start-twilio": "twilio-run --live --port 4500",
|
"start-twilio": "twilio-run --live --port 4500",
|
||||||
"start": "concurrently \"bun run watch-build\" \"bun run start-twilio\"",
|
"start": "concurrently \"bun run watch-build\" \"bun run start-twilio\"",
|
||||||
"build": "bun run src/index.ts",
|
"build": "bun run src/index.ts",
|
||||||
"deploy": "twilio-run deploy --load-system-env --env .env.example --service-name buzzer --environment=prod --override-existing-project",
|
"deploy": "twilio-run promote --environment=staging --to=prod",
|
||||||
"deploy:staging": "twilio-run deploy --load-system-env --env .env.example --service-name buzzer --environment=staging --override-existing-project"
|
"deploy:staging": "twilio-run deploy --load-system-env --env .env.example --service-name buzzer --environment=staging --override-existing-project"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@ -14,7 +14,7 @@ app.get("/api/door/info", async (c) => {
|
|||||||
const door = c.req.query().door;
|
const door = c.req.query().door;
|
||||||
if (!door) {
|
if (!door) {
|
||||||
return c.json({
|
return c.json({
|
||||||
err: "Must specify a door",
|
msg: "Must specify a door",
|
||||||
}, 400);
|
}, 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ app.get("/api/door/info", async (c) => {
|
|||||||
|
|
||||||
if (!config) {
|
if (!config) {
|
||||||
return c.json({
|
return c.json({
|
||||||
err: "This buzzer is not registered properly",
|
msg: "This buzzer is not registered properly",
|
||||||
}, 404);
|
}, 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,17 +14,17 @@ export async function loader({ params, request }: any) {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await fetchUrlEncoded('/api/door/info', {
|
const res = await fetchUrlEncoded('/api/door/info', {
|
||||||
door,
|
door,
|
||||||
}).then(res => res.json());
|
}).then(res => res.json());
|
||||||
|
|
||||||
console.log(response);
|
console.log(res);
|
||||||
|
|
||||||
if (response.err) {
|
if (res.msg) {
|
||||||
throw new Error("Not a valid door");
|
throw new Error("Not a valid door");
|
||||||
}
|
}
|
||||||
|
|
||||||
return response as DoorResponse;
|
return res as DoorResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DoorPage() {
|
export function DoorPage() {
|
||||||
|
|||||||
@ -116,8 +116,8 @@ export const EditPage = ({ isOnboarding }: EditPageProps) => {
|
|||||||
fetchUrlEncoded(apiRoute, body)
|
fetchUrlEncoded(apiRoute, body)
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.err) {
|
if (res.msg) {
|
||||||
addAlert("error", res.err);
|
addAlert("error", res.msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!isOnboarding) {
|
if (!isOnboarding) {
|
||||||
|
|||||||
@ -18,7 +18,7 @@ export const RedirectPage = () => {
|
|||||||
fetch(state.apiRedirect + '?' + params.toString())
|
fetch(state.apiRedirect + '?' + params.toString())
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.err) {
|
if (res.msg) {
|
||||||
console.error(res);
|
console.error(res);
|
||||||
window.location.href = '/';
|
window.location.href = '/';
|
||||||
return;
|
return;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user