Skip to content

Commit

Permalink
add docker compose and postgresql to store users
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexey-Sagaydak committed Nov 10, 2024
1 parent df4b80f commit aabeb2d
Show file tree
Hide file tree
Showing 13 changed files with 360 additions and 170 deletions.
3 changes: 2 additions & 1 deletion .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**"
"${workspaceFolder}/**",
"/usr/include/pqxx"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
Expand Down
19 changes: 18 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,23 @@
"thread": "cpp",
"cinttypes": "cpp",
"typeinfo": "cpp",
"valarray": "cpp"
"valarray": "cpp",
"pqxx": "cpp",
"csignal": "cpp",
"any": "cpp",
"bitset": "cpp",
"charconv": "cpp",
"codecvt": "cpp",
"complex": "cpp",
"coroutine": "cpp",
"set": "cpp",
"optional": "cpp",
"source_location": "cpp",
"iomanip": "cpp",
"ranges": "cpp",
"span": "cpp",
"typeindex": "cpp",
"variant": "cpp",
"format": "cpp"
}
}
8 changes: 7 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
FROM ubuntu:24.04

RUN apt-get update && apt-get install -y libboost-all-dev
RUN apt-get update && \
apt-get install -y \
libboost-all-dev \
libpq-dev \
libpqxx-dev \
cmake \
build-essential

COPY ./server/build/libhv-http /usr/local/bin/http-server

Expand Down
54 changes: 40 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,40 +34,66 @@
- Тело ответа: Пустое
- Описание: Редактирует данные пользователя по его идентификатору.

## Инструменты и технологии

- Язык программирования: C++
- Библиотека: libhv
- Утилита для тестирования: curl

## Сборка и запуск

1. Склонируйте репозиторий:
```bash
git clone <URL_репозитория>
```

2. Перейдите в папку build каталогов client и server проекта (создайте при необходимости):
```bash
cd <название_папки>
```
2. Перейдите в `server/build` (создайте при необходимости):

3. Соберите проекты клиента и сервера:
3. Соберите сервер:
```bash
cmake ..
make
```

4. Запустите сервер из соответствующей папки build:
4. Запустите контейнеры через Docker Compose:
```bash
./libhv-http
sudo docker compose up --build -d
```

5. Запустите клиента из соответствующей папки build:
5. Подключитесь к контейнеру с PostgreSQL
```bash
sudo docker compose exec db psql -U myuser -d usersdb
```

6. Создайте таблицу `users` при первом запуске (при последующих запусках внесенные изменения сохранятся):
```sql
CREATE TABLE users (
userId UUID PRIMARY KEY,
username VARCHAR(50) NOT NULL,
password VARCHAR(64) NOT NULL,
isAdmin BOOLEAN NOT NULL
);
```

Чтобы убедиться, что таблица создана, выполните команду `\d users`:
```
usersdb=# \d users
Table "public.users"
Column | Type | Collation | Nullable | Default
----------+-----------------------+-----------+----------+---------
userid | uuid | | not null |
username | character varying(50) | | not null |
password | character varying(64) | | not null |
isadmin | boolean | | not null |
Indexes:
"users_pkey" PRIMARY KEY, btree (userid)
"users_username_key" UNIQUE CONSTRAINT, btree (username)
```

7. Проверим работу сервера, запустив клиента из соответствующей папки build:
```bash
./libhv-client
```

8. Для завершения работы сервера введите команду:
```bash
sudo docker compose down
```

## Использование
Меню клиента имеет следующий вид:

Expand Down
29 changes: 29 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
version: '3.8'
services:
db:
image: postgres:15
environment:
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypassword
POSTGRES_DB: usersdb
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data

http-server:
build:
context: .
dockerfile: Dockerfile
ports:
- "7777:7777"
environment:
DB_HOST: db
DB_USER: myuser
DB_PASSWORD: mypassword
DB_NAME: usersdb
depends_on:
- db

volumes:
pgdata:
24 changes: 19 additions & 5 deletions server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,23 @@ set(TARGET_NAME "libhv-http")

set(LIBHV_INCLUDE ${PROJECT_BINARY_DIR}/contrib/libhv/include/hv)

# Поиск OpenSSL
find_package(OpenSSL REQUIRED)

# Поиск libpqxx и libpq
find_package(PkgConfig REQUIRED)
pkg_check_modules(PQXX REQUIRED libpqxx)
pkg_check_modules(PQ REQUIRED libpq)

# Добавляем пути к заголовкам
include_directories(${PQXX_INCLUDE_DIRS} ${PQ_INCLUDE_DIRS})

add_subdirectory(${PROJECT_SOURCE_DIR}/contrib)

# Устанавливаем флаги компиляции
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -Werror -Wempty-body -Wredundant-move -O2")

