mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 16:31:12 -05:00
134 lines
4.4 KiB
TypeScript
134 lines
4.4 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { useAuth } from '@/hooks/useAuth';
|
|
import { supabase } from '@/lib/supabaseClient';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { toast } from '@/hooks/use-toast';
|
|
import { logger } from '@/lib/logger';
|
|
|
|
export function useBanCheck() {
|
|
const { user } = useAuth();
|
|
const navigate = useNavigate();
|
|
const [isBanned, setIsBanned] = useState(false);
|
|
const [banReason, setBanReason] = useState<string | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
if (!user) {
|
|
setIsBanned(false);
|
|
setLoading(false);
|
|
return;
|
|
}
|
|
|
|
const checkBan = async () => {
|
|
try {
|
|
const { data: profile } = await supabase
|
|
.from('profiles')
|
|
.select('banned, ban_reason, ban_expires_at')
|
|
.eq('user_id', user.id)
|
|
.single();
|
|
|
|
if (profile?.banned) {
|
|
setIsBanned(true);
|
|
setBanReason(profile.ban_reason || null);
|
|
|
|
const reason = profile.ban_reason
|
|
? `Reason: ${profile.ban_reason}`
|
|
: 'Contact support for assistance.';
|
|
|
|
// Add expiration info
|
|
let expirationText = '';
|
|
if (profile.ban_expires_at) {
|
|
const expiresAt = new Date(profile.ban_expires_at);
|
|
const now = new Date();
|
|
const daysLeft = Math.ceil((expiresAt.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
|
|
expirationText = ` This ban will expire in ${daysLeft} day${daysLeft !== 1 ? 's' : ''}.`;
|
|
} else {
|
|
expirationText = ' This is a permanent ban.';
|
|
}
|
|
|
|
toast({
|
|
title: 'Account Suspended',
|
|
description: `Your account has been suspended. ${reason}${expirationText}`,
|
|
variant: 'destructive',
|
|
duration: Infinity // Don't auto-dismiss
|
|
});
|
|
// Sign out banned user
|
|
await supabase.auth.signOut();
|
|
navigate('/');
|
|
}
|
|
} catch (error) {
|
|
// Silent - ban check failure is non-critical, user proceeds normally
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
checkBan();
|
|
|
|
// Subscribe to profile changes (real-time ban/unban detection)
|
|
const channel = supabase
|
|
.channel('ban-check')
|
|
.on(
|
|
'postgres_changes',
|
|
{
|
|
event: 'UPDATE',
|
|
schema: 'public',
|
|
table: 'profiles',
|
|
filter: `user_id=eq.${user.id}`
|
|
},
|
|
(payload) => {
|
|
const newProfile = payload.new as { banned: boolean; ban_reason: string | null; ban_expires_at: string | null };
|
|
|
|
// Handle BAN event
|
|
if (newProfile.banned && !isBanned) {
|
|
setIsBanned(true);
|
|
setBanReason(newProfile.ban_reason || null);
|
|
|
|
const reason = newProfile.ban_reason
|
|
? `Reason: ${newProfile.ban_reason}`
|
|
: 'Contact support for assistance.';
|
|
|
|
// Add expiration info
|
|
let expirationText = '';
|
|
if (newProfile.ban_expires_at) {
|
|
const expiresAt = new Date(newProfile.ban_expires_at);
|
|
const now = new Date();
|
|
const daysLeft = Math.ceil((expiresAt.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
|
|
expirationText = ` This ban will expire in ${daysLeft} day${daysLeft !== 1 ? 's' : ''}.`;
|
|
} else {
|
|
expirationText = ' This is a permanent ban.';
|
|
}
|
|
|
|
toast({
|
|
title: 'Account Suspended',
|
|
description: `Your account has been suspended. ${reason}${expirationText}`,
|
|
variant: 'destructive',
|
|
duration: Infinity
|
|
});
|
|
supabase.auth.signOut();
|
|
navigate('/');
|
|
}
|
|
|
|
// Handle UNBAN event
|
|
if (!newProfile.banned && isBanned) {
|
|
setIsBanned(false);
|
|
setBanReason(null);
|
|
toast({
|
|
title: 'Account Restored',
|
|
description: 'Your account has been unbanned. You can now use the application normally.',
|
|
variant: 'default',
|
|
duration: 8000
|
|
});
|
|
}
|
|
}
|
|
)
|
|
.subscribe();
|
|
|
|
return () => {
|
|
supabase.removeChannel(channel);
|
|
};
|
|
}, [user, navigate]);
|
|
|
|
return { isBanned, loading, banReason };
|
|
}
|