fix(auth-ui): тихий фейл 400 при смене пароля, валидация, пароль при создании
PLAN-user-password-fixes.md (инцидент 2026-09-07, user 55/56):
- toServiceError в client auth.service: BadRequestError → {success:false, error}
- полная клиентская валидация пароля в ProfilePasswordRow
- опциональный пароль при создании пользователя (UserModal + POST /api/users)
- onError с toast в PollCard/ReactionBar (этап 4)
- 11 новых тестов (129/129)
This commit is contained in:
@@ -3,6 +3,7 @@ import { cn } from '@/lib/utils';
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { apiRequest } from '@/lib/queryClient';
|
||||
import { useAuth } from '@/hooks/useAuth';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
import { isAdmin } from '@/lib/permissions';
|
||||
|
||||
export interface PollData {
|
||||
@@ -26,10 +27,19 @@ interface PollCardProps {
|
||||
|
||||
export function PollCard({ poll, onPollChange, isOwn }: PollCardProps) {
|
||||
const { user } = useAuth();
|
||||
const { toast } = useToast();
|
||||
const canClose = poll.createdBy === user?.id || isAdmin(user);
|
||||
const hasVoted = poll.myVote !== null && poll.myVote.length > 0;
|
||||
const showResults = hasVoted || poll.isClosed;
|
||||
|
||||
// apiRequest при 400/409 бросает ошибку с текстом сервера в message; сетевые TypeError не показываем
|
||||
const onPollError = (error: unknown) =>
|
||||
toast({
|
||||
title: 'Ошибка голосования',
|
||||
description: error instanceof Error && !(error instanceof TypeError) ? error.message : undefined,
|
||||
variant: 'destructive',
|
||||
});
|
||||
|
||||
const voteMutation = useMutation({
|
||||
mutationFn: async (optionIndexes: number[]) => {
|
||||
const res = await apiRequest('POST', `/api/polls/${poll.id}/vote`, { optionIndexes });
|
||||
@@ -38,6 +48,7 @@ export function PollCard({ poll, onPollChange, isOwn }: PollCardProps) {
|
||||
return data.poll as PollData;
|
||||
},
|
||||
onSuccess: onPollChange,
|
||||
onError: onPollError,
|
||||
});
|
||||
|
||||
const unvoteMutation = useMutation({
|
||||
@@ -48,6 +59,7 @@ export function PollCard({ poll, onPollChange, isOwn }: PollCardProps) {
|
||||
return data.poll as PollData;
|
||||
},
|
||||
onSuccess: onPollChange,
|
||||
onError: onPollError,
|
||||
});
|
||||
|
||||
const closeMutation = useMutation({
|
||||
@@ -58,6 +70,7 @@ export function PollCard({ poll, onPollChange, isOwn }: PollCardProps) {
|
||||
return data.poll as PollData;
|
||||
},
|
||||
onSuccess: onPollChange,
|
||||
onError: onPollError,
|
||||
});
|
||||
|
||||
const handleOptionClick = (idx: number) => {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { cn } from '@/lib/utils';
|
||||
import { EmojiPicker } from './EmojiPicker';
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { apiRequest } from '@/lib/queryClient';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
@@ -39,6 +40,8 @@ export function ReactionBar({
|
||||
? `/api/messages/${messageId}/reactions`
|
||||
: `/api/conv-messages/${messageId}/reactions`;
|
||||
|
||||
const { toast } = useToast();
|
||||
|
||||
const toggleMutation = useMutation({
|
||||
mutationFn: async (emoji: string) => {
|
||||
const res = await apiRequest('POST', endpoint, { emoji });
|
||||
@@ -49,6 +52,12 @@ export function ReactionBar({
|
||||
onSuccess: (updated) => {
|
||||
onReactionsChange(updated);
|
||||
},
|
||||
// apiRequest при 400/409 бросает ошибку с текстом сервера в message; сетевые TypeError не показываем
|
||||
onError: (error) => toast({
|
||||
title: 'Не удалось поставить реакцию',
|
||||
description: error instanceof Error && !(error instanceof TypeError) ? error.message : undefined,
|
||||
variant: 'destructive',
|
||||
}),
|
||||
});
|
||||
|
||||
const handleEmoji = (emoji: string) => {
|
||||
|
||||
Reference in New Issue
Block a user