HSE first year C++ project
- Клиенты и их возможности
- Схема БД
- Архитектура клиента
- Архитектура сервера
- Схема сетей
- Обработка запросов клиента
- Сценарии
- Запросы клиента
- Формат POST-запросов
- Формат ответов
- Формат уведомлений
- Сборка
Две роли — заказчик (через приложение) и администратор (через телеграм-бота).
Возможности заказчика:
- Регистрация/авторизация
- Просмотр меню
- Изменение корзины
- Добавление/удаление товара
- Сброс корзины
- Оформление заказа
- Просмотр истории заказов
- Просмотр информации о конкретном заказе
Возможности администратора:
- Авторизация
- Изменение меню
- Изменение стоимости товара
- Изменение статуса товара
- Добавление нового товара
- Изменение статуса заказа
Запросы бывают двух типов:
- GET-запросы с целью получения актуальных данных
- POST-запросы для внесения изменений на сервере
Посылки сервера так же бывают двух типов:
- Ответ — посылается только сессии-источнику первоначального запроса
- Уведомление — посылается во все открытые принимающие сессии пользователя
На сервере у корзины и у каждого заказа должен быть timestamp — время последнего изменения с точки зрения сервера
- Запрос данных
- Клиент посылает GET-запрос.
- Сервер присылает ответ.
- Изменение данных
- Клиент посылает POST-запрос.
- Сервер обрабатывает запрос и присылает ответ содержащий итог обработки (успех/неуспех) и timestamp, который был присвоен этому изменению.
- В случае успеха сервер также посылает пользователю уведомление с информацией о том, какие данные изменились, и timestamp-ом изменения.
- Все клиенты, получившие уведомление, сравнивают timestamp изменения с timestamp-ом имеющихся данных и в случае несоответствия отправляют соответствующие GET-запросы.
- Сервер рассылает ответы на полученные GET-запросы.
- Регистрация/авторизация
- Клиент посылает POST-запрос с данными для регистрации/авторизации.
- Сервер обрабатывает запрос, присылает ответ с итогом обработки запроса.
- В случае успеха формат ответа должен совпадать с форматом ответа на запрос
sign_in
. - ОПЦИОНАЛЬНО: сервер посылает пользователю уведомление о новом входе/попытке входа в аккаунт.
- GET-запросы
get_menu
- resource: /menu
get_order
- resource: /order
get_cart
- resource: /cart
- POST-запросы
set_item_count
- resource: /cart
set_cart
- resource: /cart
create_order
- resource: /order
sign_in
- resource: /user
sign_up
- resource: /user
sign_in
/sign_up
Для sign_in
имя не передаётся, поэтому достаточно в name
передать пустую строку
Также в случае sign_in
передаётся поле update_cart
= 1, если корзина, которую пользователь набрал, будучи не залогиненным, изменялась позже, чем корзина, сохранённая на аккаунте
Для sign_up
поле update_cart
указывает на то, что корзина не пуста, и соответственно её нужно обновить (по умолчанию корзина пуста)
{
"query": "sign_in",
"body": {
"name": "Alice",
"email": "[email protected]",
"password": "password",
"update_cart": 1,
"cart": [
{
"dish_id": 1,
"count": 1
},
...
]
}
}
set_item_count
/set_cart
"cart" нужен только для set_cart
(ненужные поля для команд оставить пустыми)
{
"query": "set_item_count",
"body": {
"dish_id": 1,
"count": 1,
"cart": [
{
"dish_id": 1,
"count": 1
},
...
]
}
}
Остальная информация (имя, корзина и т.п.) не нужна, так как её можно получить по айдишнику пользователя
{
"query": "create_order",
"body": {
"address": "Somewhere in Germany",
"comment": "Something good (or not)"
}
}
timestamp
— дата последнего обновления меню в seconds since epoch
{
"query": "get_menu",
"status_code": 0,
"body": {
"item": "menu",
"timestamp": "34680923",
"contents": [
{
"item": "dish",
"dish_id": 0,
"name": "Lasagna",
"image": "https://i.imgur.com/SPHmdBR.jpg",
"price": 100,
"info": "Some kind of a description",
"status": 1
},
...
]
}
}
Аналогичный ответ для sign_up
timestamp
— дата заказа
{
"query": "sign_in",
"status_code": 0,
"body": {
"item": "user",
"user_id": 0,
"name": "Alice",
"email": "[email protected]",
"orders": [
{
"order_id": 0,
"status": 2,
"timestamp": "34680923",
"last_modified": "34680923"
},
...
]
}
}
{
"query": "get_cart",
"status_code": 0,
"body": {
"item": "cart",
"timestamp": "34680923",
"contents": [
{
"dish_id": 0,
"count": 1
},
...
]
}
}
{
"query": "get_order",
"status_code": 0,
"body": {
"item": "order",
"order_id": 0,
"timestamp": "34680923",
"last_modified": "34680923",
"cost": 1430,
"status": 0,
"address": "Somewhere in Israel",
"comment": "Something you don't know what",
"cart": {
"item": "cart",
"contents": [
{
"dish_id": 0,
"count": 1
},
...
]
}
}
}
{
"query": "...",
"status_code": 1,
"body": {
"item": "error",
"error_code": 1,
"body": {
...
}
}
}
Формат ответа для set_item_count
, set_cart
и create_order
{
"query": "cart_changed",
"status_code": 0,
"timestamp": "34680923"
}
- cart_changed
- order_changed
- menu_changed
- ОПЦИОНАЛЬНО: new_sign_in
{
"event": "cart_changed",
"timestamp": "34680923"
}
Сюда входят в частности изменение статуса и создание нового заказа
{
"event": "order_changed",
"timestamp": "34680923",
"body": {
"order_id": 1
}
}
{
"event": "menu_changed",
"timestamp": "34680923"
}
{
"event": "new_sign_in",
"timestamp": "34680923",
"body": {
"query": "sign_in",
"status": 0
}
}
Предполагается использование ОС Linux (Ubuntu 16.04+). Необходимо склонировать ветку deploy. Все последующие действия выполнять из той же директории, в которую было произведено клонирование.
- restbed — асинхронная работа с HTTPS запросами на сервере. См. build
- nlohmann/json — см. CMakeLists.txt
- PostgreSQL — реляционная база данных. См. шаги 1 и 2. Затем необходимо установить пароль командой
\password postgres
. Далее см. шаг 4. После этого необходимо настроить порты и разрешить подключение не только с локальной машины (на ваше усмотрение):-
$ sudo gedit /etc/postgresql/12/main/postgresql.conf
-
Меняем строчку
listen_addresses = '*'
-
Настроить порты можно командой
$ ss -nlt
(в нашем случае это порт 5432 и IP-адрес удаленного сервера). Убедитесь, что ваш IP-адрес есть в списке. -
Перезапускаем, чтобы сохранить изменения:
$ sudo systemctl restart postgresql
-
База данных готова к использованию. Подключение к БД на удаленном сервере выполняется командой
$ psql -U<имя_пользователя> -h<IP-адрес> -d<имя_БД>
-
См. список команд, чтобы наполнить базу данных
-
Библиотека libpqxx уже есть в CMakeLists.txt, дополнительных действий не требуется
-
- Qt — интерфейс клиента:
$ sudo apt-get install qt5-default
$ sudo apt-get install qml-module-qtquick-dialogs qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtquick-window2
- tgbot-cpp — см. установку. Больше ничего не требуется, CMakeLists.txt уже настроен
- gflags — настройка флагов для запуска из консоли:
$ sudo apt-get install libgflags-dev
- folly — потокобезопасность (folly::Synchronized) и работа с JSON (folly::dynamic). См. build. Необходимо настроить пути до папок folly, как это сделано в CMakeLists.txt. Будьте внимательны, иначе потратите кучу нервов :) А еще надо иметь в виду, что установка folly съедает немалое количество места на диске, поэтому более разумным будет установка только необходимых библиотек (см. используемые библиотеки в CMakeLists.txt)
--port N # Номер порта (0 < N < 32768), обязательный
--SSLkeys /GLOBAL/PATH # Путь до папки с ключами и сертификатом для соединения по протоколу https, обязательный
--workers # Максимальное количество потоков (0 < n < 100), по умолчанию 10
$ cmake --build . --target RestaurantBES
$ ./RestaurantBES --port <N> --SSLkeys </GLOBAL/PATH>
$ cmake --build . --target QtClient
$ ./QtClient --server <IP-адрес>