Add captcha support to authentication features

The update includes the implementation of captcha support during the sign-in and sign-up process for user accounts. The process ensures a better level of security against bot-based attacks. Also, the code has been refactored to separate error and success alerts and unnecessary useEffect hooks have been removed. Moreover, some logic concerning the authentication rendering has been simplified.
This commit is contained in:
giancarlo
2024-04-07 10:56:33 +08:00
parent 36bcf64f52
commit 0a9c1f35c6
16 changed files with 209 additions and 78 deletions

View File

@@ -10,16 +10,21 @@ import { Database } from '@kit/supabase/database';
import { requireUser } from '@kit/supabase/require-user';
import { getSupabaseServerActionClient } from '@kit/supabase/server-actions-client';
import { TeamCheckoutSchema } from '~/(dashboard)/home/[account]/_lib/schema/team-checkout.schema';
import appConfig from '~/config/app.config';
import billingConfig from '~/config/billing.config';
import pathsConfig from '~/config/paths.config';
import { TeamCheckoutSchema } from '../../_lib/schema/team-checkout.schema';
export class TeamBillingService {
private readonly namespace = 'billing.team-account';
constructor(private readonly client: SupabaseClient<Database>) {}
/**
* @name createCheckout
* @description Creates a checkout session for a Team account
*/
async createCheckout(params: z.infer<typeof TeamCheckoutSchema>) {
// we require the user to be authenticated
const { data: user } = await requireUser(this.client);
@@ -126,6 +131,12 @@ export class TeamBillingService {
}
}
/**
* @name createBillingPortalSession
* @description Creates a new billing portal session for a team account
* @param accountId
* @param slug
*/
async createBillingPortalSession({
accountId,
slug,

View File

@@ -4,13 +4,16 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryStreamedHydration } from '@tanstack/react-query-next-experimental';
import { ThemeProvider } from 'next-themes';
import { CaptchaProvider, CaptchaTokenSetter } from '@kit/auth/captcha';
import { I18nProvider } from '@kit/i18n/provider';
import { AuthChangeListener } from '@kit/supabase/components/auth-change-listener';
import appConfig from '~/config/app.config';
import authConfig from '~/config/auth.config';
import pathsConfig from '~/config/paths.config';
import { i18nResolver } from '~/lib/i18n/i18n.resolver';
const captchaSiteKey = authConfig.captchaTokenSiteKey;
const queryClient = new QueryClient();
export function RootProviders({
@@ -22,18 +25,22 @@ export function RootProviders({
return (
<QueryClientProvider client={queryClient}>
<ReactQueryStreamedHydration>
<AuthChangeListener appHomePath={pathsConfig.app.home}>
<I18nProvider lang={lang} resolver={i18nResolver}>
<ThemeProvider
attribute="class"
enableSystem
disableTransitionOnChange
defaultTheme={appConfig.theme}
>
{children}
</ThemeProvider>
</I18nProvider>
</AuthChangeListener>
<CaptchaProvider>
<CaptchaTokenSetter siteKey={captchaSiteKey} />
<AuthChangeListener appHomePath={pathsConfig.app.home}>
<I18nProvider lang={lang} resolver={i18nResolver}>
<ThemeProvider
attribute="class"
enableSystem
disableTransitionOnChange
defaultTheme={appConfig.theme}
>
{children}
</ThemeProvider>
</I18nProvider>
</AuthChangeListener>
</CaptchaProvider>
</ReactQueryStreamedHydration>
</QueryClientProvider>
);

View File

@@ -5,6 +5,7 @@ import { z } from 'zod';
const providers: z.ZodType<Provider> = getProviders();
const AuthConfigSchema = z.object({
captchaTokenSiteKey: z.string().min(1).optional(),
providers: z.object({
password: z.boolean({
description: 'Enable password authentication.',
@@ -17,6 +18,10 @@ const AuthConfigSchema = z.object({
});
const authConfig = AuthConfigSchema.parse({
// NB: This is a public key, so it's safe to expose.
// Copy the value from the Supabase Dashboard.
captchaTokenSiteKey: process.env.NEXT_PUBLIC_CAPTCHA_SITE_KEY ?? '',
// NB: Enable the providers below in the Supabase Console
// in your production project
providers: {

View File

@@ -32,6 +32,7 @@
"@kit/supabase": "workspace:^",
"@kit/team-accounts": "workspace:^",
"@kit/ui": "workspace:^",
"@marsidev/react-turnstile": "^0.5.4",
"@radix-ui/react-icons": "^1.3.0",
"@supabase/ssr": "^0.1.0",
"@supabase/supabase-js": "^2.42.0",

View File

@@ -63,6 +63,8 @@
"sendingEmailCode": "Sending code...",
"resetPasswordError": "Sorry, we could not reset your password. Please try again.",
"emailPlaceholder": "your@email.com",
"inviteAlertHeading": "You have been invited to join a team",
"inviteAlertBody": "You have been invited to join a team. Please sign in or sign up to accept the invite.",
"errors": {
"Invalid login credentials": "The credentials entered are invalid",
"User already registered": "This credential is already in use. Please try with another one.",