Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat(23UG-41): добавляет API и серверную часть форума #53

Merged
merged 27 commits into from
May 10, 2023

Conversation

EAbashin
Copy link
Contributor

Какую задачу решаем

  • создание и удаление тем форума
  • написание сообщений и возможность отвечать на ранее написаные
  • оставление и удаление реакций на сообщения

const { themes, currentMessages } = useSelector(forumSelect);
const user = useSelector(authSelect).user as User;
const themeId = useParams().themeId as string;
const { user_id, title } = themes.find((theme) => theme.id === +themeId) as ThemeType;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

При перезагрузке страницы здесь ошибка выходит
TypeError: Cannot destructure property 'user_id' of 'themes.find(...)' as it is undefined.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вчера до поздней ночи не мог понять происхождение этой ошибки - точки останова, debagger и console.log почему-то не отрабатывали. Когда попробовал решить с помощью sessionStorage и увидел ошибку: sessionStorage - undefined, понял, что код выполняется в node и вспомнил про SSR.
В общем, ошибка возникала из-за того, что при SSR мы, на тот момент, ещё не делали запрос за всеми темами.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Без SSR была бы та же ошибка, только не на странице выведена, а в консоли, поскольку и на клиенте мы еще не делали запрос за всеми темами. Просто SSR раньше отработал - раньше сломался. Точки останова и прочие прелести не работали, т.к. скрипт не загрузился в браузер - в HTML только ошибка с сервера распечатана.

И по итогу, после приделывания авторизации ошибка сохраняется ))

Comment on lines +7 to +16
router.get("/themes/", Forum.getThemes);
router.post("/themes/", Forum.postTheme);
router.delete("/themes/:theme_id", Forum.deleteTheme);
// сообщения
router.get("/messages/:theme_id", Forum.getMessages);
router.post("/messages/", Forum.postMessage);
// реакции
router.get("/reactions/:theme_id", Forum.getReactions);
router.post("/reactions/", Forum.postReaction);
router.delete("/reactions/:reaction_id", Forum.deleteReaction);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вот это вот все я могу делать не будучи авторизованным. Мне кажется, что это нехорошо ))
Пруф. Сейчас уже реализована возможность получить пользователя и есть пример в routes/index. Возможно в этом же PR имеет смысл приделать проверку пользователя.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Видел твой роут с проверкой авторизации, но почему-то подумал, что он каким-то магическим образом уже работает)))
Спасибо, за наглядное видео и за то, что всё для меня подготовил, подключил эту проверку.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А когда будет проверка авторизации, пользователя, для которого создается тема/сообщение/реакция, надо будет брать не из req.body а из данных авторизации

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Извиняюсь, но этот момент не понял..

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Первую часть вопроса я тоже не понял - проверка сделана через мидлвару и если пользователь не пользователь, то работать с темами/реакциями/сообщениями возможности не будет.

Что касается второй части вопроса. Возможно речь о том, что сейчас пользователь, для которого создается тема, берется из req.body, а должен из пользователя, которого получили с помощью аутентификационной куки. В этом случае в мидлваре нужно сохранить куда-то пользователя и в местах, где он нужен работать с этим сохраненным пользователем.

@Olegas, поясните пожалуйста подробнее по этому пункту

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Что касается второй части вопроса. Возможно речь о том, что сейчас пользователь, для которого создается тема, берется из req.body, а должен из пользователя, которого получили с помощью аутентификационной куки. В этом случае в мидлваре нужно сохранить куда-то пользователя и в местах, где он нужен работать с этим сохраненным пользователем.

@cap-Bernardito @EAbashin да, речь именно об этом. Если у вас действие выполняется для авторизованного пользователя, то надо брать это из достоверного источника. Параметры в запросе - не достоверный источник. Верно - мидлвара должна куда-то в request сохранить данные текущего пользователя и дальше контроллеры должны брать оттуда

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Понял, спасибо! Изменил.

@EAbashin EAbashin requested a review from Olegas May 1, 2023 11:19
Comment on lines 26 to 29

await loadUser(store.dispatch);
await getThemes(store.dispatch);

Copy link
Contributor

