Skip to content

Commit 694ff7d

Browse files
committed
task #152:merged with develop and resolved
2 parents 76d248d + 5073d9e commit 694ff7d

29 files changed

+465
-166
lines changed

include/controllers/notification_controller.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <crow.h>
44
#include <models/notification_model.h>
55
#include <models/service_model.h>
6+
#include <models/user_model.h>
67
#include <utils/common.h>
78
#include <utils/utils.h>
89
#include <format>
@@ -13,4 +14,5 @@
1314
class NotificationController {
1415
public:
1516
static void create_notification(pqxx::connection& db, const crow::request& req, crow::response& res, const std::string& service_id);
17+
static void handle_notification(pqxx::connection& db, const crow::request& req, crow::response& res, const std::string& notification_id);
1618
};

include/db/connection_pool.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#pragma once
2+
3+
#include <condition_variable>
4+
#include <iostream>
5+
#include <mutex>
6+
#include <pqxx/pqxx>
7+
#include <queue>
8+
9+
class ConnectionPool {
10+
public:
11+
static ConnectionPool& getInstance(const std::string& connectionString, int poolSize) {
12+
static ConnectionPool instance(connectionString, poolSize);
13+
return instance;
14+
}
15+
16+
ConnectionPool(const ConnectionPool&) = delete;
17+
ConnectionPool& operator=(const ConnectionPool&) = delete;
18+
19+
std::shared_ptr<pqxx::connection> getConnection();
20+
21+
void releaseConnection(std::shared_ptr<pqxx::connection> conn);
22+
23+
private:
24+
ConnectionPool(const std::string& connectionString, int poolSize);
25+
26+
~ConnectionPool() ;
27+
28+
std::shared_ptr<pqxx::connection> createConnection();
29+
30+
private:
31+
std::string connectionString_;
32+
int poolSize_;
33+
std::deque<std::shared_ptr<pqxx::connection>> connections_;
34+
std::mutex mutex_;
35+
std::condition_variable condition_;
36+
};

include/middlewares/verify_jwt.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
#pragma once
22

33
#include <crow.h>
4+
#include <db/connection_pool.h>
45
#include <jwt-cpp/jwt.h>
56
#include <utils/auth.h>
7+
#include <utils/common.h>
68
#include <utils/utils.h>
9+
#include <memory>
710

811
struct VerifyJWT : crow::ILocalMiddleware {
912
struct context {};
1013

1114
void before_handle(crow::request& req, crow::response& res, context& ctx);
1215
void after_handle(crow::request& req, crow::response& res, context& ctx);
1316
};
17+
18+
using NebyApp = crow::App<VerifyJWT>;

