mirror of
https://github.com/baptisteArno/typebot.io.git
synced 2026-06-05 21:04:43 +08:00
🔧 Protect preview chat with enforced auth
This commit is contained in:
parent
57aa0a4aee
commit
d96f572e60
@ -17,6 +17,7 @@ All scripts must be ran with `bunx nx`:
|
||||
|
||||
- Typescript project references can be automatically updated with `bunx nx sync`.
|
||||
- Most of the scripts are inferred with nx plugins. A few examples:
|
||||
- fastest way to typecheck `builder` and/or `viewer`: run root `bunx nx typecheck` (runs `tsc --build --emitDeclarationOnly`)
|
||||
- typecheck a particular package: `bunx nx typecheck package_name`.
|
||||
- test a package: `bunx nx test package_name`
|
||||
- typecheck all afffected packages: `bunx nx affected -t typecheck` (**IMPORTANT**: Rely first on IDE's TS server diagnostics first for faster feedback loop)
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { ORPCError } from "@orpc/server";
|
||||
import { authRouter } from "@typebot.io/auth/api/router";
|
||||
import { billingRouter } from "@typebot.io/billing/api/router";
|
||||
import { builderChatRouter } from "@typebot.io/bot-engine/api/router";
|
||||
import { publicProcedure } from "@typebot.io/config/orpc/builder/middlewares";
|
||||
import { featureFlagsRouter } from "@typebot.io/feature-flags/orpc/router";
|
||||
import { fileUploadBuilderRouter } from "@typebot.io/file-input-block/api/router";
|
||||
@ -77,6 +78,7 @@ export const appRouter: AppRouter = {
|
||||
email: emailRouter,
|
||||
telemetry: telemetryRouter,
|
||||
generateGroupTitle,
|
||||
chat: builderChatRouter,
|
||||
credentials: credentialsRouter,
|
||||
featureFlags: featureFlagsRouter,
|
||||
auth: authRouter,
|
||||
@ -107,6 +109,7 @@ export type AppRouter = {
|
||||
email: typeof emailRouter;
|
||||
telemetry: typeof telemetryRouter;
|
||||
generateGroupTitle: typeof generateGroupTitle;
|
||||
chat: typeof builderChatRouter;
|
||||
credentials: typeof credentialsRouter;
|
||||
featureFlags: typeof featureFlagsRouter;
|
||||
auth: typeof authRouter;
|
||||
|
||||
@ -31,6 +31,7 @@ export const WebPreview = () => {
|
||||
<Standard
|
||||
key={`web-preview-${startPreviewFrom?.id ?? ""}`}
|
||||
typebot={typebot}
|
||||
apiHost={window.location.origin}
|
||||
sessionId={user ? `${typebot.id}-${user.id}` : undefined}
|
||||
startFrom={
|
||||
startPreviewFrom?.type === "group"
|
||||
|
||||
@ -18,6 +18,7 @@ export const SettingsPage = () => {
|
||||
{typebot && (
|
||||
<Standard
|
||||
typebot={typebot}
|
||||
apiHost={window.location.origin}
|
||||
style={{
|
||||
borderRadius: "0.75rem",
|
||||
width: "100%",
|
||||
|
||||
@ -173,6 +173,7 @@ export const TemplatesDialog = ({
|
||||
<Standard
|
||||
key={typebot.id}
|
||||
typebot={typebot}
|
||||
apiHost={window.location.origin}
|
||||
style={{
|
||||
borderRadius: "0.25rem",
|
||||
backgroundColor: "#fff",
|
||||
|
||||
@ -18,6 +18,7 @@ export const ThemePage = () => {
|
||||
{typebot && (
|
||||
<Standard
|
||||
typebot={typebot}
|
||||
apiHost={window.location.origin}
|
||||
style={{
|
||||
borderRadius: "0.75rem",
|
||||
width: "100%",
|
||||
|
||||
@ -3,6 +3,7 @@ import {
|
||||
startChatResponseSchema,
|
||||
startPreviewChatResponseSchema,
|
||||
} from "@typebot.io/chat-api/schemas";
|
||||
import { authenticatedProcedure } from "@typebot.io/config/orpc/builder/middlewares";
|
||||
import {
|
||||
procedureWithOptionalUser,
|
||||
protectedProcedure,
|
||||
@ -37,6 +38,33 @@ import {
|
||||
import { handleSendMessageV1 } from "./legacy/handleSendMessageV1";
|
||||
import { handleSendMessageV2 } from "./legacy/handleSendMessageV2";
|
||||
|
||||
export const builderChatRouter = {
|
||||
continueChatProcedure: authenticatedProcedure
|
||||
.route({
|
||||
method: "POST",
|
||||
path: "/v1/sessions/{sessionId}/continueChat",
|
||||
})
|
||||
.input(continueChatInputSchema)
|
||||
.output(continueChatResponseSchema)
|
||||
.handler(({ input }) =>
|
||||
handleContinueChat({
|
||||
input,
|
||||
context: {
|
||||
origin: undefined,
|
||||
iframeReferrerOrigin: undefined,
|
||||
},
|
||||
}),
|
||||
),
|
||||
startChatPreviewProcedure: authenticatedProcedure
|
||||
.route({
|
||||
method: "POST",
|
||||
path: "/v1/typebots/{typebotId}/preview/startChat",
|
||||
})
|
||||
.input(startPreviewChatInputSchema)
|
||||
.output(startPreviewChatResponseSchema)
|
||||
.handler(handleStartChatPreview),
|
||||
};
|
||||
|
||||
export const chatRouter = {
|
||||
startChatProcedure: publicProcedure
|
||||
.route({
|
||||
@ -68,7 +96,7 @@ export const chatRouter = {
|
||||
.input(saveClientLogsInputSchema)
|
||||
.output(z.object({ message: z.string() }))
|
||||
.handler(handleSaveClientLogs),
|
||||
startChatPreviewProcedure: procedureWithOptionalUser
|
||||
startChatPreviewProcedure: protectedProcedure
|
||||
.route({
|
||||
method: "POST",
|
||||
path: "/v1/typebots/{typebotId}/preview/startChat",
|
||||
|
||||
@ -312,7 +312,9 @@ const parseEmailRecipient = (
|
||||
): { email?: string; name?: string } => {
|
||||
if (!recipient) return {};
|
||||
|
||||
const namedRecipientMatch = recipient.match(/^(?<name>[^<]+)<(?<email>[^>]+)>$/);
|
||||
const namedRecipientMatch = recipient.match(
|
||||
/^(?<name>[^<]+)<(?<email>[^>]+)>$/,
|
||||
);
|
||||
const email = namedRecipientMatch?.groups?.email?.trim();
|
||||
const name = namedRecipientMatch?.groups?.name?.trim().replaceAll('"', "");
|
||||
|
||||
|
||||
@ -332,14 +332,14 @@ export const startSession = async ({
|
||||
};
|
||||
|
||||
const getTypebot = async (startParams: StartParams) => {
|
||||
if (startParams.type === "preview" && startParams.typebot)
|
||||
return startParams.typebot;
|
||||
|
||||
if (startParams.type === "preview" && !startParams.userId)
|
||||
throw new ORPCError("UNAUTHORIZED", {
|
||||
message: "You need to be authenticated to perform this action",
|
||||
});
|
||||
|
||||
if (startParams.type === "preview" && startParams.typebot)
|
||||
return startParams.typebot;
|
||||
|
||||
const typebotQuery =
|
||||
startParams.type === "preview"
|
||||
? await findTypebot({
|
||||
|
||||
Loading…
Reference in New Issue
Block a user