update onboard route
This commit is contained in:
parent
1c87e93d2f
commit
8ca379b6db
@ -8,29 +8,37 @@ import { createDynaBridgeClient } from "../../../utils/ddb";
|
|||||||
import DiscordOauth2 from "discord-oauth2";
|
import DiscordOauth2 from "discord-oauth2";
|
||||||
import { DoorAliasSchema, getDoorAliasID } from "../../../schema/DoorAlias";
|
import { DoorAliasSchema, getDoorAliasID } from "../../../schema/DoorAlias";
|
||||||
import { Counter } from "prom-client";
|
import { Counter } from "prom-client";
|
||||||
|
import { z } from "zod";
|
||||||
|
import zu from "zod_utilz";
|
||||||
|
import { setResponseJson } from "../../../utils/responseUtils";
|
||||||
|
|
||||||
export interface OnboardRequest extends ServerlessEventObject<{}, UserAgentHeader> {
|
export const OnboardRequestSchema = z.object({
|
||||||
newConfig?: string;
|
newConfig: zu.stringToJSON().optional(),
|
||||||
|
code: z.string().optional(),
|
||||||
|
state: zu.stringToJSON().optional(),
|
||||||
|
}).partial()
|
||||||
|
.refine(data => data.newConfig || (data.code && data.state), 'newConfig or (code and state) must be specified');
|
||||||
|
|
||||||
// for oauth redirect
|
export type OnboardRequest = z.infer<typeof OnboardRequestSchema>;
|
||||||
code?: string;
|
|
||||||
state?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DiscordOnboardingState {
|
export interface OnboardRequestTwilio extends ServerlessEventObject<OnboardRequest, UserAgentHeader> { };
|
||||||
name: string;
|
|
||||||
id: string;
|
export const DiscordOnboardingStateSchema = z.object({
|
||||||
apiRedirect: string;
|
name: z.string(),
|
||||||
}
|
id: z.string(),
|
||||||
|
apiRedirect: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type DiscordOnboardingState = z.infer<typeof DiscordOnboardingStateSchema>;
|
||||||
|
|
||||||
const ONBOARDING_SCOPE = ['identify', 'email', 'guilds.join'];
|
const ONBOARDING_SCOPE = ['identify', 'email', 'guilds.join'];
|
||||||
|
|
||||||
export const handler: ServerlessFunctionSignature<TwilioContext, OnboardRequest> = withMetrics('onboard', async (context, event, callback, metricsRegistry) => {
|
export const handler: ServerlessFunctionSignature<TwilioContext, OnboardRequestTwilio> = withMetrics('onboard', async (context, event, callback, metricsRegistry) => {
|
||||||
const response = new Twilio.Response();
|
const response = new Twilio.Response();
|
||||||
response.appendHeader('Content-Type', 'application/json');
|
|
||||||
|
|
||||||
registerMetrics(metricsRegistry);
|
registerMetrics(metricsRegistry);
|
||||||
|
|
||||||
|
const req = OnboardRequestSchema.parse(event);
|
||||||
|
|
||||||
const db = createDynaBridgeClient(context);
|
const db = createDynaBridgeClient(context);
|
||||||
|
|
||||||
// return oauth link
|
// return oauth link
|
||||||
@ -41,23 +49,13 @@ export const handler: ServerlessFunctionSignature<TwilioContext, OnboardRequest>
|
|||||||
});
|
});
|
||||||
|
|
||||||
// create door config route
|
// create door config route
|
||||||
if (event.code && event.state) {
|
if (req.code && req.state) {
|
||||||
const code = event.code;
|
const code = req.code;
|
||||||
let discordState: DiscordOnboardingState;
|
let discordState: DiscordOnboardingState = DiscordOnboardingStateSchema.parse(req.state);
|
||||||
|
|
||||||
try {
|
|
||||||
discordState = JSON.parse(event.state);
|
|
||||||
} catch (e) {
|
|
||||||
response.setStatusCode(400);
|
|
||||||
response.setBody({ err: "invalid state" });
|
|
||||||
return callback(null, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
||||||
response.setStatusCode(404)
|
setResponseJson(response, 404, { err: "approval not found" });
|
||||||
.setBody({ err: "approval not found" });
|
|
||||||
|
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,8 +71,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, OnboardRequest>
|
|||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("something went wrong with discord authorization");
|
console.log("something went wrong with discord authorization");
|
||||||
response.setStatusCode(401);
|
setResponseJson(response, 401, { err });
|
||||||
response.setBody({ err });
|
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,9 +81,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, OnboardRequest>
|
|||||||
console.log(profileId);
|
console.log(profileId);
|
||||||
|
|
||||||
if (!profileId) {
|
if (!profileId) {
|
||||||
response.setStatusCode(404);
|
setResponseJson(response, 404, { err: "profile not found" });
|
||||||
response.setBody({ err: "profile not found" });
|
|
||||||
|
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,37 +139,26 @@ export const handler: ServerlessFunctionSignature<TwilioContext, OnboardRequest>
|
|||||||
// and all must succeed or none succeed
|
// and all must succeed or none succeed
|
||||||
try {
|
try {
|
||||||
await db.transaction([createDoorAlias, createDoorConfig, deleteOnboardingConfig]);
|
await db.transaction([createDoorAlias, createDoorConfig, deleteOnboardingConfig]);
|
||||||
response.setStatusCode(200);
|
setResponseJson(response, 200, { redirect: context.DOORMAN_URL + `?door=${config.name}` });
|
||||||
response.setBody({ redirect: context.DOORMAN_URL + `?door=${config.name}` });
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
getMetricFromRegistry<Counter>(metricsRegistry, OnboardMetrics.TRANSACTION_CONFLICT).inc(1);
|
getMetricFromRegistry<Counter>(metricsRegistry, OnboardMetrics.TRANSACTION_CONFLICT).inc(1);
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|
||||||
response.setStatusCode(409);
|
setResponseJson(response, 409, { err: "something went wrong during onboarding" });
|
||||||
response.setBody({ err: "something went wrong during onboarding" });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
let newConfig = event.newConfig;
|
let newConfig = req.newConfig;
|
||||||
|
|
||||||
if (!newConfig) {
|
if (!newConfig) {
|
||||||
response.setStatusCode(400);
|
setResponseJson(response, 400, { err: "missing newConfig" });
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
let newConfigParsed: OnboardDoorReq;
|
|
||||||
|
|
||||||
console.log("parsing config");
|
console.log("parsing config");
|
||||||
try {
|
let newConfigParsed: OnboardDoorReq = OnboardDoorReqSchema.parse(newConfig);
|
||||||
newConfigParsed = OnboardDoorReqSchema.parse(JSON.parse(newConfig));
|
|
||||||
} catch (err) {
|
|
||||||
response.setStatusCode(400);
|
|
||||||
response.setBody({ err });
|
|
||||||
return callback(null, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
const newConfigObj = createOnboardDoorConfig(newConfigParsed);
|
const newConfigObj = createOnboardDoorConfig(newConfigParsed);
|
||||||
|
|
||||||
// check if this name or buzzer is already registered?
|
// check if this name or buzzer is already registered?
|
||||||
@ -182,8 +166,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, OnboardRequest>
|
|||||||
|
|
||||||
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);
|
||||||
response.setStatusCode(409);
|
setResponseJson(response, 409, { err: `A buzzer is already registered with the number ${newConfigObj.buzzer}` });
|
||||||
response.setBody({ err: `A buzzer is already registered with the number ${newConfigObj.buzzer}` });
|
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,8 +174,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, OnboardRequest>
|
|||||||
|
|
||||||
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);
|
||||||
response.setStatusCode(409);
|
setResponseJson(response, 409, { err: `A buzzer is already registered with the name ${newConfigObj.name}` });
|
||||||
response.setBody({ err: `A buzzer is already registered with the name ${newConfigObj.name}` });
|
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,11 +184,11 @@ export const handler: ServerlessFunctionSignature<TwilioContext, OnboardRequest>
|
|||||||
// save to DB, this is a middle step until discord auth comes in
|
// save to DB, this is a middle step until discord auth comes in
|
||||||
await db.entities.onboardDoorConfig.save(newConfigObj);
|
await db.entities.onboardDoorConfig.save(newConfigObj);
|
||||||
|
|
||||||
const discordState: DiscordOnboardingState = {
|
const discordState: DiscordOnboardingState = DiscordOnboardingStateSchema.parse({
|
||||||
name: newConfigObj.name,
|
name: newConfigObj.name,
|
||||||
id: newConfigObj.nonce,
|
id: newConfigObj.nonce,
|
||||||
apiRedirect: '/api/door/onboard',
|
apiRedirect: '/api/door/onboard',
|
||||||
}
|
});
|
||||||
|
|
||||||
const redirect = oauth.generateAuthUrl({
|
const redirect = oauth.generateAuthUrl({
|
||||||
scope: ONBOARDING_SCOPE,
|
scope: ONBOARDING_SCOPE,
|
||||||
@ -214,7 +196,6 @@ export const handler: ServerlessFunctionSignature<TwilioContext, OnboardRequest>
|
|||||||
state: JSON.stringify(discordState),
|
state: JSON.stringify(discordState),
|
||||||
});
|
});
|
||||||
|
|
||||||
response.setStatusCode(200);
|
setResponseJson(response, 200, { redirect });
|
||||||
response.setBody({ redirect });
|
|
||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user