diff --git a/server/databases/core-pgsql/data/testCreateSubsrcibe.sql b/server/databases/core-pgsql/data/testCreateSubsrcibe.sql new file mode 100644 index 0000000..6a91987 --- /dev/null +++ b/server/databases/core-pgsql/data/testCreateSubsrcibe.sql @@ -0,0 +1,4 @@ +INSERT INTO users(id,name,login,password) VALUES('6cca3ced-9615-4e2c-bae4-580c86d78710','Lox','Login','Password'); +INSERT INTO users(id,name,login,password) VALUES('46775165-7542-49d9-a3b2-a7878980a2bc','Lox123','Login123','Password123'); + +INSERT INTO follows(folowee_id,folower_id) VALUES('6cca3ced-9615-4e2c-bae4-580c86d78710','46775165-7542-49d9-a3b2-a7878980a2bc'); \ No newline at end of file diff --git a/server/services/posts-uservice/CMakeLists.txt b/server/services/posts-uservice/CMakeLists.txt index 38e6f58..0a141bd 100644 --- a/server/services/posts-uservice/CMakeLists.txt +++ b/server/services/posts-uservice/CMakeLists.txt @@ -39,6 +39,8 @@ add_library(${PROJECT_NAME}_objs OBJECT src/api/v1/users/subscribers/subscribers.cpp src/api/v1/users/subscriptions/subscriptions.hpp src/api/v1/users/subscriptions/subscriptions.cpp + src/api/v1/users/subscribe/subscribe.hpp + src/api/v1/users/subscribe/subscribe.cpp src/models/s3_url.hpp src/models/s3_url.cpp src/models/post.hpp diff --git a/server/services/posts-uservice/configs/static_config.yaml b/server/services/posts-uservice/configs/static_config.yaml index 3b98e21..435330b 100644 --- a/server/services/posts-uservice/configs/static_config.yaml +++ b/server/services/posts-uservice/configs/static_config.yaml @@ -84,6 +84,10 @@ components_manager: method: GET task_processor: main-task-processor + handler-create-subscribe: + path: /api/v1/users/{userId}/subscribe + method: POST + task_processor: main-task-processor postgres-db-1: dbconnection: $dbconnection diff --git a/server/services/posts-uservice/src/api/v1/users/subscribe/subscribe.cpp b/server/services/posts-uservice/src/api/v1/users/subscribe/subscribe.cpp new file mode 100644 index 0000000..f62f957 --- /dev/null +++ b/server/services/posts-uservice/src/api/v1/users/subscribe/subscribe.cpp @@ -0,0 +1,85 @@ +#include "subscribe.hpp" + +#include +#include +#include + +#include +#include + +#include "models/user.hpp" +#include "userver/storages/secdist/exceptions.hpp" +#include "utils/errors.hpp" +#include "utils/fields.hpp" + +#include +#include +#include +#include +#include + +namespace posts_uservice { +bool Is_user_exists(const boost::uuids::uuid& user_id,const userver::storages::postgres::ClusterPtr& pg_cluster_) { + auto user_exists = pg_cluster_->Execute(userver::storages::postgres::ClusterHostType::kMaster, + "SELECT name FROM users WHERE id = $1", user_id); + return !user_exists.IsEmpty(); +} + +namespace { + +class Subscribe final : public userver::server::handlers::HttpHandlerBase { + public: + static constexpr std::string_view kName = "handler-create-subscribe"; + + Subscribe(const userver::components::ComponentConfig& config, + const userver::components::ComponentContext& context) + : HttpHandlerBase(config, context), + pg_cluster_(context.FindComponent("postgres-db-1").GetCluster()) {} + + using HttpHandlerBase::HttpHandlerBase; + + std::string HandleRequestThrow(const userver::server::http::HttpRequest& request, + userver::server::request::RequestContext&) const override { + // can be useful for hide subscriptions for someone + const std::string& user_authorized_id_argument = request.GetHeader("System-Design-User-Id"); + const std::string& user_id_argument = request.GetPathArg("userId"); + + const auto user_authorized_id = utils::ParseUUIDArgument(user_authorized_id_argument); + const auto user_id = utils::ParseUUIDArgument(user_id_argument); + + if(user_authorized_id == user_id) { + throw errors::ValidationException("user","Can not subcribe to yourself"); + } + if(!Is_user_exists(user_authorized_id,pg_cluster_)) { + throw errors::NotFoundException("user", "User with this id not found"); + } + if(!Is_user_exists(user_id,pg_cluster_)) { + throw errors::NotFoundException("user", "User with this id not found"); + } + + auto res = pg_cluster_->Execute(userver::storages::postgres::ClusterHostType::kMaster, + "SELECT folowee_id,folower_id FROM follows WHERE folowee_id = $1 AND folower_id = $2", + user_id,user_authorized_id); + + if(!res.IsEmpty()) { + return "Already subscribed"; + } + + res = pg_cluster_->Execute(userver::storages::postgres::ClusterHostType::kMaster, + "INSERT INTO follows(folowee_id,folower_id) VALUES($1,$2)", + user_id,user_authorized_id); + + return "Subcribed"; + } + + private: + userver::storages::postgres::ClusterPtr pg_cluster_; +}; + +} // namespace + +void AppendSubscribe(userver::components::ComponentList& component_list) { + component_list.Append(); +} + +} // namespace posts_uservice diff --git a/server/services/posts-uservice/src/api/v1/users/subscribe/subscribe.hpp b/server/services/posts-uservice/src/api/v1/users/subscribe/subscribe.hpp new file mode 100644 index 0000000..c22189d --- /dev/null +++ b/server/services/posts-uservice/src/api/v1/users/subscribe/subscribe.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +#include + +namespace posts_uservice { + +void AppendSubscribe(userver::components::ComponentList& component_list); + +} // namespace posts_uservice diff --git a/server/services/posts-uservice/src/api/v1/users/subscribers/subscribers.cpp b/server/services/posts-uservice/src/api/v1/users/subscribers/subscribers.cpp index 88dc549..d3e5ff9 100644 --- a/server/services/posts-uservice/src/api/v1/users/subscribers/subscribers.cpp +++ b/server/services/posts-uservice/src/api/v1/users/subscribers/subscribers.cpp @@ -39,7 +39,7 @@ class GetSubscribers final : public userver::server::handlers::HttpHandlerBase { const std::string& user_authorized_id_argument = request.GetHeader("System-Design-User-Id"); const std::string& user_id_argument = request.GetPathArg("userId"); - const auto user_authorized_id = utils::ParseUUIDArgument(user_id_argument); + const auto user_authorized_id = utils::ParseUUIDArgument(user_authorized_id_argument); const auto user_id = utils::ParseUUIDArgument(user_id_argument); auto user_exists = pg_cluster_->Execute(userver::storages::postgres::ClusterHostType::kMaster, diff --git a/server/services/posts-uservice/src/api/v1/users/subscriptions/subscriptions.cpp b/server/services/posts-uservice/src/api/v1/users/subscriptions/subscriptions.cpp index 1c7da29..3a25df4 100644 --- a/server/services/posts-uservice/src/api/v1/users/subscriptions/subscriptions.cpp +++ b/server/services/posts-uservice/src/api/v1/users/subscriptions/subscriptions.cpp @@ -39,7 +39,7 @@ class GetSubscriptions final : public userver::server::handlers::HttpHandlerBase const std::string& user_authorized_id_argument = request.GetHeader("System-Design-User-Id"); const std::string& user_id_argument = request.GetPathArg("userId"); - const auto user_authorized_id = utils::ParseUUIDArgument(user_id_argument); + const auto user_authorized_id = utils::ParseUUIDArgument(user_authorized_id_argument); const auto user_id = utils::ParseUUIDArgument(user_id_argument); auto user_exists = pg_cluster_->Execute(userver::storages::postgres::ClusterHostType::kMaster, diff --git a/server/services/posts-uservice/src/main.cpp b/server/services/posts-uservice/src/main.cpp index 9e1c2cf..7db154a 100644 --- a/server/services/posts-uservice/src/main.cpp +++ b/server/services/posts-uservice/src/main.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -13,6 +14,7 @@ #include "api/v1/users/posts/last_posts.hpp" #include "api/v1/users/subscribers/subscribers.hpp" #include "api/v1/users/subscriptions/subscriptions.hpp" +#include "api/v1/users/subscribe/subscribe.hpp" int main(int argc, char* argv[]) { auto component_list = userver::components::MinimalServerComponentList() @@ -29,6 +31,7 @@ int main(int argc, char* argv[]) { posts_uservice::AppendGetFeed(component_list); posts_uservice::AppendGetSubscribers(component_list); posts_uservice::AppendGetSubscriptions(component_list); + posts_uservice::AppendSubscribe(component_list); return userver::utils::DaemonMain(argc, argv, component_list); } diff --git a/server/services/posts-uservice/tests/test_create_subcribe.py b/server/services/posts-uservice/tests/test_create_subcribe.py new file mode 100644 index 0000000..0501afa --- /dev/null +++ b/server/services/posts-uservice/tests/test_create_subcribe.py @@ -0,0 +1,52 @@ +# Start via `make test-debug` or `make test-release` + +import pytest + +from testsuite.databases import pgsql + +from utils.error_strings import * + +# No test for absent id + +FIRST_GUY = '6cca3ced-9615-4e2c-bae4-580c86d78710' +SECOND_GUY = '46775165-7542-49d9-a3b2-a7878980a2bc' + +@pytest.mark.pgsql('db', files=['testCreateSubsrcibe.sql']) +async def test_create_subcribe_with_incorrect_id(service_client): + response = await service_client.post( + f'/api/v1/users/kek/subscribe', + headers={'System-Design-User-Id': '123'}, + ) + assert response.status == 400 + assert VALIDATION_ERROR_START in response.text + +@pytest.mark.pgsql('db', files=['testCreateSubsrcibe.sql']) +async def test_create_subcribe_with_myself(service_client): + response = await service_client.post( + f'/api/v1/users/{FIRST_GUY}/subscribe', + headers={'System-Design-User-Id': FIRST_GUY} + ) + assert response.status == 400 + assert VALIDATION_ERROR_START in response.text + +@pytest.mark.pgsql('db', files=['testCreateSubsrcibe.sql']) +async def test_create_subcribe_twice(service_client): + response = await service_client.post( + f'/api/v1/users/{FIRST_GUY}/subscribe', + headers={'System-Design-User-Id': SECOND_GUY} + ) + assert response.status == 200 + assert response.text == "Already subscribed" +@pytest.mark.pgsql('db', files=['testCreateSubsrcibe.sql']) +async def test_create_subcribe_good(service_client): + response = await service_client.post( + f'/api/v1/users/{SECOND_GUY}/subscribe', + headers={'System-Design-User-Id': FIRST_GUY} + ) + assert response.status == 200 + assert response.text == "Subcribed" + + + + +