feat(account): 🗃️Add api token
This commit is contained in:
@@ -10,6 +10,8 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
Flex,
|
Flex,
|
||||||
Text,
|
Text,
|
||||||
|
InputRightElement,
|
||||||
|
InputGroup,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { UploadIcon } from 'assets/icons'
|
import { UploadIcon } from 'assets/icons'
|
||||||
import { UploadButton } from 'components/shared/buttons/UploadButton'
|
import { UploadButton } from 'components/shared/buttons/UploadButton'
|
||||||
@@ -27,6 +29,7 @@ export const PersonalInfoForm = () => {
|
|||||||
isOAuthProvider,
|
isOAuthProvider,
|
||||||
} = useUser()
|
} = useUser()
|
||||||
const [reloadParam, setReloadParam] = useState('')
|
const [reloadParam, setReloadParam] = useState('')
|
||||||
|
const [isApiTokenVisible, setIsApiTokenVisible] = useState(false)
|
||||||
|
|
||||||
const handleFileUploaded = async (url: string) => {
|
const handleFileUploaded = async (url: string) => {
|
||||||
setReloadParam(Date.now().toString())
|
setReloadParam(Date.now().toString())
|
||||||
@@ -41,6 +44,8 @@ export const PersonalInfoForm = () => {
|
|||||||
updateUser({ email: e.target.value })
|
updateUser({ email: e.target.value })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const toggleTokenVisibility = () => setIsApiTokenVisible(!isApiTokenVisible)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack direction="row" spacing="10" justifyContent={'space-between'}>
|
<Stack direction="row" spacing="10" justifyContent={'space-between'}>
|
||||||
<Heading as="h2" fontSize="xl">
|
<Heading as="h2" fontSize="xl">
|
||||||
@@ -99,6 +104,21 @@ export const PersonalInfoForm = () => {
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel htmlFor="name">API token</FormLabel>
|
||||||
|
<InputGroup>
|
||||||
|
<Input
|
||||||
|
id="token"
|
||||||
|
value={user?.apiToken ?? ''}
|
||||||
|
type={isApiTokenVisible ? 'text' : 'password'}
|
||||||
|
/>
|
||||||
|
<InputRightElement mr="3">
|
||||||
|
<Button size="xs" onClick={toggleTokenVisibility}>
|
||||||
|
{isApiTokenVisible ? 'Hide' : 'Show'}
|
||||||
|
</Button>
|
||||||
|
</InputRightElement>
|
||||||
|
</InputGroup>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
{hasUnsavedChanges && (
|
{hasUnsavedChanges && (
|
||||||
<Flex justifyContent="flex-end">
|
<Flex justifyContent="flex-end">
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ import FacebookProvider from 'next-auth/providers/facebook'
|
|||||||
import prisma from 'libs/prisma'
|
import prisma from 'libs/prisma'
|
||||||
import { Provider } from 'next-auth/providers'
|
import { Provider } from 'next-auth/providers'
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
|
import { isNotDefined } from 'utils'
|
||||||
|
import { User } from 'db'
|
||||||
|
import { randomUUID } from 'crypto'
|
||||||
|
|
||||||
const providers: Provider[] = [
|
const providers: Provider[] = [
|
||||||
EmailProvider({
|
EmailProvider({
|
||||||
@@ -19,13 +22,6 @@ const providers: Provider[] = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
from: `"${process.env.AUTH_EMAIL_FROM_NAME}" <${process.env.AUTH_EMAIL_FROM_EMAIL}>`,
|
from: `"${process.env.AUTH_EMAIL_FROM_NAME}" <${process.env.AUTH_EMAIL_FROM_EMAIL}>`,
|
||||||
// sendVerificationRequest({
|
|
||||||
// identifier: email,
|
|
||||||
// url,
|
|
||||||
// provider: { server, from },
|
|
||||||
// }) {
|
|
||||||
// console.log(url)
|
|
||||||
// },
|
|
||||||
}),
|
}),
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -62,9 +58,23 @@ const handler = (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
strategy: 'database',
|
strategy: 'database',
|
||||||
},
|
},
|
||||||
callbacks: {
|
callbacks: {
|
||||||
session: ({ session, user }) => ({ ...session, user }),
|
session: async ({ session, user }) => {
|
||||||
|
const userFromDb = user as User
|
||||||
|
if (isNotDefined(userFromDb.apiToken))
|
||||||
|
userFromDb.apiToken = await generateApiToken(userFromDb.id)
|
||||||
|
return { ...session, user: userFromDb }
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const generateApiToken = async (userId: string) => {
|
||||||
|
const apiToken = randomUUID()
|
||||||
|
await prisma.user.update({
|
||||||
|
where: { id: userId },
|
||||||
|
data: { apiToken },
|
||||||
|
})
|
||||||
|
return apiToken
|
||||||
|
}
|
||||||
|
|
||||||
export default handler
|
export default handler
|
||||||
|
|||||||
@@ -11,5 +11,5 @@
|
|||||||
|
|
||||||
For more info on what fields you can add: https://developers.mailerlite.com/reference/create-a-subscriber
|
For more info on what fields you can add: https://developers.mailerlite.com/reference/create-a-subscriber
|
||||||
|
|
||||||
4. Replace "YOUR_TOKEN" with your API token. It can be found here: https://app.mailerlite.com/integrations/api/
|
4. Replace "YOUR_TOKEN" with your API key. It can be found here: https://app.mailerlite.com/integrations/api/
|
||||||
5. Whenever the user enters his email it should add it to your subscribers' list on MailerLite
|
5. Whenever the user enters his email it should add it to your subscribers' list on MailerLite
|
||||||
|
|||||||
@@ -6,5 +6,8 @@ import * as Sentry from '@sentry/nextjs'
|
|||||||
|
|
||||||
Sentry.init({
|
Sentry.init({
|
||||||
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
||||||
ignoreErrors: ['ResizeObserver loop limit exceeded'],
|
ignoreErrors: [
|
||||||
|
'ResizeObserver loop limit exceeded',
|
||||||
|
'ResizeObserver loop completed with undelivered notifications.',
|
||||||
|
],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,5 +6,8 @@ import * as Sentry from '@sentry/nextjs'
|
|||||||
|
|
||||||
Sentry.init({
|
Sentry.init({
|
||||||
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
||||||
ignoreErrors: ['ResizeObserver loop limit exceeded'],
|
ignoreErrors: [
|
||||||
|
'ResizeObserver loop limit exceeded',
|
||||||
|
'ResizeObserver loop completed with undelivered notifications.',
|
||||||
|
],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "User" ADD COLUMN "apiToken" TEXT;
|
||||||
@@ -51,6 +51,7 @@ model User {
|
|||||||
stripeId String? @unique
|
stripeId String? @unique
|
||||||
credentials Credentials[]
|
credentials Credentials[]
|
||||||
customDomains CustomDomain[]
|
customDomains CustomDomain[]
|
||||||
|
apiToken String?
|
||||||
}
|
}
|
||||||
|
|
||||||
model CustomDomain {
|
model CustomDomain {
|
||||||
@@ -96,6 +97,7 @@ model DashboardFolder {
|
|||||||
parentFolder DashboardFolder? @relation("ParentChild", fields: [parentFolderId], references: [id])
|
parentFolder DashboardFolder? @relation("ParentChild", fields: [parentFolderId], references: [id])
|
||||||
childrenFolder DashboardFolder[] @relation("ParentChild")
|
childrenFolder DashboardFolder[] @relation("ParentChild")
|
||||||
typebots Typebot[]
|
typebots Typebot[]
|
||||||
|
|
||||||
@@unique([id, ownerId])
|
@@unique([id, ownerId])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,6 +120,7 @@ model Typebot {
|
|||||||
settings Json
|
settings Json
|
||||||
publicId String? @unique
|
publicId String? @unique
|
||||||
customDomain String? @unique
|
customDomain String? @unique
|
||||||
|
|
||||||
@@unique([id, ownerId])
|
@@unique([id, ownerId])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user