🛂 Add isSuspended prop on workspace
This commit is contained in:
@ -6,7 +6,7 @@ import {
|
|||||||
useMemo,
|
useMemo,
|
||||||
useState,
|
useState,
|
||||||
} from 'react'
|
} from 'react'
|
||||||
import { byId } from '@typebot.io/lib'
|
import { byId, isNotDefined } from '@typebot.io/lib'
|
||||||
import { WorkspaceRole } from '@typebot.io/prisma'
|
import { WorkspaceRole } from '@typebot.io/prisma'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { trpc } from '@/lib/trpc'
|
import { trpc } from '@/lib/trpc'
|
||||||
@ -39,7 +39,7 @@ export const WorkspaceProvider = ({
|
|||||||
typebotId,
|
typebotId,
|
||||||
children,
|
children,
|
||||||
}: WorkspaceContextProps) => {
|
}: WorkspaceContextProps) => {
|
||||||
const { query } = useRouter()
|
const { pathname, query, push } = useRouter()
|
||||||
const { user } = useUser()
|
const { user } = useUser()
|
||||||
const userId = user?.id
|
const userId = user?.id
|
||||||
const [workspaceId, setWorkspaceId] = useState<string | undefined>()
|
const [workspaceId, setWorkspaceId] = useState<string | undefined>()
|
||||||
@ -132,9 +132,18 @@ export const WorkspaceProvider = ({
|
|||||||
workspaces,
|
workspaces,
|
||||||
])
|
])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isNotDefined(workspace?.isSuspended)) return
|
||||||
|
if (workspace?.isSuspended && pathname !== '/suspended') push('/suspended')
|
||||||
|
}, [pathname, push, workspace?.isSuspended])
|
||||||
|
|
||||||
const switchWorkspace = (workspaceId: string) => {
|
const switchWorkspace = (workspaceId: string) => {
|
||||||
setWorkspaceId(workspaceId)
|
|
||||||
setWorkspaceIdInLocalStorage(workspaceId)
|
setWorkspaceIdInLocalStorage(workspaceId)
|
||||||
|
if (pathname === '/suspended') {
|
||||||
|
window.location.href = '/typebots'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setWorkspaceId(workspaceId)
|
||||||
}
|
}
|
||||||
|
|
||||||
const createWorkspace = async (userFullName?: string) => {
|
const createWorkspace = async (userFullName?: string) => {
|
||||||
|
31
apps/builder/src/pages/suspended.tsx
Normal file
31
apps/builder/src/pages/suspended.tsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { TextLink } from '@/components/TextLink'
|
||||||
|
import { DashboardHeader } from '@/features/dashboard/components/DashboardHeader'
|
||||||
|
import { WorkspaceProvider } from '@/features/workspace/WorkspaceProvider'
|
||||||
|
import { Heading, Link, Text, VStack } from '@chakra-ui/react'
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<WorkspaceProvider>
|
||||||
|
<DashboardHeader />
|
||||||
|
<VStack w="full" h="calc(100vh - 64px)" justifyContent="center">
|
||||||
|
<Heading>Your workspace has been suspended.</Heading>
|
||||||
|
<Text>
|
||||||
|
We detected that one of your typebots does not comply with our{' '}
|
||||||
|
<TextLink
|
||||||
|
href="https://typebot.io/terms-of-service#scam-typebots"
|
||||||
|
isExternal
|
||||||
|
>
|
||||||
|
terms of service
|
||||||
|
</TextLink>
|
||||||
|
</Text>
|
||||||
|
<Text>
|
||||||
|
If you think it's a mistake, feel free to{' '}
|
||||||
|
<Link href="mailto:baptiste@typebot.io" textDecor="underline">
|
||||||
|
reach out
|
||||||
|
</Link>
|
||||||
|
.
|
||||||
|
</Text>
|
||||||
|
</VStack>
|
||||||
|
</WorkspaceProvider>
|
||||||
|
)
|
||||||
|
}
|
@ -3900,6 +3900,9 @@
|
|||||||
},
|
},
|
||||||
"isQuarantined": {
|
"isQuarantined": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isSuspended": {
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@ -3919,7 +3922,8 @@
|
|||||||
"customChatsLimit",
|
"customChatsLimit",
|
||||||
"customStorageLimit",
|
"customStorageLimit",
|
||||||
"customSeatsLimit",
|
"customSeatsLimit",
|
||||||
"isQuarantined"
|
"isQuarantined",
|
||||||
|
"isSuspended"
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
@ -4045,6 +4049,9 @@
|
|||||||
},
|
},
|
||||||
"isQuarantined": {
|
"isQuarantined": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isSuspended": {
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@ -4064,7 +4071,8 @@
|
|||||||
"customChatsLimit",
|
"customChatsLimit",
|
||||||
"customStorageLimit",
|
"customStorageLimit",
|
||||||
"customSeatsLimit",
|
"customSeatsLimit",
|
||||||
"isQuarantined"
|
"isQuarantined",
|
||||||
|
"isSuspended"
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
@ -4207,6 +4215,9 @@
|
|||||||
},
|
},
|
||||||
"isQuarantined": {
|
"isQuarantined": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isSuspended": {
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@ -4226,7 +4237,8 @@
|
|||||||
"customChatsLimit",
|
"customChatsLimit",
|
||||||
"customStorageLimit",
|
"customStorageLimit",
|
||||||
"customSeatsLimit",
|
"customSeatsLimit",
|
||||||
"isQuarantined"
|
"isQuarantined",
|
||||||
|
"isSuspended"
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
@ -5472,6 +5484,9 @@
|
|||||||
},
|
},
|
||||||
"isQuarantined": {
|
"isQuarantined": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isSuspended": {
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@ -5491,7 +5506,8 @@
|
|||||||
"customChatsLimit",
|
"customChatsLimit",
|
||||||
"customStorageLimit",
|
"customStorageLimit",
|
||||||
"customSeatsLimit",
|
"customSeatsLimit",
|
||||||
"isQuarantined"
|
"isQuarantined",
|
||||||
|
"isSuspended"
|
||||||
],
|
],
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"nullable": true
|
"nullable": true
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Stack, Heading } from '@chakra-ui/react'
|
import { Stack, Heading } from '@chakra-ui/react'
|
||||||
import { Header } from 'components/common/Header/Header'
|
import { Header } from 'components/common/Header/Header'
|
||||||
import { SocialMetaTags } from 'components/common/SocialMetaTags'
|
import { SocialMetaTags } from 'components/common/SocialMetaTags'
|
||||||
|
import { TextLink } from 'components/common/TextLink'
|
||||||
|
|
||||||
const PrivacyPolicies = () => {
|
const PrivacyPolicies = () => {
|
||||||
return (
|
return (
|
||||||
@ -117,11 +118,26 @@ const PrivacyPolicies = () => {
|
|||||||
bound by the current version of these Terms and Conditions of Use.
|
bound by the current version of these Terms and Conditions of Use.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<Heading>8. Your Privacy</Heading>
|
<Heading id="scam-typebots">8. Prohibition of Scam Typebots</Heading>
|
||||||
|
<p>
|
||||||
|
You agree not to create or use typebots on Typebot's Website for
|
||||||
|
the purpose of engaging in fraudulent activities, scamming
|
||||||
|
individuals, or any other unethical or illegal activities. This
|
||||||
|
includes but is not limited to typebots designed to deceive, defraud,
|
||||||
|
or mislead people for financial gain or personal benefit. Typebot
|
||||||
|
reserves the right to take appropriate action, including the
|
||||||
|
termination of any user account, if it determines that a typebot is
|
||||||
|
being used in violation of this provision.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>Please read our Privacy Policy.</p>
|
<Heading>9. Your Privacy</Heading>
|
||||||
|
|
||||||
<Heading>9. Governing Law</Heading>
|
<p>
|
||||||
|
Please read our{' '}
|
||||||
|
<TextLink href={'/privacy-policies'}>Privacy Policy</TextLink>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<Heading>10. Governing Law</Heading>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Any claim related to Typebot's Website shall be governed by the
|
Any claim related to Typebot's Website shall be governed by the
|
||||||
|
@ -301,6 +301,7 @@ const getTypebot = async (
|
|||||||
additionalChatsIndex: true,
|
additionalChatsIndex: true,
|
||||||
customChatsLimit: true,
|
customChatsLimit: true,
|
||||||
isQuarantined: true,
|
isQuarantined: true,
|
||||||
|
isSuspended: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -326,12 +327,16 @@ const getTypebot = async (
|
|||||||
message: 'Typebot not found',
|
message: 'Typebot not found',
|
||||||
})
|
})
|
||||||
|
|
||||||
const isQuarantined =
|
const isQuarantinedOrSuspended =
|
||||||
typebotQuery &&
|
typebotQuery &&
|
||||||
'typebot' in typebotQuery &&
|
'typebot' in typebotQuery &&
|
||||||
typebotQuery.typebot.workspace.isQuarantined
|
(typebotQuery.typebot.workspace.isQuarantined ||
|
||||||
|
typebotQuery.typebot.workspace.isSuspended)
|
||||||
|
|
||||||
if (('isClosed' in parsedTypebot && parsedTypebot.isClosed) || isQuarantined)
|
if (
|
||||||
|
('isClosed' in parsedTypebot && parsedTypebot.isClosed) ||
|
||||||
|
isQuarantinedOrSuspended
|
||||||
|
)
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: 'BAD_REQUEST',
|
code: 'BAD_REQUEST',
|
||||||
message: 'Typebot is closed',
|
message: 'Typebot is closed',
|
||||||
|
@ -97,6 +97,7 @@ model Workspace {
|
|||||||
customStorageLimit Int?
|
customStorageLimit Int?
|
||||||
customSeatsLimit Int?
|
customSeatsLimit Int?
|
||||||
isQuarantined Boolean @default(false)
|
isQuarantined Boolean @default(false)
|
||||||
|
isSuspended Boolean @default(false)
|
||||||
themeTemplates ThemeTemplate[]
|
themeTemplates ThemeTemplate[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Workspace" ADD COLUMN "isSuspended" BOOLEAN NOT NULL DEFAULT false;
|
@ -91,6 +91,7 @@ model Workspace {
|
|||||||
customStorageLimit Int?
|
customStorageLimit Int?
|
||||||
customSeatsLimit Int?
|
customSeatsLimit Int?
|
||||||
isQuarantined Boolean @default(false)
|
isQuarantined Boolean @default(false)
|
||||||
|
isSuspended Boolean @default(false)
|
||||||
themeTemplates ThemeTemplate[]
|
themeTemplates ThemeTemplate[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +49,7 @@ export const workspaceSchema = z.object({
|
|||||||
customStorageLimit: z.number().nullable(),
|
customStorageLimit: z.number().nullable(),
|
||||||
customSeatsLimit: z.number().nullable(),
|
customSeatsLimit: z.number().nullable(),
|
||||||
isQuarantined: z.boolean(),
|
isQuarantined: z.boolean(),
|
||||||
|
isSuspended: z.boolean(),
|
||||||
}) satisfies z.ZodType<WorkspacePrisma>
|
}) satisfies z.ZodType<WorkspacePrisma>
|
||||||
|
|
||||||
export type Workspace = z.infer<typeof workspaceSchema>
|
export type Workspace = z.infer<typeof workspaceSchema>
|
||||||
|
Reference in New Issue
Block a user