#pragma once #include #include #include #include #include #include "IExecutor.h" #include "../DAO/IAuthDAO.h" #include "../DAO/IMedicationsDAO.h" #include "../exceptions/session_exception.h" namespace uad { template class PostUserMedicationsExecutor : public IExecutor { mysqlx::Session& session_; const std::shared_ptr& auth_dao_; const std::shared_ptr& medications_dao_; public: PostUserMedicationsExecutor( mysqlx::Session& session, const std::shared_ptr& auth_dao, const std::shared_ptr& medications_dao ): session_(session), auth_dao_(auth_dao), medications_dao_(medications_dao) { } [[nodiscard]] boost::beast::http::response operator ()( boost::beast::http::request>&& req ) override { 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 = "POST /api/v1/User/Medications - Response 401: Unauthorized"s; BOOST_LOG_TRIVIAL(info) << "POST /api/v1/User/Medications - 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"); } const auto body = req.body(); value req_json; medication_dto m; try { req_json = json::parse(body); } catch (const system::system_error& err) { BOOST_LOG_TRIVIAL(error) << "POST /api/v1/User/Medications - Response 400: Cannot deserialize json"; throw session_exception(http::status::bad_request, "Cannot deserialize json"); } m.name = req_json.as_object().at("name").as_string().c_str(); m.dose = req_json.as_object().at("dose").as_int64(); m.unit = req_json.as_object().at("unit").as_string().c_str(); m.is_urgent = req_json.as_object().at("is_urgent").as_bool(); try { m.uuid = medications_dao_->Create(m); } catch (const std::runtime_error& err) { BOOST_LOG_TRIVIAL(error) << "POST /api/v1/User/Medications - Response 409: This medication already exists"; throw session_exception(http::status::conflict, "This medication already exists"); } http::response res{http::status::ok, req.version()}; res.body() = serialize(ToJSON(m)); res.set(http::field::content_type, "application/json"); res.content_length(res.body().size()); return res; } private: boost::json::object ToJSON(const medication_dto& m) { return { { "uuid", m.uuid }, { "name", m.name }, { "dose", m.dose }, { "unit", m.unit }, { "is_urgent", m.is_urgent } }; } }; }