fix(auth): handle unregistered users in authentication flow
- Updated the authentication logic in both Auth and useAuth functions to redirect unregistered users to the '/unregistered' page. - Enhanced error handling in the authOptions to check for user registration status using the Telegram ID. - Improved the matcher configuration in middleware to exclude the '/unregistered' route from authentication checks.
This commit is contained in:
parent
c9187816a1
commit
17ce24ae04
@ -23,6 +23,17 @@ export default function Auth() {
|
||||
callbackUrl: '/profile',
|
||||
redirect: false,
|
||||
telegramId: user?.id?.toString(),
|
||||
}).then((result) => {
|
||||
if (
|
||||
result?.error &&
|
||||
(result?.error?.includes('CredentialsSignin') ||
|
||||
result?.error?.includes('UNREGISTERED'))
|
||||
) {
|
||||
// Пользователь не зарегистрирован
|
||||
redirect('/unregistered');
|
||||
} else if (result?.ok) {
|
||||
redirect('/profile');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -30,7 +30,17 @@ function useAuth() {
|
||||
callbackUrl: '/profile',
|
||||
redirect: false,
|
||||
telegramId: initDataUser.id.toString(),
|
||||
}).then(() => redirect('/profile'));
|
||||
}).then((result) => {
|
||||
if (
|
||||
result?.error &&
|
||||
(result?.error?.includes('CredentialsSignin') || result?.error?.includes('UNREGISTERED'))
|
||||
) {
|
||||
// Пользователь не зарегистрирован
|
||||
redirect('/unregistered');
|
||||
} else if (result?.ok) {
|
||||
redirect('/profile');
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [initDataUser?.id, status]);
|
||||
}
|
||||
|
||||
54
apps/web/app/(auth)/unregistered/page.tsx
Normal file
54
apps/web/app/(auth)/unregistered/page.tsx
Normal file
@ -0,0 +1,54 @@
|
||||
import { UnregisteredClient } from './unregistered-client';
|
||||
import { Container } from '@/components/layout';
|
||||
import { env } from '@/config/env';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@repo/ui/components/ui/card';
|
||||
import { Bot, MessageCircle } from 'lucide-react';
|
||||
|
||||
export default function UnregisteredPage() {
|
||||
return (
|
||||
<Container>
|
||||
<div className="flex min-h-screen items-center justify-center">
|
||||
<Card className="w-full max-w-md">
|
||||
<CardHeader className="text-center">
|
||||
<div className="mx-auto mb-4 flex size-16 items-center justify-center rounded-full bg-blue-100 dark:bg-blue-900/20">
|
||||
<Bot className="size-8 text-blue-600 dark:text-blue-400" />
|
||||
</div>
|
||||
<CardTitle className="text-xl">Давайте познакомимся</CardTitle>
|
||||
<CardDescription>
|
||||
Для использования приложения необходимо поделиться своим номером телефона с ботом
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="rounded-lg bg-muted p-4">
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-start gap-3">
|
||||
<MessageCircle className="mt-0.5 size-5 text-blue-500" />
|
||||
<div className="text-sm">
|
||||
<p className="mb-1 font-medium text-foreground">Как поделиться:</p>
|
||||
<ol className="list-inside list-decimal space-y-1 text-muted-foreground">
|
||||
<li>Вернитесь к Telegram боту</li>
|
||||
<li>
|
||||
Отправьте команду{' '}
|
||||
<code className="rounded bg-muted px-1 py-0.5 text-xs">/start</code>
|
||||
</li>
|
||||
<li>Нажмите на появившуюся кнопку "Отправить номер телефона"</li>
|
||||
<li>Закройте и откройте это приложение еще раз</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<UnregisteredClient botUrl={env.BOT_URL} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
37
apps/web/app/(auth)/unregistered/unregistered-client.tsx
Normal file
37
apps/web/app/(auth)/unregistered/unregistered-client.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
'use client';
|
||||
|
||||
import { Button } from '@repo/ui/components/ui/button';
|
||||
import { Bot, ExternalLink } from 'lucide-react';
|
||||
import Link from 'next/link';
|
||||
import { signOut } from 'next-auth/react';
|
||||
|
||||
type UnregisteredClientProps = {
|
||||
readonly botUrl: string;
|
||||
};
|
||||
|
||||
export function UnregisteredClient({ botUrl }: UnregisteredClientProps) {
|
||||
const handleSignOut = () => {
|
||||
signOut({ callbackUrl: '/' });
|
||||
};
|
||||
const handleRefresh = () => {
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
<Button asChild className="w-full">
|
||||
<Link href={botUrl} rel="noopener noreferrer" target="_blank">
|
||||
<Bot className="mr-2 size-4" />
|
||||
Перейти к боту
|
||||
<ExternalLink className="ml-2 size-4" />
|
||||
</Link>
|
||||
</Button>
|
||||
<Button className="w-full" onClick={handleRefresh} variant="outline">
|
||||
Обновить страницу
|
||||
</Button>
|
||||
<Button className="w-full" onClick={handleSignOut} variant="outline">
|
||||
Выйти из аккаунта
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,3 +1,5 @@
|
||||
import { getClientWithToken } from '@repo/graphql/apollo/client';
|
||||
import * as GQL from '@repo/graphql/types';
|
||||
import { type AuthOptions } from 'next-auth';
|
||||
import CredentialsProvider from 'next-auth/providers/credentials';
|
||||
|
||||
@ -32,7 +34,29 @@ export const authOptions: AuthOptions = {
|
||||
throw new TypeError('Invalid Telegram ID format');
|
||||
}
|
||||
|
||||
return { id: parsedTelegramId.toString(), telegramId: parsedTelegramId };
|
||||
try {
|
||||
// Проверяем, зарегистрирован ли пользователь
|
||||
const { query } = await getClientWithToken();
|
||||
const result = await query({
|
||||
query: GQL.GetCustomerDocument,
|
||||
variables: { telegramId: parsedTelegramId },
|
||||
});
|
||||
|
||||
const customer = result.data.customers.at(0);
|
||||
|
||||
if (!customer) {
|
||||
// Пользователь не зарегистрирован - перенаправляем на страницу регистрации
|
||||
throw new Error('UNREGISTERED');
|
||||
}
|
||||
|
||||
return { id: parsedTelegramId.toString(), telegramId: parsedTelegramId };
|
||||
} catch (error) {
|
||||
if (error instanceof Error && error.message.includes('UNREGISTERED')) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw new Error('Authentication failed');
|
||||
}
|
||||
},
|
||||
credentials: {
|
||||
telegramId: { label: 'Telegram ID', type: 'text' },
|
||||
|
||||
@ -11,5 +11,5 @@ export default withAuth({
|
||||
});
|
||||
|
||||
export const config = {
|
||||
matcher: ['/((?!auth|browser|telegram|api|_next/static|_next/image|favicon.ico).*)'],
|
||||
matcher: ['/((?!auth|browser|telegram|unregistered|api|_next/static|_next/image|favicon.ico).*)'],
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user