Fix search cold-cache gate, 429 handling, and datetime.now() violations
ConnectionSearch.tsx: - Add loading guard for useSettings() — prevents cold cache from showing "enable connections" gate when settings haven't loaded yet - Add 429 rate limit handling in search catch block — shows user-friendly message instead of silently showing "User not found" - Import axios for isAxiosError type guard connections.py: - Fix 3x datetime.now() → datetime.now(timezone.utc) per hard rule (lines 187, 378, 565) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
360a14b87b
commit
9bcf5ace5d
@ -184,7 +184,7 @@ async def send_connection_request(
|
||||
raise HTTPException(status_code=409, detail="A pending request already exists")
|
||||
|
||||
# Per-receiver cap: max 5 pending requests within 10 minutes
|
||||
ten_min_ago = datetime.now() - timedelta(minutes=10)
|
||||
ten_min_ago = datetime.now(timezone.utc) - timedelta(minutes=10)
|
||||
pending_count = await db.scalar(
|
||||
select(func.count())
|
||||
.select_from(ConnectionRequest)
|
||||
@ -375,7 +375,7 @@ async def _respond_to_request_inner(
|
||||
db: AsyncSession,
|
||||
current_user: User,
|
||||
) -> RespondAcceptResponse | RespondRejectResponse:
|
||||
now = datetime.now()
|
||||
now = datetime.now(timezone.utc)
|
||||
|
||||
# Atomic update — only succeeds if status is still 'pending' and receiver is current user
|
||||
result = await db.execute(
|
||||
@ -562,7 +562,7 @@ async def cancel_request(
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
"""Cancel an outgoing connection request. Atomic via UPDATE...WHERE status='pending'."""
|
||||
now = datetime.now()
|
||||
now = datetime.now(timezone.utc)
|
||||
|
||||
# Atomic update — only succeeds if sender is current user and status is still pending
|
||||
result = await db.execute(
|
||||
|
||||
@ -14,6 +14,7 @@ import { Button } from '@/components/ui/button';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { useConnections } from '@/hooks/useConnections';
|
||||
import { useSettings } from '@/hooks/useSettings';
|
||||
import axios from 'axios';
|
||||
import { getErrorMessage } from '@/lib/api';
|
||||
|
||||
interface ConnectionSearchProps {
|
||||
@ -24,7 +25,7 @@ interface ConnectionSearchProps {
|
||||
|
||||
export default function ConnectionSearch({ open, onOpenChange, personId }: ConnectionSearchProps) {
|
||||
const { search, isSearching, sendRequest, isSending } = useConnections();
|
||||
const { settings } = useSettings();
|
||||
const { settings, isLoading: isLoadingSettings } = useSettings();
|
||||
const navigate = useNavigate();
|
||||
const [umbralName, setUmbralName] = useState('');
|
||||
const [found, setFound] = useState<boolean | null>(null);
|
||||
@ -39,9 +40,13 @@ export default function ConnectionSearch({ open, onOpenChange, personId }: Conne
|
||||
try {
|
||||
const result = await search(umbralName.trim());
|
||||
setFound(result.found);
|
||||
} catch {
|
||||
} catch (err) {
|
||||
if (axios.isAxiosError(err) && err.response?.status === 429) {
|
||||
toast.error('Too many searches — please wait a moment and try again');
|
||||
} else {
|
||||
setFound(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleSend = async () => {
|
||||
@ -76,7 +81,9 @@ export default function ConnectionSearch({ open, onOpenChange, personId }: Conne
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="space-y-4 pt-2">
|
||||
{!acceptConnectionsEnabled ? (
|
||||
{isLoadingSettings ? (
|
||||
<div className="flex justify-center py-6"><Loader2 className="h-5 w-5 animate-spin text-muted-foreground" /></div>
|
||||
) : !acceptConnectionsEnabled ? (
|
||||
<div className="flex flex-col items-center gap-3 py-4 text-center">
|
||||
<AlertCircle className="h-8 w-8 text-amber-400" />
|
||||
<p className="text-sm text-muted-foreground">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user