-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Initial commit of FEAT_OTP code #1985 #1986
base: main
Are you sure you want to change the base?
Conversation
@jwalsh-bdt is attempting to deploy a commit to the Typebot Team on Vercel. A member of the Team first needs to authorize it. |
WalkthroughThis pull request introduces support for OTP (One-Time Password) input blocks across multiple modules. It adds new React components for OTP display (icon, node content, settings, and input handling) and integrates OTP handling into editor, graph, and chat components. The update also extends enums, schemas, constants, and HTTP request configurations to accommodate the new OTP block type. Additionally, bot engine functions and communication handlers are updated to process OTP values appropriately. Changes
Sequence Diagram(s)sequenceDiagram
participant Editor
participant BlockIcon
participant OtpInputIcon
participant BlockContent
participant OtpInputNodeContent
participant SettingsPopover
participant OtpInputSettings
Editor->>BlockIcon: Render block (OTP type)
BlockIcon->>OtpInputIcon: Display OTP icon
Editor->>BlockContent: Render block content (OTP)
BlockContent->>OtpInputNodeContent: Display OTP node content
Editor->>SettingsPopover: Open settings for OTP block
SettingsPopover->>OtpInputSettings: Render OTP settings UI
sequenceDiagram
participant User
participant ChatBlock
participant OtpInput
participant HTTPRequest
participant BotEngine
User->>ChatBlock: Select OTP input block
ChatBlock->>OtpInput: Render OTP input fields
User->>OtpInput: Enter OTP digits
OtpInput->>HTTPRequest: Send HTTP webhook request
HTTPRequest-->>OtpInput: Return response
OtpInput->>BotEngine: Invoke onSubmit with OTP value
BotEngine-->>User: Process OTP submission
Possibly related PRs
Suggested reviewers
✨ Finishing Touches
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
🧹 Nitpick comments (10)
packages/blocks/inputs/src/otp/constants.ts (1)
4-7
: Consider enhancing OTP security and customization options.The current implementation could benefit from:
- Increasing default
codeLength
to 6 digits for better security- Adding validation range for
codeLength
(e.g., min: 4, max: 8)- Including additional options for OTP format (numeric/alphanumeric)
export const defaultTextInputOptions = { - codeLength: 4, + codeLength: 6, + format: 'numeric' as const, + validation: { + minLength: 4, + maxLength: 8, + }, labels: { button: defaultButtonLabel }, } as const satisfies OtpInputBlock["options"];packages/blocks/inputs/src/constants.ts (1)
3-17
: Consider adding JSDoc comments for better documentation.While the implementation is correct, consider adding JSDoc comments to document the purpose and usage of each input type, especially for the new OTP type.
export enum InputBlockType { TEXT = "text input", + /** One-Time Password input for authentication/verification */ OTP = "otp input", NUMBER = "number input", EMAIL = "email input",
apps/builder/src/features/blocks/inputs/otp/components/OtpInputNodeContent.tsx (2)
5-5
: Remove unused import.The
defaultTextInputOptions
is imported but never used in this component.-import { defaultTextInputOptions } from "@typebot.io/blocks-inputs/text/constants";
12-24
: Add error handling and visual feedback.Consider these improvements:
- Add error handling for missing typebot context
- Display visual feedback for OTP length configuration
export const OtpInputNodeContent = ({ options }: Props) => { const { typebot } = useTypebot(); + + if (!typebot) { + return null; + } + return ( <Stack> + <Text fontSize="sm" color="gray.500"> + {options.codeLength}-digit code + </Text> {options?.variableId && ( <SetVariableLabel variables={typebot?.variables} variableId={options.variableId} /> )} </Stack> ); };packages/blocks/inputs/src/otp/schema.ts (1)
11-15
: Consider adding more label customization options.The
labels
schema could be enhanced to support more customization options like error messages and placeholders.labels: z .object({ button: z.string().optional(), + error: z.string().optional(), + placeholder: z.string().optional(), }) .optional(),apps/builder/src/features/blocks/inputs/otp/components/OtpInputSettings.tsx (1)
44-44
: Consider organizing translation keys in a dedicated namespace.The translation keys could be better organized in a dedicated namespace for OTP-specific settings.
- label={t("blocks.inputs.settings.button.label")} + label={t("blocks.inputs.otp.settings.button.label")} - label={t("blocks.inputs.otp.settings.codeLength.label")} + label={t("blocks.inputs.otp.settings.code.length.label")} - {t("blocks.inputs.settings.saveAnswer.label")} + {t("blocks.inputs.otp.settings.save.answer.label")}Also applies to: 51-51, 57-57
packages/embeds/js/src/features/blocks/inputs/otp/components/OtpInput.tsx (3)
32-33
: Remove console.log statements.Remove debug logging statements before production deployment.
- console.log("onMount");
37-39
: Remove unused code and console.log.The
JSON.stringify
call has no effect and the console.log should be removed.- console.log("execute HTTP Request"); - JSON.stringify(props.block.options?.webhook);
161-171
: Internationalize hard-coded strings.Move hard-coded strings to translation files for better i18n support.
- Didn't receive code?{" "} + {t('input.otp.didntReceive')}{" "} <a class="font-medium text-indigo-500 hover:text-indigo-600" href="#0" on:click={resendCode} > - Resend + {t('input.otp.resend')} </a>packages/bot-engine/src/blocks/integrations/httpRequest/parseSampleResult.ts (1)
138-139
: Consider making the sample OTP value more configurable.While "123456" is a reasonable sample OTP, consider:
- Making it configurable through block options
- Generating a random n-digit number based on OTP length configuration
Example implementation:
- case InputBlockType.OTP: - return "123456"; + case InputBlockType.OTP: + const length = block.options?.length ?? 6 + return Array.from({ length }, () => Math.floor(Math.random() * 10)).join('')
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
apps/builder/src/i18n/en.json
is excluded by!**/*.json
📒 Files selected for processing (20)
apps/builder/src/features/blocks/inputs/otp/components/OtpInputIcon.tsx
(1 hunks)apps/builder/src/features/blocks/inputs/otp/components/OtpInputNodeContent.tsx
(1 hunks)apps/builder/src/features/blocks/inputs/otp/components/OtpInputSettings.tsx
(1 hunks)apps/builder/src/features/editor/components/BlockIcon.tsx
(2 hunks)apps/builder/src/features/editor/components/BlockLabel.tsx
(1 hunks)apps/builder/src/features/graph/components/nodes/block/BlockNodeContent.tsx
(2 hunks)apps/builder/src/features/graph/components/nodes/block/SettingsPopoverContent.tsx
(2 hunks)apps/builder/src/features/graph/helpers/getHelpDocUrl.ts
(1 hunks)packages/blocks/inputs/src/constants.ts
(1 hunks)packages/blocks/inputs/src/otp/constants.ts
(1 hunks)packages/blocks/inputs/src/otp/schema.ts
(1 hunks)packages/blocks/inputs/src/schema.ts
(2 hunks)packages/blocks/integrations/src/httpRequest/schema.ts
(1 hunks)packages/bot-engine/src/blocks/integrations/httpRequest/parseSampleResult.ts
(1 hunks)packages/bot-engine/src/continueBotFlow.ts
(1 hunks)packages/bot-engine/src/schemas/api.ts
(2 hunks)packages/embeds/js/src/components/InputChatBlock.tsx
(3 hunks)packages/embeds/js/src/features/blocks/inputs/otp/components/InputItem.tsx
(1 hunks)packages/embeds/js/src/features/blocks/inputs/otp/components/OtpInput.tsx
(1 hunks)packages/whatsapp/src/convertInputToWhatsAppMessage.ts
(1 hunks)
🔇 Additional comments (11)
apps/builder/src/features/blocks/inputs/otp/components/OtpInputIcon.tsx (1)
1-7
: LGTM! Clean and type-safe implementation.The component is well-structured, using proper typing and following React best practices.
packages/blocks/inputs/src/schema.ts (1)
7-7
: LGTM!The OTP input schema is correctly integrated into the input block schemas array and properly included in both v5 and v6 discriminated unions.
Also applies to: 26-26
packages/blocks/integrations/src/httpRequest/schema.ts (1)
60-67
: LGTM! Good modularization.Exporting
httpRequestOptionsSchemas
enables reuse of HTTP request schemas in OTP input blocks, promoting code reusability and consistency.apps/builder/src/features/graph/helpers/getHelpDocUrl.ts (1)
24-25
: LGTM! Documentation URL added.The OTP input block documentation URL follows the established pattern and maintains consistency with other input block URLs.
apps/builder/src/features/editor/components/BlockLabel.tsx (1)
59-59
: LGTM! Label added with i18n support.The OTP input block label is properly integrated with internationalization support, maintaining consistency with other input block labels.
packages/whatsapp/src/convertInputToWhatsAppMessage.ts (1)
36-36
: LGTM!The OTP input type is correctly handled, consistent with similar input types like DATE, TIME, and EMAIL.
apps/builder/src/features/editor/components/BlockIcon.tsx (1)
12-12
: LGTM!The OTP input icon is correctly integrated with consistent styling (orange color) matching other input block icons.
Also applies to: 68-69
apps/builder/src/features/graph/components/nodes/block/BlockNodeContent.tsx (1)
11-11
: Verify HTTP request integration with OTP input.The OTP input node is correctly integrated into the block content renderer. However, based on the PR description, there's an issue with the
executeHttpRequest
method inOtpInput.tsx
.Let's verify the webhook configuration:
Also applies to: 77-79
✅ Verification successful
HTTP Request Integration in OTP Input Verified
The OTP input (in
packages/embeds/js/src/features/blocks/inputs/otp/components/OtpInput.tsx
) correctly callsexecuteHttpRequest
with the expected webhook parameters (url, method, headers, and body), and our further searches did not reveal any misconfiguration.
- The OTP file imports and uses
executeHttpRequest
as intended.- Webhook configuration is provided via the
webhook
object.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check OTP input's HTTP request integration # Search for webhook configuration in OTP input files rg -A 10 'executeHttpRequest' --type typescript # Search for webhook block references in OTP-related files ast-grep --pattern 'type === "webhook"'Length of output: 124
Script:
#!/bin/bash # Re-run search for executeHttpRequest in OTP input files without the --type flag. echo "Searching for executeHttpRequest occurrences with context:" rg -A 10 'executeHttpRequest' echo "Searching for webhook configuration or references in OTP input files with context:" rg -A 10 'type === "webhook"'Length of output: 24720
packages/embeds/js/src/components/InputChatBlock.tsx (1)
7-7
: LGTM! The OTP input integration is well-implemented.The changes follow the established patterns in the codebase, with proper imports and consistent prop passing.
Also applies to: 26-26, 182-189
apps/builder/src/features/graph/components/nodes/block/SettingsPopoverContent.tsx (1)
6-6
: LGTM! The OTP settings integration is well-implemented.The changes follow the established patterns in the codebase, with proper imports and consistent prop passing.
Also applies to: 151-153
packages/bot-engine/src/schemas/api.ts (1)
11-11
: LGTM! The OTP schema integration is well-implemented.The changes follow the established patterns in the codebase, with proper schema imports and union type updates.
Also applies to: 354-354
button: z.string().optional(), | ||
}) | ||
.optional(), | ||
codeLength: z.number().optional(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add validation constraints for codeLength.
The codeLength
field should have minimum and maximum value constraints to ensure valid OTP lengths.
- codeLength: z.number().optional(),
+ codeLength: z.number().min(4).max(8).optional(),
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
codeLength: z.number().optional(), | |
codeLength: z.number().min(4).max(8).optional(), |
handleFocus: (e: FocusEvent) => void; | ||
handlePaste: (e: ClipboardEvent) => void; | ||
handleKeyDown: (e: KeyboardEvent) => void; | ||
handleInput: (e: any) => void; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Fix type safety for handleInput event.
The handleInput
event type is set to any
. Consider using a more specific type for better type safety.
- handleInput: (e: any) => void;
+ handleInput: (e: InputEvent) => void;
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
handleInput: (e: any) => void; | |
handleInput: (e: InputEvent) => void; |
<input | ||
type="text" | ||
ref={inputRef} | ||
class="text-input w-10 h-10 text-center text-lg font-extrabold text-slate-900 bg-slate-100 border border-transparent hover:border-slate-200 appearance-none rounded p-2 outline-none focus:bg-white focus:border-indigo-400 focus:ring-2 focus:ring-indigo-100" | ||
pattern="\d*" | ||
maxlength="1" | ||
/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance input accessibility and validation.
The input element needs accessibility improvements and stronger validation.
<input
type="text"
ref={inputRef}
+ aria-label="OTP digit input"
+ inputMode="numeric"
class="text-input w-10 h-10 text-center text-lg font-extrabold text-slate-900 bg-slate-100 border border-transparent hover:border-slate-200 appearance-none rounded p-2 outline-none focus:bg-white focus:border-indigo-400 focus:ring-2 focus:ring-indigo-100"
- pattern="\d*"
+ pattern="[0-9]*"
maxlength="1"
+ autocomplete="one-time-code"
/>
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
<input | |
type="text" | |
ref={inputRef} | |
class="text-input w-10 h-10 text-center text-lg font-extrabold text-slate-900 bg-slate-100 border border-transparent hover:border-slate-200 appearance-none rounded p-2 outline-none focus:bg-white focus:border-indigo-400 focus:ring-2 focus:ring-indigo-100" | |
pattern="\d*" | |
maxlength="1" | |
/> | |
<input | |
type="text" | |
ref={inputRef} | |
aria-label="OTP digit input" | |
inputMode="numeric" | |
class="text-input w-10 h-10 text-center text-lg font-extrabold text-slate-900 bg-slate-100 border border-transparent hover:border-slate-200 appearance-none rounded p-2 outline-none focus:bg-white focus:border-indigo-400 focus:ring-2 focus:ring-indigo-100" | |
pattern="[0-9]*" | |
maxlength="1" | |
autocomplete="one-time-code" | |
/> |
<TextInput | ||
placeholder="Paste URL..." | ||
defaultValue={options?.webhook?.url} | ||
onChange={updateUrl} | ||
/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add URL validation for webhook endpoint.
The webhook URL input should include validation to ensure a valid URL format.
<TextInput
placeholder="Paste URL..."
defaultValue={options?.webhook?.url}
+ pattern="https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)"
+ title="Please enter a valid URL"
onChange={updateUrl}
/>
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
<TextInput | |
placeholder="Paste URL..." | |
defaultValue={options?.webhook?.url} | |
onChange={updateUrl} | |
/> | |
<TextInput | |
placeholder="Paste URL..." | |
defaultValue={options?.webhook?.url} | |
pattern="https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)" | |
title="Please enter a valid URL" | |
onChange={updateUrl} | |
/> |
const setLocalWebhook = async (newLocalWebhook: HttpRequest) => { | ||
onOptionsChange({ ...options, webhook: newLocalWebhook }); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add error handling for webhook configuration.
The setLocalWebhook
function should include error handling for failed webhook updates.
const setLocalWebhook = async (newLocalWebhook: HttpRequest) => {
+ try {
onOptionsChange({ ...options, webhook: newLocalWebhook });
+ } catch (error) {
+ console.error('Failed to update webhook:', error);
+ // Add error handling UI feedback
+ }
};
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const setLocalWebhook = async (newLocalWebhook: HttpRequest) => { | |
onOptionsChange({ ...options, webhook: newLocalWebhook }); | |
}; | |
const setLocalWebhook = async (newLocalWebhook: HttpRequest) => { | |
try { | |
onOptionsChange({ ...options, webhook: newLocalWebhook }); | |
} catch (error) { | |
console.error('Failed to update webhook:', error); | |
// Add error handling UI feedback | |
} | |
}; |
const inputs: any[] = []; | ||
const codeLength = props.block.options?.codeLength ?? 4; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Type the inputs array properly.
Replace any[]
with a proper type for better type safety.
- const inputs: any[] = [];
+ const inputs: HTMLInputElement[] = [];
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const inputs: any[] = []; | |
const codeLength = props.block.options?.codeLength ?? 4; | |
const inputs: HTMLInputElement[] = []; | |
const codeLength = props.block.options?.codeLength ?? 4; |
const [inputValue, setInputValue] = createSignal(props.defaultValue ?? ""); | ||
let submitRef: HTMLButtonElement | undefined; | ||
const inputs: any[] = []; | ||
const codeLength = props.block.options?.codeLength ?? 4; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add validation for minimum code length.
Add validation to ensure the code length is at least 4 digits for security.
- const codeLength = props.block.options?.codeLength ?? 4;
+ const codeLength = Math.max(props.block.options?.codeLength ?? 4, 4);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const codeLength = props.block.options?.codeLength ?? 4; | |
const codeLength = Math.max(props.block.options?.codeLength ?? 4, 4); |
const execute = async () => { | ||
console.log("execute HTTP Request"); | ||
JSON.stringify(props.block.options?.webhook); | ||
if (!props.block.options?.webhook) return; | ||
const webhook = props.block.options?.webhook; | ||
|
||
const response = await executeHttpRequest({ | ||
url: webhook.url ?? "", | ||
method: webhook.method ?? HttpMethod.POST, | ||
headers: webhook.headers?.reduce( | ||
(acc, header) => { | ||
acc[header.key ?? ""] = header.value ?? ""; | ||
return acc; | ||
}, | ||
{} as Record<string, string>, | ||
), | ||
body: webhook.body ?? "", | ||
}); | ||
return { replyToSend: response }; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add error handling and loading state for HTTP request.
The HTTP request execution needs proper error handling and should indicate loading state to the user.
const execute = async () => {
+ const [isLoading, setIsLoading] = createSignal(false);
if (!props.block.options?.webhook) return;
const webhook = props.block.options?.webhook;
+ setIsLoading(true);
+ try {
const response = await executeHttpRequest({
url: webhook.url ?? "",
method: webhook.method ?? HttpMethod.POST,
headers: webhook.headers?.reduce(
(acc, header) => {
acc[header.key ?? ""] = header.value ?? "";
return acc;
},
{} as Record<string, string>,
),
body: webhook.body ?? "",
});
return { replyToSend: response };
+ } catch (error) {
+ console.error('Failed to execute HTTP request:', error);
+ // Handle error appropriately
+ } finally {
+ setIsLoading(false);
+ }
};
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const execute = async () => { | |
console.log("execute HTTP Request"); | |
JSON.stringify(props.block.options?.webhook); | |
if (!props.block.options?.webhook) return; | |
const webhook = props.block.options?.webhook; | |
const response = await executeHttpRequest({ | |
url: webhook.url ?? "", | |
method: webhook.method ?? HttpMethod.POST, | |
headers: webhook.headers?.reduce( | |
(acc, header) => { | |
acc[header.key ?? ""] = header.value ?? ""; | |
return acc; | |
}, | |
{} as Record<string, string>, | |
), | |
body: webhook.body ?? "", | |
}); | |
return { replyToSend: response }; | |
}; | |
const execute = async () => { | |
const [isLoading, setIsLoading] = createSignal(false); | |
console.log("execute HTTP Request"); | |
JSON.stringify(props.block.options?.webhook); | |
if (!props.block.options?.webhook) return; | |
const webhook = props.block.options?.webhook; | |
setIsLoading(true); | |
try { | |
const response = await executeHttpRequest({ | |
url: webhook.url ?? "", | |
method: webhook.method ?? HttpMethod.POST, | |
headers: webhook.headers?.reduce( | |
(acc, header) => { | |
acc[header.key ?? ""] = header.value ?? ""; | |
return acc; | |
}, | |
{} as Record<string, string>, | |
), | |
body: webhook.body ?? "", | |
}); | |
return { replyToSend: response }; | |
} catch (error) { | |
console.error('Failed to execute HTTP request:', error); | |
// Handle error appropriately | |
} finally { | |
setIsLoading(false); | |
} | |
}; |
case InputBlockType.OTP: { | ||
if (!reply || reply.type !== "text") return { status: "fail" }; | ||
return { status: "success", reply: reply.text }; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add OTP format validation.
The current implementation accepts any text input as a valid OTP. Consider adding validation to ensure:
- The OTP matches the expected format (numeric, alphanumeric)
- The OTP length matches the configured length
- The OTP characters are valid for the configured character set
Example validation:
case InputBlockType.OTP: {
if (!reply || reply.type !== "text") return { status: "fail" };
+ const { length = 6, format = "numeric" } = block.options ?? {};
+ const isValidFormat = format === "numeric"
+ ? /^\d+$/.test(reply.text)
+ : /^[A-Za-z0-9]+$/.test(reply.text);
+ if (!isValidFormat || reply.text.length !== length) return { status: "fail" };
return { status: "success", reply: reply.text };
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
case InputBlockType.OTP: { | |
if (!reply || reply.type !== "text") return { status: "fail" }; | |
return { status: "success", reply: reply.text }; | |
} | |
case InputBlockType.OTP: { | |
if (!reply || reply.type !== "text") return { status: "fail" }; | |
const { length = 6, format = "numeric" } = block.options ?? {}; | |
const isValidFormat = format === "numeric" | |
? /^\d+$/.test(reply.text) | |
: /^[A-Za-z0-9]+$/.test(reply.text); | |
if (!isValidFormat || reply.text.length !== length) return { status: "fail" }; | |
return { status: "success", reply: reply.text }; | |
} |
Following our discussion from #1985, what is your plan? |
#1985
@baptisteArno - Need some help with this one please :) have it mostly working but it's failing when it calls the executeHttpRequest method from OtpInput.tsx to request an OTP code. I think I'm pretty close but I suspect it's an issue with the schema I used from the httpRequest integration as it's not finding the webhook block that was configured.
Sample flow atttached:
typebot-export-my-typebot-0jjmdsp.json