feat: add Google OAuth login with USER role and pending approval flow
- Add GET /api/auth/google and GET /api/auth/callback/google routes with CSRF state protection and account linking via googleId - Add getPublicOrigin() for dynamic redirect_uri (supports reverse proxy via X-Forwarded-Proto) - Add USER role to schema (default for new Google sign-ins), make password optional, add googleId and image fields - Role-based redirect after login: USER → /profile, ADMIN/DEVELOPER → /dashboard - Profile page shows pending approval alert for USER role - Dashboard redirects USER role back to profile - Login page shows specific error messages per OAuth error code Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
Alert,
|
||||
Avatar,
|
||||
Badge,
|
||||
Button,
|
||||
@@ -10,7 +11,7 @@ import {
|
||||
Title,
|
||||
} from '@mantine/core'
|
||||
import { createFileRoute, redirect } from '@tanstack/react-router'
|
||||
import { TbLogout, TbUser } from 'react-icons/tb'
|
||||
import { TbClock, TbLogout, TbUser } from 'react-icons/tb'
|
||||
import { useLogout, useSession } from '@/frontend/hooks/useAuth'
|
||||
|
||||
export const Route = createFileRoute('/profile')({
|
||||
@@ -30,6 +31,7 @@ export const Route = createFileRoute('/profile')({
|
||||
})
|
||||
|
||||
const roleBadgeColor: Record<string, string> = {
|
||||
USER: 'gray',
|
||||
ADMIN: 'violet',
|
||||
DEVELOPER: 'red',
|
||||
}
|
||||
@@ -55,9 +57,26 @@ function ProfilePage() {
|
||||
</Button>
|
||||
</Group>
|
||||
|
||||
{user?.role === 'USER' && (
|
||||
<Alert
|
||||
icon={<TbClock size={18} />}
|
||||
title="Akun Menunggu Persetujuan"
|
||||
color="yellow"
|
||||
variant="light"
|
||||
radius="md"
|
||||
>
|
||||
Akun kamu sedang menunggu persetujuan admin. Hubungi admin atau developer untuk mendapatkan akses ke fitur dashboard.
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<Paper withBorder p="xl" radius="md">
|
||||
<Stack align="center" gap="md">
|
||||
<Avatar color="blue" radius="xl" size={80}>
|
||||
<Avatar
|
||||
src={user?.image ?? undefined}
|
||||
color="blue"
|
||||
radius="xl"
|
||||
size={80}
|
||||
>
|
||||
{user?.name?.charAt(0).toUpperCase()}
|
||||
</Avatar>
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
|
||||
Reference in New Issue
Block a user