@cap-Bernardito cap-Bernardito May 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут темы для форума нездорово получать, т.к. они не для всех страниц нужны (а пользователь для всех). Для этой цели ниже добавлена обработка метода load для роутов.

Ну и оно так просто не работает, нужно добавлять методы в UserService, аналогично работе с пользователем. Отправлю коммит, как я думал, это должно работать. Посмотри в нем TODO по типам - нужно дописать

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Исправил

parent_message_id,
parent_message_text,
};
dispatch(forumThunks.postMessage(data));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А что если достать все нужные данные (типа данных о пользователе) внутри action creator'а, а передать в него только данные о посте (родитель, текст).

Кстати, а зачем нужен текст родительского поста?

Copy link
Contributor Author

@EAbashin EAbashin May 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В данном случае, мы ранее уже получили данные user для сравнения id создателя темы и id текущего пользователя и, на мой взгляд, будет лишним дополнительно получать данные user ещё и в санке, удобнее сразу передать уже готовые данные с диспатчем.

Нужен для отображения при ответе на это сообщение, чтобы не делать лишний запрос. Очень удобно - например, если на странице 20 сообщений с ответами, то не нужно делать 20 лишних запросов.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Про родительский пост. Так это я тогда могу писать ответы на то чего не было (опять же подложить в вызов какой-то свой текст и будет выглядеть как будто это был текст поста, на который я пишу ответ). Плохая история. А где там 20 запросов? Почему нельзя вытянуть все одним запросом? Вроде даже ORM позволяет связанные сущности вытаскивать.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не учёл эту уязвимость и, наверное, уставший был, когда писал про запросы)) У нас же в стейте уже есть все сообщения выбранной темы, надо просто найти нужное по id.
Исправил.

res.status(400).json({ error: (error as Error).message });
}
},
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А где сделана проверка что я могу удалять только свои сообщения/темы/реакции?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

На фронте:

  • если теме не твоя, то не увидишь кнопку удаления.
    {user_id && user?.id === user_id && ( <IconButton aria-label="delete" color="error" onClick={handleClickOpen}> <DeleteIcon /> </IconButton> )}
  • если ещё не оставлял реакцию, то сердечко без фона и при клике на него отправляется запрос на добавление реакции, если уже оставлял, то при клике - удаление реакции.
    `const likesCount = useSelector(
    (state) =>
    state.forum.currentReactions.filter(
    (reaction) => reaction.message_id === messageData.id && reaction.reaction === "like"
    ).length
    );
    const myLike = useSelector((state) =>
    state.forum.currentReactions.filter(
    (reaction) =>
    reaction.message_id === messageData.id &&
    reaction.reaction === "like" &&
    reaction.user_id === user.id
    )
    )[0];
    .....
{myLike?.id ? : } {likesCount} `

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Проверка на фронте это ок, но еще проверка должна быть на стороне бэка, т.к. я могу сформировать запрос к API руками и, если проверки нет, удалить чужую тему.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Согласен. Сделал дополнительную проверку на беке.

Comment on lines +7 to +16
router.get("/themes/", Forum.getThemes);
router.post("/themes/", Forum.postTheme);
router.delete("/themes/:theme_id", Forum.deleteTheme);
// сообщения
router.get("/messages/:theme_id", Forum.getMessages);
router.post("/messages/", Forum.postMessage);
// реакции
router.get("/reactions/:theme_id", Forum.getReactions);
router.post("/reactions/", Forum.postReaction);
router.delete("/reactions/:reaction_id", Forum.deleteReaction);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А когда будет проверка авторизации, пользователя, для которого создается тема/сообщение/реакция, надо будет брать не из req.body а из данных авторизации

Evgeniy Abashin added 6 commits May 4, 2023 19:31
…мы/сообщения/реакции, при добавлении сообщения имя пользователя и аватар берёт из данных авторизации, добавляет поиск и мемоизацию текста родительского сообщения
@EAbashin
Copy link
Contributor Author

EAbashin commented May 7, 2023

Все замечания исправлены.

@EAbashin EAbashin merged commit 3a79692 into dev May 10, 2023
@EAbashin EAbashin deleted the dev-backend-forum branch May 10, 2023 15:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants