1+ #include " view.hpp"
2+ #include " ../../../../constants.hpp"
3+ #include " ../../../../models/response.hpp"
4+ #include " ../../../../models/user_dto.hpp"
5+ #include " ../../../../repositories/key_repository/key_repository.hpp"
6+
7+ #include < fmt/format.h>
8+ #include < boost/uuid/string_generator.hpp>
9+ #include < boost/uuid/uuid.hpp>
10+
11+ #include < exception>
12+ #include < userver/components/component_config.hpp>
13+ #include < userver/components/component_context.hpp>
14+ #include < userver/formats/json/serialize.hpp>
15+ #include < userver/server/handlers/http_handler_base.hpp>
16+ #include < userver/server/http/http_status.hpp>
17+ #include < userver/storages/postgres/cluster.hpp>
18+ #include < userver/storages/postgres/component.hpp>
19+ #include < userver/storages/postgres/exceptions.hpp>
20+ #include < userver/storages/postgres/io/user_types.hpp>
21+ #include < userver/utils/assert.hpp>
22+ #include < userver/utils/boost_uuid4.hpp>
23+ #include < userver/utils/uuid4.hpp>
24+
25+ namespace vpn_manager {
26+
27+ namespace {
28+
29+ class CreateKey final : public userver::server::handlers::HttpHandlerBase {
30+ public:
31+ static constexpr std::string_view kName = " handler-v1-create-key" ;
32+
33+ CreateKey (const userver::components::ComponentConfig& config,
34+ const userver::components::ComponentContext& component_context)
35+ : HttpHandlerBase(config, component_context),
36+ pg_cluster_ (component_context
37+ .FindComponent<userver::components::Postgres>(
38+ constants::postgres::kPostgresDBName )
39+ .GetCluster()),
40+ key_repository_(config, component_context) {}
41+
42+ std::string HandleRequestThrow (
43+ const userver::server::http::HttpRequest& request,
44+ userver::server::request::RequestContext&) const override {
45+ auto & response = request.GetHttpResponse ();
46+
47+ const auto json_body =
48+ userver::formats::json::FromString (request.RequestBody ());
49+
50+ if (!json_body.HasMember (" name" ) || !json_body.HasMember (" key" ) ||
51+ !json_body.HasMember (" user_id" )) {
52+ response.SetStatus (userver::server::http::HttpStatus::kBadRequest );
53+ return response::ErrorResponse (kMissingFields ).ToJson ();
54+ }
55+
56+ boost::uuids::uuid user_id;
57+ try {
58+ user_id = userver::utils::BoostUuidFromString (
59+ json_body[" user_id" ].As <std::string>());
60+ } catch (const std::exception& e) {
61+ LOG_ERROR () << " CreateKey: Invalid user_id: " << e.what ();
62+ response.SetStatus (userver::server::http::HttpStatus::kBadRequest );
63+ return response::ErrorResponse (kInvalidUserId ).ToJson ();
64+ } catch (...) {
65+ LOG_ERROR () << " CreateKey: Invalid user_id" ;
66+ response.SetStatus (userver::server::http::HttpStatus::kBadRequest );
67+ return response::ErrorResponse (kInvalidUserId ).ToJson ();
68+ }
69+ std::string name;
70+ std::string key;
71+ try {
72+ name = json_body[" name" ].As <std::string>();
73+ key = json_body[" key" ].As <std::string>();
74+ } catch (const std::exception& e) {
75+ LOG_ERROR () << " CreateKey: Unexpected error: " << e.what ();
76+ response.SetStatus (
77+ userver::server::http::HttpStatus::kInternalServerError );
78+ return response::ErrorResponse (kUnknownError ).ToJson ();
79+ } catch (...) {
80+ LOG_ERROR () << " CreateKey: Unexpected error" ;
81+ response.SetStatus (
82+ userver::server::http::HttpStatus::kInternalServerError );
83+ return response::ErrorResponse (kUnknownError ).ToJson ();
84+ }
85+
86+ boost::uuids::uuid key_id;
87+ try {
88+ key_id = key_repository_.CreateKey (user_id, name, key);
89+ } catch (const userver::storages::postgres::UniqueViolation& e) {
90+ LOG_ERROR () << " CreateKey: Unique constraint violation: " << e.what ();
91+ response.SetStatus (userver::server::http::HttpStatus::kConflict );
92+ return response::ErrorResponse (kKeyWithSuchNameAlreadyExists ).ToJson ();
93+ } catch (const userver::storages::postgres::ForeignKeyViolation& e) {
94+ LOG_ERROR () << " CreateKey: Foreign key constraint violation: "
95+ << e.what ();
96+ response.SetStatus (userver::server::http::HttpStatus::kNotFound );
97+ return response::ErrorResponse (kUserDoesNotExist ).ToJson ();
98+ } catch (const userver::storages::postgres::ClusterError& e) {
99+ LOG_ERROR () << " CreateKey: Database error: " << e.what ();
100+ response.SetStatus (
101+ userver::server::http::HttpStatus::kInternalServerError );
102+ return response::ErrorResponse (kUnknownError ).ToJson ();
103+ } catch (const std::exception& e) {
104+ LOG_ERROR () << " CreateKey: Unexpected error: " << e.what ();
105+ response.SetStatus (
106+ userver::server::http::HttpStatus::kInternalServerError );
107+ return response::ErrorResponse (kUnknownError ).ToJson ();
108+ } catch (...) {
109+ LOG_ERROR () << " CreateKey: Unexpected error" ;
110+ response.SetStatus (
111+ userver::server::http::HttpStatus::kInternalServerError );
112+ return response::ErrorResponse (kUnknownError ).ToJson ();
113+ }
114+
115+ response.SetStatus (userver::server::http::HttpStatus::kOk );
116+
117+ return response::Response (fmt::format (R"( {{"id": "{}"}})" , key_id))
118+ .ToJson ();
119+ }
120+
121+ userver::storages::postgres::ClusterPtr pg_cluster_;
122+ repositories::KeyRepositoryComponent key_repository_;
123+
124+ private:
125+ inline static constexpr std::string_view kMissingFields =
126+ " Missing required fields" ;
127+ inline static constexpr std::string_view kKeyWithSuchNameAlreadyExists =
128+ " Key with such name already exists" ;
129+ inline static constexpr std::string_view kInvalidUserId = " Invalid User ID" ;
130+ inline static constexpr std::string_view kUserDoesNotExist =
131+ " User does not exist" ;
132+ inline static constexpr std::string_view kUnknownError = " Unknown error" ;
133+ };
134+
135+ } // namespace
136+
137+ void AppendCreateKey (userver::components::ComponentList& component_list) {
138+ component_list.Append <CreateKey>();
139+ }
140+
141+ } // namespace vpn_manager
0 commit comments