mirror of
https://github.com/yawaflua/SpCloudCore.git
synced 2025-12-09 20:19:35 +02:00
Introduce update delete and improve resilience
This commit is contained in:
@@ -30,41 +30,37 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::string process_publish(const httplib::Request& req, App* app)
|
std::string process_publish(const httplib::Request& req, App* app)
|
||||||
{
|
{
|
||||||
const auto& content = req.files.begin()->second.content;
|
const auto& content = req.files.begin()->second.content;
|
||||||
|
|
||||||
const auto& filename = this->publish_app_path + req.files.begin()->second.filename;
|
const auto& filename = this->publish_app_path + req.files.begin()->second.filename;
|
||||||
|
|
||||||
if (filename.size() >= 4 && filename.substr(filename.size() - 4) == ".rar") {
|
if (filename.size() >= 4 && filename.substr(filename.size() - 4) == ".rar") {
|
||||||
//if (true) {//TODO UNCOMMIT WHEN STARING TO WRITE PUBLISH PROCESS
|
|
||||||
if (file_processing->save_file(filename, content)) {
|
if (file_processing->save_file(filename, content)) {
|
||||||
|
|
||||||
std::string app_final_file_path = app->get_name() + app->get_user_id();//TODO VERY IMPORTANT CHANGE THIS RANDOM GENERATING TO GENERATE UNIQUE STRING
|
std::string app_final_file_path = app->get_name() + app->get_user_id();
|
||||||
|
|
||||||
logger_.log(INFO, "app_final_file_path: " + app_final_file_path);
|
logger_.log(INFO, "app_final_file_path: " + app_final_file_path);
|
||||||
|
|
||||||
file_processing->unzip(filename, this->publish_app_path + app_final_file_path);//TODO UNCOMMIT WHEN STARING TO WRITE PUBLISH PROCESS
|
file_processing->unzip(filename, this->publish_app_path + app_final_file_path);
|
||||||
|
|
||||||
check_port_and_increase_if_not_available();
|
check_port_and_increase_if_not_available();
|
||||||
|
|
||||||
file_processing->adjust_nginx_configuration_and_reloud(app->get_name(), std::to_string(last_available_port));
|
file_processing->adjust_nginx_configuration_and_reloud(app->get_name(), std::to_string(last_available_port));
|
||||||
|
|
||||||
file_processing->create_service_file(this->publish_app_path, app_final_file_path);//TODO UNCOMMIT WHEN STARING TO WRITE PUBLISH PROCESS
|
file_processing->create_service_file(this->publish_app_path, app_final_file_path, std::to_string(last_available_port));
|
||||||
//file_processing->create_service_file(app->get_name());//TODO UNCOMMIT WHEN STARING TO WRITE PUBLISH PROCESS
|
|
||||||
|
|
||||||
if (app->get_target() == "dotnet network")
|
if (app->get_target() == "dotnet network")
|
||||||
{
|
{
|
||||||
this->dotnet_publish(this->publish_app_path + app_final_file_path, last_available_port);//TODO UNCOMMIT WHEN STARING TO WRITE PUBLISH PROCESS
|
this->dotnet_publish(this->publish_app_path + app_final_file_path, last_available_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (app->get_target() == "dotnet")
|
if (app->get_target() == "dotnet")
|
||||||
{
|
{
|
||||||
this->dotnet_publish(this->publish_app_path + app_final_file_path);//TODO UNCOMMIT WHEN STARING TO WRITE PUBLISH PROCESS
|
this->dotnet_publish(this->publish_app_path + app_final_file_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Todo introduce increase counter of available app for user in mongo db
|
|
||||||
|
|
||||||
file_processing->delete_file(filename);
|
file_processing->delete_file(filename);
|
||||||
|
|
||||||
app->set_url("https://" + app->get_name() + ".almavid.ru/");
|
app->set_url("https://" + app->get_name() + ".almavid.ru/");
|
||||||
@@ -85,9 +81,58 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string process_update(const httplib::Request& req, App* app)
|
||||||
|
{
|
||||||
|
const auto& content = req.files.begin()->second.content;
|
||||||
|
|
||||||
|
const auto& filename = this->publish_app_path + req.files.begin()->second.filename;
|
||||||
|
|
||||||
|
if (filename.size() >= 4 && filename.substr(filename.size() - 4) == ".rar") {
|
||||||
|
if (file_processing->save_file(filename, content)) {
|
||||||
|
|
||||||
|
std::string app_final_file_path = app->get_name() + app->get_user_id();
|
||||||
|
|
||||||
|
logger_.log(INFO, "app_final_file_path: " + app_final_file_path);
|
||||||
|
|
||||||
|
file_processing->delete_file(this->publish_app_path + app_final_file_path);
|
||||||
|
|
||||||
|
file_processing->unzip(filename, this->publish_app_path + app_final_file_path);
|
||||||
|
|
||||||
|
file_processing->stop_and_start_service_file(app_final_file_path);
|
||||||
|
|
||||||
|
file_processing->delete_file(filename);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "Invalid file type. Only .rar files are allowed." + filename;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Success";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string process_delete(const httplib::Request& req, App* app)
|
||||||
|
{
|
||||||
|
std::string app_final_file_path = app->get_name() + app->get_user_id();
|
||||||
|
|
||||||
|
logger_.log(INFO, "app_final_file_path: " + app_final_file_path);
|
||||||
|
|
||||||
|
file_processing->delete_file(this->publish_app_path + app_final_file_path);
|
||||||
|
|
||||||
|
file_processing->delete_file("/etc/systemd/system/" + app_final_file_path + ".service");
|
||||||
|
|
||||||
|
file_processing->remove_nginx_configuration_block_and_reload(app->get_name());
|
||||||
|
|
||||||
|
file_processing->stop_service_file(app_final_file_path);
|
||||||
|
|
||||||
|
//file_processing->stop_and_start_service_file(app_final_file_path);
|
||||||
|
|
||||||
|
return "Success";
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void dotnet_publish(const std::string& path, int port)
|
void dotnet_publish(const std::string& path, int port)
|
||||||
{//Todo adjust to build setting from mongodb
|
{
|
||||||
std::string dll_file_name = file_processing->find_file_by_suffix(path, "exe");
|
std::string dll_file_name = file_processing->find_file_by_suffix(path, "exe");
|
||||||
size_t pos = dll_file_name.find(".exe");
|
size_t pos = dll_file_name.find(".exe");
|
||||||
if (pos != std::string::npos) {
|
if (pos != std::string::npos) {
|
||||||
@@ -103,8 +148,8 @@ private:
|
|||||||
commandThread.detach();
|
commandThread.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
void dotnet_publish(const std::string& path)
|
void dotnet_publish(const std::string& path)//Todo test publishing not network app
|
||||||
{//Todo adjust to build setting from mongodb
|
{
|
||||||
std::string dll_file_name = file_processing->find_file_by_suffix(path, "exe");
|
std::string dll_file_name = file_processing->find_file_by_suffix(path, "exe");
|
||||||
size_t pos = dll_file_name.find(".exe");
|
size_t pos = dll_file_name.find(".exe");
|
||||||
if (pos != std::string::npos) {
|
if (pos != std::string::npos) {
|
||||||
|
|||||||
@@ -8,10 +8,17 @@
|
|||||||
#include "CommandService.cpp"
|
#include "CommandService.cpp"
|
||||||
#include "Logger.cpp"
|
#include "Logger.cpp"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <array>
|
||||||
|
#include <iostream>
|
||||||
|
#include "../httplib.h"
|
||||||
|
#include <string>
|
||||||
|
#include <future>
|
||||||
class FileProcessingService
|
class FileProcessingService
|
||||||
{
|
{
|
||||||
Logger& logger_;
|
Logger& logger_;
|
||||||
|
|
||||||
|
std::mutex nginx_config_mutex;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FileProcessingService(Logger& logger) : logger_(logger)
|
FileProcessingService(Logger& logger) : logger_(logger)
|
||||||
{
|
{
|
||||||
@@ -21,45 +28,10 @@ public:
|
|||||||
|
|
||||||
void adjust_nginx_configuration_and_reloud(const std::string& filename, std::string port)
|
void adjust_nginx_configuration_and_reloud(const std::string& filename, std::string port)
|
||||||
{
|
{
|
||||||
/*std::string file_path = "/etc/nginx/nginx.conf";
|
std::lock_guard<std::mutex> lock(nginx_config_mutex);
|
||||||
|
|
||||||
std::string new_text =
|
|
||||||
"server {\n"
|
|
||||||
" listen 443 ssl;\n"
|
|
||||||
" server_name " + filename + ".almavid.ru;\n\n"
|
|
||||||
" ssl_certificate /etc/letsencrypt/live/almavid.ru/fullchain.pem;\n"
|
|
||||||
" ssl_certificate_key /etc/letsencrypt/live/almavid.ru/privkey.pem;\n"
|
|
||||||
" ssl_protocols TLSv1 TLSv1.1 TLSv1.2;\n"
|
|
||||||
" ssl_ciphers HIGH:!aNULL:!MD5;\n\n"
|
|
||||||
" client_max_body_size 2G; # Allow file uploads up to 2GB\n\n"
|
|
||||||
" location / {\n"
|
|
||||||
" proxy_pass http://localhost:" + port + ";\n"
|
|
||||||
" proxy_set_header Host $host;\n"
|
|
||||||
" proxy_set_header X-Real-IP $remote_addr;\n"
|
|
||||||
" proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n"
|
|
||||||
" proxy_set_header X-Forwarded-Proto $scheme;\n\n"
|
|
||||||
" # Support for WebSocket\n"
|
|
||||||
" proxy_http_version 1.1;\n"
|
|
||||||
" proxy_set_header Upgrade $http_upgrade;\n"
|
|
||||||
" proxy_set_header Connection \"upgrade\";\n"
|
|
||||||
" }\n\n"
|
|
||||||
"}\n";
|
|
||||||
|
|
||||||
std::ofstream file(file_path, std::ios::app);
|
|
||||||
|
|
||||||
if (!file.is_open()) {
|
|
||||||
logger_.log(INFO, "Error: Could not open file " + file_path + strerror(errno) + '\n');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
file << new_text << '\n';
|
|
||||||
|
|
||||||
file.close();*/
|
|
||||||
|
|
||||||
|
|
||||||
std::string file_path = "/etc/nginx/nginx.conf";
|
std::string file_path = "/etc/nginx/nginx.conf";
|
||||||
|
|
||||||
// Open the nginx.conf file in read mode first
|
|
||||||
std::ifstream file_in(file_path);
|
std::ifstream file_in(file_path);
|
||||||
if (!file_in.is_open()) {
|
if (!file_in.is_open()) {
|
||||||
logger_.log(INFO, "Error: Could not open file " + file_path + strerror(errno) + '\n');
|
logger_.log(INFO, "Error: Could not open file " + file_path + strerror(errno) + '\n');
|
||||||
@@ -70,19 +42,16 @@ public:
|
|||||||
std::string line;
|
std::string line;
|
||||||
std::string temp_content;
|
std::string temp_content;
|
||||||
|
|
||||||
// Read the file content and store it in a temporary string
|
|
||||||
while (std::getline(file_in, line)) {
|
while (std::getline(file_in, line)) {
|
||||||
temp_content += line + "\n";
|
temp_content += line + "\n";
|
||||||
}
|
}
|
||||||
file_in.close();
|
file_in.close();
|
||||||
|
|
||||||
// Remove the last occurrence of "}" in the content
|
|
||||||
size_t last_brace_pos = temp_content.rfind("}");
|
size_t last_brace_pos = temp_content.rfind("}");
|
||||||
if (last_brace_pos != std::string::npos) {
|
if (last_brace_pos != std::string::npos) {
|
||||||
temp_content.erase(last_brace_pos);
|
temp_content.erase(last_brace_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now create the new server block
|
|
||||||
std::string new_text =
|
std::string new_text =
|
||||||
"\nserver {\n"
|
"\nserver {\n"
|
||||||
" listen 443 ssl;\n"
|
" listen 443 ssl;\n"
|
||||||
@@ -105,13 +74,10 @@ public:
|
|||||||
" }\n"
|
" }\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
// Append the new server block to the existing content
|
|
||||||
temp_content += new_text;
|
temp_content += new_text;
|
||||||
|
|
||||||
// Add the final closing brace
|
|
||||||
temp_content += "}\n";
|
temp_content += "}\n";
|
||||||
|
|
||||||
// Write the updated content back to the file
|
|
||||||
std::ofstream file_out(file_path);
|
std::ofstream file_out(file_path);
|
||||||
if (!file_out.is_open()) {
|
if (!file_out.is_open()) {
|
||||||
logger_.log(INFO, "Error: Could not open file " + file_path + strerror(errno) + '\n');
|
logger_.log(INFO, "Error: Could not open file " + file_path + strerror(errno) + '\n');
|
||||||
@@ -120,16 +86,6 @@ public:
|
|||||||
file_out << temp_content;
|
file_out << temp_content;
|
||||||
file_out.close();
|
file_out.close();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//TODO FIX BUG WITH }}}}}
|
|
||||||
|
|
||||||
std::string command = "sudo systemctl reload nginx";
|
std::string command = "sudo systemctl reload nginx";
|
||||||
|
|
||||||
std::thread commandThread(&CommandService::execute_command, command);
|
std::thread commandThread(&CommandService::execute_command, command);
|
||||||
@@ -139,20 +95,93 @@ public:
|
|||||||
logger_.log(INFO, "Nginx reloaded successfully.");
|
logger_.log(INFO, "Nginx reloaded successfully.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete_file(const std::string& file_path) const
|
void remove_nginx_configuration_block_and_reload(const std::string& server_name) {
|
||||||
{
|
std::lock_guard<std::mutex> lock(nginx_config_mutex);
|
||||||
try {
|
|
||||||
// Delete the original file
|
std::string file_path = "/etc/nginx/nginx.conf";
|
||||||
if (std::filesystem::exists(file_path)) {
|
|
||||||
std::filesystem::remove(file_path);
|
std::ifstream inFile(file_path);
|
||||||
logger_.log(INFO, "Deleted file: " + file_path);
|
std::ostringstream oss;
|
||||||
|
std::string line;
|
||||||
|
bool insideTargetServerBlock = false;
|
||||||
|
bool shouldRemoveBlock = false;
|
||||||
|
|
||||||
|
if (!inFile) {
|
||||||
|
std::cerr << "Error opening file: " << file_path << '\n';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (std::getline(inFile, line)) {
|
||||||
|
std::string trimmedLine = line;
|
||||||
|
trimmedLine.erase(0, trimmedLine.find_first_not_of(" \t")); // Убираем ведущие пробелы и табуляции
|
||||||
|
|
||||||
|
// Определяем начало блока server
|
||||||
|
if (trimmedLine.find("server {") != std::string::npos) {
|
||||||
|
insideTargetServerBlock = true;
|
||||||
|
shouldRemoveBlock = false; // Сбрасываем флаг удаления блока
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete the directory recursively//Todo test if method will not work
|
// Ищем server_name внутри блока server
|
||||||
/*if (std::filesystem::exists(final_files_directory)) {
|
if (insideTargetServerBlock && trimmedLine.find("server_name") != std::string::npos) {
|
||||||
std::filesystem::remove_all(final_files_directory);
|
if (trimmedLine.find(server_name) != std::string::npos) {
|
||||||
logger_.log(INFO, "Deleted directory: " + final_files_directory);
|
shouldRemoveBlock = true;
|
||||||
}*/
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если текущая строка завершает блок server
|
||||||
|
if (insideTargetServerBlock && trimmedLine == "}") {
|
||||||
|
insideTargetServerBlock = false;
|
||||||
|
if (!shouldRemoveBlock) {
|
||||||
|
oss << line << "\n"; // Если блок не должен быть удалён, записываем его
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если мы не внутри блока, или блок не подлежит удалению, записываем строку
|
||||||
|
if (!insideTargetServerBlock || !shouldRemoveBlock) {
|
||||||
|
oss << line << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inFile.close();
|
||||||
|
|
||||||
|
// Записываем результат обратно в файл
|
||||||
|
std::ofstream outFile(file_path);
|
||||||
|
if (!outFile) {
|
||||||
|
std::cerr << "Error opening file for writing: " << file_path << '\n';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
outFile << oss.str();
|
||||||
|
|
||||||
|
outFile.close();
|
||||||
|
|
||||||
|
std::string command = "sudo systemctl reload nginx";
|
||||||
|
|
||||||
|
std::thread commandThread(&CommandService::execute_command, command);
|
||||||
|
|
||||||
|
commandThread.join();
|
||||||
|
|
||||||
|
logger_.log(INFO, "Nginx reloaded successfully.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void delete_file(const std::string& file_path) const {
|
||||||
|
try {
|
||||||
|
if (std::filesystem::exists(file_path)) {
|
||||||
|
if (std::filesystem::is_directory(file_path)) {
|
||||||
|
std::filesystem::remove_all(file_path);
|
||||||
|
logger_.log(INFO, "Deleted directory and all contents: " + file_path);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::filesystem::remove(file_path);
|
||||||
|
logger_.log(INFO, "Deleted file: " + file_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logger_.log(ERROR, "File or directory does not exist: " + file_path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (const std::filesystem::filesystem_error& e) {
|
catch (const std::filesystem::filesystem_error& e) {
|
||||||
logger_.log(ERROR, "Error during deletion: " + std::string(e.what()));
|
logger_.log(ERROR, "Error during deletion: " + std::string(e.what()));
|
||||||
@@ -176,7 +205,25 @@ public:
|
|||||||
return ofs.good();
|
return ofs.good();
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_service_file(std::string path, std::string name)
|
void stop_and_start_service_file(std::string name)
|
||||||
|
{
|
||||||
|
std::string command_stop = "sudo systemctl stop " + name + ".service";
|
||||||
|
|
||||||
|
std::string command_start = "sudo systemctl start " + name + ".service";
|
||||||
|
|
||||||
|
std::string response_reload = execute_and_log_command(command_stop);
|
||||||
|
|
||||||
|
std::string response_enable = execute_and_log_command(command_start);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop_service_file(std::string name)
|
||||||
|
{
|
||||||
|
std::string command_stop = "sudo systemctl stop " + name + ".service";
|
||||||
|
|
||||||
|
std::string response_reload = execute_and_log_command(command_stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_service_file(std::string path, std::string name, std::string port)
|
||||||
{
|
{
|
||||||
logger_.log(INFO, "Start create_service_file");
|
logger_.log(INFO, "Start create_service_file");
|
||||||
|
|
||||||
@@ -194,50 +241,75 @@ public:
|
|||||||
serviceFile << "Description=" << name << " Service\n";
|
serviceFile << "Description=" << name << " Service\n";
|
||||||
serviceFile << "After=network.target\n\n";
|
serviceFile << "After=network.target\n\n";
|
||||||
|
|
||||||
|
std::string exec_start_command = "/usr/bin/dotnet /home/danilt2000/SpCloud/" + name + "/" + dll_file_name;
|
||||||
|
logger_.log(INFO, "ExecStart command: " + exec_start_command);
|
||||||
|
logger_.log(INFO, "ExecStart create_service_file");
|
||||||
|
|
||||||
serviceFile << "[Service]\n";
|
serviceFile << "[Service]\n";
|
||||||
serviceFile << "ExecStart=/usr/bin/dotnet /home/danilt2000/SpCloud/" + name + "/" + dll_file_name + "\n";
|
serviceFile << "ExecStart=" << exec_start_command << "\n";
|
||||||
|
//serviceFile << "ExecStart=/usr/bin/dotnet /home/danilt2000/SpCloud/" + name + "/" + dll_file_name + "\n";
|
||||||
//serviceFile << "ExecStart=/home/danilt2000/SpCloud/SpCloudMain/build/SpCloudMain\n";
|
//serviceFile << "ExecStart=/home/danilt2000/SpCloud/SpCloudMain/build/SpCloudMain\n";
|
||||||
serviceFile << "WorkingDirectory=/home/danilt2000/SpCloud/" + name + "\n";
|
serviceFile << "WorkingDirectory=/home/danilt2000/SpCloud/" + name + "\n";
|
||||||
//serviceFile << "WorkingDirectory=/home/danilt2000/SpCloud/SpCloudMain/build\n";
|
//serviceFile << "WorkingDirectory=/home/danilt2000/SpCloud/SpCloudMain/build\n";
|
||||||
serviceFile << "Restart=always\n";
|
serviceFile << "Restart=always\n";
|
||||||
serviceFile << "User=danilt2000\n";
|
serviceFile << "User=danilt2000\n";
|
||||||
|
serviceFile << "Environment=ASPNETCORE_URLS=http://0.0.0.0:" + port + "\n";
|
||||||
serviceFile << "Environment=PATH=/usr/bin\n";
|
serviceFile << "Environment=PATH=/usr/bin\n";
|
||||||
serviceFile << "Environment=NODE_ENV=production\n\n";
|
serviceFile << "Environment=NODE_ENV=production\n\n";
|
||||||
|
|
||||||
serviceFile << "[Install]\n";
|
serviceFile << "[Install]\n";
|
||||||
serviceFile << "WantedBy=multi-user.target\n";
|
serviceFile << "WantedBy=multi-user.target\n";
|
||||||
|
|
||||||
std::string command_reload = "sudo systemctl daemon-reload";
|
|
||||||
|
|
||||||
/*std::thread commandThreadReload(&CommandService::execute_command, command_reload);
|
|
||||||
|
|
||||||
commandThreadReload.join();*/
|
|
||||||
|
|
||||||
std::string command_start = "sudo systemctl start " + name + ".service";
|
|
||||||
|
|
||||||
//std::thread commandThreadStart(&CommandService::execute_command, commandThreadStart);
|
|
||||||
|
|
||||||
//commandThreadStart.join();
|
|
||||||
|
|
||||||
auto request_reload = std::async(std::launch::async, &FileProcessingService::execute_command, this, command_reload);
|
|
||||||
|
|
||||||
std::string response_reload = request_reload.get();
|
|
||||||
|
|
||||||
auto request_start = std::async(std::launch::async, &FileProcessingService::execute_command, this, command_start);
|
|
||||||
|
|
||||||
std::string response_start = request_start.get();
|
|
||||||
|
|
||||||
//Todo check service ->sudo systemctl status <service-name>.service
|
//Todo check service ->sudo systemctl status <service-name>.service
|
||||||
|
|
||||||
serviceFile.close();
|
serviceFile.close();
|
||||||
|
|
||||||
|
//std::string command_reload = "sudo systemctl daemon-reload";
|
||||||
|
|
||||||
|
///*std::thread commandThreadReload(&CommandService::execute_command, command_reload);
|
||||||
|
|
||||||
|
//commandThreadReload.join();*/
|
||||||
|
|
||||||
|
|
||||||
|
//std::string command_enable = "sudo systemctl enable " + name + ".service";
|
||||||
|
|
||||||
|
//std::string command_start = "sudo systemctl start " + name + ".service";
|
||||||
|
////std::thread commandThreadStart(&CommandService::execute_command, commandThreadStart);
|
||||||
|
|
||||||
|
////commandThreadStart.join();
|
||||||
|
|
||||||
|
//auto request_reload = std::async(std::launch::async, &FileProcessingService::execute_command, this, command_reload);
|
||||||
|
|
||||||
|
//std::string response_reload = request_reload.get();
|
||||||
|
|
||||||
|
//auto request_enable = std::async(std::launch::async, &FileProcessingService::execute_command, this, command_enable);
|
||||||
|
|
||||||
|
//std::string response_enable = request_enable.get();
|
||||||
|
|
||||||
|
//auto request_start = std::async(std::launch::async, &FileProcessingService::execute_command, this, command_start);
|
||||||
|
|
||||||
|
//std::string response_start = request_start.get();
|
||||||
|
|
||||||
|
std::string command_reload = "sudo systemctl daemon-reload";
|
||||||
|
std::string command_enable = "sudo systemctl enable " + name + ".service";
|
||||||
|
std::string command_start = "sudo systemctl start " + name + ".service";
|
||||||
|
|
||||||
|
std::string response_reload = execute_and_log_command(command_reload);
|
||||||
|
std::string response_enable = execute_and_log_command(command_enable);
|
||||||
|
std::string response_start = execute_and_log_command(command_start);
|
||||||
|
|
||||||
|
|
||||||
logger_.log(INFO, "Service file " + filename + " created successfully.\n");
|
logger_.log(INFO, "Service file " + filename + " created successfully.\n");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
logger_.log(INFO, "Unable to open file " + filename + " for writing: " + strerror(errno) + "\n");
|
logger_.log(INFO, "Unable to open file " + filename + " for writing: " + strerror(errno) + "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::string execute_and_log_command(const std::string& command) {
|
||||||
|
std::string result = execute_command(command);
|
||||||
|
logger_.log(INFO, "Executed command: " + command + "\nResult: " + result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
std::string execute_command(const std::string& command) {
|
std::string execute_command(const std::string& command) {
|
||||||
std::array<char, 128> buffer;
|
std::array<char, 128> buffer;
|
||||||
|
|||||||
@@ -37,6 +37,163 @@ public:
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string increase_user_app_count_(std::string user_id)
|
||||||
|
{
|
||||||
|
std::string json_data = "{"
|
||||||
|
"\"dataSource\": \"SpCloudCluster\","
|
||||||
|
"\"database\": \"SpCloud\","
|
||||||
|
"\"collection\": \"AllowedUsers\","
|
||||||
|
"\"filter\": {"
|
||||||
|
"\"discord_id\": \"" + user_id + "\""
|
||||||
|
"},"
|
||||||
|
"\"update\": {"
|
||||||
|
"\"$inc\": { \"app_count\": 1 }"
|
||||||
|
"}"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
std::string command =
|
||||||
|
"curl --location 'https://eu-central-1.aws.data.mongodb-api.com/app/data-zvcqvrr/endpoint/data/v1/action/updateOne' "
|
||||||
|
"--header 'Content-Type: application/json' "
|
||||||
|
"--header 'Access-Control-Request-Headers: *' "
|
||||||
|
"--header 'api-key: Q1NfSCrruUAzsxdrjhZd3sjSwiqbdSFmCLeaCatZiuohUXsvEq9RtEAeG0JL2Jd7' "
|
||||||
|
"--data '" + json_data + "'";
|
||||||
|
|
||||||
|
auto request = std::async(std::launch::async, &MongoDbService::execute_command, this, command);
|
||||||
|
|
||||||
|
std::string response = request.get();
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string decrease_user_app_count(std::string user_id)
|
||||||
|
{
|
||||||
|
std::string json_data = "{"
|
||||||
|
"\"dataSource\": \"SpCloudCluster\","
|
||||||
|
"\"database\": \"SpCloud\","
|
||||||
|
"\"collection\": \"AllowedUsers\","
|
||||||
|
"\"filter\": {"
|
||||||
|
"\"discord_id\": \"" + user_id + "\""
|
||||||
|
"},"
|
||||||
|
"\"update\": {"
|
||||||
|
"\"$inc\": { \"app_count\": -1 }"
|
||||||
|
"}"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
std::string command =
|
||||||
|
"curl --location 'https://eu-central-1.aws.data.mongodb-api.com/app/data-zvcqvrr/endpoint/data/v1/action/updateOne' "
|
||||||
|
"--header 'Content-Type: application/json' "
|
||||||
|
"--header 'Access-Control-Request-Headers: *' "
|
||||||
|
"--header 'api-key: Q1NfSCrruUAzsxdrjhZd3sjSwiqbdSFmCLeaCatZiuohUXsvEq9RtEAeG0JL2Jd7' "
|
||||||
|
"--data '" + json_data + "'";
|
||||||
|
|
||||||
|
auto request = std::async(std::launch::async, &MongoDbService::execute_command, this, command);
|
||||||
|
|
||||||
|
std::string response = request.get();
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string delete_document( std::string collection, std::string filter_field, std::string filter_value)
|
||||||
|
{
|
||||||
|
std::string json_data = "{"
|
||||||
|
"\"dataSource\": \"SpCloudCluster\","
|
||||||
|
"\"database\": \"SpCloud\","
|
||||||
|
"\"collection\": \"" + collection + "\","
|
||||||
|
"\"filter\": {"
|
||||||
|
"\"" + filter_field + "\": \"" + filter_value + "\""
|
||||||
|
"}"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
std::string command =
|
||||||
|
"curl --location 'https://eu-central-1.aws.data.mongodb-api.com/app/data-zvcqvrr/endpoint/data/v1/action/deleteOne' "
|
||||||
|
"--header 'Content-Type: application/json' "
|
||||||
|
"--header 'api-key: Q1NfSCrruUAzsxdrjhZd3sjSwiqbdSFmCLeaCatZiuohUXsvEq9RtEAeG0JL2Jd7' "
|
||||||
|
"--data '" + json_data + "'";
|
||||||
|
|
||||||
|
auto request = std::async(std::launch::async, &MongoDbService::execute_command, this, command);
|
||||||
|
|
||||||
|
std::string response = request.get();
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string get_user_id_by_auth_token(std::string auth_token)
|
||||||
|
{
|
||||||
|
std::string json_data = R"({
|
||||||
|
"dataSource": "SpCloudCluster",
|
||||||
|
"database": "SpCloud",
|
||||||
|
"collection": "AllowedUsers",
|
||||||
|
"filter": {
|
||||||
|
"auth_token": ")" + auth_token + R"("
|
||||||
|
}
|
||||||
|
})";
|
||||||
|
|
||||||
|
std::string command =
|
||||||
|
"curl --location 'https://eu-central-1.aws.data.mongodb-api.com/app/data-zvcqvrr/endpoint/data/v1/action/findOne' "
|
||||||
|
"--header 'Content-Type: application/json' "
|
||||||
|
"--header 'api-key: Q1NfSCrruUAzsxdrjhZd3sjSwiqbdSFmCLeaCatZiuohUXsvEq9RtEAeG0JL2Jd7' "
|
||||||
|
"--data-raw '" + json_data + "'";
|
||||||
|
|
||||||
|
auto request = std::async(std::launch::async, &MongoDbService::execute_command, this, command);
|
||||||
|
|
||||||
|
std::string response = request.get();
|
||||||
|
|
||||||
|
size_t pos_user_id = response.find("\"discord_id\":");
|
||||||
|
if (pos_user_id == std::string::npos) {
|
||||||
|
// Handle the case where "discord_id" is not found in the response
|
||||||
|
return ""; // or some other error handling
|
||||||
|
}
|
||||||
|
|
||||||
|
pos_user_id += 13; // 12 characters for "discord_id": and 1 for the opening quote
|
||||||
|
|
||||||
|
// Find the end of the user_id, either at a comma or the closing bracket
|
||||||
|
size_t end_pos = response.find_first_of(",}", pos_user_id);
|
||||||
|
if (end_pos == std::string::npos) {
|
||||||
|
// Handle malformed JSON
|
||||||
|
return ""; // or some other error handling
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the user_id from the response, making sure to strip any surrounding quotes
|
||||||
|
std::string user_id = response.substr(pos_user_id, end_pos - pos_user_id);
|
||||||
|
if (!user_id.empty() && user_id.front() == '"' && user_id.back() == '"') {
|
||||||
|
user_id = user_id.substr(1, user_id.length() - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return user_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string is_user_app_owner(std::string auth_token, std::string name_app)//Todo check it
|
||||||
|
{
|
||||||
|
std::string user_id = get_user_id_by_auth_token(auth_token);
|
||||||
|
|
||||||
|
std::string json_data = R"({
|
||||||
|
"dataSource": "SpCloudCluster",
|
||||||
|
"database": "SpCloud",
|
||||||
|
"collection": "Apps",
|
||||||
|
"filter": {
|
||||||
|
"user_id": ")" + user_id + R"(",
|
||||||
|
"name": ")" + name_app + R"("
|
||||||
|
}
|
||||||
|
})";
|
||||||
|
|
||||||
|
std::string command = "curl --location 'https://eu-central-1.aws.data.mongodb-api.com/app/data-zvcqvrr/endpoint/data/v1/action/findOne' "
|
||||||
|
"--header 'Content-Type: application/json' "
|
||||||
|
"--header 'api-key: Q1NfSCrruUAzsxdrjhZd3sjSwiqbdSFmCLeaCatZiuohUXsvEq9RtEAeG0JL2Jd7' "
|
||||||
|
"--data-raw '" + json_data + "'";
|
||||||
|
|
||||||
|
auto request = std::async(std::launch::async, &MongoDbService::execute_command, this, command);
|
||||||
|
|
||||||
|
std::string response = request.get();
|
||||||
|
|
||||||
|
if (response != "{\"document\":null}")
|
||||||
|
{
|
||||||
|
return "Success";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "User isn't app owner";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string is_user_can_publish(std::string auth_token)
|
std::string is_user_can_publish(std::string auth_token)
|
||||||
{
|
{
|
||||||
std::string json_data = R"({
|
std::string json_data = R"({
|
||||||
@@ -86,6 +243,38 @@ public:
|
|||||||
return "Success";
|
return "Success";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string is_user_banned(std::string auth_token)
|
||||||
|
{
|
||||||
|
std::string json_data = R"({
|
||||||
|
"dataSource": "SpCloudCluster",
|
||||||
|
"database": "SpCloud",
|
||||||
|
"collection": "AllowedUsers",
|
||||||
|
"filter": {
|
||||||
|
"auth_token": ")" + auth_token + R"("
|
||||||
|
}
|
||||||
|
})";
|
||||||
|
|
||||||
|
std::string command = "curl --location 'https://eu-central-1.aws.data.mongodb-api.com/app/data-zvcqvrr/endpoint/data/v1/action/findOne' "
|
||||||
|
"--header 'Content-Type: application/json' "
|
||||||
|
"--header 'api-key: Q1NfSCrruUAzsxdrjhZd3sjSwiqbdSFmCLeaCatZiuohUXsvEq9RtEAeG0JL2Jd7' "
|
||||||
|
"--data-raw '" + json_data + "'";
|
||||||
|
|
||||||
|
auto request = std::async(std::launch::async, &MongoDbService::execute_command, this, command);
|
||||||
|
|
||||||
|
std::string response = request.get();
|
||||||
|
|
||||||
|
size_t pos_is_user_banned = response.find("\"is_banned\":");
|
||||||
|
|
||||||
|
std::string is_banned_value = response.substr(pos_is_user_banned + 12, response.find_first_of(",}", pos_is_user_banned) - pos_is_user_banned - 12);
|
||||||
|
|
||||||
|
if (is_banned_value == "true")
|
||||||
|
{
|
||||||
|
return "Fail publish: user is banned";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Success";
|
||||||
|
}
|
||||||
|
|
||||||
std::string is_app_name_free(std::string name)
|
std::string is_app_name_free(std::string name)
|
||||||
{
|
{
|
||||||
std::string json_data = R"({
|
std::string json_data = R"({
|
||||||
@@ -142,6 +331,29 @@ public:
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string get_app_list(std::string user_id)//Todo test this method
|
||||||
|
{
|
||||||
|
std::string json_data = R"({
|
||||||
|
"dataSource": "SpCloudCluster",
|
||||||
|
"database": "SpCloud",
|
||||||
|
"collection": "Apps",
|
||||||
|
"filter": {
|
||||||
|
"user_id": ")" + user_id + R"("
|
||||||
|
}
|
||||||
|
})";
|
||||||
|
|
||||||
|
std::string command = "curl --location 'https://eu-central-1.aws.data.mongodb-api.com/app/data-zvcqvrr/endpoint/data/v1/action/find' "
|
||||||
|
"--header 'Content-Type: application/json' "
|
||||||
|
"--header 'api-key: Q1NfSCrruUAzsxdrjhZd3sjSwiqbdSFmCLeaCatZiuohUXsvEq9RtEAeG0JL2Jd7' "
|
||||||
|
"--data-raw '" + json_data + "'";
|
||||||
|
|
||||||
|
auto request = std::async(std::launch::async, &MongoDbService::execute_command, this, command);
|
||||||
|
|
||||||
|
std::string response = request.get();
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
std::string execute_command(const std::string& command) {
|
std::string execute_command(const std::string& command) {
|
||||||
std::array<char, 128> buffer;
|
std::array<char, 128> buffer;
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|||||||
@@ -72,19 +72,119 @@ int main()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
App* app = new App(name, user_id, "url", "local_url", target,"service_name");
|
App* app = new App(name, user_id, "url", "local_url", target, "service_name");
|
||||||
|
|
||||||
publish_controller.process_publish(req, app);
|
publish_controller.process_publish(req, app);
|
||||||
|
|
||||||
mongo_service.add_app(app->get_name(), app->get_user_id(), app->get_url(),
|
mongo_service.add_app(app->get_name(), app->get_user_id(), app->get_url(),
|
||||||
app->get_url_on_local_machine(), app->get_target(), app->get_service_name());//TODO UNCOMMENT AND FIX
|
app->get_url_on_local_machine(), app->get_target(), app->get_service_name());
|
||||||
|
|
||||||
|
mongo_service.increase_user_app_count_(app->get_user_id());
|
||||||
|
|
||||||
|
res.set_content("App is running on address:" + app->get_url(), "text/plain");
|
||||||
|
|
||||||
delete app;
|
delete app;
|
||||||
|
|
||||||
res.set_content("App is running on address ????", "text/plain");//Todo add app address showing
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
svr.Put("/update", [&](const httplib::Request& req, httplib::Response& res)
|
||||||
|
{
|
||||||
|
logger.log(INFO, "Start updating app");
|
||||||
|
|
||||||
|
std::string user_id = req.get_file_value("UserId").content;
|
||||||
|
|
||||||
|
std::string name = req.get_file_value("Name").content;
|
||||||
|
|
||||||
|
std::string authorization_token = req.get_header_value("Authorization");
|
||||||
|
|
||||||
|
string is_user_banned = mongo_service.is_user_banned(authorization_token);
|
||||||
|
|
||||||
|
if (is_user_banned != "Success")
|
||||||
|
{
|
||||||
|
res.set_content(is_user_banned, "text/plain");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string is_user_app_owner = mongo_service.is_user_app_owner(authorization_token, name);
|
||||||
|
|
||||||
|
if (is_user_app_owner != "Success")
|
||||||
|
{
|
||||||
|
res.set_content(is_user_app_owner, "text/plain");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
App* app = new App(name, user_id, "url", "local_url", "target", "service_name");
|
||||||
|
|
||||||
|
publish_controller.process_update(req, app);
|
||||||
|
|
||||||
|
res.set_content("App was updated", "text/plain");
|
||||||
|
|
||||||
|
delete app;
|
||||||
|
});
|
||||||
|
|
||||||
|
svr.Delete("/delete", [&](const httplib::Request& req, httplib::Response& res)
|
||||||
|
{
|
||||||
|
logger.log(INFO, "Start updating app");
|
||||||
|
|
||||||
|
std::string user_id = req.get_file_value("UserId").content;
|
||||||
|
|
||||||
|
std::string name = req.get_file_value("Name").content;
|
||||||
|
|
||||||
|
std::string authorization_token = req.get_header_value("Authorization");
|
||||||
|
|
||||||
|
string is_user_banned = mongo_service.is_user_banned(authorization_token);
|
||||||
|
|
||||||
|
if (is_user_banned != "Success")
|
||||||
|
{
|
||||||
|
res.set_content(is_user_banned, "text/plain");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string is_user_app_owner = mongo_service.is_user_app_owner(authorization_token, name);
|
||||||
|
|
||||||
|
if (is_user_app_owner != "Success")
|
||||||
|
{
|
||||||
|
res.set_content(is_user_app_owner, "text/plain");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
App* app = new App(name, user_id, "url", "local_url", "target", "service_name");
|
||||||
|
|
||||||
|
publish_controller.process_delete(req, app);
|
||||||
|
|
||||||
|
res.set_content("App was deleted", "text/plain");
|
||||||
|
|
||||||
|
mongo_service.decrease_user_app_count(app->get_user_id());
|
||||||
|
|
||||||
|
mongo_service.delete_document("Apps", "name", app->get_name());
|
||||||
|
|
||||||
|
delete app;
|
||||||
|
});
|
||||||
|
|
||||||
|
svr.Get("/apps", [&](const httplib::Request& req, httplib::Response& res)
|
||||||
|
{
|
||||||
|
std::string authorization_token = req.get_header_value("Authorization");
|
||||||
|
|
||||||
|
string is_user_banned = mongo_service.is_user_banned(authorization_token);
|
||||||
|
|
||||||
|
if (is_user_banned != "Success")
|
||||||
|
{
|
||||||
|
res.set_content(is_user_banned, "text/plain");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string user_id = mongo_service.get_user_id_by_auth_token(authorization_token);
|
||||||
|
|
||||||
|
string app_list = mongo_service.get_app_list(user_id);
|
||||||
|
|
||||||
|
res.set_content(app_list, "text/plain");
|
||||||
|
});
|
||||||
|
|
||||||
svr.Post("/login", [&](const httplib::Request& req, httplib::Response& res)
|
svr.Post("/login", [&](const httplib::Request& req, httplib::Response& res)
|
||||||
{
|
{
|
||||||
string discord_id = discord_service.get_discord_id(req.body);
|
string discord_id = discord_service.get_discord_id(req.body);
|
||||||
|
|||||||
Reference in New Issue
Block a user