Updated to 1.4.13 ;)
This commit is contained in:
parent
9705f84bc0
commit
b79b496ad1
@ -1 +1 @@
|
||||
Subproject commit e7befd4fc9c96b966b459ea5ad8530dc8fe9345b
|
||||
Subproject commit c4f7fdb5d692ea376ac2b7bef4fbb0b81c6ea6c5
|
@ -560,14 +560,16 @@ std::shared_ptr<Properties> DatabaseHelper::default_properties_client(std::share
|
||||
return properties;
|
||||
}
|
||||
|
||||
std::mutex DatabaseHelper::database_id_mutex{};
|
||||
|
||||
bool DatabaseHelper::assignDatabaseId(sql::SqlManager *sql, ServerId id, std::shared_ptr<DataClient> cl) {
|
||||
cl->loadDataForCurrentServer();
|
||||
if(cl->getClientDatabaseId() == 0){ //Client does not exist
|
||||
ClientDbId cldbid = 0;
|
||||
ClientDbId new_client_database_id{0};
|
||||
auto res = sql::command(sql, "SELECT `cldbid` FROM `clients` WHERE `serverId` = 0 AND `clientUid` = :cluid", variable{":cluid", cl->getUid()}).query([](ClientDbId* ptr, int length, char** values, char** names){
|
||||
*ptr = static_cast<ClientDbId>(stoll(values[0]));
|
||||
return 0;
|
||||
}, &cldbid);
|
||||
}, &new_client_database_id);
|
||||
auto pf = LOG_SQL_CMD;
|
||||
pf(res);
|
||||
if(!res) return false;
|
||||
@ -576,25 +578,26 @@ bool DatabaseHelper::assignDatabaseId(sql::SqlManager *sql, ServerId id, std::sh
|
||||
variable{":cluid", cl->getUid()}, variable{":name", cl->getDisplayName()},
|
||||
variable{":fconnect", duration_cast<seconds>(system_clock::now().time_since_epoch()).count()}, variable{":lconnect", 0},
|
||||
variable{":connections", 0});
|
||||
if(cldbid == 0){ //Completly new user
|
||||
res = sql::command(sql, "SELECT `cldbid` FROM `clients` WHERE `serverId` = 0 ORDER BY `cldbid` DESC LIMIT 1").query([](ClientDbId* ptr, int length, char** values, char** names){
|
||||
*ptr = static_cast<ClientDbId>(stoll(values[0]));
|
||||
return 0;
|
||||
}, &cldbid);
|
||||
pf(res);
|
||||
if(new_client_database_id == 0) { /* we've a completely new user */
|
||||
std::lock_guard db_id_lock{DatabaseHelper::database_id_mutex};
|
||||
res = sql::command(sql, "SELECT `cldbid` FROM `clients` WHERE `serverId` = 0 ORDER BY `cldbid` DESC LIMIT 1").query([&](int length, std::string* values, std::string* names) {
|
||||
assert(length == 1);
|
||||
new_client_database_id = (ClientDbId) stoll(values[0]);
|
||||
});
|
||||
LOG_SQL_CMD(res);
|
||||
if(!res) return false;
|
||||
|
||||
cldbid += 1;
|
||||
res = insertTemplate.command().values(variable{":serverId", 0}, variable{":cldbid", cldbid}).execute(); //Insert global
|
||||
pf(res);
|
||||
new_client_database_id += 1;
|
||||
res = insertTemplate.command().values(variable{":serverId", 0}, variable{":cldbid", new_client_database_id}).execute(); //Insert global
|
||||
LOG_SQL_CMD(res);
|
||||
if(!res) return false;
|
||||
debugMessage(id, "Having new instance user on server {}. (Database ID: {} Name: {})", id, cldbid, cl->getDisplayName());
|
||||
debugMessage(LOG_INSTANCE, "Registered a new client. Unique id: {}, First server: {}, Database ID: {}", cl->getUid(), id, new_client_database_id);
|
||||
} else {
|
||||
debugMessage(id, "Having new server user on server {}. (Database ID: {} Name: {})", id, cldbid, cl->getDisplayName());
|
||||
debugMessage(id, "Having new client, which is already known on this instance. Unique id: {}, First server: {}, Database ID: {}", cl->getUid(), id, new_client_database_id);
|
||||
}
|
||||
|
||||
if(id != 0){ //Else already inserted
|
||||
res = insertTemplate.command().values(variable{":serverId", id}, variable{":cldbid", cldbid}).execute();
|
||||
res = insertTemplate.command().values(variable{":serverId", id}, variable{":cldbid", new_client_database_id}).execute();
|
||||
pf(res);
|
||||
if(!res) return false;
|
||||
}
|
||||
@ -602,7 +605,7 @@ bool DatabaseHelper::assignDatabaseId(sql::SqlManager *sql, ServerId id, std::sh
|
||||
return assignDatabaseId(sql, id, cl);
|
||||
}
|
||||
|
||||
logTrace(id, "Loaded client from database. Database id: {} Unique id: {}", cl->getClientDatabaseId(), cl->getUid());
|
||||
logTrace(id, "Loaded client successfully from database. Database id: {} Unique id: {}", cl->getClientDatabaseId(), cl->getUid());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -78,6 +78,7 @@ namespace ts {
|
||||
public:
|
||||
static std::shared_ptr<Properties> default_properties_client(std::shared_ptr<Properties> /* properties */, ClientType /* type */);
|
||||
static bool assignDatabaseId(sql::SqlManager *, ServerId id, std::shared_ptr<DataClient>);
|
||||
static std::mutex database_id_mutex;
|
||||
|
||||
explicit DatabaseHelper(sql::SqlManager*);
|
||||
~DatabaseHelper();
|
||||
|
@ -167,8 +167,7 @@ int GroupManager::insertGroupFromDb(int count, char **values, char **column) {
|
||||
groupId = (GroupType) stoll(values[index]);
|
||||
else if(strcmp(column[index], "displayName") == 0)
|
||||
targetName = values[index];
|
||||
else if(strcmp(column[index], "serverId") == 0);
|
||||
else cerr << "Invalid group table row " << column[index] << endl;
|
||||
//else cerr << "Invalid group table row " << column[index] << endl;
|
||||
}
|
||||
|
||||
if((size_t) groupId == 0 || (size_t) target == 0xff || (size_t) type == 0xff || targetName.empty()) {
|
||||
|
@ -201,9 +201,11 @@ shared_ptr<VirtualServer> VirtualServerManager::findServerByPort(uint16_t port)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint16_t VirtualServerManager::next_available_port() {
|
||||
uint16_t VirtualServerManager::next_available_port(const std::string& host_string) {
|
||||
auto instances = this->serverInstances();
|
||||
deque<uint16_t> unallowed_ports;
|
||||
std::vector<uint16_t> unallowed_ports{};
|
||||
unallowed_ports.reserve(instances.size());
|
||||
|
||||
for(const auto& instance : instances) {
|
||||
unallowed_ports.push_back(instance->properties()[property::VIRTUALSERVER_PORT].as<uint16_t>());
|
||||
|
||||
@ -214,18 +216,39 @@ uint16_t VirtualServerManager::next_available_port() {
|
||||
}
|
||||
}
|
||||
}
|
||||
auto bindings = net::resolve_bindings(host_string, 0);
|
||||
|
||||
uint16_t port = config::voice::default_voice_port;
|
||||
while(true) {
|
||||
if(port < 1024) goto c;
|
||||
if(port < 1024) goto next_port;
|
||||
|
||||
for(auto& p : unallowed_ports) {
|
||||
if(p == port)
|
||||
goto c;
|
||||
goto next_port;
|
||||
}
|
||||
|
||||
for(auto& binding : bindings) {
|
||||
if(!std::get<2>(binding).empty()) continue; /* error on that */
|
||||
auto& baddress = std::get<1>(binding);
|
||||
auto& raw_port = baddress.ss_family == AF_INET ? ((sockaddr_in*) &baddress)->sin_port : ((sockaddr_in6*) &baddress)->sin6_port;
|
||||
raw_port = htons(port);
|
||||
|
||||
switch (net::address_available(baddress, net::binding_type::TCP)) {
|
||||
case net::binding_result::ADDRESS_USED:
|
||||
goto next_port;
|
||||
default:
|
||||
break; /* if we've an internal error we ignore it */
|
||||
}
|
||||
switch (net::address_available(baddress, net::binding_type::UDP)) {
|
||||
case net::binding_result::ADDRESS_USED:
|
||||
goto next_port;
|
||||
default:
|
||||
break; /* if we've an internal error we ignore it */
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
c:
|
||||
next_port:
|
||||
port++;
|
||||
}
|
||||
return port;
|
||||
@ -317,6 +340,7 @@ shared_ptr<VirtualServer> VirtualServerManager::create_server(std::string hosts,
|
||||
if(!sid_success)
|
||||
return nullptr;
|
||||
|
||||
this->delete_server_in_db(serverId); /* just to ensure */
|
||||
sql::command(this->handle->getSql(), "INSERT INTO `servers` (`serverId`, `host`, `port`) VALUES (:sid, :host, :port)", variable{":sid", serverId}, variable{":host", hosts}, variable{":port", port}).executeLater().waitAndGetLater(LOG_SQL_CMD, {1, "future failed"});
|
||||
|
||||
auto prop_copy = sql::command(this->handle->getSql(), "INSERT INTO `properties` (`serverId`, `type`, `id`, `key`, `value`) SELECT :target_sid AS `serverId`, `type`, `id`, `key`, `value` FROM `properties` WHERE `type` = :type AND `id` = 0 AND `serverId` = 0;",
|
||||
|
@ -38,7 +38,7 @@ namespace ts::server {
|
||||
|
||||
std::shared_ptr<VirtualServer> findServerById(ServerId);
|
||||
std::shared_ptr<VirtualServer> findServerByPort(uint16_t);
|
||||
uint16_t next_available_port();
|
||||
uint16_t next_available_port(const std::string& /* host string */);
|
||||
ServerId next_available_server_id(bool& /* success */);
|
||||
|
||||
std::deque<std::shared_ptr<VirtualServer>> serverInstances(){
|
||||
|
@ -102,7 +102,7 @@ std::shared_ptr<BasicChannel> ServerChannelTree::createChannel(ChannelId parentI
|
||||
channel->properties()[property::CHANNEL_LAST_LEFT] = chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now().time_since_epoch()).count();
|
||||
|
||||
|
||||
auto result = sql::command(this->sql, "INSERT INTO `channels` (`serverId`, `channelId`, `type`, `parentId`) VALUES(:sid, :chid, :type, :parent);", variable{":sid", this->getServerId()}, variable{":chid", channel->channelId()}, variable{":type", channel->channelType()}, variable{":parent", channel->parent() ? channel->parent()->channelId() : 0}).execute();
|
||||
auto result = sql::command(this->sql, "INSERT INTO `channels` (`serverId`, `channelId`, `parentId`) VALUES(:sid, :chid, :parent);", variable{":sid", this->getServerId()}, variable{":chid", channel->channelId()}, variable{":parent", channel->parent() ? channel->parent()->channelId() : 0}).execute();
|
||||
auto pf = LOG_SQL_CMD;
|
||||
pf(result);
|
||||
|
||||
@ -493,7 +493,7 @@ bool ServerChannelTree::validateChannelIcons() {
|
||||
}
|
||||
|
||||
void ServerChannelTree::loadChannelsFromDatabase() {
|
||||
auto res = sql::command(this->sql, "SELECT * FROM `channels` WHERE `serverId` = :sid", variable{":sid", this->getServerId()}).query(&ServerChannelTree::loadChannelFromData, this);
|
||||
auto res = sql::command(this->sql, "SELECT `channelId`, `parentId` FROM `channels` WHERE `serverId` = :sid", variable{":sid", this->getServerId()}).query(&ServerChannelTree::loadChannelFromData, this);
|
||||
(LOG_SQL_CMD)(res);
|
||||
if(!res){
|
||||
logError(this->getServerId(), "Could not load channel tree from database");
|
||||
@ -512,7 +512,6 @@ void ServerChannelTree::loadChannelsFromDatabase() {
|
||||
int ServerChannelTree::loadChannelFromData(int argc, char **data, char **column) {
|
||||
ChannelId channelId = 0;
|
||||
ChannelId parentId = 0;
|
||||
auto type = static_cast<ChannelType::ChannelType>(0xFF);
|
||||
|
||||
|
||||
int index = 0;
|
||||
@ -520,8 +519,6 @@ int ServerChannelTree::loadChannelFromData(int argc, char **data, char **column)
|
||||
for(index = 0; index < argc; index++){
|
||||
if(strcmp(column[index], "channelId") == 0) channelId = static_cast<ChannelId>(stoll(data[index]));
|
||||
else if(strcmp(column[index], "parentId") == 0) parentId = static_cast<ChannelId>(stoll(data[index]));
|
||||
else if(strcmp(column[index], "type") == 0) type = static_cast<ChannelType::ChannelType>(stoll(data[index]));
|
||||
else if(strcmp(column[index], "serverId") == 0) {}
|
||||
else logError(this->getServerId(), "ServerChannelTree::loadChannelFromData called with invalid column from sql \"{}\"", column[index]);
|
||||
}
|
||||
} catch (std::exception& ex) {
|
||||
|
@ -101,12 +101,15 @@ command_result QueryClient::handleCommand(Command& cmd) {
|
||||
case string_hash("bindinglist"):
|
||||
return this->handleCommandBindingList(cmd);
|
||||
case string_hash("serversnapshotdeploy"): {
|
||||
//return this->handleCommandServerSnapshotDeploy(cmd);
|
||||
#if 1
|
||||
return this->handleCommandServerSnapshotDeploy(cmd);
|
||||
#else
|
||||
auto cmd_str = cmd.build();
|
||||
ts::command_parser parser{cmd_str};
|
||||
if(!parser.parse(true)) return command_result{error::vs_critical};
|
||||
|
||||
return this->handleCommandServerSnapshotDeployNew(parser);
|
||||
#endif
|
||||
}
|
||||
case string_hash("serversnapshotcreate"):
|
||||
return this->handleCommandServerSnapshotCreate(cmd);
|
||||
@ -587,9 +590,9 @@ command_result QueryClient::handleCommandServerCreate(Command& cmd) {
|
||||
time_wait = duration_cast<milliseconds>(end - start);
|
||||
}
|
||||
|
||||
uint16_t freePort = serverInstance->getVoiceServerManager()->next_available_port();
|
||||
|
||||
std::string host = cmd[0].has("virtualserver_host") ? cmd["virtualserver_host"].as<string>() : config::binding::DefaultVoiceHost;
|
||||
uint16_t freePort = serverInstance->getVoiceServerManager()->next_available_port(host);
|
||||
|
||||
uint16_t port = cmd[0].has("virtualserver_port") ? cmd["virtualserver_port"].as<uint16_t>() : freePort;
|
||||
{
|
||||
auto _start = system_clock::now();
|
||||
@ -844,7 +847,7 @@ command_result QueryClient::handleCommandServerSnapshotDeploy(Command& cmd) {
|
||||
|
||||
unique_lock server_create_lock(serverInstance->getVoiceServerManager()->server_create_lock);
|
||||
if(port == 0)
|
||||
port = serverInstance->getVoiceServerManager()->next_available_port();
|
||||
port = serverInstance->getVoiceServerManager()->next_available_port(host);
|
||||
auto result = serverInstance->getVoiceServerManager()->createServerFromSnapshot(this->server, host, port, cmd, error);
|
||||
server_create_lock.unlock();
|
||||
auto end = system_clock::now();
|
||||
|
@ -445,6 +445,7 @@ ROLLBACK;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* update the client table */
|
||||
{
|
||||
result = sql::command(this->sql(), "CREATE TABLE `clients_v2` (`serverId` INT NOT NULL, `cldbid` INTEGER, `original_client_id` INTEGER DEFAULT 0, `clientUid` VARCHAR(64) NOT NULL, `firstConnect` BIGINT DEFAULT 0, `lastConnect` BIGINT DEFAULT 0, `connections` INT DEFAULT 0, `lastName` VARCHAR(128) DEFAULT '', UNIQUE(`serverId`, `clientUid`));").execute();
|
||||
@ -468,6 +469,10 @@ ROLLBACK;
|
||||
error = "failed to rename new clients table to the old clients table (" + result.fmtStr() + ")";
|
||||
return false;
|
||||
}
|
||||
|
||||
CREATE_INDEX("clients", "serverId");
|
||||
CREATE_INDEX2R("clients", "serverId", "clientUid");
|
||||
CREATE_INDEX2R("clients", "serverId", "cldbid");
|
||||
}
|
||||
db_version(12);
|
||||
default:
|
||||
|
@ -17,6 +17,8 @@ using namespace ts::server;
|
||||
using SnapshotType = ts::server::snapshots::type;
|
||||
using SnapshotVersion = ts::server::snapshots::version_t;
|
||||
|
||||
//FIXME: Music bots & Playlists
|
||||
|
||||
bool VirtualServerManager::deploy_snapshot(std::string &error, ServerId server_id, const command_parser &data) {
|
||||
if(data.bulk(0).has_key("version")) {
|
||||
return this->deploy_ts3_snapshot(error, server_id, data);
|
||||
@ -293,6 +295,7 @@ bool VirtualServerManager::deploy_raw_snapshot(std::string &error, ts::ServerId
|
||||
}
|
||||
}
|
||||
|
||||
std::map<ClientDbId, ChannelId> client_id_mapping{};
|
||||
std::map<ChannelId, ChannelId> channel_id_mapping{};
|
||||
std::map<ChannelId, ChannelId> channel_group_id_mapping{};
|
||||
std::map<ChannelId, ChannelId> server_group_id_mapping{};
|
||||
@ -302,24 +305,58 @@ bool VirtualServerManager::deploy_raw_snapshot(std::string &error, ts::ServerId
|
||||
/* cleanup all old data */
|
||||
this->delete_server_in_db(server_id);
|
||||
|
||||
/* register server & properties */
|
||||
{
|
||||
|
||||
sql::InsertQuery insert_property_query{"properties",
|
||||
sql::Column<ServerId>("serverId"),
|
||||
sql::Column<property::PropertyType>("type"),
|
||||
sql::Column<uint64_t>("id"),
|
||||
sql::Column<std::string>("key"),
|
||||
sql::Column<std::string>("value")
|
||||
};
|
||||
|
||||
for(const auto& property : parsed_server.properties.list_properties(property::FLAG_SAVE)) {
|
||||
if(!property.isModified()) continue;
|
||||
|
||||
insert_property_query.add_entry(
|
||||
server_id,
|
||||
property::PROP_TYPE_SERVER,
|
||||
0,
|
||||
std::string{property.type().name},
|
||||
property.value()
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
auto result = insert_property_query.execute(this->handle->getSql(), true);
|
||||
if(result.failed_entries.size() > 0)
|
||||
logWarning(server_id, "Failed to insert all server properties into the database. Failed property count: {}", result.failed_entries.size());
|
||||
}
|
||||
|
||||
//FIXME: Override host & port
|
||||
auto result = sql::command{this->handle->getSql(), "INSERT INTO `servers` (`serverId`, `host`, `port`) VALUES (:sid, :host, :port)"}
|
||||
.value(":sid", server_id)
|
||||
.value(":host", parsed_server.properties[property::VIRTUALSERVER_HOST].value())
|
||||
.value(":port", parsed_server.properties[property::VIRTUALSERVER_PORT].value())
|
||||
.execute();
|
||||
if(!result) {
|
||||
error = "failed to register the server (" + result.fmtStr() + ")";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* register clients */
|
||||
{
|
||||
//`original_client_id` INTEGER DEFAULT 0
|
||||
//CREATE TABLE `clients_v2` (`serverId` INT NOT NULL, `cldbid` INTEGER, `clientUid` VARCHAR(64) NOT NULL, `firstConnect` BIGINT DEFAULT 0, `lastConnect` BIGINT DEFAULT 0, `connections` INT DEFAULT 0, `lastName` VARCHAR(128) DEFAULT '', UNIQUE(`serverId`, `clientUid`));
|
||||
|
||||
sql::InsertQuery insert_general_query{"clients",
|
||||
sql::Column<ServerId>("serverId"),
|
||||
sql::Column<ClientDbId>("original_client_id"),
|
||||
sql::Column<std::string>("clientUid"),
|
||||
sql::Column<int64_t>("firstConnect"),
|
||||
sql::Column<int64_t>("lastConnect"),
|
||||
|
||||
sql::Column<uint64_t>("connections"),
|
||||
sql::Column<std::string>("lastName")
|
||||
sql::Column<ClientDbId>("cldbid"),
|
||||
sql::Column<std::string>("clientUid")
|
||||
};
|
||||
|
||||
sql::InsertQuery insert_server_query{"clients",
|
||||
sql::Column<ServerId>("serverId"),
|
||||
sql::Column<ClientDbId>("cldbid"),
|
||||
sql::Column<ClientDbId>("original_client_id"),
|
||||
sql::Column<std::string>("clientUid"),
|
||||
sql::Column<int64_t>("firstConnect"),
|
||||
@ -328,10 +365,36 @@ bool VirtualServerManager::deploy_raw_snapshot(std::string &error, ts::ServerId
|
||||
sql::Column<std::string>("lastName")
|
||||
};
|
||||
|
||||
{
|
||||
auto update_result = sql::command(this->handle->getSql(), "UPDATE `clients` SET `original_client_id` = 0 WHERE `original_client_id` = :sid AND `serverId` = 0", variable{":sid", server_id}).execute();
|
||||
if(!update_result)
|
||||
logWarning(server_id, "Failed to reset client id mapping for this server: {}", update_result.fmtStr());
|
||||
}
|
||||
|
||||
std::unique_lock db_id_lock{DatabaseHelper::database_id_mutex};
|
||||
ClientDbId new_client_database_id{0};
|
||||
{
|
||||
auto query_result = sql::command(this->handle->getSql(), "SELECT `cldbid` FROM `clients` WHERE `serverId` = 0 ORDER BY `cldbid` DESC LIMIT 1").query([&](int length, std::string* values, std::string* names) {
|
||||
assert(length == 1);
|
||||
new_client_database_id = (ClientDbId) stoll(values[0]);
|
||||
});
|
||||
if(!query_result) {
|
||||
error = "failed to query the current client database index (" + query_result.fmtStr() + ")";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for(const auto& client : parsed_clients) {
|
||||
/*
|
||||
insert_general_query.add_entry(
|
||||
0,
|
||||
++new_client_database_id, /* this might, or might not be used as new id */
|
||||
client.parsed_data.unique_id
|
||||
);
|
||||
|
||||
/* we're updating the database id afterwards */
|
||||
insert_server_query.add_entry(
|
||||
server_id,
|
||||
client.parsed_data.database_id, /* to keep stuff unique */
|
||||
client.parsed_data.database_id,
|
||||
client.parsed_data.unique_id,
|
||||
std::chrono::floor<std::chrono::seconds>(client.parsed_data.timestamp_created.time_since_epoch()).count(),
|
||||
@ -339,20 +402,32 @@ bool VirtualServerManager::deploy_raw_snapshot(std::string &error, ts::ServerId
|
||||
client.parsed_data.client_total_connections,
|
||||
client.parsed_data.nickname
|
||||
);
|
||||
*/
|
||||
insert_general_query.add_entry(
|
||||
server_id,
|
||||
client.parsed_data.database_id,
|
||||
client.parsed_data.unique_id,
|
||||
std::chrono::floor<std::chrono::seconds>(client.parsed_data.timestamp_created.time_since_epoch()).count()
|
||||
);
|
||||
}
|
||||
|
||||
auto result = insert_general_query.execute(this->handle->getSql(), true);
|
||||
for(const auto& fail : result.failed_entries)
|
||||
logWarning(server_id, "Failed to insert client {} into the database: {}", parsed_clients[std::get<0>(fail)], std::get<1>(fail).fmtStr());
|
||||
{
|
||||
auto result = insert_general_query.execute(this->handle->getSql(), true);
|
||||
for(const auto& fail : result.failed_entries)
|
||||
logWarning(server_id, "Failed to insert client {} into the general database: {}", parsed_clients[std::get<0>(fail)].parsed_data.database_id, std::get<1>(fail).fmtStr());
|
||||
}
|
||||
db_id_lock.unlock();
|
||||
|
||||
sql::command{this->handle->getSql(), "SELECT `original_client_id`,`cldbid` FROM `clients` WHERE `serverId` = :sid;"}
|
||||
{
|
||||
auto result = insert_server_query.execute(this->handle->getSql(), true);
|
||||
for(const auto& fail : result.failed_entries)
|
||||
logWarning(server_id, "Failed to insert client {} into the server database: {}", parsed_clients[std::get<0>(fail)].parsed_data.database_id, std::get<1>(fail).fmtStr());
|
||||
}
|
||||
|
||||
{
|
||||
auto update_result = sql::command{this->handle->getSql(), "UPDATE `clients` SET `cldbid` = (SELECT `cldbid` from `clients` AS `t` WHERE `t`.`clientUid` = `clients`.`clientUid` LIMIT 1) WHERE `serverId` = :sid;"}
|
||||
.value(":sid", server_id)
|
||||
.execute();
|
||||
if(!update_result) {
|
||||
error = "failed to update client database ids (" + update_result.fmtStr() + ")";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto map_query_result = sql::command{this->handle->getSql(), "SELECT `original_client_id`,`cldbid` FROM `clients` WHERE `serverId` = :sid;"}
|
||||
.value(":serverId", server_id)
|
||||
.query([&](int length, std::string* values, std::string* names) {
|
||||
ClientDbId original_id{0}, new_id{0};
|
||||
@ -363,8 +438,12 @@ bool VirtualServerManager::deploy_raw_snapshot(std::string &error, ts::ServerId
|
||||
logWarning(server_id, "Failed to parse client database entry mapping for group id {} (New ID: {})", values[1], values[0]);
|
||||
return;
|
||||
}
|
||||
server_group_id_mapping[original_id] = new_id;
|
||||
client_id_mapping[original_id] = new_id;
|
||||
});
|
||||
if(!map_query_result) {
|
||||
error = "failed to query client dabase id mappings (" + map_query_result.fmtStr() + ")";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* channels */
|
||||
@ -390,20 +469,98 @@ bool VirtualServerManager::deploy_raw_snapshot(std::string &error, ts::ServerId
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Insert them into the database
|
||||
|
||||
sql::InsertQuery insert_query{"channels",
|
||||
sql::Column<ServerId>("serverId"),
|
||||
sql::Column<ChannelId>("channelId"),
|
||||
sql::Column<ChannelId>("parentId")
|
||||
};
|
||||
|
||||
sql::InsertQuery insert_property_query{"properties",
|
||||
sql::Column<ServerId>("serverId"),
|
||||
sql::Column<property::PropertyType>("type"),
|
||||
sql::Column<uint64_t>("id"),
|
||||
sql::Column<std::string>("key"),
|
||||
sql::Column<std::string>("value")
|
||||
};
|
||||
|
||||
for(auto& channel : parsed_channels) {
|
||||
auto channel_id = channel.properties[property::CHANNEL_ID].as<ChannelId>();
|
||||
insert_query.add_entry(
|
||||
server_id,
|
||||
channel_id,
|
||||
channel.properties[property::CHANNEL_PID].as<ChannelId>()
|
||||
);
|
||||
|
||||
for(const auto& property : channel.properties.list_properties(property::FLAG_SAVE)) {
|
||||
if(!property.isModified()) continue;
|
||||
|
||||
insert_property_query.add_entry(
|
||||
server_id,
|
||||
property::PROP_TYPE_CHANNEL,
|
||||
channel_id,
|
||||
std::string{property.type().name},
|
||||
property.value()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto result = insert_query.execute(this->handle->getSql(), true);
|
||||
for(const auto& fail : result.failed_entries)
|
||||
logWarning(server_id, "Failed to insert channel {} into the server database: {}", parsed_channels[std::get<0>(fail)].properties[property::CHANNEL_NAME].value(), std::get<1>(fail).fmtStr());
|
||||
}
|
||||
|
||||
{
|
||||
auto result = insert_property_query.execute(this->handle->getSql(), true);
|
||||
if(result.failed_entries.size() > 0)
|
||||
logWarning(server_id, "Failed to insert all channel properties into the database. Failed property cound: {}", result.failed_entries.size());
|
||||
}
|
||||
}
|
||||
|
||||
/* channel permissions */
|
||||
{
|
||||
sql::InsertQuery insert_query{"permissions",
|
||||
sql::Column<ServerId>("serverId"),
|
||||
sql::Column<permission::PermissionSqlType>("type"),
|
||||
sql::Column<uint64_t>("id"),
|
||||
sql::Column<ChannelId>("channelId"),
|
||||
sql::Column<std::string>("permId"),
|
||||
|
||||
sql::Column<permission::PermissionValue>("value"),
|
||||
sql::Column<permission::PermissionValue>("grant"),
|
||||
sql::Column<bool>("flag_skip"),
|
||||
sql::Column<bool>("flag_negate")
|
||||
};
|
||||
|
||||
for(auto& entry : channel_permissions) {
|
||||
auto new_id = channel_id_mapping.find(entry.id1);
|
||||
if(new_id == channel_id_mapping.end()) {
|
||||
error = "missing channel id mapping for channel permission entry";
|
||||
return false;
|
||||
{
|
||||
auto new_id = channel_id_mapping.find(entry.id1);
|
||||
if(new_id == channel_id_mapping.end()) {
|
||||
logWarning(server_id, "Missing channel id mapping for channel permission entry (channel id: {}). Skipping permission insert.", entry.id1);
|
||||
continue;
|
||||
}
|
||||
entry.id1 = new_id->second;
|
||||
}
|
||||
|
||||
for(const auto& permission : entry.permissions) {
|
||||
insert_query.add_entry(
|
||||
server_id,
|
||||
permission::SQL_PERM_CHANNEL,
|
||||
entry.id1,
|
||||
0,
|
||||
permission.type->name,
|
||||
permission.value.has_value ? permission.value.value : permNotGranted,
|
||||
permission.granted.has_value ? permission.granted.value : permNotGranted,
|
||||
permission.flag_skip,
|
||||
permission.flag_negate
|
||||
);
|
||||
}
|
||||
entry.id1 = new_id->second;
|
||||
}
|
||||
|
||||
auto result = insert_query.execute(this->handle->getSql(), true);
|
||||
if(!result.failed_entries.empty())
|
||||
logWarning(server_id, "Failed to insert all channel permissions into the database. Failed permission count: {}", result.failed_entries.size());
|
||||
}
|
||||
|
||||
/* server groups */
|
||||
@ -432,6 +589,41 @@ bool VirtualServerManager::deploy_raw_snapshot(std::string &error, ts::ServerId
|
||||
});
|
||||
}
|
||||
|
||||
/* server group relations */
|
||||
{
|
||||
sql::InsertQuery insert_query{"assignedGroups",
|
||||
sql::Column<ServerId>("serverId"),
|
||||
sql::Column<ClientDbId>("cldbid"),
|
||||
sql::Column<GroupId>("groupId"),
|
||||
sql::Column<ChannelId>("channelId")
|
||||
};
|
||||
|
||||
for(auto& relation : parsed_server_group_relations) {
|
||||
for(auto& entry : relation.second) {
|
||||
ClientId client_id{};
|
||||
{
|
||||
auto new_id = client_id_mapping.find(entry.client_id);
|
||||
if(new_id == client_id_mapping.end()) {
|
||||
logWarning(server_id, "Missing client id mapping for channel group relation permission entry (client id: {}). Skipping relation insert.", entry.client_id);
|
||||
continue;
|
||||
}
|
||||
client_id = new_id->second;
|
||||
}
|
||||
|
||||
insert_query.add_entry(
|
||||
server_id,
|
||||
client_id,
|
||||
entry.group_id,
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
auto result = insert_query.execute(this->handle->getSql(), true);
|
||||
if(!result.failed_entries.empty())
|
||||
logWarning(server_id, "Failed to insert all server group relations into the database. Failed insert count: {}", result.failed_entries.size());
|
||||
}
|
||||
|
||||
/* channel groups */
|
||||
{
|
||||
sql::model insert_model{this->handle->getSql(), "INSERT INTO `groups` (`serverId`, `target`, `type`, `displayName`, `original_id`) VALUES (:serverId, :target, :type, :name, :id)"};
|
||||
@ -458,44 +650,148 @@ bool VirtualServerManager::deploy_raw_snapshot(std::string &error, ts::ServerId
|
||||
});
|
||||
}
|
||||
|
||||
#define INSERT_PERMISSION_COMMAND "INSERT INTO `permissions` (`serverId`, `type`, `id`, `channelId`, `permId`, `value`, `grant`, `flag_skip`, `flag_negate`) VALUES (:serverId, :type, :id, :chId, :permId, :value, :grant, :flag_skip, :flag_negate)"
|
||||
/* client permissions */
|
||||
/* channel group relations */
|
||||
{
|
||||
sql::InsertQuery insert_query{"permissions",
|
||||
sql::Column<ServerId>("serverId"),
|
||||
sql::Column<permission::PermissionSqlType>("type"),
|
||||
sql::Column<uint64_t>("id"),
|
||||
sql::Column<ChannelId>("channelId"),
|
||||
sql::Column<std::string>("permId"),
|
||||
|
||||
sql::Column<permission::PermissionValue>("value"),
|
||||
sql::Column<permission::PermissionValue>("grant"),
|
||||
sql::Column<bool>("flag_skip"),
|
||||
sql::Column<bool>("flag_negate"),
|
||||
sql::InsertQuery insert_query{"assignedGroups",
|
||||
sql::Column<ServerId>("serverId"),
|
||||
sql::Column<ClientDbId>("cldbid"),
|
||||
sql::Column<GroupId>("groupId"),
|
||||
sql::Column<ChannelId>("channelId")
|
||||
};
|
||||
|
||||
for(auto& permission : client_permissions) {
|
||||
for(auto& relation : parsed_channel_group_relations) {
|
||||
ChannelId channel_id{};
|
||||
{
|
||||
auto new_id = channel_id_mapping.find(relation.first);
|
||||
if(new_id == channel_id_mapping.end()) {
|
||||
logWarning(server_id, "Missing channel id mapping for channel group relation entry (channel id: {}). Skipping relation insert.", relation.first);
|
||||
continue;
|
||||
}
|
||||
channel_id = new_id->second;
|
||||
}
|
||||
|
||||
for(auto& entry : relation.second) {
|
||||
ClientId client_id{};
|
||||
{
|
||||
auto new_id = client_id_mapping.find(entry.client_id);
|
||||
if(new_id == client_id_mapping.end()) {
|
||||
logWarning(server_id, "Missing client id mapping for channel group relation permission entry (client id: {}, channel id: {}). Skipping relation insert.", entry.client_id, relation.first);
|
||||
continue;
|
||||
}
|
||||
client_id = new_id->second;
|
||||
}
|
||||
|
||||
insert_query.add_entry(
|
||||
server_id,
|
||||
client_id,
|
||||
entry.group_id,
|
||||
channel_id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
auto result = insert_query.execute(this->handle->getSql(), true);
|
||||
if(!result.failed_entries.empty())
|
||||
logWarning(server_id, "Failed to insert all channel group relations into the database. Failed insert count: {}", result.failed_entries.size());
|
||||
}
|
||||
|
||||
/* register clients in the database */
|
||||
/* client permissions */
|
||||
{
|
||||
sql::InsertQuery insert_query{"permissions",
|
||||
sql::Column<ServerId>("serverId"),
|
||||
sql::Column<permission::PermissionSqlType>("type"),
|
||||
sql::Column<uint64_t>("id"),
|
||||
sql::Column<ChannelId>("channelId"),
|
||||
sql::Column<std::string>("permId"),
|
||||
|
||||
sql::Column<permission::PermissionValue>("value"),
|
||||
sql::Column<permission::PermissionValue>("grant"),
|
||||
sql::Column<bool>("flag_skip"),
|
||||
sql::Column<bool>("flag_negate"),
|
||||
};
|
||||
|
||||
for(auto& entry : client_permissions) {
|
||||
{
|
||||
auto new_id = client_id_mapping.find(entry.id1);
|
||||
if(new_id == client_id_mapping.end()) {
|
||||
logWarning(server_id, "Missing client id mapping for client permission entry (client id: {}). Skipping permission insert.", entry.id1);
|
||||
continue;
|
||||
}
|
||||
entry.id1 = new_id->second;
|
||||
}
|
||||
|
||||
for(const auto& permission : entry.permissions) {
|
||||
insert_query.add_entry(
|
||||
server_id,
|
||||
permission::SQL_PERM_USER,
|
||||
entry.id1,
|
||||
0,
|
||||
permission.type->name,
|
||||
permission.value.has_value ? permission.value.value : permNotGranted,
|
||||
permission.granted.has_value ? permission.granted.value : permNotGranted,
|
||||
permission.flag_skip,
|
||||
permission.flag_negate
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
auto result = insert_query.execute(this->handle->getSql(), true);
|
||||
if(!result.failed_entries.empty())
|
||||
logWarning(server_id, "Failed to insert all client permissions into the database. Failed permission count: {}", result.failed_entries.size());
|
||||
}
|
||||
|
||||
/* client channel permissions */
|
||||
{
|
||||
sql::InsertQuery insert_query{"permissions",
|
||||
sql::Column<ServerId>("serverId"),
|
||||
sql::Column<permission::PermissionSqlType>("type"),
|
||||
sql::Column<uint64_t>("id"),
|
||||
sql::Column<ChannelId>("channelId"),
|
||||
sql::Column<std::string>("permId"),
|
||||
|
||||
sql::Column<permission::PermissionValue>("value"),
|
||||
sql::Column<permission::PermissionValue>("grant"),
|
||||
sql::Column<bool>("flag_skip"),
|
||||
sql::Column<bool>("flag_negate"),
|
||||
};
|
||||
|
||||
for(auto& entry : client_channel_permissions) {
|
||||
auto new_id = channel_id_mapping.find(entry.id1);
|
||||
if(new_id == channel_id_mapping.end()) {
|
||||
error = "missing channel id mapping for client channel permission entry";
|
||||
return false;
|
||||
{
|
||||
auto new_id = channel_id_mapping.find(entry.id1);
|
||||
if(new_id == channel_id_mapping.end()) {
|
||||
logWarning(server_id, "Missing channel id mapping for client channel permission entry (client id: {}, channel id: {}). Skipping permission insert.", entry.id2, entry.id1);
|
||||
continue;
|
||||
}
|
||||
entry.id1 = new_id->second;
|
||||
}
|
||||
|
||||
{
|
||||
auto new_id = client_id_mapping.find(entry.id2);
|
||||
if(new_id == client_id_mapping.end()) {
|
||||
logWarning(server_id, "Missing client id mapping for client channel permission entry (client id: {}, channel id: {}). Skipping permission insert.", entry.id2, entry.id1);
|
||||
continue;
|
||||
}
|
||||
entry.id2 = new_id->second;
|
||||
}
|
||||
|
||||
for(const auto& permission : entry.permissions) {
|
||||
insert_query.add_entry(
|
||||
server_id,
|
||||
permission::SQL_PERM_USER,
|
||||
entry.id2,
|
||||
(ChannelId) entry.id1,
|
||||
permission.type->name,
|
||||
permission.value.has_value ? permission.value.value : permNotGranted,
|
||||
permission.granted.has_value ? permission.granted.value : permNotGranted,
|
||||
permission.flag_skip,
|
||||
permission.flag_negate
|
||||
);
|
||||
}
|
||||
entry.id1 = new_id->second;
|
||||
}
|
||||
|
||||
auto result = insert_query.execute(this->handle->getSql(), true);
|
||||
if(!result.failed_entries.empty())
|
||||
logWarning(server_id, "Failed to insert all client channel permissions into the database. Failed permission count: {}", result.failed_entries.size());
|
||||
}
|
||||
}
|
||||
error = "not implemented";
|
||||
|
2
shared
2
shared
@ -1 +1 @@
|
||||
Subproject commit 16c2272fe4b479c55e6db6642d039a42b0774325
|
||||
Subproject commit c31cc9d0ee8fbcd04ff3a76e8fc4ab8723127a84
|
Loading…
Reference in New Issue
Block a user