include/models/community_model.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class CommunityModel {
2424
std::string get_created_at() const;
2525
std::string get_updated_at() const;
2626

27-
static std::string generate_community_code();
27+
static std::string generate_community_code(const std::string& seed);
2828

2929
static std::unique_ptr<CommunityModel> create_community(pqxx::connection& db, const std::string& name, bool throw_when_null = false);
3030

include/models/notification_model.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,10 @@ class NotificationModel {
2727

2828
// * if the requester has already requested the service before, it returns true, otherwise false
2929
static bool is_requested(pqxx::connection& db, const std::string& sender_id);
30+
31+
static std::unique_ptr<NotificationModel> handle_notification_status(pqxx::connection& db, const std::string& status, const std::string& notification_id, bool throw_when_null = false);
32+
33+
static bool refused_notifications(pqxx::connection& db, const std::string& service_id, const std::string& notification_id);
34+
35+
static std::unique_ptr<NotificationModel> get_notification_by_id(pqxx::connection& db, const std::string& id, bool throw_when_null = false);
3036
};

include/routes/auth_routes.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
#include <middlewares/verify_jwt.h>
66
#include <utils/common.h>
77
#include <pqxx/pqxx>
8+
#include <db/connection_pool.h>
89

9-
void initialize_auth_routes(NebyApp& app, pqxx::connection& db);
10+
void initialize_auth_routes(NebyApp& app);

include/routes/notification_routes.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
#include <controllers/notification_controller.h>
44
#include <crow.h>
5+
#include <db/connection_pool.h>
56
#include <middlewares/verify_jwt.h>
7+
#include <db/connection_pool.h>
68
#include <utils/common.h>
79
#include <pqxx/pqxx>
810

9-
void initialize_notifications_routes(NebyApp& app, pqxx::connection& db);
11+
void initialize_notifications_routes(NebyApp& app);

include/routes/service_routes.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
#include <controllers/service_controller.h>
44
#include <crow.h>
55
#include <middlewares/verify_jwt.h>
6+
#include <db/connection_pool.h>
67
#include <utils/common.h>
78
#include <pqxx/pqxx>
89

9-
void initialize_service_routes(NebyApp& app, pqxx::connection& db);
10+
void initialize_service_routes(NebyApp& app);

include/routes/user_routes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@
66
#include <utils/common.h>
77
#include <pqxx/pqxx>
88

9-
void initialize_user_routes(NebyApp& app, pqxx::connection& db);
9+
void initialize_user_routes(NebyApp& app);

include/utils/common.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
#pragma once
22
#include <crow.h>
3+
#include <db/connection_pool.h>
34
#include <middlewares/verify_jwt.h>
45
#include <bcrypt/BCrypt.hpp>
6+
#include <cstdlib>
57
#include <map>
68
#include <string>
79

8-
using NebyApp = crow::App<VerifyJWT>;
910

10-
struct Roles {
11+
extern const std::string DB_NAME;
12+
extern const std::string DB_USER;
13+
extern const std::string DB_PASSWORD;
14+
extern const std::string DB_HOST;
15+
extern const int DB_PORT;
16+
extern const int HTTP_PORT;
17+
extern const std::string connection_string;
18+
19+
struct Roles {
1120
static const std::string ADMIN;
1221
static const std::string NEIGHBOR;
1322
};

src/controllers/notification_controller.cpp

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ void NotificationController::create_notification(pqxx::connection& db, const cro
77
std::string notifier_id = body["id"].s();
88
int notifier_balance = body["request_balance"].i();
99

10+
std::cout << "balancation " << notifier_balance << std::endl;
11+
std::cout << "id notfiier " << notifier_id << std::endl;
12+
1013
//? check if service exist
1114
std::unique_ptr<ServiceModel> service = ServiceModel::get_service_by_id(db, service_id);
1215
if (!service) {
@@ -66,3 +69,100 @@ void NotificationController::create_notification(pqxx::connection& db, const cro
6669
handle_error(res, "internal server errror", 500);
6770
}
6871
}
72+
73+
void NotificationController::handle_notification(pqxx::connection& db, const crow::request& req, crow::response& res, const std::string& notification_id) {
74+
try {
75+
//? extarct query string param -> action = accepeted | refused
76+
auto action = req.url_params.get("action");
77+
crow::json::rvalue body = crow::json::load(req.body);
78+
std::string request_id = body["id"].s();
79+
80+
//? check if action query param exists
81+
if (!action) {
82+
handle_error(res, "string query param (action) not provided", 400);
83+
return;
84+
}
85+
86+
//? check if action = accepted || refused
87+
if (!(std::string(action) == NotificationStatus::ACCEPTED || std::string(action) == NotificationStatus::REFUSED)) {
88+
handle_error(res, "action not valid value", 400);
89+
return;
90+
}
91+
92+
//? check if the notificaction exists
93+
std::unique_ptr notification = NotificationModel::get_notification_by_id(db, notification_id);
94+
95+
if (!notification) {
96+
handle_error(res, "notification not found", 400);
97+
return;
98+
}
99+
100+
//? check if the user making the request is the creator of the service
101+
std::unique_ptr<ServiceModel> service = ServiceModel::get_service_by_id(db, notification.get()->get_service_id(), true);
102+
103+
if (request_id != service.get()->get_creator_id()) {
104+
handle_error(res, "you are not the creator of the service", 400);
105+
return;
106+
}
107+
108+
//? if action == accepted -> accept the notification and refused others
109+
110+
std::unique_ptr<NotificationModel> updated_notification;
111+
112+
if (action == NotificationStatus::REFUSED) {
113+
updated_notification = NotificationModel::handle_notification_status(db, NotificationStatus::REFUSED, notification_id, true);
114+
} else {
115+
std::unique_ptr<UserModel> notificationCreator = UserModel::get_user_by_id(db, notification->get_sender_id());
116+
std::unique_ptr<UserModel> serviceCreator = UserModel::get_user_by_id(db, service->get_creator_id());
117+
118+
if (service->get_type() == ServiceType::OFFERED) {
119+
if (notificationCreator->get_balance() < service->get_price()) {
120+
handle_error(res, "notification sender does not have enough coins to pay for the service", 400);
121+
return;
122+
}
123+
else {
124+
int new_sender_balance = notificationCreator->get_balance() - service->get_price();
125+
int new_creator_balance = serviceCreator->get_balance() + service->get_price();
126+
UserModel::update_user_admin(db, notificationCreator->get_id(), notificationCreator->get_username(), new_sender_balance);
127+
UserModel::update_user_admin(db, serviceCreator->get_id(), serviceCreator->get_username(), new_creator_balance);
128+
}
129+
}
130+
else {
131+
if (serviceCreator->get_balance() < service->get_price()) {
132+
handle_error(res, "you don't have the coins to pay for this request", 400);
133+
return;
134+
}
135+
else {
136+
int new_sender_balance = notificationCreator->get_balance() + service->get_price();
137+
int new_creator_balance = serviceCreator->get_balance() - service->get_price();
138+
UserModel::update_user_admin(db, notificationCreator->get_id(), notificationCreator->get_username(), new_sender_balance);
139+
UserModel::update_user_admin(db, serviceCreator->get_id(), serviceCreator->get_username(), new_creator_balance);
140+
}
141+
}
142+
updated_notification = NotificationModel::handle_notification_status(db, NotificationStatus::ACCEPTED, notification_id, true);
143+
144+
bool succes_refused = NotificationModel::refused_notifications(db, updated_notification.get()->get_service_id(), notification_id);
145+
146+
if (!succes_refused) {
147+
handle_error(res, "error in refused other notifications", 400);
148+
return;
149+
}
150+
}
151+
152+
//? if action == refused -> refuse the notification
153+
std::cout << action << std::endl;
154+
res.code = 200;
155+
crow::json::wvalue data;
156+
data["id"] = updated_notification.get()->get_id();
157+
data["sender_id"] = updated_notification.get()->get_sender_id();
158+
data["service_id"] = updated_notification.get()->get_service_id();
159+
data["status"] = updated_notification.get()->get_status();
160+
data["created_at"] = updated_notification.get()->get_created_at();
161+
data["updated_at"] = updated_notification.get()->get_updated_at();
162+
res.write(data.dump());
163+
164+
res.end();
165+
} catch (const std::exception& e) {
166+
std::cerr << e.what() << '\n';
167+
}
168+
}

src/db/conncection_pool.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include <db/connection_pool.h>
2+
3+
std::shared_ptr<pqxx::connection> ConnectionPool::createConnection() {
4+
auto conn = std::make_shared<pqxx::connection>(connectionString_);
5+
if (!conn->is_open()) {
6+
std::cerr << "Error in connection: " << connectionString_ << std::endl;
7+
exit(1);
8+
}
9+
std::cout << "Connection established. " << std::endl;
10+
return conn;
11+
}
12+
13+
std::shared_ptr<pqxx::connection> ConnectionPool::getConnection() {
14+
std::unique_lock<std::mutex> lock(mutex_);
15+
16+
while (connections_.empty()) {
17+
condition_.wait(lock);
18+
}
19+
20+
auto conn = connections_.front();
21+
connections_.pop_front();
22+
23+
return conn;
24+
}
25+
26+
void ConnectionPool::releaseConnection(std::shared_ptr<pqxx::connection> conn) {
27+
std::unique_lock<std::mutex> lock(mutex_);
28+
29+
connections_.push_back(conn);
30+
31+
condition_.notify_one();
32+
}
33+
34+
ConnectionPool::ConnectionPool(const std::string& connectionString, int poolSize)
35+
: connectionString_(connectionString), poolSize_(poolSize) {
36+
for (int i = 0; i < poolSize_; ++i) {
37+
connections_.push_back(createConnection());
38+
}
39+
}
40+
41+
ConnectionPool::~ConnectionPool() {
42+
for (auto& conn : connections_) {
43+
conn->disconnect();
44+
}
45+
}
46+

src/main.cpp

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <crow.h>
2+
#include <db/connection_pool.h>
23
#include <routes/auth_routes.h>
34
#include <routes/notification_routes.h>
45
#include <routes/service_routes.h>
@@ -12,32 +13,14 @@
1213

1314
int main() {
1415
try {
15-
int HTTP_PORT = std::stoi(std::getenv("HTTP_PORT"));
16-
std::string DB_NAME = std::string(std::getenv("DB_NAME"));
17-
std::string DB_USER = std::string(std::getenv("DB_USER"));
18-
std::string DB_PASSWORD = std::string(std::getenv("DB_PASSWORD"));
19-
std::string DB_HOST = std::string(std::getenv("DB_HOST"));
20-
std::string DB_PORT = std::string(std::getenv("DB_PORT"));
21-
2216
NebyApp app;
23-
std::string connection_string = std::format("dbname={} user={} password={} host={} port={}", DB_NAME, DB_USER, DB_PASSWORD, DB_HOST, DB_PORT);
24-
pqxx::connection conn(connection_string);
25-
26-
27-
if (conn.is_open()) {
28-
std::cout << "Opened database successfully: " << conn.dbname() << std::endl;
29-
} else {
30-
std::cout << "Can't open database" << std::endl;
31-
exit(1);
32-
}
3317

34-
initialize_auth_routes(app, conn);
35-
initialize_user_routes(app, conn);
36-
initialize_service_routes(app, conn);
37-
initialize_notifications_routes(app, conn);
18+
initialize_auth_routes(app);
19+
initialize_user_routes(app);
20+
initialize_service_routes(app);
21+
initialize_notifications_routes(app);
3822

3923
app.port(HTTP_PORT).multithreaded().run();
40-
conn.disconnect();
4124
} catch (const std::exception &e) {
4225
std::cerr << e.what() << std::endl;
4326
exit(1);

0 commit comments

Comments
 (0)