From 91d20fcf013dfe65af1ea2679e5e20a0dacf7ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D1=82=D0=BE=D0=BD?= Date: Thu, 29 Jan 2026 07:45:40 +0300 Subject: [PATCH] Delete Diary --- CMakeLists.txt | 1 + src/DAO/IDiariesDAO.h | 5 ++ src/DAO/MySQLDiariesDAO.cpp | 18 +++++ src/DAO/MySQLDiariesDAO.h | 5 ++ src/endpoints_handlers/DeleteDiaryExecutor.h | 79 ++++++++++++++++++++ src/endpoints_handlers/RootExecutor.h | 33 ++++++-- 6 files changed, 133 insertions(+), 8 deletions(-) create mode 100644 src/endpoints_handlers/DeleteDiaryExecutor.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0112358..dfe0413 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,6 +67,7 @@ add_executable(App ./src/main.cpp src/endpoints_handlers/GetDiariesExecutor.h src/endpoints_handlers/PostDiaryExecutor.h src/endpoints_handlers/PutDiaryExecutor.h + src/endpoints_handlers/DeleteDiaryExecutor.h src/DAO/IDiariesDAO.h src/dtos/diary_dto.h src/DAO/MySQLDiariesDao.cpp diff --git a/src/DAO/IDiariesDAO.h b/src/DAO/IDiariesDAO.h index 8c27c8d..3b7db99 100644 --- a/src/DAO/IDiariesDAO.h +++ b/src/DAO/IDiariesDAO.h @@ -23,6 +23,11 @@ public: const diary_dto& dto ) const = 0; + virtual void DeleteDiary( + const std::string& user_uuid, + const std::string& diary_uuid + ) const = 0; + virtual ~IDiariesDAO() = default; }; } diff --git a/src/DAO/MySQLDiariesDAO.cpp b/src/DAO/MySQLDiariesDAO.cpp index c935411..30efd2d 100644 --- a/src/DAO/MySQLDiariesDAO.cpp +++ b/src/DAO/MySQLDiariesDAO.cpp @@ -149,4 +149,22 @@ void MySqlDiariesDAO::UpdateDiary( throw session_exception(boost::beast::http::status::not_found, "Diary not found"); } } + +void MySqlDiariesDAO::DeleteDiary( + const std::string& user_uuid, + const std::string& diary_uuid) const +{ + auto stmt = session_.sql(R"( + DELETE FROM `up_and_down`.`diaries` + WHERE uuid = ? AND user_uuid = ? + )"); + + stmt.bind(diary_uuid, user_uuid); + + auto res = stmt.execute(); + + if (res.getAffectedItemsCount() == 0) { + throw session_exception(boost::beast::http::status::not_found, "Diary not found"); + } +} } diff --git a/src/DAO/MySQLDiariesDAO.h b/src/DAO/MySQLDiariesDAO.h index 660712f..dda3f91 100644 --- a/src/DAO/MySQLDiariesDAO.h +++ b/src/DAO/MySQLDiariesDAO.h @@ -27,5 +27,10 @@ public: const std::string& diary_uuid, const diary_dto& dto ) const override; + + void DeleteDiary( + const std::string& user_uuid, + const std::string& diary_uuid + ) const override; }; } diff --git a/src/endpoints_handlers/DeleteDiaryExecutor.h b/src/endpoints_handlers/DeleteDiaryExecutor.h new file mode 100644 index 0000000..7d19787 --- /dev/null +++ b/src/endpoints_handlers/DeleteDiaryExecutor.h @@ -0,0 +1,79 @@ +#pragma once +#include + +#include +#include +#include +#include + +#include "IExecutor.h" +#include "../DAO/IAuthDAO.h" +#include "../DAO/IDiariesDAO.h" +#include "../exceptions/session_exception.h" + +namespace uad +{ +template +class DeleteDiaryExecutor +{ + mysqlx::Session& session_; + const std::shared_ptr& auth_dao_; + const std::shared_ptr& diaries_dao_; + +public: + DeleteDiaryExecutor( + mysqlx::Session& session, + const std::shared_ptr& auth_dao, + const std::shared_ptr& diaries_dao + ) : session_(session), auth_dao_(auth_dao), diaries_dao_(diaries_dao) + { + } + + [[nodiscard]] boost::beast::http::response operator ()( + boost::beast::http::request>&& req, + std::string diary_uuid + ) + { + using namespace boost; + using namespace boost::json; + using namespace boost::beast; + using namespace std::string_literals; + using namespace std::string_view_literals; + + constexpr std::string_view auth_prefix = "Bearer "sv; + static const std::string invalid_token_message = + "DELETE /api/v1/Diary - Response 401: Unauthorized"s; + + BOOST_LOG_TRIVIAL(info) << "DELETE /api/v1/Diary - Request"; + + if (req[http::field::authorization].size() <= auth_prefix.size()) + { + BOOST_LOG_TRIVIAL(error) << invalid_token_message; + throw session_exception(http::status::unauthorized, "Unauthorized"); + } + + const std::string auth_token = { + req[http::field::authorization].begin() + auth_prefix.size(), + req[http::field::authorization].end() + }; + + if (!auth_dao_->HasAuthorized(auth_token)) + { + BOOST_LOG_TRIVIAL(error) << invalid_token_message; + throw session_exception(http::status::unauthorized, "Unauthorized"); + } + + std::string_view user_uuid_ref = auth_dao_->GetUUID(auth_token); + const std::string user_uuid{user_uuid_ref.begin(), user_uuid_ref.end()}; + + diaries_dao_->DeleteDiary(user_uuid, diary_uuid); + + http::response res{http::status::no_content, req.version()}; + res.keep_alive(req.keep_alive()); + + BOOST_LOG_TRIVIAL(info) << "DELETE /api/v1/Diary - Response 204: Diary deleted"; + + return res; + } +}; +} diff --git a/src/endpoints_handlers/RootExecutor.h b/src/endpoints_handlers/RootExecutor.h index 7ad6db7..32308b0 100644 --- a/src/endpoints_handlers/RootExecutor.h +++ b/src/endpoints_handlers/RootExecutor.h @@ -17,6 +17,7 @@ #include "GetDiariesExecutor.h" #include "PostDiaryExecutor.h" #include "PutDiaryExecutor.h" +#include "DeleteDiaryExecutor.h" #include "../DAO/IUserDAO.h" #include "../DAO/IAuthDAO.h" #include "../DAO/IDiariesDAO.h" @@ -202,15 +203,31 @@ public: parts[0] == "api" && parts[2] == "Diaries") { - std::string uuid = std::string(parts[3]); - - if (req.method() == boost::beast::http::verb::put) + try { - return send(PutDiaryExecutor( - session_, - auth_dao_, - diaries_dao_ - )(std::move(req), uuid)); + std::string uuid = std::string(parts[3]); + + if (req.method() == boost::beast::http::verb::put) + { + return send(PutDiaryExecutor( + session_, + auth_dao_, + diaries_dao_ + )(std::move(req), uuid)); + } + + if (req.method() == boost::beast::http::verb::delete_) + { + return send(DeleteDiaryExecutor( + session_, + auth_dao_, + diaries_dao_ + )(std::move(req), uuid)); + } + } + catch (const session_exception& e) + { + return send(SendSessionExceptionError(std::move(req), e)); } }