@@ -8,6 +8,9 @@ import { smtpCredentialsSchema } from '@typebot.io/schemas/features/blocks/integ
|
||||
import { encrypt } from '@typebot.io/lib/api/encryption'
|
||||
import { z } from 'zod'
|
||||
import { isWriteWorkspaceForbidden } from '@/features/workspace/helpers/isWriteWorkspaceForbidden copy'
|
||||
import { whatsAppCredentialsSchema } from '@typebot.io/schemas/features/whatsapp'
|
||||
import { Credentials } from '@typebot.io/schemas'
|
||||
import { isDefined } from '@typebot.io/lib/utils'
|
||||
|
||||
const inputShape = {
|
||||
data: true,
|
||||
@@ -33,6 +36,7 @@ export const createCredentials = authenticatedProcedure
|
||||
smtpCredentialsSchema.pick(inputShape),
|
||||
googleSheetsCredentialsSchema.pick(inputShape),
|
||||
openAICredentialsSchema.pick(inputShape),
|
||||
whatsAppCredentialsSchema.pick(inputShape),
|
||||
]),
|
||||
})
|
||||
)
|
||||
@@ -42,6 +46,11 @@ export const createCredentials = authenticatedProcedure
|
||||
})
|
||||
)
|
||||
.mutation(async ({ input: { credentials }, ctx: { user } }) => {
|
||||
if (await isNotAvailable(credentials.name, credentials.type))
|
||||
throw new TRPCError({
|
||||
code: 'CONFLICT',
|
||||
message: 'Credentials already exist.',
|
||||
})
|
||||
const workspace = await prisma.workspace.findFirst({
|
||||
where: {
|
||||
id: credentials.workspaceId,
|
||||
@@ -64,3 +73,14 @@ export const createCredentials = authenticatedProcedure
|
||||
})
|
||||
return { credentialsId: createdCredentials.id }
|
||||
})
|
||||
|
||||
const isNotAvailable = async (name: string, type: Credentials['type']) => {
|
||||
if (type !== 'whatsApp') return
|
||||
const existingCredentials = await prisma.credentials.findFirst({
|
||||
where: {
|
||||
type,
|
||||
name,
|
||||
},
|
||||
})
|
||||
return isDefined(existingCredentials)
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@ export const deleteCredentials = authenticatedProcedure
|
||||
const workspace = await prisma.workspace.findFirst({
|
||||
where: {
|
||||
id: workspaceId,
|
||||
members: {
|
||||
some: { userId: user.id, role: { in: ['ADMIN', 'MEMBER'] } },
|
||||
},
|
||||
},
|
||||
select: { id: true, members: true },
|
||||
})
|
||||
|
||||
@@ -7,6 +7,7 @@ import { openAICredentialsSchema } from '@typebot.io/schemas/features/blocks/int
|
||||
import { smtpCredentialsSchema } from '@typebot.io/schemas/features/blocks/integrations/sendEmail'
|
||||
import { z } from 'zod'
|
||||
import { isReadWorkspaceFobidden } from '@/features/workspace/helpers/isReadWorkspaceFobidden'
|
||||
import { whatsAppCredentialsSchema } from '@typebot.io/schemas/features/whatsapp'
|
||||
|
||||
export const listCredentials = authenticatedProcedure
|
||||
.meta({
|
||||
@@ -24,7 +25,8 @@ export const listCredentials = authenticatedProcedure
|
||||
type: stripeCredentialsSchema.shape.type
|
||||
.or(smtpCredentialsSchema.shape.type)
|
||||
.or(googleSheetsCredentialsSchema.shape.type)
|
||||
.or(openAICredentialsSchema.shape.type),
|
||||
.or(openAICredentialsSchema.shape.type)
|
||||
.or(whatsAppCredentialsSchema.shape.type),
|
||||
})
|
||||
)
|
||||
.output(
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {
|
||||
Button,
|
||||
ButtonProps,
|
||||
IconButton,
|
||||
Menu,
|
||||
MenuButton,
|
||||
MenuButtonProps,
|
||||
MenuItem,
|
||||
MenuList,
|
||||
Stack,
|
||||
@@ -16,13 +16,14 @@ import { useToast } from '../../../hooks/useToast'
|
||||
import { Credentials } from '@typebot.io/schemas'
|
||||
import { trpc } from '@/lib/trpc'
|
||||
|
||||
type Props = Omit<MenuButtonProps, 'type'> & {
|
||||
type Props = Omit<ButtonProps, 'type'> & {
|
||||
type: Credentials['type']
|
||||
workspaceId: string
|
||||
currentCredentialsId?: string
|
||||
onCredentialsSelect: (credentialId?: string) => void
|
||||
onCreateNewClick: () => void
|
||||
defaultCredentialLabel?: string
|
||||
credentialsName: string
|
||||
}
|
||||
|
||||
export const CredentialsDropdown = ({
|
||||
@@ -32,6 +33,7 @@ export const CredentialsDropdown = ({
|
||||
onCredentialsSelect,
|
||||
onCreateNewClick,
|
||||
defaultCredentialLabel,
|
||||
credentialsName,
|
||||
...props
|
||||
}: Props) => {
|
||||
const router = useRouter()
|
||||
@@ -59,7 +61,8 @@ export const CredentialsDropdown = ({
|
||||
},
|
||||
})
|
||||
|
||||
const defaultCredentialsLabel = defaultCredentialLabel ?? `Select an account`
|
||||
const defaultCredentialsLabel =
|
||||
defaultCredentialLabel ?? `Select ${credentialsName}`
|
||||
|
||||
const currentCredential = data?.credentials.find(
|
||||
(c) => c.id === currentCredentialsId
|
||||
@@ -97,6 +100,19 @@ export const CredentialsDropdown = ({
|
||||
mutate({ workspaceId, credentialsId })
|
||||
}
|
||||
|
||||
if (data?.credentials.length === 0 && !defaultCredentialLabel) {
|
||||
return (
|
||||
<Button
|
||||
colorScheme="gray"
|
||||
textAlign="left"
|
||||
leftIcon={<PlusIcon />}
|
||||
onClick={onCreateNewClick}
|
||||
{...props}
|
||||
>
|
||||
Add {credentialsName}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Menu isLazy>
|
||||
<MenuButton
|
||||
@@ -107,7 +123,11 @@ export const CredentialsDropdown = ({
|
||||
textAlign="left"
|
||||
{...props}
|
||||
>
|
||||
<Text noOfLines={1} overflowY="visible" h="20px">
|
||||
<Text
|
||||
noOfLines={1}
|
||||
overflowY="visible"
|
||||
h={props.size === 'sm' ? '18px' : '20px'}
|
||||
>
|
||||
{currentCredential ? currentCredential.name : defaultCredentialsLabel}
|
||||
</Text>
|
||||
</MenuButton>
|
||||
|
||||
Reference in New Issue
Block a user