# Список исходников
file(GLOB_RECURSE SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/*.hpp
Expand All @@ -23,11 +34,14 @@ execute_process(
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
string(REPLACE "\n" ";" SOURCE_DIR_HEADER ${SOURCE_DIR_HEADER})

string(REPLACE "\n" ";" SOURCE_DIR_HEADER ${SOURCE_DIR_HEADER})

# Включение директорий с заголовками
include_directories(${SOURCE_DIR_HEADER})
include_directories(${LIBHV_INCLUDE})


# Создание исполняемого файла
add_executable(${TARGET_NAME} ${SOURCES})
target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES})
target_link_libraries(${TARGET_NAME} hv_static)

# Линковка с библиотеками
target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES} ${PQXX_LIBRARIES} ${PQ_LIBRARIES} hv_static)
89 changes: 89 additions & 0 deletions server/src/Database.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include "Database.hpp"

Database::Database(const std::string& connInfo) : _conn(connInfo) {}

bool Database::addUser(const User& user) {
try {
pqxx::work txn(_conn);
txn.exec_params("INSERT INTO users (userId, username, password, isAdmin) VALUES ($1, $2, $3, $4)",
user.userId, user.username, user.password, user.isAdmin);
txn.commit();
return true;
} catch (const std::exception& e) {
return false;
}
}

bool Database::getUser(const std::string& userId, User& user) {
try {
pqxx::work txn(_conn);
auto row = txn.exec_params("SELECT userId, username, password, isAdmin FROM users WHERE userId = $1", userId);
if (row.size() == 1) {
user.userId = row[0][0].as<std::string>();
user.username = row[0][1].as<std::string>();
user.password = row[0][2].as<std::string>();
user.isAdmin = row[0][3].as<bool>();
return true;
}
return false;
} catch (const std::exception& e) {
return false;
}
}

bool Database::deleteUser(const std::string& userId) {
try {
pqxx::work txn(_conn);
txn.exec_params("DELETE FROM users WHERE userId = $1", userId);
txn.commit();
return true;
} catch (const std::exception& e) {
return false;
}
}

bool Database::updateUser(const User& user) {
try {
pqxx::work txn(_conn);
txn.exec_params("UPDATE users SET username = $2, password = $3, isAdmin = $4 WHERE userId = $1",
user.userId, user.username, user.password, user.isAdmin);
txn.commit();
return true;
} catch (const std::exception& e) {
return false;
}
}

std::vector<User> Database::getAllUsers() {
std::vector<User> users;
try {
pqxx::work txn(_conn);
auto rows = txn.exec("SELECT userId, username, password, isAdmin FROM users");
for (const auto &row : rows) {
User user;
user.userId = row[0].as<std::string>();
user.username = row[1].as<std::string>();
user.password = row[2].as<std::string>();
user.isAdmin = row[3].as<bool>();
users.push_back(user);
}
} catch (const std::exception& e) { }
return users;
}

bool Database::getUserByUsername(const std::string& username, User& user) {
try {
pqxx::work txn(_conn);
auto row = txn.exec_params("SELECT userId, username, password, isAdmin FROM users WHERE username = $1", username);
if (row.size() == 1) {
user.userId = row[0][0].as<std::string>();
user.username = row[0][1].as<std::string>();
user.password = row[0][2].as<std::string>();
user.isAdmin = row[0][3].as<bool>();
return true;
}
return false;
} catch (const std::exception& e) {
return false;
}
}
27 changes: 27 additions & 0 deletions server/src/Database.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef _DATABASE_HPP_
#define _DATABASE_HPP_

#include <pqxx/pqxx>

struct User {
std::string userId;
std::string username;
std::string password;
bool isAdmin;
};

class Database {
public:
Database(const std::string& connInfo);
bool addUser(const User& user);
bool getUser(const std::string& userId, User& user);
bool deleteUser(const std::string& userId);
bool updateUser(const User& user);
std::vector<User> getAllUsers();
bool getUserByUsername(const std::string& username, User& user);

private:
pqxx::connection _conn;
};

#endif
5 changes: 3 additions & 2 deletions server/src/HTTPServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

#include <thread>

HttpServer::HttpServer()
HttpServer::HttpServer(const std::string& dbConnInfo)
: _database(dbConnInfo)
{
_server = std::make_unique<hv::HttpServer>();
route::RegisterResources(_router, _users);
route::RegisterResources(_router, _database);
_server->registerHttpService(&_router);
}

Expand Down
14 changes: 8 additions & 6 deletions server/src/HTTPServer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,25 @@
#include "HttpServer.h"
#include "HttpService.h"
#include "Routers.hpp"
#include <memory>

class HttpServer final
{
class HttpServer final {
public:
using UPtr = std::unique_ptr<HttpServer>;

HttpServer();
explicit HttpServer(const std::string& dbConnInfo);

HttpServer(const HttpServer &) = delete;
HttpServer(HttpServer &&) = delete;
~HttpServer();


void Start(int port);

~HttpServer();

private:
std::unique_ptr<hv::HttpServer> _server;
HttpService _router;
std::unordered_map<std::string, User> _users;
Database _database;
};

#endif
Loading

0 comments on commit aabeb2d

Please sign in to comment.