From 04c77330d32b75a694ed0c442f3c9e66c4e7b10a Mon Sep 17 00:00:00 2001 From: Liiiza Date: Mon, 18 Nov 2024 21:32:00 +0300 Subject: [PATCH 1/3] add salt and minor changes --- .github/workflows/ci.yml | 2 +- .gitignore | 1 - CMakeLists.txt | 7 +- configs/dynamic_config_fallback.json | 72 ------------------- ...atic_config.yaml.in => static_config.yaml} | 4 -- postgresql/schemas/db-1.sql | 4 +- src/db/sql.hpp | 15 ++-- src/handlers/comments/comment_delete.cpp | 2 +- src/handlers/comments/comment_delete.hpp | 1 + src/handlers/profiles/profiles.cpp | 1 - src/handlers/profiles/profiles_follow.cpp | 1 - .../profiles/profiles_follow_delete.cpp | 1 - src/handlers/users/user_put.cpp | 7 +- src/handlers/users/users.cpp | 6 +- src/handlers/users/users_login.cpp | 11 ++- src/models/user.hpp | 3 +- src/utils/random.cpp | 18 +++++ src/utils/random.hpp | 7 ++ tests/CMakeLists.txt | 1 - 19 files changed, 64 insertions(+), 100 deletions(-) delete mode 100644 configs/dynamic_config_fallback.json rename configs/{static_config.yaml.in => static_config.yaml} (99%) create mode 100644 src/utils/random.cpp create mode 100644 src/utils/random.hpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 850c8e5..7ff541d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: - name: Reuse ccache directory uses: actions/cache@v4 with: - path: ~/.ccache + path: ~/.cache/ccache key: '${{matrix.os}} ${{matrix.info}} ccache-dir ${{github.ref}} run-${{github.run_number}}' restore-keys: | ${{matrix.os}} ${{matrix.info}} ccache-dir ${{github.ref}} run-' diff --git a/.gitignore b/.gitignore index b8a8c32..fb29c34 100644 --- a/.gitignore +++ b/.gitignore @@ -8,5 +8,4 @@ compile_commands.json .ccache/ cmake-build-* Testing/ -configs/static_config.yaml .DS_Store diff --git a/CMakeLists.txt b/CMakeLists.txt index 0398d3c..b5d4954 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,6 +97,8 @@ add_library(${PROJECT_NAME}_objs OBJECT src/validators/user_validators.cpp src/validators/length_validator.hpp src/validators/length_validator.cpp + src/utils/random.hpp + src/utils/random.cpp src/utils/errors.hpp src/utils/errors.cpp src/utils/make_error.hpp @@ -142,7 +144,6 @@ add_google_tests(${PROJECT_NAME}_unittest) # Functional Tests add_subdirectory(tests) - # Install include(GNUInstallDirs) @@ -152,12 +153,8 @@ if(DEFINED ENV{PREFIX}) set(CMAKE_INSTALL_PREFIX ${PREFIX_PATH}) endif() -set(CONFIG_VAR_PATH ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_SYSCONFDIR}/${PROJECT_NAME}/config_vars.yaml) -set(CONFIG_FALLBACK_PATH ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_SYSCONFDIR}/${PROJECT_NAME}/dynamic_config_fallback.json) set(CONFIG_JWT ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_SYSCONFDIR}/${PROJECT_NAME}/jwt_config.json) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configs/static_config.yaml.in ${CMAKE_CURRENT_SOURCE_DIR}/configs/static_config.yaml) - file(GLOB CONFIGS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/configs/*.yaml ${CMAKE_CURRENT_SOURCE_DIR}/configs/*.json) install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${PROJECT_NAME}) diff --git a/configs/dynamic_config_fallback.json b/configs/dynamic_config_fallback.json deleted file mode 100644 index 8b185cc..0000000 --- a/configs/dynamic_config_fallback.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "HTTP_CLIENT_CONNECTION_POOL_SIZE": 1000, - "HTTP_CLIENT_CONNECT_THROTTLE": { - "http-limit": 6000, - "http-per-second": 1500, - "https-limit": 100, - "https-per-second": 25, - "per-host-limit": 3500, - "per-host-per-second": 500 - }, - "HTTP_CLIENT_ENFORCE_TASK_DEADLINE": { - "cancel-request": false, - "update-timeout": false - }, - "POSTGRES_CONNECTION_PIPELINE_ENABLED": true, - "POSTGRES_CONNECTION_POOL_SETTINGS": { - "realmedium-database": { - "max_pool_size": 150, - "max_queue_size": 2000, - "min_pool_size": 50 - } - }, - "POSTGRES_CONNECTION_SETTINGS": {}, - "POSTGRES_DEFAULT_COMMAND_CONTROL": { - "network_timeout_ms": 750, - "statement_timeout_ms": 500 - }, - "POSTGRES_HANDLERS_COMMAND_CONTROL": { - "/v1/hello": { - "POST": { - "network_timeout_ms": 500, - "statement_timeout_ms": 250 - } - } - }, - "POSTGRES_QUERIES_COMMAND_CONTROL": {}, - "POSTGRES_STATEMENT_METRICS_SETTINGS": { - "realmedium-database": { - "max_statement_metrics": 5 - } - }, - "USERVER_BAGGAGE_ENABLED": false, - "BAGGAGE_SETTINGS": { - "allowed_keys": [] - }, - "POSTGRES_CONGESTION_CONTROL_SETTINGS": {}, - "POSTGRES_CONNLIMIT_MODE_AUTO_ENABLED": false, - "POSTGRES_CONNECTION_PIPELINE_EXPERIMENT": 0, - "POSTGRES_DEADLINE_PROPAGATION_VERSION": 0, - "USERVER_CACHES": {}, - "USERVER_CANCEL_HANDLE_REQUEST_BY_DEADLINE": false, - "USERVER_CHECK_AUTH_IN_HANDLERS": true, - "USERVER_DUMPS": {}, - "USERVER_HTTP_PROXY": "", - "USERVER_LOG_REQUEST": true, - "USERVER_LOG_REQUEST_HEADERS": false, - "USERVER_LRU_CACHES": {}, - "USERVER_RPS_CCONTROL_CUSTOM_STATUS": {}, - "USERVER_TASK_PROCESSOR_PROFILER_DEBUG": {}, - "USERVER_HANDLER_STREAM_API_ENABLED": false, - "USERVER_TASK_PROCESSOR_QOS": { - "default-service": { - "default-task-processor": { - "wait_queue_overload": { - "action": "ignore", - "length_limit": 50000, - "time_limit_us": 3000 - } - } - } - } -} diff --git a/configs/static_config.yaml.in b/configs/static_config.yaml similarity index 99% rename from configs/static_config.yaml.in rename to configs/static_config.yaml index b48009e..a3cbae9 100644 --- a/configs/static_config.yaml.in +++ b/configs/static_config.yaml @@ -1,7 +1,3 @@ -# yaml - -config_vars: @CONFIG_VAR_PATH@ - components_manager: coro_pool: initial_size: 500 # Preallocate 500 coroutines at startup. diff --git a/postgresql/schemas/db-1.sql b/postgresql/schemas/db-1.sql index fa24c44..8c49015 100644 --- a/postgresql/schemas/db-1.sql +++ b/postgresql/schemas/db-1.sql @@ -9,6 +9,7 @@ CREATE TABLE IF NOT EXISTS real_medium.users( bio text, image varchar(255), password_hash varchar(255) NOT NULL, + salt varchar(255) NOT NULL, CONSTRAINT uniq_username UNIQUE (username), CONSTRAINT uniq_email UNIQUE (email) ); @@ -77,7 +78,8 @@ CREATE TYPE real_medium.user AS ( email text, bio TEXT, image VARCHAR(255), - password_hash TEXT + password_hash TEXT, + salt TEXT ); CREATE TYPE real_medium.full_article_info AS ( diff --git a/src/db/sql.hpp b/src/db/sql.hpp index fb7c1a1..cc8e460 100644 --- a/src/db/sql.hpp +++ b/src/db/sql.hpp @@ -5,8 +5,8 @@ namespace real_medium::sql { inline constexpr std::string_view kInsertUser = R"~( -INSERT INTO real_medium.users(username, email, password_hash) -VALUES($1, $2, $3) +INSERT INTO real_medium.users(username, email, password_hash, salt) +VALUES($1, $2, $3, $4) RETURNING * )~"; @@ -21,7 +21,8 @@ UPDATE real_medium.users SET email = COALESCE($3, email), bio = COALESCE($4, bio), image = COALESCE($5, image), - password_hash = COALESCE($6, password_hash) + password_hash = COALESCE($6, password_hash), + salt = COALESCE($7, salt) WHERE user_id = $1 RETURNING * )~"; @@ -111,6 +112,10 @@ SELECT profile.username, profile.bio, profile.image, FROM profile )~"; +inline constexpr std::string_view kGetSaltByEmail = R"~( +SELECT salt FROM real_medium.users WHERE email = $1 +)~"; + inline constexpr std::string_view KFollowingUser = R"~( WITH profile AS ( SELECT * FROM real_medium.users WHERE user_id = $1 @@ -235,7 +240,7 @@ SELECT a.article_id AS articleId, FROM real_medium.followers fl WHERE fl.followed_user_id = a.user_id ) AS author_followed_by_user_ids, - ROW(u.user_id, u.username, u.email, u.bio, u.image, u.password_hash)::real_medium.user AS author_info + ROW(u.user_id, u.username, u.email, u.bio, u.image, u.password_hash, u.salt)::real_medium.user AS author_info FROM real_medium.articles a JOIN real_medium.users u ON a.user_id = u.user_id )~"}; @@ -247,7 +252,7 @@ SELECT c.comment_id, c.body, c.user_id, a.slug, - ROW(u.user_id, u.username, u.email, u.bio, u.image, u.password_hash)::real_medium.user AS author_info, + ROW(u.user_id, u.username, u.email, u.bio, u.image, u.password_hash, u.salt)::real_medium.user AS author_info, ARRAY( SELECT follower_user_id FROM real_medium.followers fl diff --git a/src/handlers/comments/comment_delete.cpp b/src/handlers/comments/comment_delete.cpp index 2288b5d..559f913 100644 --- a/src/handlers/comments/comment_delete.cpp +++ b/src/handlers/comments/comment_delete.cpp @@ -18,7 +18,7 @@ userver::formats::json::Value Handler::HandleRequestJsonThrow( const userver::formats::json::Value& /*request_json*/, userver::server::request::RequestContext& context) const { auto user_id = context.GetData>("id"); - const auto& comment_id = std::atoi(request.GetPathArg("id").c_str()); + const auto& comment_id = userver::utils::FromString(request.GetPathArg("id")); const auto& slug = request.GetPathArg("slug"); const auto result_find_comment = pg_cluster_->Execute( diff --git a/src/handlers/comments/comment_delete.hpp b/src/handlers/comments/comment_delete.hpp index e8d9661..08c0679 100644 --- a/src/handlers/comments/comment_delete.hpp +++ b/src/handlers/comments/comment_delete.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "userver/server/handlers/http_handler_base.hpp" #include "userver/server/handlers/http_handler_json_base.hpp" diff --git a/src/handlers/profiles/profiles.cpp b/src/handlers/profiles/profiles.cpp index 049f37c..191193a 100644 --- a/src/handlers/profiles/profiles.cpp +++ b/src/handlers/profiles/profiles.cpp @@ -10,7 +10,6 @@ #include "userver/storages/postgres/cluster.hpp" #include "userver/storages/postgres/component.hpp" -using namespace std; using namespace userver::formats; using namespace userver::server::http; using namespace userver::server::request; diff --git a/src/handlers/profiles/profiles_follow.cpp b/src/handlers/profiles/profiles_follow.cpp index 979208e..86aeb45 100644 --- a/src/handlers/profiles/profiles_follow.cpp +++ b/src/handlers/profiles/profiles_follow.cpp @@ -9,7 +9,6 @@ #include "userver/storages/postgres/cluster.hpp" #include "userver/storages/postgres/component.hpp" -using namespace std; using namespace userver::formats; using namespace userver::server::http; using namespace userver::server::request; diff --git a/src/handlers/profiles/profiles_follow_delete.cpp b/src/handlers/profiles/profiles_follow_delete.cpp index f117fb4..32182c1 100644 --- a/src/handlers/profiles/profiles_follow_delete.cpp +++ b/src/handlers/profiles/profiles_follow_delete.cpp @@ -8,7 +8,6 @@ #include "userver/storages/postgres/component.hpp" #include "utils/make_error.hpp" -using namespace std; using namespace userver::formats; using namespace userver::server::http; using namespace userver::server::request; diff --git a/src/handlers/users/user_put.cpp b/src/handlers/users/user_put.cpp index 6878b8b..f9b3881 100644 --- a/src/handlers/users/user_put.cpp +++ b/src/handlers/users/user_put.cpp @@ -4,6 +4,7 @@ #include "dto/user.hpp" #include "models/user.hpp" #include "utils/errors.hpp" +#include "utils/random.hpp" #include "validators/validators.hpp" namespace real_medium::handlers::users::put { @@ -33,16 +34,18 @@ userver::formats::json::Value Handler::HandleRequestJsonThrow( } std::optional password_hash = std::nullopt; + std::optional salt = std::nullopt; if (user_change_data.password) { + salt = utils::random::GenerateSalt(); password_hash = - userver::crypto::hash::Sha256(user_change_data.password.value()); + userver::crypto::hash::Sha256(user_change_data.password.value() + salt.value()); } const auto result = pg_cluster_->Execute( userver::storages::postgres::ClusterHostType::kMaster, sql::kUpdateUser.data(), user_id, user_change_data.username, user_change_data.email, user_change_data.bio, user_change_data.image, - password_hash); + password_hash, salt); auto user_result_data = result.AsSingleRow( userver::storages::postgres::kRowTag); diff --git a/src/handlers/users/users.cpp b/src/handlers/users/users.cpp index 561f827..1be8bf3 100644 --- a/src/handlers/users/users.cpp +++ b/src/handlers/users/users.cpp @@ -9,6 +9,7 @@ #include "models/user.hpp" #include "utils/errors.hpp" #include "utils/make_error.hpp" +#include "utils/random.hpp" #include "validators/validators.hpp" namespace real_medium::handlers::users::post { @@ -38,14 +39,15 @@ userver::formats::json::Value RegisterUser::HandleRequestJsonThrow( return err.GetDetails(); } + auto salt = utils::random::GenerateSalt(); auto hash_password = - userver::crypto::hash::Sha256(user_register.password.value()); + userver::crypto::hash::Sha256(user_register.password.value() + salt); models::User result_user; try { auto query_result = pg_cluster_->Execute( userver::storages::postgres::ClusterHostType::kMaster, sql::kInsertUser.data(), user_register.username, user_register.email, - hash_password); + hash_password, salt); result_user = query_result.AsSingleRow( userver::storages::postgres::kRowTag); } catch (const userver::storages::postgres::UniqueViolation& ex) { diff --git a/src/handlers/users/users_login.cpp b/src/handlers/users/users_login.cpp index fe739b5..f52a45c 100644 --- a/src/handlers/users/users_login.cpp +++ b/src/handlers/users/users_login.cpp @@ -45,8 +45,17 @@ class LoginUser final : public userver::server::handlers::HttpHandlerJsonBase { return err.GetDetails(); } + auto salt = pg_cluster_->Execute( + userver::storages::postgres::ClusterHostType::kMaster, + sql::kGetSaltByEmail.data(), + user_login.email); + if (salt.IsEmpty()) { + auto& response = request.GetHttpResponse(); + response.SetStatus(userver::server::http::HttpStatus::kNotFound); + return {}; + } auto password_hash = - userver::crypto::hash::Sha256(user_login.password.value()); + userver::crypto::hash::Sha256(user_login.password.value() + salt.AsSingleRow()); auto userResult = pg_cluster_->Execute( userver::storages::postgres::ClusterHostType::kMaster, diff --git a/src/models/user.hpp b/src/models/user.hpp index 14d7716..11eae86 100644 --- a/src/models/user.hpp +++ b/src/models/user.hpp @@ -19,9 +19,10 @@ struct User final { std::optional bio; std::optional image; std::string password_hash; + std::string salt; auto Introspect() { - return std::tie(id, username, email, bio, image, password_hash); + return std::tie(id, username, email, bio, image, password_hash, salt); } }; diff --git a/src/utils/random.cpp b/src/utils/random.cpp new file mode 100644 index 0000000..147a83c --- /dev/null +++ b/src/utils/random.cpp @@ -0,0 +1,18 @@ +#include + +#include +#include "random.hpp" + +namespace real_medium::utils::random { +std::string GenerateSalt() { + std::random_device dev; + std::mt19937 rng(dev()); + std::uniform_int_distribution dist(48,122); + const int kSaltLength = 32; + std::string salt; + for (size_t i = 0; i < kSaltLength; ++i) { + salt += static_cast(dist(rng)); + } + return salt; +} +} // namespace real_medium::utils::random \ No newline at end of file diff --git a/src/utils/random.hpp b/src/utils/random.hpp new file mode 100644 index 0000000..85108e8 --- /dev/null +++ b/src/utils/random.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include + +namespace real_medium::utils::random { +std::string GenerateSalt(); +} // namespace real_medium::utils::random diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 21a12c7..ce88e03 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -14,6 +14,5 @@ userver_testsuite_add( PYTEST_ARGS --service-config=${CMAKE_SOURCE_DIR}/configs/static_config.yaml --service-binary=${CMAKE_BINARY_DIR}/realmedium_sample - --config-fallback=${CMAKE_SOURCE_DIR}/configs/dynamic_config_fallback.json ${PYTEST_ARGS_CONFIG_VARS} ) From f40c45436d24b4f49e03e8ab60d106166608dd45 Mon Sep 17 00:00:00 2001 From: Liiiza Date: Mon, 18 Nov 2024 21:52:58 +0300 Subject: [PATCH 2/3] fix docker --- tests/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ce88e03..893d1b1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,5 +1,3 @@ -include(UserverTestsuite) - set(CONFIG_VARS_PATH "${CMAKE_SOURCE_DIR}/configs/config_vars_testing.yaml") if (EXISTS "${CONFIG_VARS_PATH}") set(PYTEST_ARGS_CONFIG_VARS "--service-config-vars=${CONFIG_VARS_PATH}") From 8f71dbbf9fd8dd58db923435a948ceaf0863462d Mon Sep 17 00:00:00 2001 From: Liiizak <144727441+Liiizak@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:00:54 +0300 Subject: [PATCH 3/3] changed utils/random.cpp --- src/utils/random.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/utils/random.cpp b/src/utils/random.cpp index 147a83c..628a487 100644 --- a/src/utils/random.cpp +++ b/src/utils/random.cpp @@ -1,18 +1,14 @@ -#include - -#include #include "random.hpp" +#include + namespace real_medium::utils::random { std::string GenerateSalt() { - std::random_device dev; - std::mt19937 rng(dev()); - std::uniform_int_distribution dist(48,122); const int kSaltLength = 32; std::string salt; for (size_t i = 0; i < kSaltLength; ++i) { - salt += static_cast(dist(rng)); + salt += userver::utils::RandRange(32, 126); } return salt; } -} // namespace real_medium::utils::random \ No newline at end of file +} // namespace real_medium::utils::random