Skip to content

Commit 13f3bc9

Browse files
authored
Merge pull request #58 from Serveis-Neby/task/138-manage-service-accpetion-and-refused
Task/138 manage service accpetion and refused
2 parents 5154a33 + f9974f6 commit 13f3bc9

29 files changed

+432
-164
lines changed

include/controllers/notification_controller.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@
1313
class NotificationController {
1414
public:
1515
static void create_notification(pqxx::connection& db, const crow::request& req, crow::response& res, const std::string& service_id);
16+
static void handle_notification(pqxx::connection& db, const crow::request& req, crow::response& res, const std::string& notification_id);
1617
};

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: 73 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,73 @@ 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+
updated_notification = NotificationModel::handle_notification_status(db, NotificationStatus::ACCEPTED, notification_id, true);
116+
117+
bool succes_refused = NotificationModel::refused_notifications(db, updated_notification.get()->get_service_id(), notification_id);
118+
119+
if (!succes_refused) {
120+
handle_error(res, "error in refused other notifications", 400);
121+
return;
122+
}
123+
}
124+
125+
//? if action == refused -> refuse the notification
126+
std::cout << action << std::endl;
127+
res.code = 200;
128+
crow::json::wvalue data;
129+
data["id"] = updated_notification.get()->get_id();
130+
data["sender_id"] = updated_notification.get()->get_sender_id();
131+
data["service_id"] = updated_notification.get()->get_service_id();
132+
data["status"] = updated_notification.get()->get_status();
133+
data["created_at"] = updated_notification.get()->get_created_at();
134+
data["updated_at"] = updated_notification.get()->get_updated_at();
135+
res.write(data.dump());
136+
137+
res.end();
138+
} catch (const std::exception& e) {
139+
std::cerr << e.what() << '\n';
140+
}
141+
}

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);

src/middlewares/verify_jwt.cpp

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#include <middlewares/verify_jwt.h>
2+
23
void VerifyJWT::before_handle(crow::request& req, crow::response& res, context& ctx) {
4+
ConnectionPool& pool = ConnectionPool::getInstance(connection_string, 10);
5+
auto conn = pool.getConnection();
36
std::string token = get_token_cookie(req);
47

58
if (token == "") {
@@ -14,52 +17,41 @@ void VerifyJWT::before_handle(crow::request& req, crow::response& res, context&
1417

1518
auto decoded = jwt::decode(token);
1619

17-
std::string id, type, community_id, username, email, created_at, updated_at, balance;
20+
std::string id;
1821

1922
for (auto& e : decoded.get_payload_json()) {
20-
if (e.first == "id") {
23+
if (e.first == "id")
2124
id = e.second.get<std::string>();
22-
} else if (e.first == "type") {
23-
type = e.second.get<std::string>();
24-
} else if (e.first == "community_id") {
25-
community_id = e.second.get<std::string>();
26-
} else if (e.first == "username") {
27-
username = e.second.get<std::string>();
28-
} else if (e.first == "email") {
29-
email = e.second.get<std::string>();
30-
} else if (e.first == "created_at") {
31-
created_at = e.second.get<std::string>();
32-
} else if (e.first == "updated_at") {
33-
updated_at = e.second.get<std::string>();
34-
} else if (e.first == "balance") {
35-
balance = e.second.get<std::string>();
36-
}
3725
}
3826

27+
std::unique_ptr<UserModel> user = UserModel::get_user_by_id(*conn.get(), id);
28+
29+
pool.releaseConnection(conn);
30+
3931
if (req.body == "") {
4032
crow::json::wvalue body;
4133

4234
body["id"] = id;
43-
body["isAdmin"] = (type == "admin");
44-
body["request_community_id"] = community_id;
45-
body["request_username"] = username;
46-
body["request_email"] = email;
47-
body["request_created_at"] = created_at;
48-
body["request_updated_at"] = updated_at;
49-
body["request_balance"] = std::stoi(balance);
35+
body["isAdmin"] = (user.get()->get_type() == "admin");
36+
body["request_community_id"] = user.get()->get_community_id();
37+
body["request_username"] = user.get()->get_username();
38+
body["request_email"] = user.get()->get_email();
39+
body["request_created_at"] = user.get()->get_created_at();
40+
body["request_updated_at"] = user.get()->get_updated_at();
41+
body["request_balance"] = user.get()->get_balance();
5042

5143
req.body = body.dump();
5244
} else {
5345
crow::json::wvalue body = crow::json::load(req.body);
5446

5547
body["id"] = id;
56-
body["isAdmin"] = (type == "admin");
57-
body["request_community_id"] = community_id;
58-
body["request_username"] = username;
59-
body["request_email"] = email;
60-
body["request_created_at"] = created_at;
61-
body["request_updated_at"] = updated_at;
62-
body["request_balance"] = std::stoi(balance);
48+
body["isAdmin"] = (user.get()->get_type() == "admin");
49+
body["request_community_id"] = user.get()->get_community_id();
50+
body["request_username"] = user.get()->get_username();
51+
body["request_email"] = user.get()->get_email();
52+
body["request_created_at"] = user.get()->get_created_at();
53+
body["request_updated_at"] = user.get()->get_updated_at();
54+
body["request_balance"] = user.get()->get_balance();
6355
req.body = body.dump();
6456
}
6557
}

0 commit comments

Comments
 (0)